FIR checker: report AMBIGUOUS_SUPER
This commit is contained in:
committed by
Ivan Kochurkin
parent
5b9ce7e823
commit
06ee84f809
@@ -15,7 +15,7 @@ open class B {
|
||||
override fun foo() {
|
||||
super.foo()
|
||||
|
||||
super.<!UNRESOLVED_REFERENCE!>bar<!>() // should be ambiguity (NB: really we should have overridden bar in C)
|
||||
<!AMBIGUOUS_SUPER!>super<!>.bar() // should be ambiguity (NB: really we should have overridden bar in C)
|
||||
|
||||
super.baz() // Ok
|
||||
baz() // Ok
|
||||
|
||||
+1
@@ -178,6 +178,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<FirRegularClassSymbol>("type")
|
||||
parameter<Collection<ConeKotlinType>>("bounds")
|
||||
}
|
||||
val AMBIGUOUS_SUPER by error<KtSuperExpression>()
|
||||
}
|
||||
|
||||
val CONSTRUCTOR_PROBLEMS by object : DiagnosticGroup("Constructor problems") {
|
||||
|
||||
@@ -71,6 +71,7 @@ import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.psi.KtPropertyAccessor
|
||||
import org.jetbrains.kotlin.psi.KtReturnExpression
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.KtSuperExpression
|
||||
import org.jetbrains.kotlin.psi.KtTypeAlias
|
||||
import org.jetbrains.kotlin.psi.KtTypeParameter
|
||||
import org.jetbrains.kotlin.psi.KtTypeProjection
|
||||
@@ -172,6 +173,7 @@ object FirErrors {
|
||||
val PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE by error0<KtModifierListOwner>(SourceElementPositioningStrategies.VARIANCE_MODIFIER)
|
||||
val INCONSISTENT_TYPE_PARAMETER_VALUES by error3<KtClass, FirTypeParameterSymbol, FirRegularClassSymbol, Collection<ConeKotlinType>>(SourceElementPositioningStrategies.SUPERTYPES_LIST)
|
||||
val INCONSISTENT_TYPE_PARAMETER_BOUNDS by error3<PsiElement, FirTypeParameterSymbol, FirRegularClassSymbol, Collection<ConeKotlinType>>()
|
||||
val AMBIGUOUS_SUPER by error0<KtSuperExpression>()
|
||||
|
||||
// Constructor problems
|
||||
val CONSTRUCTOR_IN_OBJECT by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
|
||||
+4
-1
@@ -79,7 +79,10 @@ class ErrorNodeDiagnosticCollectorComponent(
|
||||
private fun FirExpression?.cannotBeResolved(): Boolean {
|
||||
return when (val diagnostic = (this?.typeRef as? FirErrorTypeRef)?.diagnostic) {
|
||||
is ConeUnresolvedNameError, is ConeInstanceAccessBeforeSuperCall -> true
|
||||
is ConeSimpleDiagnostic -> diagnostic.kind == DiagnosticKind.NotASupertype || diagnostic.kind == DiagnosticKind.SuperNotAvailable || diagnostic.kind == DiagnosticKind.UnresolvedLabel
|
||||
is ConeSimpleDiagnostic -> diagnostic.kind == DiagnosticKind.NotASupertype ||
|
||||
diagnostic.kind == DiagnosticKind.SuperNotAvailable ||
|
||||
diagnostic.kind == DiagnosticKind.UnresolvedLabel ||
|
||||
diagnostic.kind == DiagnosticKind.AmbiguousSuper
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -51,6 +51,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_TYPE_ALIAS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_WITHOUT_EXPECT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_ACTUALS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_EXPECTS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUOUS_SUPER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_CLASS_CONSTRUCTOR_CALL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ANNOTATION_CLASS_MEMBER
|
||||
@@ -582,6 +583,7 @@ class FirDefaultErrorMessages {
|
||||
SYMBOL,
|
||||
RENDER_COLLECTION_OF_TYPES
|
||||
)
|
||||
map.put(AMBIGUOUS_SUPER, "Many supertypes available, please specify the one you mean in angle brackets, e.g. 'super<Foo>'")
|
||||
|
||||
// Constructor problems
|
||||
map.put(CONSTRUCTOR_IN_OBJECT, "Constructors are not allowed for objects")
|
||||
|
||||
+1
@@ -372,6 +372,7 @@ private fun ConeSimpleDiagnostic.getFactory(source: FirSourceElement): FirDiagno
|
||||
DiagnosticKind.EnumEntryAsType -> FirErrors.ENUM_ENTRY_AS_TYPE
|
||||
DiagnosticKind.NotASupertype -> FirErrors.NOT_A_SUPERTYPE
|
||||
DiagnosticKind.SuperNotAvailable -> FirErrors.SUPER_NOT_AVAILABLE
|
||||
DiagnosticKind.AmbiguousSuper -> FirErrors.AMBIGUOUS_SUPER
|
||||
DiagnosticKind.UnresolvedSupertype,
|
||||
DiagnosticKind.UnresolvedExpandedType,
|
||||
DiagnosticKind.Other -> FirErrors.OTHER_ERROR
|
||||
|
||||
+9
-7
@@ -236,17 +236,19 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
}
|
||||
else -> {
|
||||
val types = components.findTypesForSuperCandidates(superTypeRefs, containingCall)
|
||||
val resultType = if (types.size == 1) {
|
||||
// NB: NOT_A_SUPERTYPE is reported by a separate checker
|
||||
buildResolvedTypeRef {
|
||||
val resultType = when (types.size) {
|
||||
0 -> buildErrorTypeRef {
|
||||
source = superReferenceContainer.source
|
||||
// Report stub error so that it won't surface up. Instead, errors on the callee would be reported.
|
||||
diagnostic = ConeStubDiagnostic(ConeSimpleDiagnostic("Unresolved super method", DiagnosticKind.Other))
|
||||
}
|
||||
1 -> buildResolvedTypeRef {
|
||||
source = superReferenceContainer.source?.fakeElement(FirFakeSourceElementKind.SuperCallImplicitType)
|
||||
type = types.single()
|
||||
}
|
||||
} else {
|
||||
buildErrorTypeRef {
|
||||
else -> buildErrorTypeRef {
|
||||
source = superReferenceContainer.source
|
||||
// NB: NOT_A_SUPERTYPE is reported by a separate checker
|
||||
diagnostic = ConeStubDiagnostic(ConeSimpleDiagnostic("Ambiguous supertype", DiagnosticKind.Other))
|
||||
diagnostic = ConeSimpleDiagnostic("Ambiguous supertype", DiagnosticKind.AmbiguousSuper)
|
||||
}
|
||||
}
|
||||
superReferenceContainer.resultType =
|
||||
|
||||
@@ -48,6 +48,7 @@ enum class DiagnosticKind {
|
||||
MissingStdlibClass,
|
||||
NotASupertype,
|
||||
SuperNotAvailable,
|
||||
AmbiguousSuper,
|
||||
|
||||
LoopInSupertype,
|
||||
RecursiveTypealiasExpansion,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
enum class E : Cloneable {
|
||||
A;
|
||||
<!OVERRIDING_FINAL_MEMBER!>override<!> fun clone(): Any {
|
||||
return super.<!UNRESOLVED_REFERENCE!>clone<!>()
|
||||
return <!AMBIGUOUS_SUPER!>super<!>.clone()
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+5
-5
@@ -13,7 +13,7 @@ class GenericDerivedClass<T> : GenericBaseClass<T>(), GenericBaseInterface<T> {
|
||||
override fun bar(x: T): T = super.bar(x)
|
||||
|
||||
override fun ambiguous(x: T): T =
|
||||
super.<!UNRESOLVED_REFERENCE!>ambiguous<!>(x)
|
||||
<!AMBIGUOUS_SUPER!>super<!>.ambiguous(x)
|
||||
}
|
||||
|
||||
class SpecializedDerivedClass : GenericBaseClass<Int>(), GenericBaseInterface<String> {
|
||||
@@ -21,9 +21,9 @@ class SpecializedDerivedClass : GenericBaseClass<Int>(), GenericBaseInterface<St
|
||||
override fun bar(x: String): String = super.bar(x)
|
||||
|
||||
override fun ambiguous(x: String): String =
|
||||
super.<!UNRESOLVED_REFERENCE!>ambiguous<!>(x)
|
||||
<!AMBIGUOUS_SUPER!>super<!>.ambiguous(x)
|
||||
override fun ambiguous(x: Int): Int =
|
||||
super.<!UNRESOLVED_REFERENCE!>ambiguous<!>(x)
|
||||
<!AMBIGUOUS_SUPER!>super<!>.ambiguous(x)
|
||||
}
|
||||
|
||||
class MixedDerivedClass<T> : GenericBaseClass<Int>(), GenericBaseInterface<T> {
|
||||
@@ -31,7 +31,7 @@ class MixedDerivedClass<T> : GenericBaseClass<Int>(), GenericBaseInterface<T> {
|
||||
override fun bar(x: T): T = super.bar(x)
|
||||
|
||||
override fun ambiguous(x: Int): Int =
|
||||
super.<!UNRESOLVED_REFERENCE!>ambiguous<!>(x)
|
||||
<!AMBIGUOUS_SUPER!>super<!>.ambiguous(x)
|
||||
override fun ambiguous(x: T): T =
|
||||
super.<!UNRESOLVED_REFERENCE!>ambiguous<!>(x)
|
||||
<!AMBIGUOUS_SUPER!>super<!>.ambiguous(x)
|
||||
}
|
||||
|
||||
+2
-2
@@ -45,13 +45,13 @@ class Derived : Base(), Interface {
|
||||
super.prop
|
||||
|
||||
fun getAmbiguousSuperProp(): Int =
|
||||
super.<!UNRESOLVED_REFERENCE!>ambiguousProp<!>
|
||||
<!AMBIGUOUS_SUPER!>super<!>.ambiguousProp
|
||||
|
||||
fun callsFunFromSuperInterface() {
|
||||
super.bar()
|
||||
}
|
||||
|
||||
fun callsAmbiguousSuperFun() {
|
||||
super.<!UNRESOLVED_REFERENCE!>ambiguous<!>()
|
||||
<!AMBIGUOUS_SUPER!>super<!>.ambiguous()
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -34,6 +34,6 @@ class B : A(), I {
|
||||
}
|
||||
|
||||
override fun qux() {
|
||||
super.<!UNRESOLVED_REFERENCE!>qux<!>()
|
||||
<!AMBIGUOUS_SUPER!>super<!>.qux()
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ interface InterfaceWithFun {
|
||||
|
||||
class DerivedUsingFun : BaseWithCallableProp(), InterfaceWithFun {
|
||||
fun foo(): String =
|
||||
super.<!UNRESOLVED_REFERENCE!>fn<!>()
|
||||
<!AMBIGUOUS_SUPER!>super<!>.fn()
|
||||
|
||||
override fun bar(): String =
|
||||
super.bar()
|
||||
|
||||
Vendored
+1
-1
@@ -31,4 +31,4 @@ class C : A(), B {
|
||||
super@D.qux()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -20,9 +20,9 @@ interface AnotherInterface {
|
||||
interface DerivedInterface: Interface, AnotherInterface {
|
||||
override fun foo() { super.foo() }
|
||||
override fun ambiguous() {
|
||||
super.<!UNRESOLVED_REFERENCE!>ambiguous<!>()
|
||||
<!AMBIGUOUS_SUPER!>super<!>.ambiguous()
|
||||
}
|
||||
override val ambiguousProp: Int
|
||||
get() = super.<!UNRESOLVED_REFERENCE!>ambiguousProp<!>
|
||||
get() = <!AMBIGUOUS_SUPER!>super<!>.ambiguousProp
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -41,13 +41,13 @@ class ClassDerivedFromUnresolved : Base(), Interface, <!UNRESOLVED_REFERENCE!>Un
|
||||
super.prop
|
||||
|
||||
fun getAmbiguousSuperProp(): Int =
|
||||
super.<!UNRESOLVED_REFERENCE!>ambiguousProp<!>
|
||||
<!AMBIGUOUS_SUPER!>super<!>.ambiguousProp
|
||||
|
||||
fun callsFunFromSuperInterface() {
|
||||
super.bar()
|
||||
}
|
||||
|
||||
fun callsAmbiguousSuperFun() {
|
||||
super.<!UNRESOLVED_REFERENCE!>ambiguous<!>()
|
||||
<!AMBIGUOUS_SUPER!>super<!>.ambiguous()
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -41,7 +41,7 @@ class ManySupers: Foo2(), B {
|
||||
fun foo() {
|
||||
super<Foo2>.test()
|
||||
super<<!QUALIFIED_SUPERTYPE_EXTENDED_BY_OTHER_SUPERTYPE!>B<!>>.test()
|
||||
super.<!UNRESOLVED_REFERENCE!>test<!>()
|
||||
<!AMBIGUOUS_SUPER!>super<!>.test()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class ManySupers2: Foo2(), C {
|
||||
fun foo() {
|
||||
super<Foo2>.test()
|
||||
super<C>.test()
|
||||
super.<!UNRESOLVED_REFERENCE!>test<!>()
|
||||
<!AMBIGUOUS_SUPER!>super<!>.test()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,6 @@ class ManySupers2: Foo2(), C {
|
||||
fun foo() {
|
||||
super<Bar2>.test()
|
||||
super<C>.test()
|
||||
super.<!UNRESOLVED_REFERENCE!>test<!>()
|
||||
<!AMBIGUOUS_SUPER!>super<!>.test()
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -51,6 +51,7 @@ import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.psi.KtPropertyAccessor
|
||||
import org.jetbrains.kotlin.psi.KtReturnExpression
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.KtSuperExpression
|
||||
import org.jetbrains.kotlin.psi.KtTypeAlias
|
||||
import org.jetbrains.kotlin.psi.KtTypeParameter
|
||||
import org.jetbrains.kotlin.psi.KtTypeProjection
|
||||
@@ -515,6 +516,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.AMBIGUOUS_SUPER) { firDiagnostic ->
|
||||
AmbiguousSuperImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.CONSTRUCTOR_IN_OBJECT) { firDiagnostic ->
|
||||
ConstructorInObjectImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
|
||||
+5
@@ -59,6 +59,7 @@ import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.psi.KtPropertyAccessor
|
||||
import org.jetbrains.kotlin.psi.KtReturnExpression
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.KtSuperExpression
|
||||
import org.jetbrains.kotlin.psi.KtTypeAlias
|
||||
import org.jetbrains.kotlin.psi.KtTypeParameter
|
||||
import org.jetbrains.kotlin.psi.KtTypeProjection
|
||||
@@ -384,6 +385,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
abstract val bounds: List<KtType>
|
||||
}
|
||||
|
||||
abstract class AmbiguousSuper : KtFirDiagnostic<KtSuperExpression>() {
|
||||
override val diagnosticClass get() = AmbiguousSuper::class
|
||||
}
|
||||
|
||||
abstract class ConstructorInObject : KtFirDiagnostic<KtDeclaration>() {
|
||||
override val diagnosticClass get() = ConstructorInObject::class
|
||||
}
|
||||
|
||||
+8
@@ -61,6 +61,7 @@ import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.psi.KtPropertyAccessor
|
||||
import org.jetbrains.kotlin.psi.KtReturnExpression
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.KtSuperExpression
|
||||
import org.jetbrains.kotlin.psi.KtTypeAlias
|
||||
import org.jetbrains.kotlin.psi.KtTypeParameter
|
||||
import org.jetbrains.kotlin.psi.KtTypeProjection
|
||||
@@ -592,6 +593,13 @@ internal class InconsistentTypeParameterBoundsImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class AmbiguousSuperImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.AmbiguousSuper(), KtAbstractFirDiagnostic<KtSuperExpression> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ConstructorInObjectImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
|
||||
Reference in New Issue
Block a user