KT-13342 Unqualified super call should not resolve to a method of supertype overridden in another supertype
This commit is contained in:
+20
-8
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.KtSuperExpression
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
||||
|
||||
|
||||
@@ -121,25 +122,36 @@ private fun resolveSupertypesByPropertyName(supertypes: Collection<KotlinType>,
|
||||
|
||||
private inline fun resolveSupertypesByMembers(
|
||||
supertypes: Collection<KotlinType>,
|
||||
allowArbitraryMembers: Boolean,
|
||||
allowNonConcreteMembers: Boolean,
|
||||
getMembers: (KotlinType) -> Collection<MemberDescriptor>
|
||||
): Collection<KotlinType> {
|
||||
val typesWithConcreteMembers = SmartList<KotlinType>()
|
||||
val typesWithArbitraryMembers = SmartList<KotlinType>()
|
||||
val typesWithNonConcreteMembers = SmartList<KotlinType>()
|
||||
|
||||
for (supertype in supertypes) {
|
||||
val members = getMembers(supertype)
|
||||
if (members.isNotEmpty()) {
|
||||
typesWithArbitraryMembers.add(supertype)
|
||||
if (members.any { isConcreteMember(supertype, it) }) {
|
||||
if (members.any { isConcreteMember(supertype, it) })
|
||||
typesWithConcreteMembers.add(supertype)
|
||||
}
|
||||
else
|
||||
typesWithNonConcreteMembers.add(supertype)
|
||||
}
|
||||
}
|
||||
|
||||
return if (typesWithConcreteMembers.isNotEmpty()) typesWithConcreteMembers
|
||||
else if (allowArbitraryMembers) typesWithArbitraryMembers
|
||||
else emptyList<KotlinType>()
|
||||
typesWithConcreteMembers.removeAll { typeWithConcreteMember ->
|
||||
typesWithNonConcreteMembers.any { typeWithNonConcreteMember ->
|
||||
KotlinTypeChecker.DEFAULT.isSubtypeOf(typeWithNonConcreteMember, typeWithConcreteMember)
|
||||
}
|
||||
}
|
||||
|
||||
return when {
|
||||
typesWithConcreteMembers.isNotEmpty() ->
|
||||
typesWithConcreteMembers
|
||||
allowNonConcreteMembers ->
|
||||
typesWithNonConcreteMembers
|
||||
else ->
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFunctionMembers(type: KotlinType, name: Name, location: LookupLocation): Collection<MemberDescriptor> =
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
interface A {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
abstract class C : A {
|
||||
override abstract fun foo()
|
||||
}
|
||||
|
||||
interface Unrelated {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
class Test1 : C(), A {
|
||||
override fun foo() {
|
||||
// Abstract 'foo' defined in 'C' wins against non-abstract 'foo' defined in 'A',
|
||||
// because 'C' is a subclass of 'A' (and 'C::foo' overrides 'A::foo'),
|
||||
// even though 'A' is explicitly listed in supertypes list for 'D'.
|
||||
super.<!ABSTRACT_SUPER_CALL!>foo<!>()
|
||||
}
|
||||
}
|
||||
|
||||
class Test2 : C(), A, Unrelated {
|
||||
override fun foo() {
|
||||
// This is ok, because there's a non-abstract 'foo' in 'Unrelated',
|
||||
// which is not overridden by abstract 'foo' in 'C'.
|
||||
super.foo()
|
||||
super<Unrelated>.foo()
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package
|
||||
|
||||
public interface A {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public abstract class C : A {
|
||||
public constructor C()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract override /*1*/ fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class Test1 : C, A {
|
||||
public constructor Test1()
|
||||
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*2*/ fun foo(): kotlin.Unit
|
||||
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class Test2 : C, A, Unrelated {
|
||||
public constructor Test2()
|
||||
public open override /*3*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*3*/ fun foo(): kotlin.Unit
|
||||
public open override /*3*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*3*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface Unrelated {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -21783,6 +21783,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("withMethodOverriddenInAnotherSupertype.kt")
|
||||
public void testWithMethodOverriddenInAnotherSupertype() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/thisAndSuper/unqualifiedSuper/withMethodOverriddenInAnotherSupertype.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("withMethodsOfAny.kt")
|
||||
public void testWithMethodsOfAny() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/thisAndSuper/unqualifiedSuper/withMethodsOfAny.kt");
|
||||
|
||||
Reference in New Issue
Block a user