1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Tue Feb 28 18:04:50 2012 -0800 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Mar 02 12:57:04 2012 +0000 1.3 @@ -29,6 +29,7 @@ 1.4 import com.sun.tools.javac.code.*; 1.5 import com.sun.tools.javac.code.Type.*; 1.6 import com.sun.tools.javac.code.Symbol.*; 1.7 +import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate; 1.8 import com.sun.tools.javac.jvm.*; 1.9 import com.sun.tools.javac.tree.*; 1.10 import com.sun.tools.javac.tree.JCTree.*; 1.11 @@ -39,10 +40,9 @@ 1.12 1.13 import java.util.Arrays; 1.14 import java.util.Collection; 1.15 +import java.util.EnumMap; 1.16 import java.util.EnumSet; 1.17 -import java.util.HashMap; 1.18 import java.util.HashSet; 1.19 -import java.util.LinkedHashMap; 1.20 import java.util.Map; 1.21 import java.util.Set; 1.22 1.23 @@ -84,6 +84,58 @@ 1.24 1.25 Scope polymorphicSignatureScope; 1.26 1.27 + protected Resolve(Context context) { 1.28 + context.put(resolveKey, this); 1.29 + syms = Symtab.instance(context); 1.30 + 1.31 + varNotFound = new 1.32 + SymbolNotFoundError(ABSENT_VAR); 1.33 + wrongMethod = new 1.34 + InapplicableSymbolError(); 1.35 + wrongMethods = new 1.36 + InapplicableSymbolsError(); 1.37 + methodNotFound = new 1.38 + SymbolNotFoundError(ABSENT_MTH); 1.39 + typeNotFound = new 1.40 + SymbolNotFoundError(ABSENT_TYP); 1.41 + 1.42 + names = Names.instance(context); 1.43 + log = Log.instance(context); 1.44 + chk = Check.instance(context); 1.45 + infer = Infer.instance(context); 1.46 + reader = ClassReader.instance(context); 1.47 + treeinfo = TreeInfo.instance(context); 1.48 + types = Types.instance(context); 1.49 + diags = JCDiagnostic.Factory.instance(context); 1.50 + Source source = Source.instance(context); 1.51 + boxingEnabled = source.allowBoxing(); 1.52 + varargsEnabled = source.allowVarargs(); 1.53 + Options options = Options.instance(context); 1.54 + debugResolve = options.isSet("debugresolve"); 1.55 + verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options); 1.56 + Target target = Target.instance(context); 1.57 + allowMethodHandles = target.hasMethodHandles(); 1.58 + polymorphicSignatureScope = new Scope(syms.noSymbol); 1.59 + 1.60 + inapplicableMethodException = new InapplicableMethodException(diags); 1.61 + } 1.62 + 1.63 + /** error symbols, which are returned when resolution fails 1.64 + */ 1.65 + private final SymbolNotFoundError varNotFound; 1.66 + private final InapplicableSymbolError wrongMethod; 1.67 + private final InapplicableSymbolsError wrongMethods; 1.68 + private final SymbolNotFoundError methodNotFound; 1.69 + private final SymbolNotFoundError typeNotFound; 1.70 + 1.71 + public static Resolve instance(Context context) { 1.72 + Resolve instance = context.get(resolveKey); 1.73 + if (instance == null) 1.74 + instance = new Resolve(context); 1.75 + return instance; 1.76 + } 1.77 + 1.78 + // <editor-fold defaultstate="collapsed" desc="Verbose resolution diagnostics support"> 1.79 enum VerboseResolutionMode { 1.80 SUCCESS("success"), 1.81 FAILURE("failure"), 1.82 @@ -119,56 +171,74 @@ 1.83 } 1.84 } 1.85 1.86 - public static Resolve instance(Context context) { 1.87 - Resolve instance = context.get(resolveKey); 1.88 - if (instance == null) 1.89 - instance = new Resolve(context); 1.90 - return instance; 1.91 + void reportVerboseResolutionDiagnostic(DiagnosticPosition dpos, Name name, Type site, 1.92 + List<Type> argtypes, List<Type> typeargtypes, Symbol bestSoFar) { 1.93 + boolean success = bestSoFar.kind < ERRONEOUS; 1.94 + 1.95 + if (success && !verboseResolutionMode.contains(VerboseResolutionMode.SUCCESS)) { 1.96 + return; 1.97 + } else if (!success && !verboseResolutionMode.contains(VerboseResolutionMode.FAILURE)) { 1.98 + return; 1.99 + } 1.100 + 1.101 + if (bestSoFar.name == names.init && 1.102 + bestSoFar.owner == syms.objectType.tsym && 1.103 + !verboseResolutionMode.contains(VerboseResolutionMode.OBJECT_INIT)) { 1.104 + return; //skip diags for Object constructor resolution 1.105 + } else if (site == syms.predefClass.type && 1.106 + !verboseResolutionMode.contains(VerboseResolutionMode.PREDEF)) { 1.107 + return; //skip spurious diags for predef symbols (i.e. operators) 1.108 + } else if (currentResolutionContext.internalResolution && 1.109 + !verboseResolutionMode.contains(VerboseResolutionMode.INTERNAL)) { 1.110 + return; 1.111 + } 1.112 + 1.113 + int pos = 0; 1.114 + int mostSpecificPos = -1; 1.115 + ListBuffer<JCDiagnostic> subDiags = ListBuffer.lb(); 1.116 + for (Candidate c : currentResolutionContext.candidates) { 1.117 + if (currentResolutionContext.step != c.step || 1.118 + (c.isApplicable() && !verboseResolutionMode.contains(VerboseResolutionMode.APPLICABLE)) || 1.119 + (!c.isApplicable() && !verboseResolutionMode.contains(VerboseResolutionMode.INAPPLICABLE))) { 1.120 + continue; 1.121 + } else { 1.122 + subDiags.append(c.isApplicable() ? 1.123 + getVerboseApplicableCandidateDiag(pos, c.sym, c.mtype) : 1.124 + getVerboseInapplicableCandidateDiag(pos, c.sym, c.details)); 1.125 + if (c.sym == bestSoFar) 1.126 + mostSpecificPos = pos; 1.127 + pos++; 1.128 + } 1.129 + } 1.130 + String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1"; 1.131 + JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name, 1.132 + site.tsym, mostSpecificPos, currentResolutionContext.step, 1.133 + methodArguments(argtypes), methodArguments(typeargtypes)); 1.134 + JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, subDiags.toList()); 1.135 + log.report(d); 1.136 } 1.137 1.138 - protected Resolve(Context context) { 1.139 - context.put(resolveKey, this); 1.140 - syms = Symtab.instance(context); 1.141 + JCDiagnostic getVerboseApplicableCandidateDiag(int pos, Symbol sym, Type inst) { 1.142 + JCDiagnostic subDiag = null; 1.143 + if (inst.getReturnType().tag == FORALL) { 1.144 + Type diagType = types.createMethodTypeWithReturn(inst.asMethodType(), 1.145 + ((ForAll)inst.getReturnType()).qtype); 1.146 + subDiag = diags.fragment("partial.inst.sig", diagType); 1.147 + } else if (sym.type.tag == FORALL) { 1.148 + subDiag = diags.fragment("full.inst.sig", inst.asMethodType()); 1.149 + } 1.150 1.151 - varNotFound = new 1.152 - SymbolNotFoundError(ABSENT_VAR); 1.153 - wrongMethod = new 1.154 - InapplicableSymbolError(syms.errSymbol); 1.155 - wrongMethods = new 1.156 - InapplicableSymbolsError(syms.errSymbol); 1.157 - methodNotFound = new 1.158 - SymbolNotFoundError(ABSENT_MTH); 1.159 - typeNotFound = new 1.160 - SymbolNotFoundError(ABSENT_TYP); 1.161 + String key = subDiag == null ? 1.162 + "applicable.method.found" : 1.163 + "applicable.method.found.1"; 1.164 1.165 - names = Names.instance(context); 1.166 - log = Log.instance(context); 1.167 - chk = Check.instance(context); 1.168 - infer = Infer.instance(context); 1.169 - reader = ClassReader.instance(context); 1.170 - treeinfo = TreeInfo.instance(context); 1.171 - types = Types.instance(context); 1.172 - diags = JCDiagnostic.Factory.instance(context); 1.173 - Source source = Source.instance(context); 1.174 - boxingEnabled = source.allowBoxing(); 1.175 - varargsEnabled = source.allowVarargs(); 1.176 - Options options = Options.instance(context); 1.177 - debugResolve = options.isSet("debugresolve"); 1.178 - verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options); 1.179 - Target target = Target.instance(context); 1.180 - allowMethodHandles = target.hasMethodHandles(); 1.181 - polymorphicSignatureScope = new Scope(syms.noSymbol); 1.182 - 1.183 - inapplicableMethodException = new InapplicableMethodException(diags); 1.184 + return diags.fragment(key, pos, sym, subDiag); 1.185 } 1.186 1.187 - /** error symbols, which are returned when resolution fails 1.188 - */ 1.189 - final SymbolNotFoundError varNotFound; 1.190 - final InapplicableSymbolError wrongMethod; 1.191 - final InapplicableSymbolsError wrongMethods; 1.192 - final SymbolNotFoundError methodNotFound; 1.193 - final SymbolNotFoundError typeNotFound; 1.194 + JCDiagnostic getVerboseInapplicableCandidateDiag(int pos, Symbol sym, JCDiagnostic subDiag) { 1.195 + return diags.fragment("not.applicable.method.found", pos, sym, subDiag); 1.196 + } 1.197 + // </editor-fold> 1.198 1.199 /* ************************************************************************ 1.200 * Identifier resolution 1.201 @@ -804,17 +874,18 @@ 1.202 try { 1.203 Type mt = rawInstantiate(env, site, sym, argtypes, typeargtypes, 1.204 allowBoxing, useVarargs, Warner.noWarnings); 1.205 - if (!operator) addVerboseApplicableCandidateDiag(sym ,mt); 1.206 + if (!operator) 1.207 + currentResolutionContext.addApplicableCandidate(sym, mt); 1.208 } catch (InapplicableMethodException ex) { 1.209 - if (!operator) addVerboseInapplicableCandidateDiag(sym, ex.getDiagnostic()); 1.210 + if (!operator) 1.211 + currentResolutionContext.addInapplicableCandidate(sym, ex.getDiagnostic()); 1.212 switch (bestSoFar.kind) { 1.213 case ABSENT_MTH: 1.214 - return wrongMethod.setWrongSym(sym, ex.getDiagnostic()); 1.215 + return wrongMethod; 1.216 case WRONG_MTH: 1.217 if (operator) return bestSoFar; 1.218 - wrongMethods.addCandidate(currentStep, wrongMethod.sym, wrongMethod.explanation); 1.219 case WRONG_MTHS: 1.220 - return wrongMethods.addCandidate(currentStep, sym, ex.getDiagnostic()); 1.221 + return wrongMethods; 1.222 default: 1.223 return bestSoFar; 1.224 } 1.225 @@ -823,40 +894,12 @@ 1.226 return (bestSoFar.kind == ABSENT_MTH) 1.227 ? new AccessError(env, site, sym) 1.228 : bestSoFar; 1.229 - } 1.230 + } 1.231 return (bestSoFar.kind > AMBIGUOUS) 1.232 ? sym 1.233 : mostSpecific(sym, bestSoFar, env, site, 1.234 allowBoxing && operator, useVarargs); 1.235 } 1.236 - //where 1.237 - void addVerboseApplicableCandidateDiag(Symbol sym, Type inst) { 1.238 - if (!verboseResolutionMode.contains(VerboseResolutionMode.APPLICABLE)) 1.239 - return; 1.240 - 1.241 - JCDiagnostic subDiag = null; 1.242 - if (inst.getReturnType().tag == FORALL) { 1.243 - Type diagType = types.createMethodTypeWithReturn(inst.asMethodType(), 1.244 - ((ForAll)inst.getReturnType()).qtype); 1.245 - subDiag = diags.fragment("partial.inst.sig", diagType); 1.246 - } else if (sym.type.tag == FORALL) { 1.247 - subDiag = diags.fragment("full.inst.sig", inst.asMethodType()); 1.248 - } 1.249 - 1.250 - String key = subDiag == null ? 1.251 - "applicable.method.found" : 1.252 - "applicable.method.found.1"; 1.253 - 1.254 - verboseResolutionCandidateDiags.put(sym, 1.255 - diags.fragment(key, verboseResolutionCandidateDiags.size(), sym, subDiag)); 1.256 - } 1.257 - 1.258 - void addVerboseInapplicableCandidateDiag(Symbol sym, JCDiagnostic subDiag) { 1.259 - if (!verboseResolutionMode.contains(VerboseResolutionMode.INAPPLICABLE)) 1.260 - return; 1.261 - verboseResolutionCandidateDiags.put(sym, 1.262 - diags.fragment("not.applicable.method.found", verboseResolutionCandidateDiags.size(), sym, subDiag)); 1.263 - } 1.264 1.265 /* Return the most specific of the two methods for a call, 1.266 * given that both are accessible and applicable. 1.267 @@ -1054,7 +1097,6 @@ 1.268 boolean allowBoxing, 1.269 boolean useVarargs, 1.270 boolean operator) { 1.271 - verboseResolutionCandidateDiags.clear(); 1.272 Symbol bestSoFar = methodNotFound; 1.273 bestSoFar = findMethod(env, 1.274 site, 1.275 @@ -1127,37 +1169,6 @@ 1.276 } 1.277 return bestSoFar; 1.278 } 1.279 - //where 1.280 - void reportVerboseResolutionDiagnostic(DiagnosticPosition dpos, Name name, Type site, List<Type> argtypes, List<Type> typeargtypes, Symbol bestSoFar) { 1.281 - boolean success = bestSoFar.kind < ERRONEOUS; 1.282 - 1.283 - if (success && !verboseResolutionMode.contains(VerboseResolutionMode.SUCCESS)) { 1.284 - return; 1.285 - } else if (!success && !verboseResolutionMode.contains(VerboseResolutionMode.FAILURE)) { 1.286 - return; 1.287 - } 1.288 - 1.289 - if (bestSoFar.name == names.init && 1.290 - bestSoFar.owner == syms.objectType.tsym && 1.291 - !verboseResolutionMode.contains(VerboseResolutionMode.OBJECT_INIT)) { 1.292 - return; //skip diags for Object constructor resolution 1.293 - } else if (site == syms.predefClass.type && !verboseResolutionMode.contains(VerboseResolutionMode.PREDEF)) { 1.294 - return; //skip spurious diags for predef symbols (i.e. operators) 1.295 - } else if (internalResolution && !verboseResolutionMode.contains(VerboseResolutionMode.INTERNAL)) { 1.296 - return; 1.297 - } 1.298 - 1.299 - int pos = 0; 1.300 - for (Symbol s : verboseResolutionCandidateDiags.keySet()) { 1.301 - if (s == bestSoFar) break; 1.302 - pos++; 1.303 - } 1.304 - String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1"; 1.305 - JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name, site.tsym, pos, currentStep, 1.306 - methodArguments(argtypes), methodArguments(typeargtypes)); 1.307 - JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, List.from(verboseResolutionCandidateDiags.values().toArray(new JCDiagnostic[verboseResolutionCandidateDiags.size()]))); 1.308 - log.report(d); 1.309 - } 1.310 1.311 /** Find unqualified method matching given name, type and value arguments. 1.312 * @param env The current environment. 1.313 @@ -1591,32 +1602,33 @@ 1.314 Name name, 1.315 List<Type> argtypes, 1.316 List<Type> typeargtypes) { 1.317 - Symbol sym = startResolution(); 1.318 - List<MethodResolutionPhase> steps = methodResolutionSteps; 1.319 - while (steps.nonEmpty() && 1.320 - steps.head.isApplicable(boxingEnabled, varargsEnabled) && 1.321 - sym.kind >= ERRONEOUS) { 1.322 - currentStep = steps.head; 1.323 - sym = findFun(env, name, argtypes, typeargtypes, 1.324 - steps.head.isBoxingRequired, 1.325 - env.info.varArgs = steps.head.isVarargsRequired); 1.326 - methodResolutionCache.put(steps.head, sym); 1.327 - steps = steps.tail; 1.328 + MethodResolutionContext prevResolutionContext = currentResolutionContext; 1.329 + try { 1.330 + currentResolutionContext = new MethodResolutionContext(); 1.331 + Symbol sym = methodNotFound; 1.332 + List<MethodResolutionPhase> steps = methodResolutionSteps; 1.333 + while (steps.nonEmpty() && 1.334 + steps.head.isApplicable(boxingEnabled, varargsEnabled) && 1.335 + sym.kind >= ERRONEOUS) { 1.336 + currentResolutionContext.step = steps.head; 1.337 + sym = findFun(env, name, argtypes, typeargtypes, 1.338 + steps.head.isBoxingRequired, 1.339 + env.info.varArgs = steps.head.isVarargsRequired); 1.340 + currentResolutionContext.resolutionCache.put(steps.head, sym); 1.341 + steps = steps.tail; 1.342 + } 1.343 + if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error 1.344 + MethodResolutionPhase errPhase = 1.345 + currentResolutionContext.firstErroneousResolutionPhase(); 1.346 + sym = access(currentResolutionContext.resolutionCache.get(errPhase), 1.347 + pos, env.enclClass.sym.type, name, false, argtypes, typeargtypes); 1.348 + env.info.varArgs = errPhase.isVarargsRequired; 1.349 + } 1.350 + return sym; 1.351 } 1.352 - if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error 1.353 - MethodResolutionPhase errPhase = 1.354 - firstErroneousResolutionPhase(); 1.355 - sym = access(methodResolutionCache.get(errPhase), 1.356 - pos, env.enclClass.sym.type, name, false, argtypes, typeargtypes); 1.357 - env.info.varArgs = errPhase.isVarargsRequired; 1.358 + finally { 1.359 + currentResolutionContext = prevResolutionContext; 1.360 } 1.361 - return sym; 1.362 - } 1.363 - 1.364 - private Symbol startResolution() { 1.365 - wrongMethod.clear(); 1.366 - wrongMethods.clear(); 1.367 - return methodNotFound; 1.368 } 1.369 1.370 /** Resolve a qualified method identifier 1.371 @@ -1636,40 +1648,53 @@ 1.372 Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env, 1.373 Symbol location, Type site, Name name, List<Type> argtypes, 1.374 List<Type> typeargtypes) { 1.375 - Symbol sym = startResolution(); 1.376 - List<MethodResolutionPhase> steps = methodResolutionSteps; 1.377 - while (steps.nonEmpty() && 1.378 - steps.head.isApplicable(boxingEnabled, varargsEnabled) && 1.379 - sym.kind >= ERRONEOUS) { 1.380 - currentStep = steps.head; 1.381 - sym = findMethod(env, site, name, argtypes, typeargtypes, 1.382 - steps.head.isBoxingRequired(), 1.383 - env.info.varArgs = steps.head.isVarargsRequired(), false); 1.384 - methodResolutionCache.put(steps.head, sym); 1.385 - steps = steps.tail; 1.386 - } 1.387 - if (sym.kind >= AMBIGUOUS) { 1.388 - if (site.tsym.isPolymorphicSignatureGeneric()) { 1.389 - //polymorphic receiver - synthesize new method symbol 1.390 + return resolveQualifiedMethod(new MethodResolutionContext(), pos, env, location, site, name, argtypes, typeargtypes); 1.391 + } 1.392 + private Symbol resolveQualifiedMethod(MethodResolutionContext resolveContext, 1.393 + DiagnosticPosition pos, Env<AttrContext> env, 1.394 + Symbol location, Type site, Name name, List<Type> argtypes, 1.395 + List<Type> typeargtypes) { 1.396 + MethodResolutionContext prevResolutionContext = currentResolutionContext; 1.397 + try { 1.398 + currentResolutionContext = resolveContext; 1.399 + Symbol sym = methodNotFound; 1.400 + List<MethodResolutionPhase> steps = methodResolutionSteps; 1.401 + while (steps.nonEmpty() && 1.402 + steps.head.isApplicable(boxingEnabled, varargsEnabled) && 1.403 + sym.kind >= ERRONEOUS) { 1.404 + currentResolutionContext.step = steps.head; 1.405 + sym = findMethod(env, site, name, argtypes, typeargtypes, 1.406 + steps.head.isBoxingRequired(), 1.407 + env.info.varArgs = steps.head.isVarargsRequired(), false); 1.408 + currentResolutionContext.resolutionCache.put(steps.head, sym); 1.409 + steps = steps.tail; 1.410 + } 1.411 + if (sym.kind >= AMBIGUOUS) { 1.412 + if (site.tsym.isPolymorphicSignatureGeneric()) { 1.413 + //polymorphic receiver - synthesize new method symbol 1.414 + env.info.varArgs = false; 1.415 + sym = findPolymorphicSignatureInstance(env, 1.416 + site, name, null, argtypes); 1.417 + } 1.418 + else { 1.419 + //if nothing is found return the 'first' error 1.420 + MethodResolutionPhase errPhase = 1.421 + currentResolutionContext.firstErroneousResolutionPhase(); 1.422 + sym = access(currentResolutionContext.resolutionCache.get(errPhase), 1.423 + pos, location, site, name, true, argtypes, typeargtypes); 1.424 + env.info.varArgs = errPhase.isVarargsRequired; 1.425 + } 1.426 + } else if (allowMethodHandles && sym.isPolymorphicSignatureGeneric()) { 1.427 + //non-instantiated polymorphic signature - synthesize new method symbol 1.428 env.info.varArgs = false; 1.429 sym = findPolymorphicSignatureInstance(env, 1.430 - site, name, null, argtypes); 1.431 + site, name, (MethodSymbol)sym, argtypes); 1.432 } 1.433 - else { 1.434 - //if nothing is found return the 'first' error 1.435 - MethodResolutionPhase errPhase = 1.436 - firstErroneousResolutionPhase(); 1.437 - sym = access(methodResolutionCache.get(errPhase), 1.438 - pos, location, site, name, true, argtypes, typeargtypes); 1.439 - env.info.varArgs = errPhase.isVarargsRequired; 1.440 - } 1.441 - } else if (allowMethodHandles && sym.isPolymorphicSignatureGeneric()) { 1.442 - //non-instantiated polymorphic signature - synthesize new method symbol 1.443 - env.info.varArgs = false; 1.444 - sym = findPolymorphicSignatureInstance(env, 1.445 - site, name, (MethodSymbol)sym, argtypes); 1.446 + return sym; 1.447 } 1.448 - return sym; 1.449 + finally { 1.450 + currentResolutionContext = prevResolutionContext; 1.451 + } 1.452 } 1.453 1.454 /** Find or create an implicit method of exactly the given type (after erasure). 1.455 @@ -1726,19 +1751,14 @@ 1.456 Type site, Name name, 1.457 List<Type> argtypes, 1.458 List<Type> typeargtypes) { 1.459 - boolean prevInternal = internalResolution; 1.460 - try { 1.461 - internalResolution = true; 1.462 - Symbol sym = resolveQualifiedMethod( 1.463 - pos, env, site.tsym, site, name, argtypes, typeargtypes); 1.464 - if (sym.kind == MTH) return (MethodSymbol)sym; 1.465 - else throw new FatalError( 1.466 - diags.fragment("fatal.err.cant.locate.meth", 1.467 - name)); 1.468 - } 1.469 - finally { 1.470 - internalResolution = prevInternal; 1.471 - } 1.472 + MethodResolutionContext resolveContext = new MethodResolutionContext(); 1.473 + resolveContext.internalResolution = true; 1.474 + Symbol sym = resolveQualifiedMethod(resolveContext, pos, env, site.tsym, 1.475 + site, name, argtypes, typeargtypes); 1.476 + if (sym.kind == MTH) return (MethodSymbol)sym; 1.477 + else throw new FatalError( 1.478 + diags.fragment("fatal.err.cant.locate.meth", 1.479 + name)); 1.480 } 1.481 1.482 /** Resolve constructor. 1.483 @@ -1755,25 +1775,40 @@ 1.484 Type site, 1.485 List<Type> argtypes, 1.486 List<Type> typeargtypes) { 1.487 - Symbol sym = startResolution(); 1.488 - List<MethodResolutionPhase> steps = methodResolutionSteps; 1.489 - while (steps.nonEmpty() && 1.490 - steps.head.isApplicable(boxingEnabled, varargsEnabled) && 1.491 - sym.kind >= ERRONEOUS) { 1.492 - currentStep = steps.head; 1.493 - sym = resolveConstructor(pos, env, site, argtypes, typeargtypes, 1.494 - steps.head.isBoxingRequired(), 1.495 - env.info.varArgs = steps.head.isVarargsRequired()); 1.496 - methodResolutionCache.put(steps.head, sym); 1.497 - steps = steps.tail; 1.498 + return resolveConstructor(new MethodResolutionContext(), pos, env, site, argtypes, typeargtypes); 1.499 + } 1.500 + private Symbol resolveConstructor(MethodResolutionContext resolveContext, 1.501 + DiagnosticPosition pos, 1.502 + Env<AttrContext> env, 1.503 + Type site, 1.504 + List<Type> argtypes, 1.505 + List<Type> typeargtypes) { 1.506 + MethodResolutionContext prevResolutionContext = currentResolutionContext; 1.507 + try { 1.508 + currentResolutionContext = resolveContext; 1.509 + Symbol sym = methodNotFound; 1.510 + List<MethodResolutionPhase> steps = methodResolutionSteps; 1.511 + while (steps.nonEmpty() && 1.512 + steps.head.isApplicable(boxingEnabled, varargsEnabled) && 1.513 + sym.kind >= ERRONEOUS) { 1.514 + currentResolutionContext.step = steps.head; 1.515 + sym = findConstructor(pos, env, site, argtypes, typeargtypes, 1.516 + steps.head.isBoxingRequired(), 1.517 + env.info.varArgs = steps.head.isVarargsRequired()); 1.518 + currentResolutionContext.resolutionCache.put(steps.head, sym); 1.519 + steps = steps.tail; 1.520 + } 1.521 + if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error 1.522 + MethodResolutionPhase errPhase = currentResolutionContext.firstErroneousResolutionPhase(); 1.523 + sym = access(currentResolutionContext.resolutionCache.get(errPhase), 1.524 + pos, site, names.init, true, argtypes, typeargtypes); 1.525 + env.info.varArgs = errPhase.isVarargsRequired(); 1.526 + } 1.527 + return sym; 1.528 } 1.529 - if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error 1.530 - MethodResolutionPhase errPhase = firstErroneousResolutionPhase(); 1.531 - sym = access(methodResolutionCache.get(errPhase), 1.532 - pos, site, names.init, true, argtypes, typeargtypes); 1.533 - env.info.varArgs = errPhase.isVarargsRequired(); 1.534 + finally { 1.535 + currentResolutionContext = prevResolutionContext; 1.536 } 1.537 - return sym; 1.538 } 1.539 1.540 /** Resolve constructor using diamond inference. 1.541 @@ -1791,38 +1826,45 @@ 1.542 Type site, 1.543 List<Type> argtypes, 1.544 List<Type> typeargtypes) { 1.545 - Symbol sym = startResolution(); 1.546 - List<MethodResolutionPhase> steps = methodResolutionSteps; 1.547 - while (steps.nonEmpty() && 1.548 - steps.head.isApplicable(boxingEnabled, varargsEnabled) && 1.549 - sym.kind >= ERRONEOUS) { 1.550 - currentStep = steps.head; 1.551 - sym = resolveConstructor(pos, env, site, argtypes, typeargtypes, 1.552 - steps.head.isBoxingRequired(), 1.553 - env.info.varArgs = steps.head.isVarargsRequired()); 1.554 - methodResolutionCache.put(steps.head, sym); 1.555 - steps = steps.tail; 1.556 + MethodResolutionContext prevResolutionContext = currentResolutionContext; 1.557 + try { 1.558 + currentResolutionContext = new MethodResolutionContext(); 1.559 + Symbol sym = methodNotFound; 1.560 + List<MethodResolutionPhase> steps = methodResolutionSteps; 1.561 + while (steps.nonEmpty() && 1.562 + steps.head.isApplicable(boxingEnabled, varargsEnabled) && 1.563 + sym.kind >= ERRONEOUS) { 1.564 + currentResolutionContext.step = steps.head; 1.565 + sym = findConstructor(pos, env, site, argtypes, typeargtypes, 1.566 + steps.head.isBoxingRequired(), 1.567 + env.info.varArgs = steps.head.isVarargsRequired()); 1.568 + currentResolutionContext.resolutionCache.put(steps.head, sym); 1.569 + steps = steps.tail; 1.570 + } 1.571 + if (sym.kind >= AMBIGUOUS) { 1.572 + final JCDiagnostic details = sym.kind == WRONG_MTH ? 1.573 + currentResolutionContext.candidates.head.details : 1.574 + null; 1.575 + Symbol errSym = new ResolveError(WRONG_MTH, "diamond error") { 1.576 + @Override 1.577 + JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, 1.578 + Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { 1.579 + String key = details == null ? 1.580 + "cant.apply.diamond" : 1.581 + "cant.apply.diamond.1"; 1.582 + return diags.create(dkind, log.currentSource(), pos, key, 1.583 + diags.fragment("diamond", site.tsym), details); 1.584 + } 1.585 + }; 1.586 + MethodResolutionPhase errPhase = currentResolutionContext.firstErroneousResolutionPhase(); 1.587 + sym = access(errSym, pos, site, names.init, true, argtypes, typeargtypes); 1.588 + env.info.varArgs = errPhase.isVarargsRequired(); 1.589 + } 1.590 + return sym; 1.591 } 1.592 - if (sym.kind >= AMBIGUOUS) { 1.593 - final JCDiagnostic details = sym.kind == WRONG_MTH ? 1.594 - ((InapplicableSymbolError)sym).explanation : 1.595 - null; 1.596 - Symbol errSym = new ResolveError(WRONG_MTH, "diamond error") { 1.597 - @Override 1.598 - JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, 1.599 - Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { 1.600 - String key = details == null ? 1.601 - "cant.apply.diamond" : 1.602 - "cant.apply.diamond.1"; 1.603 - return diags.create(dkind, log.currentSource(), pos, key, 1.604 - diags.fragment("diamond", site.tsym), details); 1.605 - } 1.606 - }; 1.607 - MethodResolutionPhase errPhase = firstErroneousResolutionPhase(); 1.608 - sym = access(errSym, pos, site, names.init, true, argtypes, typeargtypes); 1.609 - env.info.varArgs = errPhase.isVarargsRequired(); 1.610 + finally { 1.611 + currentResolutionContext = prevResolutionContext; 1.612 } 1.613 - return sym; 1.614 } 1.615 1.616 /** Resolve constructor. 1.617 @@ -1841,10 +1883,25 @@ 1.618 List<Type> typeargtypes, 1.619 boolean allowBoxing, 1.620 boolean useVarargs) { 1.621 + MethodResolutionContext prevResolutionContext = currentResolutionContext; 1.622 + try { 1.623 + currentResolutionContext = new MethodResolutionContext(); 1.624 + return findConstructor(pos, env, site, argtypes, typeargtypes, allowBoxing, useVarargs); 1.625 + } 1.626 + finally { 1.627 + currentResolutionContext = prevResolutionContext; 1.628 + } 1.629 + } 1.630 + 1.631 + Symbol findConstructor(DiagnosticPosition pos, Env<AttrContext> env, 1.632 + Type site, List<Type> argtypes, 1.633 + List<Type> typeargtypes, 1.634 + boolean allowBoxing, 1.635 + boolean useVarargs) { 1.636 Symbol sym = findMethod(env, site, 1.637 - names.init, argtypes, 1.638 - typeargtypes, allowBoxing, 1.639 - useVarargs, false); 1.640 + names.init, argtypes, 1.641 + typeargtypes, allowBoxing, 1.642 + useVarargs, false); 1.643 chk.checkDeprecated(pos, env.info.scope.owner, sym); 1.644 return sym; 1.645 } 1.646 @@ -1860,8 +1917,9 @@ 1.647 Type site, 1.648 List<Type> argtypes, 1.649 List<Type> typeargtypes) { 1.650 - Symbol sym = resolveConstructor( 1.651 - pos, env, site, argtypes, typeargtypes); 1.652 + MethodResolutionContext resolveContext = new MethodResolutionContext(); 1.653 + resolveContext.internalResolution = true; 1.654 + Symbol sym = resolveConstructor(resolveContext, pos, env, site, argtypes, typeargtypes); 1.655 if (sym.kind == MTH) return (MethodSymbol)sym; 1.656 else throw new FatalError( 1.657 diags.fragment("fatal.err.cant.locate.ctor", site)); 1.658 @@ -1875,15 +1933,21 @@ 1.659 */ 1.660 Symbol resolveOperator(DiagnosticPosition pos, JCTree.Tag optag, 1.661 Env<AttrContext> env, List<Type> argtypes) { 1.662 - startResolution(); 1.663 - Name name = treeinfo.operatorName(optag); 1.664 - Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes, 1.665 - null, false, false, true); 1.666 - if (boxingEnabled && sym.kind >= WRONG_MTHS) 1.667 - sym = findMethod(env, syms.predefClass.type, name, argtypes, 1.668 - null, true, false, true); 1.669 - return access(sym, pos, env.enclClass.sym.type, name, 1.670 - false, argtypes, null); 1.671 + MethodResolutionContext prevResolutionContext = currentResolutionContext; 1.672 + try { 1.673 + currentResolutionContext = new MethodResolutionContext(); 1.674 + Name name = treeinfo.operatorName(optag); 1.675 + Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes, 1.676 + null, false, false, true); 1.677 + if (boxingEnabled && sym.kind >= WRONG_MTHS) 1.678 + sym = findMethod(env, syms.predefClass.type, name, argtypes, 1.679 + null, true, false, true); 1.680 + return access(sym, pos, env.enclClass.sym.type, name, 1.681 + false, argtypes, null); 1.682 + } 1.683 + finally { 1.684 + currentResolutionContext = prevResolutionContext; 1.685 + } 1.686 } 1.687 1.688 /** Resolve operator. 1.689 @@ -2227,34 +2291,24 @@ 1.690 * (either a method, a constructor or an operand) is not applicable 1.691 * given an actual arguments/type argument list. 1.692 */ 1.693 - class InapplicableSymbolError extends InvalidSymbolError { 1.694 + class InapplicableSymbolError extends ResolveError { 1.695 1.696 - /** An auxiliary explanation set in case of instantiation errors. */ 1.697 - JCDiagnostic explanation; 1.698 - 1.699 - InapplicableSymbolError(Symbol sym) { 1.700 - super(WRONG_MTH, sym, "inapplicable symbol error"); 1.701 + InapplicableSymbolError() { 1.702 + super(WRONG_MTH, "inapplicable symbol error"); 1.703 } 1.704 1.705 - /** Update sym and explanation and return this. 1.706 - */ 1.707 - InapplicableSymbolError setWrongSym(Symbol sym, JCDiagnostic explanation) { 1.708 - this.sym = sym; 1.709 - if (this.sym == sym && explanation != null) 1.710 - this.explanation = explanation; //update the details 1.711 - return this; 1.712 - } 1.713 - 1.714 - /** Update sym and return this. 1.715 - */ 1.716 - InapplicableSymbolError setWrongSym(Symbol sym) { 1.717 - this.sym = sym; 1.718 - return this; 1.719 + protected InapplicableSymbolError(int kind, String debugName) { 1.720 + super(kind, debugName); 1.721 } 1.722 1.723 @Override 1.724 public String toString() { 1.725 - return super.toString() + " explanation=" + explanation; 1.726 + return super.toString(); 1.727 + } 1.728 + 1.729 + @Override 1.730 + public boolean exists() { 1.731 + return true; 1.732 } 1.733 1.734 @Override 1.735 @@ -2279,27 +2333,40 @@ 1.736 key, name, first, second); 1.737 } 1.738 else { 1.739 - Symbol ws = sym.asMemberOf(site, types); 1.740 + Candidate c = errCandidate(); 1.741 + Symbol ws = c.sym.asMemberOf(site, types); 1.742 return diags.create(dkind, log.currentSource(), pos, 1.743 - "cant.apply.symbol" + (explanation != null ? ".1" : ""), 1.744 + "cant.apply.symbol" + (c.details != null ? ".1" : ""), 1.745 kindName(ws), 1.746 ws.name == names.init ? ws.owner.name : ws.name, 1.747 methodArguments(ws.type.getParameterTypes()), 1.748 methodArguments(argtypes), 1.749 kindName(ws.owner), 1.750 ws.owner.type, 1.751 - explanation); 1.752 + c.details); 1.753 } 1.754 } 1.755 1.756 - void clear() { 1.757 - explanation = null; 1.758 - } 1.759 - 1.760 @Override 1.761 public Symbol access(Name name, TypeSymbol location) { 1.762 return types.createErrorType(name, location, syms.errSymbol.type).tsym; 1.763 } 1.764 + 1.765 + protected boolean shouldReport(Candidate c) { 1.766 + return !c.isApplicable() && 1.767 + (((c.sym.flags() & VARARGS) != 0 && c.step == VARARITY) || 1.768 + (c.sym.flags() & VARARGS) == 0 && c.step == (boxingEnabled ? BOX : BASIC)); 1.769 + } 1.770 + 1.771 + private Candidate errCandidate() { 1.772 + for (Candidate c : currentResolutionContext.candidates) { 1.773 + if (shouldReport(c)) { 1.774 + return c; 1.775 + } 1.776 + } 1.777 + Assert.error(); 1.778 + return null; 1.779 + } 1.780 } 1.781 1.782 /** 1.783 @@ -2307,11 +2374,9 @@ 1.784 * (either methods, constructors or operands) is not applicable 1.785 * given an actual arguments/type argument list. 1.786 */ 1.787 - class InapplicableSymbolsError extends ResolveError { 1.788 + class InapplicableSymbolsError extends InapplicableSymbolError { 1.789 1.790 - private List<Candidate> candidates = List.nil(); 1.791 - 1.792 - InapplicableSymbolsError(Symbol sym) { 1.793 + InapplicableSymbolsError() { 1.794 super(WRONG_MTHS, "inapplicable symbols"); 1.795 } 1.796 1.797 @@ -2323,7 +2388,7 @@ 1.798 Name name, 1.799 List<Type> argtypes, 1.800 List<Type> typeargtypes) { 1.801 - if (candidates.nonEmpty()) { 1.802 + if (currentResolutionContext.candidates.nonEmpty()) { 1.803 JCDiagnostic err = diags.create(dkind, 1.804 log.currentSource(), 1.805 pos, 1.806 @@ -2341,68 +2406,24 @@ 1.807 //where 1.808 List<JCDiagnostic> candidateDetails(Type site) { 1.809 List<JCDiagnostic> details = List.nil(); 1.810 - for (Candidate c : candidates) 1.811 - details = details.prepend(c.getDiagnostic(site)); 1.812 + for (Candidate c : currentResolutionContext.candidates) { 1.813 + if (!shouldReport(c)) continue; 1.814 + JCDiagnostic detailDiag = diags.fragment("inapplicable.method", 1.815 + Kinds.kindName(c.sym), 1.816 + c.sym.location(site, types), 1.817 + c.sym.asMemberOf(site, types), 1.818 + c.details); 1.819 + details = details.prepend(detailDiag); 1.820 + } 1.821 return details.reverse(); 1.822 } 1.823 1.824 - Symbol addCandidate(MethodResolutionPhase currentStep, Symbol sym, JCDiagnostic details) { 1.825 - Candidate c = new Candidate(currentStep, sym, details); 1.826 - if (c.isValid() && !candidates.contains(c)) 1.827 - candidates = candidates.append(c); 1.828 - return this; 1.829 - } 1.830 - 1.831 - void clear() { 1.832 - candidates = List.nil(); 1.833 - } 1.834 - 1.835 private Name getName() { 1.836 - Symbol sym = candidates.head.sym; 1.837 + Symbol sym = currentResolutionContext.candidates.head.sym; 1.838 return sym.name == names.init ? 1.839 sym.owner.name : 1.840 sym.name; 1.841 } 1.842 - 1.843 - private class Candidate { 1.844 - 1.845 - final MethodResolutionPhase step; 1.846 - final Symbol sym; 1.847 - final JCDiagnostic details; 1.848 - 1.849 - private Candidate(MethodResolutionPhase step, Symbol sym, JCDiagnostic details) { 1.850 - this.step = step; 1.851 - this.sym = sym; 1.852 - this.details = details; 1.853 - } 1.854 - 1.855 - JCDiagnostic getDiagnostic(Type site) { 1.856 - return diags.fragment("inapplicable.method", 1.857 - Kinds.kindName(sym), 1.858 - sym.location(site, types), 1.859 - sym.asMemberOf(site, types), 1.860 - details); 1.861 - } 1.862 - 1.863 - @Override 1.864 - public boolean equals(Object o) { 1.865 - if (o instanceof Candidate) { 1.866 - Symbol s1 = this.sym; 1.867 - Symbol s2 = ((Candidate)o).sym; 1.868 - if ((s1 != s2 && 1.869 - (s1.overrides(s2, s1.owner.type.tsym, types, false) || 1.870 - (s2.overrides(s1, s2.owner.type.tsym, types, false)))) || 1.871 - ((s1.isConstructor() || s2.isConstructor()) && s1.owner != s2.owner)) 1.872 - return true; 1.873 - } 1.874 - return false; 1.875 - } 1.876 - 1.877 - boolean isValid() { 1.878 - return (((sym.flags() & VARARGS) != 0 && step == VARARITY) || 1.879 - (sym.flags() & VARARGS) == 0 && step == (boxingEnabled ? BOX : BASIC)); 1.880 - } 1.881 - } 1.882 } 1.883 1.884 /** 1.885 @@ -2563,29 +2584,91 @@ 1.886 } 1.887 } 1.888 1.889 - private Map<MethodResolutionPhase, Symbol> methodResolutionCache = 1.890 - new HashMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.values().length); 1.891 - 1.892 - private Map<Symbol, JCDiagnostic> verboseResolutionCandidateDiags = 1.893 - new LinkedHashMap<Symbol, JCDiagnostic>(); 1.894 - 1.895 final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY); 1.896 1.897 - private MethodResolutionPhase currentStep = null; 1.898 + /** 1.899 + * A resolution context is used to keep track of intermediate results of 1.900 + * overload resolution, such as list of method that are not applicable 1.901 + * (used to generate more precise diagnostics) and so on. Resolution contexts 1.902 + * can be nested - this means that when each overload resolution routine should 1.903 + * work within the resolution context it created. 1.904 + */ 1.905 + class MethodResolutionContext { 1.906 1.907 - private boolean internalResolution = false; 1.908 + private List<Candidate> candidates = List.nil(); 1.909 1.910 - private MethodResolutionPhase firstErroneousResolutionPhase() { 1.911 - MethodResolutionPhase bestSoFar = BASIC; 1.912 - Symbol sym = methodNotFound; 1.913 - List<MethodResolutionPhase> steps = methodResolutionSteps; 1.914 - while (steps.nonEmpty() && 1.915 - steps.head.isApplicable(boxingEnabled, varargsEnabled) && 1.916 - sym.kind >= WRONG_MTHS) { 1.917 - sym = methodResolutionCache.get(steps.head); 1.918 - bestSoFar = steps.head; 1.919 - steps = steps.tail; 1.920 + private Map<MethodResolutionPhase, Symbol> resolutionCache = 1.921 + new EnumMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.class); 1.922 + 1.923 + private MethodResolutionPhase step = null; 1.924 + 1.925 + private boolean internalResolution = false; 1.926 + 1.927 + private MethodResolutionPhase firstErroneousResolutionPhase() { 1.928 + MethodResolutionPhase bestSoFar = BASIC; 1.929 + Symbol sym = methodNotFound; 1.930 + List<MethodResolutionPhase> steps = methodResolutionSteps; 1.931 + while (steps.nonEmpty() && 1.932 + steps.head.isApplicable(boxingEnabled, varargsEnabled) && 1.933 + sym.kind >= WRONG_MTHS) { 1.934 + sym = resolutionCache.get(steps.head); 1.935 + bestSoFar = steps.head; 1.936 + steps = steps.tail; 1.937 + } 1.938 + return bestSoFar; 1.939 } 1.940 - return bestSoFar; 1.941 + 1.942 + void addInapplicableCandidate(Symbol sym, JCDiagnostic details) { 1.943 + Candidate c = new Candidate(currentResolutionContext.step, sym, details, null); 1.944 + if (!candidates.contains(c)) 1.945 + candidates = candidates.append(c); 1.946 + } 1.947 + 1.948 + void addApplicableCandidate(Symbol sym, Type mtype) { 1.949 + Candidate c = new Candidate(currentResolutionContext.step, sym, null, mtype); 1.950 + candidates = candidates.append(c); 1.951 + } 1.952 + 1.953 + /** 1.954 + * This class represents an overload resolution candidate. There are two 1.955 + * kinds of candidates: applicable methods and inapplicable methods; 1.956 + * applicable methods have a pointer to the instantiated method type, 1.957 + * while inapplicable candidates contain further details about the 1.958 + * reason why the method has been considered inapplicable. 1.959 + */ 1.960 + class Candidate { 1.961 + 1.962 + final MethodResolutionPhase step; 1.963 + final Symbol sym; 1.964 + final JCDiagnostic details; 1.965 + final Type mtype; 1.966 + 1.967 + private Candidate(MethodResolutionPhase step, Symbol sym, JCDiagnostic details, Type mtype) { 1.968 + this.step = step; 1.969 + this.sym = sym; 1.970 + this.details = details; 1.971 + this.mtype = mtype; 1.972 + } 1.973 + 1.974 + @Override 1.975 + public boolean equals(Object o) { 1.976 + if (o instanceof Candidate) { 1.977 + Symbol s1 = this.sym; 1.978 + Symbol s2 = ((Candidate)o).sym; 1.979 + if ((s1 != s2 && 1.980 + (s1.overrides(s2, s1.owner.type.tsym, types, false) || 1.981 + (s2.overrides(s1, s2.owner.type.tsym, types, false)))) || 1.982 + ((s1.isConstructor() || s2.isConstructor()) && s1.owner != s2.owner)) 1.983 + return true; 1.984 + } 1.985 + return false; 1.986 + } 1.987 + 1.988 + boolean isApplicable() { 1.989 + return mtype != null; 1.990 + } 1.991 + } 1.992 } 1.993 + 1.994 + MethodResolutionContext currentResolutionContext = null; 1.995 }