langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
changeset 1533 6a9a2f681d24
parent 1529 a076d4cd3048
child 1534 e923a41e84cc
equal deleted inserted replaced
1532:ae41c47516e5 1533:6a9a2f681d24
    28 import com.sun.tools.javac.util.*;
    28 import com.sun.tools.javac.util.*;
    29 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    29 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    30 import com.sun.tools.javac.code.*;
    30 import com.sun.tools.javac.code.*;
    31 import com.sun.tools.javac.jvm.*;
    31 import com.sun.tools.javac.jvm.*;
    32 import com.sun.tools.javac.tree.*;
    32 import com.sun.tools.javac.tree.*;
       
    33 import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*;
    33 
    34 
    34 import com.sun.tools.javac.code.Type.*;
    35 import com.sun.tools.javac.code.Type.*;
    35 import com.sun.tools.javac.code.Symbol.*;
    36 import com.sun.tools.javac.code.Symbol.*;
    36 import com.sun.tools.javac.tree.JCTree.*;
    37 import com.sun.tools.javac.tree.JCTree.*;
    37 
    38 
    38 import static com.sun.tools.javac.code.Flags.*;
    39 import static com.sun.tools.javac.code.Flags.*;
    39 import static com.sun.tools.javac.code.Kinds.*;
    40 import static com.sun.tools.javac.code.Kinds.*;
    40 import static com.sun.tools.javac.code.TypeTags.*;
    41 import static com.sun.tools.javac.code.TypeTags.*;
    41 import javax.lang.model.element.ElementVisitor;
    42 import javax.lang.model.element.ElementVisitor;
       
    43 
       
    44 import java.util.Map;
       
    45 import java.util.HashMap;
    42 
    46 
    43 /** Helper class for name resolution, used mostly by the attribution phase.
    47 /** Helper class for name resolution, used mostly by the attribution phase.
    44  *
    48  *
    45  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    49  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
    46  *  you write code that depends on this, you do so at your own risk.
    50  *  you write code that depends on this, you do so at your own risk.
  1190     Symbol resolveMethod(DiagnosticPosition pos,
  1194     Symbol resolveMethod(DiagnosticPosition pos,
  1191                          Env<AttrContext> env,
  1195                          Env<AttrContext> env,
  1192                          Name name,
  1196                          Name name,
  1193                          List<Type> argtypes,
  1197                          List<Type> argtypes,
  1194                          List<Type> typeargtypes) {
  1198                          List<Type> typeargtypes) {
  1195         Symbol sym = findFun(env, name, argtypes, typeargtypes, false, env.info.varArgs=false);
  1199         Symbol sym = methodNotFound;
  1196         if (varargsEnabled && sym.kind >= WRONG_MTHS) {
  1200         List<MethodResolutionPhase> steps = methodResolutionSteps;
  1197             sym = findFun(env, name, argtypes, typeargtypes, true, false);
  1201         while (steps.nonEmpty() &&
  1198             if (sym.kind >= WRONG_MTHS)
  1202                steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
  1199                 sym = findFun(env, name, argtypes, typeargtypes, true, env.info.varArgs=true);
  1203                sym.kind >= ERRONEOUS) {
  1200         }
  1204             sym = findFun(env, name, argtypes, typeargtypes,
  1201         if (sym.kind >= AMBIGUOUS) {
  1205                     steps.head.isBoxingRequired,
  1202             sym = access(
  1206                     env.info.varArgs = steps.head.isVarargsRequired);
  1203                 sym, pos, env.enclClass.sym.type, name, false, argtypes, typeargtypes);
  1207             methodResolutionCache.put(steps.head, sym);
       
  1208             steps = steps.tail;
       
  1209         }
       
  1210         if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error
       
  1211             MethodResolutionPhase errPhase =
       
  1212                     firstErroneousResolutionPhase();
       
  1213             sym = access(methodResolutionCache.get(errPhase),
       
  1214                     pos, env.enclClass.sym.type, name, false, argtypes, typeargtypes);
       
  1215             env.info.varArgs = errPhase.isVarargsRequired;
  1204         }
  1216         }
  1205         return sym;
  1217         return sym;
  1206     }
  1218     }
  1207 
  1219 
  1208     /** Resolve a qualified method identifier
  1220     /** Resolve a qualified method identifier
  1215      *  @param typeargtypes  The types of the invocation's type arguments.
  1227      *  @param typeargtypes  The types of the invocation's type arguments.
  1216      */
  1228      */
  1217     Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env,
  1229     Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env,
  1218                                   Type site, Name name, List<Type> argtypes,
  1230                                   Type site, Name name, List<Type> argtypes,
  1219                                   List<Type> typeargtypes) {
  1231                                   List<Type> typeargtypes) {
  1220         Symbol sym = findMethod(env, site, name, argtypes, typeargtypes, false,
  1232         Symbol sym = methodNotFound;
  1221                                 env.info.varArgs=false, false);
  1233         List<MethodResolutionPhase> steps = methodResolutionSteps;
  1222         if (varargsEnabled && sym.kind >= WRONG_MTHS) {
  1234         while (steps.nonEmpty() &&
  1223             sym = findMethod(env, site, name, argtypes, typeargtypes, true,
  1235                steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
  1224                              false, false);
  1236                sym.kind >= ERRONEOUS) {
  1225             if (sym.kind >= WRONG_MTHS)
  1237             sym = findMethod(env, site, name, argtypes, typeargtypes,
  1226                 sym = findMethod(env, site, name, argtypes, typeargtypes, true,
  1238                     steps.head.isBoxingRequired(),
  1227                                  env.info.varArgs=true, false);
  1239                     env.info.varArgs = steps.head.isVarargsRequired(), false);
  1228         }
  1240             methodResolutionCache.put(steps.head, sym);
  1229         if (sym.kind >= AMBIGUOUS) {
  1241             steps = steps.tail;
  1230             sym = access(sym, pos, site, name, true, argtypes, typeargtypes);
  1242         }
       
  1243         if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error
       
  1244             MethodResolutionPhase errPhase =
       
  1245                     firstErroneousResolutionPhase();
       
  1246             sym = access(methodResolutionCache.get(errPhase),
       
  1247                     pos, site, name, true, argtypes, typeargtypes);
       
  1248             env.info.varArgs = errPhase.isVarargsRequired;
  1231         }
  1249         }
  1232         return sym;
  1250         return sym;
  1233     }
  1251     }
  1234 
  1252 
  1235     /** Resolve a qualified method identifier, throw a fatal error if not
  1253     /** Resolve a qualified method identifier, throw a fatal error if not
  1266     Symbol resolveConstructor(DiagnosticPosition pos,
  1284     Symbol resolveConstructor(DiagnosticPosition pos,
  1267                               Env<AttrContext> env,
  1285                               Env<AttrContext> env,
  1268                               Type site,
  1286                               Type site,
  1269                               List<Type> argtypes,
  1287                               List<Type> argtypes,
  1270                               List<Type> typeargtypes) {
  1288                               List<Type> typeargtypes) {
  1271         Symbol sym = resolveConstructor(pos, env, site, argtypes, typeargtypes, false, env.info.varArgs=false);
  1289         Symbol sym = methodNotFound;
  1272         if (varargsEnabled && sym.kind >= WRONG_MTHS) {
  1290         List<MethodResolutionPhase> steps = methodResolutionSteps;
  1273             sym = resolveConstructor(pos, env, site, argtypes, typeargtypes, true, false);
  1291         while (steps.nonEmpty() &&
  1274             if (sym.kind >= WRONG_MTHS)
  1292                steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
  1275                 sym = resolveConstructor(pos, env, site, argtypes, typeargtypes, true, env.info.varArgs=true);
  1293                sym.kind >= ERRONEOUS) {
  1276         }
  1294             sym = resolveConstructor(pos, env, site, argtypes, typeargtypes,
  1277         if (sym.kind >= AMBIGUOUS) {
  1295                     steps.head.isBoxingRequired(),
  1278             sym = access(sym, pos, site, names.init, true, argtypes, typeargtypes);
  1296                     env.info.varArgs = steps.head.isVarargsRequired());
       
  1297             methodResolutionCache.put(steps.head, sym);
       
  1298             steps = steps.tail;
       
  1299         }
       
  1300         if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error
       
  1301             MethodResolutionPhase errPhase = firstErroneousResolutionPhase();
       
  1302             sym = access(methodResolutionCache.get(errPhase),
       
  1303                     pos, site, names.init, true, argtypes, typeargtypes);
       
  1304             env.info.varArgs = errPhase.isVarargsRequired();
  1279         }
  1305         }
  1280         return sym;
  1306         return sym;
  1281     }
  1307     }
  1282 
  1308 
  1283     /** Resolve constructor.
  1309     /** Resolve constructor.
  1731                       kindName(pair.sym2),
  1757                       kindName(pair.sym2),
  1732                       pair.sym2,
  1758                       pair.sym2,
  1733                       pair.sym2.location(site, types));
  1759                       pair.sym2.location(site, types));
  1734         }
  1760         }
  1735     }
  1761     }
       
  1762 
       
  1763     enum MethodResolutionPhase {
       
  1764         BASIC(false, false),
       
  1765         BOX(true, false),
       
  1766         VARARITY(true, true);
       
  1767 
       
  1768         boolean isBoxingRequired;
       
  1769         boolean isVarargsRequired;
       
  1770 
       
  1771         MethodResolutionPhase(boolean isBoxingRequired, boolean isVarargsRequired) {
       
  1772            this.isBoxingRequired = isBoxingRequired;
       
  1773            this.isVarargsRequired = isVarargsRequired;
       
  1774         }
       
  1775 
       
  1776         public boolean isBoxingRequired() {
       
  1777             return isBoxingRequired;
       
  1778         }
       
  1779 
       
  1780         public boolean isVarargsRequired() {
       
  1781             return isVarargsRequired;
       
  1782         }
       
  1783 
       
  1784         public boolean isApplicable(boolean boxingEnabled, boolean varargsEnabled) {
       
  1785             return (varargsEnabled || !isVarargsRequired) &&
       
  1786                    (boxingEnabled || !isBoxingRequired);
       
  1787         }
       
  1788     }
       
  1789 
       
  1790     private Map<MethodResolutionPhase, Symbol> methodResolutionCache =
       
  1791         new HashMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.values().length);
       
  1792 
       
  1793     final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY);
       
  1794 
       
  1795     private MethodResolutionPhase firstErroneousResolutionPhase() {
       
  1796         MethodResolutionPhase bestSoFar = BASIC;
       
  1797         Symbol sym = methodNotFound;
       
  1798         List<MethodResolutionPhase> steps = methodResolutionSteps;
       
  1799         while (steps.nonEmpty() &&
       
  1800                steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
       
  1801                sym.kind >= WRONG_MTHS) {
       
  1802             sym = methodResolutionCache.get(steps.head);
       
  1803             bestSoFar = steps.head;
       
  1804             steps = steps.tail;
       
  1805         }
       
  1806         return bestSoFar;
       
  1807     }
  1736 }
  1808 }