PSI2IR: Unify behavior for lambda return values with old back-end
See KT-35849. 1. When expected lambda return type is a type parameter, don't generate introduce implicit casts (even if the corresponding type parameter has an upper bound that would otherwise require such cast). 2. Do not generate implicit null check for lambda return value of @EnhancedNullability type.
This commit is contained in:
+5
@@ -1087,6 +1087,11 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest {
|
||||
runTest("compiler/testData/ir/irText/expressions/multipleThisReferences.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nullCheckOnGenericLambdaReturn.kt")
|
||||
public void testNullCheckOnGenericLambdaReturn() throws Exception {
|
||||
runTest("compiler/testData/ir/irText/expressions/nullCheckOnGenericLambdaReturn.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nullCheckOnLambdaReturn.kt")
|
||||
public void testNullCheckOnLambdaReturn() throws Exception {
|
||||
runTest("compiler/testData/ir/irText/expressions/nullCheckOnLambdaReturn.kt");
|
||||
|
||||
+37
-12
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
@@ -94,7 +95,9 @@ internal class InsertImplicitCasts(
|
||||
|
||||
private fun IrMemberAccessExpression.transformReceiverArguments(substitutedDescriptor: CallableDescriptor) {
|
||||
dispatchReceiver = dispatchReceiver?.cast(getEffectiveDispatchReceiverType(substitutedDescriptor))
|
||||
extensionReceiver = extensionReceiver?.cast(substitutedDescriptor.extensionReceiverParameter?.type)
|
||||
val extensionReceiverType = substitutedDescriptor.extensionReceiverParameter?.type
|
||||
val originalExtensionReceiverType = substitutedDescriptor.original.extensionReceiverParameter?.type
|
||||
extensionReceiver = extensionReceiver?.cast(extensionReceiverType, originalExtensionReceiverType)
|
||||
}
|
||||
|
||||
private fun getEffectiveDispatchReceiverType(descriptor: CallableDescriptor): KotlinType? =
|
||||
@@ -121,6 +124,7 @@ internal class InsertImplicitCasts(
|
||||
for (index in substitutedDescriptor.valueParameters.indices) {
|
||||
val argument = getValueArgument(index) ?: continue
|
||||
val parameterType = substitutedDescriptor.valueParameters[index].type
|
||||
val originalParameterType = substitutedDescriptor.original.valueParameters[index].type
|
||||
|
||||
// Hack to support SAM conversions on out-projected types.
|
||||
// See SamType#createByValueParameter and genericSamProjectedOut.kt for more details.
|
||||
@@ -130,7 +134,7 @@ internal class InsertImplicitCasts(
|
||||
else
|
||||
parameterType
|
||||
|
||||
putValueArgument(index, argument.cast(expectedType))
|
||||
putValueArgument(index, argument.cast(expectedType, originalExpectedType = originalParameterType))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,8 +172,12 @@ internal class InsertImplicitCasts(
|
||||
value = if (expression.returnTargetSymbol is IrConstructorSymbol) {
|
||||
value.coerceToUnit()
|
||||
} else {
|
||||
returnExpressionsToBePostprocessed.add(expression)
|
||||
value.cast(expression.returnTarget.returnType)
|
||||
val returnTargetDescriptor = expression.returnTarget
|
||||
val isLambdaReturnValue = returnTargetDescriptor is AnonymousFunctionDescriptor
|
||||
if (isLambdaReturnValue) {
|
||||
returnExpressionsToBePostprocessed.add(expression)
|
||||
}
|
||||
value.cast(returnTargetDescriptor.returnType, isLambdaReturnValue = isLambdaReturnValue)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,15 +300,16 @@ internal class InsertImplicitCasts(
|
||||
else
|
||||
null
|
||||
|
||||
private fun IrExpression.cast(expectedType: KotlinType?): IrExpression {
|
||||
private fun IrExpression.cast(
|
||||
expectedType: KotlinType?,
|
||||
originalExpectedType: KotlinType? = expectedType,
|
||||
isLambdaReturnValue: Boolean = false
|
||||
): IrExpression {
|
||||
if (expectedType == null) return this
|
||||
if (expectedType.isError) return this
|
||||
|
||||
if (this is IrFunctionExpression) {
|
||||
val expectedFunctionReturnType = expectedType.getFunctionReturnTypeOrNull()
|
||||
if (expectedFunctionReturnType != null) {
|
||||
expectedFunctionExpressionReturnType[function.descriptor] = expectedFunctionReturnType.toIrType()
|
||||
}
|
||||
if (this is IrFunctionExpression && originalExpectedType != null) {
|
||||
recordExpectedLambdaReturnTypeIfAppropriate(expectedType, originalExpectedType)
|
||||
}
|
||||
|
||||
// TODO here we can have non-denotable KotlinTypes (both in 'this@cast.type' and 'expectedType').
|
||||
@@ -319,8 +328,10 @@ internal class InsertImplicitCasts(
|
||||
else
|
||||
implicitCast(expectedType, IrTypeOperator.IMPLICIT_DYNAMIC_CAST)
|
||||
|
||||
(valueType.isNullabilityFlexible() && valueType.containsNull() || valueType.hasEnhancedNullability()) &&
|
||||
!expectedType.containsNull() ->
|
||||
(valueType.isNullabilityFlexible() && valueType.containsNull()) && !expectedType.containsNull() ->
|
||||
implicitNonNull(valueType, expectedType)
|
||||
|
||||
(valueType.hasEnhancedNullability() && !isLambdaReturnValue) && !expectedType.containsNull() ->
|
||||
implicitNonNull(valueType, expectedType)
|
||||
|
||||
KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType.makeNullable()) ->
|
||||
@@ -336,6 +347,20 @@ internal class InsertImplicitCasts(
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrFunctionExpression.recordExpectedLambdaReturnTypeIfAppropriate(
|
||||
expectedType: KotlinType,
|
||||
originalExpectedType: KotlinType
|
||||
) {
|
||||
// TODO see KT-35849
|
||||
|
||||
val returnTypeFromExpected = expectedType.getFunctionReturnTypeOrNull() ?: return
|
||||
val returnTypeFromOriginalExpected = originalExpectedType.getFunctionReturnTypeOrNull()
|
||||
|
||||
if (returnTypeFromOriginalExpected?.isTypeParameter() != true) {
|
||||
expectedFunctionExpressionReturnType[function.descriptor] = returnTypeFromExpected.toIrType()
|
||||
}
|
||||
}
|
||||
|
||||
private fun KotlinType.hasEnhancedNullability() =
|
||||
generatorExtensions.enhancedNullability.hasEnhancedNullability(this)
|
||||
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
// !LANGUAGE: +StrictJavaNullabilityAssertions
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// FILE: inLambdaReturnWithExpectedType.kt
|
||||
fun check(fn: () -> Any) { fn() }
|
||||
|
||||
fun <T> checkT(fn: () -> T) { fn() }
|
||||
|
||||
fun <T : Any> checkTAny(fn: () -> T) { fn() }
|
||||
|
||||
fun box(): String {
|
||||
// TODO language design; see KT-35849
|
||||
|
||||
try {
|
||||
check { J().nullString() }
|
||||
throw AssertionError("Fail: 'check { J().nullString() }' should throw")
|
||||
} catch (e: Throwable) {
|
||||
}
|
||||
|
||||
try {
|
||||
check { J().notNullString() }
|
||||
throw AssertionError("Fail: 'check { J().notNullString() }' should throw")
|
||||
} catch (e: Throwable) {
|
||||
}
|
||||
|
||||
try {
|
||||
checkT { J().nullString() }
|
||||
} catch (e: Throwable) {
|
||||
throw AssertionError("Fail: 'checkT { J().nullString() }' should not throw")
|
||||
}
|
||||
|
||||
try {
|
||||
checkT { J().notNullString() }
|
||||
} catch (e: Throwable) {
|
||||
throw AssertionError("Fail: 'checkT { J().notNullString() }' should not throw")
|
||||
}
|
||||
|
||||
try {
|
||||
checkTAny { J().nullString() }
|
||||
} catch (e: Throwable) {
|
||||
throw AssertionError("Fail: 'checkTAny { J().nullString() }' should not throw")
|
||||
}
|
||||
|
||||
try {
|
||||
checkTAny { J().notNullString() }
|
||||
} catch (e: Throwable) {
|
||||
throw AssertionError("Fail: 'checkTAny { J().notNullString() }' should not throw")
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
// FILE: J.java
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class J {
|
||||
public String nullString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public @NotNull String notNullString() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
FILE fqName:<root> fileName:/nullCheckOnGenericLambdaReturn.kt
|
||||
FUN name:checkAny visibility:public modality:FINAL <> (fn:kotlin.Function0<kotlin.Any>) returnType:kotlin.Any
|
||||
VALUE_PARAMETER name:fn index:0 type:kotlin.Function0<kotlin.Any>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun checkAny (fn: kotlin.Function0<kotlin.Any>): kotlin.Any declared in <root>'
|
||||
CALL 'public abstract fun invoke (): kotlin.Any [operator] declared in kotlin.Function0' type=kotlin.Any origin=null
|
||||
$this: GET_VAR 'fn: kotlin.Function0<kotlin.Any> declared in <root>.checkAny' type=kotlin.Function0<kotlin.Any> origin=null
|
||||
FUN name:checkAnyN visibility:public modality:FINAL <> (fn:kotlin.Function0<kotlin.Any?>) returnType:kotlin.Any?
|
||||
VALUE_PARAMETER name:fn index:0 type:kotlin.Function0<kotlin.Any?>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun checkAnyN (fn: kotlin.Function0<kotlin.Any?>): kotlin.Any? declared in <root>'
|
||||
CALL 'public abstract fun invoke (): kotlin.Any? [operator] declared in kotlin.Function0' type=kotlin.Any? origin=null
|
||||
$this: GET_VAR 'fn: kotlin.Function0<kotlin.Any?> declared in <root>.checkAnyN' type=kotlin.Function0<kotlin.Any?> origin=null
|
||||
FUN name:checkT visibility:public modality:FINAL <T> (fn:kotlin.Function0<T of <root>.checkT>) returnType:T of <root>.checkT
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
|
||||
VALUE_PARAMETER name:fn index:0 type:kotlin.Function0<T of <root>.checkT>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun checkT <T> (fn: kotlin.Function0<T of <root>.checkT>): T of <root>.checkT declared in <root>'
|
||||
CALL 'public abstract fun invoke (): T of <root>.checkT [operator] declared in kotlin.Function0' type=T of <root>.checkT origin=null
|
||||
$this: GET_VAR 'fn: kotlin.Function0<T of <root>.checkT> declared in <root>.checkT' type=kotlin.Function0<T of <root>.checkT> origin=null
|
||||
FUN name:checkTAny visibility:public modality:FINAL <T> (fn:kotlin.Function0<T of <root>.checkTAny>) returnType:T of <root>.checkTAny
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any]
|
||||
VALUE_PARAMETER name:fn index:0 type:kotlin.Function0<T of <root>.checkTAny>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun checkTAny <T> (fn: kotlin.Function0<T of <root>.checkTAny>): T of <root>.checkTAny declared in <root>'
|
||||
CALL 'public abstract fun invoke (): T of <root>.checkTAny [operator] declared in kotlin.Function0' type=T of <root>.checkTAny origin=null
|
||||
$this: GET_VAR 'fn: kotlin.Function0<T of <root>.checkTAny> declared in <root>.checkTAny' type=kotlin.Function0<T of <root>.checkTAny> origin=null
|
||||
FUN name:id visibility:public modality:FINAL <T> (x:T of <root>.id) returnType:T of <root>.id
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
|
||||
VALUE_PARAMETER name:x index:0 type:T of <root>.id
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun id <T> (x: T of <root>.id): T of <root>.id declared in <root>'
|
||||
GET_VAR 'x: T of <root>.id declared in <root>.id' type=T of <root>.id origin=null
|
||||
FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.String?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test1 (): kotlin.String? declared in <root>'
|
||||
CALL 'public final fun checkT <T> (fn: kotlin.Function0<T of <root>.checkT>): T of <root>.checkT declared in <root>' type=kotlin.String? origin=null
|
||||
<T>: kotlin.String?
|
||||
fn: FUN_EXPR type=kotlin.Function0<kotlin.String?> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.String?
|
||||
BLOCK_BODY
|
||||
CALL 'public open fun foo (): kotlin.String? [operator] declared in <root>.J' type=kotlin.String? origin=null
|
||||
FUN name:test2 visibility:public modality:FINAL <> () returnType:kotlin.String
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test2 (): kotlin.String declared in <root>'
|
||||
CALL 'public final fun checkT <T> (fn: kotlin.Function0<T of <root>.checkT>): T of <root>.checkT declared in <root>' type=kotlin.String origin=null
|
||||
<T>: kotlin.String
|
||||
fn: FUN_EXPR type=kotlin.Function0<kotlin.String> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.String
|
||||
BLOCK_BODY
|
||||
CALL 'public open fun nnFoo (): kotlin.String [operator] declared in <root>.J' type=kotlin.String origin=null
|
||||
FUN name:test3 visibility:public modality:FINAL <> () returnType:kotlin.String?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test3 (): kotlin.String? declared in <root>'
|
||||
CALL 'public final fun checkTAny <T> (fn: kotlin.Function0<T of <root>.checkTAny>): T of <root>.checkTAny declared in <root>' type=kotlin.String? origin=null
|
||||
<T>: kotlin.String?
|
||||
fn: FUN_EXPR type=kotlin.Function0<kotlin.String?> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.String?
|
||||
BLOCK_BODY
|
||||
CALL 'public open fun foo (): kotlin.String? [operator] declared in <root>.J' type=kotlin.String? origin=null
|
||||
FUN name:test4 visibility:public modality:FINAL <> () returnType:kotlin.String
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test4 (): kotlin.String declared in <root>'
|
||||
CALL 'public final fun checkTAny <T> (fn: kotlin.Function0<T of <root>.checkTAny>): T of <root>.checkTAny declared in <root>' type=kotlin.String origin=null
|
||||
<T>: kotlin.String
|
||||
fn: FUN_EXPR type=kotlin.Function0<kotlin.String> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.String
|
||||
BLOCK_BODY
|
||||
CALL 'public open fun nnFoo (): kotlin.String [operator] declared in <root>.J' type=kotlin.String origin=null
|
||||
@@ -0,0 +1,27 @@
|
||||
// FILE: nullCheckOnGenericLambdaReturn.kt
|
||||
fun checkAny(fn: () -> Any) = fn()
|
||||
|
||||
fun checkAnyN(fn: () -> Any?) = fn()
|
||||
|
||||
fun <T> checkT(fn: () -> T) = fn()
|
||||
|
||||
fun <T : Any> checkTAny(fn: () -> T) = fn()
|
||||
|
||||
fun <T> id(x: T) = x
|
||||
|
||||
fun test1() = checkT { J.foo() }
|
||||
|
||||
fun test2() = checkT { J.nnFoo() }
|
||||
|
||||
fun test3() = checkTAny { J.foo() }
|
||||
|
||||
fun test4() = checkTAny { J.nnFoo() }
|
||||
|
||||
// FILE: J.java
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
public class J {
|
||||
public static String foo() { return null; }
|
||||
|
||||
public static @NotNull String nnFoo() { return null; }
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
FILE fqName:<root> fileName:/nullCheckOnGenericLambdaReturn.kt
|
||||
FUN name:checkAny visibility:public modality:FINAL <> (fn:kotlin.Function0<kotlin.Any>) returnType:kotlin.Any
|
||||
VALUE_PARAMETER name:fn index:0 type:kotlin.Function0<kotlin.Any>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun checkAny (fn: kotlin.Function0<kotlin.Any>): kotlin.Any declared in <root>'
|
||||
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Any origin=INVOKE
|
||||
$this: GET_VAR 'fn: kotlin.Function0<kotlin.Any> declared in <root>.checkAny' type=kotlin.Function0<kotlin.Any> origin=VARIABLE_AS_FUNCTION
|
||||
FUN name:checkAnyN visibility:public modality:FINAL <> (fn:kotlin.Function0<kotlin.Any?>) returnType:kotlin.Any?
|
||||
VALUE_PARAMETER name:fn index:0 type:kotlin.Function0<kotlin.Any?>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun checkAnyN (fn: kotlin.Function0<kotlin.Any?>): kotlin.Any? declared in <root>'
|
||||
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Any? origin=INVOKE
|
||||
$this: GET_VAR 'fn: kotlin.Function0<kotlin.Any?> declared in <root>.checkAnyN' type=kotlin.Function0<kotlin.Any?> origin=VARIABLE_AS_FUNCTION
|
||||
FUN name:checkT visibility:public modality:FINAL <T> (fn:kotlin.Function0<T of <root>.checkT>) returnType:T of <root>.checkT
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
|
||||
VALUE_PARAMETER name:fn index:0 type:kotlin.Function0<T of <root>.checkT>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun checkT <T> (fn: kotlin.Function0<T of <root>.checkT>): T of <root>.checkT declared in <root>'
|
||||
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=T of <root>.checkT origin=INVOKE
|
||||
$this: GET_VAR 'fn: kotlin.Function0<T of <root>.checkT> declared in <root>.checkT' type=kotlin.Function0<T of <root>.checkT> origin=VARIABLE_AS_FUNCTION
|
||||
FUN name:checkTAny visibility:public modality:FINAL <T> (fn:kotlin.Function0<T of <root>.checkTAny>) returnType:T of <root>.checkTAny
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any]
|
||||
VALUE_PARAMETER name:fn index:0 type:kotlin.Function0<T of <root>.checkTAny>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun checkTAny <T> (fn: kotlin.Function0<T of <root>.checkTAny>): T of <root>.checkTAny declared in <root>'
|
||||
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=T of <root>.checkTAny origin=INVOKE
|
||||
$this: GET_VAR 'fn: kotlin.Function0<T of <root>.checkTAny> declared in <root>.checkTAny' type=kotlin.Function0<T of <root>.checkTAny> origin=VARIABLE_AS_FUNCTION
|
||||
FUN name:id visibility:public modality:FINAL <T> (x:T of <root>.id) returnType:T of <root>.id
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
|
||||
VALUE_PARAMETER name:x index:0 type:T of <root>.id
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun id <T> (x: T of <root>.id): T of <root>.id declared in <root>'
|
||||
GET_VAR 'x: T of <root>.id declared in <root>.id' type=T of <root>.id origin=null
|
||||
FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.String?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test1 (): kotlin.String? declared in <root>'
|
||||
CALL 'public final fun checkT <T> (fn: kotlin.Function0<T of <root>.checkT>): T of <root>.checkT declared in <root>' type=kotlin.String? origin=null
|
||||
<T>: kotlin.String?
|
||||
fn: FUN_EXPR type=kotlin.Function0<kotlin.String?> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.String?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.String? declared in <root>.test1'
|
||||
CALL 'public open fun foo (): kotlin.String? declared in <root>.J' type=kotlin.String? origin=null
|
||||
FUN name:test2 visibility:public modality:FINAL <> () returnType:kotlin.String
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test2 (): kotlin.String declared in <root>'
|
||||
TYPE_OP type=kotlin.String origin=IMPLICIT_NOTNULL typeOperand=kotlin.String
|
||||
CALL 'public final fun checkT <T> (fn: kotlin.Function0<T of <root>.checkT>): T of <root>.checkT declared in <root>' type=kotlin.String origin=null
|
||||
<T>: kotlin.String
|
||||
fn: FUN_EXPR type=kotlin.Function0<kotlin.String> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.String
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.String declared in <root>.test2'
|
||||
CALL 'public open fun nnFoo (): kotlin.String declared in <root>.J' type=kotlin.String origin=null
|
||||
FUN name:test3 visibility:public modality:FINAL <> () returnType:kotlin.String?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test3 (): kotlin.String? declared in <root>'
|
||||
CALL 'public final fun checkTAny <T> (fn: kotlin.Function0<T of <root>.checkTAny>): T of <root>.checkTAny declared in <root>' type=kotlin.String? origin=null
|
||||
<T>: kotlin.String?
|
||||
fn: FUN_EXPR type=kotlin.Function0<kotlin.String?> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.String?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.String? declared in <root>.test3'
|
||||
CALL 'public open fun foo (): kotlin.String? declared in <root>.J' type=kotlin.String? origin=null
|
||||
FUN name:test4 visibility:public modality:FINAL <> () returnType:kotlin.String
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test4 (): kotlin.String declared in <root>'
|
||||
TYPE_OP type=kotlin.String origin=IMPLICIT_NOTNULL typeOperand=kotlin.String
|
||||
CALL 'public final fun checkTAny <T> (fn: kotlin.Function0<T of <root>.checkTAny>): T of <root>.checkTAny declared in <root>' type=kotlin.String origin=null
|
||||
<T>: kotlin.String
|
||||
fn: FUN_EXPR type=kotlin.Function0<kotlin.String> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.String
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.String declared in <root>.test4'
|
||||
CALL 'public open fun nnFoo (): kotlin.String declared in <root>.J' type=kotlin.String origin=null
|
||||
@@ -1,10 +1,16 @@
|
||||
FILE fqName:<root> fileName:/nullCheckOnLambdaReturn.kt
|
||||
FUN name:check visibility:public modality:FINAL <> (fn:kotlin.Function0<kotlin.Any>) returnType:kotlin.Any
|
||||
FUN name:checkAny visibility:public modality:FINAL <> (fn:kotlin.Function0<kotlin.Any>) returnType:kotlin.Any
|
||||
VALUE_PARAMETER name:fn index:0 type:kotlin.Function0<kotlin.Any>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun check (fn: kotlin.Function0<kotlin.Any>): kotlin.Any declared in <root>'
|
||||
RETURN type=kotlin.Nothing from='public final fun checkAny (fn: kotlin.Function0<kotlin.Any>): kotlin.Any declared in <root>'
|
||||
CALL 'public abstract fun invoke (): kotlin.Any [operator] declared in kotlin.Function0' type=kotlin.Any origin=null
|
||||
$this: GET_VAR 'fn: kotlin.Function0<kotlin.Any> declared in <root>.check' type=kotlin.Function0<kotlin.Any> origin=null
|
||||
$this: GET_VAR 'fn: kotlin.Function0<kotlin.Any> declared in <root>.checkAny' type=kotlin.Function0<kotlin.Any> origin=null
|
||||
FUN name:checkAnyN visibility:public modality:FINAL <> (fn:kotlin.Function0<kotlin.Any?>) returnType:kotlin.Any?
|
||||
VALUE_PARAMETER name:fn index:0 type:kotlin.Function0<kotlin.Any?>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun checkAnyN (fn: kotlin.Function0<kotlin.Any?>): kotlin.Any? declared in <root>'
|
||||
CALL 'public abstract fun invoke (): kotlin.Any? [operator] declared in kotlin.Function0' type=kotlin.Any? origin=null
|
||||
$this: GET_VAR 'fn: kotlin.Function0<kotlin.Any?> declared in <root>.checkAnyN' type=kotlin.Function0<kotlin.Any?> origin=null
|
||||
FUN name:id visibility:public modality:FINAL <T> (x:T of <root>.id) returnType:T of <root>.id
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
|
||||
VALUE_PARAMETER name:x index:0 type:T of <root>.id
|
||||
@@ -14,7 +20,7 @@ FILE fqName:<root> fileName:/nullCheckOnLambdaReturn.kt
|
||||
FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.Any
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test1 (): kotlin.Any declared in <root>'
|
||||
CALL 'public final fun check (fn: kotlin.Function0<kotlin.Any>): kotlin.Any declared in <root>' type=kotlin.Any origin=null
|
||||
CALL 'public final fun checkAny (fn: kotlin.Function0<kotlin.Any>): kotlin.Any declared in <root>' type=kotlin.Any origin=null
|
||||
fn: FUN_EXPR type=kotlin.Function0<kotlin.Any> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Any
|
||||
BLOCK_BODY
|
||||
@@ -58,3 +64,19 @@ FILE fqName:<root> fileName:/nullCheckOnLambdaReturn.kt
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun <get-test4> (): kotlin.Function0<kotlin.Any> declared in <root>'
|
||||
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test4 type:kotlin.Function0<kotlin.Any> visibility:private [final,static]' type=kotlin.Function0<kotlin.Any> origin=null
|
||||
FUN name:test5 visibility:public modality:FINAL <> () returnType:kotlin.Any?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test5 (): kotlin.Any? declared in <root>'
|
||||
CALL 'public final fun checkAnyN (fn: kotlin.Function0<kotlin.Any?>): kotlin.Any? declared in <root>' type=kotlin.Any? origin=null
|
||||
fn: FUN_EXPR type=kotlin.Function0<kotlin.Any?> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Any?
|
||||
BLOCK_BODY
|
||||
CALL 'public open fun foo (): kotlin.String? [operator] declared in <root>.J' type=kotlin.String? origin=null
|
||||
FUN name:test6 visibility:public modality:FINAL <> () returnType:kotlin.Any?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test6 (): kotlin.Any? declared in <root>'
|
||||
CALL 'public final fun checkAnyN (fn: kotlin.Function0<kotlin.Any?>): kotlin.Any? declared in <root>' type=kotlin.Any? origin=null
|
||||
fn: FUN_EXPR type=kotlin.Function0<kotlin.Any?> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Any?
|
||||
BLOCK_BODY
|
||||
CALL 'public open fun nnFoo (): kotlin.String [operator] declared in <root>.J' type=kotlin.String origin=null
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
// FILE: nullCheckOnLambdaReturn.kt
|
||||
fun check(fn: () -> Any) = fn()
|
||||
fun checkAny(fn: () -> Any) = fn()
|
||||
|
||||
fun checkAnyN(fn: () -> Any?) = fn()
|
||||
|
||||
fun <T> id(x: T) = x
|
||||
|
||||
fun test1() = check { J.foo() }
|
||||
fun test1() = checkAny { J.foo() }
|
||||
|
||||
val test2: () -> Any = { J.foo() }
|
||||
|
||||
@@ -11,7 +13,15 @@ val test3: () -> Any = { J.foo() } as () -> Any
|
||||
|
||||
val test4: () -> Any = id { J.foo() }
|
||||
|
||||
fun test5() = checkAnyN { J.foo() }
|
||||
|
||||
fun test6() = checkAnyN { J.nnFoo() }
|
||||
|
||||
// FILE: J.java
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
public class J {
|
||||
public static String foo() { return null; }
|
||||
|
||||
public static @NotNull String nnFoo() { return null; }
|
||||
}
|
||||
@@ -1,10 +1,16 @@
|
||||
FILE fqName:<root> fileName:/nullCheckOnLambdaReturn.kt
|
||||
FUN name:check visibility:public modality:FINAL <> (fn:kotlin.Function0<kotlin.Any>) returnType:kotlin.Any
|
||||
FUN name:checkAny visibility:public modality:FINAL <> (fn:kotlin.Function0<kotlin.Any>) returnType:kotlin.Any
|
||||
VALUE_PARAMETER name:fn index:0 type:kotlin.Function0<kotlin.Any>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun check (fn: kotlin.Function0<kotlin.Any>): kotlin.Any declared in <root>'
|
||||
RETURN type=kotlin.Nothing from='public final fun checkAny (fn: kotlin.Function0<kotlin.Any>): kotlin.Any declared in <root>'
|
||||
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Any origin=INVOKE
|
||||
$this: GET_VAR 'fn: kotlin.Function0<kotlin.Any> declared in <root>.check' type=kotlin.Function0<kotlin.Any> origin=VARIABLE_AS_FUNCTION
|
||||
$this: GET_VAR 'fn: kotlin.Function0<kotlin.Any> declared in <root>.checkAny' type=kotlin.Function0<kotlin.Any> origin=VARIABLE_AS_FUNCTION
|
||||
FUN name:checkAnyN visibility:public modality:FINAL <> (fn:kotlin.Function0<kotlin.Any?>) returnType:kotlin.Any?
|
||||
VALUE_PARAMETER name:fn index:0 type:kotlin.Function0<kotlin.Any?>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun checkAnyN (fn: kotlin.Function0<kotlin.Any?>): kotlin.Any? declared in <root>'
|
||||
CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=kotlin.Any? origin=INVOKE
|
||||
$this: GET_VAR 'fn: kotlin.Function0<kotlin.Any?> declared in <root>.checkAnyN' type=kotlin.Function0<kotlin.Any?> origin=VARIABLE_AS_FUNCTION
|
||||
FUN name:id visibility:public modality:FINAL <T> (x:T of <root>.id) returnType:T of <root>.id
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
|
||||
VALUE_PARAMETER name:x index:0 type:T of <root>.id
|
||||
@@ -14,7 +20,7 @@ FILE fqName:<root> fileName:/nullCheckOnLambdaReturn.kt
|
||||
FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.Any
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test1 (): kotlin.Any declared in <root>'
|
||||
CALL 'public final fun check (fn: kotlin.Function0<kotlin.Any>): kotlin.Any declared in <root>' type=kotlin.Any origin=null
|
||||
CALL 'public final fun checkAny (fn: kotlin.Function0<kotlin.Any>): kotlin.Any declared in <root>' type=kotlin.Any origin=null
|
||||
fn: FUN_EXPR type=kotlin.Function0<kotlin.String?> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.String?
|
||||
BLOCK_BODY
|
||||
@@ -64,3 +70,21 @@ FILE fqName:<root> fileName:/nullCheckOnLambdaReturn.kt
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun <get-test4> (): kotlin.Function0<kotlin.Any> declared in <root>'
|
||||
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test4 type:kotlin.Function0<kotlin.Any> visibility:private [final,static]' type=kotlin.Function0<kotlin.Any> origin=null
|
||||
FUN name:test5 visibility:public modality:FINAL <> () returnType:kotlin.Any?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test5 (): kotlin.Any? declared in <root>'
|
||||
CALL 'public final fun checkAnyN (fn: kotlin.Function0<kotlin.Any?>): kotlin.Any? declared in <root>' type=kotlin.Any? origin=null
|
||||
fn: FUN_EXPR type=kotlin.Function0<kotlin.String?> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.String?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.String? declared in <root>.test5'
|
||||
CALL 'public open fun foo (): kotlin.String? declared in <root>.J' type=kotlin.String? origin=null
|
||||
FUN name:test6 visibility:public modality:FINAL <> () returnType:kotlin.Any?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test6 (): kotlin.Any? declared in <root>'
|
||||
CALL 'public final fun checkAnyN (fn: kotlin.Function0<kotlin.Any?>): kotlin.Any? declared in <root>' type=kotlin.Any? origin=null
|
||||
fn: FUN_EXPR type=kotlin.Function0<kotlin.String> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.String
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.String declared in <root>.test6'
|
||||
CALL 'public open fun nnFoo (): kotlin.String declared in <root>.J' type=kotlin.String origin=null
|
||||
|
||||
+5
@@ -14644,6 +14644,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/enhancedNullability/inFunctionWithExpressionBodyWithJavaGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inLambdaReturnWithExpectedType.kt")
|
||||
public void testInLambdaReturnWithExpectedType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/enhancedNullability/inLambdaReturnWithExpectedType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inLocalFunctionWithExpressionBody.kt")
|
||||
public void testInLocalFunctionWithExpressionBody() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/enhancedNullability/inLocalFunctionWithExpressionBody.kt");
|
||||
|
||||
+5
@@ -14644,6 +14644,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/enhancedNullability/inFunctionWithExpressionBodyWithJavaGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inLambdaReturnWithExpectedType.kt")
|
||||
public void testInLambdaReturnWithExpectedType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/enhancedNullability/inLambdaReturnWithExpectedType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inLocalFunctionWithExpressionBody.kt")
|
||||
public void testInLocalFunctionWithExpressionBody() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/enhancedNullability/inLocalFunctionWithExpressionBody.kt");
|
||||
|
||||
+5
@@ -13494,6 +13494,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/enhancedNullability/inFunctionWithExpressionBodyWithJavaGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inLambdaReturnWithExpectedType.kt")
|
||||
public void testInLambdaReturnWithExpectedType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/enhancedNullability/inLambdaReturnWithExpectedType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inLocalFunctionWithExpressionBody.kt")
|
||||
public void testInLocalFunctionWithExpressionBody() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/enhancedNullability/inLocalFunctionWithExpressionBody.kt");
|
||||
|
||||
+5
@@ -13494,6 +13494,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/enhancedNullability/inFunctionWithExpressionBodyWithJavaGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inLambdaReturnWithExpectedType.kt")
|
||||
public void testInLambdaReturnWithExpectedType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/enhancedNullability/inLambdaReturnWithExpectedType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inLocalFunctionWithExpressionBody.kt")
|
||||
public void testInLocalFunctionWithExpressionBody() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/enhancedNullability/inLocalFunctionWithExpressionBody.kt");
|
||||
|
||||
@@ -1086,6 +1086,11 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
|
||||
runTest("compiler/testData/ir/irText/expressions/multipleThisReferences.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nullCheckOnGenericLambdaReturn.kt")
|
||||
public void testNullCheckOnGenericLambdaReturn() throws Exception {
|
||||
runTest("compiler/testData/ir/irText/expressions/nullCheckOnGenericLambdaReturn.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nullCheckOnLambdaReturn.kt")
|
||||
public void testNullCheckOnLambdaReturn() throws Exception {
|
||||
runTest("compiler/testData/ir/irText/expressions/nullCheckOnLambdaReturn.kt");
|
||||
|
||||
Reference in New Issue
Block a user