diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java index 7188a4d43bc..6e2fd6e1ff1 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java @@ -33460,6 +33460,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr runTest("compiler/testData/codegen/box/multiplatform/k2/anonymousObjectAndSpecificImplementationInDeserializedIr.kt"); } + @Test + @TestMetadata("javaMethodWithTypeParameter.kt") + public void testJavaMethodWithTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/multiplatform/k2/javaMethodWithTypeParameter.kt"); + } + @Nested @TestMetadata("compiler/testData/codegen/box/multiplatform/k2/annotations") @TestDataPath("$PROJECT_ROOT") 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 4798ae416a2..291f885c584 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 @@ -33460,6 +33460,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo runTest("compiler/testData/codegen/box/multiplatform/k2/anonymousObjectAndSpecificImplementationInDeserializedIr.kt"); } + @Test + @TestMetadata("javaMethodWithTypeParameter.kt") + public void testJavaMethodWithTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/multiplatform/k2/javaMethodWithTypeParameter.kt"); + } + @Nested @TestMetadata("compiler/testData/codegen/box/multiplatform/k2/annotations") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt index b18fde82208..204c0845991 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.fir.java.resolveIfJavaType import org.jetbrains.kotlin.fir.java.symbols.FirJavaOverriddenSyntheticPropertySymbol import org.jetbrains.kotlin.fir.java.toConeKotlinTypeProbablyFlexible import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider +import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptor import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag @@ -251,6 +252,9 @@ class FirSignatureEnhancement( val functionSymbol: FirFunctionSymbol<*> var isJavaRecordComponent = false + val typeParameterSubstitutionMap = mutableMapOf() + var typeParameterSubstitutor: ConeSubstitutorByMap? = null + val function = when (firMethod) { is FirJavaConstructor -> { val symbol = FirConstructorSymbol(methodId).also { functionSymbol = it } @@ -288,6 +292,7 @@ class FirSignatureEnhancement( moduleData = this@FirSignatureEnhancement.moduleData resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES origin = FirDeclarationOrigin.Enhancement + // TODO: we should set a new origin / containing declaration to type parameters (KT-60440) this.typeParameters += (enhancedTypeParameters ?: firMethod.typeParameters) } } @@ -297,14 +302,6 @@ class FirSignatureEnhancement( source = firMethod.source moduleData = this@FirSignatureEnhancement.moduleData origin = FirDeclarationOrigin.Enhancement - returnTypeRef = newReturnTypeRef - receiverParameter = newReceiverTypeRef?.let { receiverType -> - buildReceiverParameter { - typeRef = receiverType - annotations += firMethod.valueParameters.first().annotations - source = receiverType.source?.fakeElement(KtFakeSourceElementKind.ReceiverFromType) - } - } this.name = name!! status = firMethod.status @@ -316,10 +313,39 @@ class FirSignatureEnhancement( "Unexpected type parameter type: ${typeParameter::class.simpleName}" } - buildTypeParameterCopy(typeParameter) { + // TODO: we probably shouldn't build a copy second time. See performFirstRoundOfBoundsResolution (KT-60446) + val newTypeParameter = buildTypeParameterCopy(typeParameter) { origin = FirDeclarationOrigin.Enhancement + symbol = FirTypeParameterSymbol() containingDeclarationSymbol = functionSymbol } + typeParameterSubstitutionMap[typeParameter.symbol] = ConeTypeParameterTypeImpl( + newTypeParameter.symbol.toLookupTag(), isNullable = false + ) + newTypeParameter + } + if (typeParameterSubstitutionMap.isNotEmpty()) { + typeParameterSubstitutor = ConeSubstitutorByMap(typeParameterSubstitutionMap, session) + } + returnTypeRef = newReturnTypeRef.withReplacedConeType( + typeParameterSubstitutor?.substituteOrNull(newReturnTypeRef.coneType) + ) + val substitutedReceiverTypeRef = newReceiverTypeRef?.withReplacedConeType( + typeParameterSubstitutor?.substituteOrNull(newReturnTypeRef.coneType) + ) + receiverParameter = substitutedReceiverTypeRef?.let { receiverType -> + buildReceiverParameter { + typeRef = receiverType + annotations += firMethod.valueParameters.first().annotations + source = receiverType.source?.fakeElement(KtFakeSourceElementKind.ReceiverFromType) + } + } + typeParameters.forEach { typeParameter -> + typeParameter.replaceBounds( + typeParameter.bounds.map { boundTypeRef -> + boundTypeRef.withReplacedConeType(typeParameterSubstitutor?.substituteOrNull(boundTypeRef.coneType)) + } + ) } dispatchReceiverType = firMethod.dispatchReceiverType @@ -336,7 +362,9 @@ class FirSignatureEnhancement( containingFunctionSymbol = functionSymbol moduleData = this@FirSignatureEnhancement.moduleData origin = FirDeclarationOrigin.Enhancement - returnTypeRef = enhancedReturnType + returnTypeRef = enhancedReturnType.withReplacedConeType( + typeParameterSubstitutor?.substituteOrNull(enhancedReturnType.coneType) + ) this.name = valueParameter.name symbol = FirValueParameterSymbol(this.name) defaultValue = valueParameter.defaultValue @@ -388,6 +416,7 @@ class FirSignatureEnhancement( typeParametersCopy += if (typeParameter is FirTypeParameter) { initialBounds.add(typeParameter.bounds.toList()) buildTypeParameterCopy(typeParameter) { + // TODO: we should create a new symbol to avoid clashing (KT-60445) bounds.clear() typeParameter.bounds.mapTo(bounds) { it.resolveIfJavaType(session, javaTypeParameterStack, FirJavaTypeConversionMode.TYPE_PARAMETER_BOUND_FIRST_ROUND) diff --git a/compiler/testData/codegen/box/multiplatform/k2/javaMethodWithTypeParameter.kt b/compiler/testData/codegen/box/multiplatform/k2/javaMethodWithTypeParameter.kt new file mode 100644 index 00000000000..cf5a09eff40 --- /dev/null +++ b/compiler/testData/codegen/box/multiplatform/k2/javaMethodWithTypeParameter.kt @@ -0,0 +1,42 @@ +// LANGUAGE: +MultiPlatformProjects +// ISSUE: KT-59766 +// WITH_STDLIB +// TARGET_BACKEND: JVM_IR +// FULL_JDK + +// MODULE: lib-jvm +// FILE: lib.kt + +import java.util.concurrent.* + +fun CompletionStage.foo() { + handle { value, exception -> + + } +} + +// MODULE: jvm()()(lib-jvm) +// FILE: jvm.kt + +package kotlinx.coroutines.future + +import java.util.concurrent.* +import java.util.function.* + +fun CompletionStage.asDeferred() { + handle { value, exception -> + + } +} + +class ContinuationHandler : BiFunction { + override fun apply(result: T?, exception: Throwable?) { + + } +} + +fun box(): String { + val handler = ContinuationHandler() + CompletableFuture().asDeferred() + return "OK" +} 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 c5b0df402e9..41d94fa8e39 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 @@ -33460,6 +33460,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/multiplatform/k2/anonymousObjectAndSpecificImplementationInDeserializedIr.kt"); } + @Test + @TestMetadata("javaMethodWithTypeParameter.kt") + public void testJavaMethodWithTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/multiplatform/k2/javaMethodWithTypeParameter.kt"); + } + @Nested @TestMetadata("compiler/testData/codegen/box/multiplatform/k2/annotations") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java index b34747b2a51..f5bbe68d5f4 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java @@ -33460,6 +33460,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack runTest("compiler/testData/codegen/box/multiplatform/k2/anonymousObjectAndSpecificImplementationInDeserializedIr.kt"); } + @Test + @TestMetadata("javaMethodWithTypeParameter.kt") + public void testJavaMethodWithTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/multiplatform/k2/javaMethodWithTypeParameter.kt"); + } + @Nested @TestMetadata("compiler/testData/codegen/box/multiplatform/k2/annotations") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 299f260f981..dbeb7b8fbde 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -28487,6 +28487,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/multiplatform/k2/anonymousObjectAndSpecificImplementationInDeserializedIr.kt"); } + @TestMetadata("javaMethodWithTypeParameter.kt") + public void testJavaMethodWithTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/multiplatform/k2/javaMethodWithTypeParameter.kt"); + } + @TestMetadata("compiler/testData/codegen/box/multiplatform/k2/annotations") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)