diff --git a/api/BUILD.bazel b/api/BUILD.bazel index 4c5e750b5e4..3d1543a0192 100644 --- a/api/BUILD.bazel +++ b/api/BUILD.bazel @@ -11,6 +11,7 @@ java_library( deps = [ artifact("com.google.code.findbugs:jsr305"), artifact("com.google.errorprone:error_prone_annotations"), + artifact("org.jspecify:jspecify"), artifact("com.google.guava:failureaccess"), # future transitive dep of Guava. See #5214 artifact("com.google.guava:guava"), ], diff --git a/api/build.gradle b/api/build.gradle index 415a17f61f8..f4a254d3934 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -37,6 +37,7 @@ dependencies { compileOnly sourceSets.context.output api libraries.jsr305, libraries.errorprone.annotations + libraries.jspecify implementation libraries.guava testFixturesApi libraries.truth diff --git a/api/src/main/java/io/grpc/StatusOr.java b/api/src/main/java/io/grpc/StatusOr.java index 0f1e9da3c75..1850020a136 100644 --- a/api/src/main/java/io/grpc/StatusOr.java +++ b/api/src/main/java/io/grpc/StatusOr.java @@ -22,25 +22,27 @@ import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.base.Objects; -import javax.annotation.Nullable; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; /** Either a Status or a value. */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/11563") -public class StatusOr { - private StatusOr(Status status, T value) { +@NullMarked +public class StatusOr { + private StatusOr(@Nullable Status status, @Nullable T value) { + assert status == null || value == null : "is `status` is not `null` then `value` should be `null`"; this.status = status; this.value = value; } /** Construct from a value. */ - public static StatusOr fromValue(@Nullable T value) { - StatusOr result = new StatusOr(null, value); - return result; + public static StatusOr fromValue(T value) { + return new StatusOr<>(null, value); } /** Construct from a non-Ok status. */ - public static StatusOr fromStatus(Status status) { - StatusOr result = new StatusOr(checkNotNull(status, "status"), null); + public static StatusOr fromStatus(Status status) { + StatusOr result = new StatusOr<>(checkNotNull(status, "status"), null); checkArgument(!status.isOk(), "cannot use OK status: %s", status); return result; } @@ -54,7 +56,7 @@ public boolean hasValue() { * Returns the value if set or throws exception if there is no value set. This method is meant * to be called after checking the return value of hasValue() first. */ - public @Nullable T getValue() { + public T getValue() { if (status != null) { throw new IllegalStateException("No value present."); } @@ -105,6 +107,6 @@ public String toString() { return stringHelper.toString(); } - private final Status status; - private final T value; + private final @Nullable Status status; + private final @Nullable T value; } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cb5dce02843..075909a818d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -34,6 +34,7 @@ cronet-embedded = "org.chromium.net:cronet-embedded:119.6045.31" errorprone-annotations = "com.google.errorprone:error_prone_annotations:2.36.0" # error-prone 2.32.0+ require Java 17+ errorprone-core = "com.google.errorprone:error_prone_core:2.31.0" +jspecify = "org.jspecify:jspecify:1.0.0" google-api-protos = "com.google.api.grpc:proto-google-common-protos:2.59.2" # google-auth-library 1.25.0+ requires error_prone_annotations 2.31.0+, which # breaks the Android build