1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Nov 14 13:47:38 2013 -0800 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Nov 15 11:08:12 2013 +0000 1.3 @@ -25,6 +25,7 @@ 1.4 1.5 package com.sun.tools.javac.comp; 1.6 1.7 +import com.sun.source.tree.MemberReferenceTree.ReferenceMode; 1.8 import com.sun.tools.javac.api.Formattable.LocalizedString; 1.9 import com.sun.tools.javac.code.*; 1.10 import com.sun.tools.javac.code.Symbol.*; 1.11 @@ -110,6 +111,9 @@ 1.12 SymbolNotFoundError(ABSENT_VAR); 1.13 methodNotFound = new 1.14 SymbolNotFoundError(ABSENT_MTH); 1.15 + methodWithCorrectStaticnessNotFound = new 1.16 + SymbolNotFoundError(WRONG_STATICNESS, 1.17 + "method found has incorrect staticness"); 1.18 typeNotFound = new 1.19 SymbolNotFoundError(ABSENT_TYP); 1.20 1.21 @@ -144,6 +148,7 @@ 1.22 */ 1.23 private final SymbolNotFoundError varNotFound; 1.24 private final SymbolNotFoundError methodNotFound; 1.25 + private final SymbolNotFoundError methodWithCorrectStaticnessNotFound; 1.26 private final SymbolNotFoundError typeNotFound; 1.27 1.28 public static Resolve instance(Context context) { 1.29 @@ -868,6 +873,12 @@ 1.30 } 1.31 }; 1.32 1.33 + /** 1.34 + * This class handles method reference applicability checks; since during 1.35 + * these checks it's sometime possible to have inference variables on 1.36 + * the actual argument types list, the method applicability check must be 1.37 + * extended so that inference variables are 'opened' as needed. 1.38 + */ 1.39 class MethodReferenceCheck extends AbstractMethodCheck { 1.40 1.41 InferenceContext pendingInferenceContext; 1.42 @@ -2674,6 +2685,97 @@ 1.43 return resolveOperator(pos, optag, env, List.of(left, right)); 1.44 } 1.45 1.46 + Symbol getMemberReference(DiagnosticPosition pos, 1.47 + Env<AttrContext> env, 1.48 + JCMemberReference referenceTree, 1.49 + Type site, 1.50 + Name name) { 1.51 + 1.52 + site = types.capture(site); 1.53 + 1.54 + ReferenceLookupHelper lookupHelper = makeReferenceLookupHelper( 1.55 + referenceTree, site, name, List.<Type>nil(), null, VARARITY); 1.56 + 1.57 + Env<AttrContext> newEnv = env.dup(env.tree, env.info.dup()); 1.58 + Symbol sym = lookupMethod(newEnv, env.tree.pos(), site.tsym, 1.59 + nilMethodCheck, lookupHelper); 1.60 + 1.61 + env.info.pendingResolutionPhase = newEnv.info.pendingResolutionPhase; 1.62 + 1.63 + return sym; 1.64 + } 1.65 + 1.66 + ReferenceLookupHelper makeReferenceLookupHelper(JCMemberReference referenceTree, 1.67 + Type site, 1.68 + Name name, 1.69 + List<Type> argtypes, 1.70 + List<Type> typeargtypes, 1.71 + MethodResolutionPhase maxPhase) { 1.72 + ReferenceLookupHelper result; 1.73 + if (!name.equals(names.init)) { 1.74 + //method reference 1.75 + result = 1.76 + new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase); 1.77 + } else { 1.78 + if (site.hasTag(ARRAY)) { 1.79 + //array constructor reference 1.80 + result = 1.81 + new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); 1.82 + } else { 1.83 + //class constructor reference 1.84 + result = 1.85 + new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); 1.86 + } 1.87 + } 1.88 + return result; 1.89 + } 1.90 + 1.91 + Symbol resolveMemberReferenceByArity(Env<AttrContext> env, 1.92 + JCMemberReference referenceTree, 1.93 + Type site, 1.94 + Name name, 1.95 + List<Type> argtypes, 1.96 + InferenceContext inferenceContext) { 1.97 + 1.98 + boolean isStaticSelector = TreeInfo.isStaticSelector(referenceTree.expr, names); 1.99 + site = types.capture(site); 1.100 + 1.101 + ReferenceLookupHelper boundLookupHelper = makeReferenceLookupHelper( 1.102 + referenceTree, site, name, argtypes, null, VARARITY); 1.103 + //step 1 - bound lookup 1.104 + Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup()); 1.105 + Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, 1.106 + arityMethodCheck, boundLookupHelper); 1.107 + if (isStaticSelector && 1.108 + !name.equals(names.init) && 1.109 + !boundSym.isStatic() && 1.110 + boundSym.kind < ERRONEOUS) { 1.111 + boundSym = methodNotFound; 1.112 + } 1.113 + 1.114 + //step 2 - unbound lookup 1.115 + Symbol unboundSym = methodNotFound; 1.116 + ReferenceLookupHelper unboundLookupHelper = null; 1.117 + Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup()); 1.118 + if (isStaticSelector) { 1.119 + unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext); 1.120 + unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym, 1.121 + arityMethodCheck, unboundLookupHelper); 1.122 + if (unboundSym.isStatic() && 1.123 + unboundSym.kind < ERRONEOUS) { 1.124 + unboundSym = methodNotFound; 1.125 + } 1.126 + } 1.127 + 1.128 + //merge results 1.129 + Symbol bestSym = choose(boundSym, unboundSym); 1.130 + env.info.pendingResolutionPhase = bestSym == unboundSym ? 1.131 + unboundEnv.info.pendingResolutionPhase : 1.132 + boundEnv.info.pendingResolutionPhase; 1.133 + 1.134 + return bestSym; 1.135 + } 1.136 + 1.137 /** 1.138 * Resolution of member references is typically done as a single 1.139 * overload resolution step, where the argument types A are inferred from 1.140 @@ -2700,47 +2802,118 @@ 1.141 * the type T might be dynamically inferred (i.e. if constructor reference 1.142 * has a raw qualifier). 1.143 */ 1.144 - Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(DiagnosticPosition pos, 1.145 - Env<AttrContext> env, 1.146 + Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(Env<AttrContext> env, 1.147 JCMemberReference referenceTree, 1.148 Type site, 1.149 - Name name, List<Type> argtypes, 1.150 + Name name, 1.151 + List<Type> argtypes, 1.152 List<Type> typeargtypes, 1.153 - boolean boxingAllowed, 1.154 MethodCheck methodCheck, 1.155 - InferenceContext inferenceContext) { 1.156 - MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC; 1.157 + InferenceContext inferenceContext, 1.158 + AttrMode mode) { 1.159 1.160 site = types.capture(site); 1.161 - 1.162 - ReferenceLookupHelper boundLookupHelper; 1.163 - if (!name.equals(names.init)) { 1.164 - //method reference 1.165 - boundLookupHelper = 1.166 - new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase); 1.167 - } else if (site.hasTag(ARRAY)) { 1.168 - //array constructor reference 1.169 - boundLookupHelper = 1.170 - new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); 1.171 - } else { 1.172 - //class constructor reference 1.173 - boundLookupHelper = 1.174 - new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); 1.175 - } 1.176 + ReferenceLookupHelper boundLookupHelper = makeReferenceLookupHelper( 1.177 + referenceTree, site, name, argtypes, typeargtypes, VARARITY); 1.178 1.179 //step 1 - bound lookup 1.180 Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup()); 1.181 - Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, methodCheck, boundLookupHelper); 1.182 + Symbol origBoundSym; 1.183 + boolean staticErrorForBound = false; 1.184 + MethodResolutionContext boundSearchResolveContext = new MethodResolutionContext(); 1.185 + boundSearchResolveContext.methodCheck = methodCheck; 1.186 + Symbol boundSym = origBoundSym = lookupMethod(boundEnv, env.tree.pos(), 1.187 + site.tsym, boundSearchResolveContext, boundLookupHelper); 1.188 + SearchResultKind boundSearchResultKind = SearchResultKind.NOT_APPLICABLE_MATCH; 1.189 + boolean isStaticSelector = TreeInfo.isStaticSelector(referenceTree.expr, names); 1.190 + boolean shouldCheckForStaticness = isStaticSelector && 1.191 + referenceTree.getMode() == ReferenceMode.INVOKE; 1.192 + if (boundSym.kind != WRONG_MTHS && boundSym.kind != WRONG_MTH) { 1.193 + if (shouldCheckForStaticness) { 1.194 + if (!boundSym.isStatic()) { 1.195 + staticErrorForBound = true; 1.196 + if (hasAnotherApplicableMethod( 1.197 + boundSearchResolveContext, boundSym, true)) { 1.198 + boundSearchResultKind = SearchResultKind.BAD_MATCH_MORE_SPECIFIC; 1.199 + } else { 1.200 + boundSearchResultKind = SearchResultKind.BAD_MATCH; 1.201 + if (boundSym.kind < ERRONEOUS) { 1.202 + boundSym = methodWithCorrectStaticnessNotFound; 1.203 + } 1.204 + } 1.205 + } else if (boundSym.kind < ERRONEOUS) { 1.206 + boundSearchResultKind = SearchResultKind.GOOD_MATCH; 1.207 + } 1.208 + } 1.209 + } 1.210 1.211 //step 2 - unbound lookup 1.212 - ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext); 1.213 + Symbol origUnboundSym = null; 1.214 + Symbol unboundSym = methodNotFound; 1.215 + ReferenceLookupHelper unboundLookupHelper = null; 1.216 Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup()); 1.217 - Symbol unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym, methodCheck, unboundLookupHelper); 1.218 + SearchResultKind unboundSearchResultKind = SearchResultKind.NOT_APPLICABLE_MATCH; 1.219 + boolean staticErrorForUnbound = false; 1.220 + if (isStaticSelector) { 1.221 + unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext); 1.222 + MethodResolutionContext unboundSearchResolveContext = 1.223 + new MethodResolutionContext(); 1.224 + unboundSearchResolveContext.methodCheck = methodCheck; 1.225 + unboundSym = origUnboundSym = lookupMethod(unboundEnv, env.tree.pos(), 1.226 + site.tsym, unboundSearchResolveContext, unboundLookupHelper); 1.227 + 1.228 + if (unboundSym.kind != WRONG_MTH && unboundSym.kind != WRONG_MTHS) { 1.229 + if (shouldCheckForStaticness) { 1.230 + if (unboundSym.isStatic()) { 1.231 + staticErrorForUnbound = true; 1.232 + if (hasAnotherApplicableMethod( 1.233 + unboundSearchResolveContext, unboundSym, false)) { 1.234 + unboundSearchResultKind = SearchResultKind.BAD_MATCH_MORE_SPECIFIC; 1.235 + } else { 1.236 + unboundSearchResultKind = SearchResultKind.BAD_MATCH; 1.237 + if (unboundSym.kind < ERRONEOUS) { 1.238 + unboundSym = methodWithCorrectStaticnessNotFound; 1.239 + } 1.240 + } 1.241 + } else if (unboundSym.kind < ERRONEOUS) { 1.242 + unboundSearchResultKind = SearchResultKind.GOOD_MATCH; 1.243 + } 1.244 + } 1.245 + } 1.246 + } 1.247 1.248 //merge results 1.249 Pair<Symbol, ReferenceLookupHelper> res; 1.250 Symbol bestSym = choose(boundSym, unboundSym); 1.251 - res = new Pair<Symbol, ReferenceLookupHelper>(bestSym, 1.252 + if (bestSym.kind < ERRONEOUS && (staticErrorForBound || staticErrorForUnbound)) { 1.253 + if (staticErrorForBound) { 1.254 + boundSym = methodWithCorrectStaticnessNotFound; 1.255 + } 1.256 + if (staticErrorForUnbound) { 1.257 + unboundSym = methodWithCorrectStaticnessNotFound; 1.258 + } 1.259 + bestSym = choose(boundSym, unboundSym); 1.260 + } 1.261 + if (bestSym == methodWithCorrectStaticnessNotFound && mode == AttrMode.CHECK) { 1.262 + Symbol symToPrint = origBoundSym; 1.263 + String errorFragmentToPrint = "non-static.cant.be.ref"; 1.264 + if (staticErrorForBound && staticErrorForUnbound) { 1.265 + if (unboundSearchResultKind == SearchResultKind.BAD_MATCH_MORE_SPECIFIC) { 1.266 + symToPrint = origUnboundSym; 1.267 + errorFragmentToPrint = "static.method.in.unbound.lookup"; 1.268 + } 1.269 + } else { 1.270 + if (!staticErrorForBound) { 1.271 + symToPrint = origUnboundSym; 1.272 + errorFragmentToPrint = "static.method.in.unbound.lookup"; 1.273 + } 1.274 + } 1.275 + log.error(referenceTree.expr.pos(), "invalid.mref", 1.276 + Kinds.kindName(referenceTree.getMode()), 1.277 + diags.fragment(errorFragmentToPrint, 1.278 + Kinds.kindName(symToPrint), symToPrint)); 1.279 + } 1.280 + res = new Pair<>(bestSym, 1.281 bestSym == unboundSym ? unboundLookupHelper : boundLookupHelper); 1.282 env.info.pendingResolutionPhase = bestSym == unboundSym ? 1.283 unboundEnv.info.pendingResolutionPhase : 1.284 @@ -2748,18 +2921,42 @@ 1.285 1.286 return res; 1.287 } 1.288 + 1.289 + enum SearchResultKind { 1.290 + GOOD_MATCH, //type I 1.291 + BAD_MATCH_MORE_SPECIFIC, //type II 1.292 + BAD_MATCH, //type III 1.293 + NOT_APPLICABLE_MATCH //type IV 1.294 + } 1.295 + 1.296 + boolean hasAnotherApplicableMethod(MethodResolutionContext resolutionContext, 1.297 + Symbol bestSoFar, boolean staticMth) { 1.298 + for (Candidate c : resolutionContext.candidates) { 1.299 + if (resolutionContext.step != c.step || 1.300 + !c.isApplicable() || 1.301 + c.sym == bestSoFar) { 1.302 + continue; 1.303 + } else { 1.304 + if (c.sym.isStatic() == staticMth) { 1.305 + return true; 1.306 + } 1.307 + } 1.308 + } 1.309 + return false; 1.310 + } 1.311 + 1.312 //where 1.313 - private Symbol choose(Symbol s1, Symbol s2) { 1.314 - if (lookupSuccess(s1) && lookupSuccess(s2)) { 1.315 - return ambiguityError(s1, s2); 1.316 - } else if (lookupSuccess(s1) || 1.317 - (canIgnore(s2) && !canIgnore(s1))) { 1.318 - return s1; 1.319 - } else if (lookupSuccess(s2) || 1.320 - (canIgnore(s1) && !canIgnore(s2))) { 1.321 - return s2; 1.322 + private Symbol choose(Symbol boundSym, Symbol unboundSym) { 1.323 + if (lookupSuccess(boundSym) && lookupSuccess(unboundSym)) { 1.324 + return ambiguityError(boundSym, unboundSym); 1.325 + } else if (lookupSuccess(boundSym) || 1.326 + (canIgnore(unboundSym) && !canIgnore(boundSym))) { 1.327 + return boundSym; 1.328 + } else if (lookupSuccess(unboundSym) || 1.329 + (canIgnore(boundSym) && !canIgnore(unboundSym))) { 1.330 + return unboundSym; 1.331 } else { 1.332 - return s1; 1.333 + return boundSym; 1.334 } 1.335 } 1.336 1.337 @@ -2780,6 +2977,8 @@ 1.338 InapplicableSymbolsError errSyms = 1.339 (InapplicableSymbolsError)s; 1.340 return errSyms.filterCandidates(errSyms.mapCandidates()).isEmpty(); 1.341 + case WRONG_STATICNESS: 1.342 + return false; 1.343 default: 1.344 return false; 1.345 } 1.346 @@ -2894,7 +3093,6 @@ 1.347 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) { 1.348 super(name, site, argtypes, typeargtypes, maxPhase); 1.349 this.referenceTree = referenceTree; 1.350 - 1.351 } 1.352 1.353 /** 1.354 @@ -3324,6 +3522,11 @@ 1.355 return false; 1.356 } 1.357 1.358 + @Override 1.359 + public boolean isStatic() { 1.360 + return false; 1.361 + } 1.362 + 1.363 /** 1.364 * Create an external representation for this erroneous symbol to be 1.365 * used during attribution - by default this returns the symbol of a 1.366 @@ -3398,7 +3601,11 @@ 1.367 class SymbolNotFoundError extends ResolveError { 1.368 1.369 SymbolNotFoundError(int kind) { 1.370 - super(kind, "symbol not found error"); 1.371 + this(kind, "symbol not found error"); 1.372 + } 1.373 + 1.374 + SymbolNotFoundError(int kind, String debugName) { 1.375 + super(kind, debugName); 1.376 } 1.377 1.378 @Override 1.379 @@ -3436,7 +3643,8 @@ 1.380 hasLocation = !location.name.equals(names._this) && 1.381 !location.name.equals(names._super); 1.382 } 1.383 - boolean isConstructor = kind == ABSENT_MTH && name == names.init; 1.384 + boolean isConstructor = (kind == ABSENT_MTH || kind == WRONG_STATICNESS) && 1.385 + name == names.init; 1.386 KindName kindname = isConstructor ? KindName.CONSTRUCTOR : absentKind(kind); 1.387 Name idname = isConstructor ? site.tsym.name : name; 1.388 String errKey = getErrorKey(kindname, typeargtypes.nonEmpty(), hasLocation);