--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Oct 24 12:45:47 2008 +0100
+++ b/langtools/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.
*
* <p><b>This is NOT part of any API supported by Sun Microsystems. If
@@ -1192,15 +1196,23 @@
Name name,
List<Type> argtypes,
List<Type> 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<MethodResolutionPhase> 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<AttrContext> env,
Type site, Name name, List<Type> argtypes,
List<Type> 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<MethodResolutionPhase> 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<Type> argtypes,
List<Type> 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<MethodResolutionPhase> 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<MethodResolutionPhase, Symbol> methodResolutionCache =
+ new HashMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.values().length);
+
+ final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY);
+
+ private MethodResolutionPhase firstErroneousResolutionPhase() {
+ MethodResolutionPhase bestSoFar = BASIC;
+ Symbol sym = methodNotFound;
+ List<MethodResolutionPhase> 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;
+ }
}