diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index bd47112f62a..4902f0b4377 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -14588,6 +14588,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/javaInterop/protectedField.kt"); } + @TestMetadata("samTypeParameter.kt") + public void testSamTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/samTypeParameter.kt"); + } + @TestMetadata("samUnboundTypeParameter.kt") public void testSamUnboundTypeParameter() throws Exception { runTest("compiler/testData/codegen/box/javaInterop/samUnboundTypeParameter.kt"); diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt index 98445089a14..71238198674 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt @@ -620,14 +620,18 @@ fun StatementGenerator.generateSamConversionForValueArgumentsIfRequired(call: Ca for (i in underlyingValueParameters.indices) { val underlyingValueParameter = underlyingValueParameters[i] - val originalUnderlyingParameterType = underlyingValueParameter.original.type if (expectSamConvertedArgumentToBeAvailableInResolvedCall && resolvedCall is NewResolvedCallImpl<*>) { // TODO support SAM conversion of varargs val argument = resolvedCall.valueArguments[originalValueParameters[i]]?.arguments?.singleOrNull() ?: continue resolvedCall.getExpectedTypeForSamConvertedArgument(argument) ?: continue } else { - if (!context.extensions.samConversion.isSamType(originalUnderlyingParameterType)) continue + // When the method is `f(T)` with `T` = a SAM type, the substituted type is a SAM while the original is not; + // when the method is `f(X)` with `T` = `out V` where `X` is a SAM type, the substituted type is `Nothing` + // while the original is a SAM interface. Thus, if *either* of those is a SAM type then it's fine. + if (!samConversion.isSamType(underlyingValueParameter.type) && + !samConversion.isSamType(underlyingValueParameter.original.type) + ) continue if (!originalValueParameters[i].type.isFunctionTypeOrSubtype) continue } @@ -640,7 +644,7 @@ fun StatementGenerator.generateSamConversionForValueArgumentsIfRequired(call: Ca val substitutedSamType = typeSubstitutor.substitute(samKotlinType, Variance.INVARIANT) ?: throw AssertionError( "Failed to substitute value argument type in SAM conversion: " + - "underlyingParameterType=$originalUnderlyingParameterType, " + + "underlyingParameterType=${underlyingValueParameter.type}, " + "substitutionContext=$substitutionContext" ) diff --git a/compiler/testData/codegen/box/javaInterop/samTypeParameter.kt b/compiler/testData/codegen/box/javaInterop/samTypeParameter.kt new file mode 100644 index 00000000000..36a0116a509 --- /dev/null +++ b/compiler/testData/codegen/box/javaInterop/samTypeParameter.kt @@ -0,0 +1,18 @@ +// TODO: new inference doesn't do SAM conversion in this case. KT-37149 +// !LANGUAGE: -NewInference +// TARGET_BACKEND: JVM +// IGNORE_BACKEND_FIR: JVM_IR +// FILE: Generic.java +class Generic { + T id(T x) { return x; } +} + +// FILE: Specialized.java +class Specialized extends Generic {} + +// FILE: use.kt +fun box(): String { + var result = "fail" + Specialized().id { result = "OK" }.run() + return result +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index f7d83dda611..d1faece6135 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -15803,6 +15803,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/javaInterop/protectedField.kt"); } + @TestMetadata("samTypeParameter.kt") + public void testSamTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/samTypeParameter.kt"); + } + @TestMetadata("samUnboundTypeParameter.kt") public void testSamUnboundTypeParameter() throws Exception { runTest("compiler/testData/codegen/box/javaInterop/samUnboundTypeParameter.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 33058f4ae0b..e99154a61b9 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -15803,6 +15803,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/javaInterop/protectedField.kt"); } + @TestMetadata("samTypeParameter.kt") + public void testSamTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/samTypeParameter.kt"); + } + @TestMetadata("samUnboundTypeParameter.kt") public void testSamUnboundTypeParameter() throws Exception { runTest("compiler/testData/codegen/box/javaInterop/samUnboundTypeParameter.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index f82df0f2044..d096009b640 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -14588,6 +14588,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/javaInterop/protectedField.kt"); } + @TestMetadata("samTypeParameter.kt") + public void testSamTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/samTypeParameter.kt"); + } + @TestMetadata("samUnboundTypeParameter.kt") public void testSamUnboundTypeParameter() throws Exception { runTest("compiler/testData/codegen/box/javaInterop/samUnboundTypeParameter.kt");