Skip to content

Commit 2e95e32

Browse files
authored
Add Optional annotations for primitive numeric Optional wrappers
1 parent 7f2fadb commit 2e95e32

File tree

3 files changed

+55
-15
lines changed

3 files changed

+55
-15
lines changed

src/java.base/share/classes/java/util/OptionalDouble.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,13 @@
2727
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
2828
import org.checkerframework.checker.nullness.qual.NonNull;
2929
import org.checkerframework.checker.nullness.qual.Nullable;
30+
import org.checkerframework.checker.optional.qual.Present;
3031
import org.checkerframework.dataflow.qual.Pure;
3132
import org.checkerframework.dataflow.qual.SideEffectFree;
3233
import org.checkerframework.framework.qual.AnnotatedFor;
34+
import org.checkerframework.framework.qual.EnsuresQualifier;
35+
import org.checkerframework.framework.qual.EnsuresQualifierIf;
36+
3337

3438
import java.util.function.DoubleConsumer;
3539
import java.util.function.DoubleSupplier;
@@ -62,9 +66,9 @@
6266
*
6367
* @since 1.8
6468
*/
65-
@AnnotatedFor({"lock", "nullness"})
69+
@AnnotatedFor({"lock", "nullness", "optional"})
6670
@jdk.internal.ValueBased
67-
public final class OptionalDouble {
71+
public final @NonNull class OptionalDouble {
6872
/**
6973
* Common instance for {@code empty()}.
7074
*/
@@ -120,7 +124,8 @@ private OptionalDouble(double value) {
120124
* @param value the value to describe
121125
* @return an {@code OptionalDouble} with the value present
122126
*/
123-
public static OptionalDouble of(double value) {
127+
@SideEffectFree
128+
public static @Present OptionalDouble of(double value) {
124129
return new OptionalDouble(value);
125130
}
126131

@@ -134,7 +139,8 @@ public static OptionalDouble of(double value) {
134139
* @return the value described by this {@code OptionalDouble}
135140
* @throws NoSuchElementException if no value is present
136141
*/
137-
public double getAsDouble() {
142+
@Pure
143+
public double getAsDouble(@Present OptionalDouble this) {
138144
if (!isPresent) {
139145
throw new NoSuchElementException("No value present");
140146
}
@@ -146,6 +152,8 @@ public double getAsDouble() {
146152
*
147153
* @return {@code true} if a value is present, otherwise {@code false}
148154
*/
155+
@Pure
156+
@EnsuresQualifierIf(result = true, expression = "this", qualifier = Present.class)
149157
public boolean isPresent() {
150158
return isPresent;
151159
}
@@ -158,6 +166,7 @@ public boolean isPresent() {
158166
* @since 11
159167
*/
160168
@Pure
169+
@EnsuresQualifierIf(result = false, expression = "this", qualifier = Present.class)
161170
public boolean isEmpty() {
162171
return !isPresent;
163172
}
@@ -212,6 +221,7 @@ public void ifPresentOrElse(DoubleConsumer action, Runnable emptyAction) {
212221
* @return the optional value as a {@code DoubleStream}
213222
* @since 9
214223
*/
224+
@SideEffectFree
215225
public DoubleStream stream() {
216226
if (isPresent) {
217227
return DoubleStream.of(value);
@@ -253,7 +263,9 @@ public double orElseGet(DoubleSupplier supplier) {
253263
* @throws NoSuchElementException if no value is present
254264
* @since 10
255265
*/
256-
public double orElseThrow() {
266+
@Pure
267+
@EnsuresQualifier(expression = "this", qualifier = Present.class)
268+
public double orElseThrow(@Present OptionalDouble this) {
257269
if (!isPresent) {
258270
throw new NoSuchElementException("No value present");
259271
}
@@ -277,6 +289,7 @@ public double orElseThrow() {
277289
* @throws NullPointerException if no value is present and the exception
278290
* supplying function is {@code null}
279291
*/
292+
@EnsuresQualifier(expression = "this", qualifier = Present.class)
280293
public<X extends Throwable> double orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
281294
if (isPresent) {
282295
return value;
@@ -320,6 +333,7 @@ public boolean equals(@Nullable Object obj) {
320333
* @return hash code value of the present value or {@code 0} if no value is
321334
* present
322335
*/
336+
@Pure
323337
@Override
324338
public int hashCode() {
325339
return isPresent ? Double.hashCode(value) : 0;

src/java.base/share/classes/java/util/OptionalInt.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,12 @@
2727
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
2828
import org.checkerframework.checker.nullness.qual.NonNull;
2929
import org.checkerframework.checker.nullness.qual.Nullable;
30+
import org.checkerframework.checker.optional.qual.Present;
3031
import org.checkerframework.dataflow.qual.Pure;
3132
import org.checkerframework.dataflow.qual.SideEffectFree;
3233
import org.checkerframework.framework.qual.AnnotatedFor;
34+
import org.checkerframework.framework.qual.EnsuresQualifier;
35+
import org.checkerframework.framework.qual.EnsuresQualifierIf;
3336

3437
import java.util.function.IntConsumer;
3538
import java.util.function.IntSupplier;
@@ -62,9 +65,9 @@
6265
*
6366
* @since 1.8
6467
*/
65-
@AnnotatedFor({"lock", "nullness"})
68+
@AnnotatedFor({"lock", "nullness", "optional"})
6669
@jdk.internal.ValueBased
67-
public final class OptionalInt {
70+
public final @NonNull class OptionalInt {
6871
/**
6972
* Common instance for {@code empty()}.
7073
*/
@@ -120,7 +123,8 @@ private OptionalInt(int value) {
120123
* @param value the value to describe
121124
* @return an {@code OptionalInt} with the value present
122125
*/
123-
public static OptionalInt of(int value) {
126+
@SideEffectFree
127+
public static @Present OptionalInt of(int value) {
124128
return new OptionalInt(value);
125129
}
126130

@@ -134,7 +138,8 @@ public static OptionalInt of(int value) {
134138
* @return the value described by this {@code OptionalInt}
135139
* @throws NoSuchElementException if no value is present
136140
*/
137-
public int getAsInt() {
141+
@Pure
142+
public int getAsInt(@Present OptionalInt this) {
138143
if (!isPresent) {
139144
throw new NoSuchElementException("No value present");
140145
}
@@ -146,6 +151,8 @@ public int getAsInt() {
146151
*
147152
* @return {@code true} if a value is present, otherwise {@code false}
148153
*/
154+
@Pure
155+
@EnsuresQualifierIf(result = true, expression = "this", qualifier = Present.class)
149156
public boolean isPresent() {
150157
return isPresent;
151158
}
@@ -158,6 +165,7 @@ public boolean isPresent() {
158165
* @since 11
159166
*/
160167
@Pure
168+
@EnsuresQualifierIf(result = false, expression = "this", qualifier = Present.class)
161169
public boolean isEmpty() {
162170
return !isPresent;
163171
}
@@ -211,6 +219,7 @@ public void ifPresentOrElse(IntConsumer action, Runnable emptyAction) {
211219
* @return the optional value as an {@code IntStream}
212220
* @since 9
213221
*/
222+
@SideEffectFree
214223
public IntStream stream() {
215224
if (isPresent) {
216225
return IntStream.of(value);
@@ -252,7 +261,9 @@ public int orElseGet(IntSupplier supplier) {
252261
* @throws NoSuchElementException if no value is present
253262
* @since 10
254263
*/
255-
public int orElseThrow() {
264+
@Pure
265+
@EnsuresQualifier(expression = "this", qualifier = Present.class)
266+
public int orElseThrow(@Present OptionalInt this) {
256267
if (!isPresent) {
257268
throw new NoSuchElementException("No value present");
258269
}
@@ -276,6 +287,7 @@ public int orElseThrow() {
276287
* @throws NullPointerException if no value is present and the exception
277288
* supplying function is {@code null}
278289
*/
290+
@EnsuresQualifier(expression = "this", qualifier = Present.class)
279291
public<X extends Throwable> int orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
280292
if (isPresent) {
281293
return value;
@@ -318,6 +330,7 @@ public boolean equals(@Nullable Object obj) {
318330
* @return hash code value of the present value or {@code 0} if no value is
319331
* present
320332
*/
333+
@Pure
321334
@Override
322335
public int hashCode() {
323336
return isPresent ? Integer.hashCode(value) : 0;

src/java.base/share/classes/java/util/OptionalLong.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,12 @@
2727
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
2828
import org.checkerframework.checker.nullness.qual.NonNull;
2929
import org.checkerframework.checker.nullness.qual.Nullable;
30+
import org.checkerframework.checker.optional.qual.Present;
3031
import org.checkerframework.dataflow.qual.Pure;
3132
import org.checkerframework.dataflow.qual.SideEffectFree;
3233
import org.checkerframework.framework.qual.AnnotatedFor;
34+
import org.checkerframework.framework.qual.EnsuresQualifier;
35+
import org.checkerframework.framework.qual.EnsuresQualifierIf;
3336

3437
import java.util.function.LongConsumer;
3538
import java.util.function.LongSupplier;
@@ -62,9 +65,9 @@
6265
*
6366
* @since 1.8
6467
*/
65-
@AnnotatedFor({"lock", "nullness"})
68+
@AnnotatedFor({"lock", "nullness", "optional"})
6669
@jdk.internal.ValueBased
67-
public final class OptionalLong {
70+
public final @NonNull class OptionalLong {
6871
/**
6972
* Common instance for {@code empty()}.
7073
*/
@@ -120,7 +123,8 @@ private OptionalLong(long value) {
120123
* @param value the value to describe
121124
* @return an {@code OptionalLong} with the value present
122125
*/
123-
public static OptionalLong of(long value) {
126+
@SideEffectFree
127+
public static @Present OptionalLong of(long value) {
124128
return new OptionalLong(value);
125129
}
126130

@@ -134,7 +138,8 @@ public static OptionalLong of(long value) {
134138
* @return the value described by this {@code OptionalLong}
135139
* @throws NoSuchElementException if no value is present
136140
*/
137-
public long getAsLong() {
141+
@Pure
142+
public long getAsLong(@Present OptionalLong this) {
138143
if (!isPresent) {
139144
throw new NoSuchElementException("No value present");
140145
}
@@ -146,6 +151,8 @@ public long getAsLong() {
146151
*
147152
* @return {@code true} if a value is present, otherwise {@code false}
148153
*/
154+
@Pure
155+
@EnsuresQualifierIf(result = true, expression = "this", qualifier = Present.class)
149156
public boolean isPresent() {
150157
return isPresent;
151158
}
@@ -158,6 +165,7 @@ public boolean isPresent() {
158165
* @since 11
159166
*/
160167
@Pure
168+
@EnsuresQualifierIf(result = false, expression = "this", qualifier = Present.class)
161169
public boolean isEmpty() {
162170
return !isPresent;
163171
}
@@ -211,6 +219,7 @@ public void ifPresentOrElse(LongConsumer action, Runnable emptyAction) {
211219
* @return the optional value as an {@code LongStream}
212220
* @since 9
213221
*/
222+
@SideEffectFree
214223
public LongStream stream() {
215224
if (isPresent) {
216225
return LongStream.of(value);
@@ -252,7 +261,9 @@ public long orElseGet(LongSupplier supplier) {
252261
* @throws NoSuchElementException if no value is present
253262
* @since 10
254263
*/
255-
public long orElseThrow() {
264+
@Pure
265+
@EnsuresQualifier(expression = "this", qualifier = Present.class)
266+
public long orElseThrow(@Present OptionalLong this) {
256267
if (!isPresent) {
257268
throw new NoSuchElementException("No value present");
258269
}
@@ -276,6 +287,7 @@ public long orElseThrow() {
276287
* @throws NullPointerException if no value is present and the exception
277288
* supplying function is {@code null}
278289
*/
290+
@EnsuresQualifier(expression = "this", qualifier = Present.class)
279291
public<X extends Throwable> long orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
280292
if (isPresent) {
281293
return value;
@@ -318,6 +330,7 @@ public boolean equals(@Nullable Object obj) {
318330
* @return hash code value of the present value or {@code 0} if no value is
319331
* present
320332
*/
333+
@Pure
321334
@Override
322335
public int hashCode() {
323336
return isPresent ? Long.hashCode(value) : 0;

0 commit comments

Comments
 (0)