[FIR] Implement warnings for java nullability type mismatch on override
#KT-56989
This commit is contained in:
committed by
Space Team
parent
a6fdeeb7df
commit
2df1e9dde6
+8
@@ -5025,6 +5025,14 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirJvmErrors.WRONG_NULLABILITY_FOR_JAVA_OVERRIDE) { firDiagnostic ->
|
||||||
|
WrongNullabilityForJavaOverrideImpl(
|
||||||
|
firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a),
|
||||||
|
firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.b),
|
||||||
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirJvmErrors.JAVA_TYPE_MISMATCH) { firDiagnostic ->
|
add(FirJvmErrors.JAVA_TYPE_MISMATCH) { firDiagnostic ->
|
||||||
JavaTypeMismatchImpl(
|
JavaTypeMismatchImpl(
|
||||||
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||||
|
|||||||
+6
@@ -3495,6 +3495,12 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = JvmInlineWithoutValueClass::class
|
override val diagnosticClass get() = JvmInlineWithoutValueClass::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface WrongNullabilityForJavaOverride : KtFirDiagnostic<PsiElement> {
|
||||||
|
override val diagnosticClass get() = WrongNullabilityForJavaOverride::class
|
||||||
|
val override: KtCallableSymbol
|
||||||
|
val base: KtCallableSymbol
|
||||||
|
}
|
||||||
|
|
||||||
interface JavaTypeMismatch : KtFirDiagnostic<KtExpression> {
|
interface JavaTypeMismatch : KtFirDiagnostic<KtExpression> {
|
||||||
override val diagnosticClass get() = JavaTypeMismatch::class
|
override val diagnosticClass get() = JavaTypeMismatch::class
|
||||||
val expectedType: KtType
|
val expectedType: KtType
|
||||||
|
|||||||
+7
@@ -4217,6 +4217,13 @@ internal class JvmInlineWithoutValueClassImpl(
|
|||||||
token: KtLifetimeToken,
|
token: KtLifetimeToken,
|
||||||
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.JvmInlineWithoutValueClass
|
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.JvmInlineWithoutValueClass
|
||||||
|
|
||||||
|
internal class WrongNullabilityForJavaOverrideImpl(
|
||||||
|
override val override: KtCallableSymbol,
|
||||||
|
override val base: KtCallableSymbol,
|
||||||
|
firDiagnostic: KtPsiDiagnostic,
|
||||||
|
token: KtLifetimeToken,
|
||||||
|
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.WrongNullabilityForJavaOverride
|
||||||
|
|
||||||
internal class JavaTypeMismatchImpl(
|
internal class JavaTypeMismatchImpl(
|
||||||
override val expectedType: KtType,
|
override val expectedType: KtType,
|
||||||
override val actualType: KtType,
|
override val actualType: KtType,
|
||||||
|
|||||||
+5
@@ -39,6 +39,11 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") {
|
|||||||
|
|
||||||
val VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION by error<PsiElement>()
|
val VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION by error<PsiElement>()
|
||||||
val JVM_INLINE_WITHOUT_VALUE_CLASS by error<PsiElement>()
|
val JVM_INLINE_WITHOUT_VALUE_CLASS by error<PsiElement>()
|
||||||
|
|
||||||
|
val WRONG_NULLABILITY_FOR_JAVA_OVERRIDE by warning<PsiElement>(PositioningStrategy.OVERRIDE_MODIFIER) {
|
||||||
|
parameter<FirCallableSymbol<*>>("override")
|
||||||
|
parameter<FirCallableSymbol<*>>("base")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val TYPES by object : DiagnosticGroup("Types") {
|
val TYPES by object : DiagnosticGroup("Types") {
|
||||||
|
|||||||
+1
@@ -41,6 +41,7 @@ object FirJvmErrors {
|
|||||||
val FUNCTION_DELEGATE_MEMBER_NAME_CLASH by error0<PsiElement>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
val FUNCTION_DELEGATE_MEMBER_NAME_CLASH by error0<PsiElement>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||||
val VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION by error0<PsiElement>()
|
val VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION by error0<PsiElement>()
|
||||||
val JVM_INLINE_WITHOUT_VALUE_CLASS by error0<PsiElement>()
|
val JVM_INLINE_WITHOUT_VALUE_CLASS by error0<PsiElement>()
|
||||||
|
val WRONG_NULLABILITY_FOR_JAVA_OVERRIDE by warning2<PsiElement, FirCallableSymbol<*>, FirCallableSymbol<*>>(SourceElementPositioningStrategies.OVERRIDE_MODIFIER)
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
val JAVA_TYPE_MISMATCH by error2<KtExpression, ConeKotlinType, ConeKotlinType>()
|
val JAVA_TYPE_MISMATCH by error2<KtExpression, ConeKotlinType, ConeKotlinType>()
|
||||||
|
|||||||
+9
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
|
|||||||
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING
|
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.DECLARATION_NAME
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.DECLARATION_NAME
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_TYPE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_TYPE
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOL
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.CONCURRENT_HASH_MAP_CONTAINS_OPERATOR
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.CONCURRENT_HASH_MAP_CONTAINS_OPERATOR
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.DELEGATION_BY_IN_JVM_RECORD
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.DELEGATION_BY_IN_JVM_RECORD
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.DEPRECATED_JAVA_ANNOTATION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.DEPRECATED_JAVA_ANNOTATION
|
||||||
@@ -80,6 +81,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZ
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZED_ON_SUSPEND
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZED_ON_SUSPEND
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.UPPER_BOUND_CANNOT_BE_ARRAY
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.UPPER_BOUND_CANNOT_BE_ARRAY
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.WRONG_NULLABILITY_FOR_JAVA_OVERRIDE
|
||||||
|
|
||||||
object FirJvmErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
object FirJvmErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||||
|
|
||||||
@@ -99,6 +101,13 @@ object FirJvmErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
|||||||
NOT_RENDERED
|
NOT_RENDERED
|
||||||
)
|
)
|
||||||
|
|
||||||
|
map.put(
|
||||||
|
WRONG_NULLABILITY_FOR_JAVA_OVERRIDE,
|
||||||
|
"Override ''{0}'' has incorrect nullability in its signature compared to the overridden declaration ''{1}''.",
|
||||||
|
SYMBOL,
|
||||||
|
SYMBOL,
|
||||||
|
)
|
||||||
|
|
||||||
map.put(UPPER_BOUND_CANNOT_BE_ARRAY, "Upper bound of type parameter cannot be an array.")
|
map.put(UPPER_BOUND_CANNOT_BE_ARRAY, "Upper bound of type parameter cannot be an array.")
|
||||||
map.put(STRICTFP_ON_CLASS, "'@Strictfp' annotation on classes is not yet supported.")
|
map.put(STRICTFP_ON_CLASS, "'@Strictfp' annotation on classes is not yet supported.")
|
||||||
map.put(SYNCHRONIZED_ON_ABSTRACT, "'@Synchronized' annotation cannot be used on abstract functions.")
|
map.put(SYNCHRONIZED_ON_ABSTRACT, "'@Synchronized' annotation cannot be used on abstract functions.")
|
||||||
|
|||||||
+2
-1
@@ -23,7 +23,8 @@ object JvmDeclarationCheckers : DeclarationCheckers() {
|
|||||||
|
|
||||||
override val classCheckers: Set<FirClassChecker>
|
override val classCheckers: Set<FirClassChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirStrictfpApplicabilityChecker
|
FirStrictfpApplicabilityChecker,
|
||||||
|
FirOverrideJavaNullabilityWarningChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val regularClassCheckers: Set<FirRegularClassChecker>
|
override val regularClassCheckers: Set<FirRegularClassChecker>
|
||||||
|
|||||||
+163
@@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* 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.jvm.checkers.declaration
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirAbstractOverrideChecker
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.java.enhancement.EnhancedForWarningConeSubstitutor
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.firOverrideChecker
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenProperties
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
|
import org.jetbrains.kotlin.fir.types.typeContext
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||||
|
|
||||||
|
object FirOverrideJavaNullabilityWarningChecker : FirAbstractOverrideChecker() {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
val substitutor = EnhancedForWarningConeSubstitutor(context.session.typeContext)
|
||||||
|
val scope = declaration.unsubstitutedScope(context)
|
||||||
|
val typeCheckerState = context.session.typeContext.newTypeCheckerState(
|
||||||
|
errorTypesEqualToAnything = false,
|
||||||
|
stubTypesEqualToAnything = false
|
||||||
|
)
|
||||||
|
|
||||||
|
for (member in declaration.declarations) {
|
||||||
|
var anyBaseEnhanced = false
|
||||||
|
|
||||||
|
if (member is FirSimpleFunction) {
|
||||||
|
val enhancedOverrides = scope
|
||||||
|
.getDirectOverriddenFunctions(member.symbol)
|
||||||
|
.map {
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
val substitutedBase = it.fir.substituteOrNull(substitutor, context) ?: return@map it
|
||||||
|
anyBaseEnhanced = true
|
||||||
|
|
||||||
|
if (!context.session.firOverrideChecker.isOverriddenFunction(member, substitutedBase)) {
|
||||||
|
reporter.reportOn(
|
||||||
|
member.source,
|
||||||
|
FirJvmErrors.WRONG_NULLABILITY_FOR_JAVA_OVERRIDE,
|
||||||
|
member.symbol,
|
||||||
|
substitutedBase.symbol,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
substitutedBase.symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anyBaseEnhanced) {
|
||||||
|
member.symbol.checkReturnType(enhancedOverrides, typeCheckerState, context)?.let {
|
||||||
|
reporter.reportOn(
|
||||||
|
member.source, FirJvmErrors.WRONG_NULLABILITY_FOR_JAVA_OVERRIDE, member.symbol, it, context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (member is FirProperty) {
|
||||||
|
val enhancedOverrides = scope
|
||||||
|
.getDirectOverriddenProperties(member.symbol)
|
||||||
|
.map {
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
|
val substitutedBase = it.fir.substituteOrNull(substitutor, context) ?: return@map it
|
||||||
|
anyBaseEnhanced = true
|
||||||
|
|
||||||
|
if (!context.session.firOverrideChecker.isOverriddenProperty(member, substitutedBase)) {
|
||||||
|
reporter.reportOn(
|
||||||
|
member.source,
|
||||||
|
FirJvmErrors.WRONG_NULLABILITY_FOR_JAVA_OVERRIDE,
|
||||||
|
member.symbol,
|
||||||
|
substitutedBase.symbol,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
substitutedBase.symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anyBaseEnhanced) {
|
||||||
|
member.symbol.checkReturnType(enhancedOverrides, typeCheckerState, context)?.let {
|
||||||
|
reporter.reportOn(
|
||||||
|
member.source, FirJvmErrors.WRONG_NULLABILITY_FOR_JAVA_OVERRIDE, member.symbol, it, context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope.createSubstitutionOverrideFunction
|
||||||
|
* @see org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope.createSubstitutedData
|
||||||
|
*/
|
||||||
|
private fun FirSimpleFunction.substituteOrNull(
|
||||||
|
substitutor: EnhancedForWarningConeSubstitutor,
|
||||||
|
context: CheckerContext,
|
||||||
|
): FirSimpleFunction? {
|
||||||
|
symbol.lazyResolveToPhase(FirResolvePhase.TYPES)
|
||||||
|
var isEnhanced = false
|
||||||
|
|
||||||
|
val newParameterTypes = valueParameters.map { substitutor.substituteOrNull(it.returnTypeRef.coneType)?.also { isEnhanced = true } }
|
||||||
|
val newContextReceiverTypes = contextReceivers.map { substitutor.substituteOrNull(it.typeRef.coneType)?.also { isEnhanced = true } }
|
||||||
|
val newReturnType = substitutor.substituteOrNull(context.returnTypeCalculator.tryCalculateReturnType(this).coneType)?.also { isEnhanced = true }
|
||||||
|
val newExtensionReceiverType =
|
||||||
|
receiverParameter?.typeRef?.coneType?.let { substitutor.substituteOrNull(it) }?.also { isEnhanced = true }
|
||||||
|
|
||||||
|
return runIf(isEnhanced) {
|
||||||
|
FirFakeOverrideGenerator.createCopyForFirFunction(
|
||||||
|
FirFakeOverrideGenerator.createSymbolForSubstitutionOverride(symbol),
|
||||||
|
this,
|
||||||
|
null,
|
||||||
|
context.session,
|
||||||
|
FirDeclarationOrigin.Enhancement,
|
||||||
|
newDispatchReceiverType = null,
|
||||||
|
newParameterTypes = newParameterTypes,
|
||||||
|
newReturnType = newReturnType,
|
||||||
|
newContextReceiverTypes = newContextReceiverTypes,
|
||||||
|
newReceiverType = newExtensionReceiverType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope.createSubstitutionOverrideProperty
|
||||||
|
* @see org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope.createSubstitutedData
|
||||||
|
*/
|
||||||
|
private fun FirProperty.substituteOrNull(
|
||||||
|
substitutor: EnhancedForWarningConeSubstitutor,
|
||||||
|
context: CheckerContext,
|
||||||
|
): FirProperty? {
|
||||||
|
if (!isJavaOrEnhancement) return null
|
||||||
|
symbol.lazyResolveToPhase(FirResolvePhase.TYPES)
|
||||||
|
var isEnhanced = false
|
||||||
|
|
||||||
|
val newContextReceiverTypes = contextReceivers.map { substitutor.substituteOrNull(it.typeRef.coneType)?.also { isEnhanced = true } }
|
||||||
|
val newReturnType = substitutor.substituteOrNull(context.returnTypeCalculator.tryCalculateReturnType(this).coneType)?.also { isEnhanced = true }
|
||||||
|
val newExtensionReceiverType =
|
||||||
|
receiverParameter?.typeRef?.coneType?.let { substitutor.substituteOrNull(it) }?.also { isEnhanced = true }
|
||||||
|
|
||||||
|
return runIf(isEnhanced) {
|
||||||
|
FirFakeOverrideGenerator.createCopyForFirProperty(
|
||||||
|
FirFakeOverrideGenerator.createSymbolForSubstitutionOverride(symbol),
|
||||||
|
this,
|
||||||
|
null,
|
||||||
|
context.session,
|
||||||
|
FirDeclarationOrigin.Enhancement,
|
||||||
|
newDispatchReceiverType = null,
|
||||||
|
newReturnType = newReturnType,
|
||||||
|
newContextReceiverTypes = newContextReceiverTypes,
|
||||||
|
newReceiverType = newExtensionReceiverType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+53
-51
@@ -42,23 +42,7 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
|||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
import org.jetbrains.kotlin.types.TypeCheckerState
|
import org.jetbrains.kotlin.types.TypeCheckerState
|
||||||
|
|
||||||
object FirOverrideChecker : FirClassChecker() {
|
abstract class FirAbstractOverrideChecker : FirClassChecker() {
|
||||||
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
|
||||||
val typeCheckerState = context.session.typeContext.newTypeCheckerState(
|
|
||||||
errorTypesEqualToAnything = false,
|
|
||||||
stubTypesEqualToAnything = false
|
|
||||||
)
|
|
||||||
|
|
||||||
val firTypeScope = declaration.unsubstitutedScope(context)
|
|
||||||
|
|
||||||
for (it in declaration.declarations) {
|
|
||||||
if (it is FirSimpleFunction || it is FirProperty) {
|
|
||||||
val callable = it as FirCallableDeclaration
|
|
||||||
checkMember(callable.symbol, declaration, reporter, typeCheckerState, firTypeScope, context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ConeKotlinType.substituteAllTypeParameters(
|
private fun ConeKotlinType.substituteAllTypeParameters(
|
||||||
overrideDeclaration: FirCallableSymbol<*>,
|
overrideDeclaration: FirCallableSymbol<*>,
|
||||||
baseDeclaration: FirCallableSymbol<*>,
|
baseDeclaration: FirCallableSymbol<*>,
|
||||||
@@ -84,6 +68,58 @@ object FirOverrideChecker : FirClassChecker() {
|
|||||||
return substitutorByMap(map, context.session).substituteOrSelf(this)
|
return substitutorByMap(map, context.session).substituteOrSelf(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See [OverrideResolver#isReturnTypeOkForOverride]
|
||||||
|
protected fun FirCallableSymbol<*>.checkReturnType(
|
||||||
|
overriddenSymbols: List<FirCallableSymbol<*>>,
|
||||||
|
typeCheckerState: TypeCheckerState,
|
||||||
|
context: CheckerContext,
|
||||||
|
): FirCallableSymbol<*>? {
|
||||||
|
val overridingReturnType = resolvedReturnTypeRef.coneType
|
||||||
|
|
||||||
|
// Don't report *_ON_OVERRIDE diagnostics according to an error return type. That should be reported separately.
|
||||||
|
if (overridingReturnType is ConeErrorType) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
val bounds = overriddenSymbols.map { context.returnTypeCalculator.tryCalculateReturnType(it).coneType }
|
||||||
|
|
||||||
|
for (it in bounds.indices) {
|
||||||
|
val overriddenDeclaration = overriddenSymbols[it]
|
||||||
|
|
||||||
|
val overriddenReturnType = bounds[it].substituteAllTypeParameters(this, overriddenDeclaration, context)
|
||||||
|
|
||||||
|
val isReturnTypeOkForOverride =
|
||||||
|
if (overriddenDeclaration is FirPropertySymbol && overriddenDeclaration.isVar)
|
||||||
|
AbstractTypeChecker.equalTypes(typeCheckerState, overridingReturnType, overriddenReturnType)
|
||||||
|
else
|
||||||
|
AbstractTypeChecker.isSubtypeOf(typeCheckerState, overridingReturnType, overriddenReturnType)
|
||||||
|
|
||||||
|
if (!isReturnTypeOkForOverride) {
|
||||||
|
return overriddenDeclaration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object FirOverrideChecker : FirAbstractOverrideChecker() {
|
||||||
|
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
val typeCheckerState = context.session.typeContext.newTypeCheckerState(
|
||||||
|
errorTypesEqualToAnything = false,
|
||||||
|
stubTypesEqualToAnything = false
|
||||||
|
)
|
||||||
|
|
||||||
|
val firTypeScope = declaration.unsubstitutedScope(context)
|
||||||
|
|
||||||
|
for (it in declaration.declarations) {
|
||||||
|
if (it is FirSimpleFunction || it is FirProperty) {
|
||||||
|
val callable = it as FirCallableDeclaration
|
||||||
|
checkMember(callable.symbol, declaration, reporter, typeCheckerState, firTypeScope, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun checkModality(
|
private fun checkModality(
|
||||||
overriddenSymbols: List<FirCallableSymbol<*>>,
|
overriddenSymbols: List<FirCallableSymbol<*>>,
|
||||||
): FirCallableSymbol<*>? {
|
): FirCallableSymbol<*>? {
|
||||||
@@ -185,40 +221,6 @@ object FirOverrideChecker : FirClassChecker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// See [OverrideResolver#isReturnTypeOkForOverride]
|
|
||||||
private fun FirCallableSymbol<*>.checkReturnType(
|
|
||||||
overriddenSymbols: List<FirCallableSymbol<*>>,
|
|
||||||
typeCheckerState: TypeCheckerState,
|
|
||||||
context: CheckerContext,
|
|
||||||
): FirCallableSymbol<*>? {
|
|
||||||
val overridingReturnType = resolvedReturnTypeRef.coneType
|
|
||||||
|
|
||||||
// Don't report *_ON_OVERRIDE diagnostics according to an error return type. That should be reported separately.
|
|
||||||
if (overridingReturnType is ConeErrorType) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
val bounds = overriddenSymbols.map { context.returnTypeCalculator.tryCalculateReturnType(it).coneType }
|
|
||||||
|
|
||||||
for (it in bounds.indices) {
|
|
||||||
val overriddenDeclaration = overriddenSymbols[it]
|
|
||||||
|
|
||||||
val overriddenReturnType = bounds[it].substituteAllTypeParameters(this, overriddenDeclaration, context)
|
|
||||||
|
|
||||||
val isReturnTypeOkForOverride =
|
|
||||||
if (overriddenDeclaration is FirPropertySymbol && overriddenDeclaration.isVar)
|
|
||||||
AbstractTypeChecker.equalTypes(typeCheckerState, overridingReturnType, overriddenReturnType)
|
|
||||||
else
|
|
||||||
AbstractTypeChecker.isSubtypeOf(typeCheckerState, overridingReturnType, overriddenReturnType)
|
|
||||||
|
|
||||||
if (!isReturnTypeOkForOverride) {
|
|
||||||
return overriddenDeclaration
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(SymbolInternals::class)
|
@OptIn(SymbolInternals::class)
|
||||||
private fun FirFunctionSymbol<*>.checkDefaultValues(
|
private fun FirFunctionSymbol<*>.checkDefaultValues(
|
||||||
reporter: DiagnosticReporter,
|
reporter: DiagnosticReporter,
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
compiler/testData/cli/jvm/jspecifyUsage.kt:2:11: warning: Java type mismatch: inferred type is 'kotlin/String', but 'kotlin/Nothing?' was expected.
|
compiler/testData/cli/jvm/jspecifyUsage.kt:2:11: warning: Java type mismatch: inferred type is 'kotlin.String', but 'kotlin.Nothing?' was expected.
|
||||||
a.foo(null)
|
a.foo(null)
|
||||||
^
|
^
|
||||||
compiler/testData/cli/jvm/jspecifyUsage.kt:3:5: warning: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type 'kotlin/String?'.
|
compiler/testData/cli/jvm/jspecifyUsage.kt:3:5: warning: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type 'kotlin.String?'.
|
||||||
a.bar().hashCode()
|
a.bar().hashCode()
|
||||||
^
|
^
|
||||||
OK
|
OK
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
warning: argument -Xjsr305-annotations is deprecated. Please use -Xjsr305 instead
|
warning: argument -Xjsr305-annotations is deprecated. Please use -Xjsr305 instead
|
||||||
compiler/testData/cli/jvm/jsr305Usage.kt:2:11: warning: Java type mismatch: inferred type is 'kotlin/String', but 'kotlin/Nothing?' was expected.
|
compiler/testData/cli/jvm/jsr305Usage.kt:2:11: warning: Java type mismatch: inferred type is 'kotlin.String', but 'kotlin.Nothing?' was expected.
|
||||||
a.foo(null)
|
a.foo(null)
|
||||||
^
|
^
|
||||||
OK
|
OK
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
compiler/testData/cli/jvm/jsr305Migration.kt:2:19: warning: Java type mismatch: inferred type is 'kotlin/String', but 'kotlin/Nothing?' was expected.
|
compiler/testData/cli/jvm/jsr305Migration.kt:2:19: warning: Java type mismatch: inferred type is 'kotlin.String', but 'kotlin.Nothing?' was expected.
|
||||||
annotated.foo(null)
|
annotated.foo(null)
|
||||||
^
|
^
|
||||||
compiler/testData/cli/jvm/jsr305Migration.kt:4:5: warning: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type 'kotlin/String?'.
|
compiler/testData/cli/jvm/jsr305Migration.kt:4:5: warning: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type 'kotlin.String?'.
|
||||||
annotated.nullable().length
|
annotated.nullable().length
|
||||||
^
|
^
|
||||||
OK
|
OK
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
compiler/testData/cli/jvm/jsr305Migration.kt:2:19: warning: Java type mismatch: inferred type is 'kotlin/String', but 'kotlin/Nothing?' was expected.
|
compiler/testData/cli/jvm/jsr305Migration.kt:2:19: warning: Java type mismatch: inferred type is 'kotlin.String', but 'kotlin.Nothing?' was expected.
|
||||||
annotated.foo(null)
|
annotated.foo(null)
|
||||||
^
|
^
|
||||||
compiler/testData/cli/jvm/jsr305Migration.kt:4:5: warning: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type 'kotlin/String?'.
|
compiler/testData/cli/jvm/jsr305Migration.kt:4:5: warning: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type 'kotlin.String?'.
|
||||||
annotated.nullable().length
|
annotated.nullable().length
|
||||||
^
|
^
|
||||||
OK
|
OK
|
||||||
|
|||||||
+3
-3
@@ -1,10 +1,10 @@
|
|||||||
compiler/testData/cli/jvm/jsr305Migration.kt:2:19: warning: Java type mismatch: inferred type is 'kotlin/String', but 'kotlin/Nothing?' was expected.
|
compiler/testData/cli/jvm/jsr305Migration.kt:2:19: warning: Java type mismatch: inferred type is 'kotlin.String', but 'kotlin.Nothing?' was expected.
|
||||||
annotated.foo(null)
|
annotated.foo(null)
|
||||||
^
|
^
|
||||||
compiler/testData/cli/jvm/jsr305Migration.kt:3:19: warning: Java type mismatch: inferred type is 'kotlin/String', but 'kotlin/Nothing?' was expected.
|
compiler/testData/cli/jvm/jsr305Migration.kt:3:19: warning: Java type mismatch: inferred type is 'kotlin.String', but 'kotlin.Nothing?' was expected.
|
||||||
annotated.bar(null)
|
annotated.bar(null)
|
||||||
^
|
^
|
||||||
compiler/testData/cli/jvm/jsr305Migration.kt:4:5: warning: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type 'kotlin/String?'.
|
compiler/testData/cli/jvm/jsr305Migration.kt:4:5: warning: only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type 'kotlin.String?'.
|
||||||
annotated.nullable().length
|
annotated.nullable().length
|
||||||
^
|
^
|
||||||
OK
|
OK
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
compiler/testData/cli/jvm/jsr305Usage.kt:2:11: warning: Java type mismatch: inferred type is 'kotlin/String', but 'kotlin/Nothing?' was expected.
|
compiler/testData/cli/jvm/jsr305Usage.kt:2:11: warning: Java type mismatch: inferred type is 'kotlin.String', but 'kotlin.Nothing?' was expected.
|
||||||
a.foo(null)
|
a.foo(null)
|
||||||
^
|
^
|
||||||
OK
|
OK
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
compiler/testData/cli/jvm/jsr305Usage.kt:2:11: warning: Java type mismatch: inferred type is 'kotlin/String', but 'kotlin/Nothing?' was expected.
|
compiler/testData/cli/jvm/jsr305Usage.kt:2:11: warning: Java type mismatch: inferred type is 'kotlin.String', but 'kotlin.Nothing?' was expected.
|
||||||
a.foo(null)
|
a.foo(null)
|
||||||
^
|
^
|
||||||
OK
|
OK
|
||||||
|
|||||||
+23
-9
@@ -17,6 +17,8 @@ public class BaseClass {
|
|||||||
public @Nullable Foo mixed(Foo x) { return null; }
|
public @Nullable Foo mixed(Foo x) { return null; }
|
||||||
|
|
||||||
public Foo explicitlyNullnessUnspecified(@NullnessUnspecified Foo x) { return null; }
|
public Foo explicitlyNullnessUnspecified(@NullnessUnspecified Foo x) { return null; }
|
||||||
|
|
||||||
|
public static Foo foo() { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -24,7 +26,11 @@ public class BaseClass {
|
|||||||
|
|
||||||
private val FOO = object : Foo {}
|
private val FOO = object : Foo {}
|
||||||
|
|
||||||
class Correct : BaseClass() {
|
open class IntermediateClass : BaseClass() {
|
||||||
|
open fun intermediateNotNull() = BaseClass.foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Correct : IntermediateClass() {
|
||||||
override fun everythingNotNullable(x: Foo): Foo {
|
override fun everythingNotNullable(x: Foo): Foo {
|
||||||
return FOO
|
return FOO
|
||||||
}
|
}
|
||||||
@@ -44,24 +50,32 @@ class Correct : BaseClass() {
|
|||||||
override fun explicitlyNullnessUnspecified(x: Foo): Foo {
|
override fun explicitlyNullnessUnspecified(x: Foo): Foo {
|
||||||
return FOO
|
return FOO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun intermediateNotNull(): Foo {
|
||||||
|
return FOO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WrongReturnTypes : BaseClass() {
|
class WrongReturnTypes : IntermediateClass() {
|
||||||
override fun everythingNotNullable(x: Foo): Foo? {
|
<!WRONG_NULLABILITY_FOR_JAVA_OVERRIDE!>override<!> fun everythingNotNullable(x: Foo): Foo? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun explicitlyNullnessUnspecified(x: Foo): Foo? {
|
<!WRONG_NULLABILITY_FOR_JAVA_OVERRIDE!>override<!> fun explicitlyNullnessUnspecified(x: Foo): Foo? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
<!WRONG_NULLABILITY_FOR_JAVA_OVERRIDE!>override<!> fun intermediateNotNull(): Foo? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WrongParameter : BaseClass() {
|
class WrongParameter : IntermediateClass() {
|
||||||
override fun everythingNotNullable(x: Foo?): Foo {
|
<!WRONG_NULLABILITY_FOR_JAVA_OVERRIDE!>override<!> fun everythingNotNullable(x: Foo?): Foo {
|
||||||
return FOO
|
return FOO
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun everythingNullable(x: Foo): Foo? {
|
<!WRONG_NULLABILITY_FOR_JAVA_OVERRIDE!>override<!> fun everythingNullable(x: Foo): Foo? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,11 +83,11 @@ class WrongParameter : BaseClass() {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mixed(x: Foo?): Foo? {
|
<!WRONG_NULLABILITY_FOR_JAVA_OVERRIDE!>override<!> fun mixed(x: Foo?): Foo? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun explicitlyNullnessUnspecified(x: Foo?): Foo {
|
override fun explicitlyNullnessUnspecified(x: Foo?): Foo {
|
||||||
return FOO
|
return FOO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-3
@@ -17,6 +17,8 @@ public class BaseClass {
|
|||||||
public @Nullable Foo mixed(Foo x) { return null; }
|
public @Nullable Foo mixed(Foo x) { return null; }
|
||||||
|
|
||||||
public Foo explicitlyNullnessUnspecified(@NullnessUnspecified Foo x) { return null; }
|
public Foo explicitlyNullnessUnspecified(@NullnessUnspecified Foo x) { return null; }
|
||||||
|
|
||||||
|
public static Foo foo() { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -24,7 +26,11 @@ public class BaseClass {
|
|||||||
|
|
||||||
private val FOO = object : Foo {}
|
private val FOO = object : Foo {}
|
||||||
|
|
||||||
class Correct : BaseClass() {
|
open class IntermediateClass : BaseClass() {
|
||||||
|
open fun intermediateNotNull() = BaseClass.foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Correct : IntermediateClass() {
|
||||||
override fun everythingNotNullable(x: Foo): Foo {
|
override fun everythingNotNullable(x: Foo): Foo {
|
||||||
return FOO
|
return FOO
|
||||||
}
|
}
|
||||||
@@ -44,9 +50,13 @@ class Correct : BaseClass() {
|
|||||||
override fun explicitlyNullnessUnspecified(x: Foo): Foo {
|
override fun explicitlyNullnessUnspecified(x: Foo): Foo {
|
||||||
return FOO
|
return FOO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun intermediateNotNull(): Foo {
|
||||||
|
return FOO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WrongReturnTypes : BaseClass() {
|
class WrongReturnTypes : IntermediateClass() {
|
||||||
<!WRONG_NULLABILITY_FOR_JAVA_OVERRIDE!>override<!> fun everythingNotNullable(x: Foo): Foo? {
|
<!WRONG_NULLABILITY_FOR_JAVA_OVERRIDE!>override<!> fun everythingNotNullable(x: Foo): Foo? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -54,9 +64,13 @@ class WrongReturnTypes : BaseClass() {
|
|||||||
<!WRONG_NULLABILITY_FOR_JAVA_OVERRIDE!>override<!> fun explicitlyNullnessUnspecified(x: Foo): Foo? {
|
<!WRONG_NULLABILITY_FOR_JAVA_OVERRIDE!>override<!> fun explicitlyNullnessUnspecified(x: Foo): Foo? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun intermediateNotNull(): Foo? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WrongParameter : BaseClass() {
|
class WrongParameter : IntermediateClass() {
|
||||||
<!WRONG_NULLABILITY_FOR_JAVA_OVERRIDE!>override<!> fun everythingNotNullable(x: Foo?): Foo {
|
<!WRONG_NULLABILITY_FOR_JAVA_OVERRIDE!>override<!> fun everythingNotNullable(x: Foo?): Foo {
|
||||||
return FOO
|
return FOO
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-3
@@ -12,9 +12,12 @@ private val FOO: FOO.`<no name provided>`
|
|||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
@org.jspecify.annotations.Nullable public open fun mixed(/*0*/ x: Foo!): @org.jspecify.annotations.Nullable Foo!
|
@org.jspecify.annotations.Nullable public open fun mixed(/*0*/ x: Foo!): @org.jspecify.annotations.Nullable Foo!
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
// Static members
|
||||||
|
public open fun foo(): Foo!
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class Correct : BaseClass {
|
public final class Correct : IntermediateClass {
|
||||||
public constructor Correct()
|
public constructor Correct()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ fun everythingNotNullable(/*0*/ x: Foo): Foo
|
public open override /*1*/ fun everythingNotNullable(/*0*/ x: Foo): Foo
|
||||||
@@ -22,6 +25,7 @@ public final class Correct : BaseClass {
|
|||||||
public open override /*1*/ fun everythingUnknown(/*0*/ x: Foo?): Foo?
|
public open override /*1*/ fun everythingUnknown(/*0*/ x: Foo?): Foo?
|
||||||
public open override /*1*/ fun explicitlyNullnessUnspecified(/*0*/ x: Foo): Foo
|
public open override /*1*/ fun explicitlyNullnessUnspecified(/*0*/ x: Foo): Foo
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ fun intermediateNotNull(): Foo
|
||||||
public open override /*1*/ fun mixed(/*0*/ x: Foo): Foo?
|
public open override /*1*/ fun mixed(/*0*/ x: Foo): Foo?
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
@@ -32,7 +36,20 @@ public interface Foo {
|
|||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class WrongParameter : BaseClass {
|
public open class IntermediateClass : BaseClass {
|
||||||
|
public constructor IntermediateClass()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun everythingNotNullable(/*0*/ x: Foo!): Foo!
|
||||||
|
@org.jspecify.annotations.Nullable public open override /*1*/ /*fake_override*/ fun everythingNullable(/*0*/ @org.jspecify.annotations.Nullable x: @org.jspecify.annotations.Nullable Foo!): @org.jspecify.annotations.Nullable Foo!
|
||||||
|
@org.jspecify.annotations.NullnessUnspecified public open override /*1*/ /*fake_override*/ fun everythingUnknown(/*0*/ @org.jspecify.annotations.NullnessUnspecified x: @org.jspecify.annotations.NullnessUnspecified Foo!): @org.jspecify.annotations.NullnessUnspecified Foo!
|
||||||
|
public open override /*1*/ /*fake_override*/ fun explicitlyNullnessUnspecified(/*0*/ @org.jspecify.annotations.NullnessUnspecified x: @org.jspecify.annotations.NullnessUnspecified Foo!): Foo!
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open fun intermediateNotNull(): Foo!
|
||||||
|
@org.jspecify.annotations.Nullable public open override /*1*/ /*fake_override*/ fun mixed(/*0*/ x: Foo!): @org.jspecify.annotations.Nullable Foo!
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class WrongParameter : IntermediateClass {
|
||||||
public constructor WrongParameter()
|
public constructor WrongParameter()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ fun everythingNotNullable(/*0*/ x: Foo?): Foo
|
public open override /*1*/ fun everythingNotNullable(/*0*/ x: Foo?): Foo
|
||||||
@@ -40,11 +57,12 @@ public final class WrongParameter : BaseClass {
|
|||||||
public open override /*1*/ fun everythingUnknown(/*0*/ x: Foo): Foo?
|
public open override /*1*/ fun everythingUnknown(/*0*/ x: Foo): Foo?
|
||||||
public open override /*1*/ fun explicitlyNullnessUnspecified(/*0*/ x: Foo?): Foo
|
public open override /*1*/ fun explicitlyNullnessUnspecified(/*0*/ x: Foo?): Foo
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun intermediateNotNull(): Foo!
|
||||||
public open override /*1*/ fun mixed(/*0*/ x: Foo?): Foo?
|
public open override /*1*/ fun mixed(/*0*/ x: Foo?): Foo?
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class WrongReturnTypes : BaseClass {
|
public final class WrongReturnTypes : IntermediateClass {
|
||||||
public constructor WrongReturnTypes()
|
public constructor WrongReturnTypes()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public open override /*1*/ fun everythingNotNullable(/*0*/ x: Foo): Foo?
|
public open override /*1*/ fun everythingNotNullable(/*0*/ x: Foo): Foo?
|
||||||
@@ -52,6 +70,8 @@ public final class WrongReturnTypes : BaseClass {
|
|||||||
@org.jspecify.annotations.NullnessUnspecified public open override /*1*/ /*fake_override*/ fun everythingUnknown(/*0*/ @org.jspecify.annotations.NullnessUnspecified x: @org.jspecify.annotations.NullnessUnspecified Foo!): @org.jspecify.annotations.NullnessUnspecified Foo!
|
@org.jspecify.annotations.NullnessUnspecified public open override /*1*/ /*fake_override*/ fun everythingUnknown(/*0*/ @org.jspecify.annotations.NullnessUnspecified x: @org.jspecify.annotations.NullnessUnspecified Foo!): @org.jspecify.annotations.NullnessUnspecified Foo!
|
||||||
public open override /*1*/ fun explicitlyNullnessUnspecified(/*0*/ x: Foo): Foo?
|
public open override /*1*/ fun explicitlyNullnessUnspecified(/*0*/ x: Foo): Foo?
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ fun intermediateNotNull(): Foo?
|
||||||
@org.jspecify.annotations.Nullable public open override /*1*/ /*fake_override*/ fun mixed(/*0*/ x: Foo!): @org.jspecify.annotations.Nullable Foo!
|
@org.jspecify.annotations.Nullable public open override /*1*/ /*fake_override*/ fun mixed(/*0*/ x: Foo!): @org.jspecify.annotations.Nullable Foo!
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-79
@@ -1,79 +0,0 @@
|
|||||||
// JSPECIFY_STATE: warn
|
|
||||||
|
|
||||||
// FILE: Foo.java
|
|
||||||
public interface Foo {}
|
|
||||||
// FILE: BaseClass.java
|
|
||||||
|
|
||||||
import org.jspecify.nullness.*;
|
|
||||||
|
|
||||||
@NullMarked
|
|
||||||
public class BaseClass {
|
|
||||||
public Foo everythingNotNullable(Foo x) { return null; }
|
|
||||||
|
|
||||||
public @Nullable Foo everythingNullable(@Nullable Foo x) { return null; }
|
|
||||||
|
|
||||||
public @NullnessUnspecified Foo everythingUnknown(@NullnessUnspecified Foo x) { return null; }
|
|
||||||
|
|
||||||
public @Nullable Foo mixed(Foo x) { return null; }
|
|
||||||
|
|
||||||
public Foo explicitlyNullnessUnspecified(@NullnessUnspecified Foo x) { return null; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// FILE: main.kt
|
|
||||||
|
|
||||||
private val FOO = object : Foo {}
|
|
||||||
|
|
||||||
class Correct : BaseClass() {
|
|
||||||
override fun everythingNotNullable(x: Foo): Foo {
|
|
||||||
return FOO
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun everythingNullable(x: Foo?): Foo? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun everythingUnknown(x: Foo?): Foo? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun mixed(x: Foo): Foo? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun explicitlyNullnessUnspecified(x: Foo): Foo {
|
|
||||||
return FOO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class WrongReturnTypes : BaseClass() {
|
|
||||||
override fun everythingNotNullable(x: Foo): Foo? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun explicitlyNullnessUnspecified(x: Foo): Foo? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class WrongParameter : BaseClass() {
|
|
||||||
override fun everythingNotNullable(x: Foo?): Foo {
|
|
||||||
return FOO
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun everythingNullable(x: Foo): Foo? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun everythingUnknown(x: Foo): Foo? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun mixed(x: Foo?): Foo? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun explicitlyNullnessUnspecified(x: Foo?): Foo {
|
|
||||||
return FOO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// JSPECIFY_STATE: warn
|
// JSPECIFY_STATE: warn
|
||||||
|
|
||||||
// FILE: Foo.java
|
// FILE: Foo.java
|
||||||
|
|||||||
Reference in New Issue
Block a user