From 05ca0013109de845a846e94afdd1b374fbfea05e Mon Sep 17 00:00:00 2001 From: "Denis.Zharkov" Date: Wed, 15 Feb 2023 11:54:17 +0100 Subject: [PATCH] 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 --- .../kotlin/backend/common/SamTypeFactory.kt | 2 + .../kotlin/fir/backend/ConversionUtils.kt | 16 +--- .../kotlin/fir/backend/Fir2IrTypeConverter.kt | 2 +- .../backend/generators/AdapterGenerator.kt | 79 +++++++++++++++++-- .../FirBlackBoxCodegenTestGenerated.java | 6 ++ .../FirPsiBlackBoxCodegenTestGenerated.java | 6 ++ .../kotlin/fir/types/ConeTypeContext.kt | 2 +- .../box/callableReference/kt49526_sam.kt | 2 - .../sam/kt51868_contravariantGenericSam.kt | 4 - .../genericWithInProjection.kt | 4 - .../invokedynamic/sam/starProjectionSam.kt | 28 +++++++ .../codegen/box/sam/kt54600.fir.ir.txt | 5 +- .../sam/genericSamProjectedOut.fir.ir.txt | 10 +-- .../sam/genericSamProjectedOut.fir.kt.txt | 10 +-- .../sam/genericSamSmartcast.fir.ir.txt | 2 +- .../sam/genericSamSmartcast.fir.kt.txt | 3 +- .../ir/irText/firProblems/kt19251.fir.ir.txt | 2 +- .../ir/irText/firProblems/kt19251.fir.kt.txt | 3 +- .../intersectionTypeInSamType.fir.ir.txt | 8 +- .../codegen/BlackBoxCodegenTestGenerated.java | 6 ++ .../IrBlackBoxCodegenTestGenerated.java | 6 ++ .../LightAnalysisModeTestGenerated.java | 5 ++ 22 files changed, 158 insertions(+), 53 deletions(-) create mode 100644 compiler/testData/codegen/box/invokedynamic/sam/starProjectionSam.kt diff --git a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/SamTypeFactory.kt b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/SamTypeFactory.kt index a0b53c18758..431d23be724 100644 --- a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/SamTypeFactory.kt +++ b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/SamTypeFactory.kt @@ -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) { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt index 31e8c1e6e28..b0c15479ee4 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt @@ -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 ) } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt index 102e69d7d27..6fdfc32d871 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt @@ -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) { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt index 71bd09b6764..bc88167f326 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/AdapterGenerator.kt @@ -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` and a method that takes e.g. `A`, 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` becomes `A`, 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 + + 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): 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 diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 08d1384f5ed..054084f2b3a 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -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 { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java index 1796d71d821..8d18a7d8d7d 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java @@ -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 { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt index b6ffdd456a2..bfe9b060e0d 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt @@ -268,7 +268,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty } } - override fun TypeConstructorMarker.getParameters(): List { + override fun TypeConstructorMarker.getParameters(): List { return when (val symbol = toClassLikeSymbol()) { is FirAnonymousObjectSymbol -> symbol.fir.typeParameters.map { it.symbol.toLookupTag() } is FirRegularClassSymbol -> symbol.fir.typeParameters.map { it.symbol.toLookupTag() } diff --git a/compiler/testData/codegen/box/callableReference/kt49526_sam.kt b/compiler/testData/codegen/box/callableReference/kt49526_sam.kt index b76b1ed3b31..d453ee6ef1f 100644 --- a/compiler/testData/codegen/box/callableReference/kt49526_sam.kt +++ b/compiler/testData/codegen/box/callableReference/kt49526_sam.kt @@ -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', which has a projected top-level argument. fun intersect(x: T, y: T): T = x diff --git a/compiler/testData/codegen/box/invokedynamic/sam/kt51868_contravariantGenericSam.kt b/compiler/testData/codegen/box/invokedynamic/sam/kt51868_contravariantGenericSam.kt index 5d969dcc4d5..3132c9d7ef3 100644 --- a/compiler/testData/codegen/box/invokedynamic/sam/kt51868_contravariantGenericSam.kt +++ b/compiler/testData/codegen/box/invokedynamic/sam/kt51868_contravariantGenericSam.kt @@ -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 diff --git a/compiler/testData/codegen/box/invokedynamic/sam/specializedGenerics/genericWithInProjection.kt b/compiler/testData/codegen/box/invokedynamic/sam/specializedGenerics/genericWithInProjection.kt index e82aabe940d..46c2519981c 100644 --- a/compiler/testData/codegen/box/invokedynamic/sam/specializedGenerics/genericWithInProjection.kt +++ b/compiler/testData/codegen/box/invokedynamic/sam/specializedGenerics/genericWithInProjection.kt @@ -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 diff --git a/compiler/testData/codegen/box/invokedynamic/sam/starProjectionSam.kt b/compiler/testData/codegen/box/invokedynamic/sam/starProjectionSam.kt new file mode 100644 index 00000000000..11c0ae9d372 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/starProjectionSam.kt @@ -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, T2 extends CharSequence, R> { + R bar(T1 t1, T2 t2); +} diff --git a/compiler/testData/codegen/box/sam/kt54600.fir.ir.txt b/compiler/testData/codegen/box/sam/kt54600.fir.ir.txt index d01302d38b1..7c7e525986b 100644 --- a/compiler/testData/codegen/box/sam/kt54600.fir.ir.txt +++ b/compiler/testData/codegen/box/sam/kt54600.fir.ir.txt @@ -9,7 +9,8 @@ FILE fqName: fileName:/box.kt BLOCK_BODY TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit CONSTRUCTOR_CALL 'public constructor (filter: @[FlexibleNullability] .Condition?) declared in .J' type=.J origin=null - filter: TYPE_OP type=@[FlexibleNullability] .Condition<@[FlexibleNullability] kotlin.String?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] .Condition<@[FlexibleNullability] kotlin.String?>? - GET_VAR 'filter: kotlin.Function1? declared in .foo' type=kotlin.Function1? origin=null + filter: TYPE_OP type=@[FlexibleNullability] .Condition? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] .Condition? + 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? declared in .foo' type=kotlin.Function1? origin=null RETURN type=kotlin.Nothing from='public final fun foo (filter: kotlin.Function1?): kotlin.String declared in ' CONST String type=kotlin.String value="OK" diff --git a/compiler/testData/ir/irText/expressions/sam/genericSamProjectedOut.fir.ir.txt b/compiler/testData/ir/irText/expressions/sam/genericSamProjectedOut.fir.ir.txt index 493b97a26cb..7afdd789f2a 100644 --- a/compiler/testData/ir/irText/expressions/sam/genericSamProjectedOut.fir.ir.txt +++ b/compiler/testData/ir/irText/expressions/sam/genericSamProjectedOut.fir.ir.txt @@ -6,7 +6,7 @@ FILE fqName: fileName:/genericSamProjectedOut.kt : 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 [var] declared in .test' type=example.SomeJavaClass 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? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] example.Hello? FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.String?, kotlin.Unit> origin=LAMBDA FUN LOCAL_FUNCTION_FOR_LAMBDA name: 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: 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? origin=PLUS $this: GET_VAR 'var a: example.SomeJavaClass [var] declared in .test' type=example.SomeJavaClass 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? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] example.Hello? FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.String?, kotlin.Unit> origin=LAMBDA FUN LOCAL_FUNCTION_FOR_LAMBDA name: 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: 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 [var] declared in .test' type=example.SomeJavaClass 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? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] example.Hello? FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.String?, kotlin.Unit> origin=LAMBDA FUN LOCAL_FUNCTION_FOR_LAMBDA name: 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: fileName:/genericSamProjectedOut.kt SET_VAR 'var a: example.SomeJavaClass [var] declared in .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? origin=null $this: GET_VAR 'var a: example.SomeJavaClass [var] declared in .test' type=example.SomeJavaClass 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? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] example.Hello? FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.String?, kotlin.Unit> origin=LAMBDA FUN LOCAL_FUNCTION_FOR_LAMBDA name: 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: 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 [var] declared in .test' type=example.SomeJavaClass 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? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] example.Hello? FUN_EXPR type=kotlin.Function1<@[FlexibleNullability] kotlin.String?, kotlin.Unit> origin=LAMBDA FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:@[FlexibleNullability] kotlin.String?) returnType:kotlin.Unit VALUE_PARAMETER name:it index:0 type:@[FlexibleNullability] kotlin.String? diff --git a/compiler/testData/ir/irText/expressions/sam/genericSamProjectedOut.fir.kt.txt b/compiler/testData/ir/irText/expressions/sam/genericSamProjectedOut.fir.kt.txt index a331e6ca50b..4f719196083 100644 --- a/compiler/testData/ir/irText/expressions/sam/genericSamProjectedOut.fir.kt.txt +++ b/compiler/testData/ir/irText/expressions/sam/genericSamProjectedOut.fir.kt.txt @@ -3,21 +3,21 @@ fun test() { a.someFunction(hello = local fun (it: @FlexibleNullability String?) { return Unit } - /*-> @FlexibleNullability Hello<@FlexibleNullability String?>? */) + /*-> @FlexibleNullability Hello? */) a.plus(hello = local fun (it: @FlexibleNullability String?) { return Unit } - /*-> @FlexibleNullability Hello<@FlexibleNullability String?>? */) /*~> Unit */ + /*-> @FlexibleNullability Hello? */) /*~> Unit */ a.get(hello = local fun (it: @FlexibleNullability String?) { return Unit } - /*-> @FlexibleNullability Hello<@FlexibleNullability String?>? */) + /*-> @FlexibleNullability Hello? */) a = a.plus(hello = local fun (it: @FlexibleNullability String?) { return Unit } - /*-> @FlexibleNullability Hello<@FlexibleNullability String?>? */) + /*-> @FlexibleNullability Hello? */) a.set(i = 0, hello = local fun (it: @FlexibleNullability String?) { return Unit } - /*-> @FlexibleNullability Hello<@FlexibleNullability String?>? */) + /*-> @FlexibleNullability Hello? */) } diff --git a/compiler/testData/ir/irText/expressions/sam/genericSamSmartcast.fir.ir.txt b/compiler/testData/ir/irText/expressions/sam/genericSamSmartcast.fir.ir.txt index a46a31f6bf2..684e953e1eb 100644 --- a/compiler/testData/ir/irText/expressions/sam/genericSamSmartcast.fir.ir.txt +++ b/compiler/testData/ir/irText/expressions/sam/genericSamSmartcast.fir.ir.txt @@ -11,7 +11,7 @@ FILE fqName: fileName:/genericSamSmartcast.kt CALL 'public open fun call (block: @[FlexibleNullability] .A.I<@[FlexibleNullability] T of .A?>?): @[FlexibleNullability] kotlin.String? declared in .A' type=@[FlexibleNullability] kotlin.String? origin=null $this: TYPE_OP type=.A<*> origin=IMPLICIT_CAST typeOperand=.A<*> GET_VAR 'x: kotlin.Any declared in .f' type=kotlin.Any origin=null - block: TYPE_OP type=@[FlexibleNullability] .A.I<@[FlexibleNullability] kotlin.Any?>? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] .A.I<@[FlexibleNullability] kotlin.Any?>? + block: TYPE_OP type=@[FlexibleNullability] .A.I? origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] .A.I? FUN_EXPR type=kotlin.Function1 origin=LAMBDA FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (y:kotlin.Any?) returnType:@[FlexibleNullability] kotlin.String? VALUE_PARAMETER name:y index:0 type:kotlin.Any? diff --git a/compiler/testData/ir/irText/expressions/sam/genericSamSmartcast.fir.kt.txt b/compiler/testData/ir/irText/expressions/sam/genericSamSmartcast.fir.kt.txt index a8e42e83cea..a944a16e833 100644 --- a/compiler/testData/ir/irText/expressions/sam/genericSamSmartcast.fir.kt.txt +++ b/compiler/testData/ir/irText/expressions/sam/genericSamSmartcast.fir.kt.txt @@ -3,8 +3,7 @@ fun f(x: Any): String { x is A<*> -> return x /*as A<*> */.call(block = local fun (y: Any?): @FlexibleNullability String? { return "OK" } - /*-> @FlexibleNullability I<@FlexibleNullability Any?>? */) /*!! String */ + /*-> @FlexibleNullability I? */) /*!! String */ } return "Fail" } - diff --git a/compiler/testData/ir/irText/firProblems/kt19251.fir.ir.txt b/compiler/testData/ir/irText/firProblems/kt19251.fir.ir.txt index f3619a4a4b1..707632c37af 100644 --- a/compiler/testData/ir/irText/firProblems/kt19251.fir.ir.txt +++ b/compiler/testData/ir/irText/firProblems/kt19251.fir.ir.txt @@ -17,7 +17,7 @@ FILE fqName: fileName:/test.kt CALL 'public open fun computeIfAbsent (p0: @[EnhancedNullability] K of kotlin.collections.MutableMap, p1: @[EnhancedNullability] java.util.function.Function): @[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<.Fun, kotlin.String> [val] declared in .box' type=kotlin.collections.MutableMap<.Fun, kotlin.String> origin=null p0: GET_VAR 'val fn: .Fun [val] declared in .box' type=.Fun origin=null - p1: TYPE_OP type=@[EnhancedNullability] java.util.function.Function<@[EnhancedNullability] .Fun, @[EnhancedNullability] kotlin.String> origin=SAM_CONVERSION typeOperand=@[EnhancedNullability] java.util.function.Function<@[EnhancedNullability] .Fun, @[EnhancedNullability] kotlin.String> + p1: TYPE_OP type=@[EnhancedNullability] java.util.function.Function origin=SAM_CONVERSION typeOperand=@[EnhancedNullability] java.util.function.Function FUN_EXPR type=kotlin.Function1<@[EnhancedNullability] .Fun, @[EnhancedNullability] kotlin.String> origin=LAMBDA FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:@[EnhancedNullability] .Fun) returnType:@[EnhancedNullability] kotlin.String VALUE_PARAMETER name:it index:0 type:@[EnhancedNullability] .Fun diff --git a/compiler/testData/ir/irText/firProblems/kt19251.fir.kt.txt b/compiler/testData/ir/irText/firProblems/kt19251.fir.kt.txt index 93dc7a21b1f..5425b0b218b 100644 --- a/compiler/testData/ir/irText/firProblems/kt19251.fir.kt.txt +++ b/compiler/testData/ir/irText/firProblems/kt19251.fir.kt.txt @@ -7,6 +7,5 @@ fun box(): String { return map.computeIfAbsent(p0 = fn, p1 = local fun (it: @EnhancedNullability Fun): @EnhancedNullability String { return "OK" } - /*-> @EnhancedNullability Function<@EnhancedNullability Fun, @EnhancedNullability String> */) /*!! String */ + /*-> @EnhancedNullability Function */) /*!! String */ } - diff --git a/compiler/testData/ir/irText/types/intersectionTypeInSamType.fir.ir.txt b/compiler/testData/ir/irText/types/intersectionTypeInSamType.fir.ir.txt index 6d684265ce9..2cb28c9c421 100644 --- a/compiler/testData/ir/irText/types/intersectionTypeInSamType.fir.ir.txt +++ b/compiler/testData/ir/irText/types/intersectionTypeInSamType.fir.ir.txt @@ -196,7 +196,7 @@ FILE fqName: fileName:/intersectionTypeInSamType.kt : .B CALL 'public final fun checkFoo (x: .IFoo.G1>): kotlin.Unit declared in .G1' type=kotlin.Unit origin=null $this: GET_VAR 'val g: .G1<*> [val] declared in .test1' type=.G1<*> origin=null - x: TYPE_OP type=.IFoo origin=SAM_CONVERSION typeOperand=.IFoo + x: TYPE_OP type=.IFoo origin=SAM_CONVERSION typeOperand=.IFoo FUN_EXPR type=kotlin.Function1 origin=LAMBDA FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:.X) returnType:kotlin.Unit VALUE_PARAMETER name:it index:0 type:.X @@ -214,7 +214,7 @@ FILE fqName: fileName:/intersectionTypeInSamType.kt : .B CALL 'public final fun checkFoo (x: .IFoo.G2>): kotlin.Unit declared in .G2' type=kotlin.Unit origin=null $this: GET_VAR 'val g: .G2<*> [val] declared in .test2' type=.G2<*> origin=null - x: TYPE_OP type=.IFoo origin=SAM_CONVERSION typeOperand=.IFoo + x: TYPE_OP type=.IFoo origin=SAM_CONVERSION typeOperand=.IFoo FUN_EXPR type=kotlin.Function1 origin=LAMBDA FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:.X) returnType:kotlin.Unit VALUE_PARAMETER name:it index:0 type:.X @@ -223,7 +223,7 @@ FILE fqName: 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: .IBar1.G2>): kotlin.Unit declared in .G2' type=kotlin.Unit origin=null $this: GET_VAR 'val g: .G2<*> [val] declared in .test2' type=.G2<*> origin=null - x: TYPE_OP type=.IBar1 origin=SAM_CONVERSION typeOperand=.IBar1 + x: TYPE_OP type=.IBar1 origin=SAM_CONVERSION typeOperand=.IBar1 FUN_EXPR type=kotlin.Function1 origin=LAMBDA FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:.X) returnType:kotlin.Unit VALUE_PARAMETER name:it index:0 type:.X @@ -232,7 +232,7 @@ FILE fqName: 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: .IBar2.G2>): kotlin.Unit declared in .G2' type=kotlin.Unit origin=null $this: GET_VAR 'val g: .G2<*> [val] declared in .test2' type=.G2<*> origin=null - x: TYPE_OP type=.IBar2 origin=SAM_CONVERSION typeOperand=.IBar2 + x: TYPE_OP type=.IBar2 origin=SAM_CONVERSION typeOperand=.IBar2 FUN_EXPR type=kotlin.Function1 origin=LAMBDA FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:.X) returnType:kotlin.Unit VALUE_PARAMETER name:it index:0 type:.X diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index b715c97a6bb..2f6758e126d 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -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 { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 670aff539ce..f7fdc9df68e 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -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 { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 7094a5fcbdc..95ccfe7a5dc 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -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");