Skip to content

Commit 9a2c9ed

Browse files
committed
KT-13342 Unqualified super call should not resolve to a method of supertype overridden in another supertype
1 parent 954c1d8 commit 9a2c9ed

File tree

4 files changed

+94
-8
lines changed

4 files changed

+94
-8
lines changed

compiler/frontend/src/org/jetbrains/kotlin/types/expressions/unqualifiedSuper/unqualifiedSuper.kt

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression
3131
import org.jetbrains.kotlin.psi.KtSuperExpression
3232
import org.jetbrains.kotlin.types.KotlinType
3333
import org.jetbrains.kotlin.types.TypeUtils
34+
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
3435
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
3536

3637

@@ -121,25 +122,36 @@ private fun resolveSupertypesByPropertyName(supertypes: Collection<KotlinType>,
121122

122123
private inline fun resolveSupertypesByMembers(
123124
supertypes: Collection<KotlinType>,
124-
allowArbitraryMembers: Boolean,
125+
allowNonConcreteMembers: Boolean,
125126
getMembers: (KotlinType) -> Collection<MemberDescriptor>
126127
): Collection<KotlinType> {
127128
val typesWithConcreteMembers = SmartList<KotlinType>()
128-
val typesWithArbitraryMembers = SmartList<KotlinType>()
129+
val typesWithNonConcreteMembers = SmartList<KotlinType>()
129130

130131
for (supertype in supertypes) {
131132
val members = getMembers(supertype)
132133
if (members.isNotEmpty()) {
133-
typesWithArbitraryMembers.add(supertype)
134-
if (members.any { isConcreteMember(supertype, it) }) {
134+
if (members.any { isConcreteMember(supertype, it) })
135135
typesWithConcreteMembers.add(supertype)
136-
}
136+
else
137+
typesWithNonConcreteMembers.add(supertype)
137138
}
138139
}
139140

140-
return if (typesWithConcreteMembers.isNotEmpty()) typesWithConcreteMembers
141-
else if (allowArbitraryMembers) typesWithArbitraryMembers
142-
else emptyList<KotlinType>()
141+
typesWithConcreteMembers.removeAll { typeWithConcreteMember ->
142+
typesWithNonConcreteMembers.any { typeWithNonConcreteMember ->
143+
KotlinTypeChecker.DEFAULT.isSubtypeOf(typeWithNonConcreteMember, typeWithConcreteMember)
144+
}
145+
}
146+
147+
return when {
148+
typesWithConcreteMembers.isNotEmpty() ->
149+
typesWithConcreteMembers
150+
allowNonConcreteMembers ->
151+
typesWithNonConcreteMembers
152+
else ->
153+
emptyList()
154+
}
143155
}
144156

145157
private fun getFunctionMembers(type: KotlinType, name: Name, location: LookupLocation): Collection<MemberDescriptor> =
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
interface A {
2+
fun foo() {}
3+
}
4+
5+
abstract class C : A {
6+
override abstract fun foo()
7+
}
8+
9+
interface Unrelated {
10+
fun foo() {}
11+
}
12+
13+
class Test1 : C(), A {
14+
override fun foo() {
15+
// Abstract 'foo' defined in 'C' wins against non-abstract 'foo' defined in 'A',
16+
// because 'C' is a subclass of 'A' (and 'C::foo' overrides 'A::foo'),
17+
// even though 'A' is explicitly listed in supertypes list for 'D'.
18+
super.<!ABSTRACT_SUPER_CALL!>foo<!>()
19+
}
20+
}
21+
22+
class Test2 : C(), A, Unrelated {
23+
override fun foo() {
24+
// This is ok, because there's a non-abstract 'foo' in 'Unrelated',
25+
// which is not overridden by abstract 'foo' in 'C'.
26+
super.foo()
27+
super<Unrelated>.foo()
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package
2+
3+
public interface A {
4+
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
5+
public open fun foo(): kotlin.Unit
6+
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
7+
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
8+
}
9+
10+
public abstract class C : A {
11+
public constructor C()
12+
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
13+
public abstract override /*1*/ fun foo(): kotlin.Unit
14+
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
15+
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
16+
}
17+
18+
public final class Test1 : C, A {
19+
public constructor Test1()
20+
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
21+
public open override /*2*/ fun foo(): kotlin.Unit
22+
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
23+
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
24+
}
25+
26+
public final class Test2 : C, A, Unrelated {
27+
public constructor Test2()
28+
public open override /*3*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
29+
public open override /*3*/ fun foo(): kotlin.Unit
30+
public open override /*3*/ /*fake_override*/ fun hashCode(): kotlin.Int
31+
public open override /*3*/ /*fake_override*/ fun toString(): kotlin.String
32+
}
33+
34+
public interface Unrelated {
35+
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
36+
public open fun foo(): kotlin.Unit
37+
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
38+
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
39+
}

compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21783,6 +21783,12 @@ public void testWithMethodOfAnyOverridenInInterface() throws Exception {
2178321783
doTest(fileName);
2178421784
}
2178521785

21786+
@TestMetadata("withMethodOverriddenInAnotherSupertype.kt")
21787+
public void testWithMethodOverriddenInAnotherSupertype() throws Exception {
21788+
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/thisAndSuper/unqualifiedSuper/withMethodOverriddenInAnotherSupertype.kt");
21789+
doTest(fileName);
21790+
}
21791+
2178621792
@TestMetadata("withMethodsOfAny.kt")
2178721793
public void testWithMethodsOfAny() throws Exception {
2178821794
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/thisAndSuper/unqualifiedSuper/withMethodsOfAny.kt");

0 commit comments

Comments
 (0)