diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java index a0b1c22a31f..ea3634063c4 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java @@ -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"); diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt index 3050f3620e4..ee133925703 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt @@ -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) diff --git a/compiler/testData/codegen/box/javaInterop/notNullAssertions/enhancedNullability/inLambdaReturnWithExpectedType.kt b/compiler/testData/codegen/box/javaInterop/notNullAssertions/enhancedNullability/inLambdaReturnWithExpectedType.kt new file mode 100644 index 00000000000..1961949d271 --- /dev/null +++ b/compiler/testData/codegen/box/javaInterop/notNullAssertions/enhancedNullability/inLambdaReturnWithExpectedType.kt @@ -0,0 +1,64 @@ +// !LANGUAGE: +StrictJavaNullabilityAssertions +// TARGET_BACKEND: JVM + +// FILE: inLambdaReturnWithExpectedType.kt +fun check(fn: () -> Any) { fn() } + +fun checkT(fn: () -> T) { fn() } + +fun 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; + } +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/nullCheckOnGenericLambdaReturn.fir.txt b/compiler/testData/ir/irText/expressions/nullCheckOnGenericLambdaReturn.fir.txt new file mode 100644 index 00000000000..291568f5eaa --- /dev/null +++ b/compiler/testData/ir/irText/expressions/nullCheckOnGenericLambdaReturn.fir.txt @@ -0,0 +1,69 @@ +FILE fqName: fileName:/nullCheckOnGenericLambdaReturn.kt + FUN name:checkAny visibility:public modality:FINAL <> (fn:kotlin.Function0) returnType:kotlin.Any + VALUE_PARAMETER name:fn index:0 type:kotlin.Function0 + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun checkAny (fn: kotlin.Function0): kotlin.Any declared in ' + CALL 'public abstract fun invoke (): kotlin.Any [operator] declared in kotlin.Function0' type=kotlin.Any origin=null + $this: GET_VAR 'fn: kotlin.Function0 declared in .checkAny' type=kotlin.Function0 origin=null + FUN name:checkAnyN visibility:public modality:FINAL <> (fn:kotlin.Function0) returnType:kotlin.Any? + VALUE_PARAMETER name:fn index:0 type:kotlin.Function0 + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun checkAnyN (fn: kotlin.Function0): kotlin.Any? declared in ' + CALL 'public abstract fun invoke (): kotlin.Any? [operator] declared in kotlin.Function0' type=kotlin.Any? origin=null + $this: GET_VAR 'fn: kotlin.Function0 declared in .checkAnyN' type=kotlin.Function0 origin=null + FUN name:checkT visibility:public modality:FINAL (fn:kotlin.Function0.checkT>) returnType:T of .checkT + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + VALUE_PARAMETER name:fn index:0 type:kotlin.Function0.checkT> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun checkT (fn: kotlin.Function0.checkT>): T of .checkT declared in ' + CALL 'public abstract fun invoke (): T of .checkT [operator] declared in kotlin.Function0' type=T of .checkT origin=null + $this: GET_VAR 'fn: kotlin.Function0.checkT> declared in .checkT' type=kotlin.Function0.checkT> origin=null + FUN name:checkTAny visibility:public modality:FINAL (fn:kotlin.Function0.checkTAny>) returnType:T of .checkTAny + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any] + VALUE_PARAMETER name:fn index:0 type:kotlin.Function0.checkTAny> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun checkTAny (fn: kotlin.Function0.checkTAny>): T of .checkTAny declared in ' + CALL 'public abstract fun invoke (): T of .checkTAny [operator] declared in kotlin.Function0' type=T of .checkTAny origin=null + $this: GET_VAR 'fn: kotlin.Function0.checkTAny> declared in .checkTAny' type=kotlin.Function0.checkTAny> origin=null + FUN name:id visibility:public modality:FINAL (x:T of .id) returnType:T of .id + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + VALUE_PARAMETER name:x index:0 type:T of .id + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun id (x: T of .id): T of .id declared in ' + GET_VAR 'x: T of .id declared in .id' type=T of .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 ' + CALL 'public final fun checkT (fn: kotlin.Function0.checkT>): T of .checkT declared in ' type=kotlin.String? origin=null + : kotlin.String? + fn: FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.String? + BLOCK_BODY + CALL 'public open fun foo (): kotlin.String? [operator] declared in .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 ' + CALL 'public final fun checkT (fn: kotlin.Function0.checkT>): T of .checkT declared in ' type=kotlin.String origin=null + : kotlin.String + fn: FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.String + BLOCK_BODY + CALL 'public open fun nnFoo (): kotlin.String [operator] declared in .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 ' + CALL 'public final fun checkTAny (fn: kotlin.Function0.checkTAny>): T of .checkTAny declared in ' type=kotlin.String? origin=null + : kotlin.String? + fn: FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.String? + BLOCK_BODY + CALL 'public open fun foo (): kotlin.String? [operator] declared in .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 ' + CALL 'public final fun checkTAny (fn: kotlin.Function0.checkTAny>): T of .checkTAny declared in ' type=kotlin.String origin=null + : kotlin.String + fn: FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.String + BLOCK_BODY + CALL 'public open fun nnFoo (): kotlin.String [operator] declared in .J' type=kotlin.String origin=null diff --git a/compiler/testData/ir/irText/expressions/nullCheckOnGenericLambdaReturn.kt b/compiler/testData/ir/irText/expressions/nullCheckOnGenericLambdaReturn.kt new file mode 100644 index 00000000000..0db77324671 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/nullCheckOnGenericLambdaReturn.kt @@ -0,0 +1,27 @@ +// FILE: nullCheckOnGenericLambdaReturn.kt +fun checkAny(fn: () -> Any) = fn() + +fun checkAnyN(fn: () -> Any?) = fn() + +fun checkT(fn: () -> T) = fn() + +fun checkTAny(fn: () -> T) = fn() + +fun 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; } +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/nullCheckOnGenericLambdaReturn.txt b/compiler/testData/ir/irText/expressions/nullCheckOnGenericLambdaReturn.txt new file mode 100644 index 00000000000..423dc3101e1 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/nullCheckOnGenericLambdaReturn.txt @@ -0,0 +1,75 @@ +FILE fqName: fileName:/nullCheckOnGenericLambdaReturn.kt + FUN name:checkAny visibility:public modality:FINAL <> (fn:kotlin.Function0) returnType:kotlin.Any + VALUE_PARAMETER name:fn index:0 type:kotlin.Function0 + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun checkAny (fn: kotlin.Function0): kotlin.Any declared in ' + 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 declared in .checkAny' type=kotlin.Function0 origin=VARIABLE_AS_FUNCTION + FUN name:checkAnyN visibility:public modality:FINAL <> (fn:kotlin.Function0) returnType:kotlin.Any? + VALUE_PARAMETER name:fn index:0 type:kotlin.Function0 + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun checkAnyN (fn: kotlin.Function0): kotlin.Any? declared in ' + 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 declared in .checkAnyN' type=kotlin.Function0 origin=VARIABLE_AS_FUNCTION + FUN name:checkT visibility:public modality:FINAL (fn:kotlin.Function0.checkT>) returnType:T of .checkT + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + VALUE_PARAMETER name:fn index:0 type:kotlin.Function0.checkT> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun checkT (fn: kotlin.Function0.checkT>): T of .checkT declared in ' + CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=T of .checkT origin=INVOKE + $this: GET_VAR 'fn: kotlin.Function0.checkT> declared in .checkT' type=kotlin.Function0.checkT> origin=VARIABLE_AS_FUNCTION + FUN name:checkTAny visibility:public modality:FINAL (fn:kotlin.Function0.checkTAny>) returnType:T of .checkTAny + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any] + VALUE_PARAMETER name:fn index:0 type:kotlin.Function0.checkTAny> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun checkTAny (fn: kotlin.Function0.checkTAny>): T of .checkTAny declared in ' + CALL 'public abstract fun invoke (): R of kotlin.Function0 [operator] declared in kotlin.Function0' type=T of .checkTAny origin=INVOKE + $this: GET_VAR 'fn: kotlin.Function0.checkTAny> declared in .checkTAny' type=kotlin.Function0.checkTAny> origin=VARIABLE_AS_FUNCTION + FUN name:id visibility:public modality:FINAL (x:T of .id) returnType:T of .id + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + VALUE_PARAMETER name:x index:0 type:T of .id + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun id (x: T of .id): T of .id declared in ' + GET_VAR 'x: T of .id declared in .id' type=T of .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 ' + CALL 'public final fun checkT (fn: kotlin.Function0.checkT>): T of .checkT declared in ' type=kotlin.String? origin=null + : kotlin.String? + fn: FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.String? + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (): kotlin.String? declared in .test1' + CALL 'public open fun foo (): kotlin.String? declared in .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 ' + TYPE_OP type=kotlin.String origin=IMPLICIT_NOTNULL typeOperand=kotlin.String + CALL 'public final fun checkT (fn: kotlin.Function0.checkT>): T of .checkT declared in ' type=kotlin.String origin=null + : kotlin.String + fn: FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (): kotlin.String declared in .test2' + CALL 'public open fun nnFoo (): kotlin.String declared in .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 ' + CALL 'public final fun checkTAny (fn: kotlin.Function0.checkTAny>): T of .checkTAny declared in ' type=kotlin.String? origin=null + : kotlin.String? + fn: FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.String? + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (): kotlin.String? declared in .test3' + CALL 'public open fun foo (): kotlin.String? declared in .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 ' + TYPE_OP type=kotlin.String origin=IMPLICIT_NOTNULL typeOperand=kotlin.String + CALL 'public final fun checkTAny (fn: kotlin.Function0.checkTAny>): T of .checkTAny declared in ' type=kotlin.String origin=null + : kotlin.String + fn: FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (): kotlin.String declared in .test4' + CALL 'public open fun nnFoo (): kotlin.String declared in .J' type=kotlin.String origin=null diff --git a/compiler/testData/ir/irText/expressions/nullCheckOnLambdaReturn.fir.txt b/compiler/testData/ir/irText/expressions/nullCheckOnLambdaReturn.fir.txt index 47ef579b674..3ca8cbc972e 100644 --- a/compiler/testData/ir/irText/expressions/nullCheckOnLambdaReturn.fir.txt +++ b/compiler/testData/ir/irText/expressions/nullCheckOnLambdaReturn.fir.txt @@ -1,10 +1,16 @@ FILE fqName: fileName:/nullCheckOnLambdaReturn.kt - FUN name:check visibility:public modality:FINAL <> (fn:kotlin.Function0) returnType:kotlin.Any + FUN name:checkAny visibility:public modality:FINAL <> (fn:kotlin.Function0) returnType:kotlin.Any VALUE_PARAMETER name:fn index:0 type:kotlin.Function0 BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun check (fn: kotlin.Function0): kotlin.Any declared in ' + RETURN type=kotlin.Nothing from='public final fun checkAny (fn: kotlin.Function0): kotlin.Any declared in ' CALL 'public abstract fun invoke (): kotlin.Any [operator] declared in kotlin.Function0' type=kotlin.Any origin=null - $this: GET_VAR 'fn: kotlin.Function0 declared in .check' type=kotlin.Function0 origin=null + $this: GET_VAR 'fn: kotlin.Function0 declared in .checkAny' type=kotlin.Function0 origin=null + FUN name:checkAnyN visibility:public modality:FINAL <> (fn:kotlin.Function0) returnType:kotlin.Any? + VALUE_PARAMETER name:fn index:0 type:kotlin.Function0 + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun checkAnyN (fn: kotlin.Function0): kotlin.Any? declared in ' + CALL 'public abstract fun invoke (): kotlin.Any? [operator] declared in kotlin.Function0' type=kotlin.Any? origin=null + $this: GET_VAR 'fn: kotlin.Function0 declared in .checkAnyN' type=kotlin.Function0 origin=null FUN name:id visibility:public modality:FINAL (x:T of .id) returnType:T of .id TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] VALUE_PARAMETER name:x index:0 type:T of .id @@ -14,7 +20,7 @@ FILE fqName: 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 ' - CALL 'public final fun check (fn: kotlin.Function0): kotlin.Any declared in ' type=kotlin.Any origin=null + CALL 'public final fun checkAny (fn: kotlin.Function0): kotlin.Any declared in ' type=kotlin.Any origin=null fn: FUN_EXPR type=kotlin.Function0 origin=LAMBDA FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.Any BLOCK_BODY @@ -58,3 +64,19 @@ FILE fqName: fileName:/nullCheckOnLambdaReturn.kt BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun (): kotlin.Function0 declared in ' GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test4 type:kotlin.Function0 visibility:private [final,static]' type=kotlin.Function0 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 ' + CALL 'public final fun checkAnyN (fn: kotlin.Function0): kotlin.Any? declared in ' type=kotlin.Any? origin=null + fn: FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.Any? + BLOCK_BODY + CALL 'public open fun foo (): kotlin.String? [operator] declared in .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 ' + CALL 'public final fun checkAnyN (fn: kotlin.Function0): kotlin.Any? declared in ' type=kotlin.Any? origin=null + fn: FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.Any? + BLOCK_BODY + CALL 'public open fun nnFoo (): kotlin.String [operator] declared in .J' type=kotlin.String origin=null diff --git a/compiler/testData/ir/irText/expressions/nullCheckOnLambdaReturn.kt b/compiler/testData/ir/irText/expressions/nullCheckOnLambdaReturn.kt index fc72c8bde2a..7ce4e63da85 100644 --- a/compiler/testData/ir/irText/expressions/nullCheckOnLambdaReturn.kt +++ b/compiler/testData/ir/irText/expressions/nullCheckOnLambdaReturn.kt @@ -1,9 +1,11 @@ // FILE: nullCheckOnLambdaReturn.kt -fun check(fn: () -> Any) = fn() +fun checkAny(fn: () -> Any) = fn() + +fun checkAnyN(fn: () -> Any?) = fn() fun 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; } } \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/nullCheckOnLambdaReturn.txt b/compiler/testData/ir/irText/expressions/nullCheckOnLambdaReturn.txt index 67076913820..7186077e147 100644 --- a/compiler/testData/ir/irText/expressions/nullCheckOnLambdaReturn.txt +++ b/compiler/testData/ir/irText/expressions/nullCheckOnLambdaReturn.txt @@ -1,10 +1,16 @@ FILE fqName: fileName:/nullCheckOnLambdaReturn.kt - FUN name:check visibility:public modality:FINAL <> (fn:kotlin.Function0) returnType:kotlin.Any + FUN name:checkAny visibility:public modality:FINAL <> (fn:kotlin.Function0) returnType:kotlin.Any VALUE_PARAMETER name:fn index:0 type:kotlin.Function0 BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun check (fn: kotlin.Function0): kotlin.Any declared in ' + RETURN type=kotlin.Nothing from='public final fun checkAny (fn: kotlin.Function0): kotlin.Any declared in ' 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 declared in .check' type=kotlin.Function0 origin=VARIABLE_AS_FUNCTION + $this: GET_VAR 'fn: kotlin.Function0 declared in .checkAny' type=kotlin.Function0 origin=VARIABLE_AS_FUNCTION + FUN name:checkAnyN visibility:public modality:FINAL <> (fn:kotlin.Function0) returnType:kotlin.Any? + VALUE_PARAMETER name:fn index:0 type:kotlin.Function0 + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun checkAnyN (fn: kotlin.Function0): kotlin.Any? declared in ' + 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 declared in .checkAnyN' type=kotlin.Function0 origin=VARIABLE_AS_FUNCTION FUN name:id visibility:public modality:FINAL (x:T of .id) returnType:T of .id TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] VALUE_PARAMETER name:x index:0 type:T of .id @@ -14,7 +20,7 @@ FILE fqName: 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 ' - CALL 'public final fun check (fn: kotlin.Function0): kotlin.Any declared in ' type=kotlin.Any origin=null + CALL 'public final fun checkAny (fn: kotlin.Function0): kotlin.Any declared in ' type=kotlin.Any origin=null fn: FUN_EXPR type=kotlin.Function0 origin=LAMBDA FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.String? BLOCK_BODY @@ -64,3 +70,21 @@ FILE fqName: fileName:/nullCheckOnLambdaReturn.kt BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun (): kotlin.Function0 declared in ' GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test4 type:kotlin.Function0 visibility:private [final,static]' type=kotlin.Function0 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 ' + CALL 'public final fun checkAnyN (fn: kotlin.Function0): kotlin.Any? declared in ' type=kotlin.Any? origin=null + fn: FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.String? + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (): kotlin.String? declared in .test5' + CALL 'public open fun foo (): kotlin.String? declared in .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 ' + CALL 'public final fun checkAnyN (fn: kotlin.Function0): kotlin.Any? declared in ' type=kotlin.Any? origin=null + fn: FUN_EXPR type=kotlin.Function0 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> () returnType:kotlin.String + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (): kotlin.String declared in .test6' + CALL 'public open fun nnFoo (): kotlin.String declared in .J' type=kotlin.String origin=null diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index b8f48ce24b4..fb870140b31 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 8d76f9d39d9..f8380ab05bf 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index a2569abb42f..aee297818f6 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 891c051249e..ea39d6f1f17 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -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"); diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index ffeddee9c3d..3344ae32ce7 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -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");