2109 * |
2101 * |
2110 * @param pos Position to be used for error reporting. |
2102 * @param pos Position to be used for error reporting. |
2111 * @param site The class whose methods are checked. |
2103 * @param site The class whose methods are checked. |
2112 * @param sym The method symbol to be checked. |
2104 * @param sym The method symbol to be checked. |
2113 */ |
2105 */ |
2114 void checkClashes(DiagnosticPosition pos, Type site, Symbol sym) { |
2106 void checkOverrideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) { |
2115 List<Type> supertypes = types.closure(site); |
2107 ClashFilter cf = new ClashFilter(site); |
2116 for (List<Type> l = supertypes; l.nonEmpty(); l = l.tail) { |
2108 //for each method m1 that is a member of 'site'... |
2117 for (List<Type> m = supertypes; m.nonEmpty(); m = m.tail) { |
2109 for (Scope.Entry e1 = types.membersClosure(site).lookup(sym.name, cf) ; |
2118 checkClashes(pos, l.head, m.head, site, sym); |
2110 e1.scope != null ; e1 = e1.next(cf)) { |
2119 } |
2111 //...find another method m2 that is overridden (directly or indirectly) |
2120 } |
2112 //by method 'sym' in 'site' |
2121 } |
2113 for (Scope.Entry e2 = types.membersClosure(site).lookup(sym.name, cf) ; |
2122 |
2114 e2.scope != null ; e2 = e2.next(cf)) { |
2123 /** Reports an error whenever 'sym' seen as a member of type 't1' clashes with |
2115 if (e1.sym == e2.sym || !sym.overrides(e2.sym, site.tsym, types, false)) continue; |
2124 * some unrelated method defined in 't2'. |
2116 //if (i) the signature of 'sym' is not a subsignature of m1 (seen as |
2125 */ |
2117 //a member of 'site') and (ii) m1 has the same erasure as m2, issue an error |
2126 private void checkClashes(DiagnosticPosition pos, Type t1, Type t2, Type site, Symbol s1) { |
2118 if (!types.isSubSignature(sym.type, types.memberType(site, e1.sym)) && |
|
2119 types.hasSameArgs(e1.sym.erasure(types), e2.sym.erasure(types))) { |
|
2120 sym.flags_field |= CLASH; |
|
2121 String key = e2.sym == sym ? |
|
2122 "name.clash.same.erasure.no.override" : |
|
2123 "name.clash.same.erasure.no.override.1"; |
|
2124 log.error(pos, |
|
2125 key, |
|
2126 sym, sym.location(), |
|
2127 e1.sym, e1.sym.location(), |
|
2128 e2.sym, e2.sym.location()); |
|
2129 return; |
|
2130 } |
|
2131 } |
|
2132 } |
|
2133 } |
|
2134 |
|
2135 /** Check that all static methods accessible from 'site' are |
|
2136 * mutually compatible (JLS 8.4.8). |
|
2137 * |
|
2138 * @param pos Position to be used for error reporting. |
|
2139 * @param site The class whose methods are checked. |
|
2140 * @param sym The method symbol to be checked. |
|
2141 */ |
|
2142 void checkHideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) { |
2127 ClashFilter cf = new ClashFilter(site); |
2143 ClashFilter cf = new ClashFilter(site); |
2128 s1 = ((MethodSymbol)s1).implementedIn(t1.tsym, types); |
2144 //for each method m1 that is a member of 'site'... |
2129 if (s1 == null) return; |
2145 for (Scope.Entry e = types.membersClosure(site).lookup(sym.name, cf) ; |
2130 Type st1 = types.memberType(site, s1); |
2146 e.scope != null ; e = e.next(cf)) { |
2131 for (Scope.Entry e2 = t2.tsym.members().lookup(s1.name, cf); e2.scope != null; e2 = e2.next(cf)) { |
2147 //if (i) the signature of 'sym' is not a subsignature of m1 (seen as |
2132 Symbol s2 = e2.sym; |
2148 //a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error |
2133 if (s1 == s2) continue; |
2149 if (!types.isSubSignature(sym.type, types.memberType(site, e.sym)) && |
2134 Type st2 = types.memberType(site, s2); |
2150 types.hasSameArgs(e.sym.erasure(types), sym.erasure(types))) { |
2135 if (!types.overrideEquivalent(st1, st2) && |
|
2136 !checkNameClash((ClassSymbol)site.tsym, s1, s2)) { |
|
2137 log.error(pos, |
2151 log.error(pos, |
2138 "name.clash.same.erasure.no.override", |
2152 "name.clash.same.erasure.no.hide", |
2139 s1, s1.location(), |
2153 sym, sym.location(), |
2140 s2, s2.location()); |
2154 e.sym, e.sym.location()); |
2141 } |
2155 return; |
2142 } |
2156 } |
2143 } |
2157 } |
2144 //where |
2158 } |
2145 private class ClashFilter implements Filter<Symbol> { |
2159 |
2146 |
2160 //where |
2147 Type site; |
2161 private class ClashFilter implements Filter<Symbol> { |
2148 |
2162 |
2149 ClashFilter(Type site) { |
2163 Type site; |
2150 this.site = site; |
2164 |
2151 } |
2165 ClashFilter(Type site) { |
2152 |
2166 this.site = site; |
2153 public boolean accepts(Symbol s) { |
2167 } |
2154 return s.kind == MTH && |
2168 |
2155 (s.flags() & (SYNTHETIC | CLASH)) == 0 && |
2169 boolean shouldSkip(Symbol s) { |
2156 s.isInheritedIn(site.tsym, types) && |
2170 return (s.flags() & CLASH) != 0 && |
2157 !s.isConstructor(); |
2171 s.owner == site.tsym; |
2158 } |
2172 } |
2159 } |
2173 |
|
2174 public boolean accepts(Symbol s) { |
|
2175 return s.kind == MTH && |
|
2176 (s.flags() & SYNTHETIC) == 0 && |
|
2177 !shouldSkip(s) && |
|
2178 s.isInheritedIn(site.tsym, types) && |
|
2179 !s.isConstructor(); |
|
2180 } |
|
2181 } |
2160 |
2182 |
2161 /** Report a conflict between a user symbol and a synthetic symbol. |
2183 /** Report a conflict between a user symbol and a synthetic symbol. |
2162 */ |
2184 */ |
2163 private void syntheticError(DiagnosticPosition pos, Symbol sym) { |
2185 private void syntheticError(DiagnosticPosition pos, Symbol sym) { |
2164 if (!sym.type.isErroneous()) { |
2186 if (!sym.type.isErroneous()) { |
2636 if (sym.type.isErroneous()) |
2658 if (sym.type.isErroneous()) |
2637 return true; |
2659 return true; |
2638 if (sym.owner.name == names.any) return false; |
2660 if (sym.owner.name == names.any) return false; |
2639 for (Scope.Entry e = s.lookup(sym.name); e.scope == s; e = e.next()) { |
2661 for (Scope.Entry e = s.lookup(sym.name); e.scope == s; e = e.next()) { |
2640 if (sym != e.sym && |
2662 if (sym != e.sym && |
2641 (e.sym.flags() & CLASH) == 0 && |
2663 (e.sym.flags() & CLASH) == 0 && |
2642 sym.kind == e.sym.kind && |
2664 sym.kind == e.sym.kind && |
2643 sym.name != names.error && |
2665 sym.name != names.error && |
2644 (sym.kind != MTH || types.hasSameArgs(types.erasure(sym.type), types.erasure(e.sym.type)))) { |
2666 (sym.kind != MTH || types.hasSameArgs(types.erasure(sym.type), types.erasure(e.sym.type)))) { |
2645 if ((sym.flags() & VARARGS) != (e.sym.flags() & VARARGS)) { |
2667 if ((sym.flags() & VARARGS) != (e.sym.flags() & VARARGS)) { |
2646 varargsDuplicateError(pos, sym, e.sym); |
2668 varargsDuplicateError(pos, sym, e.sym); |
2647 return true; |
2669 return true; |
2648 } else if (sym.kind == MTH && !hasSameSignature(sym.type, e.sym.type)) { |
2670 } else if (sym.kind == MTH && !hasSameSignature(sym.type, e.sym.type)) { |
2649 duplicateErasureError(pos, sym, e.sym); |
2671 duplicateErasureError(pos, sym, e.sym); |
2665 mt2 = types.subst(fa2, fa2.tvars, fa1.tvars); |
2687 mt2 = types.subst(fa2, fa2.tvars, fa1.tvars); |
2666 } |
2688 } |
2667 return types.hasSameArgs(mt1.asMethodType(), mt2.asMethodType()); |
2689 return types.hasSameArgs(mt1.asMethodType(), mt2.asMethodType()); |
2668 } |
2690 } |
2669 |
2691 |
2670 /** Report duplicate declaration error. |
2692 /** Report duplicate declaration error. |
2671 */ |
2693 */ |
2672 void duplicateErasureError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) { |
2694 void duplicateErasureError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) { |
2673 if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) { |
2695 if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) { |
2674 log.error(pos, "name.clash.same.erasure", sym1, sym2); |
2696 log.error(pos, "name.clash.same.erasure", sym1, sym2); |
2675 } |
2697 } |
2676 } |
2698 } |
2677 |
2699 |
2678 /** Check that single-type import is not already imported or top-level defined, |
2700 /** Check that single-type import is not already imported or top-level defined, |
2679 * but make an exception for two single-type imports which denote the same type. |
2701 * but make an exception for two single-type imports which denote the same type. |
2680 * @param pos Position for error reporting. |
2702 * @param pos Position for error reporting. |
2681 * @param sym The symbol. |
2703 * @param sym The symbol. |