--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Tue Feb 28 18:04:50 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Mar 02 12:57:04 2012 +0000
@@ -29,6 +29,7 @@
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate;
import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.tree.JCTree.*;
@@ -39,10 +40,9 @@
import java.util.Arrays;
import java.util.Collection;
+import java.util.EnumMap;
import java.util.EnumSet;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
@@ -84,6 +84,58 @@
Scope polymorphicSignatureScope;
+ protected Resolve(Context context) {
+ context.put(resolveKey, this);
+ syms = Symtab.instance(context);
+
+ varNotFound = new
+ SymbolNotFoundError(ABSENT_VAR);
+ wrongMethod = new
+ InapplicableSymbolError();
+ wrongMethods = new
+ InapplicableSymbolsError();
+ methodNotFound = new
+ SymbolNotFoundError(ABSENT_MTH);
+ typeNotFound = new
+ SymbolNotFoundError(ABSENT_TYP);
+
+ names = Names.instance(context);
+ log = Log.instance(context);
+ chk = Check.instance(context);
+ infer = Infer.instance(context);
+ reader = ClassReader.instance(context);
+ treeinfo = TreeInfo.instance(context);
+ types = Types.instance(context);
+ diags = JCDiagnostic.Factory.instance(context);
+ Source source = Source.instance(context);
+ boxingEnabled = source.allowBoxing();
+ varargsEnabled = source.allowVarargs();
+ Options options = Options.instance(context);
+ debugResolve = options.isSet("debugresolve");
+ verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
+ Target target = Target.instance(context);
+ allowMethodHandles = target.hasMethodHandles();
+ polymorphicSignatureScope = new Scope(syms.noSymbol);
+
+ inapplicableMethodException = new InapplicableMethodException(diags);
+ }
+
+ /** error symbols, which are returned when resolution fails
+ */
+ private final SymbolNotFoundError varNotFound;
+ private final InapplicableSymbolError wrongMethod;
+ private final InapplicableSymbolsError wrongMethods;
+ private final SymbolNotFoundError methodNotFound;
+ private final SymbolNotFoundError typeNotFound;
+
+ public static Resolve instance(Context context) {
+ Resolve instance = context.get(resolveKey);
+ if (instance == null)
+ instance = new Resolve(context);
+ return instance;
+ }
+
+ // <editor-fold defaultstate="collapsed" desc="Verbose resolution diagnostics support">
enum VerboseResolutionMode {
SUCCESS("success"),
FAILURE("failure"),
@@ -119,56 +171,74 @@
}
}
- public static Resolve instance(Context context) {
- Resolve instance = context.get(resolveKey);
- if (instance == null)
- instance = new Resolve(context);
- return instance;
+ void reportVerboseResolutionDiagnostic(DiagnosticPosition dpos, Name name, Type site,
+ List<Type> argtypes, List<Type> typeargtypes, Symbol bestSoFar) {
+ boolean success = bestSoFar.kind < ERRONEOUS;
+
+ if (success && !verboseResolutionMode.contains(VerboseResolutionMode.SUCCESS)) {
+ return;
+ } else if (!success && !verboseResolutionMode.contains(VerboseResolutionMode.FAILURE)) {
+ return;
+ }
+
+ if (bestSoFar.name == names.init &&
+ bestSoFar.owner == syms.objectType.tsym &&
+ !verboseResolutionMode.contains(VerboseResolutionMode.OBJECT_INIT)) {
+ return; //skip diags for Object constructor resolution
+ } else if (site == syms.predefClass.type &&
+ !verboseResolutionMode.contains(VerboseResolutionMode.PREDEF)) {
+ return; //skip spurious diags for predef symbols (i.e. operators)
+ } else if (currentResolutionContext.internalResolution &&
+ !verboseResolutionMode.contains(VerboseResolutionMode.INTERNAL)) {
+ return;
+ }
+
+ int pos = 0;
+ int mostSpecificPos = -1;
+ ListBuffer<JCDiagnostic> subDiags = ListBuffer.lb();
+ for (Candidate c : currentResolutionContext.candidates) {
+ if (currentResolutionContext.step != c.step ||
+ (c.isApplicable() && !verboseResolutionMode.contains(VerboseResolutionMode.APPLICABLE)) ||
+ (!c.isApplicable() && !verboseResolutionMode.contains(VerboseResolutionMode.INAPPLICABLE))) {
+ continue;
+ } else {
+ subDiags.append(c.isApplicable() ?
+ getVerboseApplicableCandidateDiag(pos, c.sym, c.mtype) :
+ getVerboseInapplicableCandidateDiag(pos, c.sym, c.details));
+ if (c.sym == bestSoFar)
+ mostSpecificPos = pos;
+ pos++;
+ }
+ }
+ String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1";
+ JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name,
+ site.tsym, mostSpecificPos, currentResolutionContext.step,
+ methodArguments(argtypes), methodArguments(typeargtypes));
+ JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, subDiags.toList());
+ log.report(d);
}
- protected Resolve(Context context) {
- context.put(resolveKey, this);
- syms = Symtab.instance(context);
-
- varNotFound = new
- SymbolNotFoundError(ABSENT_VAR);
- wrongMethod = new
- InapplicableSymbolError(syms.errSymbol);
- wrongMethods = new
- InapplicableSymbolsError(syms.errSymbol);
- methodNotFound = new
- SymbolNotFoundError(ABSENT_MTH);
- typeNotFound = new
- SymbolNotFoundError(ABSENT_TYP);
+ JCDiagnostic getVerboseApplicableCandidateDiag(int pos, Symbol sym, Type inst) {
+ JCDiagnostic subDiag = null;
+ if (inst.getReturnType().tag == FORALL) {
+ Type diagType = types.createMethodTypeWithReturn(inst.asMethodType(),
+ ((ForAll)inst.getReturnType()).qtype);
+ subDiag = diags.fragment("partial.inst.sig", diagType);
+ } else if (sym.type.tag == FORALL) {
+ subDiag = diags.fragment("full.inst.sig", inst.asMethodType());
+ }
- names = Names.instance(context);
- log = Log.instance(context);
- chk = Check.instance(context);
- infer = Infer.instance(context);
- reader = ClassReader.instance(context);
- treeinfo = TreeInfo.instance(context);
- types = Types.instance(context);
- diags = JCDiagnostic.Factory.instance(context);
- Source source = Source.instance(context);
- boxingEnabled = source.allowBoxing();
- varargsEnabled = source.allowVarargs();
- Options options = Options.instance(context);
- debugResolve = options.isSet("debugresolve");
- verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
- Target target = Target.instance(context);
- allowMethodHandles = target.hasMethodHandles();
- polymorphicSignatureScope = new Scope(syms.noSymbol);
+ String key = subDiag == null ?
+ "applicable.method.found" :
+ "applicable.method.found.1";
- inapplicableMethodException = new InapplicableMethodException(diags);
+ return diags.fragment(key, pos, sym, subDiag);
}
- /** error symbols, which are returned when resolution fails
- */
- final SymbolNotFoundError varNotFound;
- final InapplicableSymbolError wrongMethod;
- final InapplicableSymbolsError wrongMethods;
- final SymbolNotFoundError methodNotFound;
- final SymbolNotFoundError typeNotFound;
+ JCDiagnostic getVerboseInapplicableCandidateDiag(int pos, Symbol sym, JCDiagnostic subDiag) {
+ return diags.fragment("not.applicable.method.found", pos, sym, subDiag);
+ }
+ // </editor-fold>
/* ************************************************************************
* Identifier resolution
@@ -804,17 +874,18 @@
try {
Type mt = rawInstantiate(env, site, sym, argtypes, typeargtypes,
allowBoxing, useVarargs, Warner.noWarnings);
- if (!operator) addVerboseApplicableCandidateDiag(sym ,mt);
+ if (!operator)
+ currentResolutionContext.addApplicableCandidate(sym, mt);
} catch (InapplicableMethodException ex) {
- if (!operator) addVerboseInapplicableCandidateDiag(sym, ex.getDiagnostic());
+ if (!operator)
+ currentResolutionContext.addInapplicableCandidate(sym, ex.getDiagnostic());
switch (bestSoFar.kind) {
case ABSENT_MTH:
- return wrongMethod.setWrongSym(sym, ex.getDiagnostic());
+ return wrongMethod;
case WRONG_MTH:
if (operator) return bestSoFar;
- wrongMethods.addCandidate(currentStep, wrongMethod.sym, wrongMethod.explanation);
case WRONG_MTHS:
- return wrongMethods.addCandidate(currentStep, sym, ex.getDiagnostic());
+ return wrongMethods;
default:
return bestSoFar;
}
@@ -823,40 +894,12 @@
return (bestSoFar.kind == ABSENT_MTH)
? new AccessError(env, site, sym)
: bestSoFar;
- }
+ }
return (bestSoFar.kind > AMBIGUOUS)
? sym
: mostSpecific(sym, bestSoFar, env, site,
allowBoxing && operator, useVarargs);
}
- //where
- void addVerboseApplicableCandidateDiag(Symbol sym, Type inst) {
- if (!verboseResolutionMode.contains(VerboseResolutionMode.APPLICABLE))
- return;
-
- JCDiagnostic subDiag = null;
- if (inst.getReturnType().tag == FORALL) {
- Type diagType = types.createMethodTypeWithReturn(inst.asMethodType(),
- ((ForAll)inst.getReturnType()).qtype);
- subDiag = diags.fragment("partial.inst.sig", diagType);
- } else if (sym.type.tag == FORALL) {
- subDiag = diags.fragment("full.inst.sig", inst.asMethodType());
- }
-
- String key = subDiag == null ?
- "applicable.method.found" :
- "applicable.method.found.1";
-
- verboseResolutionCandidateDiags.put(sym,
- diags.fragment(key, verboseResolutionCandidateDiags.size(), sym, subDiag));
- }
-
- void addVerboseInapplicableCandidateDiag(Symbol sym, JCDiagnostic subDiag) {
- if (!verboseResolutionMode.contains(VerboseResolutionMode.INAPPLICABLE))
- return;
- verboseResolutionCandidateDiags.put(sym,
- diags.fragment("not.applicable.method.found", verboseResolutionCandidateDiags.size(), sym, subDiag));
- }
/* Return the most specific of the two methods for a call,
* given that both are accessible and applicable.
@@ -1054,7 +1097,6 @@
boolean allowBoxing,
boolean useVarargs,
boolean operator) {
- verboseResolutionCandidateDiags.clear();
Symbol bestSoFar = methodNotFound;
bestSoFar = findMethod(env,
site,
@@ -1127,37 +1169,6 @@
}
return bestSoFar;
}
- //where
- void reportVerboseResolutionDiagnostic(DiagnosticPosition dpos, Name name, Type site, List<Type> argtypes, List<Type> typeargtypes, Symbol bestSoFar) {
- boolean success = bestSoFar.kind < ERRONEOUS;
-
- if (success && !verboseResolutionMode.contains(VerboseResolutionMode.SUCCESS)) {
- return;
- } else if (!success && !verboseResolutionMode.contains(VerboseResolutionMode.FAILURE)) {
- return;
- }
-
- if (bestSoFar.name == names.init &&
- bestSoFar.owner == syms.objectType.tsym &&
- !verboseResolutionMode.contains(VerboseResolutionMode.OBJECT_INIT)) {
- return; //skip diags for Object constructor resolution
- } else if (site == syms.predefClass.type && !verboseResolutionMode.contains(VerboseResolutionMode.PREDEF)) {
- return; //skip spurious diags for predef symbols (i.e. operators)
- } else if (internalResolution && !verboseResolutionMode.contains(VerboseResolutionMode.INTERNAL)) {
- return;
- }
-
- int pos = 0;
- for (Symbol s : verboseResolutionCandidateDiags.keySet()) {
- if (s == bestSoFar) break;
- pos++;
- }
- String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1";
- JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name, site.tsym, pos, currentStep,
- methodArguments(argtypes), methodArguments(typeargtypes));
- JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, List.from(verboseResolutionCandidateDiags.values().toArray(new JCDiagnostic[verboseResolutionCandidateDiags.size()])));
- log.report(d);
- }
/** Find unqualified method matching given name, type and value arguments.
* @param env The current environment.
@@ -1591,32 +1602,33 @@
Name name,
List<Type> argtypes,
List<Type> typeargtypes) {
- Symbol sym = startResolution();
- List<MethodResolutionPhase> steps = methodResolutionSteps;
- while (steps.nonEmpty() &&
- steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
- sym.kind >= ERRONEOUS) {
- currentStep = steps.head;
- sym = findFun(env, name, argtypes, typeargtypes,
- steps.head.isBoxingRequired,
- env.info.varArgs = steps.head.isVarargsRequired);
- methodResolutionCache.put(steps.head, sym);
- steps = steps.tail;
+ MethodResolutionContext prevResolutionContext = currentResolutionContext;
+ try {
+ currentResolutionContext = new MethodResolutionContext();
+ Symbol sym = methodNotFound;
+ List<MethodResolutionPhase> steps = methodResolutionSteps;
+ while (steps.nonEmpty() &&
+ steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
+ sym.kind >= ERRONEOUS) {
+ currentResolutionContext.step = steps.head;
+ sym = findFun(env, name, argtypes, typeargtypes,
+ steps.head.isBoxingRequired,
+ env.info.varArgs = steps.head.isVarargsRequired);
+ currentResolutionContext.resolutionCache.put(steps.head, sym);
+ steps = steps.tail;
+ }
+ if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error
+ MethodResolutionPhase errPhase =
+ currentResolutionContext.firstErroneousResolutionPhase();
+ sym = access(currentResolutionContext.resolutionCache.get(errPhase),
+ pos, env.enclClass.sym.type, name, false, argtypes, typeargtypes);
+ env.info.varArgs = errPhase.isVarargsRequired;
+ }
+ return sym;
}
- 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;
+ finally {
+ currentResolutionContext = prevResolutionContext;
}
- return sym;
- }
-
- private Symbol startResolution() {
- wrongMethod.clear();
- wrongMethods.clear();
- return methodNotFound;
}
/** Resolve a qualified method identifier
@@ -1636,40 +1648,53 @@
Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env,
Symbol location, Type site, Name name, List<Type> argtypes,
List<Type> typeargtypes) {
- Symbol sym = startResolution();
- List<MethodResolutionPhase> steps = methodResolutionSteps;
- while (steps.nonEmpty() &&
- steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
- sym.kind >= ERRONEOUS) {
- currentStep = steps.head;
- 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) {
- if (site.tsym.isPolymorphicSignatureGeneric()) {
- //polymorphic receiver - synthesize new method symbol
+ return resolveQualifiedMethod(new MethodResolutionContext(), pos, env, location, site, name, argtypes, typeargtypes);
+ }
+ private Symbol resolveQualifiedMethod(MethodResolutionContext resolveContext,
+ DiagnosticPosition pos, Env<AttrContext> env,
+ Symbol location, Type site, Name name, List<Type> argtypes,
+ List<Type> typeargtypes) {
+ MethodResolutionContext prevResolutionContext = currentResolutionContext;
+ try {
+ currentResolutionContext = resolveContext;
+ Symbol sym = methodNotFound;
+ List<MethodResolutionPhase> steps = methodResolutionSteps;
+ while (steps.nonEmpty() &&
+ steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
+ sym.kind >= ERRONEOUS) {
+ currentResolutionContext.step = steps.head;
+ sym = findMethod(env, site, name, argtypes, typeargtypes,
+ steps.head.isBoxingRequired(),
+ env.info.varArgs = steps.head.isVarargsRequired(), false);
+ currentResolutionContext.resolutionCache.put(steps.head, sym);
+ steps = steps.tail;
+ }
+ if (sym.kind >= AMBIGUOUS) {
+ if (site.tsym.isPolymorphicSignatureGeneric()) {
+ //polymorphic receiver - synthesize new method symbol
+ env.info.varArgs = false;
+ sym = findPolymorphicSignatureInstance(env,
+ site, name, null, argtypes);
+ }
+ else {
+ //if nothing is found return the 'first' error
+ MethodResolutionPhase errPhase =
+ currentResolutionContext.firstErroneousResolutionPhase();
+ sym = access(currentResolutionContext.resolutionCache.get(errPhase),
+ pos, location, site, name, true, argtypes, typeargtypes);
+ env.info.varArgs = errPhase.isVarargsRequired;
+ }
+ } else if (allowMethodHandles && sym.isPolymorphicSignatureGeneric()) {
+ //non-instantiated polymorphic signature - synthesize new method symbol
env.info.varArgs = false;
sym = findPolymorphicSignatureInstance(env,
- site, name, null, argtypes);
+ site, name, (MethodSymbol)sym, argtypes);
}
- else {
- //if nothing is found return the 'first' error
- MethodResolutionPhase errPhase =
- firstErroneousResolutionPhase();
- sym = access(methodResolutionCache.get(errPhase),
- pos, location, site, name, true, argtypes, typeargtypes);
- env.info.varArgs = errPhase.isVarargsRequired;
- }
- } else if (allowMethodHandles && sym.isPolymorphicSignatureGeneric()) {
- //non-instantiated polymorphic signature - synthesize new method symbol
- env.info.varArgs = false;
- sym = findPolymorphicSignatureInstance(env,
- site, name, (MethodSymbol)sym, argtypes);
+ return sym;
}
- return sym;
+ finally {
+ currentResolutionContext = prevResolutionContext;
+ }
}
/** Find or create an implicit method of exactly the given type (after erasure).
@@ -1726,19 +1751,14 @@
Type site, Name name,
List<Type> argtypes,
List<Type> typeargtypes) {
- boolean prevInternal = internalResolution;
- try {
- internalResolution = true;
- Symbol sym = resolveQualifiedMethod(
- pos, env, site.tsym, site, name, argtypes, typeargtypes);
- if (sym.kind == MTH) return (MethodSymbol)sym;
- else throw new FatalError(
- diags.fragment("fatal.err.cant.locate.meth",
- name));
- }
- finally {
- internalResolution = prevInternal;
- }
+ MethodResolutionContext resolveContext = new MethodResolutionContext();
+ resolveContext.internalResolution = true;
+ Symbol sym = resolveQualifiedMethod(resolveContext, pos, env, site.tsym,
+ site, name, argtypes, typeargtypes);
+ if (sym.kind == MTH) return (MethodSymbol)sym;
+ else throw new FatalError(
+ diags.fragment("fatal.err.cant.locate.meth",
+ name));
}
/** Resolve constructor.
@@ -1755,25 +1775,40 @@
Type site,
List<Type> argtypes,
List<Type> typeargtypes) {
- Symbol sym = startResolution();
- List<MethodResolutionPhase> steps = methodResolutionSteps;
- while (steps.nonEmpty() &&
- steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
- sym.kind >= ERRONEOUS) {
- currentStep = steps.head;
- sym = resolveConstructor(pos, env, site, argtypes, typeargtypes,
- steps.head.isBoxingRequired(),
- env.info.varArgs = steps.head.isVarargsRequired());
- methodResolutionCache.put(steps.head, sym);
- steps = steps.tail;
+ return resolveConstructor(new MethodResolutionContext(), pos, env, site, argtypes, typeargtypes);
+ }
+ private Symbol resolveConstructor(MethodResolutionContext resolveContext,
+ DiagnosticPosition pos,
+ Env<AttrContext> env,
+ Type site,
+ List<Type> argtypes,
+ List<Type> typeargtypes) {
+ MethodResolutionContext prevResolutionContext = currentResolutionContext;
+ try {
+ currentResolutionContext = resolveContext;
+ Symbol sym = methodNotFound;
+ List<MethodResolutionPhase> steps = methodResolutionSteps;
+ while (steps.nonEmpty() &&
+ steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
+ sym.kind >= ERRONEOUS) {
+ currentResolutionContext.step = steps.head;
+ sym = findConstructor(pos, env, site, argtypes, typeargtypes,
+ steps.head.isBoxingRequired(),
+ env.info.varArgs = steps.head.isVarargsRequired());
+ currentResolutionContext.resolutionCache.put(steps.head, sym);
+ steps = steps.tail;
+ }
+ if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error
+ MethodResolutionPhase errPhase = currentResolutionContext.firstErroneousResolutionPhase();
+ sym = access(currentResolutionContext.resolutionCache.get(errPhase),
+ pos, site, names.init, true, argtypes, typeargtypes);
+ env.info.varArgs = errPhase.isVarargsRequired();
+ }
+ return sym;
}
- 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();
+ finally {
+ currentResolutionContext = prevResolutionContext;
}
- return sym;
}
/** Resolve constructor using diamond inference.
@@ -1791,38 +1826,45 @@
Type site,
List<Type> argtypes,
List<Type> typeargtypes) {
- Symbol sym = startResolution();
- List<MethodResolutionPhase> steps = methodResolutionSteps;
- while (steps.nonEmpty() &&
- steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
- sym.kind >= ERRONEOUS) {
- currentStep = steps.head;
- sym = resolveConstructor(pos, env, site, argtypes, typeargtypes,
- steps.head.isBoxingRequired(),
- env.info.varArgs = steps.head.isVarargsRequired());
- methodResolutionCache.put(steps.head, sym);
- steps = steps.tail;
+ MethodResolutionContext prevResolutionContext = currentResolutionContext;
+ try {
+ currentResolutionContext = new MethodResolutionContext();
+ Symbol sym = methodNotFound;
+ List<MethodResolutionPhase> steps = methodResolutionSteps;
+ while (steps.nonEmpty() &&
+ steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
+ sym.kind >= ERRONEOUS) {
+ currentResolutionContext.step = steps.head;
+ sym = findConstructor(pos, env, site, argtypes, typeargtypes,
+ steps.head.isBoxingRequired(),
+ env.info.varArgs = steps.head.isVarargsRequired());
+ currentResolutionContext.resolutionCache.put(steps.head, sym);
+ steps = steps.tail;
+ }
+ if (sym.kind >= AMBIGUOUS) {
+ final JCDiagnostic details = sym.kind == WRONG_MTH ?
+ currentResolutionContext.candidates.head.details :
+ null;
+ Symbol errSym = new ResolveError(WRONG_MTH, "diamond error") {
+ @Override
+ JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos,
+ Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
+ String key = details == null ?
+ "cant.apply.diamond" :
+ "cant.apply.diamond.1";
+ return diags.create(dkind, log.currentSource(), pos, key,
+ diags.fragment("diamond", site.tsym), details);
+ }
+ };
+ MethodResolutionPhase errPhase = currentResolutionContext.firstErroneousResolutionPhase();
+ sym = access(errSym, pos, site, names.init, true, argtypes, typeargtypes);
+ env.info.varArgs = errPhase.isVarargsRequired();
+ }
+ return sym;
}
- if (sym.kind >= AMBIGUOUS) {
- final JCDiagnostic details = sym.kind == WRONG_MTH ?
- ((InapplicableSymbolError)sym).explanation :
- null;
- Symbol errSym = new ResolveError(WRONG_MTH, "diamond error") {
- @Override
- JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos,
- Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
- String key = details == null ?
- "cant.apply.diamond" :
- "cant.apply.diamond.1";
- return diags.create(dkind, log.currentSource(), pos, key,
- diags.fragment("diamond", site.tsym), details);
- }
- };
- MethodResolutionPhase errPhase = firstErroneousResolutionPhase();
- sym = access(errSym, pos, site, names.init, true, argtypes, typeargtypes);
- env.info.varArgs = errPhase.isVarargsRequired();
+ finally {
+ currentResolutionContext = prevResolutionContext;
}
- return sym;
}
/** Resolve constructor.
@@ -1841,10 +1883,25 @@
List<Type> typeargtypes,
boolean allowBoxing,
boolean useVarargs) {
+ MethodResolutionContext prevResolutionContext = currentResolutionContext;
+ try {
+ currentResolutionContext = new MethodResolutionContext();
+ return findConstructor(pos, env, site, argtypes, typeargtypes, allowBoxing, useVarargs);
+ }
+ finally {
+ currentResolutionContext = prevResolutionContext;
+ }
+ }
+
+ Symbol findConstructor(DiagnosticPosition pos, Env<AttrContext> env,
+ Type site, List<Type> argtypes,
+ List<Type> typeargtypes,
+ boolean allowBoxing,
+ boolean useVarargs) {
Symbol sym = findMethod(env, site,
- names.init, argtypes,
- typeargtypes, allowBoxing,
- useVarargs, false);
+ names.init, argtypes,
+ typeargtypes, allowBoxing,
+ useVarargs, false);
chk.checkDeprecated(pos, env.info.scope.owner, sym);
return sym;
}
@@ -1860,8 +1917,9 @@
Type site,
List<Type> argtypes,
List<Type> typeargtypes) {
- Symbol sym = resolveConstructor(
- pos, env, site, argtypes, typeargtypes);
+ MethodResolutionContext resolveContext = new MethodResolutionContext();
+ resolveContext.internalResolution = true;
+ Symbol sym = resolveConstructor(resolveContext, pos, env, site, argtypes, typeargtypes);
if (sym.kind == MTH) return (MethodSymbol)sym;
else throw new FatalError(
diags.fragment("fatal.err.cant.locate.ctor", site));
@@ -1875,15 +1933,21 @@
*/
Symbol resolveOperator(DiagnosticPosition pos, JCTree.Tag optag,
Env<AttrContext> env, List<Type> argtypes) {
- startResolution();
- Name name = treeinfo.operatorName(optag);
- Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes,
- null, false, false, true);
- if (boxingEnabled && sym.kind >= WRONG_MTHS)
- sym = findMethod(env, syms.predefClass.type, name, argtypes,
- null, true, false, true);
- return access(sym, pos, env.enclClass.sym.type, name,
- false, argtypes, null);
+ MethodResolutionContext prevResolutionContext = currentResolutionContext;
+ try {
+ currentResolutionContext = new MethodResolutionContext();
+ Name name = treeinfo.operatorName(optag);
+ Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes,
+ null, false, false, true);
+ if (boxingEnabled && sym.kind >= WRONG_MTHS)
+ sym = findMethod(env, syms.predefClass.type, name, argtypes,
+ null, true, false, true);
+ return access(sym, pos, env.enclClass.sym.type, name,
+ false, argtypes, null);
+ }
+ finally {
+ currentResolutionContext = prevResolutionContext;
+ }
}
/** Resolve operator.
@@ -2227,34 +2291,24 @@
* (either a method, a constructor or an operand) is not applicable
* given an actual arguments/type argument list.
*/
- class InapplicableSymbolError extends InvalidSymbolError {
+ class InapplicableSymbolError extends ResolveError {
- /** An auxiliary explanation set in case of instantiation errors. */
- JCDiagnostic explanation;
-
- InapplicableSymbolError(Symbol sym) {
- super(WRONG_MTH, sym, "inapplicable symbol error");
+ InapplicableSymbolError() {
+ super(WRONG_MTH, "inapplicable symbol error");
}
- /** Update sym and explanation and return this.
- */
- InapplicableSymbolError setWrongSym(Symbol sym, JCDiagnostic explanation) {
- this.sym = sym;
- if (this.sym == sym && explanation != null)
- this.explanation = explanation; //update the details
- return this;
- }
-
- /** Update sym and return this.
- */
- InapplicableSymbolError setWrongSym(Symbol sym) {
- this.sym = sym;
- return this;
+ protected InapplicableSymbolError(int kind, String debugName) {
+ super(kind, debugName);
}
@Override
public String toString() {
- return super.toString() + " explanation=" + explanation;
+ return super.toString();
+ }
+
+ @Override
+ public boolean exists() {
+ return true;
}
@Override
@@ -2279,27 +2333,40 @@
key, name, first, second);
}
else {
- Symbol ws = sym.asMemberOf(site, types);
+ Candidate c = errCandidate();
+ Symbol ws = c.sym.asMemberOf(site, types);
return diags.create(dkind, log.currentSource(), pos,
- "cant.apply.symbol" + (explanation != null ? ".1" : ""),
+ "cant.apply.symbol" + (c.details != null ? ".1" : ""),
kindName(ws),
ws.name == names.init ? ws.owner.name : ws.name,
methodArguments(ws.type.getParameterTypes()),
methodArguments(argtypes),
kindName(ws.owner),
ws.owner.type,
- explanation);
+ c.details);
}
}
- void clear() {
- explanation = null;
- }
-
@Override
public Symbol access(Name name, TypeSymbol location) {
return types.createErrorType(name, location, syms.errSymbol.type).tsym;
}
+
+ protected boolean shouldReport(Candidate c) {
+ return !c.isApplicable() &&
+ (((c.sym.flags() & VARARGS) != 0 && c.step == VARARITY) ||
+ (c.sym.flags() & VARARGS) == 0 && c.step == (boxingEnabled ? BOX : BASIC));
+ }
+
+ private Candidate errCandidate() {
+ for (Candidate c : currentResolutionContext.candidates) {
+ if (shouldReport(c)) {
+ return c;
+ }
+ }
+ Assert.error();
+ return null;
+ }
}
/**
@@ -2307,11 +2374,9 @@
* (either methods, constructors or operands) is not applicable
* given an actual arguments/type argument list.
*/
- class InapplicableSymbolsError extends ResolveError {
+ class InapplicableSymbolsError extends InapplicableSymbolError {
- private List<Candidate> candidates = List.nil();
-
- InapplicableSymbolsError(Symbol sym) {
+ InapplicableSymbolsError() {
super(WRONG_MTHS, "inapplicable symbols");
}
@@ -2323,7 +2388,7 @@
Name name,
List<Type> argtypes,
List<Type> typeargtypes) {
- if (candidates.nonEmpty()) {
+ if (currentResolutionContext.candidates.nonEmpty()) {
JCDiagnostic err = diags.create(dkind,
log.currentSource(),
pos,
@@ -2341,68 +2406,24 @@
//where
List<JCDiagnostic> candidateDetails(Type site) {
List<JCDiagnostic> details = List.nil();
- for (Candidate c : candidates)
- details = details.prepend(c.getDiagnostic(site));
+ for (Candidate c : currentResolutionContext.candidates) {
+ if (!shouldReport(c)) continue;
+ JCDiagnostic detailDiag = diags.fragment("inapplicable.method",
+ Kinds.kindName(c.sym),
+ c.sym.location(site, types),
+ c.sym.asMemberOf(site, types),
+ c.details);
+ details = details.prepend(detailDiag);
+ }
return details.reverse();
}
- Symbol addCandidate(MethodResolutionPhase currentStep, Symbol sym, JCDiagnostic details) {
- Candidate c = new Candidate(currentStep, sym, details);
- if (c.isValid() && !candidates.contains(c))
- candidates = candidates.append(c);
- return this;
- }
-
- void clear() {
- candidates = List.nil();
- }
-
private Name getName() {
- Symbol sym = candidates.head.sym;
+ Symbol sym = currentResolutionContext.candidates.head.sym;
return sym.name == names.init ?
sym.owner.name :
sym.name;
}
-
- private class Candidate {
-
- final MethodResolutionPhase step;
- final Symbol sym;
- final JCDiagnostic details;
-
- private Candidate(MethodResolutionPhase step, Symbol sym, JCDiagnostic details) {
- this.step = step;
- this.sym = sym;
- this.details = details;
- }
-
- JCDiagnostic getDiagnostic(Type site) {
- return diags.fragment("inapplicable.method",
- Kinds.kindName(sym),
- sym.location(site, types),
- sym.asMemberOf(site, types),
- details);
- }
-
- @Override
- public boolean equals(Object o) {
- if (o instanceof Candidate) {
- Symbol s1 = this.sym;
- Symbol s2 = ((Candidate)o).sym;
- if ((s1 != s2 &&
- (s1.overrides(s2, s1.owner.type.tsym, types, false) ||
- (s2.overrides(s1, s2.owner.type.tsym, types, false)))) ||
- ((s1.isConstructor() || s2.isConstructor()) && s1.owner != s2.owner))
- return true;
- }
- return false;
- }
-
- boolean isValid() {
- return (((sym.flags() & VARARGS) != 0 && step == VARARITY) ||
- (sym.flags() & VARARGS) == 0 && step == (boxingEnabled ? BOX : BASIC));
- }
- }
}
/**
@@ -2563,29 +2584,91 @@
}
}
- private Map<MethodResolutionPhase, Symbol> methodResolutionCache =
- new HashMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.values().length);
-
- private Map<Symbol, JCDiagnostic> verboseResolutionCandidateDiags =
- new LinkedHashMap<Symbol, JCDiagnostic>();
-
final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY);
- private MethodResolutionPhase currentStep = null;
+ /**
+ * A resolution context is used to keep track of intermediate results of
+ * overload resolution, such as list of method that are not applicable
+ * (used to generate more precise diagnostics) and so on. Resolution contexts
+ * can be nested - this means that when each overload resolution routine should
+ * work within the resolution context it created.
+ */
+ class MethodResolutionContext {
+
+ private List<Candidate> candidates = List.nil();
+
+ private Map<MethodResolutionPhase, Symbol> resolutionCache =
+ new EnumMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.class);
+
+ private MethodResolutionPhase step = null;
+
+ private boolean internalResolution = false;
- private boolean internalResolution = false;
+ 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 = resolutionCache.get(steps.head);
+ bestSoFar = steps.head;
+ steps = steps.tail;
+ }
+ return bestSoFar;
+ }
+
+ void addInapplicableCandidate(Symbol sym, JCDiagnostic details) {
+ Candidate c = new Candidate(currentResolutionContext.step, sym, details, null);
+ if (!candidates.contains(c))
+ candidates = candidates.append(c);
+ }
+
+ void addApplicableCandidate(Symbol sym, Type mtype) {
+ Candidate c = new Candidate(currentResolutionContext.step, sym, null, mtype);
+ candidates = candidates.append(c);
+ }
- 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;
+ /**
+ * This class represents an overload resolution candidate. There are two
+ * kinds of candidates: applicable methods and inapplicable methods;
+ * applicable methods have a pointer to the instantiated method type,
+ * while inapplicable candidates contain further details about the
+ * reason why the method has been considered inapplicable.
+ */
+ class Candidate {
+
+ final MethodResolutionPhase step;
+ final Symbol sym;
+ final JCDiagnostic details;
+ final Type mtype;
+
+ private Candidate(MethodResolutionPhase step, Symbol sym, JCDiagnostic details, Type mtype) {
+ this.step = step;
+ this.sym = sym;
+ this.details = details;
+ this.mtype = mtype;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof Candidate) {
+ Symbol s1 = this.sym;
+ Symbol s2 = ((Candidate)o).sym;
+ if ((s1 != s2 &&
+ (s1.overrides(s2, s1.owner.type.tsym, types, false) ||
+ (s2.overrides(s1, s2.owner.type.tsym, types, false)))) ||
+ ((s1.isConstructor() || s2.isConstructor()) && s1.owner != s2.owner))
+ return true;
+ }
+ return false;
+ }
+
+ boolean isApplicable() {
+ return mtype != null;
+ }
}
- return bestSoFar;
}
+
+ MethodResolutionContext currentResolutionContext = null;
}