GROOVY-7774: Collection addAll fails CompileStatic type checking when adding a collection of subtypes (same treatment for some Map methods) (closes #376)
diff --git a/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java b/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
index 23e67b3..e952f0d 100644
--- a/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+++ b/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
@@ -5176,7 +5176,9 @@
G key = outer.getKey();
List<Map.Entry<K, V>> entries = outer.getValue();
Map<K, V> target = createSimilarMap(self);
- putAll(target, entries);
+ for (Map.Entry<K, V> entry : entries) {
+ target.put(entry.getKey(), entry.getValue());
+ }
answer.put(key, target);
}
return answer;
@@ -8903,8 +8905,8 @@
* @return the same map, after the items have been added to it.
* @since 1.6.1
*/
- public static <K, V> Map<K, V> putAll(Map<K, V> self, Collection<Map.Entry<K, V>> entries) {
- for (Map.Entry<K, V> entry : entries) {
+ public static <K, V> Map<K, V> putAll(Map<K, V> self, Collection<Map.Entry<? extends K, ? extends V>> entries) {
+ for (Map.Entry<? extends K, ? extends V> entry : entries) {
self.put(entry.getKey(), entry.getValue());
}
return self;
@@ -8923,7 +8925,7 @@
* @return a new Map containing all key, value pairs from self and entries
* @since 1.6.1
*/
- public static <K, V> Map<K, V> plus(Map<K, V> self, Collection<Map.Entry<K, V>> entries) {
+ public static <K, V> Map<K, V> plus(Map<K, V> self, Collection<Map.Entry<? extends K, ? extends V>> entries) {
Map<K, V> map = cloneSimilarMap(self);
putAll(map, entries);
return map;
diff --git a/src/test/groovy/transform/stc/Groovy7774Bug.groovy b/src/test/groovy/transform/stc/Groovy7774Bug.groovy
index ca9b1ab..96b3c7f 100644
--- a/src/test/groovy/transform/stc/Groovy7774Bug.groovy
+++ b/src/test/groovy/transform/stc/Groovy7774Bug.groovy
@@ -26,17 +26,31 @@
class Y extends X{}
def create() {
- Set<X> set = new HashSet<X>()
- List<Y> addIterable = [new Y()]
- Iterator<Y> addIterator = [new Y()].iterator()
- Y[] addArray = [new Y()]
- set.addAll(addIterable)
- set.addAll(addIterator)
- set.addAll(addArray)
- assert set.size() == 3
+ Set<X> set = new HashSet<X>()
+ List<Y> addIterable = [new Y()]
+ Iterator<Y> addIterator = [new Y()].iterator()
+ Y[] addArray = [new Y()]
+ set.addAll(addIterable)
+ set.addAll(addIterator)
+ set.addAll(addArray)
+ assert set.size() == 3
}
create()
'''
}
+
+ void testMapPutAllShouldHonorInheritance() {
+ assertScript '''
+ class X{}
+ class Y extends X{}
+
+ def create() {
+ Map<X, X> items = new HashMap<X, X>()
+ List<Map.Entry<Y, Y>> addEntries = new ArrayList<Map.Entry<Y, Y>>()
+ items.putAll(addEntries)
+ }
+ create()
+ '''
+ }
}