langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
changeset 8242 3873b4aaf4a8
parent 8238 15ff254ff5c2
child 8427 703181b01773
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Feb 07 18:09:46 2011 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Feb 07 18:10:13 2011 +0000
@@ -1679,7 +1679,7 @@
                             "(" + types.memberType(t2, s2).getParameterTypes() + ")");
                         return s2;
                     }
-                } else if (!checkNameClash((ClassSymbol)site.tsym, s1, s2)) {
+                } else if (checkNameClash((ClassSymbol)site.tsym, s1, s2)) {
                     log.error(pos,
                             "name.clash.same.erasure.no.override",
                             s1, s1.location(),
@@ -1761,18 +1761,10 @@
     }
 
     private boolean checkNameClash(ClassSymbol origin, Symbol s1, Symbol s2) {
-        if (s1.kind == MTH &&
-                    s1.isInheritedIn(origin, types) &&
-                    (s1.flags() & SYNTHETIC) == 0 &&
-                    !s2.isConstructor()) {
-            Type er1 = s2.erasure(types);
-            Type er2 = s1.erasure(types);
-            if (types.isSameTypes(er1.getParameterTypes(),
-                    er2.getParameterTypes())) {
-                    return false;
-            }
-        }
-        return true;
+        ClashFilter cf = new ClashFilter(origin.type);
+        return (cf.accepts(s1) &&
+                cf.accepts(s2) &&
+                types.hasSameArgs(s1.erasure(types), s2.erasure(types)));
     }
 
 
@@ -2111,52 +2103,82 @@
      *  @param site The class whose methods are checked.
      *  @param sym  The method symbol to be checked.
      */
-    void checkClashes(DiagnosticPosition pos, Type site, Symbol sym) {
-        List<Type> supertypes = types.closure(site);
-        for (List<Type> l = supertypes; l.nonEmpty(); l = l.tail) {
-            for (List<Type> m = supertypes; m.nonEmpty(); m = m.tail) {
-                checkClashes(pos, l.head, m.head, site, sym);
+    void checkOverrideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) {
+         ClashFilter cf = new ClashFilter(site);
+         //for each method m1 that is a member of 'site'...
+         for (Scope.Entry e1 = types.membersClosure(site).lookup(sym.name, cf) ;
+                e1.scope != null ; e1 = e1.next(cf)) {
+            //...find another method m2 that is overridden (directly or indirectly)
+            //by method 'sym' in 'site'
+            for (Scope.Entry e2 = types.membersClosure(site).lookup(sym.name, cf) ;
+                    e2.scope != null ; e2 = e2.next(cf)) {
+                if (e1.sym == e2.sym || !sym.overrides(e2.sym, site.tsym, types, false)) continue;
+                //if (i) the signature of 'sym' is not a subsignature of m1 (seen as
+                //a member of 'site') and (ii) m1 has the same erasure as m2, issue an error
+                if (!types.isSubSignature(sym.type, types.memberType(site, e1.sym)) &&
+                        types.hasSameArgs(e1.sym.erasure(types), e2.sym.erasure(types))) {
+                    sym.flags_field |= CLASH;
+                    String key = e2.sym == sym ?
+                            "name.clash.same.erasure.no.override" :
+                            "name.clash.same.erasure.no.override.1";
+                    log.error(pos,
+                            key,
+                            sym, sym.location(),
+                            e1.sym, e1.sym.location(),
+                            e2.sym, e2.sym.location());
+                    return;
+                }
             }
         }
     }
 
-    /** Reports an error whenever 'sym' seen as a member of type 't1' clashes with
-     *  some unrelated method defined in 't2'.
+    /** Check that all static methods accessible from 'site' are
+     *  mutually compatible (JLS 8.4.8).
+     *
+     *  @param pos  Position to be used for error reporting.
+     *  @param site The class whose methods are checked.
+     *  @param sym  The method symbol to be checked.
      */
-    private void checkClashes(DiagnosticPosition pos, Type t1, Type t2, Type site, Symbol s1) {
+    void checkHideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) {
         ClashFilter cf = new ClashFilter(site);
-        s1 = ((MethodSymbol)s1).implementedIn(t1.tsym, types);
-        if (s1 == null) return;
-        Type st1 = types.memberType(site, s1);
-        for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name, cf); e2.scope != null; e2 = e2.next(cf)) {
-            Symbol s2 = e2.sym;
-            if (s1 == s2) continue;
-            Type st2 = types.memberType(site, s2);
-            if (!types.overrideEquivalent(st1, st2) &&
-                    !checkNameClash((ClassSymbol)site.tsym, s1, s2)) {
+        //for each method m1 that is a member of 'site'...
+        for (Scope.Entry e = types.membersClosure(site).lookup(sym.name, cf) ;
+                e.scope != null ; e = e.next(cf)) {
+            //if (i) the signature of 'sym' is not a subsignature of m1 (seen as
+            //a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error
+            if (!types.isSubSignature(sym.type, types.memberType(site, e.sym)) &&
+                    types.hasSameArgs(e.sym.erasure(types), sym.erasure(types))) {
                 log.error(pos,
-                        "name.clash.same.erasure.no.override",
-                        s1, s1.location(),
-                        s2, s2.location());
-            }
-        }
-    }
-    //where
-    private class ClashFilter implements Filter<Symbol> {
+                        "name.clash.same.erasure.no.hide",
+                        sym, sym.location(),
+                        e.sym, e.sym.location());
+                return;
+             }
+         }
+     }
 
-        Type site;
+     //where
+     private class ClashFilter implements Filter<Symbol> {
+
+         Type site;
 
-        ClashFilter(Type site) {
-            this.site = site;
-        }
+         ClashFilter(Type site) {
+             this.site = site;
+         }
+
+         boolean shouldSkip(Symbol s) {
+             return (s.flags() & CLASH) != 0 &&
+                s.owner == site.tsym;
+         }
 
-        public boolean accepts(Symbol s) {
-            return s.kind == MTH &&
-                    (s.flags() & (SYNTHETIC | CLASH)) == 0 &&
-                    s.isInheritedIn(site.tsym, types) &&
-                    !s.isConstructor();
-        }
-    }
+         public boolean accepts(Symbol s) {
+             return s.kind == MTH &&
+                     (s.flags() & SYNTHETIC) == 0 &&
+                     !shouldSkip(s) &&
+                     s.isInheritedIn(site.tsym, types) &&
+                     !s.isConstructor();
+         }
+     }
 
     /** Report a conflict between a user symbol and a synthetic symbol.
      */
@@ -2638,10 +2660,10 @@
         if (sym.owner.name == names.any) return false;
         for (Scope.Entry e = s.lookup(sym.name); e.scope == s; e = e.next()) {
             if (sym != e.sym &&
-                (e.sym.flags() & CLASH) == 0 &&
-                sym.kind == e.sym.kind &&
-                sym.name != names.error &&
-                (sym.kind != MTH || types.hasSameArgs(types.erasure(sym.type), types.erasure(e.sym.type)))) {
+                    (e.sym.flags() & CLASH) == 0 &&
+                    sym.kind == e.sym.kind &&
+                    sym.name != names.error &&
+                    (sym.kind != MTH || types.hasSameArgs(types.erasure(sym.type), types.erasure(e.sym.type)))) {
                 if ((sym.flags() & VARARGS) != (e.sym.flags() & VARARGS)) {
                     varargsDuplicateError(pos, sym, e.sym);
                     return true;
@@ -2667,13 +2689,13 @@
             return types.hasSameArgs(mt1.asMethodType(), mt2.asMethodType());
         }
 
-        /** Report duplicate declaration error.
-         */
-        void duplicateErasureError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) {
-            if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) {
-                log.error(pos, "name.clash.same.erasure", sym1, sym2);
-            }
+    /** Report duplicate declaration error.
+     */
+    void duplicateErasureError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) {
+        if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) {
+            log.error(pos, "name.clash.same.erasure", sym1, sym2);
         }
+    }
 
     /** Check that single-type import is not already imported or top-level defined,
      *  but make an exception for two single-type imports which denote the same type.