1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Mon Sep 24 14:04:34 2012 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Tue Sep 25 11:52:37 2012 +0100 1.3 @@ -40,6 +40,7 @@ 1.4 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 1.5 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; 1.6 1.7 +import java.util.ArrayList; 1.8 import java.util.Arrays; 1.9 import java.util.Collection; 1.10 import java.util.EnumMap; 1.11 @@ -57,6 +58,7 @@ 1.12 import static com.sun.tools.javac.code.TypeTags.*; 1.13 import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*; 1.14 import static com.sun.tools.javac.tree.JCTree.Tag.*; 1.15 +import java.util.Iterator; 1.16 1.17 /** Helper class for name resolution, used mostly by the attribution phase. 1.18 * 1.19 @@ -1035,8 +1037,8 @@ 1.20 return this; 1.21 else 1.22 return super.implementation(origin, types, checkResult); 1.23 - } 1.24 - }; 1.25 + } 1.26 + }; 1.27 return result; 1.28 } 1.29 if (m1SignatureMoreSpecific) return m1; 1.30 @@ -1160,12 +1162,10 @@ 1.31 argtypes, 1.32 typeargtypes, 1.33 site.tsym.type, 1.34 - true, 1.35 bestSoFar, 1.36 allowBoxing, 1.37 useVarargs, 1.38 - operator, 1.39 - new HashSet<TypeSymbol>()); 1.40 + operator); 1.41 reportVerboseResolutionDiagnostic(env.tree.pos(), name, site, argtypes, typeargtypes, bestSoFar); 1.42 return bestSoFar; 1.43 } 1.44 @@ -1176,56 +1176,137 @@ 1.45 List<Type> argtypes, 1.46 List<Type> typeargtypes, 1.47 Type intype, 1.48 - boolean abstractok, 1.49 Symbol bestSoFar, 1.50 boolean allowBoxing, 1.51 boolean useVarargs, 1.52 - boolean operator, 1.53 - Set<TypeSymbol> seen) { 1.54 - for (Type ct = intype; ct.tag == CLASS || ct.tag == TYPEVAR; ct = types.supertype(ct)) { 1.55 - while (ct.tag == TYPEVAR) 1.56 - ct = ct.getUpperBound(); 1.57 - ClassSymbol c = (ClassSymbol)ct.tsym; 1.58 - if (!seen.add(c)) return bestSoFar; 1.59 - if ((c.flags() & (ABSTRACT | INTERFACE | ENUM)) == 0) 1.60 - abstractok = false; 1.61 - for (Scope.Entry e = c.members().lookup(name); 1.62 - e.scope != null; 1.63 - e = e.next()) { 1.64 - //- System.out.println(" e " + e.sym); 1.65 - if (e.sym.kind == MTH && 1.66 - (e.sym.flags_field & SYNTHETIC) == 0) { 1.67 - bestSoFar = selectBest(env, site, argtypes, typeargtypes, 1.68 - e.sym, bestSoFar, 1.69 - allowBoxing, 1.70 - useVarargs, 1.71 - operator); 1.72 + boolean operator) { 1.73 + boolean abstractOk = true; 1.74 + List<Type> itypes = List.nil(); 1.75 + for (TypeSymbol s : superclasses(intype)) { 1.76 + bestSoFar = lookupMethod(env, site, name, argtypes, typeargtypes, 1.77 + s.members(), bestSoFar, allowBoxing, useVarargs, operator, true); 1.78 + abstractOk &= excludeAbstractsFilter.accepts(s); 1.79 + if (abstractOk) { 1.80 + for (Type itype : types.interfaces(s.type)) { 1.81 + itypes = types.union(types.closure(itype), itypes); 1.82 } 1.83 } 1.84 - if (name == names.init) 1.85 - break; 1.86 - //- System.out.println(" - " + bestSoFar); 1.87 - if (abstractok) { 1.88 - Symbol concrete = methodNotFound; 1.89 - if ((bestSoFar.flags() & ABSTRACT) == 0) 1.90 - concrete = bestSoFar; 1.91 - for (List<Type> l = types.interfaces(c.type); 1.92 - l.nonEmpty(); 1.93 - l = l.tail) { 1.94 - bestSoFar = findMethod(env, site, name, argtypes, 1.95 - typeargtypes, 1.96 - l.head, abstractok, bestSoFar, 1.97 - allowBoxing, useVarargs, operator, seen); 1.98 - } 1.99 - if (concrete != bestSoFar && 1.100 - concrete.kind < ERR && bestSoFar.kind < ERR && 1.101 - types.isSubSignature(concrete.type, bestSoFar.type)) 1.102 - bestSoFar = concrete; 1.103 + if (name == names.init) break; 1.104 + } 1.105 + 1.106 + Symbol concrete = bestSoFar.kind < ERR && 1.107 + (bestSoFar.flags() & ABSTRACT) == 0 ? 1.108 + bestSoFar : methodNotFound; 1.109 + 1.110 + if (name != names.init) { 1.111 + //keep searching for abstract methods 1.112 + for (Type itype : itypes) { 1.113 + if (!itype.isInterface()) continue; //skip j.l.Object (included by Types.closure()) 1.114 + bestSoFar = lookupMethod(env, site, name, argtypes, typeargtypes, 1.115 + itype.tsym.members(), bestSoFar, allowBoxing, useVarargs, operator, true); 1.116 + if (concrete != bestSoFar && 1.117 + concrete.kind < ERR && bestSoFar.kind < ERR && 1.118 + types.isSubSignature(concrete.type, bestSoFar.type)) { 1.119 + //this is an hack - as javac does not do full membership checks 1.120 + //most specific ends up comparing abstract methods that might have 1.121 + //been implemented by some concrete method in a subclass and, 1.122 + //because of raw override, it is possible for an abstract method 1.123 + //to be more specific than the concrete method - so we need 1.124 + //to explicitly call that out (see CR 6178365) 1.125 + bestSoFar = concrete; 1.126 + } 1.127 } 1.128 } 1.129 return bestSoFar; 1.130 } 1.131 1.132 + /** 1.133 + * Return an Iterable object to scan the superclasses of a given type. 1.134 + * It's crucial that the scan is done lazily, as we don't want to accidentally 1.135 + * access more supertypes than strictly needed (as this could trigger completion 1.136 + * errors if some of the not-needed supertypes are missing/ill-formed). 1.137 + */ 1.138 + Iterable<TypeSymbol> superclasses(final Type intype) { 1.139 + return new Iterable<TypeSymbol>() { 1.140 + public Iterator<TypeSymbol> iterator() { 1.141 + return new Iterator<TypeSymbol>() { 1.142 + 1.143 + List<TypeSymbol> seen = List.nil(); 1.144 + TypeSymbol currentSym = getSymbol(intype); 1.145 + 1.146 + public boolean hasNext() { 1.147 + return currentSym != null; 1.148 + } 1.149 + 1.150 + public TypeSymbol next() { 1.151 + TypeSymbol prevSym = currentSym; 1.152 + currentSym = getSymbol(types.supertype(currentSym.type)); 1.153 + return prevSym; 1.154 + } 1.155 + 1.156 + public void remove() { 1.157 + throw new UnsupportedOperationException("Not supported yet."); 1.158 + } 1.159 + 1.160 + TypeSymbol getSymbol(Type intype) { 1.161 + if (intype.tag != CLASS && 1.162 + intype.tag != TYPEVAR) { 1.163 + return null; 1.164 + } 1.165 + while (intype.tag == TYPEVAR) 1.166 + intype = intype.getUpperBound(); 1.167 + if (seen.contains(intype.tsym)) { 1.168 + //degenerate case in which we have a circular 1.169 + //class hierarchy - because of ill-formed classfiles 1.170 + return null; 1.171 + } 1.172 + seen = seen.prepend(intype.tsym); 1.173 + return intype.tsym; 1.174 + } 1.175 + }; 1.176 + } 1.177 + }; 1.178 + } 1.179 + 1.180 + /** 1.181 + * We should not look for abstract methods if receiver is a concrete class 1.182 + * (as concrete classes are expected to implement all abstracts coming 1.183 + * from superinterfaces) 1.184 + */ 1.185 + Filter<Symbol> excludeAbstractsFilter = new Filter<Symbol>() { 1.186 + public boolean accepts(Symbol s) { 1.187 + return (s.flags() & (ABSTRACT | INTERFACE | ENUM)) != 0; 1.188 + } 1.189 + }; 1.190 + 1.191 + /** 1.192 + * Lookup a method with given name and argument types in a given scope 1.193 + */ 1.194 + Symbol lookupMethod(Env<AttrContext> env, 1.195 + Type site, 1.196 + Name name, 1.197 + List<Type> argtypes, 1.198 + List<Type> typeargtypes, 1.199 + Scope sc, 1.200 + Symbol bestSoFar, 1.201 + boolean allowBoxing, 1.202 + boolean useVarargs, 1.203 + boolean operator, 1.204 + boolean abstractok) { 1.205 + for (Symbol s : sc.getElementsByName(name, lookupFilter)) { 1.206 + bestSoFar = selectBest(env, site, argtypes, typeargtypes, s, 1.207 + bestSoFar, allowBoxing, useVarargs, operator); 1.208 + } 1.209 + return bestSoFar; 1.210 + } 1.211 + //where 1.212 + Filter<Symbol> lookupFilter = new Filter<Symbol>() { 1.213 + public boolean accepts(Symbol s) { 1.214 + return s.kind == MTH && 1.215 + (s.flags() & SYNTHETIC) == 0; 1.216 + } 1.217 + }; 1.218 + 1.219 /** Find unqualified method matching given name, type and value arguments. 1.220 * @param env The current environment. 1.221 * @param name The method's name.