FIR checker: report AMBIGUOUS_SUPER

This commit is contained in:
Tianyu Geng
2021-07-19 15:13:39 -07:00
committed by Ivan Kochurkin
parent 5b9ce7e823
commit 06ee84f809
20 changed files with 59 additions and 27 deletions
@@ -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
@@ -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)
@@ -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
}
}
@@ -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")
@@ -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
@@ -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()
}
}
@@ -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)
}
@@ -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()
}
}
@@ -34,6 +34,6 @@ class B : A(), I {
}
override fun qux() {
super.<!UNRESOLVED_REFERENCE!>qux<!>()
<!AMBIGUOUS_SUPER!>super<!>.qux()
}
}
@@ -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()
@@ -31,4 +31,4 @@ class C : A(), B {
super@D.qux()
}
}
}
}
@@ -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
}
@@ -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()
}
}
@@ -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()
}
}
@@ -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,
@@ -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
}
@@ -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,