[FIR] Add 3 type mismatch diagnostics

This commit is contained in:
Nick
2020-08-12 14:45:57 +03:00
parent c8f8908a01
commit 61e21dadec
27 changed files with 736 additions and 114 deletions
@@ -0,0 +1,35 @@
open class A {
open var test: Number = 10
}
open class B : A {
override var test: Double = 20.0
}
class C() : A() {
override var test: <!VAR_TYPE_MISMATCH_ON_OVERRIDE!>String<!> = "Test"
}
open class D() : B() {
override var test: <!VAR_TYPE_MISMATCH_ON_OVERRIDE!>Char<!> = '\n'
}
class E<T : Double>(val value: T) : B() {
override var test: T = value
}
open class F<T : Number>(val value: T) {
open var rest: T = value
}
class G<E : Double>(val balue: E) : F<E>(balue) {
override var rest: E = balue
}
class H<E : String>(val balue: E) : <!INAPPLICABLE_CANDIDATE!>F<E><!>(balue) {
override var rest: E = balue // no report because of INAPPLICABLE_CANDIDATE
}
class M<E : String>(val balue: E) : F<Double>(3.14) {
override var rest: <!VAR_TYPE_MISMATCH_ON_OVERRIDE!>E<!> = balue
}
@@ -0,0 +1,106 @@
FILE: propertyTypeMismatchOnOverride.kt
public open class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
public open var test: R|kotlin/Number| = Int(10)
public get(): R|kotlin/Number|
public set(value: R|kotlin/Number|): R|kotlin/Unit|
}
public open class B : R|A| {
public constructor(): R|B| {
super<R|A|>()
}
public open override var test: R|kotlin/Double| = Double(20.0)
public get(): R|kotlin/Double|
public set(value: R|kotlin/Double|): R|kotlin/Unit|
}
public final class C : R|A| {
public constructor(): R|C| {
super<R|A|>()
}
public final override var test: R|kotlin/String| = String(Test)
public get(): R|kotlin/String|
public set(value: R|kotlin/String|): R|kotlin/Unit|
}
public open class D : R|B| {
public constructor(): R|D| {
super<R|B|>()
}
public open override var test: R|kotlin/Char| = Char(10)
public get(): R|kotlin/Char|
public set(value: R|kotlin/Char|): R|kotlin/Unit|
}
public final class E<T : R|kotlin/Double|> : R|B| {
public constructor<T : R|kotlin/Double|>(value: R|T|): R|E<T>| {
super<R|B|>()
}
public final val value: R|T| = R|<local>/value|
public get(): R|T|
public final override var test: R|T| = R|<local>/value|
public get(): R|T|
public set(value: R|T|): R|kotlin/Unit|
}
public open class F<T : R|kotlin/Number|> : R|kotlin/Any| {
public constructor<T : R|kotlin/Number|>(value: R|T|): R|F<T>| {
super<R|kotlin/Any|>()
}
public final val value: R|T| = R|<local>/value|
public get(): R|T|
public open var rest: R|T| = R|<local>/value|
public get(): R|T|
public set(value: R|T|): R|kotlin/Unit|
}
public final class G<E : R|kotlin/Double|> : R|F<E>| {
public constructor<E : R|kotlin/Double|>(balue: R|E|): R|G<E>| {
super<R|F<E>|>(R|<local>/balue|)
}
public final val balue: R|E| = R|<local>/balue|
public get(): R|E|
public final override var rest: R|E| = R|<local>/balue|
public get(): R|E|
public set(value: R|E|): R|kotlin/Unit|
}
public final class H<E : R|kotlin/String|> : R|F<E>| {
public constructor<E : R|kotlin/String|>(balue: R|E|): R|H<E>| {
super<R|F<E>|>(R|<local>/balue|)
}
public final val balue: R|E| = R|<local>/balue|
public get(): R|E|
public final override var rest: R|E| = R|<local>/balue|
public get(): R|E|
public set(value: R|E|): R|kotlin/Unit|
}
public final class M<E : R|kotlin/String|> : R|F<kotlin/Double>| {
public constructor<E : R|kotlin/String|>(balue: R|E|): R|M<E>| {
super<R|F<kotlin/Double>|>(Double(3.14))
}
public final val balue: R|E| = R|<local>/balue|
public get(): R|E|
public final override var rest: R|E| = R|<local>/balue|
public get(): R|E|
public set(value: R|E|): R|kotlin/Unit|
}
@@ -0,0 +1,69 @@
open class A {
open fun test(): Number = 10
}
open class B : A {
override fun test(): Double = 20.0
fun test(x: Int) = x
}
class C() : A() {
override fun test(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>String<!> = "Test"
}
open class D() : B() {
override fun test(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Char<!> = '\n'
}
class E<T : Double>(val value: T) : B() {
override fun test(): T = value
}
open class F<T : Number>(val value: T) {
open fun rest(): T = value
}
class G<E : Double>(val balue: E) : F<E>(balue) {
override fun rest(): E = balue
}
class H<E : String>(val balue: E) : <!INAPPLICABLE_CANDIDATE!>F<E><!>(balue) {
override fun rest(): E = balue // no report because of INAPPLICABLE_CANDIDATE
}
class M<E : String>(val balue: E) : F<Double>(3.14) {
override fun rest(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>E<!> = balue
}
open class X
open class Y() : X()
open class Z() : Y()
open class W() : Z()
open class V {
open fun hello(): X = X()
}
open class L() : V()
open class Q() : L()
open class S() : Q() {
override fun hello(): W = W()
}
open class J() : S() {
override fun hello(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Z<!> = Z()
}
open class Base<T : X, Z : T> {
open fun kek(): Z = Z()
}
open class GoodDerrived : Base<Y, W>() {
override fun kek(): W = W()
}
open class BadDerrived : Base<Y, W>() {
override fun kek(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>String<!> = "test"
}
@@ -0,0 +1,206 @@
FILE: returnTypeMismatchOnOverride.kt
public open class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
public open fun test(): R|kotlin/Number| {
^test Int(10)
}
}
public open class B : R|A| {
public constructor(): R|B| {
super<R|A|>()
}
public open override fun test(): R|kotlin/Double| {
^test Double(20.0)
}
public final fun test(x: R|kotlin/Int|): R|kotlin/Int| {
^test R|<local>/x|
}
}
public final class C : R|A| {
public constructor(): R|C| {
super<R|A|>()
}
public final override fun test(): R|kotlin/String| {
^test String(Test)
}
}
public open class D : R|B| {
public constructor(): R|D| {
super<R|B|>()
}
public open override fun test(): R|kotlin/Char| {
^test Char(10)
}
}
public final class E<T : R|kotlin/Double|> : R|B| {
public constructor<T : R|kotlin/Double|>(value: R|T|): R|E<T>| {
super<R|B|>()
}
public final val value: R|T| = R|<local>/value|
public get(): R|T|
public final override fun test(): R|T| {
^test this@R|/E|.R|/E.value|
}
}
public open class F<T : R|kotlin/Number|> : R|kotlin/Any| {
public constructor<T : R|kotlin/Number|>(value: R|T|): R|F<T>| {
super<R|kotlin/Any|>()
}
public final val value: R|T| = R|<local>/value|
public get(): R|T|
public open fun rest(): R|T| {
^rest this@R|/F|.R|/F.value|
}
}
public final class G<E : R|kotlin/Double|> : R|F<E>| {
public constructor<E : R|kotlin/Double|>(balue: R|E|): R|G<E>| {
super<R|F<E>|>(R|<local>/balue|)
}
public final val balue: R|E| = R|<local>/balue|
public get(): R|E|
public final override fun rest(): R|E| {
^rest this@R|/G|.R|/G.balue|
}
}
public final class H<E : R|kotlin/String|> : R|F<E>| {
public constructor<E : R|kotlin/String|>(balue: R|E|): R|H<E>| {
super<R|F<E>|>(R|<local>/balue|)
}
public final val balue: R|E| = R|<local>/balue|
public get(): R|E|
public final override fun rest(): R|E| {
^rest this@R|/H|.R|/H.balue|
}
}
public final class M<E : R|kotlin/String|> : R|F<kotlin/Double>| {
public constructor<E : R|kotlin/String|>(balue: R|E|): R|M<E>| {
super<R|F<kotlin/Double>|>(Double(3.14))
}
public final val balue: R|E| = R|<local>/balue|
public get(): R|E|
public final override fun rest(): R|E| {
^rest this@R|/M|.R|/M.balue|
}
}
public open class X : R|kotlin/Any| {
public constructor(): R|X| {
super<R|kotlin/Any|>()
}
}
public open class Y : R|X| {
public constructor(): R|Y| {
super<R|X|>()
}
}
public open class Z : R|Y| {
public constructor(): R|Z| {
super<R|Y|>()
}
}
public open class W : R|Z| {
public constructor(): R|W| {
super<R|Z|>()
}
}
public open class V : R|kotlin/Any| {
public constructor(): R|V| {
super<R|kotlin/Any|>()
}
public open fun hello(): R|X| {
^hello R|/X.X|()
}
}
public open class L : R|V| {
public constructor(): R|L| {
super<R|V|>()
}
}
public open class Q : R|L| {
public constructor(): R|Q| {
super<R|L|>()
}
}
public open class S : R|Q| {
public constructor(): R|S| {
super<R|Q|>()
}
public open override fun hello(): R|W| {
^hello R|/W.W|()
}
}
public open class J : R|S| {
public constructor(): R|J| {
super<R|S|>()
}
public open override fun hello(): R|Z| {
^hello R|/Z.Z|()
}
}
public open class Base<T : R|X|, Z : R|T|> : R|kotlin/Any| {
public constructor<T : R|X|, Z : R|T|>(): R|Base<T, Z>| {
super<R|kotlin/Any|>()
}
public open fun kek(): R|Z| {
^kek R|/Z.Z|()
}
}
public open class GoodDerrived : R|Base<Y, W>| {
public constructor(): R|GoodDerrived| {
super<R|Base<Y, W>|>()
}
public open override fun kek(): R|W| {
^kek R|/W.W|()
}
}
public open class BadDerrived : R|Base<Y, W>| {
public constructor(): R|BadDerrived| {
super<R|Base<Y, W>|>()
}
public open override fun kek(): R|kotlin/String| {
^kek String(test)
}
}
@@ -1021,6 +1021,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/projectionsOnNonClassTypeArguments.kt");
}
@TestMetadata("propertyTypeMismatchOnOverride.kt")
public void testPropertyTypeMismatchOnOverride() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/propertyTypeMismatchOnOverride.kt");
}
@TestMetadata("qualifiedSupertypeExtendedByOtherSupertype.kt")
public void testQualifiedSupertypeExtendedByOtherSupertype() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/qualifiedSupertypeExtendedByOtherSupertype.kt");
@@ -1046,6 +1051,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/sealedSupertype.kt");
}
@TestMetadata("returnTypeMismatchOnOverride.kt")
public void testReturnTypeMismatchOnOverride() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/returnTypeMismatchOnOverride.kt");
}
@TestMetadata("superIsNotAnExpression.kt")
public void testSuperIsNotAnExpression() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.kt");
@@ -1021,6 +1021,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/projectionsOnNonClassTypeArguments.kt");
}
@TestMetadata("propertyTypeMismatchOnOverride.kt")
public void testPropertyTypeMismatchOnOverride() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/propertyTypeMismatchOnOverride.kt");
}
@TestMetadata("qualifiedSupertypeExtendedByOtherSupertype.kt")
public void testQualifiedSupertypeExtendedByOtherSupertype() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/qualifiedSupertypeExtendedByOtherSupertype.kt");
@@ -1046,6 +1051,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/sealedSupertype.kt");
}
@TestMetadata("returnTypeMismatchOnOverride.kt")
public void testReturnTypeMismatchOnOverride() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/returnTypeMismatchOnOverride.kt");
}
@TestMetadata("superIsNotAnExpression.kt")
public void testSuperIsNotAnExpression() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.kt");
@@ -40,6 +40,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirEnumClassSimpleChecker,
FirSealedSupertypeChecker,
FirInapplicableLateinitChecker,
FirTypeMismatchOnOverrideChecker,
)
override val regularClassCheckers: List<FirRegularClassChecker> = listOf(
@@ -0,0 +1,242 @@
/*
* Copyright 2010-2020 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.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
object FirTypeMismatchOnOverrideChecker : FirMemberDeclarationChecker() {
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration !is FirRegularClass) {
return
}
val typeCheckerContext = context.session.typeContext.newBaseTypeCheckerContext(
errorTypesEqualToAnything = false,
stubTypesEqualToAnything = false
)
val firTypeScope = declaration.unsubstitutedScope(
context.sessionHolder.session,
context.sessionHolder.scopeSession
)
for (it in declaration.declarations) {
when (it) {
is FirSimpleFunction -> checkFunction(declaration, it, context, reporter, typeCheckerContext, firTypeScope)
is FirProperty -> checkProperty(declaration, it, context, reporter, typeCheckerContext, firTypeScope)
}
}
}
private fun FirTypeScope.getDirectOverridesOf(function: FirSimpleFunction): List<FirFunctionSymbol<*>> {
val overriddenFunctions = mutableSetOf<FirFunctionSymbol<*>>()
processFunctionsByName(function.name) {}
processDirectlyOverriddenFunctions(function.symbol) {
overriddenFunctions.add(it)
ProcessorAction.NEXT
}
return overriddenFunctions.toList()
}
private fun FirTypeScope.getDirectOverridesOf(property: FirProperty): List<FirPropertySymbol> {
val overriddenProperties = mutableSetOf<FirPropertySymbol>()
processPropertiesByName(property.name) {}
processDirectlyOverriddenProperties(property.symbol) {
overriddenProperties.add(it)
ProcessorAction.NEXT
}
return overriddenProperties.toList()
}
private fun FirRegularClass.substituteAllSupertypeParameters(context: CheckerContext): ConeSubstitutor {
val allSupertypesMapping = mutableMapOf<FirTypeParameterSymbol, ConeKotlinType>()
val remapper = mutableMapOf<ConeKotlinType, ConeKotlinType>()
fun FirRegularClass.collectSupertypes() {
for (it in superTypeRefs) {
val fir = it.coneType.safeAs<ConeClassLikeType>()?.lookupTag?.toSymbol(context.session)
?.fir.safeAs<FirRegularClass>()
?: continue
if (it.coneType.typeArguments.size != fir.typeParameters.size) {
continue
}
for (that in fir.typeParameters.indices) {
val proto = fir.typeParameters[that].symbol
val actual = it.coneType.typeArguments[that].safeAs<ConeKotlinType>()
?.lowerBoundIfFlexible()
?: continue
val value = remapper.getOrDefault(actual, actual)
remapper[proto.fir.toConeType()] = value
allSupertypesMapping[proto] = value
}
fir.collectSupertypes()
}
}
collectSupertypes()
return substitutorByMap(allSupertypesMapping)
}
private fun ConeKotlinType.substituteAllTypeParameters(
overrideDeclaration: FirCallableMemberDeclaration<*>,
baseDeclarationSymbol: FirCallableSymbol<*>,
): ConeKotlinType {
if (overrideDeclaration.typeParameters.isEmpty()) {
return this
}
val parametersOwner = baseDeclarationSymbol.fir.safeAs<FirTypeParametersOwner>()
?: return this
val map = mutableMapOf<FirTypeParameterSymbol, ConeKotlinType>()
overrideDeclaration.typeParameters.zip(parametersOwner.typeParameters).forEach { (to, from) ->
map[from.symbol] = to.toConeType()
}
return substitutorByMap(map).substituteOrSelf(this)
}
private fun ConeKotlinType.substituteOrSelf(substitutor: ConeSubstitutor) = substitutor.substituteOrSelf(this)
private fun FirCallableMemberDeclaration<*>.checkReturnType(
regularClass: FirRegularClass,
overriddenSymbols: List<FirCallableSymbol<*>>,
context: CheckerContext,
typeCheckerContext: AbstractTypeCheckerContext,
): FirMemberDeclaration? {
val returnType = returnTypeRef.safeAs<FirResolvedTypeRef>()?.type
?: return null
val bounds = overriddenSymbols.map { it.fir.returnTypeRef.coneType.upperBoundIfFlexible() }
val supertypesParameterSubstitutor = regularClass.substituteAllSupertypeParameters(context)
for (it in bounds.indices) {
val restriction = bounds[it]
.substituteAllTypeParameters(this, overriddenSymbols[it])
.substituteOrSelf(supertypesParameterSubstitutor)
if (!AbstractTypeChecker.isSubtypeOf(typeCheckerContext, returnType, restriction)) {
return overriddenSymbols[it].fir.safeAs()
}
}
return null
}
private fun checkFunction(
regularClass: FirRegularClass,
function: FirSimpleFunction,
context: CheckerContext,
reporter: DiagnosticReporter,
typeCheckerContext: AbstractTypeCheckerContext,
firTypeScope: FirTypeScope
) {
if (!function.isOverride) {
return
}
val overriddenFunctionSymbols = firTypeScope.getDirectOverridesOf(function)
if (overriddenFunctionSymbols.isEmpty()) {
return
}
val restriction = function.checkReturnType(
regularClass = regularClass,
overriddenSymbols = overriddenFunctionSymbols,
context = context,
typeCheckerContext = typeCheckerContext
)
restriction?.let {
reporter.reportMismatchOnFunction(
function.returnTypeRef.source,
function.returnTypeRef.coneType.toString(),
it
)
}
}
private fun checkProperty(
regularClass: FirRegularClass,
property: FirProperty,
context: CheckerContext,
reporter: DiagnosticReporter,
typeCheckerContext: AbstractTypeCheckerContext,
firTypeScope: FirTypeScope
) {
if (!property.isOverride) {
return
}
val overriddenPropertySymbols = firTypeScope.getDirectOverridesOf(property)
if (overriddenPropertySymbols.isEmpty()) {
return
}
val restriction = property.checkReturnType(
regularClass = regularClass,
overriddenSymbols = overriddenPropertySymbols,
context = context,
typeCheckerContext = typeCheckerContext
)
restriction?.let {
if (property.isVar) {
reporter.reportMismatchOnVariable(
property.returnTypeRef.source,
property.returnTypeRef.coneType.toString(),
it
)
} else {
reporter.reportMismatchOnProperty(
property.returnTypeRef.source,
property.returnTypeRef.coneType.toString(),
it
)
}
}
}
private fun DiagnosticReporter.reportMismatchOnFunction(source: FirSourceElement?, type: String, declaration: FirMemberDeclaration) {
source?.let { report(FirErrors.RETURN_TYPE_MISMATCH_ON_OVERRIDE.on(it, type, declaration)) }
}
private fun DiagnosticReporter.reportMismatchOnProperty(source: FirSourceElement?, type: String, declaration: FirMemberDeclaration) {
source?.let { report(FirErrors.PROPERTY_TYPE_MISMATCH_ON_OVERRIDE.on(it, type, declaration)) }
}
private fun DiagnosticReporter.reportMismatchOnVariable(source: FirSourceElement?, type: String, declaration: FirMemberDeclaration) {
source?.let { report(FirErrors.VAR_TYPE_MISMATCH_ON_OVERRIDE.on(it, type, declaration)) }
}
}
@@ -75,6 +75,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OTHER_ERROR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_TYPE_MISMATCH_ON_OVERRIDE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.QUALIFIED_SUPERTYPE_EXTENDED_BY_OTHER_SUPERTYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RECURSION_IN_IMPLICIT_TYPES
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RECURSION_IN_SUPERTYPES
@@ -92,6 +93,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_NOT_ALLOWE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_CLASS_CONSTRUCTOR_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_SUPERTYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_SUPERTYPE_IN_LOCAL_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_TYPE_MISMATCH_ON_OVERRIDE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_INITIALIZED_IN_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR
@@ -111,6 +113,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VARIABLE_EXPECTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_ANNOTATION_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_INVOCATION_KIND
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAR_TYPE_MISMATCH_ON_OVERRIDE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS
@Suppress("unused")
@@ -275,6 +278,24 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED,
"Variance annotations are only allowed for type parameters of classes and interfaces"
)
map.put(
RETURN_TYPE_MISMATCH_ON_OVERRIDE,
"Return type of ''{0}'' is not a subtype of the return type of the overridden member ''{1}''",
TO_STRING,
DECLARATION_NAME
) // #
map.put(
PROPERTY_TYPE_MISMATCH_ON_OVERRIDE,
"Type of ''{0}'' is not a subtype of the overridden property ''{1}''",
TO_STRING,
DECLARATION_NAME
) // #
map.put(
VAR_TYPE_MISMATCH_ON_OVERRIDE,
"Type of ''{0}'' doesn''t match the type of the overridden var-property ''{1}''",
TO_STRING,
DECLARATION_NAME
) // #
// Redeclarations
map.put(MANY_COMPANION_OBJECTS, "Only one companion object is allowed per class")
@@ -130,6 +130,9 @@ object FirErrors {
val TYPE_PARAMETERS_IN_ENUM by error0<FirSourceElement, PsiElement>()
val CONFLICTING_PROJECTION by error1<FirSourceElement, PsiElement, String>()
val VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED by error0<FirSourceElement, PsiElement>()
val RETURN_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, PsiElement, String, FirMemberDeclaration>()
val PROPERTY_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, PsiElement, String, FirMemberDeclaration>()
val VAR_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, PsiElement, String, FirMemberDeclaration>()
// Redeclarations
val MANY_COMPANION_OBJECTS by error0<FirSourceElement, PsiElement>()
@@ -13,14 +13,14 @@ interface A<H> {
abstract class B<H>() : A<H> {
override fun foo() {
}
override fun foo2() : Unit {
override fun foo2() : <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Unit<!> {
}
override val a : Double = 1.toDouble()
override val a : <!PROPERTY_TYPE_MISMATCH_ON_OVERRIDE!>Double<!> = 1.toDouble()
override val a1 = 1.toDouble()
abstract override fun <X> g() : Int
abstract override fun <X> g1() : List<X>
abstract override fun <X> g() : <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Int<!>
abstract override fun <X> g1() : <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>List<X><!>
abstract override val g : Iterator<Int>
abstract override val g : <!PROPERTY_TYPE_MISMATCH_ON_OVERRIDE!>Iterator<Int><!>
}
@@ -1,9 +0,0 @@
abstract class A {
abstract var x: Int;
abstract fun foo() : Int;
}
abstract class C : A() {
override abstract var x: String =<!SYNTAX!><!> <!SYNTAX!>?<!>
override abstract fun foo(): String =<!SYNTAX!><!> <!SYNTAX!>?<!>
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
abstract class A {
abstract var x: Int;
abstract fun foo() : Int;
@@ -15,12 +15,12 @@ interface A {
@An
interface B : A {
override val p1: Int
override val p1: <!PROPERTY_TYPE_MISMATCH_ON_OVERRIDE!>Int<!>
@An
override val p2: @An String
override fun test(arg: String): Int
override fun test(arg: String): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Int<!>
}
interface C : A {
override var p2: Int
override var p2: <!VAR_TYPE_MISMATCH_ON_OVERRIDE!>Int<!>
}
@@ -27,7 +27,7 @@ import org.jetbrains.annotations.NotNull;
annotation class An
class B : A {
override fun foo(): String? = null
override fun foo(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>String?<!> = null
}
@An
@@ -38,5 +38,5 @@ public interface C {
}
class D : C {
override fun foo(): String? = null
override fun foo(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>String?<!> = null
}
@@ -21,5 +21,5 @@ data class FooImplAll(val num: Int) : Foo {
data class WrongSignatures(val num: Int) : Foo {
override fun equals(other: WrongSignatures) = false
override fun hashCode(): Boolean = true
override fun hashCode(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Boolean<!> = true
}
@@ -15,7 +15,7 @@ fun foo() {
}
class Delegate {
operator fun getValue(t: Any?, p: KProperty<*>): String {
operator fun getValue(t: Any?, p: KProperty<*>): <!PROPERTY_TYPE_MISMATCH_ON_OVERRIDE!>String<!> {
return ""
}
}
@@ -13,5 +13,5 @@ object AImpl : IA {
open class C : IA by AImpl, IB
class D : C() {
override fun foo(): Double = 3.14
override fun foo(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Double<!> = 3.14
}
@@ -11,7 +11,16 @@ import java.util.*;
abstract class B : MutableList<Int>, AbstractList<Int>() {
override fun removeAt(index: Int): Int = null!!
override fun remove(element: Int): Boolean = null!!
override fun remove(element: Int): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Boolean<!> = null!!
}
abstract class D : AbstractList<Int>() {
// removeAt() doesn't exist in java/util/AbstractList, it's a
// fake override of the method from kotlin/collections/MutableList
override fun removeAt(index: Int): Int = null!!
// AbstractList::remove() should return Int here. No fake overrides created.
// This may be a bug because the old compiler doesn't report a diagnostic here.
override fun remove(element: Int): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Boolean<!> = null!!
}
fun main(a: A, b: B, c: ArrayList<Int>) {
@@ -1,49 +0,0 @@
package test
interface X {
fun foo(): String? {
return null
}
}
interface Y {
fun foo(): String {
return "foo"
}
}
interface Incompatible {
fun foo(): Int {
return 3
}
}
class Test1(val x: X) : X by x, Y {
override fun foo(): String? {
return null
}
}
class Test2(val x: X) : X by x, Y {
override fun foo(): String {
return "foo"
}
}
class Test3(val y: Y) : X, Y by y {
override fun foo(): String? {
return null
}
}
class Test4(val y: Y) : X, Y by y {
override fun foo(): String {
return "foo"
}
}
class Test5(val y: Y, val x: X) : X by x, Y by y, Incompatible {
override fun foo(): Int {
return 3
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
package test
interface X {
@@ -3,7 +3,7 @@ interface A {
}
interface B : A {
override fun test(): Unit = "B"
override fun test(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Unit<!> = "B"
}
open class C : A
@@ -1,35 +0,0 @@
// FILE: A.java
import org.jetbrains.annotations.*;
public interface A {
@Nullable
String foo();
}
// FILE: B.java
import org.jetbrains.annotations.*;
public interface B {
@NotNull
String foo();
}
// FILE: C.kt
class C1 : A, B {
override fun foo(): String? = ""
}
class C2 : A, B {
override fun foo(): String = ""
}
interface I : A, B
class C3 : I {
override fun foo(): String? = ""
}
class C4 : I {
override fun foo(): String = ""
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: A.java
import org.jetbrains.annotations.*;
@@ -23,7 +23,7 @@ class K2 : JavaClass() {
}
class K3 : JavaClass() {
override fun foo(x: Int, y: Continuation<String>): Any? = null
override fun foo(x: Int, y: Continuation<String>): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Any?<!> = null
}
fun builder(block: suspend () -> Unit) {}
@@ -7,7 +7,7 @@ interface Bar<T> {
}
class Test1 : Foo {
override val foo = {}
override val foo = <!PROPERTY_TYPE_MISMATCH_ON_OVERRIDE!>{}<!>
}
class Test2 : Foo {
@@ -15,7 +15,7 @@ class Test2 : Foo {
}
class Test3 : Bar<suspend () -> Unit> {
override val bar = {}
override val bar = <!PROPERTY_TYPE_MISMATCH_ON_OVERRIDE!>{}<!>
}
class Test4 : Bar<suspend () -> Unit> {
@@ -11,12 +11,12 @@ abstract class Base {
}
class Case1 : Base() {
override fun foo(): Any
override fun foo(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>Any<!>
{
return ""
}
override val a: Any?
override val a: <!PROPERTY_TYPE_MISMATCH_ON_OVERRIDE!>Any?<!>
get() = TODO()
override var b: String
get() = TODO()
@@ -30,7 +30,7 @@ class Case1 : Base() {
*/
class Case2(override val a: String, override var b: String) : Base() {
override fun foo(): CharSequence? {
override fun foo(): <!RETURN_TYPE_MISMATCH_ON_OVERRIDE!>CharSequence?<!> {
return ""
}
}