From ac56f57ce6ac2a05a1eddb6d49ee32680369d3d4 Mon Sep 17 00:00:00 2001 From: Danil Pavlov Date: Wed, 21 Jan 2026 16:37:14 +0100 Subject: [PATCH 1/5] feat: JSpecify support --- docs/topics/jvm/java-interop.md | 59 +++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/docs/topics/jvm/java-interop.md b/docs/topics/jvm/java-interop.md index 973fb8faaee..78cc67819b2 100644 --- a/docs/topics/jvm/java-interop.md +++ b/docs/topics/jvm/java-interop.md @@ -199,12 +199,12 @@ Kotlin types. The compiler supports several flavors of nullability annotations, * [JetBrains](https://www.jetbrains.com/idea/help/nullable-and-notnull-annotations.html) (`@Nullable` and `@NotNull` from the `org.jetbrains.annotations` package) - * [JSpecify](https://jspecify.dev/) (`org.jspecify.annotations`) + * [JSpecify](#jspecify-support) (`org.jspecify.annotations`) * Android (`com.android.annotations` and `android.support.annotations`) - * JSR-305 (`javax.annotation`, more details below) + * [JSR-305](#jsr-305-support) (`javax.annotation`) * FindBugs (`edu.umd.cs.findbugs.annotations`) * Eclipse (`org.eclipse.jdt.annotation`) - * Lombok (`lombok.NonNull`) + * [Lombok](lombok.md) (`lombok.NonNull`) * RxJava 3 (`io.reactivex.rxjava3.annotations`) You can specify whether the compiler reports a nullability mismatch based on the information from specific types of @@ -312,6 +312,59 @@ nullability annotations support the `TYPE_USE` target (`org.jetbrains.annotation > {style="note"} +### JSpecify support + +Kotlin supports the [JSpecify](https://jspecify.dev/) nullability annotations, which provide a unified set of annotations +for Java nullness. JSpecify allows you to provide detailed nullability information for Java declarations, +helping Kotlin maintain null-safety when interoperating with Java code. + +Kotlin supports the following annotations in the `org.jspecify.annotations` package: + +* `@Nullable` marks a type as nullable. +* `@NonNull` marks a type as non-nullable. +* `@NullMarked` marks all types within a scope, for example a class or package, as non-nullable by default unless annotated + otherwise. + +Consider the following Java class with JSpecify annotations: + +```java +// Java +import org.jspecify.annotations.*; + +@NullMarked +public class InventoryService { + public String notNull() { return ""; } + @Nullable public String nullable() { return null; } +} +``` + +In Kotlin, these are treated as regular nullable and non-nullable types rather than [platform types](#null-safety-and-platform-types): + +```kotlin +// Kotlin +fun test(inventory: InventoryService) { + inventory.notNull().length // OK + inventory.nullable().length // Error: only safe (?.) or non-null asserted (!!.) calls are allowed +} +``` + +By default, the Kotlin compiler reports nullability mismatches for JSpecify annotations as errors. +You can customize this the severity of JSpecify nullability diagnostics using the following compiler option: + +```properties +-Xnullability-annotations=@org.jspecify.annotations: +``` + +Available report levels are: + +| Level | Description | +|----------|------------------------------------------------------| +| `strict` | Reports errors for nullability mismatches (default). | +| `warn` | Reports warnings. | +| `ignore` | Ignores nullability mismatches. | + +For more information, see the [JSpecify user guide](https://jspecify.dev/docs/user-guide). + ### JSR-305 support The [`@Nonnull`](https://www.javadoc.io/doc/com.google.code.findbugs/jsr305/latest/javax/annotation/Nonnull.html) annotation defined From c845fb2b709da680f16c7a3a185389678656b7d2 Mon Sep 17 00:00:00 2001 From: Danil Pavlov Date: Thu, 12 Feb 2026 15:50:20 +0100 Subject: [PATCH 2/5] fix: review suggestions, first batch Co-authored-by: Brian Norman --- docs/topics/jvm/java-interop.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/topics/jvm/java-interop.md b/docs/topics/jvm/java-interop.md index 78cc67819b2..979421a0d12 100644 --- a/docs/topics/jvm/java-interop.md +++ b/docs/topics/jvm/java-interop.md @@ -334,7 +334,7 @@ import org.jspecify.annotations.*; @NullMarked public class InventoryService { public String notNull() { return ""; } - @Nullable public String nullable() { return null; } + public @Nullable String nullable() { return null; } } ``` @@ -349,7 +349,7 @@ fun test(inventory: InventoryService) { ``` By default, the Kotlin compiler reports nullability mismatches for JSpecify annotations as errors. -You can customize this the severity of JSpecify nullability diagnostics using the following compiler option: +You can customize the severity of JSpecify nullability diagnostics using the following compiler option: ```properties -Xnullability-annotations=@org.jspecify.annotations: From 851536f42e16be490dc9f410890dc6970de9d5ec Mon Sep 17 00:00:00 2001 From: Danil Pavlov Date: Thu, 12 Feb 2026 15:54:00 +0100 Subject: [PATCH 3/5] fix: review suggestions, second part --- docs/topics/jvm/java-interop.md | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/docs/topics/jvm/java-interop.md b/docs/topics/jvm/java-interop.md index 979421a0d12..92a99645d38 100644 --- a/docs/topics/jvm/java-interop.md +++ b/docs/topics/jvm/java-interop.md @@ -207,14 +207,25 @@ Kotlin types. The compiler supports several flavors of nullability annotations, * [Lombok](lombok.md) (`lombok.NonNull`) * RxJava 3 (`io.reactivex.rxjava3.annotations`) -You can specify whether the compiler reports a nullability mismatch based on the information from specific types of -nullability annotations. Use the compiler option `-Xnullability-annotations=@:`. -In the argument, specify the fully qualified nullability annotations package and one of these report levels: +You can instruct the compiler to report a nullability mismatch based on the information from specific types of +nullability annotations with the following compiler option: + +```bash +-Xnullability-annotations=@: +``` + +Specify the package name for the fully qualified nullability annotations and one of these report levels: + * `ignore` to ignore nullability mismatches * `warn` to report warnings * `strict` to report errors. -See the full list of supported nullability annotations in the +> [JSpecify](#jspecify-support) is the recommended choice for nullability annotations because it's the only +> supported flavor that uses `strict` report level by default. +> +{style="note"} + +See the full list of supported nullability annotations in the [Kotlin compiler source code](https://github.com/JetBrains/kotlin/blob/master/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.kt). ### Annotating type arguments and type parameters @@ -325,6 +336,12 @@ Kotlin supports the following annotations in the `org.jspecify.annotations` pack * `@NullMarked` marks all types within a scope, for example a class or package, as non-nullable by default unless annotated otherwise. + This does not apply to local variables and [type variables (generics)](https://jspecify.dev/docs/user-guide/#using-type-variables-in-generic-types). + Type variables remain "null-agnostic" until a specific nullable or non-nullable type is provided later. + +* `@NullUnmarked` reverses the effect of `@NullMarked`, making all types within the scope [platform types](#null-safety-and-platform-types) + again. + Consider the following Java class with JSpecify annotations: ```java @@ -351,8 +368,8 @@ fun test(inventory: InventoryService) { By default, the Kotlin compiler reports nullability mismatches for JSpecify annotations as errors. You can customize the severity of JSpecify nullability diagnostics using the following compiler option: -```properties --Xnullability-annotations=@org.jspecify.annotations: +```bash +-Xjspecify-annotations= ``` Available report levels are: @@ -363,7 +380,9 @@ Available report levels are: | `warn` | Reports warnings. | | `ignore` | Ignores nullability mismatches. | -For more information, see the [JSpecify user guide](https://jspecify.dev/docs/user-guide). +> For more information on JSpecify annotations, see the [JSpecify user guide](https://jspecify.dev/docs/user-guide). +> +{type="tip"} ### JSR-305 support From 903af0d8eb8868e64a894f14934bf36e2bacdf50 Mon Sep 17 00:00:00 2001 From: Danil Pavlov Date: Tue, 24 Feb 2026 19:47:20 +0100 Subject: [PATCH 4/5] fix: review suggestions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Dániel Csorba <150924204+daniCsorbaJB@users.noreply.github.com> --- docs/topics/jvm/java-interop.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/topics/jvm/java-interop.md b/docs/topics/jvm/java-interop.md index 92a99645d38..29bddb92d76 100644 --- a/docs/topics/jvm/java-interop.md +++ b/docs/topics/jvm/java-interop.md @@ -326,8 +326,8 @@ nullability annotations support the `TYPE_USE` target (`org.jetbrains.annotation ### JSpecify support Kotlin supports the [JSpecify](https://jspecify.dev/) nullability annotations, which provide a unified set of annotations -for Java nullness. JSpecify allows you to provide detailed nullability information for Java declarations, -helping Kotlin maintain null-safety when interoperating with Java code. +for Java nullability. JSpecify allows you to provide detailed nullability information for Java declarations, +helping Kotlin maintain null-safety when working with Java code. Kotlin supports the following annotations in the `org.jspecify.annotations` package: @@ -336,10 +336,10 @@ Kotlin supports the following annotations in the `org.jspecify.annotations` pack * `@NullMarked` marks all types within a scope, for example a class or package, as non-nullable by default unless annotated otherwise. - This does not apply to local variables and [type variables (generics)](https://jspecify.dev/docs/user-guide/#using-type-variables-in-generic-types). - Type variables remain "null-agnostic" until a specific nullable or non-nullable type is provided later. + This annotation doesn't apply to local variables and [type variables (generics)](https://jspecify.dev/docs/user-guide/#using-type-variables-in-generic-types). + Type variables remain "null-agnostic" until a specific nullable or non-nullable type is provided. -* `@NullUnmarked` reverses the effect of `@NullMarked`, making all types within the scope [platform types](#null-safety-and-platform-types) +* `@NullUnmarked` reverses the effect of `@NullMarked`, making all types within the scope [platform types](#null-safety-and-platform-types). again. Consider the following Java class with JSpecify annotations: @@ -361,7 +361,7 @@ In Kotlin, these are treated as regular nullable and non-nullable types rather t // Kotlin fun test(inventory: InventoryService) { inventory.notNull().length // OK - inventory.nullable().length // Error: only safe (?.) or non-null asserted (!!.) calls are allowed + inventory.nullable().length // Error: only safe (?.) or non-null asserted (!!) calls are allowed } ``` From 61052c3b0f3c6fda24d46943292deb41264dc18a Mon Sep 17 00:00:00 2001 From: Danil Pavlov Date: Tue, 24 Feb 2026 19:59:17 +0100 Subject: [PATCH 5/5] fix: review suggestions --- docs/topics/jvm/java-interop.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/topics/jvm/java-interop.md b/docs/topics/jvm/java-interop.md index 29bddb92d76..69f86b8a01b 100644 --- a/docs/topics/jvm/java-interop.md +++ b/docs/topics/jvm/java-interop.md @@ -207,8 +207,7 @@ Kotlin types. The compiler supports several flavors of nullability annotations, * [Lombok](lombok.md) (`lombok.NonNull`) * RxJava 3 (`io.reactivex.rxjava3.annotations`) -You can instruct the compiler to report a nullability mismatch based on the information from specific types of -nullability annotations with the following compiler option: +You can instruct the compiler to report nullability mismatches for specific nullability annotations with the following compiler option: ```bash -Xnullability-annotations=@: @@ -220,8 +219,8 @@ Specify the package name for the fully qualified nullability annotations and one * `warn` to report warnings * `strict` to report errors. -> [JSpecify](#jspecify-support) is the recommended choice for nullability annotations because it's the only -> supported flavor that uses `strict` report level by default. +> [JSpecify](#jspecify-support) is the only supported flavor that uses `strict` report level by default. +> Use it to report errors on nullability annotations without additional configuration. > {style="note"} @@ -339,8 +338,7 @@ Kotlin supports the following annotations in the `org.jspecify.annotations` pack This annotation doesn't apply to local variables and [type variables (generics)](https://jspecify.dev/docs/user-guide/#using-type-variables-in-generic-types). Type variables remain "null-agnostic" until a specific nullable or non-nullable type is provided. -* `@NullUnmarked` reverses the effect of `@NullMarked`, making all types within the scope [platform types](#null-safety-and-platform-types). - again. +* `@NullUnmarked` reverses the effect of `@NullMarked`, making all types within the scope as [platform types](#null-safety-and-platform-types). Consider the following Java class with JSpecify annotations: