[FIR] Report MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES

Reporting it for `VIRTUAL_MEMBER_HIDDEN`
is ok, because `VIRTUAL_MEMBER_HIDDEN`
has always been an error, so we are
allowed to treat these as overrides
implicitly.

^KT-59408 Fixed
^KT-59419 Fixed
^KT-57076 Fixed
This commit is contained in:
Nikolay Lunyak
2023-08-18 11:04:25 +03:00
committed by Space Team
parent 0dd36ad456
commit 3f1bf6112f
29 changed files with 231 additions and 40 deletions
@@ -2588,6 +2588,20 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES) { firDiagnostic ->
MultipleDefaultsInheritedFromSupertypesImpl(
firSymbolBuilder.buildSymbol(firDiagnostic.a),
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE) { firDiagnostic ->
MultipleDefaultsInheritedFromSupertypesWhenNoExplicitOverrideImpl(
firSymbolBuilder.buildSymbol(firDiagnostic.a),
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.TYPEALIAS_EXPANDS_TO_ARRAY_OF_NOTHINGS) { firDiagnostic ->
TypealiasExpandsToArrayOfNothingsImpl(
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
@@ -1839,6 +1839,16 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
val containingClassName: Name
}
interface MultipleDefaultsInheritedFromSupertypes : KtFirDiagnostic<KtElement> {
override val diagnosticClass get() = MultipleDefaultsInheritedFromSupertypes::class
val valueParameter: KtSymbol
}
interface MultipleDefaultsInheritedFromSupertypesWhenNoExplicitOverride : KtFirDiagnostic<KtElement> {
override val diagnosticClass get() = MultipleDefaultsInheritedFromSupertypesWhenNoExplicitOverride::class
val valueParameter: KtSymbol
}
interface TypealiasExpandsToArrayOfNothings : KtFirDiagnostic<KtElement> {
override val diagnosticClass get() = TypealiasExpandsToArrayOfNothings::class
val type: KtType
@@ -2209,6 +2209,18 @@ internal class CannotChangeAccessPrivilegeImpl(
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<KtModifierListOwner>(firDiagnostic, token), KtFirDiagnostic.CannotChangeAccessPrivilege
internal class MultipleDefaultsInheritedFromSupertypesImpl(
override val valueParameter: KtSymbol,
firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<KtElement>(firDiagnostic, token), KtFirDiagnostic.MultipleDefaultsInheritedFromSupertypes
internal class MultipleDefaultsInheritedFromSupertypesWhenNoExplicitOverrideImpl(
override val valueParameter: KtSymbol,
firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<KtElement>(firDiagnostic, token), KtFirDiagnostic.MultipleDefaultsInheritedFromSupertypesWhenNoExplicitOverride
internal class TypealiasExpandsToArrayOfNothingsImpl(
override val type: KtType,
firDiagnostic: KtPsiDiagnostic,
@@ -882,6 +882,13 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
parameter<Name>("containingClassName")
}
val MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES by error<KtElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
parameter<FirValueParameterSymbol>("valueParameter")
}
val MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE by error<KtElement>(PositioningStrategy.DECLARATION_NAME) {
parameter<FirValueParameterSymbol>("valueParameter")
}
val TYPEALIAS_EXPANDS_TO_ARRAY_OF_NOTHINGS by error<KtElement> {
parameter<ConeKotlinType>("type")
}
@@ -489,6 +489,8 @@ object FirErrors {
val DATA_CLASS_OVERRIDE_DEFAULT_VALUES by error2<KtElement, FirCallableSymbol<*>, FirClassSymbol<*>>(SourceElementPositioningStrategies.DATA_MODIFIER)
val CANNOT_WEAKEN_ACCESS_PRIVILEGE by error3<KtModifierListOwner, Visibility, FirCallableSymbol<*>, Name>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
val CANNOT_CHANGE_ACCESS_PRIVILEGE by error3<KtModifierListOwner, Visibility, FirCallableSymbol<*>, Name>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
val MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES by error1<KtElement, FirValueParameterSymbol>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE by error1<KtElement, FirValueParameterSymbol>(SourceElementPositioningStrategies.DECLARATION_NAME)
val TYPEALIAS_EXPANDS_TO_ARRAY_OF_NOTHINGS by error1<KtElement, ConeKotlinType>()
val OVERRIDING_FINAL_MEMBER by error2<KtNamedDeclaration, FirCallableSymbol<*>, Name>(SourceElementPositioningStrategies.OVERRIDE_MODIFIER)
val RETURN_TYPE_MISMATCH_ON_INHERITANCE by error2<KtClassOrObject, FirCallableSymbol<*>, FirCallableSymbol<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
@@ -323,6 +323,8 @@ val FIR_NON_SUPPRESSIBLE_ERROR_NAMES: Set<String> = setOf(
"DATA_CLASS_OVERRIDE_DEFAULT_VALUES",
"CANNOT_WEAKEN_ACCESS_PRIVILEGE",
"CANNOT_CHANGE_ACCESS_PRIVILEGE",
"MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES",
"MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE",
"TYPEALIAS_EXPANDS_TO_ARRAY_OF_NOTHINGS",
"OVERRIDING_FINAL_MEMBER",
"RETURN_TYPE_MISMATCH_ON_INHERITANCE",
@@ -131,6 +131,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirOuterClassArgumentsRequiredChecker,
FirPropertyInitializationChecker,
FirDelegateFieldTypeMismatchChecker,
FirMultipleDefaultsInheritedFromSupertypesChecker,
FirFiniteBoundRestrictionChecker,
)
@@ -28,11 +28,9 @@ import org.jetbrains.kotlin.fir.references.FirSuperReference
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
import org.jetbrains.kotlin.fir.scopes.impl.multipleDelegatesWithTheSameSignature
import org.jetbrains.kotlin.fir.scopes.overriddenFunctions
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
@@ -726,6 +724,33 @@ fun FirNamedFunctionSymbol.directOverriddenFunctions(session: FirSession, scopeS
fun FirNamedFunctionSymbol.directOverriddenFunctions(context: CheckerContext) =
directOverriddenFunctions(context.session, context.sessionHolder.scopeSession)
inline fun <C : MutableCollection<FirNamedFunctionSymbol>> FirNamedFunctionSymbol.collectOverriddenFunctionsWhere(
collection: C,
context: CheckerContext,
crossinline condition: (FirNamedFunctionSymbol) -> Boolean,
) = collection.apply {
processOverriddenFunctions(context) {
if (condition(it)) {
add(it)
}
}
}
inline fun FirNamedFunctionSymbol.processOverriddenFunctions(
context: CheckerContext,
crossinline action: (FirNamedFunctionSymbol) -> Unit,
) {
val containingClass = getContainingClassSymbol(context.session) as? FirClassSymbol ?: return
val firTypeScope = containingClass.unsubstitutedScope(context)
firTypeScope.processFunctionsByName(callableId.callableName) { }
firTypeScope.processOverriddenFunctions(this) {
action(it)
ProcessorAction.NEXT
}
}
val CheckerContext.closestNonLocal get() = containingDeclarations.takeWhile { it.isNonLocal }.lastOrNull()
fun CheckerContext.closestNonLocalWith(declaration: FirDeclaration) =
@@ -0,0 +1,67 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.collectOverriddenFunctionsWhere
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
import org.jetbrains.kotlin.fir.isSubstitutionOverride
import org.jetbrains.kotlin.fir.scopes.processAllFunctions
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
object FirMultipleDefaultsInheritedFromSupertypesChecker : FirRegularClassChecker() {
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
declaration.unsubstitutedScope(context).processAllFunctions {
if (it.containingClassLookupTag() != declaration.symbol.toLookupTag()) {
return@processAllFunctions
}
checkFunction(declaration, it, context, reporter)
}
}
private fun checkFunction(
declaration: FirRegularClass,
function: FirNamedFunctionSymbol,
context: CheckerContext,
reporter: DiagnosticReporter,
) {
val overriddenFunctions = function.collectOverriddenFunctionsWhere(mutableSetOf(), context) { overridden ->
// Substitution overrides copy default values from originals
!overridden.isSubstitutionOverride && overridden.valueParameterSymbols.any { it.hasDefaultValue }
}
val isExplicitOverride = function.origin == FirDeclarationOrigin.Source
for ((index, parameter) in function.valueParameterSymbols.withIndex()) {
val basesWithDefaultValues = overriddenFunctions.count { it.valueParameterSymbols[index].hasDefaultValue }
when {
basesWithDefaultValues <= 1 -> {
continue
}
!isExplicitOverride -> {
reporter.reportOn(
declaration.source, FirErrors.MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE,
parameter, context,
)
// Avoid duplicates
break
}
else -> reporter.reportOn(
parameter.source, FirErrors.MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES,
parameter, context,
)
}
}
}
}
@@ -367,6 +367,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MIXING_SUSPEND_AN
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND_FUN
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_VARARG_PARAMETERS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTI_FIELD_VALUE_CLASS_PRIMARY_CONSTRUCTOR_DEFAULT_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED
@@ -1492,6 +1494,10 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
FQ_NAMES_IN_TYPES
)
val multipleDefaultsMessage = "More than one overridden descriptor declares a default value for ''{0}''. As the compiler can not make sure these values agree, this is not allowed."
map.put(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES, multipleDefaultsMessage, SYMBOL)
map.put(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE, multipleDefaultsMessage, SYMBOL)
map.put(TYPEALIAS_EXPANDS_TO_ARRAY_OF_NOTHINGS, "Type alias expanded to malformed type ''{0}''", RENDER_TYPE)
map.put(OVERRIDING_FINAL_MEMBER, "''{0}'' in ''{1}'' is final and cannot be overridden.", DECLARATION_NAME, TO_STRING)
+3 -1
View File
@@ -1,4 +1,6 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6
// IGNORE_BACKEND_K1: JS, JS_IR, JS_IR_ES6
// IGNORE_BACKEND_K2: ANY
// STATUS: This must be red code anyway, KT-36188
// The code in this test should be prohibited in the frontend, see KT-36188.
@@ -1,4 +1,6 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6
// IGNORE_BACKEND_K1: JS, JS_IR, JS_IR_ES6
// IGNORE_BACKEND_K2: ANY
// STATUS: This must be red code anyway, KT-36188
// !JVM_DEFAULT_MODE: all
// JVM_TARGET: 1.8
@@ -1,4 +1,6 @@
// IGNORE_BACKEND: JS
// IGNORE_BACKEND_K2: ANY
// STATUS: This must be red code anyway, KT-36188
// Test for KT-36188 bug compatibility between non-IR and IR backends
@@ -1,4 +1,6 @@
// IGNORE_BACKEND: JS
// IGNORE_BACKEND_K2: ANY
// STATUS: This must be red code anyway, KT-36188
// Test for KT-36188 bug compatibility between non-IR and IR backends
@@ -17,10 +17,10 @@ interface B {
fun foo(@An a: @An Int = @An 2)
}
class AB1 : A, B
<!MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE("@An() a: @R|An|() Int = ...")!>class AB1<!> : A, B
@An
class AB2 : A, B {
@An
override fun foo(@An a: @An Int) {}
override fun foo(<!MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES("@An() a: @R|An|() Int")!>@An a: @An Int<!>) {}
}
@@ -0,0 +1,15 @@
// ISSUE: KT-36188
interface SomeRandomBase<K> {
fun child(props: Int = 20)
}
interface SomeRandomOverride<J> : SomeRandomBase<J>
open class Keker<P> {
open fun child(props: Int = 10) {}
}
class Implementation<P>() : Keker<P>(), SomeRandomOverride<P> {
override fun child(<!MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES!>props: Int<!>) {}
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// ISSUE: KT-36188
interface SomeRandomBase<K> {
@@ -0,0 +1,17 @@
// ISSUE: KT-36188
interface SomeRandomBase<K> {
fun child(props: Int = 20)
}
interface SomeRandomOverride<J> : SomeRandomBase<J> {
override fun child(props: Int) {}
}
open class Keker<P> {
open fun child(props: Int = 10) {}
}
class Implementation<P>() : Keker<P>(), SomeRandomOverride<P> {
override fun child(<!MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES!>props: Int<!>) {}
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// ISSUE: KT-36188
interface SomeRandomBase<K> {
@@ -0,0 +1,17 @@
// ISSUE: KT-36188
interface SomeRandomBase<K> {
fun child(props: Int = 20)
}
interface SomeRandomOverride<J> : SomeRandomBase<J> {
override abstract fun child(props: Int)
}
open class Keker<P> {
open fun child(props: Int = 10) {}
}
class Implementation<P>() : Keker<P>(), SomeRandomOverride<P> {
override fun child(<!MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES!>props: Int<!>) {}
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// ISSUE: KT-36188
interface SomeRandomBase<K> {
@@ -10,5 +10,5 @@ interface Y {
object YImpl : Y
<!DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE!>class Z1<!> : X, Y by YImpl {}
<!DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE!>object Z1O<!> : X, Y by YImpl {}
<!DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE, MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE!>class Z1<!> : X, Y by YImpl {}
<!DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE, MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE!>object Z1O<!> : X, Y by YImpl {}
@@ -1,15 +0,0 @@
interface X {
fun foo(a : Int = 1)
}
interface Y {
fun foo(a : Int = 1)
}
class Z : X, Y {
override fun foo(a : Int) {}
}
object ZO : X, Y {
override fun foo(a : Int) {}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
interface X {
fun foo(a : Int = 1)
}
@@ -0,0 +1,15 @@
interface X {
fun foo(a : Int = 1)
}
interface Y {
fun foo(a : Int = 1)
}
class Z : X, Y {
fun <!VIRTUAL_MEMBER_HIDDEN!>foo<!>(<!MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES!>a : Int<!>) {}
}
object ZO : X, Y {
fun <!VIRTUAL_MEMBER_HIDDEN!>foo<!>(<!MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES!>a : Int<!>) {}
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
interface X {
fun foo(a : Int = 1)
}
@@ -11,4 +11,4 @@ interface C {
}
// TODO DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES reported twice
class Z : A, B(), C
<!MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE!>class Z<!> : A, B(), C
@@ -1,10 +0,0 @@
interface X {
fun foo(a : Int = 1)
}
interface Y {
fun foo(a : Int = 1)
}
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class Z1<!> : X, Y {} // BUG
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>object Z1O<!> : X, Y {} // BUG
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
interface X {
fun foo(a : Int = 1)
}