Skip to content

Commit d44d8ea

Browse files
committed
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 (cherry picked from commit bc7aea1)
1 parent ebdbaab commit d44d8ea

7 files changed

Lines changed: 125 additions & 14 deletions

File tree

compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegationResolver.kt

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,11 @@ class DelegationResolver<T : CallableMemberDescriptor> private constructor(
151151
// descriptor = Foo
152152
// toInterface = Bar
153153
// delegateExpressionType = typeof(baz)
154-
// return Map<member of Foo, corresponding member of typeOf(baz)>
154+
//
155+
// This method returns a map where keys are members of Foo, and values are members of typeof(baz).
156+
//
157+
// In case delegation is to an error type, which is useful for KAPT stub generation mode, typeof(baz) has no members, so we return
158+
// a map from each element to it (so keys = values in the returned map).
155159
fun getDelegates(
156160
descriptor: ClassDescriptor,
157161
toInterface: ClassDescriptor,
@@ -175,18 +179,22 @@ class DelegationResolver<T : CallableMemberDescriptor> private constructor(
175179
val actualDelegates = DescriptorUtils.getAllOverriddenDescriptors(delegatingMember)
176180
.filter { it.containingDeclaration == toInterface }
177181
.map { overriddenDescriptor ->
178-
val name = overriddenDescriptor.name
179-
// this is the actual member of delegateExpressionType that we are delegating to
180-
(scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_OVERRIDES) +
181-
scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_OVERRIDES))
182-
.firstOrNull {
183-
it == overriddenDescriptor || OverridingUtil.overrides(
184-
it,
185-
overriddenDescriptor,
186-
it.module.isTypeRefinementEnabled(),
187-
true
188-
)
189-
}
182+
if (scopeType.isError) {
183+
overriddenDescriptor
184+
} else {
185+
val name = overriddenDescriptor.name
186+
// This is the actual member of delegateExpressionType that we are delegating to.
187+
(scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_OVERRIDES) +
188+
scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_OVERRIDES))
189+
.firstOrNull {
190+
it == overriddenDescriptor || OverridingUtil.overrides(
191+
it,
192+
overriddenDescriptor,
193+
it.module.isTypeRefinementEnabled(),
194+
true
195+
)
196+
}
197+
}
190198
}
191199

192200
actualDelegates.firstOrNull()

compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,9 @@ class ClassGenerator(
325325
// TODO could possibly refer to scoped type parameters for property accessors
326326
irFunction.returnType = delegatedDescriptor.returnType!!.toIrType()
327327

328-
irFunction.body = generateDelegateFunctionBody(irDelegate, delegatedDescriptor, delegateToDescriptor, irFunction)
328+
if (context.configuration.generateBodies) {
329+
irFunction.body = generateDelegateFunctionBody(irDelegate, delegatedDescriptor, delegateToDescriptor, irFunction)
330+
}
329331
}
330332

331333
private fun generateDelegateFunctionBody(
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// CORRECT_ERROR_TYPES
2+
3+
@Suppress("UNRESOLVED_REFERENCE")
4+
interface A {
5+
fun inject(b: B)
6+
val x: String
7+
8+
companion object : B()
9+
10+
abstract class B : A by Unresolved
11+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
@kotlin.Metadata()
2+
@kotlin.Suppress(names = {"UNRESOLVED_REFERENCE"})
3+
public abstract interface A {
4+
@org.jetbrains.annotations.NotNull()
5+
public static final A.Companion Companion = null;
6+
7+
public abstract void inject(@org.jetbrains.annotations.NotNull()
8+
A.B b);
9+
10+
@org.jetbrains.annotations.NotNull()
11+
public abstract java.lang.String getX();
12+
13+
@kotlin.Metadata()
14+
public static abstract class B implements A {
15+
16+
@java.lang.Override()
17+
public void inject(@org.jetbrains.annotations.NotNull()
18+
A.B b) {
19+
}
20+
21+
@java.lang.Override()
22+
@org.jetbrains.annotations.NotNull()
23+
public java.lang.String getX() {
24+
return null;
25+
}
26+
27+
public B() {
28+
super();
29+
}
30+
}
31+
32+
@kotlin.Metadata()
33+
public static final class Companion extends A.B {
34+
35+
private Companion() {
36+
super();
37+
}
38+
}
39+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
@kotlin.Metadata()
2+
@kotlin.Suppress(names = {"UNRESOLVED_REFERENCE"})
3+
public abstract interface A {
4+
@org.jetbrains.annotations.NotNull()
5+
public static final A.Companion Companion = null;
6+
7+
public abstract void inject(@org.jetbrains.annotations.NotNull()
8+
A.B b);
9+
10+
@org.jetbrains.annotations.NotNull()
11+
public abstract java.lang.String getX();
12+
13+
@kotlin.Metadata()
14+
public static abstract class B implements A {
15+
16+
public B() {
17+
super();
18+
}
19+
20+
@java.lang.Override()
21+
@org.jetbrains.annotations.NotNull()
22+
public java.lang.String getX() {
23+
return null;
24+
}
25+
26+
@java.lang.Override()
27+
public void inject(@org.jetbrains.annotations.NotNull()
28+
A.B b) {
29+
}
30+
}
31+
32+
@kotlin.Metadata()
33+
public static final class Companion extends A.B {
34+
35+
private Companion() {
36+
super();
37+
}
38+
}
39+
}

plugins/kapt3/kapt3-compiler/tests-gen/org/jetbrains/kotlin/kapt3/test/runners/ClassFileToSourceStubConverterTestGenerated.java

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/kapt3/kapt3-compiler/tests-gen/org/jetbrains/kotlin/kapt3/test/runners/IrClassFileToSourceStubConverterTestGenerated.java

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)