FIR2IR: Repeat the K1 behavior: SAM conversion with 'in' projection

It would be more consistently to prohibit the behavior from the unmuted
test (see KT-52428), but it was decided to postpone the breaking change.

Unfortunately, it didn't work to make a test where for computing
star projections we would need to substitute other type parameters
because effectively, it's not allowed to have SAM conversion when
star projections/wildcard is based on a type parameter which bounds
use other type parameters.

^KT-53552 In progress
This commit is contained in:
Denis.Zharkov
2023-02-15 11:54:17 +01:00
committed by Space Team
parent 45eefab811
commit 05ca001310
22 changed files with 158 additions and 53 deletions
@@ -61,6 +61,8 @@ class SamTypeApproximator(builtIns: KotlinBuiltIns, languageVersionSettings: Lan
return approximatedOriginalTypeToUse.removeExternalProjections(carefulApproximationOfContravariantProjection)
}
// When changing this, please consider also changing the mirroring K2 function at
// org.jetbrains.kotlin.fir.backend.generators.AdapterGenerator.removeExternalProjections
private fun KotlinType.removeExternalProjections(carefulApproximationOfContravariantProjection: Boolean): KotlinType? {
val newArguments = arguments.mapIndexed { i, argument ->
if (carefulApproximationOfContravariantProjection && argument.projectionKind == Variance.IN_VARIANCE) {
@@ -101,27 +101,17 @@ internal enum class ConversionTypeOrigin {
SETTER
}
class ConversionTypeContext internal constructor(
internal val invariantProjection: Boolean = false,
internal val origin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT,
) {
class ConversionTypeContext internal constructor(internal val origin: ConversionTypeOrigin) {
fun inSetter() = ConversionTypeContext(
invariantProjection = invariantProjection,
origin = ConversionTypeOrigin.SETTER
)
fun withInvariantProjections() = ConversionTypeContext(
invariantProjection = true,
origin = origin
)
companion object {
internal val DEFAULT = ConversionTypeContext(
invariantProjection = false, origin = ConversionTypeOrigin.DEFAULT
origin = ConversionTypeOrigin.DEFAULT
)
internal val WITH_INVARIANT = DEFAULT.withInvariantProjections()
internal val IN_SETTER = ConversionTypeContext(
invariantProjection = false, origin = ConversionTypeOrigin.SETTER
origin = ConversionTypeOrigin.SETTER
)
}
}
@@ -229,7 +229,7 @@ class Fir2IrTypeConverter(
private fun ConeTypeProjection.toIrTypeArgument(typeContext: ConversionTypeContext): IrTypeArgument {
fun toIrTypeArgument(type: ConeKotlinType, variance: Variance): IrTypeProjection {
val irType = type.toIrType(typeContext)
return makeTypeProjection(irType, if (typeContext.invariantProjection) Variance.INVARIANT else variance)
return makeTypeProjection(irType, variance)
}
return when (this) {
@@ -26,7 +26,9 @@ import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.ir.builders.declarations.UNDEFINED_PARAMETER_INDEX
import org.jetbrains.kotlin.ir.declarations.*
@@ -44,6 +46,7 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.model.TypeVariance
/**
* A generator that converts callable references or arguments that needs an adapter in between. This covers:
@@ -428,17 +431,81 @@ internal class AdapterGenerator(
return this
}
val parameterType = parameter.returnTypeRef.coneType
val substitutedParameterType = starProjectionApproximator.substituteOrSelf(substitutor.substituteOrSelf(parameterType))
val samFirType = if (substitutedParameterType is ConeRawType) substitutedParameterType.lowerBound else substitutedParameterType
var samType = samFirType.toIrType(ConversionTypeContext.WITH_INVARIANT)
if (shouldUnwrapVarargType) {
samType = samType.getArrayElementType(irBuiltIns)
}
val substitutedParameterType =
starProjectionApproximator.substituteOrSelf(substitutor.substituteOrSelf(parameterType)).let {
if (shouldUnwrapVarargType)
it.arrayElementType() ?: it
else
it
}
val samFirType = substitutedParameterType.removeExternalProjections() ?: substitutedParameterType
val samType = samFirType.toIrType(ConversionTypeContext.DEFAULT)
// Make sure the converted IrType owner indeed has a single abstract method, since FunctionReferenceLowering relies on it.
if (!samType.isSamType) return this
return IrTypeOperatorCallImpl(this.startOffset, this.endOffset, samType, IrTypeOperator.SAM_CONVERSION, samType, this)
}
// This function is mostly a mirror of org.jetbrains.kotlin.backend.common.SamTypeApproximator.removeExternalProjections
// First attempts, to share the code between K1 and K2 via type contexts stumbled upon the absence of star-projection-type in K2
// and the possibility of incorrectly mapped details that might break some code when using K1.
private fun ConeKotlinType.removeExternalProjections(): ConeKotlinType? =
when (this) {
is ConeSimpleKotlinType -> removeExternalProjections()
is ConeFlexibleType -> ConeFlexibleType(
lowerBound.removeExternalProjections() ?: lowerBound,
upperBound.removeExternalProjections() ?: upperBound,
)
}
private fun ConeSimpleKotlinType.removeExternalProjections(): ConeSimpleKotlinType? =
with(session.typeContext) {
val typeConstructor = typeConstructor()
val parameters = typeConstructor.getParameters()
val parameterSet = parameters.toSet()
@Suppress("UNCHECKED_CAST")
val newArguments = getArguments().mapIndexed { i, argument ->
val parameter = parameters.getOrNull(i) ?: return null
when {
argument.getVariance() == TypeVariance.IN -> {
// Just erasing `in` from the type projection would lead to an incorrect type for the SAM adapter,
// and error at runtime on JVM if invokedynamic + LambdaMetafactory is used, see KT-51868.
// So we do it "carefully". If we have a class `A<T>` and a method that takes e.g. `A<in String>`, we check
// if `T` has a non-trivial upper bound. If it has one, we don't attempt to perform a SAM conversion at all.
// Otherwise we erase the type to `Any?`, so `A<in String>` becomes `A<Any?>`, which is the computed SAM type.
val upperBound = parameter.getUpperBounds().singleOrNull()?.upperBoundIfFlexible() ?: return null
if (!upperBound.isNullableAny()) return null
upperBound
}
!argument.isStarProjection() -> argument.getType()
else -> parameter.typeParameterSymbol.starProjectionTypeRepresentation(parameterSet)
}
} as List<ConeTypeProjection>
withArguments(newArguments.toTypedArray())
}
// See the definition from K1 at org.jetbrains.kotlin.types.StarProjectionImpl.get_type
// In K1, it's used more frequently because of not-nullable TypeProjection::getType, but in K2 we almost got rid of it
// But here, we still need it to more-or-less fully reproduce the semantics of K1 when generating SAM conversions
private fun FirTypeParameterSymbol.starProjectionTypeRepresentation(containingParameterSet: Set<ConeTypeParameterLookupTag>): ConeKotlinType {
val substitutor = object : AbstractConeSubstitutor(session.typeContext) {
// We don't substitute types
override fun substituteType(type: ConeKotlinType): ConeKotlinType? = null
override fun substituteArgument(projection: ConeTypeProjection, index: Int): ConeTypeProjection? {
// But we substitute type parameters from the class-owner of this@FirTypeParameterSymbol as it's done in K1
if (projection is ConeTypeParameterType && projection.lookupTag in containingParameterSet) return ConeStarProjection
return super.substituteArgument(projection, index)
}
}
return substitutor.substituteOrSelf(resolvedBounds.first().type)
}
private fun IrVararg.applyConversionOnVararg(
argument: FirExpression,
conversion: IrExpression.(FirExpression) -> IrExpression
@@ -27416,6 +27416,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/invokedynamic/sam/simpleIndySam.kt");
}
@Test
@TestMetadata("starProjectionSam.kt")
public void testStarProjectionSam() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/starProjectionSam.kt");
}
@Test
@TestMetadata("streamApi1.kt")
public void testStreamApi1() throws Exception {
@@ -27416,6 +27416,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/invokedynamic/sam/simpleIndySam.kt");
}
@Test
@TestMetadata("starProjectionSam.kt")
public void testStarProjectionSam() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/starProjectionSam.kt");
}
@Test
@TestMetadata("streamApi1.kt")
public void testStreamApi1() throws Exception {
@@ -268,7 +268,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
}
}
override fun TypeConstructorMarker.getParameters(): List<TypeParameterMarker> {
override fun TypeConstructorMarker.getParameters(): List<ConeTypeParameterLookupTag> {
return when (val symbol = toClassLikeSymbol()) {
is FirAnonymousObjectSymbol -> symbol.fir.typeParameters.map { it.symbol.toLookupTag() }
is FirRegularClassSymbol -> symbol.fir.typeParameters.map { it.symbol.toLookupTag() }
@@ -1,8 +1,6 @@
// IGNORE_BACKEND: JVM
// IGNORE_LIGHT_ANALYSIS
// IGNORE_BACKEND_K2: JVM_IR
// FIR_STATUS: LambdaConversionException: Type mismatch for lambda argument 1: class java.lang.Object is not convertible to interface I1
// JVM_IR it this case has an approximated type 'KFun<out Any>', which has a projected top-level argument.
fun <T> intersect(x: T, y: T): T = x
@@ -1,7 +1,3 @@
// IGNORE_BACKEND_K2: JVM_IR, JS_IR
// FIR status: "ClassCastException: String cannot be cast to StringBuilder".
// FIR always takes the parameter type and erases type projections in it to obtain the SAM type. This is incorrect, see KT-51868 and KT-52428.
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_STDLIB
@@ -1,7 +1,3 @@
// IGNORE_BACKEND_K2: JVM_IR, JS_IR
// FIR status: the test passes but LambdaMetafactory is used, so bytecode text check fails.
// In this case FIR behavior is fine but it works because of a hack in
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// SAM_CONVERSIONS: INDY
@@ -0,0 +1,28 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_STDLIB
// CHECK_BYTECODE_TEXT
// JVM_IR_TEMPLATES
// 1 java/lang/invoke/LambdaMetafactory
// FILE: box.kt
fun box(): String {
return Request.foo { x, y -> "OK" }
}
// FILE: Request.java
public class Request {
public static String foo(Func<?, ?, ?> x) {
return ((Func) x).bar(null, null).toString();
}
}
// FILE: Func.java
import java.util.List;
public interface Func<T1 extends List<?>, T2 extends CharSequence, R> {
R bar(T1 t1, T2 t2);
}
+3 -2
View File
@@ -9,7 +9,8 @@ FILE fqName:<root> fileName:/box.kt
BLOCK_BODY
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
CONSTRUCTOR_CALL 'public constructor <init> (filter: @[FlexibleNullability] <root>.Condition<in @[FlexibleNullability] kotlin.String?>?) declared in <root>.J' type=<root>.J origin=null
filter: TYPE_OP type=@[FlexibleNullability] <root>.Condition<@[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] <root>.Condition<@[FlexibleNullability] kotlin.String?>?
GET_VAR 'filter: kotlin.Function1<kotlin.String, kotlin.Boolean>? declared in <root>.foo' type=kotlin.Function1<kotlin.String, kotlin.Boolean>? origin=null
filter: TYPE_OP type=@[FlexibleNullability] <root>.Condition<kotlin.Any?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] <root>.Condition<kotlin.Any?>?
TYPE_OP type=@[FlexibleNullability] kotlin.Function1<@[FlexibleNullability] kotlin.Any?, kotlin.Boolean>? origin=IMPLICIT_CAST typeOperand=@[FlexibleNullability] kotlin.Function1<@[FlexibleNullability] kotlin.Any?, kotlin.Boolean>?
GET_VAR 'filter: kotlin.Function1<kotlin.String, kotlin.Boolean>? declared in <root>.foo' type=kotlin.Function1<kotlin.String, kotlin.Boolean>? origin=null
RETURN type=kotlin.Nothing from='public final fun foo (filter: kotlin.Function1<kotlin.String, kotlin.Boolean>?): kotlin.String declared in <root>'
CONST String type=kotlin.String value="OK"
@@ -6,7 +6,7 @@ FILE fqName:<root> fileName:/genericSamProjectedOut.kt
<class: A>: kotlin.String
CALL 'public open fun someFunction (hello: @[FlexibleNullability] example.Hello<@[FlexibleNullability] A of example.SomeJavaClass?>?): kotlin.Unit declared in example.SomeJavaClass' type=kotlin.Unit origin=null
$this: GET_VAR 'var a: example.SomeJavaClass<out kotlin.String> [var] declared in <root>.test' type=example.SomeJavaClass<out kotlin.String> origin=null
hello: TYPE_OP type=@[FlexibleNullability] example.Hello<@[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] example.Hello<@[FlexibleNullability] kotlin.String?>?
hello: TYPE_OP type=@[FlexibleNullability] example.Hello<out @[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] example.Hello<out @[FlexibleNullability] kotlin.String?>?
FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.String?, kotlin.Unit> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (it:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Unit
VALUE_PARAMETER name:it index:0 type:@[FlexibleNullability] kotlin.String?
@@ -16,7 +16,7 @@ FILE fqName:<root> fileName:/genericSamProjectedOut.kt
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
CALL 'public open fun plus (hello: @[FlexibleNullability] example.Hello<@[FlexibleNullability] A of example.SomeJavaClass?>?): @[FlexibleNullability] example.SomeJavaClass<@[FlexibleNullability] A of example.SomeJavaClass?>? [operator] declared in example.SomeJavaClass' type=@[FlexibleNullability] example.SomeJavaClass<out @[FlexibleNullability] kotlin.String?>? origin=PLUS
$this: GET_VAR 'var a: example.SomeJavaClass<out kotlin.String> [var] declared in <root>.test' type=example.SomeJavaClass<out kotlin.String> origin=null
hello: TYPE_OP type=@[FlexibleNullability] example.Hello<@[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] example.Hello<@[FlexibleNullability] kotlin.String?>?
hello: TYPE_OP type=@[FlexibleNullability] example.Hello<out @[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] example.Hello<out @[FlexibleNullability] kotlin.String?>?
FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.String?, kotlin.Unit> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (it:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Unit
VALUE_PARAMETER name:it index:0 type:@[FlexibleNullability] kotlin.String?
@@ -25,7 +25,7 @@ FILE fqName:<root> fileName:/genericSamProjectedOut.kt
GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
CALL 'public open fun get (hello: @[FlexibleNullability] example.Hello<@[FlexibleNullability] A of example.SomeJavaClass?>?): kotlin.Unit [operator] declared in example.SomeJavaClass' type=kotlin.Unit origin=null
$this: GET_VAR 'var a: example.SomeJavaClass<out kotlin.String> [var] declared in <root>.test' type=example.SomeJavaClass<out kotlin.String> origin=null
hello: TYPE_OP type=@[FlexibleNullability] example.Hello<@[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] example.Hello<@[FlexibleNullability] kotlin.String?>?
hello: TYPE_OP type=@[FlexibleNullability] example.Hello<out @[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] example.Hello<out @[FlexibleNullability] kotlin.String?>?
FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.String?, kotlin.Unit> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (it:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Unit
VALUE_PARAMETER name:it index:0 type:@[FlexibleNullability] kotlin.String?
@@ -35,7 +35,7 @@ FILE fqName:<root> fileName:/genericSamProjectedOut.kt
SET_VAR 'var a: example.SomeJavaClass<out kotlin.String> [var] declared in <root>.test' type=kotlin.Unit origin=EQ
CALL 'public open fun plus (hello: @[FlexibleNullability] example.Hello<@[FlexibleNullability] A of example.SomeJavaClass?>?): @[FlexibleNullability] example.SomeJavaClass<@[FlexibleNullability] A of example.SomeJavaClass?>? [operator] declared in example.SomeJavaClass' type=@[FlexibleNullability] example.SomeJavaClass<out @[FlexibleNullability] kotlin.String?>? origin=null
$this: GET_VAR 'var a: example.SomeJavaClass<out kotlin.String> [var] declared in <root>.test' type=example.SomeJavaClass<out kotlin.String> origin=null
hello: TYPE_OP type=@[FlexibleNullability] example.Hello<@[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] example.Hello<@[FlexibleNullability] kotlin.String?>?
hello: TYPE_OP type=@[FlexibleNullability] example.Hello<out @[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] example.Hello<out @[FlexibleNullability] kotlin.String?>?
FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.String?, kotlin.Unit> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (it:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Unit
VALUE_PARAMETER name:it index:0 type:@[FlexibleNullability] kotlin.String?
@@ -45,7 +45,7 @@ FILE fqName:<root> fileName:/genericSamProjectedOut.kt
CALL 'public open fun set (i: kotlin.Int, hello: @[FlexibleNullability] example.Hello<@[FlexibleNullability] A of example.SomeJavaClass?>?): kotlin.Unit [operator] declared in example.SomeJavaClass' type=kotlin.Unit origin=null
$this: GET_VAR 'var a: example.SomeJavaClass<out kotlin.String> [var] declared in <root>.test' type=example.SomeJavaClass<out kotlin.String> origin=null
i: CONST Int type=kotlin.Int value=0
hello: TYPE_OP type=@[FlexibleNullability] example.Hello<@[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] example.Hello<@[FlexibleNullability] kotlin.String?>?
hello: TYPE_OP type=@[FlexibleNullability] example.Hello<out @[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] example.Hello<out @[FlexibleNullability] kotlin.String?>?
FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.String?, kotlin.Unit> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (it:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Unit
VALUE_PARAMETER name:it index:0 type:@[FlexibleNullability] kotlin.String?
@@ -3,21 +3,21 @@ fun test() {
a.someFunction(hello = local fun <anonymous>(it: @FlexibleNullability String?) {
return Unit
}
/*-> @FlexibleNullability Hello<@FlexibleNullability String?>? */)
/*-> @FlexibleNullability Hello<out @FlexibleNullability String?>? */)
a.plus(hello = local fun <anonymous>(it: @FlexibleNullability String?) {
return Unit
}
/*-> @FlexibleNullability Hello<@FlexibleNullability String?>? */) /*~> Unit */
/*-> @FlexibleNullability Hello<out @FlexibleNullability String?>? */) /*~> Unit */
a.get(hello = local fun <anonymous>(it: @FlexibleNullability String?) {
return Unit
}
/*-> @FlexibleNullability Hello<@FlexibleNullability String?>? */)
/*-> @FlexibleNullability Hello<out @FlexibleNullability String?>? */)
a = a.plus(hello = local fun <anonymous>(it: @FlexibleNullability String?) {
return Unit
}
/*-> @FlexibleNullability Hello<@FlexibleNullability String?>? */)
/*-> @FlexibleNullability Hello<out @FlexibleNullability String?>? */)
a.set(i = 0, hello = local fun <anonymous>(it: @FlexibleNullability String?) {
return Unit
}
/*-> @FlexibleNullability Hello<@FlexibleNullability String?>? */)
/*-> @FlexibleNullability Hello<out @FlexibleNullability String?>? */)
}
@@ -11,7 +11,7 @@ FILE fqName:<root> fileName:/genericSamSmartcast.kt
CALL 'public open fun call (block: @[FlexibleNullability] <root>.A.I<@[FlexibleNullability] T of <root>.A?>?): @[FlexibleNullability] kotlin.String? declared in <root>.A' type=@[FlexibleNullability] kotlin.String? origin=null
$this: TYPE_OP type=<root>.A<*> origin=IMPLICIT_CAST typeOperand=<root>.A<*>
GET_VAR 'x: kotlin.Any declared in <root>.f' type=kotlin.Any origin=null
block: TYPE_OP type=@[FlexibleNullability] <root>.A.I<@[FlexibleNullability] kotlin.Any?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] <root>.A.I<@[FlexibleNullability] kotlin.Any?>?
block: TYPE_OP type=@[FlexibleNullability] <root>.A.I<out @[FlexibleNullability] kotlin.Any?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] <root>.A.I<out @[FlexibleNullability] kotlin.Any?>?
FUN_EXPR type=kotlin.Function1<kotlin.Any?, @[FlexibleNullability] kotlin.String?> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (y:kotlin.Any?) returnType:@[FlexibleNullability] kotlin.String?
VALUE_PARAMETER name:y index:0 type:kotlin.Any?
@@ -3,8 +3,7 @@ fun f(x: Any): String {
x is A<*> -> return x /*as A<*> */.call(block = local fun <anonymous>(y: Any?): @FlexibleNullability String? {
return "OK"
}
/*-> @FlexibleNullability I<@FlexibleNullability Any?>? */) /*!! String */
/*-> @FlexibleNullability I<out @FlexibleNullability Any?>? */) /*!! String */
}
return "Fail"
}
+1 -1
View File
@@ -17,7 +17,7 @@ FILE fqName:<root> fileName:/test.kt
CALL 'public open fun computeIfAbsent (p0: @[EnhancedNullability] K of kotlin.collections.MutableMap, p1: @[EnhancedNullability] java.util.function.Function<in @[EnhancedNullability] K of kotlin.collections.MutableMap, out @[EnhancedNullability] V of kotlin.collections.MutableMap>): @[EnhancedNullability] V of kotlin.collections.MutableMap declared in kotlin.collections.MutableMap' type=@[EnhancedNullability] kotlin.String origin=null
$this: GET_VAR 'val map: kotlin.collections.MutableMap<<root>.Fun, kotlin.String> [val] declared in <root>.box' type=kotlin.collections.MutableMap<<root>.Fun, kotlin.String> origin=null
p0: GET_VAR 'val fn: <root>.Fun [val] declared in <root>.box' type=<root>.Fun origin=null
p1: TYPE_OP type=@[EnhancedNullability] java.util.function.Function<@[EnhancedNullability] <root>.Fun, @[EnhancedNullability] kotlin.String> origin=SAM_CONVERSION typeOperand=@[EnhancedNullability] java.util.function.Function<@[EnhancedNullability] <root>.Fun, @[EnhancedNullability] kotlin.String>
p1: TYPE_OP type=@[EnhancedNullability] java.util.function.Function<kotlin.Any?, @[EnhancedNullability] kotlin.String> origin=SAM_CONVERSION typeOperand=@[EnhancedNullability] java.util.function.Function<kotlin.Any?, @[EnhancedNullability] kotlin.String>
FUN_EXPR type=kotlin.Function1<@[EnhancedNullability] <root>.Fun, @[EnhancedNullability] kotlin.String> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (it:@[EnhancedNullability] <root>.Fun) returnType:@[EnhancedNullability] kotlin.String
VALUE_PARAMETER name:it index:0 type:@[EnhancedNullability] <root>.Fun
+1 -2
View File
@@ -7,6 +7,5 @@ fun box(): String {
return map.computeIfAbsent(p0 = fn, p1 = local fun <anonymous>(it: @EnhancedNullability Fun): @EnhancedNullability String {
return "OK"
}
/*-> @EnhancedNullability Function<@EnhancedNullability Fun, @EnhancedNullability String> */) /*!! String */
/*-> @EnhancedNullability Function<Any?, @EnhancedNullability String> */) /*!! String */
}
@@ -196,7 +196,7 @@ FILE fqName:<root> fileName:/intersectionTypeInSamType.kt
<class: T>: <root>.B
CALL 'public final fun checkFoo (x: <root>.IFoo<in T of <root>.G1>): kotlin.Unit declared in <root>.G1' type=kotlin.Unit origin=null
$this: GET_VAR 'val g: <root>.G1<*> [val] declared in <root>.test1' type=<root>.G1<*> origin=null
x: TYPE_OP type=<root>.IFoo<kotlin.Nothing> origin=SAM_CONVERSION typeOperand=<root>.IFoo<kotlin.Nothing>
x: TYPE_OP type=<root>.IFoo<in kotlin.Nothing> origin=SAM_CONVERSION typeOperand=<root>.IFoo<in kotlin.Nothing>
FUN_EXPR type=kotlin.Function1<kotlin.Nothing, kotlin.Unit> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (it:<root>.X) returnType:kotlin.Unit
VALUE_PARAMETER name:it index:0 type:<root>.X
@@ -214,7 +214,7 @@ FILE fqName:<root> fileName:/intersectionTypeInSamType.kt
<class: T>: <root>.B
CALL 'public final fun checkFoo (x: <root>.IFoo<in T of <root>.G2>): kotlin.Unit declared in <root>.G2' type=kotlin.Unit origin=null
$this: GET_VAR 'val g: <root>.G2<*> [val] declared in <root>.test2' type=<root>.G2<*> origin=null
x: TYPE_OP type=<root>.IFoo<kotlin.Nothing> origin=SAM_CONVERSION typeOperand=<root>.IFoo<kotlin.Nothing>
x: TYPE_OP type=<root>.IFoo<in kotlin.Nothing> origin=SAM_CONVERSION typeOperand=<root>.IFoo<in kotlin.Nothing>
FUN_EXPR type=kotlin.Function1<kotlin.Nothing, kotlin.Unit> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (it:<root>.X) returnType:kotlin.Unit
VALUE_PARAMETER name:it index:0 type:<root>.X
@@ -223,7 +223,7 @@ FILE fqName:<root> fileName:/intersectionTypeInSamType.kt
GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
CALL 'public final fun checkBar1 (x: <root>.IBar1<in T of <root>.G2>): kotlin.Unit declared in <root>.G2' type=kotlin.Unit origin=null
$this: GET_VAR 'val g: <root>.G2<*> [val] declared in <root>.test2' type=<root>.G2<*> origin=null
x: TYPE_OP type=<root>.IBar1<kotlin.Nothing> origin=SAM_CONVERSION typeOperand=<root>.IBar1<kotlin.Nothing>
x: TYPE_OP type=<root>.IBar1<in kotlin.Nothing> origin=SAM_CONVERSION typeOperand=<root>.IBar1<in kotlin.Nothing>
FUN_EXPR type=kotlin.Function1<kotlin.Nothing, kotlin.Unit> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (it:<root>.X) returnType:kotlin.Unit
VALUE_PARAMETER name:it index:0 type:<root>.X
@@ -232,7 +232,7 @@ FILE fqName:<root> fileName:/intersectionTypeInSamType.kt
GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
CALL 'public final fun checkBar2 (x: <root>.IBar2<in T of <root>.G2>): kotlin.Unit declared in <root>.G2' type=kotlin.Unit origin=null
$this: GET_VAR 'val g: <root>.G2<*> [val] declared in <root>.test2' type=<root>.G2<*> origin=null
x: TYPE_OP type=<root>.IBar2<kotlin.Nothing> origin=SAM_CONVERSION typeOperand=<root>.IBar2<kotlin.Nothing>
x: TYPE_OP type=<root>.IBar2<in kotlin.Nothing> origin=SAM_CONVERSION typeOperand=<root>.IBar2<in kotlin.Nothing>
FUN_EXPR type=kotlin.Function1<kotlin.Nothing, kotlin.Unit> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (it:<root>.X) returnType:kotlin.Unit
VALUE_PARAMETER name:it index:0 type:<root>.X
@@ -26324,6 +26324,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/invokedynamic/sam/simpleIndySam.kt");
}
@Test
@TestMetadata("starProjectionSam.kt")
public void testStarProjectionSam() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/starProjectionSam.kt");
}
@Test
@TestMetadata("streamApi1.kt")
public void testStreamApi1() throws Exception {
@@ -27416,6 +27416,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/invokedynamic/sam/simpleIndySam.kt");
}
@Test
@TestMetadata("starProjectionSam.kt")
public void testStarProjectionSam() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/starProjectionSam.kt");
}
@Test
@TestMetadata("streamApi1.kt")
public void testStreamApi1() throws Exception {
@@ -22167,6 +22167,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/invokedynamic/sam/simpleIndySam.kt");
}
@TestMetadata("starProjectionSam.kt")
public void testStarProjectionSam() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/starProjectionSam.kt");
}
@TestMetadata("streamApi1.kt")
public void testStreamApi1() throws Exception {
runTest("compiler/testData/codegen/box/invokedynamic/sam/streamApi1.kt");