You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2022/04/08 17:13:51 UTC
[groovy] branch master updated: GROOVY-10576: "?" source and target "? extends Object"
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new 07a5cd4527 GROOVY-10576: "?" source and target "? extends Object"
07a5cd4527 is described below
commit 07a5cd4527a477677c13723cd24fa95bcda72c7e
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Apr 8 11:59:21 2022 -0500
GROOVY-10576: "?" source and target "? extends Object"
---
.../java/org/codehaus/groovy/ast/GenericsType.java | 4 +-
.../groovy/transform/stc/GenericsSTCTest.groovy | 105 ++++++++++++---------
2 files changed, 63 insertions(+), 46 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/ast/GenericsType.java b/src/main/java/org/codehaus/groovy/ast/GenericsType.java
index ab7dfbddb3..cd5414ad11 100644
--- a/src/main/java/org/codehaus/groovy/ast/GenericsType.java
+++ b/src/main/java/org/codehaus/groovy/ast/GenericsType.java
@@ -412,8 +412,8 @@ public class GenericsType extends ASTNode {
match = gt.checkGenerics(classNodeType.getLowerBound());
} else if (classNodeType.getUpperBounds() != null) {
match = gt.checkGenerics(classNodeType.getUpperBounds()[0]);
- } else {
- match = false; // "?" (from Comparable<?>) does not satisfy anything
+ } else { // GROOVY-10576: "?" vs "? extends Object" (citation required) or no match
+ match = (!gt.isPlaceholder() && !gt.isWildcard() && isObjectType(gt.getType()));
}
} else {
match = implementsInterfaceOrIsSubclassOf(classNodeType.getType(), gt.getType());
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 46cf006622..021cba68fb 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -1598,44 +1598,6 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'Cannot call A#<init>(java.lang.Class<java.lang.String>, java.lang.Class<java.lang.Integer>) with arguments [java.lang.Class<java.lang.Integer>, java.lang.Class<java.lang.String>]'
}
- void testMethodCallWithMapParameterUnbounded() {
- assertScript """
- import static ${this.class.name}.isEmpty
- class C {
- Map<String, ?> map = new HashMap()
- }
- assert isEmpty(new C().map)
- """
- }
-
- // GROOVY-9460
- void testMethodCallWithClassParameterUnbounded() {
- assertScript '''
- class Bar {
- static void baz(Class<?> target) {
- }
- }
- class Foo<X> { // cannot be "T" because that matches type parameter in Class
- void test(Class<X> c) {
- Bar.baz(c) // Cannot call Bar#baz(Class<?>) with arguments [Class<X>]
- }
- }
- new Foo<String>().test(String.class)
- '''
- }
-
- // GROOVY-10525
- void testMethodCallWithClassParameterUnbounded2() {
- assertScript '''
- @Grab('javax.validation:validation-api:1.1.0.Final')
- import javax.validation.Validator
-
- void test(Object bean, List<Class<?>> types, Validator validator) {
- validator.validate(bean, types as Class<?>[])
- }
- '''
- }
-
void testConstructorCallWithClassParameterUsingClassLiteralArg() {
assertScript '''
class A {}
@@ -1662,21 +1624,21 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'''
}
- void testPutMethodWithPrimitiveValue() {
+ void testPutWithPrimitiveValue() {
assertScript '''
def map = new HashMap<String, Integer>()
map.put('hello', 1)
'''
}
- void testPutAtMethodWithPrimitiveValue() {
+ void testPutAtWithPrimitiveValue() {
assertScript '''
def map = new HashMap<String, Integer>()
map['hello'] = 1
'''
}
- void testPutMethodWithWrongValueType() {
+ void testPutWithWrongValueType() {
shouldFailWithMessages '''
def map = new HashMap<String, Integer>()
map.put('hello', new Object())
@@ -1684,7 +1646,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'Cannot find matching method java.util.HashMap#put(java.lang.String, java.lang.Object). Please check if the declared type is correct and if the method exists.'
}
- void testPutAtMethodWithWrongValueType() {
+ void testPutAtWithWrongValueType() {
shouldFailWithMessages '''
def map = new HashMap<String, Integer>()
map['hello'] = new Object()
@@ -1693,7 +1655,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
}
// GROOVY-9069
- void testPutAtMethodWithWrongValueType2() {
+ void testPutAtWithWrongValueType2() {
shouldFailWithMessages '''
class ConfigAttribute {
}
@@ -1709,7 +1671,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'Cannot call <K,V> org.codehaus.groovy.runtime.DefaultGroovyMethods#putAt(java.util.Map<K, V>, K, V) with arguments [java.util.Map<java.lang.String, java.util.Map<java.lang.String, java.util.List<java.lang.String>>>, java.lang.String, java.util.LinkedHashMap<java.lang.String, java.util.List<ConfigAttribute>>]'
}
- void testPutAtMethodWithWrongValueType3() {
+ void testPutAtWithWrongValueType3() {
assertScript '''
void test(Map<String, Map<String, List<String>>> maps) {
maps.each { String key, Map<String, List<String>> map ->
@@ -1722,6 +1684,61 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'''
}
+ // GROOVY-10576
+ void testPutAllWithMapParameterUnbounded() {
+ assertScript '''
+ class C {
+ Map<String,Object> map
+ void test(Map<String,?> m) {
+ map.putAll(m) // Cannot call Map#putAll(Map<? extends String, ? extends Object>) with arguments [Map<String, ?>]
+ }
+ }
+ def obj = new C(map:[:])
+ obj.test(foo:'bar')
+ def map = obj.map
+
+ assert map == [foo:'bar']
+ '''
+ }
+
+ void testMethodCallWithMapParameterUnbounded() {
+ assertScript """
+ import static ${this.class.name}.isEmpty
+ class C {
+ Map<String,?> map = new HashMap()
+ }
+ assert isEmpty(new C().map)
+ """
+ }
+
+ // GROOVY-9460
+ void testMethodCallWithClassParameterUnbounded() {
+ assertScript '''
+ class Bar {
+ static void baz(Class<?> target) {
+ }
+ }
+ class Foo<X> { // cannot be "T" because that matches type parameter in Class
+ void test(Class<X> c) {
+ Bar.baz(c) // Cannot call Bar#baz(Class<?>) with arguments [Class<X>]
+ }
+ }
+ new Foo<String>().test(String.class)
+ '''
+ }
+
+ // GROOVY-10525
+ void testMethodCallWithClassParameterUnbounded2() {
+ assertScript '''
+ @Grab('javax.validation:validation-api:1.1.0.Final')
+ import javax.validation.Validator
+
+ void test(Object bean, List<Class<?>> types, Validator validator) {
+ validator.validate(bean, types as Class<?>[])
+ }
+ '''
+ }
+
void testShouldComplainAboutToInteger() {
shouldFailWithMessages '''
class Test {