Repository: groovy Updated Branches: refs/heads/master 26fc4e0f2 -> 34df6cf46
GROOVY-7721: Static type checking fails when compiling against a Java interface call (closes #599) Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/34df6cf4 Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/34df6cf4 Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/34df6cf4 Branch: refs/heads/master Commit: 34df6cf461a5ecce66f2c2c0f14489cf96feaf34 Parents: 26fc4e0 Author: sunlan <sun...@apache.org> Authored: Wed Sep 13 20:20:11 2017 +0800 Committer: sunlan <sun...@apache.org> Committed: Wed Sep 13 20:20:11 2017 +0800 ---------------------------------------------------------------------- .../stc/StaticTypeCheckingSupport.java | 11 ++- src/test/groovy/bugs/Groovy7721Bug.groovy | 80 ++++++++++++++++++++ 2 files changed, 89 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/groovy/blob/34df6cf4/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java ---------------------------------------------------------------------- diff --git a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java index 98fb157..eb208fe 100644 --- a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java +++ b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java @@ -1149,13 +1149,20 @@ public abstract class StaticTypeCheckingSupport { private static void removeMethodWithSuperReturnType(List<MethodNode> toBeRemoved, MethodNode one, MethodNode two) { ClassNode oneRT = one.getReturnType(); ClassNode twoRT = two.getReturnType(); - if (oneRT.isDerivedFrom(twoRT) || oneRT.implementsInterface(twoRT)) { + if (isCovariant(oneRT, twoRT)) { toBeRemoved.add(two); - } else if (twoRT.isDerivedFrom(oneRT) || twoRT.implementsInterface(oneRT)) { + } else if (isCovariant(twoRT, oneRT)) { toBeRemoved.add(one); } } + private static boolean isCovariant(ClassNode left, ClassNode right) { + if (left.isArray() && right.isArray()) { + return isCovariant(left.getComponentType(), right.getComponentType()); + } + return left.isDerivedFrom(right) || left.implementsInterface(right); + } + private static boolean areOverloadMethodsInSameClass(MethodNode one, MethodNode two) { return one.getName().equals(two.getName()) && one.getDeclaringClass() == two.getDeclaringClass(); } http://git-wip-us.apache.org/repos/asf/groovy/blob/34df6cf4/src/test/groovy/bugs/Groovy7721Bug.groovy ---------------------------------------------------------------------- diff --git a/src/test/groovy/bugs/Groovy7721Bug.groovy b/src/test/groovy/bugs/Groovy7721Bug.groovy new file mode 100644 index 0000000..f316a2a --- /dev/null +++ b/src/test/groovy/bugs/Groovy7721Bug.groovy @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 groovy.bugs + +import org.codehaus.groovy.control.CompilerConfiguration +import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit + +class Groovy7721Bug extends GroovyTestCase { + void testCovariantArrayAtOverriding() { + def config = new CompilerConfiguration() + config.with { + targetDirectory = createTempDir() + jointCompilationOptions = [stubDir: createTempDir()] + } + + File parentDir = createTempDir() + try { + def a = new File(parentDir, 'A.java') + a.write ''' + package pack; + interface A { + Object[] bar(); + } + + ''' + def b = new File(parentDir, 'B.java') + b.write ''' + package pack; + interface B extends A { + @Override + String[] bar(); + } + ''' + + def c = new File(parentDir, 'C.groovy') + c.write ''' + import groovy.transform.CompileStatic + + @CompileStatic + class C { + static def bar(pack.B b) { + b.bar() + } + } + ''' + def loader = new GroovyClassLoader(this.class.classLoader) + def cu = new JavaAwareCompilationUnit(config, loader) + cu.addSources([a, b, c] as File[]) + cu.compile() + } finally { + parentDir.deleteDir() + config.targetDirectory?.deleteDir() + config.jointCompilationOptions.stubDir?.deleteDir() + } + + } + + private static File createTempDir() { + File.createTempDir("groovyTest${System.currentTimeMillis()}", "") + } + +}