changeset 1909:edd5b0c398f6

8010922: Cleanup: add support for ad-hoc method check logic 8010923: Avoid redundant speculative attribution
author mcimadamore
date Wed, 27 Mar 2013 17:11:16 +0000
parents 4161bfd68145
children a9c871ba3a24
files src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java src/share/classes/com/sun/tools/javac/comp/Infer.java src/share/classes/com/sun/tools/javac/comp/Resolve.java src/share/classes/com/sun/tools/javac/tree/TreeInfo.java
diffstat 5 files changed, 419 insertions(+), 133 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Tue Mar 26 15:06:13 2013 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Mar 27 17:11:16 2013 +0000
@@ -148,6 +148,7 @@
         varInfo = new ResultInfo(VAR, Type.noType);
         unknownExprInfo = new ResultInfo(VAL, Type.noType);
         unknownTypeInfo = new ResultInfo(TYP, Type.noType);
+        unknownTypeExprInfo = new ResultInfo(Kinds.TYP | Kinds.VAL, Type.noType);
         recoveryInfo = new RecoveryInfo(deferredAttr.emptyDeferredAttrContext);
     }
 
@@ -559,6 +560,7 @@
     final ResultInfo varInfo;
     final ResultInfo unknownExprInfo;
     final ResultInfo unknownTypeInfo;
+    final ResultInfo unknownTypeExprInfo;
     final ResultInfo recoveryInfo;
 
     Type pt() {
@@ -667,7 +669,7 @@
     List<Type> attribArgs(List<JCExpression> trees, Env<AttrContext> env) {
         ListBuffer<Type> argtypes = new ListBuffer<Type>();
         for (JCExpression arg : trees) {
-            Type argtype = allowPoly && TreeInfo.isPoly(arg, env.tree) ?
+            Type argtype = allowPoly && deferredAttr.isDeferred(env, arg) ?
                     deferredAttr.new DeferredType(arg, env) :
                     chk.checkNonVoid(arg, attribExpr(arg, env, Infer.anyPoly));
             argtypes.append(argtype);
@@ -1410,7 +1412,7 @@
     public void visitConditional(JCConditional tree) {
         Type condtype = attribExpr(tree.cond, env, syms.booleanType);
 
-        tree.polyKind = (!allowPoly ||
+        tree.polyKind = (!allowPoly ||                
                 pt().hasTag(NONE) && pt() != Type.recoveryType ||
                 isBooleanOrNumeric(env, tree)) ?
                 PolyKind.STANDALONE : PolyKind.POLY;
@@ -2626,8 +2628,9 @@
             setFunctionalInfo(that, pt(), desc, target, resultInfo.checkContext.inferenceContext());
             List<Type> argtypes = desc.getParameterTypes();
 
-            Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = rs.resolveMemberReference(that.pos(), localEnv, that,
-                    that.expr.type, that.name, argtypes, typeargtypes, true);
+            Pair<Symbol, Resolve.ReferenceLookupHelper> refResult =
+                    rs.resolveMemberReference(that.pos(), localEnv, that,
+                        that.expr.type, that.name, argtypes, typeargtypes, true, rs.resolveMethodCheck);
 
             Symbol refSym = refResult.fst;
             Resolve.ReferenceLookupHelper lookupHelper = refResult.snd;
@@ -2984,7 +2987,8 @@
         Env<AttrContext> localEnv = env.dup(tree);
         //should we propagate the target type?
         final ResultInfo castInfo;
-        final boolean isPoly = TreeInfo.isPoly(tree.expr, tree);
+        JCExpression expr = TreeInfo.skipParens(tree.expr);
+        boolean isPoly = expr.hasTag(LAMBDA) || expr.hasTag(REFERENCE);
         if (isPoly) {
             //expression is a poly - we need to propagate target type info
             castInfo = new ResultInfo(VAL, clazztype, new Check.NestedCheckContext(resultInfo.checkContext) {
--- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Tue Mar 26 15:06:13 2013 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Wed Mar 27 17:11:16 2013 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
 import com.sun.tools.javac.comp.Attr.ResultInfo;
@@ -284,7 +285,7 @@
             public boolean accepts(final JCDiagnostic t) {
                 class PosScanner extends TreeScanner {
                     boolean found = false;
-                    
+
                     @Override
                     public void scan(JCTree tree) {
                         if (tree != null &&
@@ -531,12 +532,13 @@
                             attr.memberReferenceQualifierResult(tree));
                     ListBuffer<Type> argtypes = ListBuffer.lb();
                     for (Type t : types.findDescriptorType(pt).getParameterTypes()) {
-                        argtypes.append(syms.errType);
+                        argtypes.append(Type.noType);
                     }
                     JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
                     mref2.expr = exprTree;
                     Pair<Symbol, ?> lookupRes =
-                            rs.resolveMemberReference(tree, env, mref2, exprTree.type, tree.name, argtypes.toList(), null, true);
+                            rs.resolveMemberReference(tree, env, mref2, exprTree.type,
+                                tree.name, argtypes.toList(), null, true, rs.arityMethodCheck);
                     switch (lookupRes.fst.kind) {
                         //note: as argtypes are erroneous types, type-errors must
                         //have been caused by arity mismatch
@@ -798,4 +800,216 @@
             }
         }
     }
+    
+    /**
+     * Does the argument expression {@code arg} need speculative type-checking?
+     */
+    boolean isDeferred(Env<AttrContext> env, JCExpression expr) {
+        DeferredChecker dc = new DeferredChecker(env);
+        dc.scan(expr);
+        return dc.result.isPoly();
+    }
+
+    /**
+     * The kind of an argument expression. This is used by the analysis that
+     * determines as to whether speculative attribution is necessary.
+     */
+    enum ArgumentExpressionKind {
+        
+        /** kind that denotes poly argument expression */
+        POLY,
+        /** kind that denotes a standalone expression */
+        NO_POLY,
+        /** kind that denotes a primitive/boxed standalone expression */
+        PRIMITIVE;
+
+        /**
+         * Does this kind denote a poly argument expression
+         */
+        public final boolean isPoly() {
+            return this == POLY;
+        }
+        
+        /**
+         * Does this kind denote a primitive standalone expression
+         */
+        public final boolean isPrimitive() {
+            return this == PRIMITIVE;
+        }
+        
+        /**
+         * Compute the kind of a standalone expression of a given type
+         */
+        static ArgumentExpressionKind standaloneKind(Type type, Types types) {
+            return types.unboxedTypeOrType(type).isPrimitive() ?
+                    ArgumentExpressionKind.PRIMITIVE :
+                    ArgumentExpressionKind.NO_POLY;
+        }
+        
+        /**
+         * Compute the kind of a method argument expression given its symbol
+         */
+        static ArgumentExpressionKind methodKind(Symbol sym, Types types) {
+            Type restype = sym.type.getReturnType();
+            if (sym.type.hasTag(FORALL) &&
+                    restype.containsAny(((ForAll)sym.type).tvars)) {
+                return ArgumentExpressionKind.POLY;
+            } else {
+                return ArgumentExpressionKind.standaloneKind(restype, types);
+            }
+        }
+    }
+    
+    /**
+     * Tree scanner used for checking as to whether an argument expression
+     * requires speculative attribution
+     */
+    final class DeferredChecker extends FilterScanner {
+        
+        Env<AttrContext> env;
+        ArgumentExpressionKind result;
+
+        public DeferredChecker(Env<AttrContext> env) {
+            super(EnumSet.of(LAMBDA, REFERENCE, PARENS, TYPECAST, CONDEXPR,
+                    NEWCLASS, APPLY, LITERAL));
+            this.env = env;
+        }
+
+        @Override
+        public void visitLambda(JCLambda tree) {
+            //a lambda is always a poly expression
+            result = ArgumentExpressionKind.POLY;
+        }
+
+        @Override
+        public void visitReference(JCMemberReference tree) {
+            //a method reference is always a poly expression
+            result = ArgumentExpressionKind.POLY;
+        }
+
+        @Override
+        public void visitTypeCast(JCTypeCast tree) {
+            //a cast is always a standalone expression
+            result = ArgumentExpressionKind.NO_POLY;
+        }
+
+        @Override
+        public void visitConditional(JCConditional tree) {
+            scan(tree.truepart);
+            if (!result.isPrimitive()) {
+                result = ArgumentExpressionKind.POLY;
+                return;
+            }
+            scan(tree.falsepart);
+            result = reduce(ArgumentExpressionKind.PRIMITIVE);
+        }
+
+        @Override
+        public void visitNewClass(JCNewClass tree) {
+            result = (TreeInfo.isDiamond(tree) || attr.findDiamonds) ?
+                    ArgumentExpressionKind.POLY : ArgumentExpressionKind.NO_POLY;
+        }
+
+        @Override
+        public void visitApply(JCMethodInvocation tree) {
+            Name name = TreeInfo.name(tree.meth);
+
+            //fast path
+            if (tree.typeargs.nonEmpty() ||
+                    name == name.table.names._this ||
+                    name == name.table.names._super) {
+                result = ArgumentExpressionKind.NO_POLY;
+                return;
+            } 
+
+            //slow path
+            final JCExpression rec = tree.meth.hasTag(SELECT) ?
+                    ((JCFieldAccess)tree.meth).selected :
+                    null;
+
+            if (rec != null && !isSimpleReceiver(rec)) {
+                //give up if receiver is too complex (to cut down analysis time)
+                result = ArgumentExpressionKind.POLY;
+                return;
+            }
+
+            Type site = rec != null ?
+                    attribSpeculative(rec, env, attr.unknownTypeExprInfo).type :
+                    env.enclClass.sym.type;
+
+            ListBuffer<Type> args = ListBuffer.lb();
+            for (int i = 0; i < tree.args.length(); i ++) {
+                args.append(Type.noType);
+            }
+
+            Resolve.LookupHelper lh = rs.new LookupHelper(name, site, args.toList(), List.<Type>nil(), MethodResolutionPhase.VARARITY) {
+                @Override
+                Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+                    return rec == null ?
+                        rs.findFun(env, name, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) :
+                        rs.findMethod(env, site, name, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired(), false);
+                }
+                @Override
+                Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
+                    return sym;
+                }
+            };
+
+            Symbol sym = rs.lookupMethod(env, tree, site.tsym, rs.arityMethodCheck, lh);
+
+            if (sym.kind == Kinds.AMBIGUOUS) {
+                Resolve.AmbiguityError err = (Resolve.AmbiguityError)sym;
+                result = ArgumentExpressionKind.PRIMITIVE;
+                for (List<Symbol> ambigousSyms = err.ambiguousSyms ;
+                        ambigousSyms.nonEmpty() && !result.isPoly() ;
+                        ambigousSyms = ambigousSyms.tail) {
+                    Symbol s = ambigousSyms.head;
+                    if (s.kind == Kinds.MTH) {
+                        result = reduce(ArgumentExpressionKind.methodKind(s, types));
+                    }
+                }
+            } else {
+                result = (sym.kind == Kinds.MTH) ?
+                    ArgumentExpressionKind.methodKind(sym, types) :
+                    ArgumentExpressionKind.NO_POLY;
+            }
+        }
+        //where
+            private boolean isSimpleReceiver(JCTree rec) {
+                switch (rec.getTag()) {
+                    case IDENT:
+                        return true;
+                    case SELECT:
+                        return isSimpleReceiver(((JCFieldAccess)rec).selected);
+                    case TYPEAPPLY:
+                    case TYPEARRAY:
+                        return true;
+                    case ANNOTATED_TYPE:
+                        return isSimpleReceiver(((JCAnnotatedType)rec).underlyingType);
+                    default:
+                        return false;
+                }
+            }
+            private ArgumentExpressionKind reduce(ArgumentExpressionKind kind) {
+                switch (result) {
+                    case PRIMITIVE: return kind;
+                    case NO_POLY: return kind.isPoly() ? kind : result;
+                    case POLY: return result;
+                    default:
+                        Assert.error();
+                        return null;
+                }
+            }
+
+        @Override
+        public void visitLiteral(JCLiteral tree) {
+            Type litType = attr.litType(tree.typetag);
+            result = ArgumentExpressionKind.standaloneKind(litType, types);
+        }
+
+        @Override
+        void skip(JCTree tree) {
+            result = ArgumentExpressionKind.NO_POLY;
+        }        
+    }
 }
--- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Tue Mar 26 15:06:13 2013 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Wed Mar 27 17:11:16 2013 +0000
@@ -143,7 +143,6 @@
                                   boolean allowBoxing,
                                   boolean useVarargs,
                                   Resolve.MethodResolutionContext resolveContext,
-                                  Resolve.MethodCheck methodCheck,
                                   Warner warn) throws InferenceException {
         //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
         final InferenceContext inferenceContext = new InferenceContext(tvars);
@@ -152,7 +151,7 @@
             DeferredAttr.DeferredAttrContext deferredAttrContext =
                     resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn);
 
-            methodCheck.argumentsAcceptable(env, deferredAttrContext,
+            resolveContext.methodCheck.argumentsAcceptable(env, deferredAttrContext,
                     argtypes, mt.getParameterTypes(), warn);
 
             if (allowGraphInference &&
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Tue Mar 26 15:06:13 2013 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Wed Mar 27 17:11:16 2013 +0000
@@ -508,7 +508,6 @@
                         List<Type> typeargtypes,
                         boolean allowBoxing,
                         boolean useVarargs,
-                        MethodCheck methodCheck,
                         Warner warn) throws Infer.InferenceException {
 
         Type mt = types.memberType(site, m);
@@ -561,10 +560,9 @@
                                     allowBoxing,
                                     useVarargs,
                                     currentResolutionContext,
-                                    methodCheck,
                                     warn);
 
-        methodCheck.argumentsAcceptable(env, currentResolutionContext.deferredAttrContext(m, infer.emptyContext, resultInfo, warn),
+        currentResolutionContext.methodCheck.argumentsAcceptable(env, currentResolutionContext.deferredAttrContext(m, infer.emptyContext, resultInfo, warn),
                                 argtypes, mt.getParameterTypes(), warn);
         return mt;
     }
@@ -582,7 +580,7 @@
             currentResolutionContext.attrMode = DeferredAttr.AttrMode.CHECK;
             MethodResolutionPhase step = currentResolutionContext.step = env.info.pendingResolutionPhase;
             return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes,
-                    step.isBoxingRequired(), step.isVarargsRequired(), resolveMethodCheck, warn);
+                    step.isBoxingRequired(), step.isVarargsRequired(), warn);
         }
         finally {
             currentResolutionContext = prevContext;
@@ -599,11 +597,10 @@
                      List<Type> typeargtypes,
                      boolean allowBoxing,
                      boolean useVarargs,
-                     MethodCheck methodCheck,
                      Warner warn) {
         try {
             return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes,
-                                  allowBoxing, useVarargs, methodCheck, warn);
+                                  allowBoxing, useVarargs, warn);
         } catch (InapplicableMethodException ex) {
             return null;
         }
@@ -628,6 +625,12 @@
                                 List<Type> argtypes,
                                 List<Type> formals,
                                 Warner warn);
+        
+        /**
+         * Retrieve the method check object that will be used during a
+         * most specific check.
+         */
+        MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict);
     }
 
     /**
@@ -659,6 +662,100 @@
             this.inferKey = inferKey;
         }
     }
+    
+    /**
+     * Dummy method check object. All methods are deemed applicable, regardless
+     * of their formal parameter types.
+     */
+    MethodCheck nilMethodCheck = new MethodCheck() {
+        public void argumentsAcceptable(Env<AttrContext> env, DeferredAttrContext deferredAttrContext, List<Type> argtypes, List<Type> formals, Warner warn) {
+            //do nothing - method always applicable regardless of actuals
+        }
+
+        public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
+            return this;
+        }
+    };
+
+    /**
+     * Base class for 'real' method checks. The class defines the logic for
+     * iterating through formals and actuals and provides and entry point
+     * that can be used by subclasses in order to define the actual check logic.
+     */
+    abstract class AbstractMethodCheck implements MethodCheck {
+        @Override
+        public void argumentsAcceptable(final Env<AttrContext> env,
+                                    DeferredAttrContext deferredAttrContext,
+                                    List<Type> argtypes,
+                                    List<Type> formals,
+                                    Warner warn) {
+            //should we expand formals?
+            boolean useVarargs = deferredAttrContext.phase.isVarargsRequired();
+
+            //inference context used during this method check
+            InferenceContext inferenceContext = deferredAttrContext.inferenceContext;
+
+            Type varargsFormal = useVarargs ? formals.last() : null;
+
+            if (varargsFormal == null &&
+                    argtypes.size() != formals.size()) {
+                reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
+            }
+
+            while (argtypes.nonEmpty() && formals.head != varargsFormal) {
+                checkArg(false, argtypes.head, formals.head, deferredAttrContext, warn);
+                argtypes = argtypes.tail;
+                formals = formals.tail;
+            }
+
+            if (formals.head != varargsFormal) {
+                reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
+            }
+
+            if (useVarargs) {
+                //note: if applicability check is triggered by most specific test,
+                //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
+                final Type elt = types.elemtype(varargsFormal);
+                while (argtypes.nonEmpty()) {
+                    checkArg(true, argtypes.head, elt, deferredAttrContext, warn);
+                    argtypes = argtypes.tail;
+                }
+            }
+        }
+        
+        /**
+         * Does the actual argument conforms to the corresponding formal?
+         */
+        abstract void checkArg(boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn);
+
+        protected void reportMC(MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) {
+            boolean inferDiag = inferenceContext != infer.emptyContext;
+            InapplicableMethodException ex = inferDiag ?
+                    infer.inferenceException : inapplicableMethodException;
+            if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) {
+                Object[] args2 = new Object[args.length + 1];
+                System.arraycopy(args, 0, args2, 1, args.length);
+                args2[0] = inferenceContext.inferenceVars();
+                args = args2;
+            }
+            throw ex.setMessage(inferDiag ? diag.inferKey : diag.basicKey, args);
+        }
+
+        public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
+            return nilMethodCheck;
+        }
+    }
+
+    /**
+     * Arity-based method check. A method is applicable if the number of actuals
+     * supplied conforms to the method signature.
+     */
+    MethodCheck arityMethodCheck = new AbstractMethodCheck() {
+        @Override
+        void checkArg(boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) {
+            //do nothing - actual always compatible to formals
+        }
+    };
 
     /**
      * Main method applicability routine. Given a list of actual types A,
@@ -678,62 +775,27 @@
      *
      * A method check handler (see above) is used in order to report errors.
      */
-    MethodCheck resolveMethodCheck = new MethodCheck() {
+    MethodCheck resolveMethodCheck = new AbstractMethodCheck() {
+
+        @Override
+        void checkArg(boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) {
+            ResultInfo mresult = methodCheckResult(varargs, formal, deferredAttrContext, warn);
+            mresult.check(null, actual);
+        }
+        
         @Override
         public void argumentsAcceptable(final Env<AttrContext> env,
                                     DeferredAttrContext deferredAttrContext,
                                     List<Type> argtypes,
                                     List<Type> formals,
                                     Warner warn) {
+            super.argumentsAcceptable(env, deferredAttrContext, argtypes, formals, warn);
             //should we expand formals?
-            boolean useVarargs = deferredAttrContext.phase.isVarargsRequired();
-
-            //inference context used during this method check
-            InferenceContext inferenceContext = deferredAttrContext.inferenceContext;
-
-            Type varargsFormal = useVarargs ? formals.last() : null;
-
-            if (varargsFormal == null &&
-                    argtypes.size() != formals.size()) {
-                reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
+            if (deferredAttrContext.phase.isVarargsRequired()) {
+                //check varargs element type accessibility
+                varargsAccessible(env, types.elemtype(formals.last()),
+                        deferredAttrContext.inferenceContext);
             }
-
-            while (argtypes.nonEmpty() && formals.head != varargsFormal) {
-                ResultInfo mresult = methodCheckResult(false, formals.head, deferredAttrContext, warn);
-                mresult.check(null, argtypes.head);
-                argtypes = argtypes.tail;
-                formals = formals.tail;
-            }
-
-            if (formals.head != varargsFormal) {
-                reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
-            }
-
-            if (useVarargs) {
-                //note: if applicability check is triggered by most specific test,
-                //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
-                final Type elt = types.elemtype(varargsFormal);
-                ResultInfo mresult = methodCheckResult(true, elt, deferredAttrContext, warn);
-                while (argtypes.nonEmpty()) {
-                    mresult.check(null, argtypes.head);
-                    argtypes = argtypes.tail;
-                }
-                //check varargs element type accessibility
-                varargsAccessible(env, elt, inferenceContext);
-            }
-        }
-
-        private void reportMC(MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) {
-            boolean inferDiag = inferenceContext != infer.emptyContext;
-            InapplicableMethodException ex = inferDiag ?
-                    infer.inferenceException : inapplicableMethodException;
-            if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) {
-                Object[] args2 = new Object[args.length + 1];
-                System.arraycopy(args, 0, args2, 1, args.length);
-                args2[0] = inferenceContext.inferenceVars();
-                args = args2;
-            }
-            throw ex.setMessage(inferDiag ? diag.inferKey : diag.basicKey, args);
         }
 
         private void varargsAccessible(final Env<AttrContext> env, final Type t, final InferenceContext inferenceContext) {
@@ -765,6 +827,11 @@
             };
             return new MethodResultInfo(to, checkContext);
         }
+
+        @Override
+        public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
+            return new MostSpecificCheck(strict, actuals);
+        }
     };
 
     /**
@@ -1042,6 +1109,11 @@
                 }
             }
         }
+
+        public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
+            Assert.error("Cannot get here!");
+            return null;
+        }
     }
 
     public static class InapplicableMethodException extends RuntimeException {
@@ -1251,7 +1323,7 @@
         Assert.check(sym.kind < AMBIGUOUS);
         try {
             Type mt = rawInstantiate(env, site, sym, null, argtypes, typeargtypes,
-                               allowBoxing, useVarargs, resolveMethodCheck, types.noWarnings);
+                               allowBoxing, useVarargs, types.noWarnings);
             if (!operator)
                 currentResolutionContext.addApplicableCandidate(sym, mt);
         } catch (InapplicableMethodException ex) {
@@ -1355,11 +1427,20 @@
         int maxLength = Math.max(
                             Math.max(m1.type.getParameterTypes().length(), actuals.length()),
                             m2.type.getParameterTypes().length());
-        Type mst = instantiate(env, site, m2, null,
-                adjustArgs(types.lowerBounds(types.memberType(site, m1).getParameterTypes()), m1, maxLength, useVarargs), null,
-                allowBoxing, useVarargs, new MostSpecificCheck(!allowBoxing, actuals), noteWarner);
-        return mst != null &&
-                !noteWarner.hasLint(Lint.LintCategory.UNCHECKED);
+        MethodResolutionContext prevResolutionContext = currentResolutionContext;
+        try {
+            currentResolutionContext = new MethodResolutionContext();
+            currentResolutionContext.step = prevResolutionContext.step;
+            currentResolutionContext.methodCheck =
+                    prevResolutionContext.methodCheck.mostSpecificCheck(actuals, !allowBoxing);
+            Type mst = instantiate(env, site, m2, null,
+                    adjustArgs(types.lowerBounds(types.memberType(site, m1).getParameterTypes()), m1, maxLength, useVarargs), null,
+                    allowBoxing, useVarargs, noteWarner);
+            return mst != null &&
+                    !noteWarner.hasLint(Lint.LintCategory.UNCHECKED);
+        } finally {
+            currentResolutionContext = prevResolutionContext;
+        }
     }
     private List<Type> adjustArgs(List<Type> args, Symbol msym, int length, boolean allowVarargs) {
         if ((msym.flags() & VARARGS) != 0 && allowVarargs) {
@@ -2121,14 +2202,14 @@
                          Name name,
                          List<Type> argtypes,
                          List<Type> typeargtypes) {
-        return lookupMethod(env, pos, env.enclClass.sym, new BasicLookupHelper(name, env.enclClass.sym.type, argtypes, typeargtypes) {
-            @Override
-            Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
-                return findFun(env, name, argtypes, typeargtypes,
-                        phase.isBoxingRequired(),
-                        phase.isVarargsRequired());
-            }
-        });
+        return lookupMethod(env, pos, env.enclClass.sym, resolveMethodCheck,
+                new BasicLookupHelper(name, env.enclClass.sym.type, argtypes, typeargtypes) {
+                    @Override
+                    Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+                        return findFun(env, name, argtypes, typeargtypes,
+                                phase.isBoxingRequired(),
+                                phase.isVarargsRequired());
+                    }});
     }
 
     /** Resolve a qualified method identifier
@@ -2310,36 +2391,36 @@
                               Type site,
                               List<Type> argtypes,
                               List<Type> typeargtypes) {
-        return lookupMethod(env, pos, site.tsym, new BasicLookupHelper(names.init, site, argtypes, typeargtypes) {
-            @Override
-            Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
-                return findDiamond(env, site, argtypes, typeargtypes,
-                        phase.isBoxingRequired(),
-                        phase.isVarargsRequired());
-            }
-            @Override
-            Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
-                if (sym.kind >= AMBIGUOUS) {
-                    final JCDiagnostic details = sym.kind == WRONG_MTH ?
-                                    ((InapplicableSymbolError)sym).errCandidate().details :
-                                    null;
-                    sym = new InapplicableSymbolError(sym.kind, "diamondError", currentResolutionContext) {
-                        @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);
+        return lookupMethod(env, pos, site.tsym, resolveMethodCheck,
+                new BasicLookupHelper(names.init, site, argtypes, typeargtypes) {
+                    @Override
+                    Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+                        return findDiamond(env, site, argtypes, typeargtypes,
+                                phase.isBoxingRequired(),
+                                phase.isVarargsRequired());
+                    }
+                    @Override
+                    Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
+                        if (sym.kind >= AMBIGUOUS) {
+                            final JCDiagnostic details = sym.kind == WRONG_MTH ?
+                                            ((InapplicableSymbolError)sym).errCandidate().details :
+                                            null;
+                            sym = new InapplicableSymbolError(sym.kind, "diamondError", currentResolutionContext) {
+                                @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);
+                                }
+                            };
+                            sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes);
+                            env.info.pendingResolutionPhase = currentResolutionContext.step;
                         }
-                    };
-                    sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes);
-                    env.info.pendingResolutionPhase = currentResolutionContext.step;
-                }
-                return sym;
-            }
-        });
+                        return sym;
+                    }});
     }
 
     /** This method scans all the constructor symbol in a given class scope -
@@ -2472,7 +2553,8 @@
                                   Type site,
                                   Name name, List<Type> argtypes,
                                   List<Type> typeargtypes,
-                                  boolean boxingAllowed) {
+                                  boolean boxingAllowed,
+                                  MethodCheck methodCheck) {
         MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC;
 
         ReferenceLookupHelper boundLookupHelper;
@@ -2492,12 +2574,12 @@
 
         //step 1 - bound lookup
         Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup());
-        Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, boundLookupHelper);
+        Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, methodCheck, boundLookupHelper);
 
         //step 2 - unbound lookup
         ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup();
         Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup());
-        Symbol unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym, unboundLookupHelper);
+        Symbol unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym, methodCheck, unboundLookupHelper);
 
         //merge results
         Pair<Symbol, ReferenceLookupHelper> res;
@@ -2668,7 +2750,7 @@
         ReferenceLookupHelper unboundLookup() {
             if (TreeInfo.isStaticSelector(referenceTree.expr, names) &&
                     argtypes.nonEmpty() &&
-                    types.isSubtypeUnchecked(argtypes.head, site)) {
+                    (argtypes.head.hasTag(NONE) || types.isSubtypeUnchecked(argtypes.head, site))) {
                 return new UnboundMethodReferenceLookupHelper(referenceTree, name,
                         site, argtypes, typeargtypes, maxPhase);
             } else {
@@ -2701,8 +2783,8 @@
         UnboundMethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
                 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
             super(referenceTree, name, site, argtypes.tail, typeargtypes, maxPhase);
-            Type asSuperSite = types.asSuper(argtypes.head, site.tsym);
-            if (site.isRaw() && !asSuperSite.isErroneous()) {
+            if (site.isRaw() && !argtypes.head.hasTag(NONE)) {
+                Type asSuperSite = types.asSuper(argtypes.head, site.tsym);
                 this.site = asSuperSite;
             }
         }
@@ -2797,8 +2879,10 @@
      * at the end of the lookup, the helper is used to validate the results
      * (this last step might trigger overload resolution diagnostics).
      */
-    Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, LookupHelper lookupHelper) {
-        return lookupMethod(env, pos, location, new MethodResolutionContext(), lookupHelper);
+    Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, MethodCheck methodCheck, LookupHelper lookupHelper) {
+        MethodResolutionContext resolveContext = new MethodResolutionContext();
+        resolveContext.methodCheck = methodCheck;
+        return lookupMethod(env, pos, location, resolveContext, lookupHelper);
     }
 
     Symbol lookupMethod(Env<AttrContext> env, DiagnosticPosition pos, Symbol location,
@@ -3566,6 +3650,8 @@
         private List<Candidate> candidates = List.nil();
 
         MethodResolutionPhase step = null;
+        
+        MethodCheck methodCheck = resolveMethodCheck;
 
         private boolean internalResolution = false;
         private DeferredAttr.AttrMode attrMode = DeferredAttr.AttrMode.SPECULATIVE;
--- a/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Tue Mar 26 15:06:13 2013 +0000
+++ b/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Wed Mar 27 17:11:16 2013 +0000
@@ -249,23 +249,6 @@
         }
     }
 
-    /** Return true if a a tree corresponds to a poly expression. */
-    public static boolean isPoly(JCTree tree, JCTree origin) {
-        switch (tree.getTag()) {
-            case APPLY:
-            case NEWCLASS:
-            case CONDEXPR:
-                return !origin.hasTag(TYPECAST);
-            case LAMBDA:
-            case REFERENCE:
-                return true;
-            case PARENS:
-                return isPoly(((JCParens)tree).expr, origin);
-            default:
-                return false;
-        }
-    }
-
     /** set 'polyKind' on given tree */
     public static void setPolyKind(JCTree tree, PolyKind pkind) {
         switch (tree.getTag()) {