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:
committed by
Space Team
parent
45eefab811
commit
05ca001310
@@ -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) {
|
||||
|
||||
+73
-6
@@ -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
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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
|
||||
|
||||
-4
@@ -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
|
||||
|
||||
Vendored
-4
@@ -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
@@ -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"
|
||||
|
||||
+5
-5
@@ -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?
|
||||
|
||||
+5
-5
@@ -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"
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user