Permalink
Browse files

GROOVY-5748: STC - Cannot find method due to wrong return type inference

  • Loading branch information...
1 parent 0728bb8 commit 5478bc33bb848fa2d3dda430dcea2b335ab16539 @melix melix committed Oct 10, 2012
View
11 src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1311,7 +1311,8 @@ private ClassNode checkReturnType(final ReturnStatement statement) {
);
virtualDecl.setSourcePosition(statement);
virtualDecl.visit(this);
- inferred = (ClassNode) virtualDecl.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
+ ClassNode newlyInferred = (ClassNode) virtualDecl.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
+ if (!missesGenericsTypes(newlyInferred)) inferred = newlyInferred;
}
methodNode.putNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE, inferred);
return inferred;
@@ -2783,6 +2784,14 @@ private ClassNode inferReturnTypeGenerics(final ClassNode receiver, final Method
}
}
+ // GROOVY-5748
+ if (returnType.isGenericsPlaceHolder()) {
+ GenericsType resolved = resolvedPlaceholders.get(returnType.getUnresolvedName());
+ if (resolved!=null && !resolved.isPlaceholder() && !resolved.isWildcard()) {
+ return resolved.getType();
+ }
+ }
+
GenericsType[] copy = new GenericsType[returnTypeGenerics.length];
for (int i = 0; i < copy.length; i++) {
GenericsType returnTypeGeneric = returnTypeGenerics[i];
View
60 src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -870,6 +870,66 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
''', '#printEqual(java.lang.Object <T>, java.util.List <T>) with arguments [int, java.util.List <java.lang.String>]'
}
+ void testGroovy5748() {
+ assertScript '''
+ interface IStack<T> {
+ INonEmptyStack<T, ? extends IStack<T>> push(T x)
+ }
+
+ interface IEmptyStack<T> extends IStack<T> {
+ INonEmptyStack<T, IEmptyStack<T>> push(T x)
+ }
+
+ interface INonEmptyStack<T, TStackBeneath extends IStack<T>> extends IStack<T> {
+ T getTop()
+
+ TStackBeneath pop()
+
+ INonEmptyStack<T, INonEmptyStack<T, TStackBeneath>> push(T x)
+ }
+
+ class EmptyStack<T> implements IEmptyStack<T> {
+ INonEmptyStack<T, IEmptyStack<T>> push(T x) {
+ new NonEmptyStack<T, IEmptyStack<T>>(x, this)
+ }
+ }
+
+ class NonEmptyStack<T, TStackBeneath extends IStack<T>>
+ implements INonEmptyStack<T, TStackBeneath> {
+ private final TStackBeneath stackBeneathTop;
+ private final T top
+
+ NonEmptyStack(T top, TStackBeneath stackBeneathTop) {
+ this.top = top
+ this.stackBeneathTop = stackBeneathTop
+ }
+
+ T getTop() {
+ top
+ }
+
+ TStackBeneath pop() {
+ stackBeneathTop
+ }
+
+ INonEmptyStack<T, INonEmptyStack<T, TStackBeneath>> push(T x) {
+ new NonEmptyStack<T, INonEmptyStack<T, TStackBeneath>>(x, this)
+ }
+ }
+
+ final IStack<Integer> stack = new EmptyStack<Integer>()
+
+ def oneInteger = stack.push(1)
+ assert oneInteger.getTop() == 1
+
+ def twoIntegers = stack.push(1).push(2)
+ assert twoIntegers.getTop() == 2
+
+ def oneIntegerAgain = stack.push(1).push(2).pop()
+ assert oneIntegerAgain.getTop() == 1 // BOOM!!!!
+ '''
+ }
+
static class MyList extends LinkedList<String> {}
public static class ClassA<T> {

0 comments on commit 5478bc3

Please sign in to comment.