/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/** Helper class for name resolution, used mostly by the attribution phase.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class Resolve {
public final boolean allowMethodHandles;
private final boolean debugResolve;
return instance;
}
varNotFound = new
wrongMethod = new
wrongMethods = new
methodNotFound = new
typeNotFound = new
}
/** error symbols, which are returned when resolution fails
*/
/* ************************************************************************
* Identifier resolution
*************************************************************************/
/** An environment is "static" if its static level is greater than
* the one of its outer environment
*/
}
/** An environment is an "initializer" if it is a constructor or
* an instance initializer.
*/
return owner.isConstructor() ||
}
/** Is class accessible in given evironment?
* @param env The current environment.
* @param c The class whose accessibility is checked.
*/
return isAccessible(env, c, false);
}
boolean isAccessible = false;
switch ((short)(c.flags() & AccessFlags)) {
case PRIVATE:
c.owner.outermostClass();
break;
case 0:
||
||
// Hack: this case is added since synthesized default constructors
// of anonymous classes should be allowed to access
// classes which would be inaccessible otherwise.
break;
default: // error recovery
case PUBLIC:
isAccessible = true;
break;
case PROTECTED:
||
||
break;
}
}
//where
/** Is given class a subclass of given base class, or an inner class
* of a subclass?
* Return null if no such class exists.
* @param c The class which is the subclass or is contained in it.
* @param base The base class
*/
}
return c != null;
}
return isAccessible(env, t, false);
}
}
/** Is symbol accessible as a member of given type in given evironment?
* @param env The current environment.
* @param site The type of which the tested symbol is regarded
* as a member.
* @param sym The symbol.
*/
}
case PRIVATE:
return
||
&&
case 0:
return
||
&&
&&
&&
case PROTECTED:
return
||
||
||
// OK to select instance method or field from 'super' or type name
// (but type names should be disallowed elsewhere!)
&&
&&
default: // this case includes erroneous combinations as well
}
}
//where
/* `sym' is accessible only if not overridden by
* another symbol which is a member of `site'
* (because, if it is overridden, `sym' is not strictly
* speaking a member of `site'). A polymorphic signature method
* cannot be overridden (e.g. MH.invokeExact(Object[])).
*/
return true;
else {
}
}
//where
/** Is given protected symbol accessible if it is selected from given site
* and the selection takes place in given class?
* @param sym The symbol with protected access
* @param c The class where the access takes place
* @site The type of the qualifier
*/
private
while (c != null &&
// In JLS 2e 6.6.2.1, the subclass restriction applies
// only to instance fields and methods -- types are excluded
// regardless of whether they are declared 'static' or not.
return c != null;
}
/** Try to instantiate the type of a method so that it fits
* given type arguments and argument types. If successful, return
* the method's instantiated type, else return null.
* The instantiation will take into account an additional leading
* formal parameter if the method is an instance method seen as a member
* of an undetermined site In this case, we treat site as an additional
* parameter and the parameters of the class containing the method as
* additional type variables that get instantiated.
*
* @param env The current environment
* @param site The type of which the method is a member.
* @param m The method symbol.
* @param argtypes The invocation's given value arguments.
* @param typeargtypes The invocation's given type arguments.
* @param allowBoxing Allow boxing conversions of arguments.
* @param useVarargs Box trailing arguments into an array for varargs.
*/
Symbol m,
boolean allowBoxing,
boolean useVarargs,
throws Infer.InferenceException {
throw inapplicableMethodException.setMessage();
// tvars is the list of formal type variables for which type arguments
// need to inferred.
}
// This is not a polymorphic method, but typeargs are supplied
// which is fine, see JLS 15.12.2.1
// Check type arguments are within bounds
throw inapplicableMethodException.setMessage("explicit.param.do.not.conform.to.bounds",actuals.head, bounds);
}
}
// find out whether we need to go the slow route via infer
l = l.tail) {
}
if (instNeeded)
return polymorphicSignature ?
(MethodType)mt,
m,
warn);
return mt;
}
/** Same but returns null instead throwing a NoInstanceException
*/
Symbol m,
boolean allowBoxing,
boolean useVarargs,
try {
} catch (InapplicableMethodException ex) {
return null;
}
}
/** Check if a parameter list accepts a list of args.
*/
boolean allowBoxing,
boolean useVarargs,
try {
return true;
} catch (InapplicableMethodException ex) {
return false;
}
}
boolean allowBoxing,
boolean useVarargs,
if (varargsFormal == null &&
}
boolean works = allowBoxing
if (!works)
}
if (useVarargs) {
elt);
}
//check varargs element type accessibility
elt,
location);
}
}
return;
}
// where
this.diagnostic = null;
}
this.diagnostic = null;
return this;
}
return this;
}
return this;
}
this.diagnostic = diag;
return this;
}
return diagnostic;
}
}
/* ***************************************************************************
* Symbol lookup
* the following naming conventions for arguments are used
*
* env is the environment where the symbol was mentioned
* site is the type of which the symbol is a member
* name is the symbol's name
* if no arguments are given
* argtypes are the value arguments, if we search for a method
*
* If no symbol was found, a ResolveError detailing the problem is returned.
****************************************************************************/
/** Find field. Synthetic fields are always skipped.
* @param env The current environment.
* @param site The original type from where the selection takes place.
* @param name The name of the field.
* @param c The class to search for the field. This is always
* a superclass or implemented interface of site's class.
*/
TypeSymbol c) {
}
e = e.next();
}
}
l = l.tail) {
}
return bestSoFar;
}
/** Resolve a field identifier, throw a fatal error if not found.
* @param pos The position to use for error reporting.
* @param env The environment current at the method invocation.
* @param site The type of the qualifying expression, in which
* identifier is searched.
* @param name The identifier's name.
*/
else throw new FatalError(
name));
}
/** Find unqualified variable or field with given name.
* Synthetic fields always skipped.
* @param env The current environment.
* @param name The name of the variable or field.
*/
boolean staticOnly = false;
e = e.next();
? e.sym
: findField(
if (staticOnly &&
return new StaticError(sym);
else
return sym;
}
}
return sym;
return bestSoFar;
}
}
continue;
// invariant: sym.kind == VAR
}
}
else
return bestSoFar;
}
/** Select the best method for a call site among two choices.
* @param env The current environment.
* @param site The original type from where the
* selection takes place.
* @param argtypes The invocation's value arguments,
* @param typeargtypes The invocation's type arguments,
* @param sym Proposed new best match.
* @param bestSoFar Previously found best match.
* @param allowBoxing Allow boxing conversions of arguments.
* @param useVarargs Box trailing arguments into an array for varargs.
*/
@SuppressWarnings("fallthrough")
boolean allowBoxing,
boolean useVarargs,
boolean operator) {
try {
} catch (InapplicableMethodException ex) {
case ABSENT_MTH:
case WRONG_MTH:
case WRONG_MTHS:
default:
return bestSoFar;
}
}
: bestSoFar;
}
? sym
}
/* Return the most specific of the two methods for a call,
* given that both are accessible and applicable.
* @param m1 A new candidate for most specific.
* @param m2 The previous most specific candidate.
* @param env The current environment.
* @param site The original type from where the selection
* takes place.
* @param allowBoxing Allow boxing conversions of arguments.
* @param useVarargs Box trailing arguments into an array for varargs.
*/
boolean allowBoxing,
boolean useVarargs) {
case MTH:
boolean m1SignatureMoreSpecific = signatureMoreSpecific(env, site, m1, m2, allowBoxing, useVarargs);
boolean m2SignatureMoreSpecific = signatureMoreSpecific(env, site, m2, m1, allowBoxing, useVarargs);
// same signature; select (a) the non-bridge method, or
// (b) the one that overrides the other, or (c) the concrete
// one, or (d) merge both abstract signatures
// if one overrides or hides the other, use it
return m1;
return m2;
// both abstract or both concrete
if (!m1Abstract && !m2Abstract)
// check that both signatures have the same erasure
// both abstract, neither overridden; merge throws clause and result type
// Theoretically, this can't happen, but it is possible
// due to error recovery or mixing incompatible class files
}
return this;
else
}
};
return result;
}
if (m1SignatureMoreSpecific) return m1;
if (m2SignatureMoreSpecific) return m2;
case AMBIGUOUS:
if (err1 instanceof AmbiguityError &&
err2 instanceof AmbiguityError &&
else
default:
throw new AssertionError();
}
}
//where
private boolean signatureMoreSpecific(Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean allowBoxing, boolean useVarargs) {
noteWarner.clear();
allowBoxing, false, noteWarner);
}
//where
if (useVarargs &&
//if we are checking a varargs method 'from' against another varargs
//method 'to' (where arity of 'to' < arity of 'from') then expand signature
//of 'to' to 'fit' arity of 'from' (this means adding fake formals to 'to'
//until 'to' signature has the same arity as 'from')
toArgs :
}
} else {
//formal argument list is same as original list where last
//argument (array type) is removed
}
//append varargs element type as last synthetic formal
} else {
return to;
}
}
//where
//if both are generic methods, adjust return type ahead of subtyping check
}
//first use subtyping, then return type substitutability
return mt1;
return mt2;
return mt1;
return mt2;
} else {
return null;
}
}
//where
} else {
}
}
/** Find best qualified method matching given name, type and value
* arguments.
* @param env The current environment.
* @param site The original type from where the selection
* takes place.
* @param name The method's name.
* @param argtypes The method's value arguments.
* @param typeargtypes The method's type arguments
* @param allowBoxing Allow boxing conversions of arguments.
* @param useVarargs Box trailing arguments into an array for varargs.
*/
boolean allowBoxing,
boolean useVarargs,
boolean operator) {
return findMethod(env,
site,
name,
true,
new HashSet<TypeSymbol>());
}
// where
boolean abstractok,
boolean allowBoxing,
boolean useVarargs,
boolean operator,
abstractok = false;
e = e.next()) {
//- System.out.println(" e " + e.sym);
operator);
}
}
break;
//- System.out.println(" - " + bestSoFar);
if (abstractok) {
l.nonEmpty();
l = l.tail) {
}
}
}
return bestSoFar;
}
/** Find unqualified method matching given name, type and value arguments.
* @param env The current environment.
* @param name The method's name.
* @param argtypes The method's value arguments.
* @param typeargtypes The method's type arguments.
* @param allowBoxing Allow boxing conversions of arguments.
* @param useVarargs Box trailing arguments into an array for varargs.
*/
boolean allowBoxing, boolean useVarargs) {
boolean staticOnly = false;
sym = findMethod(
allowBoxing, useVarargs, false);
if (staticOnly &&
else return sym;
}
}
return sym;
allowBoxing, useVarargs, false);
}
}
return bestSoFar;
allowBoxing, useVarargs, false);
}
}
return bestSoFar;
}
/** Load toplevel or member class with given fully qualified name and
* verify that it is accessible.
* @param env The current environment.
* @param name The fully qualified name of the class to be loaded.
*/
try {
throw err;
} catch (CompletionFailure ex) {
return typeNotFound;
}
}
/** Find qualified member type.
* @param env The current environment.
* @param site The original type from where the selection takes
* place.
* @param name The type's name.
* @param c The class to search for the member type. This is
* always a superclass or implemented interface of
* site's class.
*/
TypeSymbol c) {
? e.sym
}
e = e.next();
}
}
l = l.tail) {
}
return bestSoFar;
}
/** Find a global type in given scope and load corresponding class.
* @param env The current environment.
* @param scope The scope in which to look for the type.
* @param name The type's name.
*/
}
return bestSoFar;
}
/** Find an unqualified type symbol.
* @param env The current environment.
* @param name The type's name.
*/
boolean staticOnly = false;
e = e.next()) {
if (staticOnly &&
return e.sym;
}
}
return new StaticError(sym);
staticOnly = true;
}
}
return bestSoFar;
}
/** Find an unqualified identifier which matches a specified kind set.
* @param env The current environment.
* @param name The indentifier's name.
* @param kind Indicates the possible symbol kinds
* (a subset of VAL, TYP, PCK).
*/
}
}
else return bestSoFar;
}
/** Find an identifier in a package which matches a specified kind set.
* @param env The current environment.
* @param name The identifier's name.
* @param kind Indicates the possible symbol kinds
* (a nonempty subset of TYP, PCK).
*/
}
// don't allow programs to use flatnames
}
}
}
/** Find an identifier among the members of a given type `site'.
* @param env The current environment.
* @param site The type containing the symbol to be found.
* @param name The identifier's name.
* @param kind Indicates the possible symbol kinds
* (a subset of VAL, TYP).
*/
}
}
return bestSoFar;
}
/* ***************************************************************************
* Access checking
* The following methods convert ResolveErrors to ErrorSymbols, issuing
* an error message in the process
****************************************************************************/
/** If `sym' is a bad symbol: report error and return errSymbol
* else pass through unchanged,
* additional arguments duplicate what has been used in trying to find the
* symbol (--> flyweight pattern). This improves performance since we
* expect misses to happen frequently.
*
* @param sym The symbol that was found, or a ResolveError.
* @param pos The position to use for error reporting.
* @param site The original type from where the selection took place.
* @param name The symbol's name.
* @param argtypes The invocation's value arguments,
* if we looked for a method.
* @param typeargtypes The invocation's type arguments,
* if we looked for a method.
*/
boolean qualified,
if (!site.isErroneous() &&
}
return sym;
}
/** Same as original access(), but without location.
*/
boolean qualified,
}
/** Same as original access(), but without type arguments and arguments.
*/
boolean qualified) {
else
return sym;
}
/** Same as original access(), but without location, type arguments and arguments.
*/
boolean qualified) {
}
/** Check that sym is not an abstract method.
*/
}
/* ***************************************************************************
* Debugging
****************************************************************************/
/** print all scopes starting with scope s and proceeding outwards.
* used for debugging.
*/
while (s != null) {
}
s = s.next;
}
}
}
}
}
}
/* ***************************************************************************
* Name resolution
* Naming conventions are as for symbol lookup
* Unlike the find... methods these methods will report access errors
****************************************************************************/
/** Resolve an unqualified (non-method) identifier.
* @param pos The position to use for error reporting.
* @param env The environment current at the identifier use.
* @param name The identifier's name.
* @param kind The set of admissible symbol kinds for the identifier.
*/
return access(
}
/** Resolve an unqualified method identifier.
* @param pos The position to use for error reporting.
* @param env The environment current at the method invocation.
* @param name The identifier's name.
* @param argtypes The types of the invocation's value arguments.
* @param typeargtypes The types of the invocation's type arguments.
*/
}
}
return sym;
}
wrongMethod.clear();
return methodNotFound;
}
/** Resolve a qualified method identifier
* @param pos The position to use for error reporting.
* @param env The environment current at the method invocation.
* @param site The type of the qualifying expression, in which
* identifier is searched.
* @param name The identifier's name.
* @param argtypes The types of the invocation's value arguments.
* @param typeargtypes The types of the invocation's type arguments.
*/
}
}
//polymorphic receiver - synthesize new method symbol
}
else {
//if nothing is found return the 'first' error
}
//non-instantiated polymorphic signature - synthesize new method symbol
}
return sym;
}
/** Find or create an implicit method of exactly the given type (after erasure).
* Searches in a side table, not the main scope of the site.
* This emulates the lookup process required by JSR 292 in JVM.
* @param env Attribution environment
* @param site The original type from where the selection takes place.
* @param name The method's name.
* @param spMethod A template for the implicit method, or null.
* @param argtypes The required argument types.
* @param typeargtypes The required type arguments.
*/
e = e.next()) {
m = sym;
break;
}
}
if (m == null) {
// create the desired method
}
return m;
}
/** Resolve a qualified method identifier, throw a fatal error if not
* found.
* @param pos The position to use for error reporting.
* @param env The environment current at the method invocation.
* @param site The type of the qualifying expression, in which
* identifier is searched.
* @param name The identifier's name.
* @param argtypes The types of the invocation's value arguments.
* @param typeargtypes The types of the invocation's type arguments.
*/
else throw new FatalError(
name));
}
/** Resolve constructor.
* @param pos The position to use for error reporting.
* @param env The environment current at the constructor invocation.
* @param site The type of class for which a constructor is searched.
* @param argtypes The types of the constructor invocation's value
* arguments.
* @param typeargtypes The types of the constructor invocation's type
* arguments.
*/
}
}
return sym;
}
/** Resolve constructor using diamond inference.
* @param pos The position to use for error reporting.
* @param env The environment current at the constructor invocation.
* @param site The type of class for which a constructor is searched.
* The scope of this class has been touched in attribution.
* @param argtypes The types of the constructor invocation's value
* arguments.
* @param typeargtypes The types of the constructor invocation's type
* arguments.
*/
}
null;
"cant.apply.diamond" :
"cant.apply.diamond.1";
}
};
}
return sym;
}
/** Resolve constructor.
* @param pos The position to use for error reporting.
* @param env The environment current at the constructor invocation.
* @param site The type of class for which a constructor is searched.
* @param argtypes The types of the constructor invocation's value
* arguments.
* @param typeargtypes The types of the constructor invocation's type
* arguments.
* @param allowBoxing Allow boxing and varargs conversions.
* @param useVarargs Box trailing arguments into an array for varargs.
*/
boolean allowBoxing,
boolean useVarargs) {
useVarargs, false);
return sym;
}
/** Resolve a constructor, throw a fatal error if not found.
* @param pos The position to use for error reporting.
* @param env The environment current at the method invocation.
* @param site The type to be constructed.
* @param argtypes The types of the invocation's value arguments.
* @param typeargtypes The types of the invocation's type arguments.
*/
else throw new FatalError(
}
/** Resolve operator.
* @param pos The position to use for error reporting.
* @param optag The tag of the operation tree.
* @param env The environment current at the operation.
* @param argtypes The types of the operands.
*/
null, false, false, true);
null, true, false, true);
}
/** Resolve operator.
* @param pos The position to use for error reporting.
* @param optag The tag of the operation tree.
* @param env The environment current at the operation.
* @param arg The type of the operand.
*/
}
/** Resolve binary operator.
* @param pos The position to use for error reporting.
* @param optag The tag of the operation tree.
* @param env The environment current at the operation.
* @param left The types of the left operand.
* @param right The types of the right operand.
*/
int optag,
}
/**
* Resolve `c.name' where name == this or name == super.
* @param pos The position to use for error reporting.
* @param env The environment current at the expression.
* @param c The qualifier.
* @param name The identifier's name.
*/
TypeSymbol c,
boolean staticOnly = false;
name, true);
}
}
}
}
/**
* Resolve `c.this' for an enclosing class c that contains the
* named member.
* @param pos The position to use for error reporting.
* @param env The environment current at the expression.
* @param member The member that must be contained in the result.
*/
boolean isSuperCall) {
boolean staticOnly = false;
name, true);
}
}
staticOnly = true;
}
}
}
/**
* Resolve an appropriate implicit this instance for t's container.
* JLS 8.8.5.1 and 15.9.2
*/
}
Type resolveImplicitThis(DiagnosticPosition pos, Env<AttrContext> env, Type t, boolean isSuperCall) {
return thisType;
}
/* ***************************************************************************
* ResolveError classes, indicating error situations when accessing symbols
****************************************************************************/
//used by TransTypes when checking target type of synthetic cast
}
//where
if (d != null) {
}
}
}
/**
* Root class for resolution errors. Subclass of ResolveError
* represent a different kinds of resolution error - as such they must
* specify how they map into concrete compiler diagnostics.
*/
/** The name of the kind of error, for debugging only. */
}
throw new AssertionError();
}
return debugName;
}
public boolean exists() {
return false;
}
/**
* Create an external representation for this erroneous symbol to be
* used during attribution - by default this returns the symbol of a
* brand new error type which stores the original type found
* during resolution.
*
* @param name the name used during resolution
* @param location the location from which the symbol is accessed
*/
}
/**
* Create a diagnostic representing this resolution error.
*
* @param dkind The kind of the diagnostic to be created (e.g error).
* @param pos The position to be used for error reporting.
* @param site The original type from where the selection took place.
* @param name The name of the symbol to be resolved.
* @param argtypes The invocation's value arguments,
* if we looked for a method.
* @param typeargtypes The invocation's type arguments,
* if we looked for a method.
*/
/**
* A name designates an operator if it consists
* of a non-empty sequence of operator symbols +-~!/*%&|^<>=
*/
int i = 0;
while (i < name.getByteLength() &&
}
}
/**
* This class is the root class of all resolution errors caused by
* an invalid symbol being found during resolution.
*/
/** The invalid symbol found during resolution */
}
public boolean exists() {
return true;
}
}
else
return sym;
}
}
/**
* InvalidSymbolError error class indicating that a symbol matching a
* given name does not exists in a given site.
*/
super(kind, "symbol not found error");
}
return null;
if (isOperator(name)) {
"operator.cant.be.applied" :
"operator.cant.be.applied.1";
}
boolean hasLocation = false;
}
"doesnt.exist", location);
}
}
if (hasLocation) {
}
else {
}
}
//where
switch (kindname) {
case METHOD:
case CONSTRUCTOR: {
suffix += ".args";
}
}
}
} else {
site,
null);
}
}
}
/**
* InvalidSymbolError error class indicating that a given symbol
* (either a method, a constructor or an operand) is not applicable
*/
/** An auxiliary explanation set in case of instantiation errors. */
}
/** Update sym and explanation and return this.
*/
return this;
}
/** Update sym and return this.
*/
return this;
}
}
return null;
if (isOperator(name)) {
"operator.cant.be.applied" :
"operator.cant.be.applied.1";
}
else {
}
}
void clear() {
explanation = null;
}
}
}
/**
* ResolveError error class indicating that a set of symbols
* (either methods, constructors or operands) is not applicable
*/
super(WRONG_MTHS, "inapplicable symbols");
}
if (!candidates.isEmpty()) {
log.currentSource(),
pos,
"cant.apply.symbols",
getName(),
argtypes);
} else {
}
}
//where
for (Candidate c : candidates) {
}
}
candidates.add(c);
}
return this;
}
void clear() {
candidates.clear();
}
}
private class Candidate {
}
details);
}
if (o instanceof Candidate) {
return true;
}
return false;
}
boolean isValid() {
}
}
}
/**
* An InvalidSymbolError error class indicating that a symbol is not
* accessible from a given site
*/
}
if (debugResolve)
}
public boolean exists() {
return false;
}
return null;
}
pos, "not.def.access.class.intf.cant.access",
}
}
else {
}
}
}
/**
* InvalidSymbolError error class indicating that an instance member
* has erroneously been accessed from a static context.
*/
}
: sym);
}
}
/**
* InvalidSymbolError error class indicating that a pair of symbols
* (either methods, constructors or operands) are ambiguous
*/
/** The other maximally specific symbol */
}
AmbiguityError pair = this;
while (true) {
else break;
}
}
}
enum MethodResolutionPhase {
BASIC(false, false),
BOX(true, false),
VARARITY(true, true);
boolean isBoxingRequired;
boolean isVarargsRequired;
this.isBoxingRequired = isBoxingRequired;
this.isVarargsRequired = isVarargsRequired;
}
public boolean isBoxingRequired() {
return isBoxingRequired;
}
public boolean isVarargsRequired() {
return isVarargsRequired;
}
return (varargsEnabled || !isVarargsRequired) &&
(boxingEnabled || !isBoxingRequired);
}
}
}
return bestSoFar;
}
}