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:
Dmitry Petrov
2020-01-09 13:47:56 +03:00
parent c47e04ac8d
commit 4cf8203ce7
14 changed files with 368 additions and 22 deletions
@@ -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");
@@ -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)
@@ -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;
}
}
@@ -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
@@ -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");
@@ -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");
@@ -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");
@@ -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");