FE1.0: keep nullability when approximating local types (in 1.9)

Report an error that inference will change and type has to be provided
manually in other language versions, since the current behavior is an
unsoundness that can cause runtime NPEs while the new behavior may
silently change overload resolution.

^KT-30054 Fixed
This commit is contained in:
pyos
2022-09-12 12:59:42 +02:00
committed by teamcity
parent 062308c7c1
commit adcbc5ec99
9 changed files with 44 additions and 3 deletions
@@ -619,6 +619,8 @@ public interface Errors {
DiagnosticFactory1<KtDeclaration, Collection<KotlinType>> AMBIGUOUS_ANONYMOUS_TYPE_INFERRED =
DiagnosticFactory1.create(ERROR, DECLARATION_SIGNATURE);
DiagnosticFactory1<KtDeclaration, KotlinType> APPROXIMATED_LOCAL_TYPE_WILL_BECOME_NULLABLE =
DiagnosticFactory1.create(WARNING, DECLARATION_SIGNATURE);
DiagnosticFactory1<KtNamedDeclaration, TypeParameterDescriptor>
KCLASS_WITH_NULLABLE_TYPE_PARAMETER_IN_SIGNATURE = DiagnosticFactory1.create(ERROR, PositioningStrategies.DECLARATION_NAME);
@@ -1067,6 +1067,8 @@ public class DefaultErrorMessages {
MAP.put(CATCH_PARAMETER_WITH_DEFAULT_VALUE, "Catch clause parameter may not have a default value");
MAP.put(AMBIGUOUS_ANONYMOUS_TYPE_INFERRED, "Right-hand side has anonymous type. Please specify type explicitly", TO_STRING);
MAP.put(APPROXIMATED_LOCAL_TYPE_WILL_BECOME_NULLABLE,
"Declaration return type inferred as ''{0}'' instead of ''{0}?''. This will be fixed in Kotlin 1.9. Please specify the type explicitly to avoid future errors or unexpected changes in behavior. See https://youtrack.jetbrains.com/issue/KT-53982 for details.", TO_STRING);
MAP.put(KCLASS_WITH_NULLABLE_TYPE_PARAMETER_IN_SIGNATURE,
"Declaration has an inconsistent return type. Please add upper bound Any for type parameter ''{0}'' or specify return type explicitly", NAME);
@@ -1094,6 +1094,11 @@ public class DescriptorResolver {
substitutedSuperType = approximatingSuperType;
}
if (languageVersionSettings.supportsFeature(LanguageFeature.KeepNullabilityWhenApproximatingLocalType)) {
return TypeUtils.makeNullableIfNeeded(substitutedSuperType, type.isMarkedNullable());
} else if (type.isMarkedNullable()) {
trace.report(APPROXIMATED_LOCAL_TYPE_WILL_BECOME_NULLABLE.on(declaration, substitutedSuperType));
}
return substitutedSuperType;
}
else {
@@ -1,4 +1,6 @@
// ISSUE: KT-30054
// FIR_IDENTICAL
// !LANGUAGE: +KeepNullabilityWhenApproximatingLocalType
interface I {
fun foo(): String
}
@@ -13,6 +15,6 @@ fun bar(condition: Boolean) /*: I? */ =
fun main() {
bar(false).<!UNRESOLVED_REFERENCE!>baz<!>()
bar(false).foo()
bar(false)<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
bar(false)<!UNSAFE_CALL!>.<!>foo()
bar(false)?.foo()
}
@@ -1,6 +1,6 @@
package
public fun bar(/*0*/ condition: kotlin.Boolean): I
public fun bar(/*0*/ condition: kotlin.Boolean): I?
public fun main(): kotlin.Unit
public interface I {
@@ -0,0 +1,18 @@
// ISSUE: KT-30054
interface I {
fun foo(): String
}
<!APPROXIMATED_LOCAL_TYPE_WILL_BECOME_NULLABLE!>fun bar(condition: Boolean)<!> /*: I? */ =
if (condition)
object : I {
override fun foo() = "should check for null first"
fun baz() = "invisible"
}
else null
fun main() {
bar(false).<!UNRESOLVED_REFERENCE!>baz<!>()
bar(false).foo()
bar(false)<!UNNECESSARY_SAFE_CALL!>?.<!>foo()
}
@@ -0,0 +1,11 @@
package
public fun bar(/*0*/ condition: kotlin.Boolean): I
public fun main(): kotlin.Unit
public interface I {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(): kotlin.String
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -278,6 +278,7 @@ enum class LanguageFeature(
ForbidInferringTypeVariablesIntoEmptyIntersection(KOTLIN_1_9, kind = BUG_FIX), // KT-51221
ForbidExtensionCallsOnInlineFunctionalParameters(KOTLIN_1_9, kind = BUG_FIX), // KT-52502
ForbidInferringPostponedTypeVariableIntoDeclaredUpperBound(KOTLIN_1_9, kind = BUG_FIX), // KT-47986
KeepNullabilityWhenApproximatingLocalType(KOTLIN_1_9, kind = BUG_FIX), // KT-53982
SkipStandaloneScriptsInSourceRoots(KOTLIN_1_9, kind = OTHER), // KT-52525
ModifierNonBuiltinSuspendFunError(KOTLIN_1_9),
BreakContinueInInlineLambdas(KOTLIN_1_9, defaultState = State.ENABLED), // KT-1436