Skip to content

Commit e66f8fb

Browse files
committed
GROOVY-8310, GROOVY-10082, GROOVY-10091
1 parent 75b9406 commit e66f8fb

File tree

5 files changed

+65
-26
lines changed

5 files changed

+65
-26
lines changed

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

+7-12
Original file line numberDiff line numberDiff line change
@@ -1764,25 +1764,20 @@ public void testCompileStatic8310() {
17641764
//@formatter:off
17651765
String[] sources = {
17661766
"Main.groovy",
1767-
"def bar(Closure<Collection<Integer>> block) {\n" +
1768-
" block()\n" +
1767+
"def bar(Closure<Collection<Integer>> baz) {\n" +
1768+
" baz()\n" +
17691769
"}\n" +
17701770
"@groovy.transform.CompileStatic\n" +
1771-
"def use() {\n" +
1771+
"def foo() {\n" +
17721772
" bar {\n" +
1773-
" [1]\n" + // List<Integer> is not compatible with Collection<Integer>; "? extends Collection<Integer>" works
1773+
" [1]\n" +
17741774
" }\n" +
1775-
"}\n",
1775+
"}\n" +
1776+
"print foo()\n",
17761777
};
17771778
//@formatter:on
17781779

1779-
runNegativeTest(sources,
1780-
"----------\n" +
1781-
"1. ERROR in Main.groovy (at line 6)\n" +
1782-
"\tbar {\n" +
1783-
"\t^\n" +
1784-
"Groovy:[Static type checking] - Cannot find matching method Main#bar(groovy.lang.Closure<java.util.List<java.lang.Integer>>). Please check if the declared type is correct and if the method exists.\n" +
1785-
"----------\n");
1780+
runConformTest(sources, "[1]");
17861781
}
17871782

17881783
@Test

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

+48
Original file line numberDiff line numberDiff line change
@@ -2762,6 +2762,27 @@ public void testTypeChecked10082() {
27622762
runConformTest(sources, "truetrue");
27632763
}
27642764

2765+
@Test
2766+
public void testTypeChecked10082a() {
2767+
//@formatter:off
2768+
String[] sources = {
2769+
"Main.groovy",
2770+
"@groovy.transform.TypeChecked\n" +
2771+
"void test() {\n" +
2772+
" Closure<String> c = {-> 42}\n" +
2773+
"}\n",
2774+
};
2775+
//@formatter:on
2776+
2777+
runNegativeTest(sources,
2778+
"----------\n" +
2779+
"1. ERROR in Main.groovy (at line 3)\n" +
2780+
"\tClosure<String> c = {-> 42}\n" +
2781+
"\t ^^^^^^^\n" +
2782+
"Groovy:[Static type checking] - Incompatible generic argument types. Cannot assign groovy.lang.Closure<java.lang.Integer> to: groovy.lang.Closure<java.lang.String>\n" +
2783+
"----------\n");
2784+
}
2785+
27652786
@Test
27662787
public void testTypeChecked10086() {
27672788
//@formatter:off
@@ -2819,4 +2840,31 @@ public void testTypeChecked10088() {
28192840
"Groovy:[Static type checking] - Cannot assign value of type java.lang.String to variable of type java.lang.Number\n" +
28202841
"----------\n");
28212842
}
2843+
2844+
@Test
2845+
public void testTypeChecked10091() {
2846+
//@formatter:off
2847+
String[] sources = {
2848+
"Main.groovy",
2849+
"class A<T> {}\n" +
2850+
"class B extends A<Number> {}\n" +
2851+
"class X extends A<String> {}\n" +
2852+
"class Y<Z> extends A<Number> {}\n" +
2853+
"@groovy.transform.TypeChecked\n" +
2854+
"void test() {\n" +
2855+
" Closure<A<Number>> b = { -> new B()}\n" +
2856+
" Closure<A<Number>> x = { -> new X()}\n" +
2857+
" Closure<A<Number>> y = { -> new Y<String>()}\n" +
2858+
"}\n",
2859+
};
2860+
//@formatter:on
2861+
2862+
runNegativeTest(sources,
2863+
"----------\n" +
2864+
"1. ERROR in Main.groovy (at line 8)\n" +
2865+
"\tClosure<A<Number>> x = { -> new X()}\n" +
2866+
"\t ^^^^^^^^^^^^^\n" +
2867+
"Groovy:[Static type checking] - Incompatible generic argument types. Cannot assign groovy.lang.Closure<X> to: groovy.lang.Closure<A<java.lang.Number>>\n" +
2868+
"----------\n");
2869+
}
28222870
}

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

+3-4
Original file line numberDiff line numberDiff line change
@@ -2643,7 +2643,7 @@ private ClassNode infer(ClassNode target, ClassNode source) {
26432643

26442644
protected ClassNode checkReturnType(final ReturnStatement statement) {
26452645
Expression expression = statement.getExpression();
2646-
/* GRECLIPSE edit -- GROOVY-9907, GROOVY-9971, GROOVY-9995, GROOVY-10080, GROOVY-10082
2646+
/* GRECLIPSE edit -- GROOVY-8310, GROOVY-9907, GROOVY-9971, GROOVY-9995, GROOVY-10080, GROOVY-10082, GROOVY-10091
26472647
ClassNode type = getType(expression);
26482648
26492649
if (typeCheckingContext.getEnclosingClosure() != null) {
@@ -2667,9 +2667,8 @@ protected ClassNode checkReturnType(final ReturnStatement statement) {
26672667
}
26682668
if (STRING_TYPE.equals(inferredReturnType) && StaticTypeCheckingSupport.isGStringOrGStringStringLUB(type)) {
26692669
type = STRING_TYPE; // implicit "toString()" before return
2670-
} else if (inferredReturnType != null && !inferredReturnType.isGenericsPlaceHolder()
2671-
&& !type.isUsingGenerics() && !type.equals(inferredReturnType) && (inferredReturnType.isInterface()
2672-
? type.implementsInterface(inferredReturnType) : type.isDerivedFrom(inferredReturnType))) {
2670+
} else if (inferredReturnType != null && !GenericsUtils.hasUnresolvedGenerics(inferredReturnType)
2671+
&& GenericsUtils.buildWildcardType(inferredReturnType).isCompatibleWith(type)) {
26732672
type = inferredReturnType; // allow simple covariance
26742673
}
26752674
return type;

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

+3-4
Original file line numberDiff line numberDiff line change
@@ -2395,16 +2395,15 @@ protected ClassNode checkReturnType(final ReturnStatement statement) {
23952395
type = getType(expression);
23962396
}
23972397
if (typeCheckingContext.getEnclosingClosure() != null) {
2398-
// GRECLIPSE add -- GROOVY-9971, GROOVY-9995, GROOVY-10080, GROOVY-10082
2398+
// GRECLIPSE add -- GROOVY-8310, GROOVY-9971, GROOVY-9995, GROOVY-10080, GROOVY-10082, GROOVY-10091
23992399
ClassNode inferredReturnType = getInferredReturnType(typeCheckingContext.getEnclosingClosure().getClosureExpression());
24002400
if (expression instanceof ConstructorCallExpression) {
24012401
inferDiamondType((ConstructorCallExpression) expression, inferredReturnType != null ? inferredReturnType : DYNAMIC_TYPE);
24022402
}
24032403
if (STRING_TYPE.equals(inferredReturnType) && StaticTypeCheckingSupport.isGStringOrGStringStringLUB(type)) {
24042404
type = STRING_TYPE; // implicit "toString()" before return
2405-
} else if (inferredReturnType != null && !inferredReturnType.isGenericsPlaceHolder()
2406-
&& !type.isUsingGenerics() && !type.equals(inferredReturnType) && (inferredReturnType.isInterface()
2407-
? type.implementsInterface(inferredReturnType) : type.isDerivedFrom(inferredReturnType))) {
2405+
} else if (inferredReturnType != null && !GenericsUtils.hasUnresolvedGenerics(inferredReturnType)
2406+
&& GenericsUtils.buildWildcardType(inferredReturnType).isCompatibleWith(type)) {
24082407
type = inferredReturnType; // allow simple covariance
24092408
}
24102409
// GRECLIPSE end

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

+4-6
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,6 @@
268268
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.isBoolIntrinsicOp;
269269
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.isClassClassNodeWrappingConcreteType;
270270
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.isCompareToBoolean;
271-
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.isGStringOrGStringStringLUB;
272271
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.isOperationInGroup;
273272
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.isParameterizedWithGStringOrGStringString;
274273
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.isParameterizedWithString;
@@ -2312,7 +2311,7 @@ protected ClassNode checkReturnType(final ReturnStatement statement) {
23122311
type = getType(expression);
23132312
}
23142313
if (typeCheckingContext.getEnclosingClosure() != null) {
2315-
/* GRECLIPSE edit -- GROOVY-9971, GROOVY-9995, GROOVY-10080, GROOVY-10082
2314+
/* GRECLIPSE edit -- GROOVY-8310, GROOVY-9971, GROOVY-9995, GROOVY-10080, GROOVY-10082, GROOVY-10091
23162315
if (expression instanceof ConstructorCallExpression) {
23172316
ClassNode inferredClosureReturnType = getInferredReturnType(typeCheckingContext.getEnclosingClosure().getClosureExpression());
23182317
if (inferredClosureReturnType != null) inferDiamondType((ConstructorCallExpression) expression, inferredClosureReturnType);
@@ -2322,11 +2321,10 @@ protected ClassNode checkReturnType(final ReturnStatement statement) {
23222321
if (expression instanceof ConstructorCallExpression) {
23232322
inferDiamondType((ConstructorCallExpression) expression, inferredReturnType != null ? inferredReturnType : DYNAMIC_TYPE);
23242323
}
2325-
if (STRING_TYPE.equals(inferredReturnType) && isGStringOrGStringStringLUB(type)) {
2324+
if (STRING_TYPE.equals(inferredReturnType) && StaticTypeCheckingSupport.isGStringOrGStringStringLUB(type)) {
23262325
type = STRING_TYPE; // convert GString to String at the point of return
2327-
} else if (inferredReturnType != null && !inferredReturnType.isGenericsPlaceHolder()
2328-
&& !type.isUsingGenerics() && !type.equals(inferredReturnType) && (inferredReturnType.isInterface()
2329-
? type.implementsInterface(inferredReturnType) : type.isDerivedFrom(inferredReturnType))) {
2326+
} else if (inferredReturnType != null && !GenericsUtils.hasUnresolvedGenerics(inferredReturnType)
2327+
&& GenericsUtils.buildWildcardType(inferredReturnType).isCompatibleWith(type)) {
23302328
type = inferredReturnType; // allow simple covariance
23312329
}
23322330
// GRECLIPSE end

0 commit comments

Comments
 (0)