You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2015/11/03 19:05:54 UTC

incubator-groovy git commit: GROOVY-7363: Frequent compilation error on cascading generic types (closes #158)

Repository: incubator-groovy
Updated Branches:
  refs/heads/master de31d0456 -> 4c4ead4ac


GROOVY-7363: Frequent compilation error on cascading generic types (closes #158)

Reliable type resolution in the static type checker with covariant getters

Prefer a non-bridge getter method

Preferring a non-bridge getter over a bridge one ensures that the type
resolution of expressions in the static type checker always uses the
covariant return type of getters (due to generics, for example) and doesn't
lose accuracy, resulting in spurious type checking errors.

It's worth noting that the check is actually whether the method is synthetic
or not, because MethodNode doesn't keep the bridge flag, but that should be
good enough.


Project: http://git-wip-us.apache.org/repos/asf/incubator-groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-groovy/commit/4c4ead4a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-groovy/tree/4c4ead4a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-groovy/diff/4c4ead4a

Branch: refs/heads/master
Commit: 4c4ead4acd52dea0fe669d34e8eb93ce1ea763af
Parents: de31d04
Author: Frank Pavageau <fp...@ekino.com>
Authored: Mon Aug 3 15:04:37 2015 +0200
Committer: pascalschumacher <pa...@gmx.net>
Committed: Tue Nov 3 19:02:42 2015 +0100

----------------------------------------------------------------------
 src/main/org/codehaus/groovy/ast/ClassNode.java | 10 +++-
 .../classgen/asm/sc/bugs/Groovy7363Bug.groovy   | 28 ++++++++++++
 .../asm/sc/bugs/support/Groovy7363Support.java  | 48 ++++++++++++++++++++
 3 files changed, 85 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-groovy/blob/4c4ead4a/src/main/org/codehaus/groovy/ast/ClassNode.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/ast/ClassNode.java b/src/main/org/codehaus/groovy/ast/ClassNode.java
index 8485157..bf045d8 100644
--- a/src/main/org/codehaus/groovy/ast/ClassNode.java
+++ b/src/main/org/codehaus/groovy/ast/ClassNode.java
@@ -1096,13 +1096,21 @@ public class ClassNode extends AnnotatedNode implements Opcodes {
     }
 
     public MethodNode getGetterMethod(String getterName) {
+        MethodNode getterMethod = null;
         for (MethodNode method : getDeclaredMethods(getterName)) {
             if (getterName.equals(method.getName())
                     && ClassHelper.VOID_TYPE!=method.getReturnType()
                     && method.getParameters().length == 0) {
-                return method;
+                // GROOVY-7363: There can be multiple matches for a getter returning a generic parameter type, due to
+                // the generation of a bridge method. The real getter is really the non-bridge, non-synthetic one as it
+                // has the most specific and exact return type of the two. Picking the bridge method results in loss of
+                // type information, as it down-casts the return type to the lower bound of the generic parameter.
+                if (getterMethod == null || getterMethod.isSynthetic()) {
+                    getterMethod = method;
+                }
             }
         }
+        if (getterMethod != null) return getterMethod;
         ClassNode parent = getSuperClass();
         if (parent!=null) return parent.getGetterMethod(getterName);
         return null;

http://git-wip-us.apache.org/repos/asf/incubator-groovy/blob/4c4ead4a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7363Bug.groovy
----------------------------------------------------------------------
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7363Bug.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7363Bug.groovy
new file mode 100644
index 0000000..b1f23c1
--- /dev/null
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7363Bug.groovy
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2003-2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.codehaus.groovy.classgen.asm.sc.bugs
+
+import groovy.transform.stc.StaticTypeCheckingTestCase
+import org.codehaus.groovy.classgen.asm.sc.StaticCompilationTestSupport
+
+class Groovy7363Bug extends StaticTypeCheckingTestCase implements StaticCompilationTestSupport {
+    void testCascadingGenericTypes() {
+        assertScript """import org.codehaus.groovy.classgen.asm.sc.bugs.support.Groovy7363Support
+            Groovy7363Support.ABC a = new Groovy7363Support.ABC()
+            assert ('' + a.b.object.value) == '42'
+        """
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-groovy/blob/4c4ead4a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/support/Groovy7363Support.java
----------------------------------------------------------------------
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/support/Groovy7363Support.java b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/support/Groovy7363Support.java
new file mode 100644
index 0000000..44e4d6a
--- /dev/null
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/support/Groovy7363Support.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2003-2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.codehaus.groovy.classgen.asm.sc.bugs.support;
+
+public class Groovy7363Support {
+    public interface A<T, U extends B<T>> {
+        U getB();
+    }
+
+    public static class ABC implements A<C, BC> {
+        public void setB(BC b) {}
+
+        @Override
+        public BC getB() {
+            return new BC();
+        }
+    }
+
+    public interface B<T> {
+        T getObject();
+    }
+
+    public static class BC implements B<C> {
+        @Override
+        public C getObject() {
+            return new C();
+        }
+    }
+
+    public static class C {
+        public long getValue() {
+            return 42;
+        }
+    }
+}