From 7a603a9d891b9068874ba9aeb6df6b8e54b1a485 Mon Sep 17 00:00:00 2001 From: cpovirk Date: Mon, 27 Sep 2021 17:43:54 -0700 Subject: [PATCH] Annotate `TypeToInstanceMap` classes for nullness. I believe these are the only user-facing classes that I missed (aside from some annotations, which don't need nullness annotations). I must have intended to pick them up after `ClassToInstanceMap`, but I completely forgot. I noticed only when I tried to remove our checker-compat-qual dependency. After this, I may send another CL to change some checker-compat-qual annotations into checker-qual and jsr305 annotations so that we can at least remove that dependency. RELNOTES=n/a PiperOrigin-RevId: 399322975 --- .../reflect/ImmutableTypeToInstanceMap.java | 8 ++++ .../reflect/MutableTypeToInstanceMap.java | 39 +++++++++++++------ .../common/reflect/TypeToInstanceMap.java | 18 +++++---- .../reflect/ImmutableTypeToInstanceMap.java | 8 ++++ .../reflect/MutableTypeToInstanceMap.java | 37 ++++++++++++++---- .../common/reflect/TypeToInstanceMap.java | 18 ++++++--- 6 files changed, 96 insertions(+), 32 deletions(-) diff --git a/android/guava/src/com/google/common/reflect/ImmutableTypeToInstanceMap.java b/android/guava/src/com/google/common/reflect/ImmutableTypeToInstanceMap.java index 7fad5ded3bdf..7112be010245 100644 --- a/android/guava/src/com/google/common/reflect/ImmutableTypeToInstanceMap.java +++ b/android/guava/src/com/google/common/reflect/ImmutableTypeToInstanceMap.java @@ -20,6 +20,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.DoNotCall; import java.util.Map; +import javax.annotation.CheckForNull; /** * A type-to-instance map backed by an {@link ImmutableMap}. See also {@link @@ -29,6 +30,7 @@ * @since 13.0 */ @Beta +@ElementTypesAreNonnullByDefault public final class ImmutableTypeToInstanceMap extends ForwardingMap, B> implements TypeToInstanceMap { @@ -102,11 +104,13 @@ private ImmutableTypeToInstanceMap(ImmutableMap, B> deleg } @Override + @CheckForNull public T getInstance(TypeToken type) { return trustedGet(type.rejectTypeVariables()); } @Override + @CheckForNull public T getInstance(Class type) { return trustedGet(TypeToken.of(type)); } @@ -121,6 +125,7 @@ public T getInstance(Class type) { @Deprecated @Override @DoNotCall("Always throws UnsupportedOperationException") + @CheckForNull public T putInstance(TypeToken type, T value) { throw new UnsupportedOperationException(); } @@ -135,6 +140,7 @@ public T putInstance(TypeToken type, T value) { @Deprecated @Override @DoNotCall("Always throws UnsupportedOperationException") + @CheckForNull public T putInstance(Class type, T value) { throw new UnsupportedOperationException(); } @@ -149,6 +155,7 @@ public T putInstance(Class type, T value) { @Deprecated @Override @DoNotCall("Always throws UnsupportedOperationException") + @CheckForNull public B put(TypeToken key, B value) { throw new UnsupportedOperationException(); } @@ -172,6 +179,7 @@ protected Map, B> delegate() { } @SuppressWarnings("unchecked") // value could not get in if not a T + @CheckForNull private T trustedGet(TypeToken type) { return (T) delegate.get(type); } diff --git a/android/guava/src/com/google/common/reflect/MutableTypeToInstanceMap.java b/android/guava/src/com/google/common/reflect/MutableTypeToInstanceMap.java index dccd2983b32c..f158d80f9367 100644 --- a/android/guava/src/com/google/common/reflect/MutableTypeToInstanceMap.java +++ b/android/guava/src/com/google/common/reflect/MutableTypeToInstanceMap.java @@ -28,43 +28,48 @@ import java.util.Iterator; import java.util.Map; import java.util.Set; -import org.checkerframework.checker.nullness.compatqual.NullableDecl; +import javax.annotation.CheckForNull; +import org.checkerframework.checker.nullness.qual.Nullable; /** * A mutable type-to-instance map. See also {@link ImmutableTypeToInstanceMap}. * + *

This implementation does support null values, despite how it is annotated; see + * discussion at {@link TypeToInstanceMap}. + * * @author Ben Yu * @since 13.0 */ @Beta +@ElementTypesAreNonnullByDefault public final class MutableTypeToInstanceMap extends ForwardingMap, B> implements TypeToInstanceMap { private final Map, B> backingMap = Maps.newHashMap(); @Override - @NullableDecl + @CheckForNull public T getInstance(Class type) { return trustedGet(TypeToken.of(type)); } @Override - @NullableDecl + @CheckForNull public T getInstance(TypeToken type) { return trustedGet(type.rejectTypeVariables()); } @Override @CanIgnoreReturnValue - @NullableDecl - public T putInstance(Class type, @NullableDecl T value) { + @CheckForNull + public T putInstance(Class type, T value) { return trustedPut(TypeToken.of(type), value); } @Override @CanIgnoreReturnValue - @NullableDecl - public T putInstance(TypeToken type, @NullableDecl T value) { + @CheckForNull + public T putInstance(TypeToken type, T value) { return trustedPut(type.rejectTypeVariables(), value); } @@ -78,6 +83,7 @@ public T putInstance(TypeToken type, @NullableDecl T value) { @Deprecated @Override @DoNotCall("Always throws UnsupportedOperationException") + @CheckForNull public B put(TypeToken key, B value) { throw new UnsupportedOperationException("Please use putInstance() instead."); } @@ -106,13 +112,13 @@ protected Map, B> delegate() { } @SuppressWarnings("unchecked") // value could not get in if not a T - @NullableDecl - private T trustedPut(TypeToken type, @NullableDecl T value) { + @CheckForNull + private T trustedPut(TypeToken type, T value) { return (T) backingMap.put(type, value); } @SuppressWarnings("unchecked") // value could not get in if not a T - @NullableDecl + @CheckForNull private T trustedGet(TypeToken type) { return (T) backingMap.get(type); } @@ -135,11 +141,20 @@ public Iterator> iterator() { @Override public Object[] toArray() { - return standardToArray(); + /* + * standardToArray returns `@Nullable Object[]` rather than `Object[]` but only because it + * can be used with collections that may contain null. This collection is a collection of + * non-null Entry objects (Entry objects that might contain null values but are not + * themselves null), so we can treat it as a plain `Object[]`. + */ + @SuppressWarnings("nullness") + Object[] result = standardToArray(); + return result; } @Override - public T[] toArray(T[] array) { + @SuppressWarnings("nullness") // b/192354773 in our checker affects toArray declarations + public T[] toArray(T[] array) { return standardToArray(array); } }; diff --git a/android/guava/src/com/google/common/reflect/TypeToInstanceMap.java b/android/guava/src/com/google/common/reflect/TypeToInstanceMap.java index 80396bc7893f..8a329bdb38ed 100644 --- a/android/guava/src/com/google/common/reflect/TypeToInstanceMap.java +++ b/android/guava/src/com/google/common/reflect/TypeToInstanceMap.java @@ -18,7 +18,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.DoNotMock; import java.util.Map; -import org.checkerframework.checker.nullness.compatqual.NullableDecl; +import javax.annotation.CheckForNull; /** * A map, each entry of which maps a {@link TypeToken} to an instance of that type. In addition to @@ -35,12 +35,16 @@ *

Like any other {@code Map}, this map may contain entries for primitive types, * and a primitive type and its corresponding wrapper type may map to different values. * + *

This class's support for {@code null} requires some explanation. For details, see {@link + * ClassToInstanceMap}. Its explanation applies equally well to {@code TypeToInstanceMap}. + * * @param the common supertype that all entries must share; often this is simply {@link Object} * @author Ben Yu * @since 13.0 */ @Beta @DoNotMock("Use ImmutableTypeToInstanceMap or MutableTypeToInstanceMap") +@ElementTypesAreNonnullByDefault public interface TypeToInstanceMap extends Map, B> { /** @@ -51,7 +55,7 @@ public interface TypeToInstanceMap extends Map, B> { *

{@code getInstance(Foo.class)} is equivalent to {@code * getInstance(TypeToken.of(Foo.class))}. */ - @NullableDecl + @CheckForNull T getInstance(Class type); /** @@ -59,7 +63,7 @@ public interface TypeToInstanceMap extends Map, B> { * present. This will only return a value that was bound to this specific type, not a value that * may have been bound to a subtype. */ - @NullableDecl + @CheckForNull T getInstance(TypeToken type); /** @@ -73,8 +77,8 @@ public interface TypeToInstanceMap extends Map, B> { * null} if there was no previous entry. */ @CanIgnoreReturnValue - @NullableDecl - T putInstance(Class type, @NullableDecl T value); + @CheckForNull + T putInstance(Class type, T value); /** * Maps the specified type to the specified value. Does not associate this value with any @@ -84,6 +88,6 @@ public interface TypeToInstanceMap extends Map, B> { * if there was no previous entry. */ @CanIgnoreReturnValue - @NullableDecl - T putInstance(TypeToken type, @NullableDecl T value); + @CheckForNull + T putInstance(TypeToken type, T value); } diff --git a/guava/src/com/google/common/reflect/ImmutableTypeToInstanceMap.java b/guava/src/com/google/common/reflect/ImmutableTypeToInstanceMap.java index 7fad5ded3bdf..7112be010245 100644 --- a/guava/src/com/google/common/reflect/ImmutableTypeToInstanceMap.java +++ b/guava/src/com/google/common/reflect/ImmutableTypeToInstanceMap.java @@ -20,6 +20,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.DoNotCall; import java.util.Map; +import javax.annotation.CheckForNull; /** * A type-to-instance map backed by an {@link ImmutableMap}. See also {@link @@ -29,6 +30,7 @@ * @since 13.0 */ @Beta +@ElementTypesAreNonnullByDefault public final class ImmutableTypeToInstanceMap extends ForwardingMap, B> implements TypeToInstanceMap { @@ -102,11 +104,13 @@ private ImmutableTypeToInstanceMap(ImmutableMap, B> deleg } @Override + @CheckForNull public T getInstance(TypeToken type) { return trustedGet(type.rejectTypeVariables()); } @Override + @CheckForNull public T getInstance(Class type) { return trustedGet(TypeToken.of(type)); } @@ -121,6 +125,7 @@ public T getInstance(Class type) { @Deprecated @Override @DoNotCall("Always throws UnsupportedOperationException") + @CheckForNull public T putInstance(TypeToken type, T value) { throw new UnsupportedOperationException(); } @@ -135,6 +140,7 @@ public T putInstance(TypeToken type, T value) { @Deprecated @Override @DoNotCall("Always throws UnsupportedOperationException") + @CheckForNull public T putInstance(Class type, T value) { throw new UnsupportedOperationException(); } @@ -149,6 +155,7 @@ public T putInstance(Class type, T value) { @Deprecated @Override @DoNotCall("Always throws UnsupportedOperationException") + @CheckForNull public B put(TypeToken key, B value) { throw new UnsupportedOperationException(); } @@ -172,6 +179,7 @@ protected Map, B> delegate() { } @SuppressWarnings("unchecked") // value could not get in if not a T + @CheckForNull private T trustedGet(TypeToken type) { return (T) delegate.get(type); } diff --git a/guava/src/com/google/common/reflect/MutableTypeToInstanceMap.java b/guava/src/com/google/common/reflect/MutableTypeToInstanceMap.java index 2d21dbbcc7f8..f158d80f9367 100644 --- a/guava/src/com/google/common/reflect/MutableTypeToInstanceMap.java +++ b/guava/src/com/google/common/reflect/MutableTypeToInstanceMap.java @@ -28,39 +28,48 @@ import java.util.Iterator; import java.util.Map; import java.util.Set; +import javax.annotation.CheckForNull; import org.checkerframework.checker.nullness.qual.Nullable; /** * A mutable type-to-instance map. See also {@link ImmutableTypeToInstanceMap}. * + *

This implementation does support null values, despite how it is annotated; see + * discussion at {@link TypeToInstanceMap}. + * * @author Ben Yu * @since 13.0 */ @Beta +@ElementTypesAreNonnullByDefault public final class MutableTypeToInstanceMap extends ForwardingMap, B> implements TypeToInstanceMap { private final Map, B> backingMap = Maps.newHashMap(); @Override - public @Nullable T getInstance(Class type) { + @CheckForNull + public T getInstance(Class type) { return trustedGet(TypeToken.of(type)); } @Override - public @Nullable T getInstance(TypeToken type) { + @CheckForNull + public T getInstance(TypeToken type) { return trustedGet(type.rejectTypeVariables()); } @Override @CanIgnoreReturnValue - public @Nullable T putInstance(Class type, @Nullable T value) { + @CheckForNull + public T putInstance(Class type, T value) { return trustedPut(TypeToken.of(type), value); } @Override @CanIgnoreReturnValue - public @Nullable T putInstance(TypeToken type, @Nullable T value) { + @CheckForNull + public T putInstance(TypeToken type, T value) { return trustedPut(type.rejectTypeVariables(), value); } @@ -74,6 +83,7 @@ public final class MutableTypeToInstanceMap extends ForwardingMap key, B value) { throw new UnsupportedOperationException("Please use putInstance() instead."); } @@ -102,12 +112,14 @@ protected Map, B> delegate() { } @SuppressWarnings("unchecked") // value could not get in if not a T - private @Nullable T trustedPut(TypeToken type, @Nullable T value) { + @CheckForNull + private T trustedPut(TypeToken type, T value) { return (T) backingMap.put(type, value); } @SuppressWarnings("unchecked") // value could not get in if not a T - private @Nullable T trustedGet(TypeToken type) { + @CheckForNull + private T trustedGet(TypeToken type) { return (T) backingMap.get(type); } @@ -129,11 +141,20 @@ public Iterator> iterator() { @Override public Object[] toArray() { - return standardToArray(); + /* + * standardToArray returns `@Nullable Object[]` rather than `Object[]` but only because it + * can be used with collections that may contain null. This collection is a collection of + * non-null Entry objects (Entry objects that might contain null values but are not + * themselves null), so we can treat it as a plain `Object[]`. + */ + @SuppressWarnings("nullness") + Object[] result = standardToArray(); + return result; } @Override - public T[] toArray(T[] array) { + @SuppressWarnings("nullness") // b/192354773 in our checker affects toArray declarations + public T[] toArray(T[] array) { return standardToArray(array); } }; diff --git a/guava/src/com/google/common/reflect/TypeToInstanceMap.java b/guava/src/com/google/common/reflect/TypeToInstanceMap.java index 443b2580cfc5..8a329bdb38ed 100644 --- a/guava/src/com/google/common/reflect/TypeToInstanceMap.java +++ b/guava/src/com/google/common/reflect/TypeToInstanceMap.java @@ -18,7 +18,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.DoNotMock; import java.util.Map; -import org.checkerframework.checker.nullness.qual.Nullable; +import javax.annotation.CheckForNull; /** * A map, each entry of which maps a {@link TypeToken} to an instance of that type. In addition to @@ -35,12 +35,16 @@ *

Like any other {@code Map}, this map may contain entries for primitive types, * and a primitive type and its corresponding wrapper type may map to different values. * + *

This class's support for {@code null} requires some explanation. For details, see {@link + * ClassToInstanceMap}. Its explanation applies equally well to {@code TypeToInstanceMap}. + * * @param the common supertype that all entries must share; often this is simply {@link Object} * @author Ben Yu * @since 13.0 */ @Beta @DoNotMock("Use ImmutableTypeToInstanceMap or MutableTypeToInstanceMap") +@ElementTypesAreNonnullByDefault public interface TypeToInstanceMap extends Map, B> { /** @@ -51,14 +55,16 @@ public interface TypeToInstanceMap extends Map, B> { *

{@code getInstance(Foo.class)} is equivalent to {@code * getInstance(TypeToken.of(Foo.class))}. */ - @Nullable T getInstance(Class type); + @CheckForNull + T getInstance(Class type); /** * Returns the value the specified type is mapped to, or {@code null} if no entry for this type is * present. This will only return a value that was bound to this specific type, not a value that * may have been bound to a subtype. */ - @Nullable T getInstance(TypeToken type); + @CheckForNull + T getInstance(TypeToken type); /** * Maps the specified class to the specified value. Does not associate this value with any @@ -71,7 +77,8 @@ public interface TypeToInstanceMap extends Map, B> { * null} if there was no previous entry. */ @CanIgnoreReturnValue - @Nullable T putInstance(Class type, @Nullable T value); + @CheckForNull + T putInstance(Class type, T value); /** * Maps the specified type to the specified value. Does not associate this value with any @@ -81,5 +88,6 @@ public interface TypeToInstanceMap extends Map, B> { * if there was no previous entry. */ @CanIgnoreReturnValue - @Nullable T putInstance(TypeToken type, @Nullable T value); + @CheckForNull + T putInstance(TypeToken type, T value); }