Kapt+JVM_IR: generate delegated members correctly
Generate a declaration for each delegated member without body. If we don't generate delegated declarations, subclasses will have incorrect IR with unbound symbols in fake overrides. #KT-58027 Fixed
This commit is contained in:
committed by
Space Team
parent
5407ac1c72
commit
bc7aea1426
@@ -151,7 +151,11 @@ class DelegationResolver<T : CallableMemberDescriptor> private constructor(
|
|||||||
// descriptor = Foo
|
// descriptor = Foo
|
||||||
// toInterface = Bar
|
// toInterface = Bar
|
||||||
// delegateExpressionType = typeof(baz)
|
// delegateExpressionType = typeof(baz)
|
||||||
// return Map<member of Foo, corresponding member of typeOf(baz)>
|
//
|
||||||
|
// This method returns a map where keys are members of Foo, and values are members of typeof(baz).
|
||||||
|
//
|
||||||
|
// In case delegation is to an error type, which is useful for KAPT stub generation mode, typeof(baz) has no members, so we return
|
||||||
|
// a map from each element to it (so keys = values in the returned map).
|
||||||
fun getDelegates(
|
fun getDelegates(
|
||||||
descriptor: ClassDescriptor,
|
descriptor: ClassDescriptor,
|
||||||
toInterface: ClassDescriptor,
|
toInterface: ClassDescriptor,
|
||||||
@@ -175,18 +179,22 @@ class DelegationResolver<T : CallableMemberDescriptor> private constructor(
|
|||||||
val actualDelegates = DescriptorUtils.getAllOverriddenDescriptors(delegatingMember)
|
val actualDelegates = DescriptorUtils.getAllOverriddenDescriptors(delegatingMember)
|
||||||
.filter { it.containingDeclaration == toInterface }
|
.filter { it.containingDeclaration == toInterface }
|
||||||
.map { overriddenDescriptor ->
|
.map { overriddenDescriptor ->
|
||||||
val name = overriddenDescriptor.name
|
if (scopeType.isError) {
|
||||||
// this is the actual member of delegateExpressionType that we are delegating to
|
overriddenDescriptor
|
||||||
(scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_OVERRIDES) +
|
} else {
|
||||||
scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_OVERRIDES))
|
val name = overriddenDescriptor.name
|
||||||
.firstOrNull {
|
// This is the actual member of delegateExpressionType that we are delegating to.
|
||||||
it == overriddenDescriptor || OverridingUtil.overrides(
|
(scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_OVERRIDES) +
|
||||||
it,
|
scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_OVERRIDES))
|
||||||
overriddenDescriptor,
|
.firstOrNull {
|
||||||
it.module.isTypeRefinementEnabled(),
|
it == overriddenDescriptor || OverridingUtil.overrides(
|
||||||
true
|
it,
|
||||||
)
|
overriddenDescriptor,
|
||||||
}
|
it.module.isTypeRefinementEnabled(),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actualDelegates.firstOrNull()
|
actualDelegates.firstOrNull()
|
||||||
|
|||||||
@@ -324,7 +324,9 @@ internal class ClassGenerator(
|
|||||||
// TODO could possibly refer to scoped type parameters for property accessors
|
// TODO could possibly refer to scoped type parameters for property accessors
|
||||||
irFunction.returnType = delegatedDescriptor.returnType!!.toIrType()
|
irFunction.returnType = delegatedDescriptor.returnType!!.toIrType()
|
||||||
|
|
||||||
irFunction.body = generateDelegateFunctionBody(irDelegate, delegatedDescriptor, delegateToDescriptor, irFunction)
|
if (context.configuration.generateBodies) {
|
||||||
|
irFunction.body = generateDelegateFunctionBody(irDelegate, delegatedDescriptor, delegateToDescriptor, irFunction)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateDelegateFunctionBody(
|
private fun generateDelegateFunctionBody(
|
||||||
|
|||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
@kotlin.Metadata()
|
||||||
|
@kotlin.Suppress(names = {"UNRESOLVED_REFERENCE"})
|
||||||
|
public abstract interface A {
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public static final A.Companion Companion = null;
|
||||||
|
|
||||||
|
public abstract void inject(@org.jetbrains.annotations.NotNull()
|
||||||
|
A.B b);
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public abstract java.lang.String getX();
|
||||||
|
|
||||||
|
@kotlin.Metadata()
|
||||||
|
public static abstract class B implements A {
|
||||||
|
|
||||||
|
public B() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override()
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public java.lang.String getX() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override()
|
||||||
|
public void inject(@org.jetbrains.annotations.NotNull()
|
||||||
|
A.B b) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata()
|
||||||
|
public static final class Companion extends A.B {
|
||||||
|
|
||||||
|
private Companion() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// CORRECT_ERROR_TYPES
|
||||||
|
|
||||||
|
@Suppress("UNRESOLVED_REFERENCE")
|
||||||
|
interface A {
|
||||||
|
fun inject(b: B)
|
||||||
|
val x: String
|
||||||
|
|
||||||
|
companion object : B()
|
||||||
|
|
||||||
|
abstract class B : A by Unresolved
|
||||||
|
}
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
@kotlin.Metadata()
|
||||||
|
@kotlin.Suppress(names = {"UNRESOLVED_REFERENCE"})
|
||||||
|
public abstract interface A {
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public static final A.Companion Companion = null;
|
||||||
|
|
||||||
|
public abstract void inject(@org.jetbrains.annotations.NotNull()
|
||||||
|
A.B b);
|
||||||
|
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public abstract java.lang.String getX();
|
||||||
|
|
||||||
|
@kotlin.Metadata()
|
||||||
|
public static abstract class B implements A {
|
||||||
|
|
||||||
|
@java.lang.Override()
|
||||||
|
public void inject(@org.jetbrains.annotations.NotNull()
|
||||||
|
A.B b) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override()
|
||||||
|
@org.jetbrains.annotations.NotNull()
|
||||||
|
public java.lang.String getX() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public B() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata()
|
||||||
|
public static final class Companion extends A.B {
|
||||||
|
|
||||||
|
private Companion() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -157,6 +157,12 @@ public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFi
|
|||||||
runTest("plugins/kapt3/kapt3-compiler/testData/converter/delegatedProperties.kt");
|
runTest("plugins/kapt3/kapt3-compiler/testData/converter/delegatedProperties.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("delegationAndCompanionObject.kt")
|
||||||
|
public void testDelegationAndCompanionObject() throws Exception {
|
||||||
|
runTest("plugins/kapt3/kapt3-compiler/testData/converter/delegationAndCompanionObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("deprecated.kt")
|
@TestMetadata("deprecated.kt")
|
||||||
public void testDeprecated() throws Exception {
|
public void testDeprecated() throws Exception {
|
||||||
|
|||||||
+6
@@ -157,6 +157,12 @@ public class IrClassFileToSourceStubConverterTestGenerated extends AbstractIrCla
|
|||||||
runTest("plugins/kapt3/kapt3-compiler/testData/converter/delegatedProperties.kt");
|
runTest("plugins/kapt3/kapt3-compiler/testData/converter/delegatedProperties.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("delegationAndCompanionObject.kt")
|
||||||
|
public void testDelegationAndCompanionObject() throws Exception {
|
||||||
|
runTest("plugins/kapt3/kapt3-compiler/testData/converter/delegationAndCompanionObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("deprecated.kt")
|
@TestMetadata("deprecated.kt")
|
||||||
public void testDeprecated() throws Exception {
|
public void testDeprecated() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user