Skip to content

Commit

Permalink
GROOVY-10327
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Oct 23, 2021
1 parent 323bf18 commit 62910e5
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1780,10 +1780,13 @@ public void testTypeChecked9074d() {
};
//@formatter:on

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

@Test
Expand Down Expand Up @@ -4228,4 +4231,24 @@ public void testTypeChecked10326() {
"Groovy:[Static type checking] - Cannot set read-only property: key\n" +
"----------\n");
}

@Test
public void testTypeChecked10327() {
//@formatter:off
String[] sources = {
"Main.groovy",
"@groovy.transform.TypeChecked\n" +
"void test(Map<String,? super String> map) {\n" +
" @groovy.transform.ASTTest(phase=INSTRUCTION_SELECTION, value={\n" +
" def type = node.getNodeMetaData(org.codehaus.groovy.transform.stc.StaticTypesMarker.INFERRED_TYPE)\n" +
" assert type == org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE\n" +
" })\n" +
" def foo = map.foo\n" +
"}\n" +
"test(foo:'bar')\n",
};
//@formatter:on

runConformTest(sources);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2030,8 +2030,8 @@ private static void extractGenericsConnections(Map<GenericsTypeName, GenericsTyp
if (ui.isWildcard()) {
extractGenericsConnections(connections, ui.getLowerBound(), di.getLowerBound());
extractGenericsConnections(connections, ui.getUpperBounds(), di.getUpperBounds());
/* GRECLIPSE edit -- GROOVY-9998
} else {
/* GRECLIPSE edit -- GROOVY-9998
ClassNode cu = ui.getType();
extractGenericsConnections(connections, cu, di.getLowerBound());
ClassNode[] upperBounds = di.getUpperBounds();
Expand All @@ -2040,17 +2040,19 @@ private static void extractGenericsConnections(Map<GenericsTypeName, GenericsTyp
extractGenericsConnections(connections, cu, cn);
}
}
*/
ClassNode boundType = getCombinedBoundType(di);
}
*/
} else if (!isUnboundedWildcard(di)) {
ClassNode boundType = di.getLowerBound() != null ? di.getLowerBound() : di.getUpperBounds()[0];
if (boundType.isGenericsPlaceHolder()) {
String placeholderName = boundType.getUnresolvedName();
ui = new GenericsType(ui.getType()); ui.setPlaceHolder(false); ui.setWildcard(true);
connections.put(new GenericsTypeName(placeholderName), ui);
} else { // di like "? super Collection<T>" and ui like "List<Type>"
extractGenericsConnections(connections, ui.getType(), boundType);
}
// GRECLIPSE end
}
// GRECLIPSE end
} else {
extractGenericsConnections(connections, ui.getType(), di.getType());
}
Expand Down Expand Up @@ -2205,7 +2207,7 @@ static ClassNode getCombinedBoundType(GenericsType genericsType) {
// 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-10327
if (genericsType.getUpperBounds() != null) return genericsType.getUpperBounds()[0];
}
return genericsType.getType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3850,12 +3850,21 @@ private ClassNode[] resolveGenericsFromTypeHint(final ClassNode receiver, final
dummyMN.setGenericsTypes(orig.getGenericsTypes());
}
ClassNode classNode = inferReturnTypeGenerics(receiver, dummyMN, arguments);
/* GRECLIPSE edit -- GROOVY-10327
ClassNode[] inferred = new ClassNode[classNode.getGenericsTypes().length];
for (int i = 0; i < classNode.getGenericsTypes().length; i++) {
GenericsType genericsType = classNode.getGenericsTypes()[i];
ClassNode value = createUsableClassNodeFromGenericsType(genericsType);
inferred[i] = value;
}
*/
GenericsType[] returnTypeGenerics = classNode.getGenericsTypes();
ClassNode[] inferred = new ClassNode[returnTypeGenerics.length];
for (int i = 0, n = returnTypeGenerics.length; i < n; i += 1) {
GenericsType genericsType = returnTypeGenerics[i];
inferred[i] = getCombinedBoundType(genericsType);
}
// GRECLIPSE end
return inferred;
}

Expand All @@ -3865,14 +3874,10 @@ private ClassNode[] resolveGenericsFromTypeHint(final ClassNode receiver, final
* @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
*/
/* GRECLIPSE edit
private static ClassNode createUsableClassNodeFromGenericsType(final GenericsType genericsType) {
ClassNode value = genericsType.getType();
if (genericsType.isPlaceholder()) {
// GRECLIPSE add -- GROOVY-9968
if (value.isRedirectNode())
value = value.redirect();
else
// GRECLIPSE end
value = OBJECT_TYPE;
}
ClassNode lowerBound = genericsType.getLowerBound();
Expand All @@ -3886,6 +3891,7 @@ private static ClassNode createUsableClassNodeFromGenericsType(final GenericsTyp
}
return value;
}
*/

private static String[] convertToStringArray(final Expression options) {
if (options == null) {
Expand Down Expand Up @@ -4159,7 +4165,7 @@ public void visitMethodCallExpression(MethodCallExpression call) {
*/
if (genericsTypes != null && genericsTypes.length == 1
&& genericsTypes[0].getLowerBound() == null) {
type = getCombinedBoundType(genericsTypes[0]);
type = genericsTypes[0].getType();
} else {
type = OBJECT_TYPE;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1896,8 +1896,8 @@ private static void extractGenericsConnections(final Map<GenericsTypeName, Gener
if (ui.isWildcard()) {
extractGenericsConnections(connections, ui.getLowerBound(), di.getLowerBound());
extractGenericsConnections(connections, ui.getUpperBounds(), di.getUpperBounds());
/* GRECLIPSE edit -- GROOVY-9998, GROOVY-10327
} else {
/* GRECLIPSE edit -- GROOVY-9998
ClassNode cu = ui.getType();
extractGenericsConnections(connections, cu, di.getLowerBound());
ClassNode[] upperBounds = di.getUpperBounds();
Expand All @@ -1906,17 +1906,19 @@ private static void extractGenericsConnections(final Map<GenericsTypeName, Gener
extractGenericsConnections(connections, cu, cn);
}
}
*/
ClassNode boundType = getCombinedBoundType(di);
}
*/
} else if (!isUnboundedWildcard(di)) {
ClassNode boundType = di.getLowerBound() != null ? di.getLowerBound() : di.getUpperBounds()[0];
if (boundType.isGenericsPlaceHolder()) {
String placeholderName = boundType.getUnresolvedName();
ui = new GenericsType(ui.getType()); ui.setPlaceHolder(false); ui.setWildcard(true);
connections.put(new GenericsTypeName(placeholderName), ui);
} else { // di like "? super Collection<T>" and ui like "List<Type>"
extractGenericsConnections(connections, ui.getType(), boundType);
}
// GRECLIPSE end
}
// GRECLIPSE end
} else {
extractGenericsConnections(connections, ui.getType(), di.getType());
}
Expand Down Expand Up @@ -2080,7 +2082,7 @@ static ClassNode getCombinedBoundType(final GenericsType genericsType) {
// 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-10327
if (genericsType.getUpperBounds() != null) return genericsType.getUpperBounds()[0];
}
return genericsType.getType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3534,12 +3534,21 @@ private ClassNode[] resolveGenericsFromTypeHint(final ClassNode receiver, final
dummyMN.setGenericsTypes(orig.getGenericsTypes());
}
ClassNode classNode = inferReturnTypeGenerics(receiver, dummyMN, arguments);
/* GRECLIPSE edit -- GROOVY-10327
ClassNode[] inferred = new ClassNode[classNode.getGenericsTypes().length];
for (int i = 0; i < classNode.getGenericsTypes().length; i++) {
GenericsType genericsType = classNode.getGenericsTypes()[i];
ClassNode value = createUsableClassNodeFromGenericsType(genericsType);
inferred[i] = value;
}
*/
GenericsType[] returnTypeGenerics = classNode.getGenericsTypes();
ClassNode[] inferred = new ClassNode[returnTypeGenerics.length];
for (int i = 0, n = returnTypeGenerics.length; i < n; i += 1) {
GenericsType genericsType = returnTypeGenerics[i];
inferred[i] = getCombinedBoundType(genericsType);
}
// GRECLIPSE end
return inferred;
}

Expand All @@ -3549,6 +3558,7 @@ private ClassNode[] resolveGenericsFromTypeHint(final ClassNode receiver, final
* @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
*/
/* GRECLIPSE edit
private static ClassNode createUsableClassNodeFromGenericsType(final GenericsType genericsType) {
ClassNode value = genericsType.getType();
if (genericsType.isPlaceholder()) {
Expand All @@ -3565,6 +3575,7 @@ private static ClassNode createUsableClassNodeFromGenericsType(final GenericsTyp
}
return value;
}
*/

private static String[] convertToStringArray(final Expression options) {
if (options == null) {
Expand Down Expand Up @@ -3807,7 +3818,7 @@ public void visitMethodCallExpression(final MethodCallExpression call) {
GenericsType[] genericsTypes = type.getGenericsTypes();
if (genericsTypes != null && genericsTypes.length == 1
&& genericsTypes[0].getLowerBound() == null) {
type = getCombinedBoundType(genericsTypes[0]);
type = genericsTypes[0].getType();
} else {
type = OBJECT_TYPE;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1774,8 +1774,8 @@ private static void extractGenericsConnections(final Map<GenericsTypeName, Gener
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);
Expand Down Expand Up @@ -1916,7 +1916,7 @@ static ClassNode getCombinedBoundType(final GenericsType genericsType) {
// 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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3285,36 +3285,11 @@ private ClassNode[] resolveGenericsFromTypeHint(final ClassNode receiver, final
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;
Expand Down Expand Up @@ -3556,7 +3531,7 @@ public void visitMethodCallExpression(final MethodCallExpression call) {
GenericsType[] genericsTypes = type.getGenericsTypes();
if (genericsTypes != null && genericsTypes.length == 1
&& genericsTypes[0].getLowerBound() == null) {
type = getCombinedBoundType(genericsTypes[0]);
type = genericsTypes[0].getType();
} else {
type = OBJECT_TYPE;
}
Expand Down

0 comments on commit 62910e5

Please sign in to comment.