Skip to content

Commit 34f3253

Browse files
cpovirkGoogle Java Core Libraries
authored andcommitted
Rework ImmutableMap.copyOf handling of EnumMap to follow what 06b6f4b did for ImmutableSet.
Plus, expand the comment on `ImmutableSet` to acknowledge a second reason for the `unchecked` warning there. RELNOTES=n/a PiperOrigin-RevId: 829442016
1 parent c91bd2a commit 34f3253

File tree

2 files changed

+18
-16
lines changed

2 files changed

+18
-16
lines changed

guava/src/com/google/common/collect/ImmutableMap.java

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -692,12 +692,22 @@ public static <K, V> ImmutableMap<K, V> copyOf(Map<? extends K, ? extends V> map
692692
return kvMap;
693693
}
694694
} else if (map instanceof EnumMap) {
695-
@SuppressWarnings("unchecked") // safe since map is not writable
696-
ImmutableMap<K, V> kvMap =
697-
(ImmutableMap<K, V>)
698-
copyOfEnumMap(
699-
(EnumMap<?, ? extends V>) map); // hide K (violates bounds) from J2KT, preserve V.
700-
return kvMap;
695+
EnumMap<?, ? extends V> clone = ((EnumMap<?, ? extends V>) map).clone();
696+
for (Entry<?, ?> entry : clone.entrySet()) {
697+
checkEntryNotNull(entry.getKey(), entry.getValue());
698+
}
699+
ImmutableMap<?, ? extends V> untypedResult = ImmutableEnumMap.asImmutable(clone);
700+
/*
701+
* The result has the same type argument we started with. We just couldn't express EnumMap<K,
702+
* ...> or ImmutableEnumMap<K, ...> along the way because our own <K> isn't <K extends
703+
* Enum<K>>.
704+
*
705+
* We are also performing a covariant cast, potentially from ImmutableMap<K, Sub> to
706+
* ImmutableMap<K, Super>. That is safe because no one can add elements to the map.
707+
*/
708+
@SuppressWarnings("unchecked")
709+
ImmutableMap<K, V> result = (ImmutableMap<K, V>) untypedResult;
710+
return result;
701711
}
702712
return copyOf(map.entrySet());
703713
}
@@ -730,16 +740,6 @@ public static <K, V> ImmutableMap<K, V> copyOf(
730740
}
731741
}
732742

733-
private static <K extends Enum<K>, V> ImmutableMap<K, ? extends V> copyOfEnumMap(
734-
EnumMap<?, ? extends V> original) {
735-
@SuppressWarnings("unchecked") // the best we could do to make copyOf(Map) compile
736-
EnumMap<K, V> copy = new EnumMap<>((EnumMap<K, ? extends V>) original);
737-
for (Entry<K, V> entry : copy.entrySet()) {
738-
checkEntryNotNull(entry.getKey(), entry.getValue());
739-
}
740-
return ImmutableEnumMap.asImmutable(copy);
741-
}
742-
743743
static final Entry<?, ?>[] EMPTY_ENTRY_ARRAY = new Entry<?, ?>[0];
744744

745745
abstract static class IteratorBasedImmutableMap<K, V> extends ImmutableMap<K, V> {

guava/src/com/google/common/collect/ImmutableSet.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ public static <E> ImmutableSet<E> copyOf(Collection<? extends E> elements) {
187187
/*
188188
* The result has the same type argument we started with. We just couldn't express EnumSet<E>
189189
* or ImmutableEnumSet<E> along the way because our own <E> isn't <E extends Enum<E>>.
190+
*
191+
* We are also performing a safe covariant cast to change <? extends E> to <E>.
190192
*/
191193
@SuppressWarnings("unchecked")
192194
ImmutableSet<E> result = (ImmutableSet<E>) untypedResult;

0 commit comments

Comments
 (0)