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 {
|
public void testJavaNestedSamInterface() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/javaInterop/generics/javaNestedSamInterface.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/javaInterop/notNullAssertions")
|
||||||
|
|||||||
+6
-2
@@ -330,9 +330,13 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
|
|||||||
ktExpression.startOffsetSkippingComments, ktExpression.endOffset, origin,
|
ktExpression.startOffsetSkippingComments, ktExpression.endOffset, origin,
|
||||||
propertyIrType,
|
propertyIrType,
|
||||||
getterSymbol,
|
getterSymbol,
|
||||||
getterDescriptor?.let { computeSubstitutedSyntheticAccessor(unwrappedPropertyDescriptor, it) },
|
getterDescriptor?.let {
|
||||||
|
computeSubstitutedSyntheticAccessor(unwrappedPropertyDescriptor, it, unwrappedPropertyDescriptor.getter!!)
|
||||||
|
},
|
||||||
setterSymbol,
|
setterSymbol,
|
||||||
setterDescriptor?.let { computeSubstitutedSyntheticAccessor(unwrappedPropertyDescriptor, it) },
|
setterDescriptor?.let {
|
||||||
|
computeSubstitutedSyntheticAccessor(unwrappedPropertyDescriptor, it, unwrappedPropertyDescriptor.setter!!)
|
||||||
|
},
|
||||||
typeArgumentsList,
|
typeArgumentsList,
|
||||||
propertyReceiver,
|
propertyReceiver,
|
||||||
superQualifierSymbol
|
superQualifierSymbol
|
||||||
|
|||||||
@@ -211,7 +211,9 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
IrStatementOrigin.GET_PROPERTY,
|
IrStatementOrigin.GET_PROPERTY,
|
||||||
superQualifierSymbol
|
superQualifierSymbol
|
||||||
).apply {
|
).apply {
|
||||||
context.callToSubstitutedDescriptorMap[this] = computeSubstitutedSyntheticAccessor(descriptor, getMethodDescriptor)
|
context.callToSubstitutedDescriptorMap[this] = computeSubstitutedSyntheticAccessor(
|
||||||
|
descriptor, getMethodDescriptor, descriptor.getter!!
|
||||||
|
)
|
||||||
putTypeArguments(call.typeArguments) { it.toIrType() }
|
putTypeArguments(call.typeArguments) { it.toIrType() }
|
||||||
dispatchReceiver = dispatchReceiverValue?.load()
|
dispatchReceiver = dispatchReceiverValue?.load()
|
||||||
extensionReceiver = extensionReceiverValue?.load()
|
extensionReceiver = extensionReceiverValue?.load()
|
||||||
|
|||||||
@@ -17,12 +17,10 @@
|
|||||||
package org.jetbrains.kotlin.psi2ir.intermediate
|
package org.jetbrains.kotlin.psi2ir.intermediate
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
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 =
|
fun IrVariable.defaultLoad(): IrExpression =
|
||||||
IrGetValueImpl(startOffset, endOffset, type, symbol)
|
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
|
if (propertyDescriptor.original == propertyDescriptor) return accessorFunctionDescriptor
|
||||||
|
|
||||||
// Compute substituted accessor descriptor in case of Synthetic Java property `Java: getFoo() -> Kotlin: foo`
|
// 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
|
if (accessorFunctionDescriptor !is SimpleFunctionDescriptor) return accessorFunctionDescriptor
|
||||||
|
|
||||||
/**
|
return copyTypesFromExtensionAccessor(accessorFunctionDescriptor, substitutedExtensionAccessorDescriptor)
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
val classDescriptor = accessorFunctionDescriptor.containingDeclaration as ClassDescriptor
|
// When computing substituted descriptor for a synthetic accessor of a synthesized property,
|
||||||
val collectedTypeParameters = classDescriptor.typeConstructor.parameters.map { it.typeConstructor }
|
// the property descriptor's accessor field almost has the right type,
|
||||||
assert(collectedTypeParameters.size == propertyDescriptor.typeParametersCount)
|
// except with extension receiver instead of dispatch receiver. Need to patch it up.
|
||||||
|
private fun copyTypesFromExtensionAccessor(
|
||||||
val typeArguments = propertyDescriptor.extensionReceiverParameter!!.type.arguments
|
accessorFunctionDescriptor: SimpleFunctionDescriptor,
|
||||||
assert(typeArguments.size == collectedTypeParameters.size)
|
extensionAccessorDescriptor: PropertyAccessorDescriptor
|
||||||
|
): FunctionDescriptor =
|
||||||
val typeSubstitutor = TypeSubstitutor.create(collectedTypeParameters.zip(typeArguments).toMap())
|
SimpleFunctionDescriptorImpl.create(
|
||||||
return accessorFunctionDescriptor.substitute(typeSubstitutor) ?: error("Cannot substitute descriptor for $accessorFunctionDescriptor")
|
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 {
|
public void testJavaNestedSamInterface() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/javaInterop/generics/javaNestedSamInterface.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/javaInterop/notNullAssertions")
|
||||||
|
|||||||
+5
@@ -15602,6 +15602,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
public void testJavaNestedSamInterface() throws Exception {
|
public void testJavaNestedSamInterface() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/javaInterop/generics/javaNestedSamInterface.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/javaInterop/notNullAssertions")
|
||||||
|
|||||||
+5
@@ -14387,6 +14387,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
public void testJavaNestedSamInterface() throws Exception {
|
public void testJavaNestedSamInterface() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/javaInterop/generics/javaNestedSamInterface.kt");
|
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")
|
@TestMetadata("compiler/testData/codegen/box/javaInterop/notNullAssertions")
|
||||||
|
|||||||
Reference in New Issue
Block a user