| // Test case for Issue 1633: |
| // https://github.com/typetools/checker-framework/issues/1633 |
| |
| import java.util.function.Supplier; |
| import org.checkerframework.checker.nullness.qual.*; |
| import org.checkerframework.checker.nullness.qual.NonNull; |
| import org.checkerframework.checker.nullness.qual.Nullable; |
| import org.checkerframework.framework.qual.Covariant; |
| |
| public class Issue1633 { |
| |
| // supplyNullable is a supplier that may return null. |
| // supplyNonNull is a supplier that does not return null. |
| |
| void foo1(Optional1633<String> o, Supplier<@Nullable String> supplyNullable) { |
| // :: error: (argument) |
| @Nullable String str = o.orElseGetUnannotated(supplyNullable); |
| } |
| |
| void foo2(Optional1633<String> o, Supplier<@Nullable String> supplyNullable) { |
| @Nullable String str1 = o.orElseGetNullable(supplyNullable); |
| } |
| |
| void foo2nw(Optional1633<String> o, Supplier<@Nullable String> supplyNullable) { |
| @Nullable String str1 = o.orElseGetNullableNoWildcard(supplyNullable); |
| } |
| |
| void foo3(Optional1633<String> o, Supplier<@Nullable String> supplyNullable) { |
| // :: error: (argument) |
| @Nullable String str2 = o.orElseGetNonNull(supplyNullable); |
| } |
| |
| void foo4(Optional1633<String> o, Supplier<@Nullable String> supplyNullable) { |
| @Nullable String str3 = o.orElseGetPolyNull(supplyNullable); |
| } |
| |
| void foo4nw(Optional1633<String> o, Supplier<@Nullable String> supplyNullable) { |
| @Nullable String str3 = o.orElseGetPolyNullNoWildcard(supplyNullable); |
| } |
| |
| void foo41(Optional1633<String> o) { |
| @SuppressWarnings("return") // https://tinyurl.com/cfissue/979 |
| @Nullable String str3 = o.orElseGetPolyNull(() -> null); |
| } |
| |
| void foo41nw(Optional1633<String> o) { |
| @SuppressWarnings("return") // https://tinyurl.com/cfissue/979 |
| @Nullable String str3 = o.orElseGetPolyNullNoWildcard(() -> null); |
| } |
| |
| void foo5(Optional1633<String> o, Supplier<@NonNull String> supplyNonNull) { |
| @NonNull String str = o.orElseGetUnannotated(supplyNonNull); |
| } |
| |
| void foo6(Optional1633<String> o, Supplier<@NonNull String> supplyNonNull) { |
| // :: error: (assignment) |
| @NonNull String str1 = o.orElseGetNullable(supplyNonNull); |
| } |
| |
| void foo6nw(Optional1633<String> o, Supplier<@NonNull String> supplyNonNull) { |
| // :: error: (assignment) |
| @NonNull String str1 = o.orElseGetNullableNoWildcard(supplyNonNull); |
| } |
| |
| void foo7(Optional1633<String> o, Supplier<@NonNull String> supplyNonNull) { |
| @NonNull String str2 = o.orElseGetNonNull(supplyNonNull); |
| } |
| |
| void foo8(Optional1633<String> o, Supplier<@NonNull String> supplyNonNull) { |
| @NonNull String str3 = o.orElseGetPolyNull(supplyNonNull); |
| } |
| |
| void foo8nw(Optional1633<String> o, Supplier<@NonNull String> supplyNonNull) { |
| @NonNull String str3 = o.orElseGetPolyNullNoWildcard(supplyNonNull); |
| } |
| } |
| |
| // From the JDK |
| @Covariant(0) |
| final @NonNull class Optional1633<T extends @Nullable Object> { |
| |
| /** If non-null, the value; if null, indicates no value is present. */ |
| private final @Nullable T value = null; |
| |
| // TODO: there are conceptually two versions of this method: |
| // public @Nullable T orElseGet(Supplier<? extends @Nullable T> other) { |
| // public @NonNull T orElseGet(Supplier<? extends @NonNull T> other) { |
| // Issue #1633 says that this annotation doesn't help at all: |
| // public @PolyNull T orElseGet(Supplier<? extends @PolyNull T> other) { |
| // but it does seem to work in this test case. |
| public T orElseGetUnannotated(Supplier<? extends T> other) { |
| return value != null ? value : other.get(); |
| } |
| |
| public @Nullable T orElseGetNullable(Supplier<@Nullable ? extends @Nullable T> other) { |
| return value != null ? value : other.get(); |
| } |
| |
| public @Nullable T orElseGetNullableNoWildcard(Supplier<? extends @Nullable T> other) { |
| // The commented-out line fails to typecheck due to issue #979 |
| // return value != null ? value : other.get(); |
| if (value != null) { |
| return value; |
| } else { |
| return other.get(); |
| } |
| } |
| |
| public @NonNull T orElseGetNonNull(Supplier<@NonNull ? extends @NonNull T> other) { |
| return value != null ? value : other.get(); |
| } |
| |
| public @PolyNull T orElseGetPolyNull(Supplier<@PolyNull ? extends @PolyNull T> other) { |
| return value != null ? value : other.get(); |
| } |
| |
| public @PolyNull T orElseGetPolyNullNoWildcard(Supplier<? extends @PolyNull T> other) { |
| // The commented-out line fails to typecheck due to issue #979 |
| // return value != null ? value : other.get(); |
| if (value != null) { |
| return value; |
| } else { |
| return other.get(); |
| } |
| } |
| } |