Thu, 09 Dec 2010 15:50:34 +0000
6476118: compiler bug causes runtime ClassCastException for generics overloading
Summary: compiler allows bridge methods to override unrelated method
Reviewed-by: jjg
1.1 --- a/src/share/classes/com/sun/tools/javac/code/Scope.java Thu Dec 09 15:50:10 2010 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Scope.java Thu Dec 09 15:50:34 2010 +0000 1.3 @@ -495,6 +495,11 @@ 1.4 return shadowed; 1.5 } 1.6 1.7 + public Entry next(Filter<Symbol> sf) { 1.8 + if (shadowed.sym == null || sf.accepts(shadowed.sym)) return shadowed; 1.9 + else return shadowed.next(sf); 1.10 + } 1.11 + 1.12 public Scope getOrigin() { 1.13 // The origin is only recorded for import scopes. For all 1.14 // other scope entries, the "enclosing" type is available
2.1 --- a/src/share/classes/com/sun/tools/javac/code/Symbol.java Thu Dec 09 15:50:10 2010 +0000 2.2 +++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java Thu Dec 09 15:50:34 2010 +0000 2.3 @@ -1103,18 +1103,24 @@ 2.4 impl == null && is.nonEmpty(); 2.5 is = is.tail) { 2.6 TypeSymbol i = is.head.tsym; 2.7 - for (Scope.Entry e = i.members().lookup(name); 2.8 - impl == null && e.scope != null; 2.9 - e = e.next()) { 2.10 - if (this.overrides(e.sym, (TypeSymbol)owner, types, true) && 2.11 - // FIXME: I suspect the following requires a 2.12 - // subst() for a parametric return type. 2.13 - types.isSameType(type.getReturnType(), 2.14 - types.memberType(owner.type, e.sym).getReturnType())) { 2.15 - impl = e.sym; 2.16 - } 2.17 - if (impl == null) 2.18 - impl = implemented(i, types); 2.19 + impl = implementedIn(i, types); 2.20 + if (impl == null) 2.21 + impl = implemented(i, types); 2.22 + } 2.23 + return impl; 2.24 + } 2.25 + 2.26 + public Symbol implementedIn(TypeSymbol c, Types types) { 2.27 + Symbol impl = null; 2.28 + for (Scope.Entry e = c.members().lookup(name); 2.29 + impl == null && e.scope != null; 2.30 + e = e.next()) { 2.31 + if (this.overrides(e.sym, (TypeSymbol)owner, types, true) && 2.32 + // FIXME: I suspect the following requires a 2.33 + // subst() for a parametric return type. 2.34 + types.isSameType(type.getReturnType(), 2.35 + types.memberType(owner.type, e.sym).getReturnType())) { 2.36 + impl = e.sym; 2.37 } 2.38 } 2.39 return impl;
3.1 --- a/src/share/classes/com/sun/tools/javac/code/Types.java Thu Dec 09 15:50:10 2010 +0000 3.2 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java Thu Dec 09 15:50:34 2010 +0000 3.3 @@ -2026,7 +2026,7 @@ 3.4 TypeSymbol c = t.tsym; 3.5 for (Scope.Entry e = c.members().lookup(ms.name, implFilter); 3.6 e.scope != null; 3.7 - e = e.next()) { 3.8 + e = e.next(implFilter)) { 3.9 if (e.sym != null && 3.10 e.sym.overrides(ms, origin, types, checkResult)) 3.11 return (MethodSymbol)e.sym;
4.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Dec 09 15:50:10 2010 +0000 4.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Dec 09 15:50:34 2010 +0000 4.3 @@ -676,6 +676,7 @@ 4.4 4.5 // If we override any other methods, check that we do so properly. 4.6 // JLS ??? 4.7 + chk.checkClashes(tree.pos(), env.enclClass.type, m); 4.8 chk.checkOverride(tree, m); 4.9 4.10 // Create a new environment with local scope
5.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Thu Dec 09 15:50:10 2010 +0000 5.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Thu Dec 09 15:50:34 2010 +0000 5.3 @@ -1668,12 +1668,6 @@ 5.4 checkOverride(tree, m, (MethodSymbol)e.sym, origin); 5.5 } 5.6 } 5.7 - else if (!checkNameClash(origin, e.sym, m)) { 5.8 - log.error(tree, 5.9 - "name.clash.same.erasure.no.override", 5.10 - m, m.location(), 5.11 - e.sym, e.sym.location()); 5.12 - } 5.13 e = e.next(); 5.14 } 5.15 } 5.16 @@ -2022,6 +2016,60 @@ 5.17 } 5.18 } 5.19 5.20 + /** Check that all non-override equivalent methods accessible from 'site' 5.21 + * are mutually compatible (JLS 8.4.8/9.4.1). 5.22 + * 5.23 + * @param pos Position to be used for error reporting. 5.24 + * @param site The class whose methods are checked. 5.25 + * @param sym The method symbol to be checked. 5.26 + */ 5.27 + void checkClashes(DiagnosticPosition pos, Type site, Symbol sym) { 5.28 + List<Type> supertypes = types.closure(site); 5.29 + for (List<Type> l = supertypes; l.nonEmpty(); l = l.tail) { 5.30 + for (List<Type> m = supertypes; m.nonEmpty(); m = m.tail) { 5.31 + checkClashes(pos, l.head, m.head, site, sym); 5.32 + } 5.33 + } 5.34 + } 5.35 + 5.36 + /** Reports an error whenever 'sym' seen as a member of type 't1' clashes with 5.37 + * some unrelated method defined in 't2'. 5.38 + */ 5.39 + private void checkClashes(DiagnosticPosition pos, Type t1, Type t2, Type site, Symbol s1) { 5.40 + ClashFilter cf = new ClashFilter(site); 5.41 + s1 = ((MethodSymbol)s1).implementedIn(t1.tsym, types); 5.42 + if (s1 == null) return; 5.43 + Type st1 = types.memberType(site, s1); 5.44 + for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name, cf); e2.scope != null; e2 = e2.next(cf)) { 5.45 + Symbol s2 = e2.sym; 5.46 + if (s1 == s2) continue; 5.47 + Type st2 = types.memberType(site, s2); 5.48 + if (!types.overrideEquivalent(st1, st2) && 5.49 + !checkNameClash((ClassSymbol)site.tsym, s1, s2)) { 5.50 + log.error(pos, 5.51 + "name.clash.same.erasure.no.override", 5.52 + s1, s1.location(), 5.53 + s2, s2.location()); 5.54 + } 5.55 + } 5.56 + } 5.57 + //where 5.58 + private class ClashFilter implements Filter<Symbol> { 5.59 + 5.60 + Type site; 5.61 + 5.62 + ClashFilter(Type site) { 5.63 + this.site = site; 5.64 + } 5.65 + 5.66 + public boolean accepts(Symbol s) { 5.67 + return s.kind == MTH && 5.68 + (s.flags() & SYNTHETIC) == 0 && 5.69 + s.isInheritedIn(site.tsym, types) && 5.70 + !s.isConstructor(); 5.71 + } 5.72 + } 5.73 + 5.74 /** Report a conflict between a user symbol and a synthetic symbol. 5.75 */ 5.76 private void syntheticError(DiagnosticPosition pos, Symbol sym) {
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/tools/javac/generics/6476118/T6476118a.java Thu Dec 09 15:50:34 2010 +0000 6.3 @@ -0,0 +1,16 @@ 6.4 +/** 6.5 + * @test /nodynamiccopyright/ 6.6 + * @bug 6476118 6.7 + * @summary compiler bug causes runtime ClassCastException for generics overloading 6.8 + * @compile/fail/ref=T6476118a.out -XDrawDiagnostics T6476118a.java 6.9 + */ 6.10 + 6.11 +class T6476118a { 6.12 + static class A { 6.13 + public int compareTo(Object o) { return 0; } 6.14 + } 6.15 + 6.16 + static class B extends A implements Comparable<B>{ 6.17 + public int compareTo(B b){ return 0; } 6.18 + } 6.19 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/test/tools/javac/generics/6476118/T6476118a.out Thu Dec 09 15:50:34 2010 +0000 7.3 @@ -0,0 +1,2 @@ 7.4 +T6476118a.java:14:20: compiler.err.name.clash.same.erasure.no.override: compareTo(T), java.lang.Comparable, compareTo(java.lang.Object), T6476118a.A 7.5 +1 error
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/test/tools/javac/generics/6476118/T6476118b.java Thu Dec 09 15:50:34 2010 +0000 8.3 @@ -0,0 +1,14 @@ 8.4 +/** 8.5 + * @test /nodynamiccopyright/ 8.6 + * @bug 6476118 6533652 8.7 + * @summary compiler bug causes runtime ClassCastException for generics overloading 8.8 + * @compile/fail/ref=T6476118b.out -XDrawDiagnostics T6476118b.java 8.9 + */ 8.10 + 8.11 +class T6476118b { 8.12 + public final int compareTo(Object o) { return 0; } 8.13 + 8.14 + static class B extends T6476118b implements Comparable<B> { 8.15 + public int compareTo(B b){ return 0; } 8.16 + } 8.17 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/test/tools/javac/generics/6476118/T6476118b.out Thu Dec 09 15:50:34 2010 +0000 9.3 @@ -0,0 +1,2 @@ 9.4 +T6476118b.java:12:20: compiler.err.name.clash.same.erasure.no.override: compareTo(T), java.lang.Comparable, compareTo(java.lang.Object), T6476118b 9.5 +1 error
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/test/tools/javac/generics/6476118/T6476118c.java Thu Dec 09 15:50:34 2010 +0000 10.3 @@ -0,0 +1,23 @@ 10.4 +/** 10.5 + * @test /nodynamiccopyright/ 10.6 + * @bug 6476118 10.7 + * @summary compiler bug causes runtime ClassCastException for generics overloading 10.8 + * @compile/fail/ref=T6476118c.out -XDrawDiagnostics T6476118c.java 10.9 + */ 10.10 + 10.11 +class T6476118b { 10.12 + static class A<T> { 10.13 + public void foo(T t) { } 10.14 + } 10.15 + 10.16 + static class B<T extends Number> extends A<T> { 10.17 + public void foo(T t) { } 10.18 + } 10.19 + 10.20 + static class C extends B<Integer> { 10.21 + public void foo(Object o) { } 10.22 + public void foo(Number o) { } 10.23 + } 10.24 + 10.25 + static class D extends C {} //check that no spurious diags generated here! 10.26 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/test/tools/javac/generics/6476118/T6476118c.out Thu Dec 09 15:50:34 2010 +0000 11.3 @@ -0,0 +1,3 @@ 11.4 +T6476118c.java:18:21: compiler.err.name.clash.same.erasure.no.override: foo(java.lang.Object), T6476118b.C, foo(T), T6476118b.A 11.5 +T6476118c.java:19:21: compiler.err.name.clash.same.erasure.no.override: foo(java.lang.Number), T6476118b.C, foo(T), T6476118b.B 11.6 +2 errors
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/test/tools/javac/generics/6476118/T6476118d.java Thu Dec 09 15:50:34 2010 +0000 12.3 @@ -0,0 +1,39 @@ 12.4 +/* 12.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 12.7 + * 12.8 + * This code is free software; you can redistribute it and/or modify it 12.9 + * under the terms of the GNU General Public License version 2 only, as 12.10 + * published by the Free Software Foundation. 12.11 + * 12.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 12.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12.15 + * version 2 for more details (a copy is included in the LICENSE file that 12.16 + * accompanied this code). 12.17 + * 12.18 + * You should have received a copy of the GNU General Public License version 12.19 + * 2 along with this work; if not, write to the Free Software Foundation, 12.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 12.21 + * 12.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 12.23 + * or visit www.oracle.com if you need additional information or have any 12.24 + * questions. 12.25 + */ 12.26 + 12.27 +/* 12.28 + * @test 12.29 + * @bug 6476118 12.30 + * @summary compiler bug causes runtime ClassCastException for generics overloading 12.31 + * @compile T6476118d.java 12.32 + */ 12.33 + 12.34 +class T6476118d { 12.35 + int m = 3; 12.36 + 12.37 + interface m { } 12.38 + 12.39 + int m () { 12.40 + return m; 12.41 + } 12.42 +}