resolve.java
来自「是一款用JAVA 编写的编译器 具有很强的编译功能」· Java 代码 · 共 1,519 行 · 第 1/5 页
JAVA
1,519 行
return null; formals = formals.tail; actuals = actuals.tail; } mt = types.subst(pmt.qtype, pmt.tvars, typeargtypes); } else if (mt.tag == FORALL) { ForAll pmt = (ForAll) mt; List<Type> tvars1 = types.newInstances(pmt.tvars); tvars = tvars.appendList(tvars1); mt = types.subst(pmt.qtype, pmt.tvars, tvars1); } // find out whether we need to go the slow route via infer boolean instNeeded = tvars.tail != null/*inlined: tvars.nonEmpty()*/; for (List<Type> l = argtypes; l.tail != null/*inlined: l.nonEmpty()*/ && !instNeeded; l = l.tail) { if (l.head.tag == FORALL) instNeeded = true; } if (instNeeded) return infer.instantiateMethod(tvars, (MethodType)mt, argtypes, allowBoxing, useVarargs, warn); return argumentsAcceptable(argtypes, mt.getParameterTypes(), allowBoxing, useVarargs, warn) ? mt : null; } /** Same but returns null instead throwing a NoInstanceException */ Type instantiate(Env<AttrContext> env, Type site, Symbol m, List<Type> argtypes, List<Type> typeargtypes, boolean allowBoxing, boolean useVarargs, Warner warn) { try { return rawInstantiate(env, site, m, argtypes, typeargtypes, allowBoxing, useVarargs, warn); } catch (Infer.NoInstanceException ex) { return null; } } /** Check if a parameter list accepts a list of args. */ boolean argumentsAcceptable(List<Type> argtypes, List<Type> formals, boolean allowBoxing, boolean useVarargs, Warner warn) { Type varargsFormal = useVarargs ? formals.last() : null; while (argtypes.nonEmpty() && formals.head != varargsFormal) { boolean works = allowBoxing ? types.isConvertible(argtypes.head, formals.head, warn) : types.isSubtypeUnchecked(argtypes.head, formals.head, warn); if (!works) return false; argtypes = argtypes.tail; formals = formals.tail; } if (formals.head != varargsFormal) return false; // not enough args if (!useVarargs) return argtypes.isEmpty(); Type elt = types.elemtype(varargsFormal); while (argtypes.nonEmpty()) { if (!types.isConvertible(argtypes.head, elt, warn)) return false; argtypes = argtypes.tail; } return true; }/* *************************************************************************** * 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. */ Symbol findField(Env<AttrContext> env, Type site, Name name, TypeSymbol c) { Symbol bestSoFar = varNotFound; Symbol sym; Scope.Entry e = c.members().lookup(name); while (e.scope != null) { if (e.sym.kind == VAR && (e.sym.flags_field & SYNTHETIC) == 0) { return isAccessible(env, site, e.sym) ? e.sym : new AccessError(env, site, e.sym); } e = e.next(); } Type st = types.supertype(c.type); if (st != null && st.tag == CLASS) { sym = findField(env, site, name, st.tsym); if (sym.kind < bestSoFar.kind) bestSoFar = sym; } for (List<Type> l = types.interfaces(c.type); bestSoFar.kind != AMBIGUOUS && l.nonEmpty(); l = l.tail) { sym = findField(env, site, name, l.head.tsym); if (bestSoFar.kind < AMBIGUOUS && sym.kind < AMBIGUOUS && sym.owner != bestSoFar.owner) bestSoFar = new AmbiguityError(bestSoFar, sym); else if (sym.kind < bestSoFar.kind) bestSoFar = sym; } 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. */ public VarSymbol resolveInternalField(DiagnosticPosition pos, Env<AttrContext> env, Type site, Name name) { Symbol sym = findField(env, site, name, site.tsym); if (sym.kind == VAR) return (VarSymbol)sym; else throw new FatalError( JCDiagnostic.fragment("fatal.err.cant.locate.field", 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. */ Symbol findVar(Env<AttrContext> env, Name name) { Symbol bestSoFar = varNotFound; Symbol sym; Env<AttrContext> env1 = env; boolean staticOnly = false; while (env1.outer != null) { if (isStatic(env1)) staticOnly = true; Scope.Entry e = env1.info.scope.lookup(name); while (e.scope != null && (e.sym.kind != VAR || (e.sym.flags_field & SYNTHETIC) != 0)) e = e.next(); sym = (e.scope != null) ? e.sym : findField( env1, env1.enclClass.sym.type, name, env1.enclClass.sym); if (sym.exists()) { if (staticOnly && sym.kind == VAR && sym.owner.kind == TYP && (sym.flags() & STATIC) == 0) return new StaticError(sym); else return sym; } else if (sym.kind < bestSoFar.kind) { bestSoFar = sym; } if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true; env1 = env1.outer; } sym = findField(env, syms.predefClass.type, name, syms.predefClass); if (sym.exists()) return sym; if (bestSoFar.exists()) return bestSoFar; Scope.Entry e = env.toplevel.namedImportScope.lookup(name); for (; e.scope != null; e = e.next()) { sym = e.sym; Type origin = e.getOrigin().owner.type; if (sym.kind == VAR) { if (e.sym.owner.type != origin) sym = sym.clone(e.getOrigin().owner); return isAccessible(env, origin, sym) ? sym : new AccessError(env, origin, sym); } } Symbol origin = null; e = env.toplevel.starImportScope.lookup(name); for (; e.scope != null; e = e.next()) { sym = e.sym; if (sym.kind != VAR) continue; // invariant: sym.kind == VAR if (bestSoFar.kind < AMBIGUOUS && sym.owner != bestSoFar.owner) return new AmbiguityError(bestSoFar, sym); else if (bestSoFar.kind >= VAR) { origin = e.getOrigin().owner; bestSoFar = isAccessible(env, origin.type, sym) ? sym : new AccessError(env, origin.type, sym); } } if (bestSoFar.kind == VAR && bestSoFar.owner.type != origin.type) return bestSoFar.clone(origin); else return bestSoFar; } Warner noteWarner = new Warner(); /** 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. */ Symbol selectBest(Env<AttrContext> env, Type site, List<Type> argtypes, List<Type> typeargtypes, Symbol sym, Symbol bestSoFar, boolean allowBoxing, boolean useVarargs, boolean operator) { if (sym.kind == ERR) return bestSoFar; if (!sym.isInheritedIn(site.tsym, types)) return bestSoFar; assert sym.kind < AMBIGUOUS; try { if (rawInstantiate(env, site, sym, argtypes, typeargtypes, allowBoxing, useVarargs, Warner.noWarnings) == null) { // inapplicable switch (bestSoFar.kind) { case ABSENT_MTH: return wrongMethod.setWrongSym(sym); case WRONG_MTH: return wrongMethods; default: return bestSoFar; } } } catch (Infer.NoInstanceException ex) { switch (bestSoFar.kind) { case ABSENT_MTH: return wrongMethod.setWrongSym(sym, ex.getDiagnostic()); case WRONG_MTH: return wrongMethods; default: return bestSoFar; } } if (!isAccessible(env, site, sym)) { return (bestSoFar.kind == ABSENT_MTH) ? new AccessError(env, site, sym) : bestSoFar; } return (bestSoFar.kind > AMBIGUOUS) ? sym : mostSpecific(sym, bestSoFar, env, site, allowBoxing && operator, useVarargs); } /* 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. */ Symbol mostSpecific(Symbol m1, Symbol m2, Env<AttrContext> env, Type site, boolean allowBoxing, boolean useVarargs) { switch (m2.kind) { case MTH: if (m1 == m2) return m1; Type mt1 = types.memberType(site, m1); noteWarner.unchecked = false; boolean m1SignatureMoreSpecific = (instantiate(env, site, m2, types.lowerBoundArgtypes(mt1), null,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?