1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Apr 05 14:51:55 2013 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Mon Apr 08 15:51:41 2013 +0100 1.3 @@ -508,7 +508,6 @@ 1.4 List<Type> typeargtypes, 1.5 boolean allowBoxing, 1.6 boolean useVarargs, 1.7 - MethodCheck methodCheck, 1.8 Warner warn) throws Infer.InferenceException { 1.9 1.10 Type mt = types.memberType(site, m); 1.11 @@ -561,10 +560,9 @@ 1.12 allowBoxing, 1.13 useVarargs, 1.14 currentResolutionContext, 1.15 - methodCheck, 1.16 warn); 1.17 1.18 - methodCheck.argumentsAcceptable(env, currentResolutionContext.deferredAttrContext(m, infer.emptyContext, resultInfo, warn), 1.19 + currentResolutionContext.methodCheck.argumentsAcceptable(env, currentResolutionContext.deferredAttrContext(m, infer.emptyContext, resultInfo, warn), 1.20 argtypes, mt.getParameterTypes(), warn); 1.21 return mt; 1.22 } 1.23 @@ -582,7 +580,7 @@ 1.24 currentResolutionContext.attrMode = DeferredAttr.AttrMode.CHECK; 1.25 MethodResolutionPhase step = currentResolutionContext.step = env.info.pendingResolutionPhase; 1.26 return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes, 1.27 - step.isBoxingRequired(), step.isVarargsRequired(), resolveMethodCheck, warn); 1.28 + step.isBoxingRequired(), step.isVarargsRequired(), warn); 1.29 } 1.30 finally { 1.31 currentResolutionContext = prevContext; 1.32 @@ -599,11 +597,10 @@ 1.33 List<Type> typeargtypes, 1.34 boolean allowBoxing, 1.35 boolean useVarargs, 1.36 - MethodCheck methodCheck, 1.37 Warner warn) { 1.38 try { 1.39 return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes, 1.40 - allowBoxing, useVarargs, methodCheck, warn); 1.41 + allowBoxing, useVarargs, warn); 1.42 } catch (InapplicableMethodException ex) { 1.43 return null; 1.44 } 1.45 @@ -628,6 +625,12 @@ 1.46 List<Type> argtypes, 1.47 List<Type> formals, 1.48 Warner warn); 1.49 + 1.50 + /** 1.51 + * Retrieve the method check object that will be used during a 1.52 + * most specific check. 1.53 + */ 1.54 + MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict); 1.55 } 1.56 1.57 /** 1.58 @@ -661,6 +664,100 @@ 1.59 } 1.60 1.61 /** 1.62 + * Dummy method check object. All methods are deemed applicable, regardless 1.63 + * of their formal parameter types. 1.64 + */ 1.65 + MethodCheck nilMethodCheck = new MethodCheck() { 1.66 + public void argumentsAcceptable(Env<AttrContext> env, DeferredAttrContext deferredAttrContext, List<Type> argtypes, List<Type> formals, Warner warn) { 1.67 + //do nothing - method always applicable regardless of actuals 1.68 + } 1.69 + 1.70 + public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) { 1.71 + return this; 1.72 + } 1.73 + }; 1.74 + 1.75 + /** 1.76 + * Base class for 'real' method checks. The class defines the logic for 1.77 + * iterating through formals and actuals and provides and entry point 1.78 + * that can be used by subclasses in order to define the actual check logic. 1.79 + */ 1.80 + abstract class AbstractMethodCheck implements MethodCheck { 1.81 + @Override 1.82 + public void argumentsAcceptable(final Env<AttrContext> env, 1.83 + DeferredAttrContext deferredAttrContext, 1.84 + List<Type> argtypes, 1.85 + List<Type> formals, 1.86 + Warner warn) { 1.87 + //should we expand formals? 1.88 + boolean useVarargs = deferredAttrContext.phase.isVarargsRequired(); 1.89 + 1.90 + //inference context used during this method check 1.91 + InferenceContext inferenceContext = deferredAttrContext.inferenceContext; 1.92 + 1.93 + Type varargsFormal = useVarargs ? formals.last() : null; 1.94 + 1.95 + if (varargsFormal == null && 1.96 + argtypes.size() != formals.size()) { 1.97 + reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args 1.98 + } 1.99 + 1.100 + while (argtypes.nonEmpty() && formals.head != varargsFormal) { 1.101 + checkArg(false, argtypes.head, formals.head, deferredAttrContext, warn); 1.102 + argtypes = argtypes.tail; 1.103 + formals = formals.tail; 1.104 + } 1.105 + 1.106 + if (formals.head != varargsFormal) { 1.107 + reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args 1.108 + } 1.109 + 1.110 + if (useVarargs) { 1.111 + //note: if applicability check is triggered by most specific test, 1.112 + //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5) 1.113 + final Type elt = types.elemtype(varargsFormal); 1.114 + while (argtypes.nonEmpty()) { 1.115 + checkArg(true, argtypes.head, elt, deferredAttrContext, warn); 1.116 + argtypes = argtypes.tail; 1.117 + } 1.118 + } 1.119 + } 1.120 + 1.121 + /** 1.122 + * Does the actual argument conforms to the corresponding formal? 1.123 + */ 1.124 + abstract void checkArg(boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn); 1.125 + 1.126 + protected void reportMC(MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) { 1.127 + boolean inferDiag = inferenceContext != infer.emptyContext; 1.128 + InapplicableMethodException ex = inferDiag ? 1.129 + infer.inferenceException : inapplicableMethodException; 1.130 + if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) { 1.131 + Object[] args2 = new Object[args.length + 1]; 1.132 + System.arraycopy(args, 0, args2, 1, args.length); 1.133 + args2[0] = inferenceContext.inferenceVars(); 1.134 + args = args2; 1.135 + } 1.136 + throw ex.setMessage(inferDiag ? diag.inferKey : diag.basicKey, args); 1.137 + } 1.138 + 1.139 + public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) { 1.140 + return nilMethodCheck; 1.141 + } 1.142 + } 1.143 + 1.144 + /** 1.145 + * Arity-based method check. A method is applicable if the number of actuals 1.146 + * supplied conforms to the method signature. 1.147 + */ 1.148 + MethodCheck arityMethodCheck = new AbstractMethodCheck() { 1.149 + @Override 1.150 + void checkArg(boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) { 1.151 + //do nothing - actual always compatible to formals 1.152 + } 1.153 + }; 1.154 + 1.155 + /** 1.156 * Main method applicability routine. Given a list of actual types A, 1.157 * a list of formal types F, determines whether the types in A are 1.158 * compatible (by method invocation conversion) with the types in F. 1.159 @@ -678,62 +775,27 @@ 1.160 * 1.161 * A method check handler (see above) is used in order to report errors. 1.162 */ 1.163 - MethodCheck resolveMethodCheck = new MethodCheck() { 1.164 + MethodCheck resolveMethodCheck = new AbstractMethodCheck() { 1.165 + 1.166 + @Override 1.167 + void checkArg(boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) { 1.168 + ResultInfo mresult = methodCheckResult(varargs, formal, deferredAttrContext, warn); 1.169 + mresult.check(null, actual); 1.170 + } 1.171 + 1.172 @Override 1.173 public void argumentsAcceptable(final Env<AttrContext> env, 1.174 DeferredAttrContext deferredAttrContext, 1.175 List<Type> argtypes, 1.176 List<Type> formals, 1.177 Warner warn) { 1.178 + super.argumentsAcceptable(env, deferredAttrContext, argtypes, formals, warn); 1.179 //should we expand formals? 1.180 - boolean useVarargs = deferredAttrContext.phase.isVarargsRequired(); 1.181 - 1.182 - //inference context used during this method check 1.183 - InferenceContext inferenceContext = deferredAttrContext.inferenceContext; 1.184 - 1.185 - Type varargsFormal = useVarargs ? formals.last() : null; 1.186 - 1.187 - if (varargsFormal == null && 1.188 - argtypes.size() != formals.size()) { 1.189 - reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args 1.190 + if (deferredAttrContext.phase.isVarargsRequired()) { 1.191 + //check varargs element type accessibility 1.192 + varargsAccessible(env, types.elemtype(formals.last()), 1.193 + deferredAttrContext.inferenceContext); 1.194 } 1.195 - 1.196 - while (argtypes.nonEmpty() && formals.head != varargsFormal) { 1.197 - ResultInfo mresult = methodCheckResult(false, formals.head, deferredAttrContext, warn); 1.198 - mresult.check(null, argtypes.head); 1.199 - argtypes = argtypes.tail; 1.200 - formals = formals.tail; 1.201 - } 1.202 - 1.203 - if (formals.head != varargsFormal) { 1.204 - reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args 1.205 - } 1.206 - 1.207 - if (useVarargs) { 1.208 - //note: if applicability check is triggered by most specific test, 1.209 - //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5) 1.210 - final Type elt = types.elemtype(varargsFormal); 1.211 - ResultInfo mresult = methodCheckResult(true, elt, deferredAttrContext, warn); 1.212 - while (argtypes.nonEmpty()) { 1.213 - mresult.check(null, argtypes.head); 1.214 - argtypes = argtypes.tail; 1.215 - } 1.216 - //check varargs element type accessibility 1.217 - varargsAccessible(env, elt, inferenceContext); 1.218 - } 1.219 - } 1.220 - 1.221 - private void reportMC(MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) { 1.222 - boolean inferDiag = inferenceContext != infer.emptyContext; 1.223 - InapplicableMethodException ex = inferDiag ? 1.224 - infer.inferenceException : inapplicableMethodException; 1.225 - if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) { 1.226 - Object[] args2 = new Object[args.length + 1]; 1.227 - System.arraycopy(args, 0, args2, 1, args.length); 1.228 - args2[0] = inferenceContext.inferenceVars(); 1.229 - args = args2; 1.230 - } 1.231 - throw ex.setMessage(inferDiag ? diag.inferKey : diag.basicKey, args); 1.232 } 1.233 1.234 private void varargsAccessible(final Env<AttrContext> env, final Type t, final InferenceContext inferenceContext) { 1.235 @@ -765,6 +827,11 @@ 1.236 }; 1.237 return new MethodResultInfo(to, checkContext); 1.238 } 1.239 + 1.240 + @Override 1.241 + public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) { 1.242 + return new MostSpecificCheck(strict, actuals); 1.243 + } 1.244 }; 1.245 1.246 /** 1.247 @@ -1042,6 +1109,11 @@ 1.248 } 1.249 } 1.250 } 1.251 + 1.252 + public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) { 1.253 + Assert.error("Cannot get here!"); 1.254 + return null; 1.255 + } 1.256 } 1.257 1.258 public static class InapplicableMethodException extends RuntimeException { 1.259 @@ -1254,7 +1326,7 @@ 1.260 Assert.check(sym.kind < AMBIGUOUS); 1.261 try { 1.262 Type mt = rawInstantiate(env, site, sym, null, argtypes, typeargtypes, 1.263 - allowBoxing, useVarargs, resolveMethodCheck, types.noWarnings); 1.264 + allowBoxing, useVarargs, types.noWarnings); 1.265 if (!operator) 1.266 currentResolutionContext.addApplicableCandidate(sym, mt); 1.267 } catch (InapplicableMethodException ex) { 1.268 @@ -1358,11 +1430,20 @@ 1.269 int maxLength = Math.max( 1.270 Math.max(m1.type.getParameterTypes().length(), actuals.length()), 1.271 m2.type.getParameterTypes().length()); 1.272 - Type mst = instantiate(env, site, m2, null, 1.273 - adjustArgs(types.lowerBounds(types.memberType(site, m1).getParameterTypes()), m1, maxLength, useVarargs), null, 1.274 - allowBoxing, useVarargs, new MostSpecificCheck(!allowBoxing, actuals), noteWarner); 1.275 - return mst != null && 1.276 - !noteWarner.hasLint(Lint.LintCategory.UNCHECKED); 1.277 + MethodResolutionContext prevResolutionContext = currentResolutionContext; 1.278 + try { 1.279 + currentResolutionContext = new MethodResolutionContext(); 1.280 + currentResolutionContext.step = prevResolutionContext.step; 1.281 + currentResolutionContext.methodCheck = 1.282 + prevResolutionContext.methodCheck.mostSpecificCheck(actuals, !allowBoxing); 1.283 + Type mst = instantiate(env, site, m2, null, 1.284 + adjustArgs(types.lowerBounds(types.memberType(site, m1).getParameterTypes()), m1, maxLength, useVarargs), null, 1.285 + allowBoxing, useVarargs, noteWarner); 1.286 + return mst != null && 1.287 + !noteWarner.hasLint(Lint.LintCategory.UNCHECKED); 1.288 + } finally { 1.289 + currentResolutionContext = prevResolutionContext; 1.290 + } 1.291 } 1.292 private List<Type> adjustArgs(List<Type> args, Symbol msym, int length, boolean allowVarargs) { 1.293 if ((msym.flags() & VARARGS) != 0 && allowVarargs) { 1.294 @@ -2124,14 +2205,14 @@ 1.295 Name name, 1.296 List<Type> argtypes, 1.297 List<Type> typeargtypes) { 1.298 - return lookupMethod(env, pos, env.enclClass.sym, new BasicLookupHelper(name, env.enclClass.sym.type, argtypes, typeargtypes) { 1.299 - @Override 1.300 - Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 1.301 - return findFun(env, name, argtypes, typeargtypes, 1.302 - phase.isBoxingRequired(), 1.303 - phase.isVarargsRequired()); 1.304 - } 1.305 - }); 1.306 + return lookupMethod(env, pos, env.enclClass.sym, resolveMethodCheck, 1.307 + new BasicLookupHelper(name, env.enclClass.sym.type, argtypes, typeargtypes) { 1.308 + @Override 1.309 + Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 1.310 + return findFun(env, name, argtypes, typeargtypes, 1.311 + phase.isBoxingRequired(), 1.312 + phase.isVarargsRequired()); 1.313 + }}); 1.314 } 1.315 1.316 /** Resolve a qualified method identifier 1.317 @@ -2313,36 +2394,36 @@ 1.318 Type site, 1.319 List<Type> argtypes, 1.320 List<Type> typeargtypes) { 1.321 - return lookupMethod(env, pos, site.tsym, new BasicLookupHelper(names.init, site, argtypes, typeargtypes) { 1.322 - @Override 1.323 - Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 1.324 - return findDiamond(env, site, argtypes, typeargtypes, 1.325 - phase.isBoxingRequired(), 1.326 - phase.isVarargsRequired()); 1.327 - } 1.328 - @Override 1.329 - Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) { 1.330 - if (sym.kind >= AMBIGUOUS) { 1.331 - final JCDiagnostic details = sym.kind == WRONG_MTH ? 1.332 - ((InapplicableSymbolError)sym).errCandidate().details : 1.333 - null; 1.334 - sym = new InapplicableSymbolError(sym.kind, "diamondError", currentResolutionContext) { 1.335 - @Override 1.336 - JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, 1.337 - Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { 1.338 - String key = details == null ? 1.339 - "cant.apply.diamond" : 1.340 - "cant.apply.diamond.1"; 1.341 - return diags.create(dkind, log.currentSource(), pos, key, 1.342 - diags.fragment("diamond", site.tsym), details); 1.343 + return lookupMethod(env, pos, site.tsym, resolveMethodCheck, 1.344 + new BasicLookupHelper(names.init, site, argtypes, typeargtypes) { 1.345 + @Override 1.346 + Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { 1.347 + return findDiamond(env, site, argtypes, typeargtypes, 1.348 + phase.isBoxingRequired(), 1.349 + phase.isVarargsRequired()); 1.350 + } 1.351 + @Override 1.352 + Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) { 1.353 + if (sym.kind >= AMBIGUOUS) { 1.354 + final JCDiagnostic details = sym.kind == WRONG_MTH ? 1.355 + ((InapplicableSymbolError)sym).errCandidate().details : 1.356 + null; 1.357 + sym = new InapplicableSymbolError(sym.kind, "diamondError", currentResolutionContext) { 1.358 + @Override 1.359 + JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, 1.360 + Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) { 1.361 + String key = details == null ? 1.362 + "cant.apply.diamond" : 1.363 + "cant.apply.diamond.1"; 1.364 + return diags.create(dkind, log.currentSource(), pos, key, 1.365 + diags.fragment("diamond", site.tsym), details); 1.366 + } 1.367 + }; 1.368 + sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes); 1.369 + env.info.pendingResolutionPhase = currentResolutionContext.step; 1.370 } 1.371 - }; 1.372 - sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes); 1.373 - env.info.pendingResolutionPhase = currentResolutionContext.step; 1.374 - } 1.375 - return sym; 1.376 - } 1.377 - }); 1.378 + return sym; 1.379 + }}); 1.380 } 1.381 1.382 /** This method scans all the constructor symbol in a given class scope - 1.383 @@ -2475,7 +2556,8 @@ 1.384 Type site, 1.385 Name name, List<Type> argtypes, 1.386 List<Type> typeargtypes, 1.387 - boolean boxingAllowed) { 1.388 + boolean boxingAllowed, 1.389 + MethodCheck methodCheck) { 1.390 MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC; 1.391 1.392 ReferenceLookupHelper boundLookupHelper; 1.393 @@ -2495,12 +2577,12 @@ 1.394 1.395 //step 1 - bound lookup 1.396 Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup()); 1.397 - Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, boundLookupHelper); 1.398 + Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, methodCheck, boundLookupHelper); 1.399 1.400 //step 2 - unbound lookup 1.401 ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup(); 1.402 Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup()); 1.403 - Symbol unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym, unboundLookupHelper); 1.404 + Symbol unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym, methodCheck, unboundLookupHelper); 1.405 1.406 //merge results 1.407 Pair<Symbol, ReferenceLookupHelper> res; 1.408 @@ -2671,7 +2753,7 @@ 1.409 ReferenceLookupHelper unboundLookup() { 1.410 if (TreeInfo.isStaticSelector(referenceTree.expr, names) && 1.411 argtypes.nonEmpty() && 1.412 - types.isSubtypeUnchecked(argtypes.head, site)) { 1.413 + (argtypes.head.hasTag(NONE) || types.isSubtypeUnchecked(argtypes.head, site))) { 1.414 return new UnboundMethodReferenceLookupHelper(referenceTree, name, 1.415 site, argtypes, typeargtypes, maxPhase); 1.416 } else { 1.417 @@ -2704,8 +2786,8 @@ 1.418 UnboundMethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site, 1.419 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 1.420 super(referenceTree, name, site, argtypes.tail, typeargtypes, maxPhase); 1.421 - Type asSuperSite = types.asSuper(argtypes.head, site.tsym); 1.422 - if (site.isRaw() && !asSuperSite.isErroneous()) { 1.423 + if (site.isRaw() && !argtypes.head.hasTag(NONE)) { 1.424 + Type asSuperSite = types.asSuper(argtypes.head, site.tsym); 1.425 this.site = asSuperSite; 1.426 } 1.427 } 1.428 @@ -2800,8 +2882,10 @@ 1.429 * at the end of the lookup, the helper is used to validate the results 1.430 * (this last step might trigger overload resolution diagnostics). 1.431 */ 1.432 - Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, LookupHelper lookupHelper) { 1.433 - return lookupMethod(env, pos, location, new MethodResolutionContext(), lookupHelper); 1.434 + Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, MethodCheck methodCheck, LookupHelper lookupHelper) { 1.435 + MethodResolutionContext resolveContext = new MethodResolutionContext(); 1.436 + resolveContext.methodCheck = methodCheck; 1.437 + return lookupMethod(env, pos, location, resolveContext, lookupHelper); 1.438 } 1.439 1.440 Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, 1.441 @@ -3595,6 +3679,8 @@ 1.442 1.443 MethodResolutionPhase step = null; 1.444 1.445 + MethodCheck methodCheck = resolveMethodCheck; 1.446 + 1.447 private boolean internalResolution = false; 1.448 private DeferredAttr.AttrMode attrMode = DeferredAttr.AttrMode.SPECULATIVE; 1.449