IR: deal with conflicting variances in computeSubstitutedSyntheticAccessor
This commit is contained in:
Generated
+5
@@ -14387,6 +14387,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
public void testJavaNestedSamInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/generics/javaNestedSamInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyVarianceConflict.kt")
|
||||
public void testPropertyVarianceConflict() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/generics/propertyVarianceConflict.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/javaInterop/notNullAssertions")
|
||||
|
||||
+6
-2
@@ -330,9 +330,13 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
|
||||
ktExpression.startOffsetSkippingComments, ktExpression.endOffset, origin,
|
||||
propertyIrType,
|
||||
getterSymbol,
|
||||
getterDescriptor?.let { computeSubstitutedSyntheticAccessor(unwrappedPropertyDescriptor, it) },
|
||||
getterDescriptor?.let {
|
||||
computeSubstitutedSyntheticAccessor(unwrappedPropertyDescriptor, it, unwrappedPropertyDescriptor.getter!!)
|
||||
},
|
||||
setterSymbol,
|
||||
setterDescriptor?.let { computeSubstitutedSyntheticAccessor(unwrappedPropertyDescriptor, it) },
|
||||
setterDescriptor?.let {
|
||||
computeSubstitutedSyntheticAccessor(unwrappedPropertyDescriptor, it, unwrappedPropertyDescriptor.setter!!)
|
||||
},
|
||||
typeArgumentsList,
|
||||
propertyReceiver,
|
||||
superQualifierSymbol
|
||||
|
||||
@@ -211,7 +211,9 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
IrStatementOrigin.GET_PROPERTY,
|
||||
superQualifierSymbol
|
||||
).apply {
|
||||
context.callToSubstitutedDescriptorMap[this] = computeSubstitutedSyntheticAccessor(descriptor, getMethodDescriptor)
|
||||
context.callToSubstitutedDescriptorMap[this] = computeSubstitutedSyntheticAccessor(
|
||||
descriptor, getMethodDescriptor, descriptor.getter!!
|
||||
)
|
||||
putTypeArguments(call.typeArguments) { it.toIrType() }
|
||||
dispatchReceiver = dispatchReceiverValue?.load()
|
||||
extensionReceiver = extensionReceiverValue?.load()
|
||||
|
||||
@@ -17,12 +17,10 @@
|
||||
package org.jetbrains.kotlin.psi2ir.intermediate
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.typeParametersCount
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
|
||||
fun IrVariable.defaultLoad(): IrExpression =
|
||||
IrGetValueImpl(startOffset, endOffset, type, symbol)
|
||||
@@ -53,7 +51,11 @@ fun CallReceiver.adjustForCallee(callee: CallableMemberDescriptor): CallReceiver
|
||||
}
|
||||
|
||||
|
||||
fun computeSubstitutedSyntheticAccessor(propertyDescriptor: PropertyDescriptor, accessorFunctionDescriptor: FunctionDescriptor): FunctionDescriptor {
|
||||
fun computeSubstitutedSyntheticAccessor(
|
||||
propertyDescriptor: PropertyDescriptor,
|
||||
accessorFunctionDescriptor: FunctionDescriptor,
|
||||
substitutedExtensionAccessorDescriptor: PropertyAccessorDescriptor
|
||||
): FunctionDescriptor {
|
||||
if (propertyDescriptor.original == propertyDescriptor) return accessorFunctionDescriptor
|
||||
|
||||
// Compute substituted accessor descriptor in case of Synthetic Java property `Java: getFoo() -> Kotlin: foo`
|
||||
@@ -65,38 +67,30 @@ fun computeSubstitutedSyntheticAccessor(propertyDescriptor: PropertyDescriptor,
|
||||
|
||||
if (accessorFunctionDescriptor !is SimpleFunctionDescriptor) return accessorFunctionDescriptor
|
||||
|
||||
/**
|
||||
* Consider java class like
|
||||
* O.java
|
||||
* class O<T1> {
|
||||
* class I<T2> {
|
||||
* public String getFoo() { ... }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* k.kt
|
||||
* fun f(i: O<String>.I<Int>) = i.foo
|
||||
*
|
||||
*
|
||||
* for that case front end creates synthetic property foo
|
||||
* private val <T1', T2'> O<T1'>.I<T2'>.foo get() = this.getFoo()
|
||||
*
|
||||
* So to get substituted descriptor for getFoo() we need to extract substitution from extension receiver type.
|
||||
* To do so map Tx parameters onto Tx' arguments like
|
||||
* T1' -> String
|
||||
* T2' -> Int
|
||||
* into
|
||||
* T1 -> String
|
||||
* T2 -> Int
|
||||
*/
|
||||
return copyTypesFromExtensionAccessor(accessorFunctionDescriptor, substitutedExtensionAccessorDescriptor)
|
||||
}
|
||||
|
||||
val classDescriptor = accessorFunctionDescriptor.containingDeclaration as ClassDescriptor
|
||||
val collectedTypeParameters = classDescriptor.typeConstructor.parameters.map { it.typeConstructor }
|
||||
assert(collectedTypeParameters.size == propertyDescriptor.typeParametersCount)
|
||||
|
||||
val typeArguments = propertyDescriptor.extensionReceiverParameter!!.type.arguments
|
||||
assert(typeArguments.size == collectedTypeParameters.size)
|
||||
|
||||
val typeSubstitutor = TypeSubstitutor.create(collectedTypeParameters.zip(typeArguments).toMap())
|
||||
return accessorFunctionDescriptor.substitute(typeSubstitutor) ?: error("Cannot substitute descriptor for $accessorFunctionDescriptor")
|
||||
}
|
||||
// When computing substituted descriptor for a synthetic accessor of a synthesized property,
|
||||
// the property descriptor's accessor field almost has the right type,
|
||||
// except with extension receiver instead of dispatch receiver. Need to patch it up.
|
||||
private fun copyTypesFromExtensionAccessor(
|
||||
accessorFunctionDescriptor: SimpleFunctionDescriptor,
|
||||
extensionAccessorDescriptor: PropertyAccessorDescriptor
|
||||
): FunctionDescriptor =
|
||||
SimpleFunctionDescriptorImpl.create(
|
||||
accessorFunctionDescriptor.containingDeclaration,
|
||||
accessorFunctionDescriptor.annotations,
|
||||
accessorFunctionDescriptor.name,
|
||||
accessorFunctionDescriptor.kind,
|
||||
accessorFunctionDescriptor.source
|
||||
).apply {
|
||||
initialize(
|
||||
null,
|
||||
extensionAccessorDescriptor.extensionReceiverParameter?.copy(this),
|
||||
emptyList(),
|
||||
extensionAccessorDescriptor.valueParameters.map { it.copy(this, it.name, it.index) },
|
||||
extensionAccessorDescriptor.returnType,
|
||||
accessorFunctionDescriptor.modality,
|
||||
accessorFunctionDescriptor.visibility
|
||||
)
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// FILE: C.java
|
||||
|
||||
class C<T> {
|
||||
public C<? super T> getXx() { return this; }
|
||||
}
|
||||
|
||||
// FILE: test.kt
|
||||
|
||||
fun test() {
|
||||
var c: C<out Any?> = C()
|
||||
c = c.xx
|
||||
}
|
||||
|
||||
fun box() = "OK"
|
||||
+5
@@ -15602,6 +15602,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
public void testJavaNestedSamInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/generics/javaNestedSamInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyVarianceConflict.kt")
|
||||
public void testPropertyVarianceConflict() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/generics/propertyVarianceConflict.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/javaInterop/notNullAssertions")
|
||||
|
||||
+5
@@ -15602,6 +15602,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
public void testJavaNestedSamInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/generics/javaNestedSamInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyVarianceConflict.kt")
|
||||
public void testPropertyVarianceConflict() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/generics/propertyVarianceConflict.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/javaInterop/notNullAssertions")
|
||||
|
||||
+5
@@ -14387,6 +14387,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
public void testJavaNestedSamInterface() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/generics/javaNestedSamInterface.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyVarianceConflict.kt")
|
||||
public void testPropertyVarianceConflict() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/javaInterop/generics/propertyVarianceConflict.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/javaInterop/notNullAssertions")
|
||||
|
||||
Reference in New Issue
Block a user