diff options
author | cpovirk <cpovirk@google.com> | 2023-06-26 13:53:57 -0700 |
---|---|---|
committer | Google Java Core Libraries <java-core-libraries-team+copybara@google.com> | 2023-06-26 14:02:13 -0700 |
commit | 1df87a86cb7f327e5d80e478f7bcda1061c2e861 (patch) | |
tree | 9f0e944afce16cc9683c33a3ffc49f2a8599c358 | |
parent | 80c8d9ce4a8ba63f9704113399a001e456e83e73 (diff) | |
download | guava-1df87a86cb7f327e5d80e478f7bcda1061c2e861.tar.gz |
Improve racy single-check init code:
- Use `@LazyInit` (to help J2ObjC and TSAN) on various `@CheckForNull transient` fields (and also on `UnmodifiableBiMap.inverse` and on the `LocalCache` fields, all of which are `@RetainedWith @CheckForNull`). I skipped some other such fields, including:
- `Synchronized` (which already uses, well, `synchronized`, making the check not racy)
- `TreeBasedTable.TreeRow` and some `common.graph` classes (e.g., `DirectedMultiNetworkConnections`), which are doing something more sophisticated.
- Update the TODO in `ImmutableSortedMap` about actually caching a view computed on the fly.
It's likely that I didn't get _every_ field that deserves an annotation. It's also likely that some of the fields should additionally use `@RetainedWith` or similar for J2ObjC purposes. And probably some fields would be better off with either eagerly computing the views or with not caching them at all (b/280079296). But this CL should be strictly an improvement over the status quo.
RELNOTES=n/a
PiperOrigin-RevId: 543532432
39 files changed, 142 insertions, 101 deletions
diff --git a/android/guava/src/com/google/common/cache/LocalCache.java b/android/guava/src/com/google/common/cache/LocalCache.java index 74df5a234..239afe204 100644 --- a/android/guava/src/com/google/common/cache/LocalCache.java +++ b/android/guava/src/com/google/common/cache/LocalCache.java @@ -52,6 +52,7 @@ import com.google.common.util.concurrent.UncheckedExecutionException; import com.google.common.util.concurrent.Uninterruptibles; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.concurrent.GuardedBy; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.RetainedWith; import com.google.j2objc.annotations.Weak; import java.io.IOException; @@ -4201,7 +4202,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> } } - @RetainedWith @CheckForNull Set<K> keySet; + @LazyInit @RetainedWith @CheckForNull Set<K> keySet; @Override public Set<K> keySet() { @@ -4210,7 +4211,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> return (ks != null) ? ks : (keySet = new KeySet()); } - @RetainedWith @CheckForNull Collection<V> values; + @LazyInit @RetainedWith @CheckForNull Collection<V> values; @Override public Collection<V> values() { @@ -4219,7 +4220,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> return (vs != null) ? vs : (values = new Values()); } - @RetainedWith @CheckForNull Set<Entry<K, V>> entrySet; + @LazyInit @RetainedWith @CheckForNull Set<Entry<K, V>> entrySet; @Override @GwtIncompatible // Not supported. diff --git a/android/guava/src/com/google/common/collect/AbstractBiMap.java b/android/guava/src/com/google/common/collect/AbstractBiMap.java index 56cf0a00a..10edc5c4c 100644 --- a/android/guava/src/com/google/common/collect/AbstractBiMap.java +++ b/android/guava/src/com/google/common/collect/AbstractBiMap.java @@ -25,6 +25,7 @@ import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.J2ktIncompatible; import com.google.common.base.Objects; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.RetainedWith; import com.google.j2objc.annotations.WeakOuter; import java.io.IOException; @@ -206,7 +207,7 @@ abstract class AbstractBiMap<K extends @Nullable Object, V extends @Nullable Obj return inverse; } - @CheckForNull private transient Set<K> keySet; + @LazyInit @CheckForNull private transient Set<K> keySet; @Override public Set<K> keySet() { @@ -251,7 +252,7 @@ abstract class AbstractBiMap<K extends @Nullable Object, V extends @Nullable Obj } } - @CheckForNull private transient Set<V> valueSet; + @LazyInit @CheckForNull private transient Set<V> valueSet; @Override public Set<V> values() { @@ -294,7 +295,7 @@ abstract class AbstractBiMap<K extends @Nullable Object, V extends @Nullable Obj } } - @CheckForNull private transient Set<Entry<K, V>> entrySet; + @LazyInit @CheckForNull private transient Set<Entry<K, V>> entrySet; @Override public Set<Entry<K, V>> entrySet() { diff --git a/android/guava/src/com/google/common/collect/AbstractSortedMultiset.java b/android/guava/src/com/google/common/collect/AbstractSortedMultiset.java index 621e8f98a..98b6211a7 100644 --- a/android/guava/src/com/google/common/collect/AbstractSortedMultiset.java +++ b/android/guava/src/com/google/common/collect/AbstractSortedMultiset.java @@ -17,6 +17,7 @@ package com.google.common.collect; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.GwtCompatible; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.WeakOuter; import java.util.Comparator; import java.util.Iterator; @@ -122,7 +123,7 @@ abstract class AbstractSortedMultiset<E extends @Nullable Object> extends Abstra return Multisets.iteratorImpl(descendingMultiset()); } - @CheckForNull private transient SortedMultiset<E> descendingMultiset; + @LazyInit @CheckForNull private transient SortedMultiset<E> descendingMultiset; @Override public SortedMultiset<E> descendingMultiset() { diff --git a/android/guava/src/com/google/common/collect/ArrayTable.java b/android/guava/src/com/google/common/collect/ArrayTable.java index d63853a82..97a784bac 100644 --- a/android/guava/src/com/google/common/collect/ArrayTable.java +++ b/android/guava/src/com/google/common/collect/ArrayTable.java @@ -27,6 +27,7 @@ import com.google.common.base.Objects; import com.google.common.collect.Maps.IteratorBasedAbstractMap; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.DoNotCall; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.WeakOuter; import java.io.Serializable; import java.lang.reflect.Array; @@ -648,7 +649,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, @Nullable V> return columnKeyToIndex.keySet(); } - @CheckForNull private transient ColumnMap columnMap; + @LazyInit @CheckForNull private transient ColumnMap columnMap; @Override public Map<C, Map<R, @Nullable V>> columnMap() { @@ -743,7 +744,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, @Nullable V> return rowKeyToIndex.keySet(); } - @CheckForNull private transient RowMap rowMap; + @LazyInit @CheckForNull private transient RowMap rowMap; @Override public Map<R, Map<C, @Nullable V>> rowMap() { diff --git a/android/guava/src/com/google/common/collect/CompactHashMap.java b/android/guava/src/com/google/common/collect/CompactHashMap.java index 1e5da07ac..d664c46ac 100644 --- a/android/guava/src/com/google/common/collect/CompactHashMap.java +++ b/android/guava/src/com/google/common/collect/CompactHashMap.java @@ -30,6 +30,7 @@ import com.google.common.base.Objects; import com.google.common.base.Preconditions; import com.google.common.primitives.Ints; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.WeakOuter; import java.io.IOException; import java.io.InvalidObjectException; @@ -671,7 +672,7 @@ class CompactHashMap<K extends @Nullable Object, V extends @Nullable Object> } } - @CheckForNull private transient Set<K> keySetView; + @LazyInit @CheckForNull private transient Set<K> keySetView; @Override public Set<K> keySet() { @@ -727,7 +728,7 @@ class CompactHashMap<K extends @Nullable Object, V extends @Nullable Object> }; } - @CheckForNull private transient Set<Entry<K, V>> entrySetView; + @LazyInit @CheckForNull private transient Set<Entry<K, V>> entrySetView; @Override public Set<Entry<K, V>> entrySet() { @@ -907,7 +908,7 @@ class CompactHashMap<K extends @Nullable Object, V extends @Nullable Object> return false; } - @CheckForNull private transient Collection<V> valuesView; + @LazyInit @CheckForNull private transient Collection<V> valuesView; @Override public Collection<V> values() { diff --git a/android/guava/src/com/google/common/collect/DescendingMultiset.java b/android/guava/src/com/google/common/collect/DescendingMultiset.java index 7db0fbbd4..23ff8319c 100644 --- a/android/guava/src/com/google/common/collect/DescendingMultiset.java +++ b/android/guava/src/com/google/common/collect/DescendingMultiset.java @@ -17,6 +17,7 @@ package com.google.common.collect; import com.google.common.annotations.GwtCompatible; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.WeakOuter; import java.util.Comparator; import java.util.Iterator; @@ -37,7 +38,7 @@ abstract class DescendingMultiset<E extends @Nullable Object> extends Forwarding implements SortedMultiset<E> { abstract SortedMultiset<E> forwardMultiset(); - @CheckForNull private transient Comparator<? super E> comparator; + @LazyInit @CheckForNull private transient Comparator<? super E> comparator; @Override public Comparator<? super E> comparator() { @@ -48,7 +49,7 @@ abstract class DescendingMultiset<E extends @Nullable Object> extends Forwarding return result; } - @CheckForNull private transient NavigableSet<E> elementSet; + @LazyInit @CheckForNull private transient NavigableSet<E> elementSet; @Override public NavigableSet<E> elementSet() { @@ -116,7 +117,7 @@ abstract class DescendingMultiset<E extends @Nullable Object> extends Forwarding abstract Iterator<Entry<E>> entryIterator(); - @CheckForNull private transient Set<Entry<E>> entrySet; + @LazyInit @CheckForNull private transient Set<Entry<E>> entrySet; @Override public Set<Entry<E>> entrySet() { diff --git a/android/guava/src/com/google/common/collect/GeneralRange.java b/android/guava/src/com/google/common/collect/GeneralRange.java index c5e1ba3c4..e462b7a01 100644 --- a/android/guava/src/com/google/common/collect/GeneralRange.java +++ b/android/guava/src/com/google/common/collect/GeneralRange.java @@ -22,6 +22,7 @@ import static com.google.common.collect.NullnessCasts.uncheckedCastNullableTToT; import com.google.common.annotations.GwtCompatible; import com.google.common.base.Objects; +import com.google.errorprone.annotations.concurrent.LazyInit; import java.io.Serializable; import java.util.Comparator; import javax.annotation.CheckForNull; @@ -263,7 +264,7 @@ final class GeneralRange<T extends @Nullable Object> implements Serializable { getUpperBoundType()); } - @CheckForNull private transient GeneralRange<T> reverse; + @LazyInit @CheckForNull private transient GeneralRange<T> reverse; /** Returns the same range relative to the reversed comparator. */ GeneralRange<T> reverse() { diff --git a/android/guava/src/com/google/common/collect/ImmutableRangeSet.java b/android/guava/src/com/google/common/collect/ImmutableRangeSet.java index e09bc4a84..844c1c1dc 100644 --- a/android/guava/src/com/google/common/collect/ImmutableRangeSet.java +++ b/android/guava/src/com/google/common/collect/ImmutableRangeSet.java @@ -542,7 +542,7 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange this.domain = domain; } - @CheckForNull private transient Integer size; + @LazyInit @CheckForNull private transient Integer size; @Override public int size() { diff --git a/android/guava/src/com/google/common/collect/ImmutableSortedMap.java b/android/guava/src/com/google/common/collect/ImmutableSortedMap.java index 6ee63c680..15c384eb7 100644 --- a/android/guava/src/com/google/common/collect/ImmutableSortedMap.java +++ b/android/guava/src/com/google/common/collect/ImmutableSortedMap.java @@ -1083,16 +1083,18 @@ public final class ImmutableSortedMap<K, V> extends ImmutableSortedMapFauxveride @Override public ImmutableSortedMap<K, V> descendingMap() { - // TODO(kevinb): the descendingMap is never actually cached at all. Either it should be or the - // code below simplified. + // TODO(kevinb): The descendingMap is never actually cached at all. Either: + // + // - Cache it, and annotate the field with @LazyInit. + // - Simplify the code below, and consider eliminating the field (b/287198172), which is also + // set by one of the constructors. ImmutableSortedMap<K, V> result = descendingMap; if (result == null) { if (isEmpty()) { - return result = emptyMap(Ordering.from(comparator()).reverse()); + return emptyMap(Ordering.from(comparator()).reverse()); } else { - return result = - new ImmutableSortedMap<>( - (RegularImmutableSortedSet<K>) keySet.descendingSet(), valueList.reverse(), this); + return new ImmutableSortedMap<>( + (RegularImmutableSortedSet<K>) keySet.descendingSet(), valueList.reverse(), this); } } return result; diff --git a/android/guava/src/com/google/common/collect/MapMakerInternalMap.java b/android/guava/src/com/google/common/collect/MapMakerInternalMap.java index e80ec27a5..c64d81eb3 100644 --- a/android/guava/src/com/google/common/collect/MapMakerInternalMap.java +++ b/android/guava/src/com/google/common/collect/MapMakerInternalMap.java @@ -25,6 +25,7 @@ import com.google.common.collect.MapMaker.Dummy; import com.google.common.primitives.Ints; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.concurrent.GuardedBy; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.Weak; import com.google.j2objc.annotations.WeakOuter; import java.io.IOException; @@ -2522,7 +2523,7 @@ class MapMakerInternalMap< } } - @CheckForNull transient Set<K> keySet; + @LazyInit @CheckForNull transient Set<K> keySet; @Override public Set<K> keySet() { @@ -2530,7 +2531,7 @@ class MapMakerInternalMap< return (ks != null) ? ks : (keySet = new KeySet()); } - @CheckForNull transient Collection<V> values; + @LazyInit @CheckForNull transient Collection<V> values; @Override public Collection<V> values() { @@ -2538,7 +2539,7 @@ class MapMakerInternalMap< return (vs != null) ? vs : (values = new Values()); } - @CheckForNull transient Set<Entry<K, V>> entrySet; + @LazyInit @CheckForNull transient Set<Entry<K, V>> entrySet; @Override public Set<Entry<K, V>> entrySet() { diff --git a/android/guava/src/com/google/common/collect/Maps.java b/android/guava/src/com/google/common/collect/Maps.java index 4e9792057..9a3852047 100644 --- a/android/guava/src/com/google/common/collect/Maps.java +++ b/android/guava/src/com/google/common/collect/Maps.java @@ -38,6 +38,7 @@ import com.google.common.base.Predicates; import com.google.common.collect.MapDifference.ValueDifference; import com.google.common.primitives.Ints; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.RetainedWith; import com.google.j2objc.annotations.Weak; import com.google.j2objc.annotations.WeakOuter; @@ -1605,8 +1606,8 @@ public final class Maps { extends ForwardingMap<K, V> implements BiMap<K, V>, Serializable { final Map<K, V> unmodifiableMap; final BiMap<? extends K, ? extends V> delegate; - @RetainedWith @CheckForNull BiMap<V, K> inverse; - @CheckForNull transient Set<V> values; + @LazyInit @RetainedWith @CheckForNull BiMap<V, K> inverse; + @LazyInit @CheckForNull transient Set<V> values; UnmodifiableBiMap(BiMap<? extends K, ? extends V> delegate, @CheckForNull BiMap<V, K> inverse) { unmodifiableMap = Collections.unmodifiableMap(delegate); @@ -3450,7 +3451,7 @@ public final class Maps { throw new UnsupportedOperationException(); } - @CheckForNull private transient UnmodifiableNavigableMap<K, V> descendingMap; + @LazyInit @CheckForNull private transient UnmodifiableNavigableMap<K, V> descendingMap; @Override public NavigableMap<K, V> descendingMap() { @@ -3580,7 +3581,7 @@ public final class Maps { */ abstract Set<Entry<K, V>> createEntrySet(); - @CheckForNull private transient Set<Entry<K, V>> entrySet; + @LazyInit @CheckForNull private transient Set<Entry<K, V>> entrySet; @Override public Set<Entry<K, V>> entrySet() { @@ -3588,7 +3589,7 @@ public final class Maps { return (result == null) ? entrySet = createEntrySet() : result; } - @CheckForNull private transient Set<K> keySet; + @LazyInit @CheckForNull private transient Set<K> keySet; @Override public Set<K> keySet() { @@ -3600,7 +3601,7 @@ public final class Maps { return new KeySet<>(this); } - @CheckForNull private transient Collection<V> values; + @LazyInit @CheckForNull private transient Collection<V> values; @Override public Collection<V> values() { @@ -4129,7 +4130,7 @@ public final class Maps { return forward(); } - @CheckForNull private transient Comparator<? super K> comparator; + @LazyInit @CheckForNull private transient Comparator<? super K> comparator; @SuppressWarnings("unchecked") @Override @@ -4239,7 +4240,7 @@ public final class Maps { return forward(); } - @CheckForNull private transient Set<Entry<K, V>> entrySet; + @LazyInit @CheckForNull private transient Set<Entry<K, V>> entrySet; @Override public Set<Entry<K, V>> entrySet() { @@ -4270,7 +4271,7 @@ public final class Maps { return navigableKeySet(); } - @CheckForNull private transient NavigableSet<K> navigableKeySet; + @LazyInit @CheckForNull private transient NavigableSet<K> navigableKeySet; @Override public NavigableSet<K> navigableKeySet() { diff --git a/android/guava/src/com/google/common/collect/Multisets.java b/android/guava/src/com/google/common/collect/Multisets.java index 0483de559..8bcc639ab 100644 --- a/android/guava/src/com/google/common/collect/Multisets.java +++ b/android/guava/src/com/google/common/collect/Multisets.java @@ -30,6 +30,7 @@ import com.google.common.collect.Multiset.Entry; import com.google.common.math.IntMath; import com.google.common.primitives.Ints; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.concurrent.LazyInit; import java.io.Serializable; import java.util.Arrays; import java.util.Collection; @@ -104,7 +105,7 @@ public final class Multisets { return (Multiset<E>) delegate; } - @CheckForNull transient Set<E> elementSet; + @LazyInit @CheckForNull transient Set<E> elementSet; Set<E> createElementSet() { return Collections.<E>unmodifiableSet(delegate.elementSet()); @@ -116,7 +117,7 @@ public final class Multisets { return (es == null) ? elementSet = createElementSet() : es; } - @CheckForNull transient Set<Multiset.Entry<E>> entrySet; + @LazyInit @CheckForNull transient Set<Multiset.Entry<E>> entrySet; @SuppressWarnings("unchecked") @Override diff --git a/android/guava/src/com/google/common/collect/NaturalOrdering.java b/android/guava/src/com/google/common/collect/NaturalOrdering.java index 8cb8aef9a..dae531270 100644 --- a/android/guava/src/com/google/common/collect/NaturalOrdering.java +++ b/android/guava/src/com/google/common/collect/NaturalOrdering.java @@ -19,6 +19,7 @@ package com.google.common.collect; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.GwtCompatible; +import com.google.errorprone.annotations.concurrent.LazyInit; import java.io.Serializable; import javax.annotation.CheckForNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -30,8 +31,9 @@ import org.checkerframework.checker.nullness.qual.Nullable; final class NaturalOrdering extends Ordering<Comparable<?>> implements Serializable { static final NaturalOrdering INSTANCE = new NaturalOrdering(); - @CheckForNull private transient Ordering<@Nullable Comparable<?>> nullsFirst; - @CheckForNull private transient Ordering<@Nullable Comparable<?>> nullsLast; + // TODO: b/287198172 - Consider eagerly initializing these (but think about serialization). + @LazyInit @CheckForNull private transient Ordering<@Nullable Comparable<?>> nullsFirst; + @LazyInit @CheckForNull private transient Ordering<@Nullable Comparable<?>> nullsLast; @Override public int compare(Comparable<?> left, Comparable<?> right) { diff --git a/android/guava/src/com/google/common/collect/Sets.java b/android/guava/src/com/google/common/collect/Sets.java index 4a62001f1..1f433f4b6 100644 --- a/android/guava/src/com/google/common/collect/Sets.java +++ b/android/guava/src/com/google/common/collect/Sets.java @@ -29,6 +29,7 @@ import com.google.common.collect.Collections2.FilteredCollection; import com.google.common.math.IntMath; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.DoNotCall; +import com.google.errorprone.annotations.concurrent.LazyInit; import java.io.Serializable; import java.util.AbstractSet; import java.util.Arrays; @@ -1802,7 +1803,7 @@ public final class Sets { throw new UnsupportedOperationException(); } - @CheckForNull private transient UnmodifiableNavigableSet<E> descendingSet; + @LazyInit @CheckForNull private transient UnmodifiableNavigableSet<E> descendingSet; @Override public NavigableSet<E> descendingSet() { diff --git a/android/guava/src/com/google/common/collect/StandardTable.java b/android/guava/src/com/google/common/collect/StandardTable.java index b2dacf181..e039877a9 100644 --- a/android/guava/src/com/google/common/collect/StandardTable.java +++ b/android/guava/src/com/google/common/collect/StandardTable.java @@ -34,6 +34,7 @@ import com.google.common.collect.Maps.IteratorBasedAbstractMap; import com.google.common.collect.Maps.ViewCachingAbstractMap; import com.google.common.collect.Sets.ImprovedAbstractSet; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.WeakOuter; import java.io.Serializable; import java.util.Collection; @@ -649,7 +650,7 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa return rowMap().keySet(); } - @CheckForNull private transient Set<C> columnKeySet; + @LazyInit @CheckForNull private transient Set<C> columnKeySet; /** * {@inheritDoc} @@ -780,7 +781,7 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa return super.values(); } - @CheckForNull private transient Map<R, Map<C, V>> rowMap; + @LazyInit @CheckForNull private transient Map<R, Map<C, V>> rowMap; @Override public Map<R, Map<C, V>> rowMap() { @@ -862,7 +863,7 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa } } - @CheckForNull private transient ColumnMap columnMap; + @LazyInit @CheckForNull private transient ColumnMap columnMap; @Override public Map<C, Map<R, V>> columnMap() { diff --git a/android/guava/src/com/google/common/collect/TreeRangeSet.java b/android/guava/src/com/google/common/collect/TreeRangeSet.java index 967981ff6..415e80ffb 100644 --- a/android/guava/src/com/google/common/collect/TreeRangeSet.java +++ b/android/guava/src/com/google/common/collect/TreeRangeSet.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; +import com.google.errorprone.annotations.concurrent.LazyInit; import java.io.Serializable; import java.util.Collection; import java.util.Comparator; @@ -75,8 +76,8 @@ public class TreeRangeSet<C extends Comparable<?>> extends AbstractRangeSet<C> this.rangesByLowerBound = rangesByLowerCut; } - @CheckForNull private transient Set<Range<C>> asRanges; - @CheckForNull private transient Set<Range<C>> asDescendingSetOfRanges; + @LazyInit @CheckForNull private transient Set<Range<C>> asRanges; + @LazyInit @CheckForNull private transient Set<Range<C>> asDescendingSetOfRanges; @Override public Set<Range<C>> asRanges() { @@ -272,7 +273,7 @@ public class TreeRangeSet<C extends Comparable<?>> extends AbstractRangeSet<C> } } - @CheckForNull private transient RangeSet<C> complement; + @LazyInit @CheckForNull private transient RangeSet<C> complement; @Override public RangeSet<C> complement() { diff --git a/android/guava/src/com/google/common/collect/UnmodifiableSortedMultiset.java b/android/guava/src/com/google/common/collect/UnmodifiableSortedMultiset.java index 31f3c7197..c7e1d4c33 100644 --- a/android/guava/src/com/google/common/collect/UnmodifiableSortedMultiset.java +++ b/android/guava/src/com/google/common/collect/UnmodifiableSortedMultiset.java @@ -18,6 +18,7 @@ package com.google.common.collect; import com.google.common.annotations.GwtCompatible; import com.google.common.collect.Multisets.UnmodifiableMultiset; +import com.google.errorprone.annotations.concurrent.LazyInit; import java.util.Comparator; import java.util.NavigableSet; import javax.annotation.CheckForNull; @@ -58,7 +59,7 @@ final class UnmodifiableSortedMultiset<E extends @Nullable Object> extends Unmod return (NavigableSet<E>) super.elementSet(); } - @CheckForNull private transient UnmodifiableSortedMultiset<E> descendingMultiset; + @LazyInit @CheckForNull private transient UnmodifiableSortedMultiset<E> descendingMultiset; @Override public SortedMultiset<E> descendingMultiset() { diff --git a/android/guava/src/com/google/common/reflect/TypeToken.java b/android/guava/src/com/google/common/reflect/TypeToken.java index 8abec1a57..6ac3385e8 100644 --- a/android/guava/src/com/google/common/reflect/TypeToken.java +++ b/android/guava/src/com/google/common/reflect/TypeToken.java @@ -31,6 +31,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Ordering; import com.google.common.primitives.Primitives; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.concurrent.LazyInit; import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.GenericArrayType; @@ -103,10 +104,10 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl private final Type runtimeType; /** Resolver for resolving parameter and field types with {@link #runtimeType} as context. */ - @CheckForNull private transient TypeResolver invariantTypeResolver; + @LazyInit @CheckForNull private transient TypeResolver invariantTypeResolver; /** Resolver for resolving covariant types with {@link #runtimeType} as context. */ - @CheckForNull private transient TypeResolver covariantTypeResolver; + @LazyInit @CheckForNull private transient TypeResolver covariantTypeResolver; /** * Constructs a new type token of {@code T}. diff --git a/android/guava/src/com/google/common/util/concurrent/AtomicLongMap.java b/android/guava/src/com/google/common/util/concurrent/AtomicLongMap.java index ace5e3c53..33f08298c 100644 --- a/android/guava/src/com/google/common/util/concurrent/AtomicLongMap.java +++ b/android/guava/src/com/google/common/util/concurrent/AtomicLongMap.java @@ -21,6 +21,7 @@ import com.google.common.annotations.J2ktIncompatible; import com.google.common.base.Function; import com.google.common.collect.Maps; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.concurrent.LazyInit; import java.io.Serializable; import java.util.Collections; import java.util.Iterator; @@ -328,7 +329,7 @@ public final class AtomicLongMap<K> implements Serializable { return sum; } - @CheckForNull private transient Map<K, Long> asMap; + @LazyInit @CheckForNull private transient Map<K, Long> asMap; /** Returns a live, read-only view of the map backing this {@code AtomicLongMap}. */ public Map<K, Long> asMap() { diff --git a/guava/src/com/google/common/cache/LocalCache.java b/guava/src/com/google/common/cache/LocalCache.java index a0d58280d..8206c8c8a 100644 --- a/guava/src/com/google/common/cache/LocalCache.java +++ b/guava/src/com/google/common/cache/LocalCache.java @@ -51,6 +51,7 @@ import com.google.common.util.concurrent.UncheckedExecutionException; import com.google.common.util.concurrent.Uninterruptibles; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.concurrent.GuardedBy; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.RetainedWith; import com.google.j2objc.annotations.Weak; import java.io.IOException; @@ -4348,7 +4349,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> } } - @RetainedWith @CheckForNull Set<K> keySet; + @LazyInit @RetainedWith @CheckForNull Set<K> keySet; @Override public Set<K> keySet() { @@ -4357,7 +4358,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> return (ks != null) ? ks : (keySet = new KeySet()); } - @RetainedWith @CheckForNull Collection<V> values; + @LazyInit @RetainedWith @CheckForNull Collection<V> values; @Override public Collection<V> values() { @@ -4366,7 +4367,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> return (vs != null) ? vs : (values = new Values()); } - @RetainedWith @CheckForNull Set<Entry<K, V>> entrySet; + @LazyInit @RetainedWith @CheckForNull Set<Entry<K, V>> entrySet; @Override @GwtIncompatible // Not supported. diff --git a/guava/src/com/google/common/collect/AbstractBiMap.java b/guava/src/com/google/common/collect/AbstractBiMap.java index e72462975..0563ea0e8 100644 --- a/guava/src/com/google/common/collect/AbstractBiMap.java +++ b/guava/src/com/google/common/collect/AbstractBiMap.java @@ -25,6 +25,7 @@ import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.J2ktIncompatible; import com.google.common.base.Objects; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.RetainedWith; import com.google.j2objc.annotations.WeakOuter; import java.io.IOException; @@ -230,7 +231,7 @@ abstract class AbstractBiMap<K extends @Nullable Object, V extends @Nullable Obj return inverse; } - @CheckForNull private transient Set<K> keySet; + @LazyInit @CheckForNull private transient Set<K> keySet; @Override public Set<K> keySet() { @@ -275,7 +276,7 @@ abstract class AbstractBiMap<K extends @Nullable Object, V extends @Nullable Obj } } - @CheckForNull private transient Set<V> valueSet; + @LazyInit @CheckForNull private transient Set<V> valueSet; @Override public Set<V> values() { @@ -318,7 +319,7 @@ abstract class AbstractBiMap<K extends @Nullable Object, V extends @Nullable Obj } } - @CheckForNull private transient Set<Entry<K, V>> entrySet; + @LazyInit @CheckForNull private transient Set<Entry<K, V>> entrySet; @Override public Set<Entry<K, V>> entrySet() { diff --git a/guava/src/com/google/common/collect/AbstractSortedMultiset.java b/guava/src/com/google/common/collect/AbstractSortedMultiset.java index 621e8f98a..98b6211a7 100644 --- a/guava/src/com/google/common/collect/AbstractSortedMultiset.java +++ b/guava/src/com/google/common/collect/AbstractSortedMultiset.java @@ -17,6 +17,7 @@ package com.google.common.collect; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.GwtCompatible; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.WeakOuter; import java.util.Comparator; import java.util.Iterator; @@ -122,7 +123,7 @@ abstract class AbstractSortedMultiset<E extends @Nullable Object> extends Abstra return Multisets.iteratorImpl(descendingMultiset()); } - @CheckForNull private transient SortedMultiset<E> descendingMultiset; + @LazyInit @CheckForNull private transient SortedMultiset<E> descendingMultiset; @Override public SortedMultiset<E> descendingMultiset() { diff --git a/guava/src/com/google/common/collect/ArrayTable.java b/guava/src/com/google/common/collect/ArrayTable.java index 38902e3c9..411ee6335 100644 --- a/guava/src/com/google/common/collect/ArrayTable.java +++ b/guava/src/com/google/common/collect/ArrayTable.java @@ -27,6 +27,7 @@ import com.google.common.base.Objects; import com.google.common.collect.Maps.IteratorBasedAbstractMap; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.DoNotCall; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.WeakOuter; import java.io.Serializable; import java.lang.reflect.Array; @@ -660,7 +661,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, @Nullable V> return columnKeyToIndex.keySet(); } - @CheckForNull private transient ColumnMap columnMap; + @LazyInit @CheckForNull private transient ColumnMap columnMap; @Override public Map<C, Map<R, @Nullable V>> columnMap() { @@ -755,7 +756,7 @@ public final class ArrayTable<R, C, V> extends AbstractTable<R, C, @Nullable V> return rowKeyToIndex.keySet(); } - @CheckForNull private transient RowMap rowMap; + @LazyInit @CheckForNull private transient RowMap rowMap; @Override public Map<R, Map<C, @Nullable V>> rowMap() { diff --git a/guava/src/com/google/common/collect/CompactHashMap.java b/guava/src/com/google/common/collect/CompactHashMap.java index 83f27f8e6..c5cac7ca5 100644 --- a/guava/src/com/google/common/collect/CompactHashMap.java +++ b/guava/src/com/google/common/collect/CompactHashMap.java @@ -31,6 +31,7 @@ import com.google.common.base.Objects; import com.google.common.base.Preconditions; import com.google.common.primitives.Ints; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.WeakOuter; import java.io.IOException; import java.io.InvalidObjectException; @@ -688,7 +689,7 @@ class CompactHashMap<K extends @Nullable Object, V extends @Nullable Object> } } - @CheckForNull private transient Set<K> keySetView; + @LazyInit @CheckForNull private transient Set<K> keySetView; @Override public Set<K> keySet() { @@ -798,7 +799,7 @@ class CompactHashMap<K extends @Nullable Object, V extends @Nullable Object> } } - @CheckForNull private transient Set<Entry<K, V>> entrySetView; + @LazyInit @CheckForNull private transient Set<Entry<K, V>> entrySetView; @Override public Set<Entry<K, V>> entrySet() { @@ -981,7 +982,7 @@ class CompactHashMap<K extends @Nullable Object, V extends @Nullable Object> return false; } - @CheckForNull private transient Collection<V> valuesView; + @LazyInit @CheckForNull private transient Collection<V> valuesView; @Override public Collection<V> values() { diff --git a/guava/src/com/google/common/collect/DescendingMultiset.java b/guava/src/com/google/common/collect/DescendingMultiset.java index 7db0fbbd4..23ff8319c 100644 --- a/guava/src/com/google/common/collect/DescendingMultiset.java +++ b/guava/src/com/google/common/collect/DescendingMultiset.java @@ -17,6 +17,7 @@ package com.google.common.collect; import com.google.common.annotations.GwtCompatible; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.WeakOuter; import java.util.Comparator; import java.util.Iterator; @@ -37,7 +38,7 @@ abstract class DescendingMultiset<E extends @Nullable Object> extends Forwarding implements SortedMultiset<E> { abstract SortedMultiset<E> forwardMultiset(); - @CheckForNull private transient Comparator<? super E> comparator; + @LazyInit @CheckForNull private transient Comparator<? super E> comparator; @Override public Comparator<? super E> comparator() { @@ -48,7 +49,7 @@ abstract class DescendingMultiset<E extends @Nullable Object> extends Forwarding return result; } - @CheckForNull private transient NavigableSet<E> elementSet; + @LazyInit @CheckForNull private transient NavigableSet<E> elementSet; @Override public NavigableSet<E> elementSet() { @@ -116,7 +117,7 @@ abstract class DescendingMultiset<E extends @Nullable Object> extends Forwarding abstract Iterator<Entry<E>> entryIterator(); - @CheckForNull private transient Set<Entry<E>> entrySet; + @LazyInit @CheckForNull private transient Set<Entry<E>> entrySet; @Override public Set<Entry<E>> entrySet() { diff --git a/guava/src/com/google/common/collect/GeneralRange.java b/guava/src/com/google/common/collect/GeneralRange.java index c5e1ba3c4..e462b7a01 100644 --- a/guava/src/com/google/common/collect/GeneralRange.java +++ b/guava/src/com/google/common/collect/GeneralRange.java @@ -22,6 +22,7 @@ import static com.google.common.collect.NullnessCasts.uncheckedCastNullableTToT; import com.google.common.annotations.GwtCompatible; import com.google.common.base.Objects; +import com.google.errorprone.annotations.concurrent.LazyInit; import java.io.Serializable; import java.util.Comparator; import javax.annotation.CheckForNull; @@ -263,7 +264,7 @@ final class GeneralRange<T extends @Nullable Object> implements Serializable { getUpperBoundType()); } - @CheckForNull private transient GeneralRange<T> reverse; + @LazyInit @CheckForNull private transient GeneralRange<T> reverse; /** Returns the same range relative to the reversed comparator. */ GeneralRange<T> reverse() { diff --git a/guava/src/com/google/common/collect/ImmutableRangeSet.java b/guava/src/com/google/common/collect/ImmutableRangeSet.java index 608456496..afd421cd7 100644 --- a/guava/src/com/google/common/collect/ImmutableRangeSet.java +++ b/guava/src/com/google/common/collect/ImmutableRangeSet.java @@ -555,7 +555,7 @@ public final class ImmutableRangeSet<C extends Comparable> extends AbstractRange this.domain = domain; } - @CheckForNull private transient Integer size; + @LazyInit @CheckForNull private transient Integer size; @Override public int size() { diff --git a/guava/src/com/google/common/collect/ImmutableSortedMap.java b/guava/src/com/google/common/collect/ImmutableSortedMap.java index 7479a6023..f38922e43 100644 --- a/guava/src/com/google/common/collect/ImmutableSortedMap.java +++ b/guava/src/com/google/common/collect/ImmutableSortedMap.java @@ -1104,16 +1104,18 @@ public final class ImmutableSortedMap<K, V> extends ImmutableSortedMapFauxveride @Override public ImmutableSortedMap<K, V> descendingMap() { - // TODO(kevinb): the descendingMap is never actually cached at all. Either it should be or the - // code below simplified. + // TODO(kevinb): The descendingMap is never actually cached at all. Either: + // + // - Cache it, and annotate the field with @LazyInit. + // - Simplify the code below, and consider eliminating the field (b/287198172), which is also + // set by one of the constructors. ImmutableSortedMap<K, V> result = descendingMap; if (result == null) { if (isEmpty()) { - return result = emptyMap(Ordering.from(comparator()).reverse()); + return emptyMap(Ordering.from(comparator()).reverse()); } else { - return result = - new ImmutableSortedMap<>( - (RegularImmutableSortedSet<K>) keySet.descendingSet(), valueList.reverse(), this); + return new ImmutableSortedMap<>( + (RegularImmutableSortedSet<K>) keySet.descendingSet(), valueList.reverse(), this); } } return result; diff --git a/guava/src/com/google/common/collect/JdkBackedImmutableMultiset.java b/guava/src/com/google/common/collect/JdkBackedImmutableMultiset.java index faf22b343..41d95f045 100644 --- a/guava/src/com/google/common/collect/JdkBackedImmutableMultiset.java +++ b/guava/src/com/google/common/collect/JdkBackedImmutableMultiset.java @@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.GwtCompatible; import com.google.common.primitives.Ints; +import com.google.errorprone.annotations.concurrent.LazyInit; import java.util.Collection; import java.util.Map; import javax.annotation.CheckForNull; @@ -66,7 +67,7 @@ final class JdkBackedImmutableMultiset<E> extends ImmutableMultiset<E> { return delegateMap.getOrDefault(element, 0); } - @CheckForNull private transient ImmutableSet<E> elementSet; + @LazyInit @CheckForNull private transient ImmutableSet<E> elementSet; @Override public ImmutableSet<E> elementSet() { diff --git a/guava/src/com/google/common/collect/MapMakerInternalMap.java b/guava/src/com/google/common/collect/MapMakerInternalMap.java index e80ec27a5..c64d81eb3 100644 --- a/guava/src/com/google/common/collect/MapMakerInternalMap.java +++ b/guava/src/com/google/common/collect/MapMakerInternalMap.java @@ -25,6 +25,7 @@ import com.google.common.collect.MapMaker.Dummy; import com.google.common.primitives.Ints; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.concurrent.GuardedBy; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.Weak; import com.google.j2objc.annotations.WeakOuter; import java.io.IOException; @@ -2522,7 +2523,7 @@ class MapMakerInternalMap< } } - @CheckForNull transient Set<K> keySet; + @LazyInit @CheckForNull transient Set<K> keySet; @Override public Set<K> keySet() { @@ -2530,7 +2531,7 @@ class MapMakerInternalMap< return (ks != null) ? ks : (keySet = new KeySet()); } - @CheckForNull transient Collection<V> values; + @LazyInit @CheckForNull transient Collection<V> values; @Override public Collection<V> values() { @@ -2538,7 +2539,7 @@ class MapMakerInternalMap< return (vs != null) ? vs : (values = new Values()); } - @CheckForNull transient Set<Entry<K, V>> entrySet; + @LazyInit @CheckForNull transient Set<Entry<K, V>> entrySet; @Override public Set<Entry<K, V>> entrySet() { diff --git a/guava/src/com/google/common/collect/Maps.java b/guava/src/com/google/common/collect/Maps.java index 942e21cc8..3c1e9c03f 100644 --- a/guava/src/com/google/common/collect/Maps.java +++ b/guava/src/com/google/common/collect/Maps.java @@ -38,6 +38,7 @@ import com.google.common.base.Predicates; import com.google.common.collect.MapDifference.ValueDifference; import com.google.common.primitives.Ints; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.RetainedWith; import com.google.j2objc.annotations.Weak; import com.google.j2objc.annotations.WeakOuter; @@ -1683,8 +1684,8 @@ public final class Maps { extends ForwardingMap<K, V> implements BiMap<K, V>, Serializable { final Map<K, V> unmodifiableMap; final BiMap<? extends K, ? extends V> delegate; - @RetainedWith @CheckForNull BiMap<V, K> inverse; - @CheckForNull transient Set<V> values; + @LazyInit @RetainedWith @CheckForNull BiMap<V, K> inverse; + @LazyInit @CheckForNull transient Set<V> values; UnmodifiableBiMap(BiMap<? extends K, ? extends V> delegate, @CheckForNull BiMap<V, K> inverse) { unmodifiableMap = Collections.unmodifiableMap(delegate); @@ -3660,7 +3661,7 @@ public final class Maps { throw new UnsupportedOperationException(); } - @CheckForNull private transient UnmodifiableNavigableMap<K, V> descendingMap; + @LazyInit @CheckForNull private transient UnmodifiableNavigableMap<K, V> descendingMap; @Override public NavigableMap<K, V> descendingMap() { @@ -3790,7 +3791,7 @@ public final class Maps { */ abstract Set<Entry<K, V>> createEntrySet(); - @CheckForNull private transient Set<Entry<K, V>> entrySet; + @LazyInit @CheckForNull private transient Set<Entry<K, V>> entrySet; @Override public Set<Entry<K, V>> entrySet() { @@ -3798,7 +3799,7 @@ public final class Maps { return (result == null) ? entrySet = createEntrySet() : result; } - @CheckForNull private transient Set<K> keySet; + @LazyInit @CheckForNull private transient Set<K> keySet; @Override public Set<K> keySet() { @@ -3810,7 +3811,7 @@ public final class Maps { return new KeySet<>(this); } - @CheckForNull private transient Collection<V> values; + @LazyInit @CheckForNull private transient Collection<V> values; @Override public Collection<V> values() { @@ -4372,7 +4373,7 @@ public final class Maps { return forward(); } - @CheckForNull private transient Comparator<? super K> comparator; + @LazyInit @CheckForNull private transient Comparator<? super K> comparator; @SuppressWarnings("unchecked") @Override @@ -4482,7 +4483,7 @@ public final class Maps { return forward(); } - @CheckForNull private transient Set<Entry<K, V>> entrySet; + @LazyInit @CheckForNull private transient Set<Entry<K, V>> entrySet; @Override public Set<Entry<K, V>> entrySet() { @@ -4513,7 +4514,7 @@ public final class Maps { return navigableKeySet(); } - @CheckForNull private transient NavigableSet<K> navigableKeySet; + @LazyInit @CheckForNull private transient NavigableSet<K> navigableKeySet; @Override public NavigableSet<K> navigableKeySet() { diff --git a/guava/src/com/google/common/collect/Multisets.java b/guava/src/com/google/common/collect/Multisets.java index 88e458315..fcc674472 100644 --- a/guava/src/com/google/common/collect/Multisets.java +++ b/guava/src/com/google/common/collect/Multisets.java @@ -30,6 +30,7 @@ import com.google.common.collect.Multiset.Entry; import com.google.common.math.IntMath; import com.google.common.primitives.Ints; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.concurrent.LazyInit; import java.io.Serializable; import java.util.Arrays; import java.util.Collection; @@ -134,7 +135,7 @@ public final class Multisets { return (Multiset<E>) delegate; } - @CheckForNull transient Set<E> elementSet; + @LazyInit @CheckForNull transient Set<E> elementSet; Set<E> createElementSet() { return Collections.<E>unmodifiableSet(delegate.elementSet()); @@ -146,7 +147,7 @@ public final class Multisets { return (es == null) ? elementSet = createElementSet() : es; } - @CheckForNull transient Set<Multiset.Entry<E>> entrySet; + @LazyInit @CheckForNull transient Set<Multiset.Entry<E>> entrySet; @SuppressWarnings("unchecked") @Override diff --git a/guava/src/com/google/common/collect/NaturalOrdering.java b/guava/src/com/google/common/collect/NaturalOrdering.java index 8cb8aef9a..dae531270 100644 --- a/guava/src/com/google/common/collect/NaturalOrdering.java +++ b/guava/src/com/google/common/collect/NaturalOrdering.java @@ -19,6 +19,7 @@ package com.google.common.collect; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.GwtCompatible; +import com.google.errorprone.annotations.concurrent.LazyInit; import java.io.Serializable; import javax.annotation.CheckForNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -30,8 +31,9 @@ import org.checkerframework.checker.nullness.qual.Nullable; final class NaturalOrdering extends Ordering<Comparable<?>> implements Serializable { static final NaturalOrdering INSTANCE = new NaturalOrdering(); - @CheckForNull private transient Ordering<@Nullable Comparable<?>> nullsFirst; - @CheckForNull private transient Ordering<@Nullable Comparable<?>> nullsLast; + // TODO: b/287198172 - Consider eagerly initializing these (but think about serialization). + @LazyInit @CheckForNull private transient Ordering<@Nullable Comparable<?>> nullsFirst; + @LazyInit @CheckForNull private transient Ordering<@Nullable Comparable<?>> nullsLast; @Override public int compare(Comparable<?> left, Comparable<?> right) { diff --git a/guava/src/com/google/common/collect/Sets.java b/guava/src/com/google/common/collect/Sets.java index 057888f3e..da3814881 100644 --- a/guava/src/com/google/common/collect/Sets.java +++ b/guava/src/com/google/common/collect/Sets.java @@ -29,6 +29,7 @@ import com.google.common.collect.Collections2.FilteredCollection; import com.google.common.math.IntMath; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.DoNotCall; +import com.google.errorprone.annotations.concurrent.LazyInit; import java.io.Serializable; import java.util.AbstractSet; import java.util.Arrays; @@ -1883,7 +1884,7 @@ public final class Sets { throw new UnsupportedOperationException(); } - @CheckForNull private transient UnmodifiableNavigableSet<E> descendingSet; + @LazyInit @CheckForNull private transient UnmodifiableNavigableSet<E> descendingSet; @Override public NavigableSet<E> descendingSet() { diff --git a/guava/src/com/google/common/collect/StandardTable.java b/guava/src/com/google/common/collect/StandardTable.java index 9f5898d4a..6ec3c6b23 100644 --- a/guava/src/com/google/common/collect/StandardTable.java +++ b/guava/src/com/google/common/collect/StandardTable.java @@ -34,6 +34,7 @@ import com.google.common.collect.Maps.IteratorBasedAbstractMap; import com.google.common.collect.Maps.ViewCachingAbstractMap; import com.google.common.collect.Sets.ImprovedAbstractSet; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.concurrent.LazyInit; import com.google.j2objc.annotations.WeakOuter; import java.io.Serializable; import java.util.Collection; @@ -674,7 +675,7 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa return rowMap().keySet(); } - @CheckForNull private transient Set<C> columnKeySet; + @LazyInit @CheckForNull private transient Set<C> columnKeySet; /** * {@inheritDoc} @@ -805,7 +806,7 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa return super.values(); } - @CheckForNull private transient Map<R, Map<C, V>> rowMap; + @LazyInit @CheckForNull private transient Map<R, Map<C, V>> rowMap; @Override public Map<R, Map<C, V>> rowMap() { @@ -887,7 +888,7 @@ class StandardTable<R, C, V> extends AbstractTable<R, C, V> implements Serializa } } - @CheckForNull private transient ColumnMap columnMap; + @LazyInit @CheckForNull private transient ColumnMap columnMap; @Override public Map<C, Map<R, V>> columnMap() { diff --git a/guava/src/com/google/common/collect/TreeRangeSet.java b/guava/src/com/google/common/collect/TreeRangeSet.java index 967981ff6..415e80ffb 100644 --- a/guava/src/com/google/common/collect/TreeRangeSet.java +++ b/guava/src/com/google/common/collect/TreeRangeSet.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; +import com.google.errorprone.annotations.concurrent.LazyInit; import java.io.Serializable; import java.util.Collection; import java.util.Comparator; @@ -75,8 +76,8 @@ public class TreeRangeSet<C extends Comparable<?>> extends AbstractRangeSet<C> this.rangesByLowerBound = rangesByLowerCut; } - @CheckForNull private transient Set<Range<C>> asRanges; - @CheckForNull private transient Set<Range<C>> asDescendingSetOfRanges; + @LazyInit @CheckForNull private transient Set<Range<C>> asRanges; + @LazyInit @CheckForNull private transient Set<Range<C>> asDescendingSetOfRanges; @Override public Set<Range<C>> asRanges() { @@ -272,7 +273,7 @@ public class TreeRangeSet<C extends Comparable<?>> extends AbstractRangeSet<C> } } - @CheckForNull private transient RangeSet<C> complement; + @LazyInit @CheckForNull private transient RangeSet<C> complement; @Override public RangeSet<C> complement() { diff --git a/guava/src/com/google/common/collect/UnmodifiableSortedMultiset.java b/guava/src/com/google/common/collect/UnmodifiableSortedMultiset.java index 31f3c7197..c7e1d4c33 100644 --- a/guava/src/com/google/common/collect/UnmodifiableSortedMultiset.java +++ b/guava/src/com/google/common/collect/UnmodifiableSortedMultiset.java @@ -18,6 +18,7 @@ package com.google.common.collect; import com.google.common.annotations.GwtCompatible; import com.google.common.collect.Multisets.UnmodifiableMultiset; +import com.google.errorprone.annotations.concurrent.LazyInit; import java.util.Comparator; import java.util.NavigableSet; import javax.annotation.CheckForNull; @@ -58,7 +59,7 @@ final class UnmodifiableSortedMultiset<E extends @Nullable Object> extends Unmod return (NavigableSet<E>) super.elementSet(); } - @CheckForNull private transient UnmodifiableSortedMultiset<E> descendingMultiset; + @LazyInit @CheckForNull private transient UnmodifiableSortedMultiset<E> descendingMultiset; @Override public SortedMultiset<E> descendingMultiset() { diff --git a/guava/src/com/google/common/reflect/TypeToken.java b/guava/src/com/google/common/reflect/TypeToken.java index 8abec1a57..6ac3385e8 100644 --- a/guava/src/com/google/common/reflect/TypeToken.java +++ b/guava/src/com/google/common/reflect/TypeToken.java @@ -31,6 +31,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Ordering; import com.google.common.primitives.Primitives; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.concurrent.LazyInit; import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.GenericArrayType; @@ -103,10 +104,10 @@ public abstract class TypeToken<T> extends TypeCapture<T> implements Serializabl private final Type runtimeType; /** Resolver for resolving parameter and field types with {@link #runtimeType} as context. */ - @CheckForNull private transient TypeResolver invariantTypeResolver; + @LazyInit @CheckForNull private transient TypeResolver invariantTypeResolver; /** Resolver for resolving covariant types with {@link #runtimeType} as context. */ - @CheckForNull private transient TypeResolver covariantTypeResolver; + @LazyInit @CheckForNull private transient TypeResolver covariantTypeResolver; /** * Constructs a new type token of {@code T}. diff --git a/guava/src/com/google/common/util/concurrent/AtomicLongMap.java b/guava/src/com/google/common/util/concurrent/AtomicLongMap.java index 571e1b1d3..28481cca5 100644 --- a/guava/src/com/google/common/util/concurrent/AtomicLongMap.java +++ b/guava/src/com/google/common/util/concurrent/AtomicLongMap.java @@ -21,6 +21,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.J2ktIncompatible; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.concurrent.LazyInit; import java.io.Serializable; import java.util.Collections; import java.util.Map; @@ -265,7 +266,7 @@ public final class AtomicLongMap<K> implements Serializable { return map.values().stream().mapToLong(Long::longValue).sum(); } - @CheckForNull private transient Map<K, Long> asMap; + @LazyInit @CheckForNull private transient Map<K, Long> asMap; /** Returns a live, read-only view of the map backing this {@code AtomicLongMap}. */ public Map<K, Long> asMap() { |