src/share/classes/com/sun/tools/javac/comp/Resolve.java

changeset 2193
d4cbb671de1c
parent 2117
70a301b35e71
child 2219
5bf0af735c61
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Nov 14 13:47:38 2013 -0800
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Nov 15 11:08:12 2013 +0000
     1.3 @@ -25,6 +25,7 @@
     1.4  
     1.5  package com.sun.tools.javac.comp;
     1.6  
     1.7 +import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
     1.8  import com.sun.tools.javac.api.Formattable.LocalizedString;
     1.9  import com.sun.tools.javac.code.*;
    1.10  import com.sun.tools.javac.code.Symbol.*;
    1.11 @@ -110,6 +111,9 @@
    1.12              SymbolNotFoundError(ABSENT_VAR);
    1.13          methodNotFound = new
    1.14              SymbolNotFoundError(ABSENT_MTH);
    1.15 +        methodWithCorrectStaticnessNotFound = new
    1.16 +            SymbolNotFoundError(WRONG_STATICNESS,
    1.17 +                "method found has incorrect staticness");
    1.18          typeNotFound = new
    1.19              SymbolNotFoundError(ABSENT_TYP);
    1.20  
    1.21 @@ -144,6 +148,7 @@
    1.22       */
    1.23      private final SymbolNotFoundError varNotFound;
    1.24      private final SymbolNotFoundError methodNotFound;
    1.25 +    private final SymbolNotFoundError methodWithCorrectStaticnessNotFound;
    1.26      private final SymbolNotFoundError typeNotFound;
    1.27  
    1.28      public static Resolve instance(Context context) {
    1.29 @@ -868,6 +873,12 @@
    1.30          }
    1.31      };
    1.32  
    1.33 +    /**
    1.34 +     * This class handles method reference applicability checks; since during
    1.35 +     * these checks it's sometime possible to have inference variables on
    1.36 +     * the actual argument types list, the method applicability check must be
    1.37 +     * extended so that inference variables are 'opened' as needed.
    1.38 +     */
    1.39      class MethodReferenceCheck extends AbstractMethodCheck {
    1.40  
    1.41          InferenceContext pendingInferenceContext;
    1.42 @@ -2674,6 +2685,97 @@
    1.43          return resolveOperator(pos, optag, env, List.of(left, right));
    1.44      }
    1.45  
    1.46 +    Symbol getMemberReference(DiagnosticPosition pos,
    1.47 +            Env<AttrContext> env,
    1.48 +            JCMemberReference referenceTree,
    1.49 +            Type site,
    1.50 +            Name name) {
    1.51 +
    1.52 +        site = types.capture(site);
    1.53 +
    1.54 +        ReferenceLookupHelper lookupHelper = makeReferenceLookupHelper(
    1.55 +                referenceTree, site, name, List.<Type>nil(), null, VARARITY);
    1.56 +
    1.57 +        Env<AttrContext> newEnv = env.dup(env.tree, env.info.dup());
    1.58 +        Symbol sym = lookupMethod(newEnv, env.tree.pos(), site.tsym,
    1.59 +                nilMethodCheck, lookupHelper);
    1.60 +
    1.61 +        env.info.pendingResolutionPhase = newEnv.info.pendingResolutionPhase;
    1.62 +
    1.63 +        return sym;
    1.64 +    }
    1.65 +
    1.66 +    ReferenceLookupHelper makeReferenceLookupHelper(JCMemberReference referenceTree,
    1.67 +                                  Type site,
    1.68 +                                  Name name,
    1.69 +                                  List<Type> argtypes,
    1.70 +                                  List<Type> typeargtypes,
    1.71 +                                  MethodResolutionPhase maxPhase) {
    1.72 +        ReferenceLookupHelper result;
    1.73 +        if (!name.equals(names.init)) {
    1.74 +            //method reference
    1.75 +            result =
    1.76 +                    new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase);
    1.77 +        } else {
    1.78 +            if (site.hasTag(ARRAY)) {
    1.79 +                //array constructor reference
    1.80 +                result =
    1.81 +                        new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
    1.82 +            } else {
    1.83 +                //class constructor reference
    1.84 +                result =
    1.85 +                        new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
    1.86 +            }
    1.87 +        }
    1.88 +        return result;
    1.89 +    }
    1.90 +
    1.91 +    Symbol resolveMemberReferenceByArity(Env<AttrContext> env,
    1.92 +                                  JCMemberReference referenceTree,
    1.93 +                                  Type site,
    1.94 +                                  Name name,
    1.95 +                                  List<Type> argtypes,
    1.96 +                                  InferenceContext inferenceContext) {
    1.97 +
    1.98 +        boolean isStaticSelector = TreeInfo.isStaticSelector(referenceTree.expr, names);
    1.99 +        site = types.capture(site);
   1.100 +
   1.101 +        ReferenceLookupHelper boundLookupHelper = makeReferenceLookupHelper(
   1.102 +                referenceTree, site, name, argtypes, null, VARARITY);
   1.103 +        //step 1 - bound lookup
   1.104 +        Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup());
   1.105 +        Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym,
   1.106 +                arityMethodCheck, boundLookupHelper);
   1.107 +        if (isStaticSelector &&
   1.108 +            !name.equals(names.init) &&
   1.109 +            !boundSym.isStatic() &&
   1.110 +            boundSym.kind < ERRONEOUS) {
   1.111 +            boundSym = methodNotFound;
   1.112 +        }
   1.113 +
   1.114 +        //step 2 - unbound lookup
   1.115 +        Symbol unboundSym = methodNotFound;
   1.116 +        ReferenceLookupHelper unboundLookupHelper = null;
   1.117 +        Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup());
   1.118 +        if (isStaticSelector) {
   1.119 +            unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext);
   1.120 +            unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym,
   1.121 +                    arityMethodCheck, unboundLookupHelper);
   1.122 +            if (unboundSym.isStatic() &&
   1.123 +                unboundSym.kind < ERRONEOUS) {
   1.124 +                unboundSym = methodNotFound;
   1.125 +            }
   1.126 +        }
   1.127 +
   1.128 +        //merge results
   1.129 +        Symbol bestSym = choose(boundSym, unboundSym);
   1.130 +        env.info.pendingResolutionPhase = bestSym == unboundSym ?
   1.131 +                unboundEnv.info.pendingResolutionPhase :
   1.132 +                boundEnv.info.pendingResolutionPhase;
   1.133 +
   1.134 +        return bestSym;
   1.135 +    }
   1.136 +
   1.137      /**
   1.138       * Resolution of member references is typically done as a single
   1.139       * overload resolution step, where the argument types A are inferred from
   1.140 @@ -2700,47 +2802,118 @@
   1.141       * the type T might be dynamically inferred (i.e. if constructor reference
   1.142       * has a raw qualifier).
   1.143       */
   1.144 -    Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(DiagnosticPosition pos,
   1.145 -                                  Env<AttrContext> env,
   1.146 +    Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(Env<AttrContext> env,
   1.147                                    JCMemberReference referenceTree,
   1.148                                    Type site,
   1.149 -                                  Name name, List<Type> argtypes,
   1.150 +                                  Name name,
   1.151 +                                  List<Type> argtypes,
   1.152                                    List<Type> typeargtypes,
   1.153 -                                  boolean boxingAllowed,
   1.154                                    MethodCheck methodCheck,
   1.155 -                                  InferenceContext inferenceContext) {
   1.156 -        MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC;
   1.157 +                                  InferenceContext inferenceContext,
   1.158 +                                  AttrMode mode) {
   1.159  
   1.160          site = types.capture(site);
   1.161 -
   1.162 -        ReferenceLookupHelper boundLookupHelper;
   1.163 -        if (!name.equals(names.init)) {
   1.164 -            //method reference
   1.165 -            boundLookupHelper =
   1.166 -                    new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase);
   1.167 -        } else if (site.hasTag(ARRAY)) {
   1.168 -            //array constructor reference
   1.169 -            boundLookupHelper =
   1.170 -                    new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
   1.171 -        } else {
   1.172 -            //class constructor reference
   1.173 -            boundLookupHelper =
   1.174 -                    new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
   1.175 -        }
   1.176 +        ReferenceLookupHelper boundLookupHelper = makeReferenceLookupHelper(
   1.177 +                referenceTree, site, name, argtypes, typeargtypes, VARARITY);
   1.178  
   1.179          //step 1 - bound lookup
   1.180          Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup());
   1.181 -        Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, methodCheck, boundLookupHelper);
   1.182 +        Symbol origBoundSym;
   1.183 +        boolean staticErrorForBound = false;
   1.184 +        MethodResolutionContext boundSearchResolveContext = new MethodResolutionContext();
   1.185 +        boundSearchResolveContext.methodCheck = methodCheck;
   1.186 +        Symbol boundSym = origBoundSym = lookupMethod(boundEnv, env.tree.pos(),
   1.187 +                site.tsym, boundSearchResolveContext, boundLookupHelper);
   1.188 +        SearchResultKind boundSearchResultKind = SearchResultKind.NOT_APPLICABLE_MATCH;
   1.189 +        boolean isStaticSelector = TreeInfo.isStaticSelector(referenceTree.expr, names);
   1.190 +        boolean shouldCheckForStaticness = isStaticSelector &&
   1.191 +                referenceTree.getMode() == ReferenceMode.INVOKE;
   1.192 +        if (boundSym.kind != WRONG_MTHS && boundSym.kind != WRONG_MTH) {
   1.193 +            if (shouldCheckForStaticness) {
   1.194 +                if (!boundSym.isStatic()) {
   1.195 +                    staticErrorForBound = true;
   1.196 +                    if (hasAnotherApplicableMethod(
   1.197 +                            boundSearchResolveContext, boundSym, true)) {
   1.198 +                        boundSearchResultKind = SearchResultKind.BAD_MATCH_MORE_SPECIFIC;
   1.199 +                    } else {
   1.200 +                        boundSearchResultKind = SearchResultKind.BAD_MATCH;
   1.201 +                        if (boundSym.kind < ERRONEOUS) {
   1.202 +                            boundSym = methodWithCorrectStaticnessNotFound;
   1.203 +                        }
   1.204 +                    }
   1.205 +                } else if (boundSym.kind < ERRONEOUS) {
   1.206 +                    boundSearchResultKind = SearchResultKind.GOOD_MATCH;
   1.207 +                }
   1.208 +            }
   1.209 +        }
   1.210  
   1.211          //step 2 - unbound lookup
   1.212 -        ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext);
   1.213 +        Symbol origUnboundSym = null;
   1.214 +        Symbol unboundSym = methodNotFound;
   1.215 +        ReferenceLookupHelper unboundLookupHelper = null;
   1.216          Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup());
   1.217 -        Symbol unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym, methodCheck, unboundLookupHelper);
   1.218 +        SearchResultKind unboundSearchResultKind = SearchResultKind.NOT_APPLICABLE_MATCH;
   1.219 +        boolean staticErrorForUnbound = false;
   1.220 +        if (isStaticSelector) {
   1.221 +            unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext);
   1.222 +            MethodResolutionContext unboundSearchResolveContext =
   1.223 +                    new MethodResolutionContext();
   1.224 +            unboundSearchResolveContext.methodCheck = methodCheck;
   1.225 +            unboundSym = origUnboundSym = lookupMethod(unboundEnv, env.tree.pos(),
   1.226 +                    site.tsym, unboundSearchResolveContext, unboundLookupHelper);
   1.227 +
   1.228 +            if (unboundSym.kind != WRONG_MTH && unboundSym.kind != WRONG_MTHS) {
   1.229 +                if (shouldCheckForStaticness) {
   1.230 +                    if (unboundSym.isStatic()) {
   1.231 +                        staticErrorForUnbound = true;
   1.232 +                        if (hasAnotherApplicableMethod(
   1.233 +                                unboundSearchResolveContext, unboundSym, false)) {
   1.234 +                            unboundSearchResultKind = SearchResultKind.BAD_MATCH_MORE_SPECIFIC;
   1.235 +                        } else {
   1.236 +                            unboundSearchResultKind = SearchResultKind.BAD_MATCH;
   1.237 +                            if (unboundSym.kind < ERRONEOUS) {
   1.238 +                                unboundSym = methodWithCorrectStaticnessNotFound;
   1.239 +                            }
   1.240 +                        }
   1.241 +                    } else if (unboundSym.kind < ERRONEOUS) {
   1.242 +                        unboundSearchResultKind = SearchResultKind.GOOD_MATCH;
   1.243 +                    }
   1.244 +                }
   1.245 +            }
   1.246 +        }
   1.247  
   1.248          //merge results
   1.249          Pair<Symbol, ReferenceLookupHelper> res;
   1.250          Symbol bestSym = choose(boundSym, unboundSym);
   1.251 -        res = new Pair<Symbol, ReferenceLookupHelper>(bestSym,
   1.252 +        if (bestSym.kind < ERRONEOUS && (staticErrorForBound || staticErrorForUnbound)) {
   1.253 +            if (staticErrorForBound) {
   1.254 +                boundSym = methodWithCorrectStaticnessNotFound;
   1.255 +            }
   1.256 +            if (staticErrorForUnbound) {
   1.257 +                unboundSym = methodWithCorrectStaticnessNotFound;
   1.258 +            }
   1.259 +            bestSym = choose(boundSym, unboundSym);
   1.260 +        }
   1.261 +        if (bestSym == methodWithCorrectStaticnessNotFound && mode == AttrMode.CHECK) {
   1.262 +            Symbol symToPrint = origBoundSym;
   1.263 +            String errorFragmentToPrint = "non-static.cant.be.ref";
   1.264 +            if (staticErrorForBound && staticErrorForUnbound) {
   1.265 +                if (unboundSearchResultKind == SearchResultKind.BAD_MATCH_MORE_SPECIFIC) {
   1.266 +                    symToPrint = origUnboundSym;
   1.267 +                    errorFragmentToPrint = "static.method.in.unbound.lookup";
   1.268 +                }
   1.269 +            } else {
   1.270 +                if (!staticErrorForBound) {
   1.271 +                    symToPrint = origUnboundSym;
   1.272 +                    errorFragmentToPrint = "static.method.in.unbound.lookup";
   1.273 +                }
   1.274 +            }
   1.275 +            log.error(referenceTree.expr.pos(), "invalid.mref",
   1.276 +                Kinds.kindName(referenceTree.getMode()),
   1.277 +                diags.fragment(errorFragmentToPrint,
   1.278 +                Kinds.kindName(symToPrint), symToPrint));
   1.279 +        }
   1.280 +        res = new Pair<>(bestSym,
   1.281                  bestSym == unboundSym ? unboundLookupHelper : boundLookupHelper);
   1.282          env.info.pendingResolutionPhase = bestSym == unboundSym ?
   1.283                  unboundEnv.info.pendingResolutionPhase :
   1.284 @@ -2748,18 +2921,42 @@
   1.285  
   1.286          return res;
   1.287      }
   1.288 +
   1.289 +    enum SearchResultKind {
   1.290 +        GOOD_MATCH,                 //type I
   1.291 +        BAD_MATCH_MORE_SPECIFIC,    //type II
   1.292 +        BAD_MATCH,                  //type III
   1.293 +        NOT_APPLICABLE_MATCH        //type IV
   1.294 +    }
   1.295 +
   1.296 +    boolean hasAnotherApplicableMethod(MethodResolutionContext resolutionContext,
   1.297 +            Symbol bestSoFar, boolean staticMth) {
   1.298 +        for (Candidate c : resolutionContext.candidates) {
   1.299 +            if (resolutionContext.step != c.step ||
   1.300 +                !c.isApplicable() ||
   1.301 +                c.sym == bestSoFar) {
   1.302 +                continue;
   1.303 +            } else {
   1.304 +                if (c.sym.isStatic() == staticMth) {
   1.305 +                    return true;
   1.306 +                }
   1.307 +            }
   1.308 +        }
   1.309 +        return false;
   1.310 +    }
   1.311 +
   1.312      //where
   1.313 -        private Symbol choose(Symbol s1, Symbol s2) {
   1.314 -            if (lookupSuccess(s1) && lookupSuccess(s2)) {
   1.315 -                return ambiguityError(s1, s2);
   1.316 -            } else if (lookupSuccess(s1) ||
   1.317 -                    (canIgnore(s2) && !canIgnore(s1))) {
   1.318 -                return s1;
   1.319 -            } else if (lookupSuccess(s2) ||
   1.320 -                    (canIgnore(s1) && !canIgnore(s2))) {
   1.321 -                return s2;
   1.322 +        private Symbol choose(Symbol boundSym, Symbol unboundSym) {
   1.323 +            if (lookupSuccess(boundSym) && lookupSuccess(unboundSym)) {
   1.324 +                return ambiguityError(boundSym, unboundSym);
   1.325 +            } else if (lookupSuccess(boundSym) ||
   1.326 +                    (canIgnore(unboundSym) && !canIgnore(boundSym))) {
   1.327 +                return boundSym;
   1.328 +            } else if (lookupSuccess(unboundSym) ||
   1.329 +                    (canIgnore(boundSym) && !canIgnore(unboundSym))) {
   1.330 +                return unboundSym;
   1.331              } else {
   1.332 -                return s1;
   1.333 +                return boundSym;
   1.334              }
   1.335          }
   1.336  
   1.337 @@ -2780,6 +2977,8 @@
   1.338                      InapplicableSymbolsError errSyms =
   1.339                              (InapplicableSymbolsError)s;
   1.340                      return errSyms.filterCandidates(errSyms.mapCandidates()).isEmpty();
   1.341 +                case WRONG_STATICNESS:
   1.342 +                    return false;
   1.343                  default:
   1.344                      return false;
   1.345              }
   1.346 @@ -2894,7 +3093,6 @@
   1.347                  List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
   1.348              super(name, site, argtypes, typeargtypes, maxPhase);
   1.349              this.referenceTree = referenceTree;
   1.350 -
   1.351          }
   1.352  
   1.353          /**
   1.354 @@ -3324,6 +3522,11 @@
   1.355              return false;
   1.356          }
   1.357  
   1.358 +        @Override
   1.359 +        public boolean isStatic() {
   1.360 +            return false;
   1.361 +        }
   1.362 +
   1.363          /**
   1.364           * Create an external representation for this erroneous symbol to be
   1.365           * used during attribution - by default this returns the symbol of a
   1.366 @@ -3398,7 +3601,11 @@
   1.367      class SymbolNotFoundError extends ResolveError {
   1.368  
   1.369          SymbolNotFoundError(int kind) {
   1.370 -            super(kind, "symbol not found error");
   1.371 +            this(kind, "symbol not found error");
   1.372 +        }
   1.373 +
   1.374 +        SymbolNotFoundError(int kind, String debugName) {
   1.375 +            super(kind, debugName);
   1.376          }
   1.377  
   1.378          @Override
   1.379 @@ -3436,7 +3643,8 @@
   1.380                  hasLocation = !location.name.equals(names._this) &&
   1.381                          !location.name.equals(names._super);
   1.382              }
   1.383 -            boolean isConstructor = kind == ABSENT_MTH && name == names.init;
   1.384 +            boolean isConstructor = (kind == ABSENT_MTH || kind == WRONG_STATICNESS) &&
   1.385 +                    name == names.init;
   1.386              KindName kindname = isConstructor ? KindName.CONSTRUCTOR : absentKind(kind);
   1.387              Name idname = isConstructor ? site.tsym.name : name;
   1.388              String errKey = getErrorKey(kindname, typeargtypes.nonEmpty(), hasLocation);

mercurial