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 75c26fb8444..211c6b3f440 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 @@ -71,16 +71,32 @@ internal enum class ConversionTypeOrigin { class ConversionTypeContext internal constructor( internal val definitelyNotNull: Boolean, - internal val origin: ConversionTypeOrigin + internal val invariantProjection: Boolean = false, + internal val origin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT, ) { - fun definitelyNotNull() = ConversionTypeContext(true, origin) + fun definitelyNotNull() = ConversionTypeContext( + definitelyNotNull = true, + invariantProjection = invariantProjection, + origin = origin + ) - fun inSetter() = ConversionTypeContext(definitelyNotNull, ConversionTypeOrigin.SETTER) + fun inSetter() = ConversionTypeContext( + definitelyNotNull = definitelyNotNull, + invariantProjection = invariantProjection, + origin = ConversionTypeOrigin.SETTER + ) + + fun withInvariantProjections() = ConversionTypeContext( + definitelyNotNull = definitelyNotNull, + invariantProjection = true, + origin = origin + ) companion object { internal val DEFAULT = ConversionTypeContext( - definitelyNotNull = false, origin = ConversionTypeOrigin.DEFAULT + definitelyNotNull = false, origin = ConversionTypeOrigin.DEFAULT, invariantProjection = false ) + internal val WITH_INVARIANT = DEFAULT.withInvariantProjections() } } 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 18138333a5e..272b346a8cd 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 @@ -10,7 +10,6 @@ import org.jetbrains.kotlin.fir.expressions.classId import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.StandardClassIds -import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.* import org.jetbrains.kotlin.ir.expressions.IrConstructorCall @@ -20,7 +19,6 @@ import org.jetbrains.kotlin.ir.types.IrTypeArgument import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection -import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.types.Variance @@ -150,11 +148,11 @@ class Fir2IrTypeConverter( ConeStarProjection -> IrStarProjectionImpl is ConeKotlinTypeProjectionIn -> { val irType = this.type.toIrType(typeContext) - makeTypeProjection(irType, Variance.IN_VARIANCE) + makeTypeProjection(irType, if (typeContext.invariantProjection) Variance.INVARIANT else Variance.IN_VARIANCE) } is ConeKotlinTypeProjectionOut -> { val irType = this.type.toIrType(typeContext) - makeTypeProjection(irType, Variance.OUT_VARIANCE) + makeTypeProjection(irType, if (typeContext.invariantProjection) Variance.INVARIANT else Variance.OUT_VARIANCE) } is ConeKotlinType -> { if (this is ConeCapturedType && this in capturedTypeCache && this.isRecursive(mutableSetOf())) { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index 50463b06569..cb37d83c8bd 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -52,7 +52,8 @@ class CallAndReferenceGenerator( private val adapterGenerator = AdapterGenerator(components, conversionScope) private val samResolver = FirSamResolverImpl(session, scopeSession) - private fun FirTypeRef.toIrType(): IrType = with(typeConverter) { toIrType() } + private fun FirTypeRef.toIrType(conversionTypeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT): IrType = + with(typeConverter) { toIrType(conversionTypeContext) } private fun ConeKotlinType.toIrType(): IrType = with(typeConverter) { toIrType() } @@ -608,7 +609,7 @@ class CallAndReferenceGenerator( if (!needSamConversion(argument, parameter)) { return this } - var samType = parameter.returnTypeRef.toIrType() + var samType = parameter.returnTypeRef.toIrType(ConversionTypeContext.WITH_INVARIANT) if (shouldUnwrapVarargType) { samType = samType.getArrayElementType(irBuiltIns) } diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java index 6c0c63e55c0..ce07fa4515b 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/ir/Fir2IrTextTestGenerated.java @@ -2152,6 +2152,12 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest { runTest("compiler/testData/ir/irText/firProblems/JCTree.kt"); } + @Test + @TestMetadata("kt19251.kt") + public void testKt19251() throws Exception { + runTest("compiler/testData/ir/irText/firProblems/kt19251.kt"); + } + @Test @TestMetadata("kt43342.kt") public void testKt43342() throws Exception { diff --git a/compiler/testData/codegen/box/invokedynamic/sam/streamApi1.kt b/compiler/testData/codegen/box/invokedynamic/sam/streamApi1.kt index 29d4105043f..8e2807d3f4f 100644 --- a/compiler/testData/codegen/box/invokedynamic/sam/streamApi1.kt +++ b/compiler/testData/codegen/box/invokedynamic/sam/streamApi1.kt @@ -1,5 +1,4 @@ // TARGET_BACKEND: JVM -// IGNORE_BACKEND_FIR: JVM_IR // JVM_TARGET: 1.8 // SAM_CONVERSIONS: INDY // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/invokedynamic/sam/streamApi2.kt b/compiler/testData/codegen/box/invokedynamic/sam/streamApi2.kt index acf3669d37f..5746bfd079b 100644 --- a/compiler/testData/codegen/box/invokedynamic/sam/streamApi2.kt +++ b/compiler/testData/codegen/box/invokedynamic/sam/streamApi2.kt @@ -1,5 +1,4 @@ // TARGET_BACKEND: JVM -// IGNORE_BACKEND_FIR: JVM_IR // JVM_TARGET: 1.8 // SAM_CONVERSIONS: INDY // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/sam/kt11519.kt b/compiler/testData/codegen/box/sam/kt11519.kt index 6555291dbbf..d99b46ff331 100644 --- a/compiler/testData/codegen/box/sam/kt11519.kt +++ b/compiler/testData/codegen/box/sam/kt11519.kt @@ -1,5 +1,4 @@ // DONT_TARGET_EXACT_BACKEND: JS JS_IR JS_IR_ES6 WASM NATIVE -// IGNORE_BACKEND_FIR: JVM_IR // SKIP_JDK6 // MODULE: lib // FILE: Custom.java diff --git a/compiler/testData/codegen/bytecodeText/invokedynamic/streamApi.kt b/compiler/testData/codegen/bytecodeText/invokedynamic/streamApi.kt index 52f0ae1029c..99dad35114a 100644 --- a/compiler/testData/codegen/bytecodeText/invokedynamic/streamApi.kt +++ b/compiler/testData/codegen/bytecodeText/invokedynamic/streamApi.kt @@ -1,5 +1,4 @@ // TARGET_BACKEND: JVM -// IGNORE_BACKEND_FIR: JVM_IR // JVM_TARGET: 1.8 // SAM_CONVERSIONS: INDY // WITH_RUNTIME diff --git a/compiler/testData/ir/irText/firProblems/kt19251.fir.kt.txt b/compiler/testData/ir/irText/firProblems/kt19251.fir.kt.txt new file mode 100644 index 00000000000..f2ec41e978f --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/kt19251.fir.kt.txt @@ -0,0 +1,11 @@ +fun box(): String { + val map: MutableMap = mutableMapOf() + val fn: Fun = local fun (it: String?): String? { + return TODO() + } + /*-> Fun */ + return map.computeIfAbsent(p0 = fn, p1 = local fun (it: Fun?): String? { + return "OK" + } + /*-> @FlexibleNullability Function */) +} diff --git a/compiler/testData/ir/irText/firProblems/kt19251.fir.txt b/compiler/testData/ir/irText/firProblems/kt19251.fir.txt new file mode 100644 index 00000000000..c3a84e3562b --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/kt19251.fir.txt @@ -0,0 +1,26 @@ +FILE fqName: fileName:/test.kt + FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String + BLOCK_BODY + VAR name:map type:kotlin.collections.MutableMap<.Fun, kotlin.String> [val] + CALL 'public final fun mutableMapOf (): kotlin.collections.MutableMap [inline] declared in kotlin.collections.MapsKt' type=kotlin.collections.MutableMap<.Fun, kotlin.String> origin=null + : .Fun + : kotlin.String + VAR name:fn type:.Fun [val] + TYPE_OP type=.Fun origin=SAM_CONVERSION typeOperand=.Fun + FUN_EXPR type=kotlin.Function1 origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:kotlin.String?) returnType:kotlin.String? + VALUE_PARAMETER name:it index:0 type:kotlin.String? + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (it: kotlin.String?): kotlin.String? declared in .box' + CALL 'public final fun TODO (): kotlin.Nothing [inline] declared in kotlin.StandardKt' type=kotlin.Nothing origin=null + RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in ' + CALL 'public open fun computeIfAbsent (p0: K of kotlin.collections.MutableMap, p1: @[FlexibleNullability] java.util.function.Function): V of kotlin.collections.MutableMap declared in kotlin.collections.MutableMap' type=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=@[FlexibleNullability] java.util.function.Function<.Fun?, kotlin.String?> origin=SAM_CONVERSION typeOperand=@[FlexibleNullability] java.util.function.Function<.Fun?, kotlin.String?> + FUN_EXPR type=kotlin.Function1<.Fun?, kotlin.String?> origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:.Fun?) returnType:kotlin.String? + VALUE_PARAMETER name:it index:0 type:.Fun? + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (it: .Fun?): kotlin.String? declared in .box' + CONST String type=kotlin.String value="OK" diff --git a/compiler/testData/ir/irText/firProblems/kt19251.kt b/compiler/testData/ir/irText/firProblems/kt19251.kt new file mode 100644 index 00000000000..5ab0fdecbd2 --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/kt19251.kt @@ -0,0 +1,14 @@ +// WITH_RUNTIME +// FULL_JDK +// FILE: Fun.java +public interface Fun { + String invoke(String string); +} + +// FILE: test.kt +fun box(): String { + val map = mutableMapOf() + val fn = Fun { TODO() } + return map.computeIfAbsent(fn, { "OK" }) +} + diff --git a/compiler/testData/ir/irText/firProblems/kt19251.kt.txt b/compiler/testData/ir/irText/firProblems/kt19251.kt.txt new file mode 100644 index 00000000000..504268b1f0d --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/kt19251.kt.txt @@ -0,0 +1,11 @@ +fun box(): String { + val map: MutableMap = mutableMapOf() + val fn: Fun = local fun (it: @FlexibleNullability String?): @FlexibleNullability String? { + TODO() + } + /*-> Fun */ + return map.computeIfAbsent(p0 = fn, p1 = local fun (it: @EnhancedNullability Fun): @EnhancedNullability String { + return "OK" + } + /*-> @EnhancedNullability Function<@EnhancedNullability Fun, @EnhancedNullability String> */) /*!! String */ +} diff --git a/compiler/testData/ir/irText/firProblems/kt19251.txt b/compiler/testData/ir/irText/firProblems/kt19251.txt new file mode 100644 index 00000000000..9cc7b4ca1c7 --- /dev/null +++ b/compiler/testData/ir/irText/firProblems/kt19251.txt @@ -0,0 +1,26 @@ +FILE fqName: fileName:/test.kt + FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String + BLOCK_BODY + VAR name:map type:kotlin.collections.MutableMap<.Fun, kotlin.String> [val] + CALL 'public final fun mutableMapOf (): kotlin.collections.MutableMap [inline] declared in kotlin.collections.MapsKt' type=kotlin.collections.MutableMap<.Fun, kotlin.String> origin=null + : .Fun + : kotlin.String + VAR name:fn type:.Fun [val] + TYPE_OP type=.Fun origin=SAM_CONVERSION typeOperand=.Fun + FUN_EXPR type=kotlin.Function1<@[ParameterName(name = 'string')] @[FlexibleNullability] kotlin.String?, @[FlexibleNullability] kotlin.String?> origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> (it:@[FlexibleNullability] kotlin.String?) returnType:@[FlexibleNullability] kotlin.String? + VALUE_PARAMETER name:it index:0 type:@[FlexibleNullability] kotlin.String? + BLOCK_BODY + CALL 'public final fun TODO (): kotlin.Nothing [inline] declared in kotlin.StandardKt' type=kotlin.Nothing origin=null + RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in ' + TYPE_OP type=kotlin.String origin=IMPLICIT_NOTNULL typeOperand=kotlin.String + 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> + 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 + BLOCK_BODY + RETURN type=kotlin.Nothing from='local final fun (it: @[EnhancedNullability] .Fun): @[EnhancedNullability] kotlin.String declared in .box' + CONST String type=kotlin.String value="OK" diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java index b7324e8531e..ceff6e39e78 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/ir/IrTextTestGenerated.java @@ -2152,6 +2152,12 @@ public class IrTextTestGenerated extends AbstractIrTextTest { runTest("compiler/testData/ir/irText/firProblems/JCTree.kt"); } + @Test + @TestMetadata("kt19251.kt") + public void testKt19251() throws Exception { + runTest("compiler/testData/ir/irText/firProblems/kt19251.kt"); + } + @Test @TestMetadata("kt43342.kt") public void testKt43342() throws Exception {