You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2021/05/18 19:35:37 UTC
[groovy] branch master updated: GROOVY-8310,
GROOVY-10091: STC: allow simple covariace of closure return
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 f3d030a GROOVY-8310, GROOVY-10091: STC: allow simple covariace of closure return
f3d030a is described below
commit f3d030afaaae44eca567ead74e68efb932831b08
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue May 18 13:06:27 2021 -0500
GROOVY-8310, GROOVY-10091: STC: allow simple covariace of closure return
---
.../transform/stc/StaticTypeCheckingVisitor.java | 8 ++---
src/test/groovy/bugs/Groovy8310.groovy | 39 ++++++++++------------
.../groovy/transform/stc/ClosuresSTCTest.groovy | 26 +++++++++++++--
3 files changed, 45 insertions(+), 28 deletions(-)
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 4c2cdf6..a0edd33 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -2207,10 +2207,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
if (isStringType(inferredReturnType) && isGStringOrGStringStringLUB(type)) {
type = STRING_TYPE; // GROOVY-9971: convert GString to String at point of return
- } else if (inferredReturnType != null && !inferredReturnType.isGenericsPlaceHolder()
- && !type.isUsingGenerics() && !type.equals(inferredReturnType) && (inferredReturnType.isInterface()
- ? type.implementsInterface(inferredReturnType) : type.isDerivedFrom(inferredReturnType))) {
- type = inferredReturnType; // GROOVY-10082: allow simple covariance
+ } else if (inferredReturnType != null
+ && !GenericsUtils.hasUnresolvedGenerics(inferredReturnType)
+ && GenericsUtils.buildWildcardType(inferredReturnType).isCompatibleWith(type)) {
+ type = inferredReturnType; // GROOVY-8310, GROOVY-10082, GROOVY-10091: allow simple covariance
}
return type;
}
diff --git a/src/test/groovy/bugs/Groovy8310.groovy b/src/test/groovy/bugs/Groovy8310.groovy
index d6e4116..14ba764 100644
--- a/src/test/groovy/bugs/Groovy8310.groovy
+++ b/src/test/groovy/bugs/Groovy8310.groovy
@@ -18,101 +18,98 @@
*/
package groovy.bugs
-import groovy.transform.CompileStatic
import org.junit.Test
import static groovy.test.GroovyAssert.assertScript
-import static groovy.test.GroovyAssert.shouldFail
-@CompileStatic
final class Groovy8310 {
@Test
void testClosureReturnType1() {
- def err = shouldFail '''
+ assertScript '''
def bar(Closure<Collection<Integer>> block) {
block()
}
@groovy.transform.CompileStatic
- def use() {
+ def foo() {
bar {
[1]
}
}
- '''
- assert err =~ /Cannot find matching method \w+#bar\(groovy.lang.Closure<java.util.List<java.lang.Integer>>\)/
+ assert foo() == [1]
+ '''
}
@Test
void testClosureReturnType2() {
- def err = shouldFail '''
- public <T> T bar(Closure<Collection<Integer>> block) {
+ assertScript '''
+ def <T> T bar(Closure<Collection<Integer>> block) {
block()
}
@groovy.transform.CompileStatic
- def use() {
+ def foo() {
bar {
[1]
}
}
- '''
- assert err =~ /Cannot call <T> \w+#bar\(groovy.lang.Closure<java.util.Collection<java.lang.Integer>>\) with arguments \[groovy.lang.Closure<java.util.List<java.lang.Integer>>\]/
+ assert foo() == [1]
+ '''
}
@Test
void testClosureReturnType3() {
assertScript '''
- public <T> T bar(Closure<? extends Collection<Integer>> block) {
+ def <T> T bar(Closure<? extends Collection<Integer>> block) {
block()
}
@groovy.transform.CompileStatic
- def use() {
+ def foo() {
bar {
[1]
}
}
- assert use() == [1]
+ assert foo() == [1]
'''
}
@Test
void testClosureReturnType4() {
assertScript '''
- public <T> T bar(Closure<Collection<Integer>> block) {
+ def <T> T bar(Closure<Collection<Integer>> block) {
block()
}
@groovy.transform.CompileStatic
- def use() {
+ def foo() {
bar {
(Collection<Integer>) [1]
}
}
- assert use() == [1]
+ assert foo() == [1]
'''
}
@Test
void testClosureReturnType5() {
assertScript '''
- public <T> T bar(Closure<Collection<Integer>> block) {
+ def <T> T bar(Closure<Collection<Integer>> block) {
block()
}
- def use() {
+ def foo() {
bar {
[1] as Collection<Integer>
}
}
- assert use() == [1]
+ assert foo() == [1]
'''
}
}
diff --git a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
index 4024fc3..437c63e 100644
--- a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
@@ -165,16 +165,36 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
assertScript '''
class A {}
class B extends A {}
- Closure<A> c = { -> new B() } // Cannot assign Closure<B> to Closure<A>
+ Closure<A> c = { -> new B() }
def result = c()
assert result instanceof A
assert result instanceof B
'''
+ shouldFailWithMessages '''
+ Closure<String> c = { -> 42 }
+ ''',
+ 'Cannot assign groovy.lang.Closure<java.lang.Integer> to: groovy.lang.Closure<java.lang.String>'
}
- // GROOVY-8427
+ // GROOVY-10091
void testClosureReturnTypeInference7() {
+ shouldFailWithMessages '''
+ class A<T> {}
+ class B extends A<Number> {}
+ class X extends A<String> {}
+ class Y<Z> extends A<Number> {}
+
+ Closure<A<Number>> c
+ c = { -> return new B() }
+ c = { -> return new X() }
+ c = { -> return new Y<String>() }
+ ''',
+ 'Cannot assign groovy.lang.Closure<X> to: groovy.lang.Closure<A<java.lang.Number>>'
+ }
+
+ // GROOVY-8427
+ void testClosureReturnTypeInference8() {
assertScript '''
import java.util.function.Consumer
@@ -196,7 +216,7 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
}
// GROOVY-8202
- void testClosureReturnTypeInference8() {
+ void testClosureReturnTypeInference9() {
assertScript '''
void proc() {
}