Skip to content

Commit 8ca4d13

Browse files
committed
GROOVY-10291
1 parent 41556b2 commit 8ca4d13

File tree

4 files changed

+80
-53
lines changed

4 files changed

+80
-53
lines changed

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

+26
Original file line numberDiff line numberDiff line change
@@ -4150,6 +4150,32 @@ public void testTypeChecked10283() {
41504150
runConformTest(sources);
41514151
}
41524152

4153+
@Test
4154+
public void testTypeChecked10291() {
4155+
//@formatter:off
4156+
String[] sources = {
4157+
"Main.groovy",
4158+
"@groovy.transform.TupleConstructor(defaults=false)\n" +
4159+
"class A<X> {\n" +
4160+
" X x\n" +
4161+
"}\n" +
4162+
"class B<Y> {\n" +
4163+
" def method(Y y) { null }\n" +
4164+
" @groovy.transform.TypeChecked\n" +
4165+
" void test() {\n" +
4166+
" def closure = { Y why -> null }\n" +
4167+
" Y y = null\n" +
4168+
" method(new A<>(y).x)\n" + // works
4169+
" closure(new A<>(y).x)\n" + // fails
4170+
" }\n" +
4171+
"}\n" +
4172+
"new B().test()\n",
4173+
};
4174+
//@formatter:on
4175+
4176+
runConformTest(sources);
4177+
}
4178+
41534179
@Test
41544180
public void testTypeChecked10294() {
41554181
//@formatter:off

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

+19-18
Original file line numberDiff line numberDiff line change
@@ -1217,7 +1217,7 @@ protected void inferDiamondType(final ConstructorCallExpression cce, final Class
12171217
// check if constructor call expression makes use of the diamond operator
12181218
if (cceType.getGenericsTypes() != null && cceType.getGenericsTypes().length == 0) {
12191219
ArgumentListExpression argumentListExpression = InvocationWriter.makeArgumentList(cce.getArguments());
1220-
/* GRECLIPSE edit -- GROOVY-9948, GROOVY-9983
1220+
/* GRECLIPSE edit -- GROOVY-9948, GROOVY-9983, GROOVY-10291
12211221
if (argumentListExpression.getExpressions().isEmpty()) {
12221222
adjustGenerics(lType, cceType);
12231223
} else {
@@ -1233,23 +1233,23 @@ protected void inferDiamondType(final ConstructorCallExpression cce, final Class
12331233
if (!argumentListExpression.getExpressions().isEmpty() && constructor != null) {
12341234
ClassNode type = GenericsUtils.parameterizeType(cceType, cceType);
12351235
type = inferReturnTypeGenerics(type, constructor, argumentListExpression);
1236-
if (type.isUsingGenerics()) {
1237-
// GROOVY-6232, GROOVY-9956: if cce not assignment compatible, process target as additional type witness
1238-
if (GenericsUtils.hasUnresolvedGenerics(type) || checkCompatibleAssignmentTypes(lType, type, cce) && !GenericsUtils.buildWildcardType(lType).isCompatibleWith(type)) {
1239-
// allow covariance of each type parameter, but maintain semantics for nested generics
1240-
1241-
ClassNode pType = GenericsUtils.parameterizeType(lType, type);
1242-
GenericsType[] lhs = pType.getGenericsTypes(), rhs = type.getGenericsTypes();
1243-
if (lhs == null || rhs == null || lhs.length != rhs.length) throw new GroovyBugError(
1244-
"Parameterization failed: " + prettyPrintType(pType) + " ~ " + prettyPrintType(type));
1245-
1246-
if (java.util.stream.IntStream.range(0, lhs.length).allMatch(i ->
1247-
GenericsUtils.buildWildcardType(getCombinedBoundType(lhs[i])).isCompatibleWith(getCombinedBoundType(rhs[i])))) {
1248-
type = pType; // lType proved to be a viable type witness
1249-
}
1236+
// process target as additional type witness, if ...
1237+
if (type.toString(false).indexOf('#') > 0 // unresolved generics
1238+
// GROOVY-6232, GROOVY-9956: cce not assignment compatible
1239+
|| checkCompatibleAssignmentTypes(lType, type, cce) && !GenericsUtils.buildWildcardType(lType).isCompatibleWith(type)) {
1240+
// allow covariance of each type parameter, but maintain semantics for nested generics
1241+
1242+
ClassNode pType = GenericsUtils.parameterizeType(lType, type);
1243+
GenericsType[] lhs = pType.getGenericsTypes(), rhs = type.getGenericsTypes();
1244+
if (lhs == null || rhs == null || lhs.length != rhs.length) throw new GroovyBugError(
1245+
"Parameterization failed: " + prettyPrintType(pType) + " ~ " + prettyPrintType(type));
1246+
1247+
if (java.util.stream.IntStream.range(0, lhs.length).allMatch(i ->
1248+
GenericsUtils.buildWildcardType(getCombinedBoundType(lhs[i])).isCompatibleWith(getCombinedBoundType(rhs[i])))) {
1249+
type = pType; // lType proved to be a viable type witness
12501250
}
1251-
inferredType = type;
12521251
}
1252+
inferredType = type;
12531253
}
12541254
adjustGenerics(inferredType, cceType);
12551255
storeType(cce, cceType);
@@ -1744,9 +1744,10 @@ protected boolean existsProperty(final PropertyExpression pexp, final boolean re
17441744

17451745
Expression objectExpression = pexp.getObjectExpression();
17461746
ClassNode objectExpressionType = getType(objectExpression);
1747-
// GRECLIPSE add -- GROOVY-9963
1747+
// GRECLIPSE add -- GROOVY-9963, GROOVY-10291
17481748
if (objectExpression instanceof ConstructorCallExpression) {
1749-
inferDiamondType((ConstructorCallExpression) objectExpression, objectExpressionType);
1749+
ClassNode rawType = objectExpressionType.getPlainNodeReference();
1750+
inferDiamondType((ConstructorCallExpression) objectExpression, rawType);
17501751
}
17511752
// GRECLIPSE end
17521753
List<ClassNode> enclosingTypes = typeCheckingContext.getEnclosingClassNodes();

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

+19-18
Original file line numberDiff line numberDiff line change
@@ -1114,7 +1114,7 @@ protected void inferDiamondType(final ConstructorCallExpression cce, final Class
11141114
ClassNode cceType = cce.getType(), inferredType = lType;
11151115
// check if constructor call expression makes use of the diamond operator
11161116
if (cceType.getGenericsTypes() != null && cceType.getGenericsTypes().length == 0) {
1117-
/* GRECLIPSE edit -- GROOVY-9948, GROOVY-9983
1117+
/* GRECLIPSE edit -- GROOVY-9948, GROOVY-9983, GROOVY-10291
11181118
ArgumentListExpression argumentListExpression = InvocationWriter.makeArgumentList(cce.getArguments());
11191119
if (argumentListExpression.getExpressions().isEmpty()) {
11201120
adjustGenerics(lType, cceType);
@@ -1132,23 +1132,23 @@ protected void inferDiamondType(final ConstructorCallExpression cce, final Class
11321132
if (!argumentList.getExpressions().isEmpty() && constructor != null) {
11331133
ClassNode type = GenericsUtils.parameterizeType(cceType, cceType);
11341134
type = inferReturnTypeGenerics(type, constructor, argumentList);
1135-
if (type.isUsingGenerics()) {
1136-
// GROOVY-6232, GROOVY-9956: if cce not assignment compatible, process target as additional type witness
1137-
if (GenericsUtils.hasUnresolvedGenerics(type) || checkCompatibleAssignmentTypes(lType, type, cce) && !GenericsUtils.buildWildcardType(lType).isCompatibleWith(type)) {
1138-
// allow covariance of each type parameter, but maintain semantics for nested generics
1139-
1140-
ClassNode pType = GenericsUtils.parameterizeType(lType, type);
1141-
GenericsType[] lhs = pType.getGenericsTypes(), rhs = type.getGenericsTypes();
1142-
if (lhs == null || rhs == null || lhs.length != rhs.length) throw new GroovyBugError(
1143-
"Parameterization failed: " + prettyPrintType(pType) + " ~ " + prettyPrintType(type));
1144-
1145-
if (java.util.stream.IntStream.range(0, lhs.length).allMatch(i ->
1146-
GenericsUtils.buildWildcardType(getCombinedBoundType(lhs[i])).isCompatibleWith(getCombinedBoundType(rhs[i])))) {
1147-
type = pType; // lType proved to be a viable type witness
1148-
}
1135+
// process target as additional type witness, if ...
1136+
if (type.toString(false).indexOf('#') > 0 // unresolved generics
1137+
// GROOVY-6232, GROOVY-9956: cce not assignment compatible
1138+
|| checkCompatibleAssignmentTypes(lType, type, cce) && !GenericsUtils.buildWildcardType(lType).isCompatibleWith(type)) {
1139+
// allow covariance of each type parameter, but maintain semantics for nested generics
1140+
1141+
ClassNode pType = GenericsUtils.parameterizeType(lType, type);
1142+
GenericsType[] lhs = pType.getGenericsTypes(), rhs = type.getGenericsTypes();
1143+
if (lhs == null || rhs == null || lhs.length != rhs.length) throw new GroovyBugError(
1144+
"Parameterization failed: " + prettyPrintType(pType) + " ~ " + prettyPrintType(type));
1145+
1146+
if (java.util.stream.IntStream.range(0, lhs.length).allMatch(i ->
1147+
GenericsUtils.buildWildcardType(getCombinedBoundType(lhs[i])).isCompatibleWith(getCombinedBoundType(rhs[i])))) {
1148+
type = pType; // lType proved to be a viable type witness
11491149
}
1150-
inferredType = type;
11511150
}
1151+
inferredType = type;
11521152
}
11531153
adjustGenerics(inferredType, cceType);
11541154
storeType(cce, cceType);
@@ -1660,9 +1660,10 @@ protected boolean existsProperty(final PropertyExpression pexp, final boolean re
16601660

16611661
Expression objectExpression = pexp.getObjectExpression();
16621662
ClassNode objectExpressionType = getType(objectExpression);
1663-
// GRECLIPSE add -- GROOVY-9963
1663+
// GRECLIPSE add -- GROOVY-9963, GROOVY-10291
16641664
if (objectExpression instanceof ConstructorCallExpression) {
1665-
inferDiamondType((ConstructorCallExpression) objectExpression, objectExpressionType);
1665+
ClassNode rawType = objectExpressionType.getPlainNodeReference();
1666+
inferDiamondType((ConstructorCallExpression) objectExpression, rawType);
16661667
}
16671668
// GRECLIPSE end
16681669
List<ClassNode> enclosingTypes = typeCheckingContext.getEnclosingClassNodes();

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

+16-17
Original file line numberDiff line numberDiff line change
@@ -1098,24 +1098,22 @@ protected void inferDiamondType(final ConstructorCallExpression cce, final Class
10981098
if (!argumentList.getExpressions().isEmpty() && constructor != null) {
10991099
ClassNode type = GenericsUtils.parameterizeType(cceType, cceType);
11001100
type = inferReturnTypeGenerics(type, constructor, argumentList);
1101-
if (type.isUsingGenerics()) {
1102-
// GROOVY-6232, GROOVY-9956: if cce not assignment compatible, process target as additional type witness
1103-
if (GenericsUtils.hasUnresolvedGenerics(type) || checkCompatibleAssignmentTypes(lType, type, cce)
1104-
&& !GenericsUtils.buildWildcardType(lType).isCompatibleWith(type)) {
1105-
// allow covariance of each type parameter, but maintain semantics for nested generics
1106-
1107-
ClassNode pType = GenericsUtils.parameterizeType(lType, type);
1108-
GenericsType[] lhs = pType.getGenericsTypes(), rhs = type.getGenericsTypes();
1109-
if (lhs == null || rhs == null || lhs.length != rhs.length) throw new GroovyBugError(
1110-
"Parameterization failed: " + prettyPrintType(pType) + " ~ " + prettyPrintType(type));
1111-
1112-
if (java.util.stream.IntStream.range(0, lhs.length).allMatch(i ->
1113-
GenericsUtils.buildWildcardType(getCombinedBoundType(lhs[i])).isCompatibleWith(getCombinedBoundType(rhs[i])))) {
1114-
type = pType; // lType proved to be a viable type witness
1115-
}
1101+
if (type.toString(false).indexOf('#') > 0 // GROOVY-9983, GROOVY-10291
1102+
// GROOVY-6232, GROOVY-9956: if cce not assignment compatible, process target as additional type witness
1103+
|| checkCompatibleAssignmentTypes(lType, type, cce) && !GenericsUtils.buildWildcardType(lType).isCompatibleWith(type)) {
1104+
// allow covariance of each type parameter, but maintain semantics for nested generics
1105+
1106+
ClassNode pType = GenericsUtils.parameterizeType(lType, type);
1107+
GenericsType[] lhs = pType.getGenericsTypes(), rhs = type.getGenericsTypes();
1108+
if (lhs == null || rhs == null || lhs.length != rhs.length) throw new GroovyBugError(
1109+
"Parameterization failed: " + prettyPrintType(pType) + " ~ " + prettyPrintType(type));
1110+
1111+
if (java.util.stream.IntStream.range(0, lhs.length).allMatch(i ->
1112+
GenericsUtils.buildWildcardType(getCombinedBoundType(lhs[i])).isCompatibleWith(getCombinedBoundType(rhs[i])))) {
1113+
type = pType; // lType proved to be a viable type witness
11161114
}
1117-
inferredType = type;
11181115
}
1116+
inferredType = type;
11191117
}
11201118
adjustGenerics(inferredType, cceType);
11211119
storeType(cce, cceType);
@@ -1491,7 +1489,8 @@ protected boolean existsProperty(final PropertyExpression pexp, final boolean re
14911489
Expression objectExpression = pexp.getObjectExpression();
14921490
ClassNode objectExpressionType = getType(objectExpression);
14931491
if (objectExpression instanceof ConstructorCallExpression) {
1494-
inferDiamondType((ConstructorCallExpression) objectExpression, objectExpressionType);
1492+
ClassNode rawType = objectExpressionType.getPlainNodeReference();
1493+
inferDiamondType((ConstructorCallExpression) objectExpression, rawType);
14951494
}
14961495
List<ClassNode> enclosingTypes = typeCheckingContext.getEnclosingClassNodes();
14971496

0 commit comments

Comments
 (0)