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 51eb2a0 GROOVY-10328: STC: `List<? super Type>` dot get returns
Object, not Type
51eb2a0 is described below
commit 51eb2a026a9ce1b4f6232d8ac4414eda586ac3e0
Author: Eric Milles <[email protected]>
AuthorDate: Sat Oct 23 09:54:15 2021 -0500
GROOVY-10328: STC: `List<? super Type>` dot get returns Object, not Type
---
.../transform/stc/StaticTypeCheckingSupport.java | 12 ++---
.../transform/stc/StaticTypeCheckingVisitor.java | 27 +---------
src/test/groovy/bugs/Groovy9074.groovy | 46 ++++++++--------
.../transform/stc/TypeInferenceSTCTest.groovy | 62 ++++++++++++++--------
4 files changed, 71 insertions(+), 76 deletions(-)
diff --git
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index e30ff75..a7243a2 100644
---
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -1754,8 +1754,8 @@ public abstract class StaticTypeCheckingSupport {
if (ui.isWildcard()) {
extractGenericsConnections(connections,
ui.getLowerBound(), di.getLowerBound());
extractGenericsConnections(connections,
ui.getUpperBounds(), di.getUpperBounds());
- } else {
- ClassNode boundType = getCombinedBoundType(di);
+ } else if (!isUnboundedWildcard(di)) {
+ ClassNode boundType = di.getLowerBound() != null ?
di.getLowerBound() : di.getUpperBounds()[0];
if (boundType.isGenericsPlaceHolder()) { // GROOVY-9998
String placeholderName = boundType.getUnresolvedName();
ui = new GenericsType(ui.getType());
ui.setWildcard(true);
@@ -1892,11 +1892,11 @@ public abstract class StaticTypeCheckingSupport {
}
static ClassNode getCombinedBoundType(final GenericsType genericsType) {
- // TODO: this method should really return some kind of meta ClassNode
- // representing the combination of all bounds. The code here, just
picks
- // something out to be able to proceed and is not actually correct
+ // TODO: This method should really return some kind of meta ClassNode
+ // representing the combination of all bounds. The code here just picks
+ // something out to be able to proceed and is not actually correct.
if (hasNonTrivialBounds(genericsType)) {
- if (genericsType.getLowerBound() != null) return
genericsType.getLowerBound();
+ if (genericsType.getLowerBound() != null) return OBJECT_TYPE; //
GROOVY-10328
if (genericsType.getUpperBounds() != null) return
genericsType.getUpperBounds()[0];
}
return genericsType.getType();
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 f7f75c4..376a857 100644
---
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -3149,36 +3149,11 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
ClassNode[] inferred = new ClassNode[returnTypeGenerics.length];
for (int i = 0, n = returnTypeGenerics.length; i < n; i += 1) {
GenericsType genericsType = returnTypeGenerics[i];
- ClassNode value =
createUsableClassNodeFromGenericsType(genericsType);
- inferred[i] = value;
+ inferred[i] = getCombinedBoundType(genericsType);
}
return inferred;
}
- /**
- * Given a GenericsType instance, returns a ClassNode which can be used as
an inferred type.
- *
- * @param genericsType a {@link org.codehaus.groovy.ast.GenericsType}
representing either a type, a placeholder or a wildcard
- * @return a class node usable as an inferred type
- */
- private static ClassNode createUsableClassNodeFromGenericsType(final
GenericsType genericsType) {
- // TODO: Merge with
StaticTypeCheckingSupport#getCombinedBoundType(GenericsType)?
- ClassNode value = genericsType.getType();
- if (genericsType.isPlaceholder()) {
- value = value.isRedirectNode() ? value.redirect() : OBJECT_TYPE;
- }
- ClassNode lowerBound = genericsType.getLowerBound();
- if (lowerBound != null) {
- value = lowerBound;
- } else {
- ClassNode[] upperBounds = genericsType.getUpperBounds();
- if (upperBounds != null) {
- value = lowestUpperBound(Arrays.asList(upperBounds));
- }
- }
- return value;
- }
-
private static String[] convertToStringArray(final Expression options) {
if (options == null) {
return ResolveVisitor.EMPTY_STRING_ARRAY;
diff --git a/src/test/groovy/bugs/Groovy9074.groovy
b/src/test/groovy/bugs/Groovy9074.groovy
index aac3c9c..f518ee5 100644
--- a/src/test/groovy/bugs/Groovy9074.groovy
+++ b/src/test/groovy/bugs/Groovy9074.groovy
@@ -29,7 +29,7 @@ final class Groovy9074 extends GroovyTestCase {
void _FIXME_testWildcardCapture() {
def err = shouldFail '''
- @groovy.transform.CompileStatic
+ @groovy.transform.TypeChecked
class Main {
private static Collection<?> c = new ArrayList<String>()
static main(args) {
@@ -46,20 +46,20 @@ final class Groovy9074 extends GroovyTestCase {
def err = shouldFail '''
import java.awt.Canvas
abstract class Shape {
- abstract void draw(Canvas c)
+ abstract void draw(Canvas c)
}
class Circle extends Shape {
- private int x, y, radius
- @Override void draw(Canvas c) {}
+ private int x, y, radius
+ @Override void draw(Canvas c) {}
}
class Rectangle extends Shape {
- private int x, y, width, height
- @Override void draw(Canvas c) {}
+ private int x, y, width, height
+ @Override void draw(Canvas c) {}
}
- @groovy.transform.CompileStatic
+ @groovy.transform.TypeChecked
void addRectangle(List<? extends Shape> shapes) {
- shapes.add(0, new Rectangle()) // TODO: compile-time error!
+ shapes.add(0, new Rectangle()) // TODO: compile-time error!
}
'''
@@ -71,20 +71,20 @@ final class Groovy9074 extends GroovyTestCase {
assertScript '''
import java.awt.Canvas
abstract class Shape {
- abstract void draw(Canvas c)
+ abstract void draw(Canvas c)
}
class Circle extends Shape {
- private int x, y, radius
- @Override void draw(Canvas c) {}
+ private int x, y, radius
+ @Override void draw(Canvas c) {}
}
class Rectangle extends Shape {
- private int x, y, width, height
- @Override void draw(Canvas c) {}
+ private int x, y, width, height
+ @Override void draw(Canvas c) {}
}
- @groovy.transform.CompileStatic
+ @groovy.transform.TypeChecked
void addRectangle(List<? super Shape> shapes) {
- shapes.add(0, new Rectangle())
+ shapes.add(0, new Rectangle())
}
List<Shape> list = []
@@ -99,12 +99,12 @@ final class Groovy9074 extends GroovyTestCase {
new CompilationUnit().with {
addSource 'Main.groovy', '''
class Factory {
- def <T> T make(Class<T> type, ... args) {}
+ def <T> T make(Class<T> type, ... args) {}
}
- @groovy.transform.CompileStatic
+ @groovy.transform.TypeChecked
void test(Factory fact, Rule rule) {
- Type bean = fact.make(rule.type)
+ Type bean = fact.make(rule.type)
}
'''
@@ -124,16 +124,16 @@ final class Groovy9074 extends GroovyTestCase {
}
}
- void _FIXME_testWildcardSuper2() {
+ void testWildcardSuper2() {
new CompilationUnit().with {
addSource 'Main.groovy', '''
class Factory {
- def <T> T make(Class<T> type, ... args) {}
+ def <T> T make(Class<T> type, ... args) {}
}
- @groovy.transform.CompileStatic
+ @groovy.transform.TypeChecked
void test(Factory fact, Rule rule) {
- Type bean = fact.make(rule.type) // can't assign "? super
Type" to "Type"
+ Type bean = fact.make(rule.type) // can't assign "? super
Type" to "Type"
}
'''
@@ -152,7 +152,7 @@ final class Groovy9074 extends GroovyTestCase {
def err = shouldFail {
compile CLASS_GENERATION
}
- assert err =~ "cannot convert from capture#1-of ? super Type to
Type"
+ assert err =~ 'Cannot assign value of type java.lang.Object to
variable of type Type'
}
}
}
diff --git a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
index 697a866..3e7cff4 100644
--- a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
@@ -787,7 +787,7 @@ class TypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
def o
o = 1L
o = 2
- @ASTTest(phase=INSTRUCTION_SELECTION, value= {
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
assert
node.rightExpression.accessedVariable.getNodeMetaData(DECLARATION_INFERRED_TYPE)
== long_TYPE
})
def z = o
@@ -858,10 +858,10 @@ class TypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
returnValue = 1;
break;
}
- @ASTTest(phase=INSTRUCTION_SELECTION,value={
- def ift = node.getNodeMetaData(INFERRED_TYPE)
- assert ift instanceof LUB
- assert ift.name == 'java.io.Serializable'
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ def type = node.getNodeMetaData(INFERRED_TYPE)
+ assert type instanceof LUB
+ assert type.name == 'java.io.Serializable'
})
def val = returnValue
@@ -913,8 +913,8 @@ class TypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
assertScript """
$orig b = 65 as $orig
@ASTTest(phase=INSTRUCTION_SELECTION, value={
- def rit = node.rightExpression.getNodeMetaData(INFERRED_TYPE)
- assert rit == make($dest)
+ def type = node.rightExpression.getNodeMetaData(INFERRED_TYPE)
+ assert type == make($dest)
})
def pp = ++b
println '++${orig} -> ' + pp.class + ' ' + pp
@@ -937,8 +937,8 @@ class TypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
assertScript """
$orig b = 65 as $orig
@ASTTest(phase=INSTRUCTION_SELECTION, value={
- def rit = node.rightExpression.getNodeMetaData(INFERRED_TYPE)
- assert rit == make($dest)
+ def type = node.rightExpression.getNodeMetaData(INFERRED_TYPE)
+ assert type == make($dest)
})
def pp = b++
println '${orig}++ -> ' + pp.class + ' ' + pp
@@ -959,11 +959,11 @@ class TypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
callable.call()
}
- @ASTTest(phase=INSTRUCTION_SELECTION,value={
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
lookup('test').each {
def call = it.expression
- def irt = call.getNodeMetaData(INFERRED_TYPE)
- assert irt == LIST_TYPE
+ def type = call.getNodeMetaData(INFERRED_TYPE)
+ assert type == LIST_TYPE
}
})
static void run() {
@@ -982,7 +982,7 @@ class TypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
public <T> T[] intArray(ArrayFactory<T> f) {
f.array()
}
- @ASTTest(phase=INSTRUCTION_SELECTION,value={
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
assert node.getNodeMetaData(INFERRED_TYPE) ==
Integer_TYPE.makeArray()
})
def array = intArray { new Integer[8] }
@@ -998,10 +998,10 @@ class TypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
f.list()
}
- @ASTTest(phase=INSTRUCTION_SELECTION,value={
- def irt = node.getNodeMetaData(INFERRED_TYPE)
- assert irt == LIST_TYPE
- assert irt.genericsTypes[0].type == Integer_TYPE
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ def type = node.getNodeMetaData(INFERRED_TYPE)
+ assert type == LIST_TYPE
+ assert type.genericsTypes[0].type == Integer_TYPE
})
def res = list { new LinkedList<Integer>() }
assert res.size() == 0
@@ -1042,7 +1042,7 @@ class TypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
void testShouldInferPrimitiveBoolean() {
assertScript '''
def foo(Boolean o) {
- @ASTTest(phase=INSTRUCTION_SELECTION,value={
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
assert node.getNodeMetaData(INFERRED_TYPE) == boolean_TYPE
})
boolean b = o
@@ -1139,15 +1139,15 @@ class TypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
String field
}
- @ASTTest(phase=INSTRUCTION_SELECTION,value={
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
lookup('second').each {
- assert it.expression.getNodeMetaData(INFERRED_TYPE).name ==
'Ann2'
+ assert it.expression.getNodeMetaData(INFERRED_TYPE).name
== 'Ann2'
}
})
def doit(obj, String propName) {
def field = obj.getClass().getDeclaredField(propName)
if (field) {
- @ASTTest(phase=INSTRUCTION_SELECTION,value={
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
assert node.getNodeMetaData(INFERRED_TYPE).name ==
'Ann1'
})
def annotation = field.getAnnotation Ann1
@@ -1218,4 +1218,24 @@ class TypeInferenceSTCTest extends
StaticTypeCheckingTestCase {
test( [id:'x'] )
'''
}
+
+ // GROOVY-10328
+ void testInferredTypeForMapOrList() {
+ assertScript '''
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ for (decl in node.code.statements*.expression) {
+ assert decl.getNodeMetaData(INFERRED_TYPE) == OBJECT_TYPE
+ }
+ })
+ void test(List<? super String> list, Map<String, ? super String>
map) {
+ def a = list.first()
+ def b = list.get(0)
+ def c = list[0]
+
+ def x = map.get('foo')
+ def y = map['foo']
+ def z = map.foo
+ }
+ '''
+ }
}