diff -r 5e54a59bcee7 -r a23e1dc02698 src/share/classes/com/sun/tools/javac/comp/Resolve.java --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Oct 24 12:45:47 2008 +0100 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Oct 24 12:46:07 2008 +0100 @@ -30,6 +30,7 @@ import com.sun.tools.javac.code.*; import com.sun.tools.javac.jvm.*; import com.sun.tools.javac.tree.*; +import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Symbol.*; @@ -40,6 +41,9 @@ import static com.sun.tools.javac.code.TypeTags.*; import javax.lang.model.element.ElementVisitor; +import java.util.Map; +import java.util.HashMap; + /** Helper class for name resolution, used mostly by the attribution phase. * *

This is NOT part of any API supported by Sun Microsystems. If @@ -1192,15 +1196,23 @@ Name name, List argtypes, List typeargtypes) { - Symbol sym = findFun(env, name, argtypes, typeargtypes, false, env.info.varArgs=false); - if (varargsEnabled && sym.kind >= WRONG_MTHS) { - sym = findFun(env, name, argtypes, typeargtypes, true, false); - if (sym.kind >= WRONG_MTHS) - sym = findFun(env, name, argtypes, typeargtypes, true, env.info.varArgs=true); + Symbol sym = methodNotFound; + List steps = methodResolutionSteps; + while (steps.nonEmpty() && + steps.head.isApplicable(boxingEnabled, varargsEnabled) && + sym.kind >= ERRONEOUS) { + sym = findFun(env, name, argtypes, typeargtypes, + steps.head.isBoxingRequired, + env.info.varArgs = steps.head.isVarargsRequired); + methodResolutionCache.put(steps.head, sym); + steps = steps.tail; } - if (sym.kind >= AMBIGUOUS) { - sym = access( - sym, pos, env.enclClass.sym.type, name, false, argtypes, typeargtypes); + if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error + MethodResolutionPhase errPhase = + firstErroneousResolutionPhase(); + sym = access(methodResolutionCache.get(errPhase), + pos, env.enclClass.sym.type, name, false, argtypes, typeargtypes); + env.info.varArgs = errPhase.isVarargsRequired; } return sym; } @@ -1217,17 +1229,23 @@ Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env env, Type site, Name name, List argtypes, List typeargtypes) { - Symbol sym = findMethod(env, site, name, argtypes, typeargtypes, false, - env.info.varArgs=false, false); - if (varargsEnabled && sym.kind >= WRONG_MTHS) { - sym = findMethod(env, site, name, argtypes, typeargtypes, true, - false, false); - if (sym.kind >= WRONG_MTHS) - sym = findMethod(env, site, name, argtypes, typeargtypes, true, - env.info.varArgs=true, false); + Symbol sym = methodNotFound; + List steps = methodResolutionSteps; + while (steps.nonEmpty() && + steps.head.isApplicable(boxingEnabled, varargsEnabled) && + sym.kind >= ERRONEOUS) { + sym = findMethod(env, site, name, argtypes, typeargtypes, + steps.head.isBoxingRequired(), + env.info.varArgs = steps.head.isVarargsRequired(), false); + methodResolutionCache.put(steps.head, sym); + steps = steps.tail; } - if (sym.kind >= AMBIGUOUS) { - sym = access(sym, pos, site, name, true, argtypes, typeargtypes); + if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error + MethodResolutionPhase errPhase = + firstErroneousResolutionPhase(); + sym = access(methodResolutionCache.get(errPhase), + pos, site, name, true, argtypes, typeargtypes); + env.info.varArgs = errPhase.isVarargsRequired; } return sym; } @@ -1268,14 +1286,22 @@ Type site, List argtypes, List typeargtypes) { - Symbol sym = resolveConstructor(pos, env, site, argtypes, typeargtypes, false, env.info.varArgs=false); - if (varargsEnabled && sym.kind >= WRONG_MTHS) { - sym = resolveConstructor(pos, env, site, argtypes, typeargtypes, true, false); - if (sym.kind >= WRONG_MTHS) - sym = resolveConstructor(pos, env, site, argtypes, typeargtypes, true, env.info.varArgs=true); + Symbol sym = methodNotFound; + List steps = methodResolutionSteps; + while (steps.nonEmpty() && + steps.head.isApplicable(boxingEnabled, varargsEnabled) && + sym.kind >= ERRONEOUS) { + sym = resolveConstructor(pos, env, site, argtypes, typeargtypes, + steps.head.isBoxingRequired(), + env.info.varArgs = steps.head.isVarargsRequired()); + methodResolutionCache.put(steps.head, sym); + steps = steps.tail; } - if (sym.kind >= AMBIGUOUS) { - sym = access(sym, pos, site, names.init, true, argtypes, typeargtypes); + if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error + MethodResolutionPhase errPhase = firstErroneousResolutionPhase(); + sym = access(methodResolutionCache.get(errPhase), + pos, site, names.init, true, argtypes, typeargtypes); + env.info.varArgs = errPhase.isVarargsRequired(); } return sym; } @@ -1733,4 +1759,50 @@ pair.sym2.location(site, types)); } } + + enum MethodResolutionPhase { + BASIC(false, false), + BOX(true, false), + VARARITY(true, true); + + boolean isBoxingRequired; + boolean isVarargsRequired; + + MethodResolutionPhase(boolean isBoxingRequired, boolean isVarargsRequired) { + this.isBoxingRequired = isBoxingRequired; + this.isVarargsRequired = isVarargsRequired; + } + + public boolean isBoxingRequired() { + return isBoxingRequired; + } + + public boolean isVarargsRequired() { + return isVarargsRequired; + } + + public boolean isApplicable(boolean boxingEnabled, boolean varargsEnabled) { + return (varargsEnabled || !isVarargsRequired) && + (boxingEnabled || !isBoxingRequired); + } + } + + private Map methodResolutionCache = + new HashMap(MethodResolutionPhase.values().length); + + final List methodResolutionSteps = List.of(BASIC, BOX, VARARITY); + + private MethodResolutionPhase firstErroneousResolutionPhase() { + MethodResolutionPhase bestSoFar = BASIC; + Symbol sym = methodNotFound; + List steps = methodResolutionSteps; + while (steps.nonEmpty() && + steps.head.isApplicable(boxingEnabled, varargsEnabled) && + sym.kind >= WRONG_MTHS) { + sym = methodResolutionCache.get(steps.head); + bestSoFar = steps.head; + steps = steps.tail; + } + return bestSoFar; + } }