6476118: compiler bug causes runtime ClassCastException for generics overloading

Thu, 09 Dec 2010 15:50:34 +0000

author
mcimadamore
date
Thu, 09 Dec 2010 15:50:34 +0000
changeset 780
1d625fbe6c22
parent 779
5ef88773462b
child 781
e3df8d7a9752

6476118: compiler bug causes runtime ClassCastException for generics overloading
Summary: compiler allows bridge methods to override unrelated method
Reviewed-by: jjg

src/share/classes/com/sun/tools/javac/code/Scope.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/code/Symbol.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/code/Types.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/Attr.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/Check.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/6476118/T6476118a.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/6476118/T6476118a.out file | annotate | diff | comparison | revisions
test/tools/javac/generics/6476118/T6476118b.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/6476118/T6476118b.out file | annotate | diff | comparison | revisions
test/tools/javac/generics/6476118/T6476118c.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/6476118/T6476118c.out file | annotate | diff | comparison | revisions
test/tools/javac/generics/6476118/T6476118d.java file | annotate | diff | comparison | revisions
     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 +}

mercurial