mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-19 04:13:07 +00:00
7132880: Resolve should support nested resolution contexts
Overload resolution routine should be updated so that it can be called recursively Reviewed-by: jjg, dlsmith
This commit is contained in:
parent
45a7449ceb
commit
f01bc46dfe
@ -29,6 +29,7 @@ import com.sun.tools.javac.api.Formattable.LocalizedString;
|
||||
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 com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
|
||||
|
||||
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 @@ public class Resolve {
|
||||
|
||||
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 class Resolve {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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());
|
||||
}
|
||||
|
||||
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);
|
||||
String key = subDiag == null ?
|
||||
"applicable.method.found" :
|
||||
"applicable.method.found.1";
|
||||
|
||||
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);
|
||||
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 @@ public class Resolve {
|
||||
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 @@ public class Resolve {
|
||||
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 @@ public class Resolve {
|
||||
boolean allowBoxing,
|
||||
boolean useVarargs,
|
||||
boolean operator) {
|
||||
verboseResolutionCandidateDiags.clear();
|
||||
Symbol bestSoFar = methodNotFound;
|
||||
bestSoFar = findMethod(env,
|
||||
site,
|
||||
@ -1127,37 +1169,6 @@ public class Resolve {
|
||||
}
|
||||
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 @@ public class Resolve {
|
||||
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 @@ public class Resolve {
|
||||
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;
|
||||
}
|
||||
finally {
|
||||
currentResolutionContext = prevResolutionContext;
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
|
||||
/** Find or create an implicit method of exactly the given type (after erasure).
|
||||
@ -1726,19 +1751,14 @@ public class Resolve {
|
||||
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 @@ public class Resolve {
|
||||
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 @@ public class Resolve {
|
||||
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 @@ public class Resolve {
|
||||
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 @@ public class Resolve {
|
||||
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 @@ public class Resolve {
|
||||
*/
|
||||
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 @@ public class Resolve {
|
||||
* (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 @@ public class Resolve {
|
||||
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 @@ public class Resolve {
|
||||
* (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 @@ public class Resolve {
|
||||
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 @@ public class Resolve {
|
||||
//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 @@ public class Resolve {
|
||||
}
|
||||
}
|
||||
|
||||
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 boolean internalResolution = false;
|
||||
private List<Candidate> candidates = List.nil();
|
||||
|
||||
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;
|
||||
private Map<MethodResolutionPhase, Symbol> resolutionCache =
|
||||
new EnumMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.class);
|
||||
|
||||
private MethodResolutionPhase step = null;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
60
langtools/test/tools/javac/7132880/T7132880.java
Normal file
60
langtools/test/tools/javac/7132880/T7132880.java
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 7132880
|
||||
* @summary Resolve should support nested resolution contexts
|
||||
* @compile/fail/ref=T7132880.out -XDrawDiagnostics T7132880.java
|
||||
*/
|
||||
class Outer {
|
||||
void m1(String s) { }
|
||||
void m2(int i1, int i2) { }
|
||||
|
||||
class Inner {
|
||||
void test() {
|
||||
//ok - no method named 'm' in Inner - hence, class to search is Outer
|
||||
m1("");
|
||||
}
|
||||
}
|
||||
|
||||
class Inner1 {
|
||||
void m1(Integer i) { }
|
||||
|
||||
void test() {
|
||||
//error - Inner1 defines an incompatible method - hence, class to search is Inner1
|
||||
m1("");
|
||||
}
|
||||
}
|
||||
|
||||
class Inner2 {
|
||||
private void m1(Integer i) { }
|
||||
private void m1(Double d) { }
|
||||
|
||||
void test() {
|
||||
//error - Inner2 defines multiple incompatible methods - hence, class to search is Inner2
|
||||
m1("");
|
||||
}
|
||||
}
|
||||
|
||||
class Inner3 {
|
||||
private void m2(Object o, int i) { }
|
||||
private void m2(int i, Object o) { }
|
||||
|
||||
void test() {
|
||||
//error - Inner3 defines multiple ambiguous methods - hence, class to search is Inner3
|
||||
m2(1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
class Inner4 extends Inner2 {
|
||||
void test() {
|
||||
//ok - Inner2 defines multiple incompatible inaccessible methods - hence, class to search is Outer
|
||||
m1("");
|
||||
}
|
||||
}
|
||||
|
||||
class Inner5 extends Inner3 {
|
||||
void test() {
|
||||
//ok - Inner3 defines multiple inaccessible ambiguous methods - hence, class to search is Outer
|
||||
m2(1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
4
langtools/test/tools/javac/7132880/T7132880.out
Normal file
4
langtools/test/tools/javac/7132880/T7132880.out
Normal file
@ -0,0 +1,4 @@
|
||||
T7132880.java:23:12: compiler.err.cant.apply.symbol.1: kindname.method, m1, java.lang.Integer, java.lang.String, kindname.class, Outer.Inner1, (compiler.misc.no.conforming.assignment.exists: java.lang.String, java.lang.Integer)
|
||||
T7132880.java:33:12: compiler.err.cant.apply.symbols: kindname.method, m1, java.lang.String,{(compiler.misc.inapplicable.method: kindname.method, Outer.Inner2, m1(java.lang.Double), (compiler.misc.no.conforming.assignment.exists: java.lang.String, java.lang.Double)),(compiler.misc.inapplicable.method: kindname.method, Outer.Inner2, m1(java.lang.Integer), (compiler.misc.no.conforming.assignment.exists: java.lang.String, java.lang.Integer))}
|
||||
T7132880.java:43:12: compiler.err.ref.ambiguous: m2, kindname.method, m2(java.lang.Object,int), Outer.Inner3, kindname.method, m2(int,java.lang.Object), Outer.Inner3
|
||||
3 errors
|
||||
Loading…
x
Reference in New Issue
Block a user