diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt index f69e45b0a60..6cdc3cc24c0 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.load.java.typeEnhancement.* import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.utils.addToStdlib.applyIf internal fun ConeKotlinType.enhance(session: FirSession, qualifiers: IndexedJavaTypeQualifiers): ConeKotlinType? = enhanceConeKotlinType(session, qualifiers, 0, mutableListOf().apply { computeSubtreeSizes(this) }) @@ -115,6 +116,10 @@ private fun ConeSimpleKotlinType.enhanceInflexibleType( enhancedTag.constructType(typeArguments, isNullable, newAttributes) } else { this.withAttributes(newAttributes) + }.applyIf(isFromDefinitelyNotNullType) { + // If the original type was DNN, we need to wrap the result in a DNN type because `this` is the non-DNN part of the original. + // In the non-warning case, this happens in the nested call and so `enhanced` is already DNN. + ConeDefinitelyNotNullType.create(this, session.typeContext) } } else { enhanced diff --git a/compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/jspecify/warnMode/UnannotatedWildcard.fir.kt b/compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/jspecify/warnMode/UnannotatedWildcard.fir.kt deleted file mode 100644 index 9ca60e314f0..00000000000 --- a/compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/jspecify/warnMode/UnannotatedWildcard.fir.kt +++ /dev/null @@ -1,17 +0,0 @@ -// JSPECIFY_STATE: warn -// FILE: J1.java -import org.jspecify.annotations.*; - -@NullMarked -public interface J1 { - T foo(); -} - -// FILE: J2.java -public interface J2 { - J1 bar(); -} - -// FILE: main.kt -// jspecify_nullness_mismatch -fun baz(j2: J2): Any = j2.bar().foo() // Any..Any? diff --git a/compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/jspecify/warnMode/UnannotatedWildcard.kt b/compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/jspecify/warnMode/UnannotatedWildcard.kt index 48d0471ee11..749756a2fd2 100644 --- a/compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/jspecify/warnMode/UnannotatedWildcard.kt +++ b/compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/jspecify/warnMode/UnannotatedWildcard.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // JSPECIFY_STATE: warn // FILE: J1.java import org.jspecify.annotations.*; diff --git a/compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/jspecifyOld/warnMode/UnannotatedWildcard.fir.kt b/compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/jspecifyOld/warnMode/UnannotatedWildcard.fir.kt deleted file mode 100644 index 9c5f706ce9f..00000000000 --- a/compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/jspecifyOld/warnMode/UnannotatedWildcard.fir.kt +++ /dev/null @@ -1,16 +0,0 @@ -// JSPECIFY_STATE: warn -// FILE: J1.java -import org.jspecify.nullness.*; - -@NullMarked -public interface J1 { - T foo(); -} - -// FILE: J2.java -public interface J2 { - J1 bar(); -} - -// FILE: main.kt -fun baz(j2: J2): Any = j2.bar().foo() // Any..Any? diff --git a/compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/jspecifyOld/warnMode/UnannotatedWildcard.kt b/compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/jspecifyOld/warnMode/UnannotatedWildcard.kt index e41b1397c21..6344ec52ed3 100644 --- a/compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/jspecifyOld/warnMode/UnannotatedWildcard.kt +++ b/compiler/testData/diagnostics/foreignAnnotationsTests/java8Tests/jspecifyOld/warnMode/UnannotatedWildcard.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // JSPECIFY_STATE: warn // FILE: J1.java import org.jspecify.nullness.*; diff --git a/compiler/testData/diagnostics/foreignAnnotationsTests/tests/jsr305/nullabilityWarnings/override.fir.kt b/compiler/testData/diagnostics/foreignAnnotationsTests/tests/jsr305/nullabilityWarnings/override.fir.kt index b0e97da4f49..a771ab21b9d 100644 --- a/compiler/testData/diagnostics/foreignAnnotationsTests/tests/jsr305/nullabilityWarnings/override.fir.kt +++ b/compiler/testData/diagnostics/foreignAnnotationsTests/tests/jsr305/nullabilityWarnings/override.fir.kt @@ -62,3 +62,23 @@ abstract class A : Provider { override fun getSet(x: T): T = x override fun getSetNullable(x: T): T = x } + +abstract class B : Provider { + override fun get(): T & Any = null!! + override fun getNullable(): T? = null!! + override fun set(x: T & Any) {} // False positive in K1 + override fun setNullable(x: T?) {} + + override fun getSet(x: T & Any): T & Any = x // False positive in K1 + override fun getSetNullable(x: T?): T? = x +} + +abstract class C : Provider { + override fun getSet(x: T): T & Any = x!! // Missing warning in K1, K2 get's this right + override fun getSetNullable(x: T): T? = x +} + +abstract class D : Provider { + override fun getSet(x: T & Any): T = x!! // False positive in K1 + override fun getSetNullable(x: T?): T = x!! +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/foreignAnnotationsTests/tests/jsr305/nullabilityWarnings/override.kt b/compiler/testData/diagnostics/foreignAnnotationsTests/tests/jsr305/nullabilityWarnings/override.kt index 13544ad0b55..ce786293f29 100644 --- a/compiler/testData/diagnostics/foreignAnnotationsTests/tests/jsr305/nullabilityWarnings/override.kt +++ b/compiler/testData/diagnostics/foreignAnnotationsTests/tests/jsr305/nullabilityWarnings/override.kt @@ -62,3 +62,23 @@ abstract class A : Provider { override fun getSet(x: T): T = x override fun getSetNullable(x: T): T = x } + +abstract class B : Provider { + override fun get(): T & Any = null!! + override fun getNullable(): T? = null!! + override fun set(x: T & Any) {} // False positive in K1 + override fun setNullable(x: T?) {} + + override fun getSet(x: T & Any): T & Any = x // False positive in K1 + override fun getSetNullable(x: T?): T? = x +} + +abstract class C : Provider { + override fun getSet(x: T): T & Any = x!! // Missing warning in K1, K2 get's this right + override fun getSetNullable(x: T): T? = x +} + +abstract class D : Provider { + override fun getSet(x: T & Any): T = x!! // False positive in K1 + override fun getSetNullable(x: T?): T = x!! +} \ No newline at end of file