K2: fix enhancement building for Java methods with type parameters
Before this commit, we copied each type parameter during method enhancement, while not copying the symbol. This led to symbol clashes in MPP scenarios and various other problems. Now we create a fully-functional type parameter copy in enhancement and perform a substitution of old type parameters with new ones in receiver type, value parameter types, return type, and type parameter upper bounds. #KT-59766 Fixed #KT-59738 Fixed
This commit is contained in:
committed by
Space Team
parent
52068e11ee
commit
c350280e64
+6
@@ -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")
|
||||
|
||||
+6
@@ -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")
|
||||
|
||||
+39
-10
@@ -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<FirTypeParameterSymbol, ConeKotlinType>()
|
||||
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)
|
||||
|
||||
+42
@@ -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 <T> CompletionStage<T>.foo() {
|
||||
handle { value, exception ->
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// MODULE: jvm()()(lib-jvm)
|
||||
// FILE: jvm.kt
|
||||
|
||||
package kotlinx.coroutines.future
|
||||
|
||||
import java.util.concurrent.*
|
||||
import java.util.function.*
|
||||
|
||||
fun <T> CompletionStage<T>.asDeferred() {
|
||||
handle { value, exception ->
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class ContinuationHandler<T> : BiFunction<T?, Throwable?, Unit> {
|
||||
override fun apply(result: T?, exception: Throwable?) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val handler = ContinuationHandler<String>()
|
||||
CompletableFuture<String>().asDeferred()
|
||||
return "OK"
|
||||
}
|
||||
+6
@@ -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")
|
||||
|
||||
+6
@@ -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")
|
||||
|
||||
+5
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user