FE: do not enhance ? in jspecify NullMarked scope
No clue whether this should be done for `@TypeQualifierDefault` since it appears to have no specification whatsoever. #KT-48262 Fixed
This commit is contained in:
-35
@@ -1,35 +0,0 @@
|
|||||||
// JSPECIFY_STATE: strict
|
|
||||||
// MUTE_FOR_PSI_CLASS_FILES_READING
|
|
||||||
|
|
||||||
// FILE: WildcardsWithDefault.java
|
|
||||||
import org.jspecify.nullness.*;
|
|
||||||
|
|
||||||
@NullMarked
|
|
||||||
public class WildcardsWithDefault {
|
|
||||||
public void noBoundsNotNull(A<?, ?, ?> a) {}
|
|
||||||
public void noBoundsNullable(A<? extends @Nullable Object, ? extends @Nullable Object, ? extends @Nullable Object> a) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: A.java
|
|
||||||
import org.jspecify.nullness.*;
|
|
||||||
|
|
||||||
public class A <T extends Object, E extends @Nullable Object, F extends @NullnessUnspecified Object> {}
|
|
||||||
|
|
||||||
// FILE: main.kt
|
|
||||||
fun main(
|
|
||||||
aNotNullNotNullNotNull: A<Any, Any, Any>,
|
|
||||||
aNotNullNotNullNull: A<Any, Any, Any?>,
|
|
||||||
aNotNullNullNotNull: A<Any, Any?, Any>,
|
|
||||||
aNotNullNullNull: A<Any, Any?, Any?>,
|
|
||||||
b: WildcardsWithDefault
|
|
||||||
): Unit {
|
|
||||||
b.noBoundsNotNull(aNotNullNotNullNotNull)
|
|
||||||
b.noBoundsNotNull(aNotNullNotNullNull)
|
|
||||||
b.noBoundsNotNull(aNotNullNullNotNull)
|
|
||||||
b.noBoundsNotNull(aNotNullNullNull)
|
|
||||||
|
|
||||||
b.noBoundsNullable(aNotNullNotNullNotNull)
|
|
||||||
b.noBoundsNullable(aNotNullNotNullNull)
|
|
||||||
b.noBoundsNullable(aNotNullNullNotNull)
|
|
||||||
b.noBoundsNullable(aNotNullNullNull)
|
|
||||||
}
|
|
||||||
+4
-5
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// JSPECIFY_STATE: strict
|
// JSPECIFY_STATE: strict
|
||||||
// MUTE_FOR_PSI_CLASS_FILES_READING
|
// MUTE_FOR_PSI_CLASS_FILES_READING
|
||||||
|
|
||||||
@@ -24,14 +25,12 @@ fun main(
|
|||||||
b: WildcardsWithDefault
|
b: WildcardsWithDefault
|
||||||
): Unit {
|
): Unit {
|
||||||
b.noBoundsNotNull(aNotNullNotNullNotNull)
|
b.noBoundsNotNull(aNotNullNotNullNotNull)
|
||||||
// jspecify_nullness_mismatch
|
b.noBoundsNotNull(aNotNullNotNullNull)
|
||||||
b.noBoundsNotNull(<!TYPE_MISMATCH!>aNotNullNotNullNull<!>)
|
|
||||||
b.noBoundsNotNull(aNotNullNullNotNull)
|
b.noBoundsNotNull(aNotNullNullNotNull)
|
||||||
// jspecify_nullness_mismatch
|
b.noBoundsNotNull(aNotNullNullNull)
|
||||||
b.noBoundsNotNull(<!TYPE_MISMATCH!>aNotNullNullNull<!>)
|
|
||||||
|
|
||||||
b.noBoundsNullable(aNotNullNotNullNotNull)
|
b.noBoundsNullable(aNotNullNotNullNotNull)
|
||||||
b.noBoundsNullable(aNotNullNotNullNull)
|
b.noBoundsNullable(aNotNullNotNullNull)
|
||||||
b.noBoundsNullable(aNotNullNullNotNull)
|
b.noBoundsNullable(aNotNullNullNotNull)
|
||||||
b.noBoundsNullable(aNotNullNullNull)
|
b.noBoundsNullable(aNotNullNullNull)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ public open class A</*0*/ T : kotlin.Any!, /*1*/ E, /*2*/ F : @org.jspecify.null
|
|||||||
public constructor WildcardsWithDefault()
|
public constructor WildcardsWithDefault()
|
||||||
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*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public open fun noBoundsNotNull(/*0*/ a: A<out kotlin.Any, *, out @org.jspecify.nullness.NullnessUnspecified kotlin.Any>): kotlin.Unit
|
public open fun noBoundsNotNull(/*0*/ a: A<*, *, *>): kotlin.Unit
|
||||||
public open fun noBoundsNullable(/*0*/ a: A<out @org.jspecify.nullness.Nullable kotlin.Any?, out @org.jspecify.nullness.Nullable kotlin.Any?, out @org.jspecify.nullness.Nullable kotlin.Any?>): kotlin.Unit
|
public open fun noBoundsNullable(/*0*/ a: A<out @org.jspecify.nullness.Nullable kotlin.Any?, out @org.jspecify.nullness.Nullable kotlin.Any?, out @org.jspecify.nullness.Nullable kotlin.Any?>): kotlin.Unit
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
|
|||||||
-35
@@ -1,35 +0,0 @@
|
|||||||
// JSPECIFY_STATE: warn
|
|
||||||
// MUTE_FOR_PSI_CLASS_FILES_READING
|
|
||||||
|
|
||||||
// FILE: WildcardsWithDefault.java
|
|
||||||
import org.jspecify.nullness.*;
|
|
||||||
|
|
||||||
@NullMarked
|
|
||||||
public class WildcardsWithDefault {
|
|
||||||
public void noBoundsNotNull(A<?, ?, ?> a) {}
|
|
||||||
public void noBoundsNullable(A<? extends @Nullable Object, ? extends @Nullable Object, ? extends @Nullable Object> a) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: A.java
|
|
||||||
import org.jspecify.nullness.*;
|
|
||||||
|
|
||||||
public class A <T extends Object, E extends @Nullable Object, F extends @NullnessUnspecified Object> {}
|
|
||||||
|
|
||||||
// FILE: main.kt
|
|
||||||
fun main(
|
|
||||||
aNotNullNotNullNotNull: A<Any, Any, Any>,
|
|
||||||
aNotNullNotNullNull: A<Any, Any, Any?>,
|
|
||||||
aNotNullNullNotNull: A<Any, Any?, Any>,
|
|
||||||
aNotNullNullNull: A<Any, Any?, Any?>,
|
|
||||||
b: WildcardsWithDefault
|
|
||||||
): Unit {
|
|
||||||
b.noBoundsNotNull(aNotNullNotNullNotNull)
|
|
||||||
b.noBoundsNotNull(aNotNullNotNullNull)
|
|
||||||
b.noBoundsNotNull(aNotNullNullNotNull)
|
|
||||||
b.noBoundsNotNull(aNotNullNullNull)
|
|
||||||
|
|
||||||
b.noBoundsNullable(aNotNullNotNullNotNull)
|
|
||||||
b.noBoundsNullable(aNotNullNotNullNull)
|
|
||||||
b.noBoundsNullable(aNotNullNullNotNull)
|
|
||||||
b.noBoundsNullable(aNotNullNullNull)
|
|
||||||
}
|
|
||||||
+4
-5
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// JSPECIFY_STATE: warn
|
// JSPECIFY_STATE: warn
|
||||||
// MUTE_FOR_PSI_CLASS_FILES_READING
|
// MUTE_FOR_PSI_CLASS_FILES_READING
|
||||||
|
|
||||||
@@ -24,14 +25,12 @@ fun main(
|
|||||||
b: WildcardsWithDefault
|
b: WildcardsWithDefault
|
||||||
): Unit {
|
): Unit {
|
||||||
b.noBoundsNotNull(aNotNullNotNullNotNull)
|
b.noBoundsNotNull(aNotNullNotNullNotNull)
|
||||||
// jspecify_nullness_mismatch
|
b.noBoundsNotNull(aNotNullNotNullNull)
|
||||||
b.noBoundsNotNull(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>aNotNullNotNullNull<!>)
|
|
||||||
b.noBoundsNotNull(aNotNullNullNotNull)
|
b.noBoundsNotNull(aNotNullNullNotNull)
|
||||||
// jspecify_nullness_mismatch
|
b.noBoundsNotNull(aNotNullNullNull)
|
||||||
b.noBoundsNotNull(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>aNotNullNullNull<!>)
|
|
||||||
|
|
||||||
b.noBoundsNullable(aNotNullNotNullNotNull)
|
b.noBoundsNullable(aNotNullNotNullNotNull)
|
||||||
b.noBoundsNullable(aNotNullNotNullNull)
|
b.noBoundsNullable(aNotNullNotNullNull)
|
||||||
b.noBoundsNullable(aNotNullNullNotNull)
|
b.noBoundsNullable(aNotNullNullNotNull)
|
||||||
b.noBoundsNullable(aNotNullNullNull)
|
b.noBoundsNullable(aNotNullNullNull)
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -12,7 +12,8 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
data class JavaDefaultQualifiers(
|
data class JavaDefaultQualifiers(
|
||||||
val nullabilityQualifier: NullabilityQualifierWithMigrationStatus,
|
val nullabilityQualifier: NullabilityQualifierWithMigrationStatus,
|
||||||
val qualifierApplicabilityTypes: Collection<AnnotationQualifierApplicabilityType>,
|
val qualifierApplicabilityTypes: Collection<AnnotationQualifierApplicabilityType>,
|
||||||
val affectsTypeParameterBasedTypes: Boolean = nullabilityQualifier.qualifier == NullabilityQualifier.NOT_NULL
|
val affectsTypeParameterBasedTypes: Boolean = nullabilityQualifier.qualifier == NullabilityQualifier.NOT_NULL,
|
||||||
|
val affectsStarProjection: Boolean = affectsTypeParameterBasedTypes
|
||||||
) {
|
) {
|
||||||
val makesTypeParameterNotNull get() = nullabilityQualifier.qualifier == NullabilityQualifier.NOT_NULL && affectsTypeParameterBasedTypes
|
val makesTypeParameterNotNull get() = nullabilityQualifier.qualifier == NullabilityQualifier.NOT_NULL && affectsTypeParameterBasedTypes
|
||||||
}
|
}
|
||||||
@@ -35,7 +36,8 @@ val JSPECIFY_DEFAULT_ANNOTATIONS = mapOf(
|
|||||||
JSPECIFY_NULL_MARKED to JavaDefaultQualifiers(
|
JSPECIFY_NULL_MARKED to JavaDefaultQualifiers(
|
||||||
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL),
|
NullabilityQualifierWithMigrationStatus(NullabilityQualifier.NOT_NULL),
|
||||||
DEFAULT_JSPECIFY_APPLICABILITY,
|
DEFAULT_JSPECIFY_APPLICABILITY,
|
||||||
affectsTypeParameterBasedTypes = false
|
affectsTypeParameterBasedTypes = false,
|
||||||
|
affectsStarProjection = false
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+10
-6
@@ -317,6 +317,12 @@ class SignatureEnhancement(
|
|||||||
typeParameterForArgument: TypeParameterDescriptor?,
|
typeParameterForArgument: TypeParameterDescriptor?,
|
||||||
isFromStarProjection: Boolean
|
isFromStarProjection: Boolean
|
||||||
): JavaTypeQualifiers {
|
): JavaTypeQualifiers {
|
||||||
|
if (isFromStarProjection && typeParameterForArgument?.variance == Variance.IN_VARIANCE) {
|
||||||
|
// Star projections can only be enhanced in one way: `?` -> `? extends <something>`. Given a Kotlin type `C<in T>
|
||||||
|
// (declaration-site variance), this is not a valid enhancement due to conflicting variances.
|
||||||
|
return JavaTypeQualifiers.NONE
|
||||||
|
}
|
||||||
|
|
||||||
val areImprovementsInStrictMode = containerContext.components.settings.typeEnhancementImprovementsInStrictMode
|
val areImprovementsInStrictMode = containerContext.components.settings.typeEnhancementImprovementsInStrictMode
|
||||||
|
|
||||||
val composedAnnotation =
|
val composedAnnotation =
|
||||||
@@ -349,7 +355,7 @@ class SignatureEnhancement(
|
|||||||
containerContext.defaultTypeQualifiers?.get(containerApplicabilityType)
|
containerContext.defaultTypeQualifiers?.get(containerApplicabilityType)
|
||||||
else
|
else
|
||||||
defaultQualifiersForType)?.takeIf {
|
defaultQualifiersForType)?.takeIf {
|
||||||
it.affectsTypeParameterBasedTypes || !isTypeParameter()
|
(it.affectsTypeParameterBasedTypes || !isTypeParameter()) && (it.affectsStarProjection || !isFromStarProjection)
|
||||||
}
|
}
|
||||||
|
|
||||||
val (nullabilityFromBoundsForTypeBasedOnTypeParameter, isTypeParameterWithNotNullableBounds) =
|
val (nullabilityFromBoundsForTypeBasedOnTypeParameter, isTypeParameterWithNotNullableBounds) =
|
||||||
@@ -362,8 +368,7 @@ class SignatureEnhancement(
|
|||||||
?: computeNullabilityInfoInTheAbsenceOfExplicitAnnotation(
|
?: computeNullabilityInfoInTheAbsenceOfExplicitAnnotation(
|
||||||
nullabilityFromBoundsForTypeBasedOnTypeParameter,
|
nullabilityFromBoundsForTypeBasedOnTypeParameter,
|
||||||
defaultTypeQualifier,
|
defaultTypeQualifier,
|
||||||
typeParameterForArgument,
|
typeParameterForArgument
|
||||||
isFromStarProjection
|
|
||||||
)
|
)
|
||||||
|
|
||||||
val isNotNullTypeParameter =
|
val isNotNullTypeParameter =
|
||||||
@@ -390,8 +395,7 @@ class SignatureEnhancement(
|
|||||||
private fun computeNullabilityInfoInTheAbsenceOfExplicitAnnotation(
|
private fun computeNullabilityInfoInTheAbsenceOfExplicitAnnotation(
|
||||||
nullabilityFromBoundsForTypeBasedOnTypeParameter: NullabilityQualifierWithMigrationStatus?,
|
nullabilityFromBoundsForTypeBasedOnTypeParameter: NullabilityQualifierWithMigrationStatus?,
|
||||||
defaultTypeQualifier: JavaDefaultQualifiers?,
|
defaultTypeQualifier: JavaDefaultQualifiers?,
|
||||||
typeParameterForArgument: TypeParameterDescriptor?,
|
typeParameterForArgument: TypeParameterDescriptor?
|
||||||
isFromStarProjection: Boolean
|
|
||||||
): NullabilityQualifierWithMigrationStatus? {
|
): NullabilityQualifierWithMigrationStatus? {
|
||||||
|
|
||||||
val result =
|
val result =
|
||||||
@@ -412,7 +416,7 @@ class SignatureEnhancement(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == null || isFromStarProjection) return boundsFromTypeParameterForArgument
|
if (result == null) return boundsFromTypeParameterForArgument
|
||||||
|
|
||||||
return mostSpecific(boundsFromTypeParameterForArgument, result)
|
return mostSpecific(boundsFromTypeParameterForArgument, result)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user