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 2021/02/17 21:05:32 UTC
[groovy] 01/01: GROOVY-9948: infer type arguments for CCE diamond
using argument type(s)
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY-9948
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 338856dcce3665bd29c1064e60747ede9dafa3d3
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Feb 17 15:05:15 2021 -0600
GROOVY-9948: infer type arguments for CCE diamond using argument type(s)
---
.../transform/stc/StaticTypeCheckingVisitor.java | 22 +++---
.../groovy/transform/stc/GenericsSTCTest.groovy | 82 +++++++++++++++++-----
2 files changed, 74 insertions(+), 30 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index fc30121..f3eb159 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1019,20 +1019,20 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
protected void inferDiamondType(final ConstructorCallExpression cce, final ClassNode lType) {
+ ClassNode cceType = cce.getType(), inferredType = lType;
// check if constructor call expression makes use of the diamond operator
- ClassNode node = cce.getType();
- if (node.isUsingGenerics() && node.getGenericsTypes() != null && node.getGenericsTypes().length == 0) {
- ArgumentListExpression argumentListExpression = InvocationWriter.makeArgumentList(cce.getArguments());
- if (argumentListExpression.getExpressions().isEmpty()) {
- adjustGenerics(lType, node);
- } else {
- ClassNode type = getType(argumentListExpression.getExpression(0));
+ if (cceType.getGenericsTypes() != null && cceType.getGenericsTypes().length == 0) {
+ ArgumentListExpression argumentList = InvocationWriter.makeArgumentList(cce.getArguments());
+ ConstructorNode constructor = cce.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
+ if (!argumentList.getExpressions().isEmpty() && constructor != null) {
+ ClassNode type = GenericsUtils.parameterizeType(cceType, cceType);
+ type = inferReturnTypeGenerics(type, constructor, argumentList);
if (type.isUsingGenerics()) {
- adjustGenerics(type, node);
+ inferredType = type;
}
}
- // store inferred type on CCE
- storeType(cce, node);
+ adjustGenerics(inferredType, cceType);
+ storeType(cce, cceType);
}
}
@@ -5096,7 +5096,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
* @return parameterized, infered, class node
*/
protected ClassNode inferReturnTypeGenerics(final ClassNode receiver, final MethodNode method, final Expression arguments, final GenericsType[] explicitTypeHints) {
- ClassNode returnType = method.getReturnType();
+ ClassNode returnType = method instanceof ConstructorNode ? method.getDeclaringClass() : method.getReturnType();
if (getGenericsWithoutArray(returnType) == null) {
return returnType;
}
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 3e27826..1c253f2 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -210,27 +210,82 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'''
}
- void testDiamondInferrenceFromConstructor() {
+ void testDiamondInferrenceFromConstructor1() {
assertScript '''
- Set< Long > s2 = new HashSet<>()
+ Set<Long> set = new HashSet<>()
'''
}
- void testDiamondInferrenceFromConstructorWithoutAssignment() {
+ void testDiamondInferrenceFromConstructor2() {
assertScript '''
- new HashSet<>(Arrays.asList(0L,0L));
+ new HashSet<>(Arrays.asList(0L))
'''
}
- void testDiamondInferrenceFromConstructor2() {
+ void testDiamondInferrenceFromConstructor3() {
shouldFailWithMessages '''
- Set< Number > s3 = new HashSet<>(Arrays.asList(0L,0L));
+ Set<Number> set = new HashSet<>(Arrays.asList(0L))
''', 'Cannot assign java.util.HashSet <java.lang.Long> to: java.util.Set <Number>'
+
+ // not diamond inference, but tests compatible assignment
+ assertScript '''
+ Set<Number> set = new HashSet<Number>(Arrays.asList(0L))
+ '''
}
- void testDiamondInferrenceFromConstructor3() {
+ void testDiamondInferrenceFromConstructor4() {
+ assertScript '''
+ Set<? extends Number> set = new HashSet<>(Arrays.asList(0L))
+ '''
+ }
+
+ // GROOVY-6232
+ void testDiamondInferrenceFromConstructor5() {
+ [/*'"a",new Object()',*/ 'new Object(),"b"', /*'"a","b"'*/].each { args ->
+ assertScript """
+ class C<T> {
+ C(T x, T y) {
+ }
+ }
+ void test() {
+ C<Object> c = new C<>($args)
+ }
+ test()
+ """
+ }
+ }
+
+ // GROOVY-9948
+ void testDiamondInferrenceFromConstructor6() {
+ assertScript '''
+ class C<T> {
+ T p
+ C(T p) {
+ this.p = p
+ }
+ }
+
+ void test() {
+ C<Integer> c = new C<>(1)
+ assert c.p < 10
+ }
+ test()
+ '''
+ }
+
+ // GROOVY-9948
+ void testDiamondInferrenceFromConstructor7() {
assertScript '''
- Set<Number> s4 = new HashSet<Number>(Arrays.asList(0L,0L))
+ @groovy.transform.TupleConstructor
+ class C<T> {
+ T p
+ }
+
+ void test() {
+ C<Integer> c = new C<>(1)
+ assert c.p < 10
+ }
+ test()
'''
}
@@ -1760,17 +1815,6 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'''
}
- // GROOVY-6232
- void testDiamond() {
- assertScript '''
- class Foo<T>{ Foo(T a, T b){} }
- def bar() {
- Foo<Object> f = new Foo<>("a",new Object())
- }
- bar()
- '''
- }
-
// GROOVY-6233
void testConstructorArgumentsAgainstGenerics() {
shouldFailWithMessages '''