[FIR] Implement RETURN_TYPE_MISMATCH_ON_INHERITANCE diagnostic
This commit is contained in:
committed by
teamcityserver
parent
8012eb3214
commit
94da1e37aa
+6
@@ -587,6 +587,12 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
parameter<Name>("containingClassName")
|
parameter<Name>("containingClassName")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val RETURN_TYPE_MISMATCH_ON_INHERITANCE by error<KtClassOrObject>(PositioningStrategy.DECLARATION_NAME) {
|
||||||
|
parameter<FirClass<*>>("classOrObject")
|
||||||
|
parameter<FirCallableDeclaration<*>>("conflictingDeclaration1")
|
||||||
|
parameter<FirCallableDeclaration<*>>("conflictingDeclaration2")
|
||||||
|
}
|
||||||
|
|
||||||
val ABSTRACT_MEMBER_NOT_IMPLEMENTED by error<KtClassOrObject>(PositioningStrategy.DECLARATION_NAME) {
|
val ABSTRACT_MEMBER_NOT_IMPLEMENTED by error<KtClassOrObject>(PositioningStrategy.DECLARATION_NAME) {
|
||||||
parameter<FirClass>("classOrObject")
|
parameter<FirClass>("classOrObject")
|
||||||
parameter<FirCallableDeclaration>("missingDeclaration")
|
parameter<FirCallableDeclaration>("missingDeclaration")
|
||||||
|
|||||||
@@ -347,6 +347,7 @@ object FirErrors {
|
|||||||
val CANNOT_WEAKEN_ACCESS_PRIVILEGE by error3<KtModifierListOwner, Visibility, FirCallableDeclaration, Name>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
val CANNOT_WEAKEN_ACCESS_PRIVILEGE by error3<KtModifierListOwner, Visibility, FirCallableDeclaration, Name>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
||||||
val CANNOT_CHANGE_ACCESS_PRIVILEGE by error3<KtModifierListOwner, Visibility, FirCallableDeclaration, Name>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
val CANNOT_CHANGE_ACCESS_PRIVILEGE by error3<KtModifierListOwner, Visibility, FirCallableDeclaration, Name>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
||||||
val OVERRIDING_FINAL_MEMBER by error2<KtNamedDeclaration, FirCallableDeclaration, Name>(SourceElementPositioningStrategies.OVERRIDE_MODIFIER)
|
val OVERRIDING_FINAL_MEMBER by error2<KtNamedDeclaration, FirCallableDeclaration, Name>(SourceElementPositioningStrategies.OVERRIDE_MODIFIER)
|
||||||
|
val RETURN_TYPE_MISMATCH_ON_INHERITANCE by error3<KtClassOrObject, FirClass<*>, FirCallableDeclaration<*>, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||||
val ABSTRACT_MEMBER_NOT_IMPLEMENTED by error2<KtClassOrObject, FirClass, FirCallableDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
val ABSTRACT_MEMBER_NOT_IMPLEMENTED by error2<KtClassOrObject, FirClass, FirCallableDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||||
val ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED by error2<KtClassOrObject, FirClass, FirCallableDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
val ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED by error2<KtClassOrObject, FirClass, FirCallableDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||||
val INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER by error2<KtClassOrObject, FirClass, FirCallableDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
val INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER by error2<KtClassOrObject, FirClass, FirCallableDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||||
|
|||||||
+1
@@ -66,6 +66,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
FirSealedSupertypeChecker,
|
FirSealedSupertypeChecker,
|
||||||
FirMemberFunctionsChecker,
|
FirMemberFunctionsChecker,
|
||||||
FirMemberPropertiesChecker,
|
FirMemberPropertiesChecker,
|
||||||
|
FirImplementationMismatchChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val regularClassCheckers: Set<FirRegularClassChecker>
|
override val regularClassCheckers: Set<FirRegularClassChecker>
|
||||||
|
|||||||
+96
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.impl.deduplicating
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionCallableSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.typeContext
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeKotlinErrorType
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
|
|
||||||
|
object FirImplementationMismatchChecker : FirClassChecker() {
|
||||||
|
|
||||||
|
override fun check(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
val source = declaration.source ?: return
|
||||||
|
val sourceKind = source.kind
|
||||||
|
if (sourceKind is FirFakeSourceElementKind && sourceKind != FirFakeSourceElementKind.EnumInitializer) return
|
||||||
|
if (declaration is FirRegularClass && declaration.isExpect) return
|
||||||
|
val classKind = declaration.classKind
|
||||||
|
if (classKind == ClassKind.ANNOTATION_CLASS || classKind == ClassKind.ENUM_CLASS) return
|
||||||
|
|
||||||
|
val typeCheckerContext = context.session.typeContext.newBaseTypeCheckerContext(
|
||||||
|
errorTypesEqualToAnything = false,
|
||||||
|
stubTypesEqualToAnything = false
|
||||||
|
)
|
||||||
|
val classScope = declaration.unsubstitutedScope(context)
|
||||||
|
val dedupReporter = reporter.deduplicating()
|
||||||
|
|
||||||
|
fun checkSymbol(symbol: FirCallableSymbol<*>) {
|
||||||
|
if (symbol.callableId.classId != declaration.classId) return
|
||||||
|
if (symbol !is FirIntersectionCallableSymbol) return
|
||||||
|
val withTypes = symbol.intersections.map {
|
||||||
|
it.fir to context.returnTypeCalculator.tryCalculateReturnType(it.fir).coneType
|
||||||
|
}
|
||||||
|
|
||||||
|
if (withTypes.any { it.second is ConeKotlinErrorType }) return
|
||||||
|
|
||||||
|
var delegation: FirCallableDeclaration<*>? = null
|
||||||
|
val implementations = mutableListOf<FirCallableDeclaration<*>>()
|
||||||
|
|
||||||
|
for (intSymbol in symbol.intersections) {
|
||||||
|
val fir = intSymbol.fir
|
||||||
|
if (fir.delegatedWrapperData?.containingClass?.classId == declaration.classId) {
|
||||||
|
delegation = fir
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (!(fir as FirCallableMemberDeclaration<*>).isAbstract) {
|
||||||
|
implementations.add(fir)
|
||||||
|
}
|
||||||
|
// val type = context.returnTypeCalculator.tryCalculateReturnType(intSymbol.fir).coneType
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delegation != null || implementations.isNotEmpty()) {
|
||||||
|
//if there are more than one implementation we report nothing because it will be reported differently
|
||||||
|
val method = delegation ?: implementations.singleOrNull() ?: return
|
||||||
|
val methodType = context.returnTypeCalculator.tryCalculateReturnType(method).coneType
|
||||||
|
val (conflict, _) = withTypes.find { (_, type) ->
|
||||||
|
!AbstractTypeChecker.isSubtypeOf(typeCheckerContext, methodType, type)
|
||||||
|
} ?: return
|
||||||
|
dedupReporter.reportOn(source, FirErrors.RETURN_TYPE_MISMATCH_ON_INHERITANCE, declaration, method, conflict, context)
|
||||||
|
} else {
|
||||||
|
//if there is no implementation, check that there can be any type compatible (subtype of) with all
|
||||||
|
var clash: Pair<FirCallableDeclaration<*>, FirCallableDeclaration<*>>? = null
|
||||||
|
val compatible = withTypes.any { (m1, type1) ->
|
||||||
|
withTypes.all { (m2, type2) ->
|
||||||
|
val result = AbstractTypeChecker.isSubtypeOf(typeCheckerContext, type1, type2)
|
||||||
|
if (!result && clash == null && !AbstractTypeChecker.isSubtypeOf(typeCheckerContext, type2, type1)) {
|
||||||
|
clash = m1 to m2
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clash?.takeIf { !compatible }?.let { (m1, m2) ->
|
||||||
|
dedupReporter.reportOn(source, FirErrors.RETURN_TYPE_MISMATCH_ON_INHERITANCE, declaration, m1, m2, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (name in classScope.getCallableNames()) {
|
||||||
|
classScope.processFunctionsByName(name, ::checkSymbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.diagnostics.impl
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.AbstractFirDiagnosticFactory
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
|
||||||
|
|
||||||
|
class DeduplicatingDiagnosticReporter(private val inner: DiagnosticReporter) : DiagnosticReporter() {
|
||||||
|
|
||||||
|
private val reported = mutableSetOf<Pair<FirSourceElement, AbstractFirDiagnosticFactory>>()
|
||||||
|
|
||||||
|
override fun report(diagnostic: FirDiagnostic?, context: CheckerContext) {
|
||||||
|
if (diagnostic != null && reported.add(Pair(diagnostic.element, diagnostic.factory))) {
|
||||||
|
inner.report(diagnostic, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun DiagnosticReporter.deduplicating(): DeduplicatingDiagnosticReporter = DeduplicatingDiagnosticReporter(this)
|
||||||
+4
-4
@@ -10,9 +10,9 @@ interface Three {
|
|||||||
public fun foo(): String
|
public fun foo(): String
|
||||||
}
|
}
|
||||||
|
|
||||||
<!MANY_IMPL_MEMBER_NOT_IMPLEMENTED!>class Test123<!>(val v1: One, val v2: Two, val v3: Three) : One by v1, Two by v2, Three by v3 { }
|
<!MANY_IMPL_MEMBER_NOT_IMPLEMENTED, RETURN_TYPE_MISMATCH_ON_INHERITANCE!>class Test123<!>(val v1: One, val v2: Two, val v3: Three) : One by v1, Two by v2, Three by v3 { }
|
||||||
<!MANY_IMPL_MEMBER_NOT_IMPLEMENTED!>class Test132<!>(val v1: One, val v2: Two, val v3: Three) : One by v1, Three by v3, Two by v2 { }
|
<!MANY_IMPL_MEMBER_NOT_IMPLEMENTED, RETURN_TYPE_MISMATCH_ON_INHERITANCE!>class Test132<!>(val v1: One, val v2: Two, val v3: Three) : One by v1, Three by v3, Two by v2 { }
|
||||||
<!MANY_IMPL_MEMBER_NOT_IMPLEMENTED!>class Test312<!>(val v1: One, val v2: Two, val v3: Three) : Three by v3, One by v1, Two by v2 { }
|
<!MANY_IMPL_MEMBER_NOT_IMPLEMENTED!>class Test312<!>(val v1: One, val v2: Two, val v3: Three) : Three by v3, One by v1, Two by v2 { }
|
||||||
<!MANY_IMPL_MEMBER_NOT_IMPLEMENTED!>class Test321<!>(val v1: One, val v2: Two, val v3: Three) : Three by v3, Two by v2, One by v1 { }
|
<!MANY_IMPL_MEMBER_NOT_IMPLEMENTED!>class Test321<!>(val v1: One, val v2: Two, val v3: Three) : Three by v3, Two by v2, One by v1 { }
|
||||||
<!MANY_IMPL_MEMBER_NOT_IMPLEMENTED!>class Test231<!>(val v1: One, val v2: Two, val v3: Three) : Two by v2, Three by v3, One by v1 { }
|
<!MANY_IMPL_MEMBER_NOT_IMPLEMENTED, RETURN_TYPE_MISMATCH_ON_INHERITANCE!>class Test231<!>(val v1: One, val v2: Two, val v3: Three) : Two by v2, Three by v3, One by v1 { }
|
||||||
<!MANY_IMPL_MEMBER_NOT_IMPLEMENTED!>class Test213<!>(val v1: One, val v2: Two, val v3: Three) : Two by v2, One by v1, Three by v3 { }
|
<!MANY_IMPL_MEMBER_NOT_IMPLEMENTED, RETURN_TYPE_MISMATCH_ON_INHERITANCE!>class Test213<!>(val v1: One, val v2: Two, val v3: Three) : Two by v2, One by v1, Three by v3 { }
|
||||||
|
|||||||
+8
-8
@@ -32,28 +32,28 @@ class CGeneric<T> : IGeneric<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Test1 : IStr by CStr(), IInt
|
abstract <!RETURN_TYPE_MISMATCH_ON_INHERITANCE!>class Test1<!> : IStr by CStr(), IInt
|
||||||
|
|
||||||
abstract class Test2 : IStr, IInt by CInt()
|
abstract <!RETURN_TYPE_MISMATCH_ON_INHERITANCE!>class Test2<!> : IStr, IInt by CInt()
|
||||||
|
|
||||||
abstract <!MANY_IMPL_MEMBER_NOT_IMPLEMENTED!>class Test3<!> : IStr by CStr(), IInt by CInt()
|
abstract <!MANY_IMPL_MEMBER_NOT_IMPLEMENTED, RETURN_TYPE_MISMATCH_ON_INHERITANCE!>class Test3<!> : IStr by CStr(), IInt by CInt()
|
||||||
|
|
||||||
abstract class Test4 : IStr by CStr(), IGeneric<String>
|
abstract class Test4 : IStr by CStr(), IGeneric<String>
|
||||||
|
|
||||||
abstract class Test5 : IStr by CStr(), IGeneric<Any>
|
abstract class Test5 : IStr by CStr(), IGeneric<Any>
|
||||||
|
|
||||||
abstract class Test6 : IStr by CStr(), IGeneric<Int>
|
abstract <!RETURN_TYPE_MISMATCH_ON_INHERITANCE!>class Test6<!> : IStr by CStr(), IGeneric<Int>
|
||||||
|
|
||||||
abstract class Test7 : IGeneric<String> by CGeneric<String>(), IStr
|
abstract class Test7 : IGeneric<String> by CGeneric<String>(), IStr
|
||||||
|
|
||||||
abstract class Test8 : IGeneric<String> by CGeneric<String>(), IInt
|
abstract <!RETURN_TYPE_MISMATCH_ON_INHERITANCE!>class Test8<!> : IGeneric<String> by CGeneric<String>(), IInt
|
||||||
|
|
||||||
// Can't test due to https://youtrack.jetbrains.com/issue/KT-10258
|
// Can't test due to https://youtrack.jetbrains.com/issue/KT-10258
|
||||||
// abstract class Test9 : IGeneric<String> by CGeneric<String>(), IGeneric<Int>
|
// abstract class Test9 : IGeneric<String> by CGeneric<String>(), IGeneric<Int>
|
||||||
|
|
||||||
abstract <!MANY_IMPL_MEMBER_NOT_IMPLEMENTED!>class Test10<!> : IInt by CInt(), IStr by CStr(), IAny by CAny()
|
abstract <!MANY_IMPL_MEMBER_NOT_IMPLEMENTED, RETURN_TYPE_MISMATCH_ON_INHERITANCE!>class Test10<!> : IInt by CInt(), IStr by CStr(), IAny by CAny()
|
||||||
|
|
||||||
abstract <!MANY_IMPL_MEMBER_NOT_IMPLEMENTED!>class Test11<!> : IInt, IStr by CStr(), IAny by CAny()
|
abstract <!MANY_IMPL_MEMBER_NOT_IMPLEMENTED, RETURN_TYPE_MISMATCH_ON_INHERITANCE!>class Test11<!> : IInt, IStr by CStr(), IAny by CAny()
|
||||||
|
|
||||||
abstract class Test12 : IInt, IStr, IAny by CAny()
|
abstract <!RETURN_TYPE_MISMATCH_ON_INHERITANCE!>class Test12<!> : IInt, IStr, IAny by CAny()
|
||||||
|
|
||||||
|
|||||||
Vendored
-37
@@ -1,37 +0,0 @@
|
|||||||
interface IBase {
|
|
||||||
fun copy(): IBase
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ILeft : IBase {
|
|
||||||
override fun copy(): ILeft
|
|
||||||
}
|
|
||||||
|
|
||||||
open class CLeft : ILeft {
|
|
||||||
override fun copy(): ILeft = CLeft()
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IRight : IBase {
|
|
||||||
override fun copy(): IRight
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IDerived : ILeft, IRight {
|
|
||||||
override fun copy(): IDerived
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error: ILeft::copy and IRight::copy have unrelated return types
|
|
||||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class CDerivedInvalid1<!> : ILeft, IRight
|
|
||||||
|
|
||||||
// Error: CLeft::copy and IRight::copy have unrelated return types
|
|
||||||
class CDerivedInvalid2 : CLeft(), IRight
|
|
||||||
|
|
||||||
// OK: CDerived1::copy overrides both ILeft::copy and IRight::copy
|
|
||||||
class CDerived1 : ILeft, IRight {
|
|
||||||
override fun copy(): CDerived1 = CDerived1()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Although ILeft::copy and IRight::copy return types are unrelated, IDerived::copy return type is the most specific of three.
|
|
||||||
abstract class CDerived2 : ILeft, IRight, IDerived
|
|
||||||
|
|
||||||
class CDerived2a : ILeft, IRight, IDerived {
|
|
||||||
override fun copy(): IDerived = CDerived2a()
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
interface IBase {
|
interface IBase {
|
||||||
fun copy(): IBase
|
fun copy(): IBase
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
-43
@@ -1,43 +0,0 @@
|
|||||||
// FILE: J.java
|
|
||||||
public interface J {
|
|
||||||
java.util.List<String> foo();
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: K.kt
|
|
||||||
interface ILNS {
|
|
||||||
fun foo(): List<String?>
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IMLS {
|
|
||||||
fun foo(): MutableList<String>
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IMLNS {
|
|
||||||
fun foo(): MutableList<String?>
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ILS {
|
|
||||||
fun foo(): List<String>
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Test1 : ILNS, J
|
|
||||||
interface Test2 : J, ILNS
|
|
||||||
|
|
||||||
interface Test3 : IMLS, J
|
|
||||||
interface Test4 : J, IMLS
|
|
||||||
|
|
||||||
interface Test5 : ILNS, IMLS, J
|
|
||||||
interface Test6 : ILNS, J, IMLS
|
|
||||||
interface Test7 : J, ILNS, IMLS
|
|
||||||
|
|
||||||
// Return types of ILS::foo and IMLNS::foo are incompatible themselves.
|
|
||||||
// However, return type of J::foo is (Mutable)List<String!>!,
|
|
||||||
// which is subtype of both List<String> and MutalbeList<String?>.
|
|
||||||
// Thus, inheriting from J, IMLNS, and ILS is Ok,
|
|
||||||
// but inheriting from IMLNS and ILS is not.
|
|
||||||
|
|
||||||
interface Test8 : J, IMLNS, ILS
|
|
||||||
interface Test9 : IMLNS, J, ILS
|
|
||||||
interface Test10 : IMLNS, ILS, J
|
|
||||||
|
|
||||||
interface Test11 : IMLNS, ILS
|
|
||||||
Vendored
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// FILE: J.java
|
// FILE: J.java
|
||||||
public interface J {
|
public interface J {
|
||||||
java.util.List<String> foo();
|
java.util.List<String> foo();
|
||||||
|
|||||||
-47
@@ -1,47 +0,0 @@
|
|||||||
// FILE: K.kt
|
|
||||||
abstract class ATest1 : TestNN.JNullVsNotNull()
|
|
||||||
|
|
||||||
abstract class ATest2 : TestNN.JUnknownImpl(), TestNN.JNotNull
|
|
||||||
|
|
||||||
abstract class ATest3 : TestNN.JUnknownVsNotNull()
|
|
||||||
|
|
||||||
class CTest1 : TestNN.JNullVsNotNull()
|
|
||||||
|
|
||||||
class CTest2 : TestNN.JUnknownImpl(), TestNN.JNotNull
|
|
||||||
|
|
||||||
class CTest3 : TestNN.JUnknownVsNotNull()
|
|
||||||
|
|
||||||
// FILE: TestNN.java
|
|
||||||
import org.jetbrains.annotations.*;
|
|
||||||
|
|
||||||
public class TestNN {
|
|
||||||
public interface JNull {
|
|
||||||
@Nullable Object foo();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface JNotNull {
|
|
||||||
@NotNull Object foo();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class JNullVsNotNull implements JNull, JNotNull {
|
|
||||||
public Object foo() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class JNullBase {
|
|
||||||
@Nullable public Object foo() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class JUnknownImpl extends JNullBase {
|
|
||||||
public Object foo() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class JUnknownVsNotNull extends JUnknownImpl implements JNotNull {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// FILE: K.kt
|
// FILE: K.kt
|
||||||
abstract class ATest1 : TestNN.JNullVsNotNull()
|
abstract class ATest1 : TestNN.JNullVsNotNull()
|
||||||
|
|
||||||
|
|||||||
Vendored
-29
@@ -1,29 +0,0 @@
|
|||||||
open class A {
|
|
||||||
open fun foo(): Boolean = true
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IA {
|
|
||||||
fun foo(): String
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IAA {
|
|
||||||
fun foo(): Int
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IGA<T> {
|
|
||||||
fun foo(): T
|
|
||||||
}
|
|
||||||
|
|
||||||
class B1: A(), IA
|
|
||||||
|
|
||||||
class B2: A(), IA, IAA
|
|
||||||
|
|
||||||
abstract class B3: IA, IAA
|
|
||||||
|
|
||||||
class BS1: A(), IGA<Boolean>
|
|
||||||
|
|
||||||
class BS2: A(), IGA<Any>
|
|
||||||
|
|
||||||
class BS3: A(), IGA<String>
|
|
||||||
|
|
||||||
class BG1<T>: A(), IGA<T>
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
open class A {
|
open class A {
|
||||||
open fun foo(): Boolean = true
|
open fun foo(): Boolean = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
interface A {
|
|
||||||
fun f(): String
|
|
||||||
}
|
|
||||||
|
|
||||||
open class B {
|
|
||||||
open fun f(): CharSequence = "charSequence"
|
|
||||||
}
|
|
||||||
|
|
||||||
class C : B(), A
|
|
||||||
|
|
||||||
val d: A = object : B(), A {}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
interface A {
|
interface A {
|
||||||
fun f(): String
|
fun f(): String
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+1
-1
@@ -20624,7 +20624,7 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt13355viaJava.kt")
|
@TestMetadata("kt13355viaJava.kt")
|
||||||
public void testKt13355viaJava() throws Exception {
|
public void testKt13355viaJava1111() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/override/clashesOnInheritance/kt13355viaJava.kt");
|
runTest("compiler/testData/diagnostics/tests/override/clashesOnInheritance/kt13355viaJava.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
@@ -1652,6 +1652,15 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.RETURN_TYPE_MISMATCH_ON_INHERITANCE) { firDiagnostic ->
|
||||||
|
ReturnTypeMismatchOnInheritanceImpl(
|
||||||
|
firSymbolBuilder.classifierBuilder.buildClassLikeSymbol(firDiagnostic.a),
|
||||||
|
firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.b as FirCallableDeclaration),
|
||||||
|
firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.c as FirCallableDeclaration),
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.ABSTRACT_MEMBER_NOT_IMPLEMENTED) { firDiagnostic ->
|
add(FirErrors.ABSTRACT_MEMBER_NOT_IMPLEMENTED) { firDiagnostic ->
|
||||||
AbstractMemberNotImplementedImpl(
|
AbstractMemberNotImplementedImpl(
|
||||||
firSymbolBuilder.classifierBuilder.buildClassLikeSymbol(firDiagnostic.a),
|
firSymbolBuilder.classifierBuilder.buildClassLikeSymbol(firDiagnostic.a),
|
||||||
|
|||||||
+7
@@ -1171,6 +1171,13 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
abstract val containingClassName: Name
|
abstract val containingClassName: Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class ReturnTypeMismatchOnInheritance : KtFirDiagnostic<KtClassOrObject>() {
|
||||||
|
override val diagnosticClass get() = ReturnTypeMismatchOnInheritance::class
|
||||||
|
abstract val classOrObject: KtClassLikeSymbol
|
||||||
|
abstract val conflictingDeclaration1: KtCallableSymbol
|
||||||
|
abstract val conflictingDeclaration2: KtCallableSymbol
|
||||||
|
}
|
||||||
|
|
||||||
abstract class AbstractMemberNotImplemented : KtFirDiagnostic<KtClassOrObject>() {
|
abstract class AbstractMemberNotImplemented : KtFirDiagnostic<KtClassOrObject>() {
|
||||||
override val diagnosticClass get() = AbstractMemberNotImplemented::class
|
override val diagnosticClass get() = AbstractMemberNotImplemented::class
|
||||||
abstract val classOrObject: KtClassLikeSymbol
|
abstract val classOrObject: KtClassLikeSymbol
|
||||||
|
|||||||
+10
@@ -1883,6 +1883,16 @@ internal class OverridingFinalMemberImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class ReturnTypeMismatchOnInheritanceImpl(
|
||||||
|
override val classOrObject: KtClassLikeSymbol,
|
||||||
|
override val conflictingDeclaration1: KtCallableSymbol,
|
||||||
|
override val conflictingDeclaration2: KtCallableSymbol,
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.ReturnTypeMismatchOnInheritance(), KtAbstractFirDiagnostic<KtClassOrObject> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
internal class AbstractMemberNotImplementedImpl(
|
internal class AbstractMemberNotImplementedImpl(
|
||||||
override val classOrObject: KtClassLikeSymbol,
|
override val classOrObject: KtClassLikeSymbol,
|
||||||
override val missingDeclaration: KtCallableSymbol,
|
override val missingDeclaration: KtCallableSymbol,
|
||||||
|
|||||||
Reference in New Issue
Block a user