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

File tree

7 files changed

+125
-14
lines changed

7 files changed

+125
-14
lines changed

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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy