Skip to content

Commit 62910e5

Browse files
committed
GROOVY-10327
1 parent 323bf18 commit 62910e5

File tree

7 files changed

+70
-51
lines changed

7 files changed

+70
-51
lines changed

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java

+27-4
Original file line numberDiff line numberDiff line change
@@ -1780,10 +1780,13 @@ public void testTypeChecked9074d() {
17801780
};
17811781
//@formatter:on
17821782

1783-
runConformTest(sources);
1784-
/*
1785-
runNegativeTest(sources, "cannot convert from capture#1-of ? super Type to Type");
1786-
*/
1783+
runNegativeTest(sources,
1784+
"----------\n" +
1785+
"1. ERROR in Main.groovy (at line 7)\n" +
1786+
"\tType bean = fact.make(rule.type)\n" +
1787+
"\t ^^^^^^^^^^^^^^^^^^^^\n" +
1788+
"Groovy:[Static type checking] - Cannot assign value of type java.lang.Object to variable of type Type\n" +
1789+
"----------\n");
17871790
}
17881791

17891792
@Test
@@ -4228,4 +4231,24 @@ public void testTypeChecked10326() {
42284231
"Groovy:[Static type checking] - Cannot set read-only property: key\n" +
42294232
"----------\n");
42304233
}
4234+
4235+
@Test
4236+
public void testTypeChecked10327() {
4237+
//@formatter:off
4238+
String[] sources = {
4239+
"Main.groovy",
4240+
"@groovy.transform.TypeChecked\n" +
4241+
"void test(Map<String,? super String> map) {\n" +
4242+
" @groovy.transform.ASTTest(phase=INSTRUCTION_SELECTION, value={\n" +
4243+
" def type = node.getNodeMetaData(org.codehaus.groovy.transform.stc.StaticTypesMarker.INFERRED_TYPE)\n" +
4244+
" assert type == org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE\n" +
4245+
" })\n" +
4246+
" def foo = map.foo\n" +
4247+
"}\n" +
4248+
"test(foo:'bar')\n",
4249+
};
4250+
//@formatter:on
4251+
4252+
runConformTest(sources);
4253+
}
42314254
}

base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java

+7-5
Original file line numberDiff line numberDiff line change
@@ -2030,8 +2030,8 @@ private static void extractGenericsConnections(Map<GenericsTypeName, GenericsTyp
20302030
if (ui.isWildcard()) {
20312031
extractGenericsConnections(connections, ui.getLowerBound(), di.getLowerBound());
20322032
extractGenericsConnections(connections, ui.getUpperBounds(), di.getUpperBounds());
2033+
/* GRECLIPSE edit -- GROOVY-9998
20332034
} else {
2034-
/* GRECLIPSE edit -- GROOVY-9998
20352035
ClassNode cu = ui.getType();
20362036
extractGenericsConnections(connections, cu, di.getLowerBound());
20372037
ClassNode[] upperBounds = di.getUpperBounds();
@@ -2040,17 +2040,19 @@ private static void extractGenericsConnections(Map<GenericsTypeName, GenericsTyp
20402040
extractGenericsConnections(connections, cu, cn);
20412041
}
20422042
}
2043-
*/
2044-
ClassNode boundType = getCombinedBoundType(di);
2043+
}
2044+
*/
2045+
} else if (!isUnboundedWildcard(di)) {
2046+
ClassNode boundType = di.getLowerBound() != null ? di.getLowerBound() : di.getUpperBounds()[0];
20452047
if (boundType.isGenericsPlaceHolder()) {
20462048
String placeholderName = boundType.getUnresolvedName();
20472049
ui = new GenericsType(ui.getType()); ui.setPlaceHolder(false); ui.setWildcard(true);
20482050
connections.put(new GenericsTypeName(placeholderName), ui);
20492051
} else { // di like "? super Collection<T>" and ui like "List<Type>"
20502052
extractGenericsConnections(connections, ui.getType(), boundType);
20512053
}
2052-
// GRECLIPSE end
20532054
}
2055+
// GRECLIPSE end
20542056
} else {
20552057
extractGenericsConnections(connections, ui.getType(), di.getType());
20562058
}
@@ -2205,7 +2207,7 @@ static ClassNode getCombinedBoundType(GenericsType genericsType) {
22052207
// representing the combination of all bounds. The code here, just picks
22062208
// something out to be able to proceed and is not actually correct
22072209
if (hasNonTrivialBounds(genericsType)) {
2208-
if (genericsType.getLowerBound() != null) return genericsType.getLowerBound();
2210+
if (genericsType.getLowerBound() != null) return OBJECT_TYPE; // GROOVY-10327
22092211
if (genericsType.getUpperBounds() != null) return genericsType.getUpperBounds()[0];
22102212
}
22112213
return genericsType.getType();

base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

+12-6
Original file line numberDiff line numberDiff line change
@@ -3850,12 +3850,21 @@ private ClassNode[] resolveGenericsFromTypeHint(final ClassNode receiver, final
38503850
dummyMN.setGenericsTypes(orig.getGenericsTypes());
38513851
}
38523852
ClassNode classNode = inferReturnTypeGenerics(receiver, dummyMN, arguments);
3853+
/* GRECLIPSE edit -- GROOVY-10327
38533854
ClassNode[] inferred = new ClassNode[classNode.getGenericsTypes().length];
38543855
for (int i = 0; i < classNode.getGenericsTypes().length; i++) {
38553856
GenericsType genericsType = classNode.getGenericsTypes()[i];
38563857
ClassNode value = createUsableClassNodeFromGenericsType(genericsType);
38573858
inferred[i] = value;
38583859
}
3860+
*/
3861+
GenericsType[] returnTypeGenerics = classNode.getGenericsTypes();
3862+
ClassNode[] inferred = new ClassNode[returnTypeGenerics.length];
3863+
for (int i = 0, n = returnTypeGenerics.length; i < n; i += 1) {
3864+
GenericsType genericsType = returnTypeGenerics[i];
3865+
inferred[i] = getCombinedBoundType(genericsType);
3866+
}
3867+
// GRECLIPSE end
38593868
return inferred;
38603869
}
38613870

@@ -3865,14 +3874,10 @@ private ClassNode[] resolveGenericsFromTypeHint(final ClassNode receiver, final
38653874
* @param genericsType a {@link org.codehaus.groovy.ast.GenericsType} representing either a type, a placeholder or a wildcard
38663875
* @return a class node usable as an inferred type
38673876
*/
3877+
/* GRECLIPSE edit
38683878
private static ClassNode createUsableClassNodeFromGenericsType(final GenericsType genericsType) {
38693879
ClassNode value = genericsType.getType();
38703880
if (genericsType.isPlaceholder()) {
3871-
// GRECLIPSE add -- GROOVY-9968
3872-
if (value.isRedirectNode())
3873-
value = value.redirect();
3874-
else
3875-
// GRECLIPSE end
38763881
value = OBJECT_TYPE;
38773882
}
38783883
ClassNode lowerBound = genericsType.getLowerBound();
@@ -3886,6 +3891,7 @@ private static ClassNode createUsableClassNodeFromGenericsType(final GenericsTyp
38863891
}
38873892
return value;
38883893
}
3894+
*/
38893895

38903896
private static String[] convertToStringArray(final Expression options) {
38913897
if (options == null) {
@@ -4159,7 +4165,7 @@ public void visitMethodCallExpression(MethodCallExpression call) {
41594165
*/
41604166
if (genericsTypes != null && genericsTypes.length == 1
41614167
&& genericsTypes[0].getLowerBound() == null) {
4162-
type = getCombinedBoundType(genericsTypes[0]);
4168+
type = genericsTypes[0].getType();
41634169
} else {
41644170
type = OBJECT_TYPE;
41654171
}

base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java

+7-5
Original file line numberDiff line numberDiff line change
@@ -1896,8 +1896,8 @@ private static void extractGenericsConnections(final Map<GenericsTypeName, Gener
18961896
if (ui.isWildcard()) {
18971897
extractGenericsConnections(connections, ui.getLowerBound(), di.getLowerBound());
18981898
extractGenericsConnections(connections, ui.getUpperBounds(), di.getUpperBounds());
1899+
/* GRECLIPSE edit -- GROOVY-9998, GROOVY-10327
18991900
} else {
1900-
/* GRECLIPSE edit -- GROOVY-9998
19011901
ClassNode cu = ui.getType();
19021902
extractGenericsConnections(connections, cu, di.getLowerBound());
19031903
ClassNode[] upperBounds = di.getUpperBounds();
@@ -1906,17 +1906,19 @@ private static void extractGenericsConnections(final Map<GenericsTypeName, Gener
19061906
extractGenericsConnections(connections, cu, cn);
19071907
}
19081908
}
1909-
*/
1910-
ClassNode boundType = getCombinedBoundType(di);
1909+
}
1910+
*/
1911+
} else if (!isUnboundedWildcard(di)) {
1912+
ClassNode boundType = di.getLowerBound() != null ? di.getLowerBound() : di.getUpperBounds()[0];
19111913
if (boundType.isGenericsPlaceHolder()) {
19121914
String placeholderName = boundType.getUnresolvedName();
19131915
ui = new GenericsType(ui.getType()); ui.setPlaceHolder(false); ui.setWildcard(true);
19141916
connections.put(new GenericsTypeName(placeholderName), ui);
19151917
} else { // di like "? super Collection<T>" and ui like "List<Type>"
19161918
extractGenericsConnections(connections, ui.getType(), boundType);
19171919
}
1918-
// GRECLIPSE end
19191920
}
1921+
// GRECLIPSE end
19201922
} else {
19211923
extractGenericsConnections(connections, ui.getType(), di.getType());
19221924
}
@@ -2080,7 +2082,7 @@ static ClassNode getCombinedBoundType(final GenericsType genericsType) {
20802082
// representing the combination of all bounds. The code here, just picks
20812083
// something out to be able to proceed and is not actually correct
20822084
if (hasNonTrivialBounds(genericsType)) {
2083-
if (genericsType.getLowerBound() != null) return genericsType.getLowerBound();
2085+
if (genericsType.getLowerBound() != null) return OBJECT_TYPE; // GROOVY-10327
20842086
if (genericsType.getUpperBounds() != null) return genericsType.getUpperBounds()[0];
20852087
}
20862088
return genericsType.getType();

base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

+12-1
Original file line numberDiff line numberDiff line change
@@ -3534,12 +3534,21 @@ private ClassNode[] resolveGenericsFromTypeHint(final ClassNode receiver, final
35343534
dummyMN.setGenericsTypes(orig.getGenericsTypes());
35353535
}
35363536
ClassNode classNode = inferReturnTypeGenerics(receiver, dummyMN, arguments);
3537+
/* GRECLIPSE edit -- GROOVY-10327
35373538
ClassNode[] inferred = new ClassNode[classNode.getGenericsTypes().length];
35383539
for (int i = 0; i < classNode.getGenericsTypes().length; i++) {
35393540
GenericsType genericsType = classNode.getGenericsTypes()[i];
35403541
ClassNode value = createUsableClassNodeFromGenericsType(genericsType);
35413542
inferred[i] = value;
35423543
}
3544+
*/
3545+
GenericsType[] returnTypeGenerics = classNode.getGenericsTypes();
3546+
ClassNode[] inferred = new ClassNode[returnTypeGenerics.length];
3547+
for (int i = 0, n = returnTypeGenerics.length; i < n; i += 1) {
3548+
GenericsType genericsType = returnTypeGenerics[i];
3549+
inferred[i] = getCombinedBoundType(genericsType);
3550+
}
3551+
// GRECLIPSE end
35433552
return inferred;
35443553
}
35453554

@@ -3549,6 +3558,7 @@ private ClassNode[] resolveGenericsFromTypeHint(final ClassNode receiver, final
35493558
* @param genericsType a {@link org.codehaus.groovy.ast.GenericsType} representing either a type, a placeholder or a wildcard
35503559
* @return a class node usable as an inferred type
35513560
*/
3561+
/* GRECLIPSE edit
35523562
private static ClassNode createUsableClassNodeFromGenericsType(final GenericsType genericsType) {
35533563
ClassNode value = genericsType.getType();
35543564
if (genericsType.isPlaceholder()) {
@@ -3565,6 +3575,7 @@ private static ClassNode createUsableClassNodeFromGenericsType(final GenericsTyp
35653575
}
35663576
return value;
35673577
}
3578+
*/
35683579

35693580
private static String[] convertToStringArray(final Expression options) {
35703581
if (options == null) {
@@ -3807,7 +3818,7 @@ public void visitMethodCallExpression(final MethodCallExpression call) {
38073818
GenericsType[] genericsTypes = type.getGenericsTypes();
38083819
if (genericsTypes != null && genericsTypes.length == 1
38093820
&& genericsTypes[0].getLowerBound() == null) {
3810-
type = getCombinedBoundType(genericsTypes[0]);
3821+
type = genericsTypes[0].getType();
38113822
} else {
38123823
type = OBJECT_TYPE;
38133824
}

base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -1774,8 +1774,8 @@ private static void extractGenericsConnections(final Map<GenericsTypeName, Gener
17741774
if (ui.isWildcard()) {
17751775
extractGenericsConnections(connections, ui.getLowerBound(), di.getLowerBound());
17761776
extractGenericsConnections(connections, ui.getUpperBounds(), di.getUpperBounds());
1777-
} else {
1778-
ClassNode boundType = getCombinedBoundType(di);
1777+
} else if (!isUnboundedWildcard(di)) {
1778+
ClassNode boundType = di.getLowerBound() != null ? di.getLowerBound() : di.getUpperBounds()[0];
17791779
if (boundType.isGenericsPlaceHolder()) { // GROOVY-9998
17801780
String placeholderName = boundType.getUnresolvedName();
17811781
ui = new GenericsType(ui.getType()); ui.setWildcard(true);
@@ -1916,7 +1916,7 @@ static ClassNode getCombinedBoundType(final GenericsType genericsType) {
19161916
// representing the combination of all bounds. The code here, just picks
19171917
// something out to be able to proceed and is not actually correct
19181918
if (hasNonTrivialBounds(genericsType)) {
1919-
if (genericsType.getLowerBound() != null) return genericsType.getLowerBound();
1919+
if (genericsType.getLowerBound() != null) return OBJECT_TYPE; // GROOVY-10328
19201920
if (genericsType.getUpperBounds() != null) return genericsType.getUpperBounds()[0];
19211921
}
19221922
return genericsType.getType();

base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

+2-27
Original file line numberDiff line numberDiff line change
@@ -3285,36 +3285,11 @@ private ClassNode[] resolveGenericsFromTypeHint(final ClassNode receiver, final
32853285
ClassNode[] inferred = new ClassNode[returnTypeGenerics.length];
32863286
for (int i = 0, n = returnTypeGenerics.length; i < n; i += 1) {
32873287
GenericsType genericsType = returnTypeGenerics[i];
3288-
ClassNode value = createUsableClassNodeFromGenericsType(genericsType);
3289-
inferred[i] = value;
3288+
inferred[i] = getCombinedBoundType(genericsType);
32903289
}
32913290
return inferred;
32923291
}
32933292

3294-
/**
3295-
* Given a GenericsType instance, returns a ClassNode which can be used as an inferred type.
3296-
*
3297-
* @param genericsType a {@link org.codehaus.groovy.ast.GenericsType} representing either a type, a placeholder or a wildcard
3298-
* @return a class node usable as an inferred type
3299-
*/
3300-
private static ClassNode createUsableClassNodeFromGenericsType(final GenericsType genericsType) {
3301-
// TODO: Merge with StaticTypeCheckingSupport#getCombinedBoundType(GenericsType)?
3302-
ClassNode value = genericsType.getType();
3303-
if (genericsType.isPlaceholder()) {
3304-
value = value.isRedirectNode() ? value.redirect() : OBJECT_TYPE;
3305-
}
3306-
ClassNode lowerBound = genericsType.getLowerBound();
3307-
if (lowerBound != null) {
3308-
value = lowerBound;
3309-
} else {
3310-
ClassNode[] upperBounds = genericsType.getUpperBounds();
3311-
if (upperBounds != null) {
3312-
value = lowestUpperBound(Arrays.asList(upperBounds));
3313-
}
3314-
}
3315-
return value;
3316-
}
3317-
33183293
private static String[] convertToStringArray(final Expression options) {
33193294
if (options == null) {
33203295
return ResolveVisitor.EMPTY_STRING_ARRAY;
@@ -3556,7 +3531,7 @@ public void visitMethodCallExpression(final MethodCallExpression call) {
35563531
GenericsType[] genericsTypes = type.getGenericsTypes();
35573532
if (genericsTypes != null && genericsTypes.length == 1
35583533
&& genericsTypes[0].getLowerBound() == null) {
3559-
type = getCombinedBoundType(genericsTypes[0]);
3534+
type = genericsTypes[0].getType();
35603535
} else {
35613536
type = OBJECT_TYPE;
35623537
}

0 commit comments

Comments
 (0)