K2/Java/enhancement: implement wildcards replacement with flexible bounds
This commit in fact changes two very related places: - first, it implements forgotten 'enhancedForWarnings' in K2 enhancement - second, it repeats KT-48515 fix for K2 while enhancing wildcards #KT-65594 Fixed Related to KT-48515, KT-63746
This commit is contained in:
committed by
Space Team
parent
5b0cb5c9db
commit
40c4e865c7
+2
-2
@@ -29,13 +29,13 @@
|
||||
|
||||
}
|
||||
@R|NullableApi|() public open class B : R|A|, R|AInt| {
|
||||
public open fun foo1(x: R|Enhanced for warning(kotlin/String?) kotlin/String!|): R|Enhanced for warning(kotlin/String?) kotlin/String!|
|
||||
public open fun foo1(x: R|kotlin/String!|): R|kotlin/String!|
|
||||
|
||||
@R|javax/annotation/Nonnull|() public open fun foo2(@R|javax/annotation/Nonnull|() x: R|@EnhancedNullability kotlin/String|): R|@EnhancedNullability kotlin/String|
|
||||
|
||||
public open fun bar1(x: R|@EnhancedNullability kotlin/String?|): R|@EnhancedNullability kotlin/String?|
|
||||
|
||||
public open fun baz(x: R|@EnhancedNullability kotlin/String|): R|Enhanced for warning(kotlin/String?) kotlin/String!|
|
||||
public open fun baz(x: R|@EnhancedNullability kotlin/String|): R|kotlin/String!|
|
||||
|
||||
public constructor(): R|B|
|
||||
|
||||
|
||||
+1
-1
@@ -891,7 +891,7 @@ private class EnhancementSignatureParts(
|
||||
get() = ((this as? ConeLookupTagBasedType)?.lookupTag as? ConeClassLikeLookupTag)?.classId?.asSingleFqName()?.toUnsafe()
|
||||
|
||||
override val KotlinTypeMarker.enhancedForWarnings: KotlinTypeMarker?
|
||||
get() = null // TODO: implement enhancement for warnings
|
||||
get() = (this as ConeKotlinType).enhancedTypeForWarning
|
||||
|
||||
override fun KotlinTypeMarker.isEqual(other: KotlinTypeMarker): Boolean =
|
||||
AbstractTypeChecker.equalTypes(session.typeContext, this, other)
|
||||
|
||||
@@ -8,7 +8,9 @@ package org.jetbrains.kotlin.fir.java.enhancement
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
@@ -160,17 +162,31 @@ private fun ConeLookupTagBasedType.enhanceInflexibleType(
|
||||
}
|
||||
|
||||
var globalArgIndex = index + 1
|
||||
val enhancedArguments = typeArguments.map { arg ->
|
||||
val argIndex = globalArgIndex.also { globalArgIndex += subtreeSizes[it] }
|
||||
arg.type?.enhanceConeKotlinType(session, qualifiers, argIndex, subtreeSizes, convertErrorsToWarnings = convertNestedErrorsToWarnings)
|
||||
?.let {
|
||||
when (arg.kind) {
|
||||
ProjectionKind.IN -> ConeKotlinTypeProjectionIn(it)
|
||||
ProjectionKind.OUT -> ConeKotlinTypeProjectionOut(it)
|
||||
ProjectionKind.STAR -> ConeStarProjection
|
||||
ProjectionKind.INVARIANT -> it
|
||||
}
|
||||
val enhancedArguments = typeArguments.mapIndexed { currentArgLocalIndex, arg ->
|
||||
val currentArgGlobalIndex = globalArgIndex.also { globalArgIndex += subtreeSizes[it] }
|
||||
if (arg.type == null && qualifiers(currentArgGlobalIndex).nullability == NullabilityQualifier.FORCE_FLEXIBILITY) {
|
||||
// Given `C<T extends @Nullable V>`, unannotated `C<?>` is `C<out (V..V?)>`.
|
||||
val typeParameters = (this.lookupTag.toSymbol(session)?.fir as? FirClassLikeDeclaration)?.typeParameters
|
||||
if (typeParameters != null) {
|
||||
val bound = typeParameters[currentArgLocalIndex].symbol.fir.bounds.first().coneType
|
||||
return@mapIndexed ConeKotlinTypeProjectionOut(
|
||||
ConeFlexibleType(
|
||||
bound.lowerBoundIfFlexible().withNullability(ConeNullability.NOT_NULL, session.typeContext),
|
||||
bound.upperBoundIfFlexible().withNullability(ConeNullability.NULLABLE, session.typeContext)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
arg.type?.enhanceConeKotlinType(
|
||||
session, qualifiers, currentArgGlobalIndex, subtreeSizes, convertErrorsToWarnings = convertNestedErrorsToWarnings
|
||||
)?.let {
|
||||
when (arg.kind) {
|
||||
ProjectionKind.IN -> ConeKotlinTypeProjectionIn(it)
|
||||
ProjectionKind.OUT -> ConeKotlinTypeProjectionOut(it)
|
||||
ProjectionKind.STAR -> ConeStarProjection
|
||||
ProjectionKind.INVARIANT -> it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val shouldAddAttribute = nullabilityFromQualifiers == NullabilityQualifier.NOT_NULL && !hasEnhancedNullability
|
||||
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
// FILE: NullnessUnspecifiedTypeParameter.java
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
@NullMarked
|
||||
public class NullnessUnspecifiedTypeParameter<T> {
|
||||
public void foo(T t) {}
|
||||
|
||||
public void bar(Test s, T t) {} // t should not become not nullable
|
||||
}
|
||||
|
||||
// FILE: Test.java
|
||||
public class Test {}
|
||||
|
||||
// FILE: main.kt
|
||||
// jspecify_nullness_mismatch
|
||||
fun main(a1: NullnessUnspecifiedTypeParameter<Any>, a2: NullnessUnspecifiedTypeParameter<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Any?<!>>, x: Test): Unit {
|
||||
// jspecify_nullness_mismatch
|
||||
a1.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
a1.foo(1)
|
||||
|
||||
a2.foo(null)
|
||||
a2.foo(1)
|
||||
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a1.bar(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, <!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
// jspecify_nullness_mismatch
|
||||
a1.bar(x, <!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
a1.bar(x, 1)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
a2.bar(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, null)
|
||||
a2.bar(x, null)
|
||||
a2.bar(x, 1)
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// FILE: NullnessUnspecifiedTypeParameter.java
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
// JSPECIFY_STATE: strict
|
||||
// FILE: Box.java
|
||||
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
@NullMarked
|
||||
public class Box<V extends @Nullable Object> {
|
||||
public static <V extends @Nullable Object> Box<V> make() {
|
||||
return new Box<>();
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: Util.java
|
||||
public final class Util {
|
||||
public Box<?> boxId(Box<?> box) { return box; }
|
||||
}
|
||||
|
||||
// FILE: a.kt
|
||||
fun foo(u: Util) =
|
||||
u.boxId(Box.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>make<!>())
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// JSPECIFY_STATE: strict
|
||||
// FILE: Box.java
|
||||
|
||||
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
// JSPECIFY_STATE: strict
|
||||
// !LANGUAGE: +TypeEnhancementImprovementsInStrictMode
|
||||
|
||||
// FILE: J1.java
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
@NullMarked
|
||||
public interface J1<T extends @Nullable Object> {
|
||||
T foo();
|
||||
}
|
||||
|
||||
// FILE: J2.java
|
||||
public interface J2 {
|
||||
J1<?> bar();
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun baz(j2: J2): Any = <!RETURN_TYPE_MISMATCH!>j2.bar().foo()<!> // Any..Any?
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// JSPECIFY_STATE: strict
|
||||
// !LANGUAGE: +TypeEnhancementImprovementsInStrictMode
|
||||
|
||||
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
// JSPECIFY_STATE: warn
|
||||
// FILE: Box.java
|
||||
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
@NullMarked
|
||||
public class Box<V extends @Nullable Object> {
|
||||
public static <V extends @Nullable Object> Box<V> make() {
|
||||
return new Box<>();
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: Util.java
|
||||
public final class Util {
|
||||
public Box<?> boxId(Box<?> box) { return box; }
|
||||
}
|
||||
|
||||
// FILE: a.kt
|
||||
fun foo(u: Util) =
|
||||
u.boxId(Box.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>make<!>())
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// JSPECIFY_STATE: warn
|
||||
// FILE: Box.java
|
||||
|
||||
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
// JSPECIFY_STATE: warn
|
||||
// FILE: NullnessUnspecifiedTypeParameter.java
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
@NullMarked
|
||||
public class NullnessUnspecifiedTypeParameter<T> {
|
||||
public void foo(T t) {}
|
||||
|
||||
public void bar(Test s, T t) {} // t should not become not nullable
|
||||
}
|
||||
|
||||
// FILE: Test.java
|
||||
public class Test {}
|
||||
|
||||
// FILE: main.kt
|
||||
// jspecify_nullness_mismatch
|
||||
fun main(a1: NullnessUnspecifiedTypeParameter<Any>, a2: NullnessUnspecifiedTypeParameter<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Any?<!>>, x: Test): Unit {
|
||||
// jspecify_nullness_mismatch
|
||||
a1.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
a1.foo(1)
|
||||
|
||||
a2.foo(null)
|
||||
a2.foo(1)
|
||||
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a1.bar(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, <!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
// jspecify_nullness_mismatch
|
||||
a1.bar(x, <!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
a1.bar(x, 1)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
a2.bar(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, null)
|
||||
a2.bar(x, null)
|
||||
a2.bar(x, 1)
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// JSPECIFY_STATE: warn
|
||||
// FILE: NullnessUnspecifiedTypeParameter.java
|
||||
import org.jspecify.annotations.*;
|
||||
|
||||
Vendored
+6
-3
@@ -40,15 +40,18 @@ public class CKN extends C<@Nullable CK> {}
|
||||
// FILE: main.kt
|
||||
fun main(ak: AK, akn: AKN, bk: BK, ck: CK, ckn: CKN): Unit {
|
||||
ak.foo(ak)
|
||||
ak.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
ak.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
|
||||
akn.foo(null) // the corresponding warning/error is present on the Java side
|
||||
|
||||
bk.foo(bk)
|
||||
bk.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
bk.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
|
||||
ck.foo(ck)
|
||||
ck.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
ck.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
|
||||
ckn.foo(null) // the corresponding warning/error is present on the Java side
|
||||
}
|
||||
|
||||
+10
-5
@@ -23,19 +23,24 @@ public class Test {}
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
fun <T : Test> main(a1: A<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Any?<!>>, a2: A<Test>, b1: B<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Any?<!>>, b2: B<Test>, x: T): Unit {
|
||||
a1.foo(null)
|
||||
a1.bar<T?>(null)
|
||||
// jspecify_nullness_mismatch
|
||||
a1.bar<T?>(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
a1.bar<T>(x)
|
||||
|
||||
a2.foo(null)
|
||||
a2.bar<T?>(null)
|
||||
// jspecify_nullness_mismatch
|
||||
a2.bar<T?>(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
a2.bar<T>(x)
|
||||
|
||||
b1.foo(null)
|
||||
b1.bar<T?>(null)
|
||||
// jspecify_nullness_mismatch
|
||||
b1.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
// jspecify_nullness_mismatch
|
||||
b1.bar<T?>(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
b1.bar<T>(x)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
b2.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
b2.bar<T?>(null)
|
||||
// jspecify_nullness_mismatch
|
||||
b2.bar<T?>(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
b2.bar<T>(x)
|
||||
}
|
||||
|
||||
Vendored
-36
@@ -1,36 +0,0 @@
|
||||
// FILE: NullnessUnspecifiedTypeParameter.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
@NullMarked
|
||||
public class NullnessUnspecifiedTypeParameter<T> {
|
||||
public void foo(T t) {}
|
||||
|
||||
public void bar(Test s, T t) {} // t should not become not nullable
|
||||
}
|
||||
|
||||
// FILE: Test.java
|
||||
public class Test {}
|
||||
|
||||
// FILE: main.kt
|
||||
// jspecify_nullness_mismatch
|
||||
fun main(a1: NullnessUnspecifiedTypeParameter<Any>, a2: NullnessUnspecifiedTypeParameter<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Any?<!>>, x: Test): Unit {
|
||||
// jspecify_nullness_mismatch
|
||||
a1.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
a1.foo(1)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
a2.foo(null)
|
||||
a2.foo(1)
|
||||
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a1.bar(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, <!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
// jspecify_nullness_mismatch
|
||||
a1.bar(x, <!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
a1.bar(x, 1)
|
||||
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a2.bar(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, null)
|
||||
// jspecify_nullness_mismatch
|
||||
a2.bar(x, null)
|
||||
a2.bar(x, 1)
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// FILE: NullnessUnspecifiedTypeParameter.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
// JSPECIFY_STATE: strict
|
||||
// !LANGUAGE: +TypeEnhancementImprovementsInStrictMode
|
||||
|
||||
// FILE: J1.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
@NullMarked
|
||||
public interface J1<T extends @Nullable Object> {
|
||||
T foo();
|
||||
}
|
||||
|
||||
// FILE: J2.java
|
||||
public interface J2 {
|
||||
J1<?> bar();
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun baz(j2: J2): Any = <!RETURN_TYPE_MISMATCH!>j2.bar().foo()<!> // Any..Any?
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// JSPECIFY_STATE: strict
|
||||
// !LANGUAGE: +TypeEnhancementImprovementsInStrictMode
|
||||
|
||||
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
// JSPECIFY_STATE: warn
|
||||
// FILE: NullnessUnspecifiedTypeParameter.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
@NullMarked
|
||||
public class NullnessUnspecifiedTypeParameter<T> {
|
||||
public void foo(T t) {}
|
||||
|
||||
public void bar(Test s, T t) {} // t should not become not nullable
|
||||
}
|
||||
|
||||
// FILE: Test.java
|
||||
public class Test {}
|
||||
|
||||
// FILE: main.kt
|
||||
// jspecify_nullness_mismatch
|
||||
fun main(a1: NullnessUnspecifiedTypeParameter<Any>, a2: NullnessUnspecifiedTypeParameter<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Any?<!>>, x: Test): Unit {
|
||||
// jspecify_nullness_mismatch
|
||||
a1.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
a1.foo(1)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
a2.foo(null)
|
||||
a2.foo(1)
|
||||
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a1.bar(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, <!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
// jspecify_nullness_mismatch
|
||||
a1.bar(x, <!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
a1.bar(x, 1)
|
||||
|
||||
// jspecify_nullness_mismatch, jspecify_nullness_mismatch
|
||||
a2.bar(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>, null)
|
||||
// jspecify_nullness_mismatch
|
||||
a2.bar(x, null)
|
||||
a2.bar(x, 1)
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// JSPECIFY_STATE: warn
|
||||
// FILE: NullnessUnspecifiedTypeParameter.java
|
||||
import org.jspecify.nullness.*;
|
||||
|
||||
+3
-3
@@ -41,17 +41,17 @@ public class CKN extends C<@Nullable CK> {}
|
||||
fun main(ak: AK, akn: AKN, bk: BK, ck: CK, ckn: CKN): Unit {
|
||||
ak.foo(ak)
|
||||
// jspecify_nullness_mismatch
|
||||
ak.foo(null)
|
||||
ak.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
|
||||
akn.foo(null) // the corresponding warning/error is present on the Java side
|
||||
|
||||
bk.foo(bk)
|
||||
// jspecify_nullness_mismatch
|
||||
bk.foo(null)
|
||||
bk.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
|
||||
ck.foo(ck)
|
||||
// jspecify_nullness_mismatch
|
||||
ck.foo(null)
|
||||
ck.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
|
||||
ckn.foo(null) // the corresponding warning/error is present on the Java side
|
||||
}
|
||||
|
||||
+5
-5
@@ -24,23 +24,23 @@ public class Test {}
|
||||
fun <T : Test> main(a1: A<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Any?<!>>, a2: A<Test>, b1: B<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Any?<!>>, b2: B<Test>, x: T): Unit {
|
||||
a1.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
a1.bar<T?>(null)
|
||||
a1.bar<T?>(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
a1.bar<T>(x)
|
||||
|
||||
a2.foo(null)
|
||||
// jspecify_nullness_mismatch
|
||||
a2.bar<T?>(null)
|
||||
a2.bar<T?>(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
a2.bar<T>(x)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
b1.foo(null)
|
||||
b1.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
// jspecify_nullness_mismatch
|
||||
b1.bar<T?>(null)
|
||||
b1.bar<T?>(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
b1.bar<T>(x)
|
||||
|
||||
// jspecify_nullness_mismatch
|
||||
b2.foo(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
// jspecify_nullness_mismatch
|
||||
b2.bar<T?>(null)
|
||||
b2.bar<T?>(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>)
|
||||
b2.bar<T>(x)
|
||||
}
|
||||
|
||||
-152
@@ -1,152 +0,0 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// JSR305_GLOBAL_REPORT: warn
|
||||
|
||||
// FILE: NonNullApi.java
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.meta.TypeQualifierDefault;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Nonnull
|
||||
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
|
||||
public @interface NonNullApi {
|
||||
}
|
||||
|
||||
// FILE: NullableApi.java
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import javax.annotation.CheckForNull;
|
||||
import javax.annotation.meta.TypeQualifierDefault;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@CheckForNull
|
||||
@TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
|
||||
public @interface NullableApi {
|
||||
}
|
||||
|
||||
// FILE: A.java
|
||||
import javax.annotation.CheckForNull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@NonNullApi
|
||||
public class A {
|
||||
public String foo1(String x) { return ""; }
|
||||
public String foo2(String x) { return ""; }
|
||||
public String foo3(String x) { return ""; }
|
||||
|
||||
|
||||
@Nullable
|
||||
public String bar1(@Nullable String x) { return ""; }
|
||||
@Nullable
|
||||
public String bar2(@Nullable String x) { return ""; }
|
||||
|
||||
public String baz(@Nonnull String x) { return ""; }
|
||||
}
|
||||
|
||||
// FILE: AInt.java
|
||||
import javax.annotation.CheckForNull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@NonNullApi
|
||||
public interface AInt {
|
||||
public CharSequence foo1(String x);
|
||||
public CharSequence foo2(String x);
|
||||
public CharSequence foo3(String x);
|
||||
|
||||
|
||||
@Nullable
|
||||
public CharSequence bar1(@Nullable String x);
|
||||
@Nullable
|
||||
public CharSequence bar2(@Nullable String x);
|
||||
|
||||
public CharSequence baz(@Nonnull String x);
|
||||
}
|
||||
|
||||
|
||||
// FILE: B.java
|
||||
import javax.annotation.CheckForNull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@NullableApi
|
||||
public class B extends A implements AInt {
|
||||
// conflicts
|
||||
public String foo1(String x) { return ""; }
|
||||
|
||||
// no conflicts
|
||||
@Nonnull
|
||||
public String foo2(@Nonnull String x) { return ""; }
|
||||
|
||||
// fake override for foo3 shouldn't have any conflicts
|
||||
|
||||
// no conflicts
|
||||
public String bar1(String x) { return ""; }
|
||||
|
||||
// conflicts
|
||||
public String baz(String x) { return ""; }
|
||||
}
|
||||
|
||||
// FILE: C.java
|
||||
import javax.annotation.CheckForNull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@NonNullApi
|
||||
public class C extends A implements AInt {
|
||||
// no conflicts
|
||||
public String foo1(String x) { return ""; }
|
||||
|
||||
// no conflicts
|
||||
public String foo2(@Nonnull String x) { return ""; }
|
||||
|
||||
// fake override for foo3 shouldn't have any conflicts
|
||||
|
||||
// no conflicts, covariant override
|
||||
public String bar1(String x) { return ""; }
|
||||
// no conflicts
|
||||
@Nullable
|
||||
public String bar2(@Nullable String x) { return ""; }
|
||||
|
||||
// no conflicts
|
||||
public String baz(String x) { return ""; }
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun main(a: A, b: B, c: C) {
|
||||
a.foo1(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>).length
|
||||
a.foo2(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>).length
|
||||
a.foo3(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>).length
|
||||
a.bar1(null)<!UNSAFE_CALL!>.<!>length
|
||||
a.bar2(null)<!UNSAFE_CALL!>.<!>length
|
||||
a.baz(<!NULL_FOR_NONNULL_TYPE!>null<!>).length
|
||||
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>b.foo1(null)<!>.length
|
||||
b.foo1(null)?.length
|
||||
b.foo2(<!NULL_FOR_NONNULL_TYPE!>null<!>).length
|
||||
b.foo3(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>).length
|
||||
b.bar1(null)<!UNSAFE_CALL!>.<!>length
|
||||
b.bar2(null)<!UNSAFE_CALL!>.<!>length
|
||||
<!RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>b.baz(<!NULL_FOR_NONNULL_TYPE!>null<!>)<!>.length
|
||||
b.baz(<!NULL_FOR_NONNULL_TYPE!>null<!>)?.length
|
||||
|
||||
c.foo1(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>).length
|
||||
c.foo2(<!NULL_FOR_NONNULL_TYPE!>null<!>).length
|
||||
c.foo3(<!NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS!>null<!>).length
|
||||
c.bar1(null)<!UNSAFE_CALL!>.<!>length
|
||||
c.bar1(null)?.length
|
||||
c.bar2(null)<!UNSAFE_CALL!>.<!>length
|
||||
c.baz(<!NULL_FOR_NONNULL_TYPE!>null<!>).length
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// JSR305_GLOBAL_REPORT: warn
|
||||
|
||||
|
||||
Reference in New Issue
Block a user