8026231: Look at 'static' flag when checking method references
authorvromero
Fri, 15 Nov 2013 11:08:12 +0000
changeset 21718 74a5882faf79
parent 21717 11ba59c9bbb5
child 21719 b8a5f2e7f41a
child 21887 8dc93a1c9782
8026231: Look at 'static' flag when checking method references Reviewed-by: jjg, dlsmith
langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java
langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
langtools/test/tools/javac/lambda/MethodReference22.java
langtools/test/tools/javac/lambda/MethodReference22.out
langtools/test/tools/javac/lambda/MethodReference51.java
langtools/test/tools/javac/lambda/MethodReference68.out
langtools/test/tools/javac/lambda/MethodReference73.java
langtools/test/tools/javac/lambda/MethodReference73.out
langtools/test/tools/javac/lambda/TargetType60.java
langtools/test/tools/javac/lambda/TargetType60.out
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java	Thu Nov 14 13:47:38 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java	Fri Nov 15 11:08:12 2013 +0000
@@ -87,16 +87,17 @@
 
     /** Kinds for erroneous symbols that complement the above
      */
-    public static final int ERRONEOUS = 1 << 7;
-    public static final int AMBIGUOUS    = ERRONEOUS+1; // ambiguous reference
-    public static final int HIDDEN       = ERRONEOUS+2; // hidden method or field
-    public static final int STATICERR    = ERRONEOUS+3; // nonstatic member from static context
-    public static final int MISSING_ENCL = ERRONEOUS+4; // missing enclosing class
-    public static final int ABSENT_VAR   = ERRONEOUS+5; // missing variable
-    public static final int WRONG_MTHS   = ERRONEOUS+6; // methods with wrong arguments
-    public static final int WRONG_MTH    = ERRONEOUS+7; // one method with wrong arguments
-    public static final int ABSENT_MTH   = ERRONEOUS+8; // missing method
-    public static final int ABSENT_TYP   = ERRONEOUS+9; // missing type
+    public static final int ERRONEOUS           = 1 << 7;
+    public static final int AMBIGUOUS           = ERRONEOUS + 1;  // ambiguous reference
+    public static final int HIDDEN              = ERRONEOUS + 2;  // hidden method or field
+    public static final int STATICERR           = ERRONEOUS + 3;  // nonstatic member from static context
+    public static final int MISSING_ENCL        = ERRONEOUS + 4;  // missing enclosing class
+    public static final int ABSENT_VAR          = ERRONEOUS + 5;  // missing variable
+    public static final int WRONG_MTHS          = ERRONEOUS + 6;  // methods with wrong arguments
+    public static final int WRONG_MTH           = ERRONEOUS + 7;  // one method with wrong arguments
+    public static final int ABSENT_MTH          = ERRONEOUS + 8;  // missing method
+    public static final int ABSENT_TYP          = ERRONEOUS + 9;  // missing type
+    public static final int WRONG_STATICNESS    = ERRONEOUS + 10; // wrong staticness for method references
 
     public enum KindName implements Formattable {
         ANNOTATION("kindname.annotation"),
@@ -231,14 +232,14 @@
             return KindName.CLASS;
     }
 
-    /** A KindName representing the kind of a a missing symbol, given an
+    /** A KindName representing the kind of a missing symbol, given an
      *  error kind.
      * */
     public static KindName absentKind(int kind) {
         switch (kind) {
         case ABSENT_VAR:
             return KindName.VAR;
-        case WRONG_MTHS: case WRONG_MTH: case ABSENT_MTH:
+        case WRONG_MTHS: case WRONG_MTH: case ABSENT_MTH: case WRONG_STATICNESS:
             return KindName.METHOD;
         case ABSENT_TYP:
             return KindName.CLASS;
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Nov 14 13:47:38 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Nov 15 11:08:12 2013 +0000
@@ -2697,9 +2697,10 @@
             Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = null;
             List<Type> saved_undet = resultInfo.checkContext.inferenceContext().save();
             try {
-                refResult = rs.resolveMemberReference(that.pos(), localEnv, that, that.expr.type,
-                        that.name, argtypes, typeargtypes, true, referenceCheck,
-                        resultInfo.checkContext.inferenceContext());
+                refResult = rs.resolveMemberReference(localEnv, that, that.expr.type,
+                        that.name, argtypes, typeargtypes, referenceCheck,
+                        resultInfo.checkContext.inferenceContext(),
+                        resultInfo.checkContext.deferredAttrContext().mode);
             } finally {
                 resultInfo.checkContext.inferenceContext().rollback(saved_undet);
             }
@@ -2719,6 +2720,7 @@
                     case HIDDEN:
                     case STATICERR:
                     case MISSING_ENCL:
+                    case WRONG_STATICNESS:
                         targetError = true;
                         break;
                     default:
@@ -2770,26 +2772,6 @@
                     chk.checkRaw(that.expr, localEnv);
                 }
 
-                if (!that.kind.isUnbound() &&
-                        that.getMode() == ReferenceMode.INVOKE &&
-                        TreeInfo.isStaticSelector(that.expr, names) &&
-                        !that.sym.isStatic()) {
-                    log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()),
-                            diags.fragment("non-static.cant.be.ref", Kinds.kindName(refSym), refSym));
-                    result = that.type = types.createErrorType(target);
-                    return;
-                }
-
-                if (that.kind.isUnbound() &&
-                        that.getMode() == ReferenceMode.INVOKE &&
-                        TreeInfo.isStaticSelector(that.expr, names) &&
-                        that.sym.isStatic()) {
-                    log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()),
-                            diags.fragment("static.method.in.unbound.lookup", Kinds.kindName(refSym), refSym));
-                    result = that.type = types.createErrorType(target);
-                    return;
-                }
-
                 if (that.sym.isStatic() && TreeInfo.isStaticSelector(that.expr, names) &&
                         exprType.getTypeArguments().nonEmpty()) {
                     //static ref with class type-args
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Thu Nov 14 13:47:38 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Fri Nov 15 11:08:12 2013 +0000
@@ -643,15 +643,16 @@
                     }
                     JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
                     mref2.expr = exprTree;
-                    Pair<Symbol, ?> lookupRes =
-                            rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type,
-                                tree.name, argtypes.toList(), null, true, rs.arityMethodCheck, inferenceContext);
-                    switch (lookupRes.fst.kind) {
+                    Symbol lookupSym =
+                            rs.resolveMemberReferenceByArity(localEnv, mref2, exprTree.type,
+                                tree.name, argtypes.toList(), inferenceContext);
+                    switch (lookupSym.kind) {
                         //note: as argtypes are erroneous types, type-errors must
                         //have been caused by arity mismatch
                         case Kinds.ABSENT_MTH:
                         case Kinds.WRONG_MTH:
                         case Kinds.WRONG_MTHS:
+                        case Kinds.WRONG_STATICNESS:
                            checkContext.report(tree, diags.fragment("incompatible.arg.types.in.mref"));
                     }
                 }
@@ -1037,11 +1038,10 @@
                     attr.memberReferenceQualifierResult(tree));
             JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
             mref2.expr = exprTree;
-            Pair<Symbol, ReferenceLookupHelper> lookupRes =
-                    rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type,
-                        tree.name, List.<Type>nil(), null, true, rs.nilMethodCheck,
-                        infer.emptyContext);
-            Symbol res = tree.sym = lookupRes.fst;
+            Symbol res =
+                    rs.getMemberReference(tree, localEnv, mref2,
+                        exprTree.type, tree.name);
+            tree.sym = res;
             if (res.kind >= Kinds.ERRONEOUS ||
                     res.type.hasTag(FORALL) ||
                     (res.flags() & Flags.VARARGS) != 0 ||
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Nov 14 13:47:38 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Nov 15 11:08:12 2013 +0000
@@ -25,6 +25,7 @@
 
 package com.sun.tools.javac.comp;
 
+import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
 import com.sun.tools.javac.api.Formattable.LocalizedString;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Symbol.*;
@@ -110,6 +111,9 @@
             SymbolNotFoundError(ABSENT_VAR);
         methodNotFound = new
             SymbolNotFoundError(ABSENT_MTH);
+        methodWithCorrectStaticnessNotFound = new
+            SymbolNotFoundError(WRONG_STATICNESS,
+                "method found has incorrect staticness");
         typeNotFound = new
             SymbolNotFoundError(ABSENT_TYP);
 
@@ -144,6 +148,7 @@
      */
     private final SymbolNotFoundError varNotFound;
     private final SymbolNotFoundError methodNotFound;
+    private final SymbolNotFoundError methodWithCorrectStaticnessNotFound;
     private final SymbolNotFoundError typeNotFound;
 
     public static Resolve instance(Context context) {
@@ -868,6 +873,12 @@
         }
     };
 
+    /**
+     * This class handles method reference applicability checks; since during
+     * these checks it's sometime possible to have inference variables on
+     * the actual argument types list, the method applicability check must be
+     * extended so that inference variables are 'opened' as needed.
+     */
     class MethodReferenceCheck extends AbstractMethodCheck {
 
         InferenceContext pendingInferenceContext;
@@ -2674,6 +2685,97 @@
         return resolveOperator(pos, optag, env, List.of(left, right));
     }
 
+    Symbol getMemberReference(DiagnosticPosition pos,
+            Env<AttrContext> env,
+            JCMemberReference referenceTree,
+            Type site,
+            Name name) {
+
+        site = types.capture(site);
+
+        ReferenceLookupHelper lookupHelper = makeReferenceLookupHelper(
+                referenceTree, site, name, List.<Type>nil(), null, VARARITY);
+
+        Env<AttrContext> newEnv = env.dup(env.tree, env.info.dup());
+        Symbol sym = lookupMethod(newEnv, env.tree.pos(), site.tsym,
+                nilMethodCheck, lookupHelper);
+
+        env.info.pendingResolutionPhase = newEnv.info.pendingResolutionPhase;
+
+        return sym;
+    }
+
+    ReferenceLookupHelper makeReferenceLookupHelper(JCMemberReference referenceTree,
+                                  Type site,
+                                  Name name,
+                                  List<Type> argtypes,
+                                  List<Type> typeargtypes,
+                                  MethodResolutionPhase maxPhase) {
+        ReferenceLookupHelper result;
+        if (!name.equals(names.init)) {
+            //method reference
+            result =
+                    new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase);
+        } else {
+            if (site.hasTag(ARRAY)) {
+                //array constructor reference
+                result =
+                        new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
+            } else {
+                //class constructor reference
+                result =
+                        new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
+            }
+        }
+        return result;
+    }
+
+    Symbol resolveMemberReferenceByArity(Env<AttrContext> env,
+                                  JCMemberReference referenceTree,
+                                  Type site,
+                                  Name name,
+                                  List<Type> argtypes,
+                                  InferenceContext inferenceContext) {
+
+        boolean isStaticSelector = TreeInfo.isStaticSelector(referenceTree.expr, names);
+        site = types.capture(site);
+
+        ReferenceLookupHelper boundLookupHelper = makeReferenceLookupHelper(
+                referenceTree, site, name, argtypes, null, VARARITY);
+        //step 1 - bound lookup
+        Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup());
+        Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym,
+                arityMethodCheck, boundLookupHelper);
+        if (isStaticSelector &&
+            !name.equals(names.init) &&
+            !boundSym.isStatic() &&
+            boundSym.kind < ERRONEOUS) {
+            boundSym = methodNotFound;
+        }
+
+        //step 2 - unbound lookup
+        Symbol unboundSym = methodNotFound;
+        ReferenceLookupHelper unboundLookupHelper = null;
+        Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup());
+        if (isStaticSelector) {
+            unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext);
+            unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym,
+                    arityMethodCheck, unboundLookupHelper);
+            if (unboundSym.isStatic() &&
+                unboundSym.kind < ERRONEOUS) {
+                unboundSym = methodNotFound;
+            }
+        }
+
+        //merge results
+        Symbol bestSym = choose(boundSym, unboundSym);
+        env.info.pendingResolutionPhase = bestSym == unboundSym ?
+                unboundEnv.info.pendingResolutionPhase :
+                boundEnv.info.pendingResolutionPhase;
+
+        return bestSym;
+    }
+
     /**
      * Resolution of member references is typically done as a single
      * overload resolution step, where the argument types A are inferred from
@@ -2700,47 +2802,118 @@
      * the type T might be dynamically inferred (i.e. if constructor reference
      * has a raw qualifier).
      */
-    Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(DiagnosticPosition pos,
-                                  Env<AttrContext> env,
+    Pair<Symbol, ReferenceLookupHelper> resolveMemberReference(Env<AttrContext> env,
                                   JCMemberReference referenceTree,
                                   Type site,
-                                  Name name, List<Type> argtypes,
+                                  Name name,
+                                  List<Type> argtypes,
                                   List<Type> typeargtypes,
-                                  boolean boxingAllowed,
                                   MethodCheck methodCheck,
-                                  InferenceContext inferenceContext) {
-        MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC;
+                                  InferenceContext inferenceContext,
+                                  AttrMode mode) {
 
         site = types.capture(site);
-
-        ReferenceLookupHelper boundLookupHelper;
-        if (!name.equals(names.init)) {
-            //method reference
-            boundLookupHelper =
-                    new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase);
-        } else if (site.hasTag(ARRAY)) {
-            //array constructor reference
-            boundLookupHelper =
-                    new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
-        } else {
-            //class constructor reference
-            boundLookupHelper =
-                    new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
-        }
+        ReferenceLookupHelper boundLookupHelper = makeReferenceLookupHelper(
+                referenceTree, site, name, argtypes, typeargtypes, VARARITY);
 
         //step 1 - bound lookup
         Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup());
-        Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, methodCheck, boundLookupHelper);
+        Symbol origBoundSym;
+        boolean staticErrorForBound = false;
+        MethodResolutionContext boundSearchResolveContext = new MethodResolutionContext();
+        boundSearchResolveContext.methodCheck = methodCheck;
+        Symbol boundSym = origBoundSym = lookupMethod(boundEnv, env.tree.pos(),
+                site.tsym, boundSearchResolveContext, boundLookupHelper);
+        SearchResultKind boundSearchResultKind = SearchResultKind.NOT_APPLICABLE_MATCH;
+        boolean isStaticSelector = TreeInfo.isStaticSelector(referenceTree.expr, names);
+        boolean shouldCheckForStaticness = isStaticSelector &&
+                referenceTree.getMode() == ReferenceMode.INVOKE;
+        if (boundSym.kind != WRONG_MTHS && boundSym.kind != WRONG_MTH) {
+            if (shouldCheckForStaticness) {
+                if (!boundSym.isStatic()) {
+                    staticErrorForBound = true;
+                    if (hasAnotherApplicableMethod(
+                            boundSearchResolveContext, boundSym, true)) {
+                        boundSearchResultKind = SearchResultKind.BAD_MATCH_MORE_SPECIFIC;
+                    } else {
+                        boundSearchResultKind = SearchResultKind.BAD_MATCH;
+                        if (boundSym.kind < ERRONEOUS) {
+                            boundSym = methodWithCorrectStaticnessNotFound;
+                        }
+                    }
+                } else if (boundSym.kind < ERRONEOUS) {
+                    boundSearchResultKind = SearchResultKind.GOOD_MATCH;
+                }
+            }
+        }
 
         //step 2 - unbound lookup
-        ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext);
+        Symbol origUnboundSym = null;
+        Symbol unboundSym = methodNotFound;
+        ReferenceLookupHelper unboundLookupHelper = null;
         Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup());
-        Symbol unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym, methodCheck, unboundLookupHelper);
+        SearchResultKind unboundSearchResultKind = SearchResultKind.NOT_APPLICABLE_MATCH;
+        boolean staticErrorForUnbound = false;
+        if (isStaticSelector) {
+            unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext);
+            MethodResolutionContext unboundSearchResolveContext =
+                    new MethodResolutionContext();
+            unboundSearchResolveContext.methodCheck = methodCheck;
+            unboundSym = origUnboundSym = lookupMethod(unboundEnv, env.tree.pos(),
+                    site.tsym, unboundSearchResolveContext, unboundLookupHelper);
+
+            if (unboundSym.kind != WRONG_MTH && unboundSym.kind != WRONG_MTHS) {
+                if (shouldCheckForStaticness) {
+                    if (unboundSym.isStatic()) {
+                        staticErrorForUnbound = true;
+                        if (hasAnotherApplicableMethod(
+                                unboundSearchResolveContext, unboundSym, false)) {
+                            unboundSearchResultKind = SearchResultKind.BAD_MATCH_MORE_SPECIFIC;
+                        } else {
+                            unboundSearchResultKind = SearchResultKind.BAD_MATCH;
+                            if (unboundSym.kind < ERRONEOUS) {
+                                unboundSym = methodWithCorrectStaticnessNotFound;
+                            }
+                        }
+                    } else if (unboundSym.kind < ERRONEOUS) {
+                        unboundSearchResultKind = SearchResultKind.GOOD_MATCH;
+                    }
+                }
+            }
+        }
 
         //merge results
         Pair<Symbol, ReferenceLookupHelper> res;
         Symbol bestSym = choose(boundSym, unboundSym);
-        res = new Pair<Symbol, ReferenceLookupHelper>(bestSym,
+        if (bestSym.kind < ERRONEOUS && (staticErrorForBound || staticErrorForUnbound)) {
+            if (staticErrorForBound) {
+                boundSym = methodWithCorrectStaticnessNotFound;
+            }
+            if (staticErrorForUnbound) {
+                unboundSym = methodWithCorrectStaticnessNotFound;
+            }
+            bestSym = choose(boundSym, unboundSym);
+        }
+        if (bestSym == methodWithCorrectStaticnessNotFound && mode == AttrMode.CHECK) {
+            Symbol symToPrint = origBoundSym;
+            String errorFragmentToPrint = "non-static.cant.be.ref";
+            if (staticErrorForBound && staticErrorForUnbound) {
+                if (unboundSearchResultKind == SearchResultKind.BAD_MATCH_MORE_SPECIFIC) {
+                    symToPrint = origUnboundSym;
+                    errorFragmentToPrint = "static.method.in.unbound.lookup";
+                }
+            } else {
+                if (!staticErrorForBound) {
+                    symToPrint = origUnboundSym;
+                    errorFragmentToPrint = "static.method.in.unbound.lookup";
+                }
+            }
+            log.error(referenceTree.expr.pos(), "invalid.mref",
+                Kinds.kindName(referenceTree.getMode()),
+                diags.fragment(errorFragmentToPrint,
+                Kinds.kindName(symToPrint), symToPrint));
+        }
+        res = new Pair<>(bestSym,
                 bestSym == unboundSym ? unboundLookupHelper : boundLookupHelper);
         env.info.pendingResolutionPhase = bestSym == unboundSym ?
                 unboundEnv.info.pendingResolutionPhase :
@@ -2748,18 +2921,42 @@
 
         return res;
     }
+
+    enum SearchResultKind {
+        GOOD_MATCH,                 //type I
+        BAD_MATCH_MORE_SPECIFIC,    //type II
+        BAD_MATCH,                  //type III
+        NOT_APPLICABLE_MATCH        //type IV
+    }
+
+    boolean hasAnotherApplicableMethod(MethodResolutionContext resolutionContext,
+            Symbol bestSoFar, boolean staticMth) {
+        for (Candidate c : resolutionContext.candidates) {
+            if (resolutionContext.step != c.step ||
+                !c.isApplicable() ||
+                c.sym == bestSoFar) {
+                continue;
+            } else {
+                if (c.sym.isStatic() == staticMth) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     //where
-        private Symbol choose(Symbol s1, Symbol s2) {
-            if (lookupSuccess(s1) && lookupSuccess(s2)) {
-                return ambiguityError(s1, s2);
-            } else if (lookupSuccess(s1) ||
-                    (canIgnore(s2) && !canIgnore(s1))) {
-                return s1;
-            } else if (lookupSuccess(s2) ||
-                    (canIgnore(s1) && !canIgnore(s2))) {
-                return s2;
+        private Symbol choose(Symbol boundSym, Symbol unboundSym) {
+            if (lookupSuccess(boundSym) && lookupSuccess(unboundSym)) {
+                return ambiguityError(boundSym, unboundSym);
+            } else if (lookupSuccess(boundSym) ||
+                    (canIgnore(unboundSym) && !canIgnore(boundSym))) {
+                return boundSym;
+            } else if (lookupSuccess(unboundSym) ||
+                    (canIgnore(boundSym) && !canIgnore(unboundSym))) {
+                return unboundSym;
             } else {
-                return s1;
+                return boundSym;
             }
         }
 
@@ -2780,6 +2977,8 @@
                     InapplicableSymbolsError errSyms =
                             (InapplicableSymbolsError)s;
                     return errSyms.filterCandidates(errSyms.mapCandidates()).isEmpty();
+                case WRONG_STATICNESS:
+                    return false;
                 default:
                     return false;
             }
@@ -2894,7 +3093,6 @@
                 List<Type> argtypes, List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
             super(name, site, argtypes, typeargtypes, maxPhase);
             this.referenceTree = referenceTree;
-
         }
 
         /**
@@ -3324,6 +3522,11 @@
             return false;
         }
 
+        @Override
+        public boolean isStatic() {
+            return false;
+        }
+
         /**
          * Create an external representation for this erroneous symbol to be
          * used during attribution - by default this returns the symbol of a
@@ -3398,7 +3601,11 @@
     class SymbolNotFoundError extends ResolveError {
 
         SymbolNotFoundError(int kind) {
-            super(kind, "symbol not found error");
+            this(kind, "symbol not found error");
+        }
+
+        SymbolNotFoundError(int kind, String debugName) {
+            super(kind, debugName);
         }
 
         @Override
@@ -3436,7 +3643,8 @@
                 hasLocation = !location.name.equals(names._this) &&
                         !location.name.equals(names._super);
             }
-            boolean isConstructor = kind == ABSENT_MTH && name == names.init;
+            boolean isConstructor = (kind == ABSENT_MTH || kind == WRONG_STATICNESS) &&
+                    name == names.init;
             KindName kindname = isConstructor ? KindName.CONSTRUCTOR : absentKind(kind);
             Name idname = isConstructor ? site.tsym.name : name;
             String errKey = getErrorKey(kindname, typeargtypes.nonEmpty(), hasLocation);
--- a/langtools/test/tools/javac/lambda/MethodReference22.java	Thu Nov 14 13:47:38 2013 -0800
+++ b/langtools/test/tools/javac/lambda/MethodReference22.java	Fri Nov 15 11:08:12 2013 +0000
@@ -48,19 +48,19 @@
     }
 
     static void test2() {
-        SAM2 s1 = MethodReference22::m1; //ambiguous
-        call2(MethodReference22::m1); //ambiguous
-        SAM2 s2 = MethodReference22::m2; //ambiguous
-        call2(MethodReference22::m2); //ambiguous
-        SAM2 s3 = MethodReference22::m3; //ambiguous
-        call2(MethodReference22::m3); //ambiguous
-        SAM2 s4 = MethodReference22::m4; //ambiguous
-        call2(MethodReference22::m4); //ambiguous
+        SAM2 s1 = MethodReference22::m1; //ok
+        call2(MethodReference22::m1); //ok
+        SAM2 s2 = MethodReference22::m2; //ok
+        call2(MethodReference22::m2); //ok
+        SAM2 s3 = MethodReference22::m3; //fail
+        call2(MethodReference22::m3); //fail
+        SAM2 s4 = MethodReference22::m4; //fail
+        call2(MethodReference22::m4); //fail
     }
 
     static void test3() {
-        call3(MethodReference22::m1); //fail
-        call3(MethodReference22::m2); //ok
+        call3(MethodReference22::m1); //ok
+        call3(MethodReference22::m2); //ambiguous
         call3(MethodReference22::m3); //ok
         call3(MethodReference22::m4); //fail
     }
--- a/langtools/test/tools/javac/lambda/MethodReference22.out	Thu Nov 14 13:47:38 2013 -0800
+++ b/langtools/test/tools/javac/lambda/MethodReference22.out	Fri Nov 15 11:08:12 2013 +0000
@@ -1,19 +1,11 @@
 MethodReference22.java:40:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m1(java.lang.String))
-MethodReference22.java:41:15: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m1(java.lang.String))
+MethodReference22.java:41:9: compiler.err.cant.apply.symbol: kindname.method, call1, MethodReference22.SAM1, @999, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.arg.types.in.mref))
 MethodReference22.java:46:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m4(java.lang.String))
-MethodReference22.java:47:15: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m4(java.lang.String))
-MethodReference22.java:51:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m1, kindname.method, m1(MethodReference22,java.lang.String), MethodReference22, kindname.method, m1(java.lang.String), MethodReference22))
-MethodReference22.java:52:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1401, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m1, kindname.method, m1(MethodReference22,java.lang.String), MethodReference22, kindname.method, m1(java.lang.String), MethodReference22)))
-MethodReference22.java:53:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m2, kindname.method, m2(MethodReference22,java.lang.String), MethodReference22, kindname.method, m2(java.lang.String), MethodReference22))
-MethodReference22.java:54:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1504, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m2, kindname.method, m2(MethodReference22,java.lang.String), MethodReference22, kindname.method, m2(java.lang.String), MethodReference22)))
-MethodReference22.java:55:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m3, kindname.method, m3(MethodReference22,java.lang.String), MethodReference22, kindname.method, m3(java.lang.String), MethodReference22))
-MethodReference22.java:56:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1607, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m3, kindname.method, m3(MethodReference22,java.lang.String), MethodReference22, kindname.method, m3(java.lang.String), MethodReference22)))
+MethodReference22.java:47:9: compiler.err.cant.apply.symbol: kindname.method, call1, MethodReference22.SAM1, @1270, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.arg.types.in.mref))
+MethodReference22.java:55:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m3(MethodReference22,java.lang.String))
+MethodReference22.java:56:9: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1574, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.arg.types.in.mref))
 MethodReference22.java:57:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m4, kindname.method, m4(MethodReference22,java.lang.String), MethodReference22, kindname.method, m4(java.lang.String), MethodReference22))
-MethodReference22.java:58:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1710, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m4, kindname.method, m4(MethodReference22,java.lang.String), MethodReference22, kindname.method, m4(java.lang.String), MethodReference22)))
-MethodReference22.java:62:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference22.SAM1), MethodReference22, kindname.method, call3(MethodReference22.SAM2), MethodReference22
-MethodReference22.java:62:15: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m1(java.lang.String))
+MethodReference22.java:58:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1667, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m4, kindname.method, m4(MethodReference22,java.lang.String), MethodReference22, kindname.method, m4(java.lang.String), MethodReference22)))
 MethodReference22.java:63:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference22.SAM1), MethodReference22, kindname.method, call3(MethodReference22.SAM2), MethodReference22
-MethodReference22.java:64:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference22.SAM1), MethodReference22, kindname.method, call3(MethodReference22.SAM2), MethodReference22
-MethodReference22.java:65:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference22.SAM1), MethodReference22, kindname.method, call3(MethodReference22.SAM2), MethodReference22
-MethodReference22.java:65:15: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m4(java.lang.String))
-18 errors
+MethodReference22.java:65:14: compiler.err.cant.apply.symbol: kindname.method, call3, MethodReference22.SAM2, @1881, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m4, kindname.method, m4(MethodReference22,java.lang.String), MethodReference22, kindname.method, m4(java.lang.String), MethodReference22)))
+10 errors
--- a/langtools/test/tools/javac/lambda/MethodReference51.java	Thu Nov 14 13:47:38 2013 -0800
+++ b/langtools/test/tools/javac/lambda/MethodReference51.java	Fri Nov 15 11:08:12 2013 +0000
@@ -36,11 +36,11 @@
 
 
     static void test() {
-        IntSam s1 = MethodReference51::unknown; //method not found
-        IntSam s2 = MethodReference51::f; //inapplicable method
-        IntSam s3 = MethodReference51::g; //inapplicable methods
-        IntegerIntegerSam s4 = MethodReference51::g; //ambiguous
-        IntSam s5 = MethodReference51::h; //static error
-        IntSam s6 = MethodReference51.foo::j; //inaccessible method
+        IntSam s1 = MethodReference51::unknown; //fail
+        IntSam s2 = MethodReference51::f; //fail
+        IntSam s3 = MethodReference51::g; //fail
+        IntegerIntegerSam s4 = MethodReference51::g; //fail
+        IntSam s5 = MethodReference51::h; //fail
+        IntSam s6 = MethodReference51.foo::j; //fail
     }
 }
--- a/langtools/test/tools/javac/lambda/MethodReference68.out	Thu Nov 14 13:47:38 2013 -0800
+++ b/langtools/test/tools/javac/lambda/MethodReference68.out	Fri Nov 15 11:08:12 2013 +0000
@@ -1,2 +1,3 @@
 MethodReference68.java:21:10: compiler.err.cant.apply.symbol: kindname.method, g, MethodReference68.F<Z>,Z[], @493,int, kindname.class, MethodReference68, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, MethodReference68.Foo,java.lang.Object)
-1 error
+MethodReference68.java:21:12: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, getName())
+2 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MethodReference73.java	Fri Nov 15 11:08:12 2013 +0000
@@ -0,0 +1,110 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8026231
+ * @summary Look at 'static' flag when checking method references
+ * @compile/fail/ref=MethodReference73.out -XDrawDiagnostics MethodReference73.java
+ */
+
+public class MethodReference73 {
+
+    interface SAM {
+        void m(MethodReference73 rec, String x);
+    }
+
+    void m1(MethodReference73 rec, String x) {}
+    static void m1(MethodReference73 rec, Object x) {}
+    void m1(String x) {}
+
+    static void m2(MethodReference73 rec, String x) {}
+    void m2(Object x) {}
+    static void m2(String x) {}
+
+    static void m3(MethodReference73 rec, String x) {}
+    void m3(String x) {}
+
+    void m4(MethodReference73 rec, String x) {}
+    static void m4(MethodReference73 rec, Object x) {}
+    static void m4(String x) {}
+    void m4(Object x) {}
+
+    static void m5(MethodReference73 rec, String x) {}
+    static void m5(String x) {}
+
+    static void m6(MethodReference73 rec, String x) {}
+    void m6(String x, int i) {}
+
+    void m7(MethodReference73 rec, String x) {}
+    void m7(String x) {}
+
+    static void m8(MethodReference73 rec, String x, int i) {}
+    void m8(String x) {}
+
+    void m9(MethodReference73 rec, String x) {}
+    static void m9(MethodReference73 rec, Object x) {}
+    static void m9(String x) {}
+
+    void m10(MethodReference73 rec, String x) {}
+    static void m10(MethodReference73 rec, Object x) {}
+    void m10(String x, int i) {}
+
+    void m11(MethodReference73 rec, String x) {}
+    void m11(Object x) {}
+    static void m11(String x) {}
+
+    static void m12(MethodReference73 rec, String x, int i) {}
+    void m12(Object x) {}
+    static void m12(String x) {}
+
+    void m13(MethodReference73 rec, String x) {}
+    void m13(String x, int i) {}
+
+    static void m14(MethodReference73 rec, String x, int i) {}
+    static void m14(String x) {}
+
+    void m15(MethodReference73 rec, String x) {}
+    static void m15(String x) {}
+
+    static void m16(MethodReference73 rec, String x, int i) {}
+    void m16(String x, int i) {}
+
+    /** For method references with a type selector two searches are performed.
+     *  Each of them may yield one of the following results:
+     *      I)   a good match
+     *      II)  a bad match more specific than a good match
+     *      III) a bad match with no good matches
+     *      IV)  no applicable method found
+     *
+     *  Whether a match is considered to be good or not depends on the staticness
+     *  of the matched method. The expected result of the first search is a static
+     *  method. The expected result of the second search is an instance method.
+     *
+     *  If the most specific method has the wrong staticness but there is an
+     *  applicable method with the right staticness then we have the (II) case.
+     *  The (III) case is reserved for those cases when the most specific method
+     *  has the wrong staticness but there is no applicable method with the right
+     *  staticness.
+     */
+
+    static void test() {
+        SAM s1 = MethodReference73::m1;           //(II, I)       ambiguous
+        SAM s2 = MethodReference73::m2;           //(I, II)       ambiguous
+        SAM s3 = MethodReference73::m3;           //(I, I)        ambiguous
+        SAM s4 = MethodReference73::m4;           //(II, II)      ambiguous
+
+        SAM s5 = MethodReference73::m5;           //(I, III)      first search's result gets selected
+        SAM s6 = MethodReference73::m6;           //(I, IV)       first search's result gets selected
+
+        SAM s7 = MethodReference73::m7;           //(III, I)      second search's result gets selected
+        SAM s8 = MethodReference73::m8;           //(IV, I)       second search's result gets selected
+
+        SAM s9 = MethodReference73::m9;           //(II, III)     method matched by first search has the wrong staticness
+        SAM s10 = MethodReference73::m10;         //(II, IV)      method matched by first search has the wrong staticness
+        SAM s11 = MethodReference73::m11;         //(III, II)     method matched by second search has the wrong staticness
+        SAM s12 = MethodReference73::m12;         //(IV, II)      method matched by second search has the wrong staticness
+        SAM s13 = MethodReference73::m13;         //(III, IV)     method matched by first search has the wrong staticness
+        SAM s14 = MethodReference73::m14;         //(IV, III)     method matched by second search has the wrong staticness
+        SAM s15 = MethodReference73::m15;         //(III, III)    method matched by first search has the wrong staticness
+
+        SAM s16 = MethodReference73::m16;         //(IV, IV)      incompatible types, invalid method reference
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MethodReference73.out	Fri Nov 15 11:08:12 2013 +0000
@@ -0,0 +1,13 @@
+MethodReference73.java:89:18: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m1, kindname.method, m1(MethodReference73,java.lang.String), MethodReference73, kindname.method, m1(java.lang.String), MethodReference73))
+MethodReference73.java:90:18: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m2, kindname.method, m2(MethodReference73,java.lang.String), MethodReference73, kindname.method, m2(java.lang.String), MethodReference73))
+MethodReference73.java:91:18: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m3, kindname.method, m3(MethodReference73,java.lang.String), MethodReference73, kindname.method, m3(java.lang.String), MethodReference73))
+MethodReference73.java:92:18: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m4, kindname.method, m4(MethodReference73,java.lang.String), MethodReference73, kindname.method, m4(java.lang.String), MethodReference73))
+MethodReference73.java:100:18: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m9(MethodReference73,java.lang.String))
+MethodReference73.java:101:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m10(MethodReference73,java.lang.String))
+MethodReference73.java:102:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.method.in.unbound.lookup: kindname.method, m11(java.lang.String))
+MethodReference73.java:103:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.method.in.unbound.lookup: kindname.method, m12(java.lang.String))
+MethodReference73.java:104:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m13(MethodReference73,java.lang.String))
+MethodReference73.java:105:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.static.method.in.unbound.lookup: kindname.method, m14(java.lang.String))
+MethodReference73.java:106:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m15(MethodReference73,java.lang.String))
+MethodReference73.java:108:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbols: kindname.method, m16, MethodReference73,java.lang.String,{(compiler.misc.inapplicable.method: kindname.method, MethodReference73, m16(MethodReference73,java.lang.String,int), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, MethodReference73, m16(java.lang.String,int), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: MethodReference73, java.lang.String)))}))
+12 errors
--- a/langtools/test/tools/javac/lambda/TargetType60.java	Thu Nov 14 13:47:38 2013 -0800
+++ b/langtools/test/tools/javac/lambda/TargetType60.java	Fri Nov 15 11:08:12 2013 +0000
@@ -57,7 +57,7 @@
 
     static void testUnbound() {
         TargetType60 s1 = u(TargetType60::n0); //ok - resolves to u(Sam1)
-        TargetType60 s2 = u(TargetType60::n1); //ambiguous (u(Sam1), u(Sam2) apply)
+        TargetType60 s2 = u(TargetType60::n1); //ok - resolves to u(Sam2)
         TargetType60 s3 = u(TargetType60::n2); //none is applicable
         TargetType60 s4 = u(TargetType60::n01);//ambiguous (u(Sam1), u(Sam2) apply)
         TargetType60 s5 = u(TargetType60::n012);//ambiguous (u(Sam1), u(Sam2) apply)
--- a/langtools/test/tools/javac/lambda/TargetType60.out	Thu Nov 14 13:47:38 2013 -0800
+++ b/langtools/test/tools/javac/lambda/TargetType60.out	Fri Nov 15 11:08:12 2013 +0000
@@ -1,8 +1,6 @@
 TargetType60.java:54:21: compiler.err.ref.ambiguous: g, kindname.method, g(TargetType60.Sam0), TargetType60, kindname.method, <U>g(TargetType60.Sam1<U>), TargetType60
 TargetType60.java:55:21: compiler.err.ref.ambiguous: g, kindname.method, <U>g(TargetType60.Sam1<U>), TargetType60, kindname.method, <U>g(TargetType60.Sam2<U,java.lang.String>), TargetType60
-TargetType60.java:60:27: compiler.err.ref.ambiguous: u, kindname.method, <U>u(TargetType60.Sam1<U>), TargetType60, kindname.method, <U>u(TargetType60.Sam2<U,java.lang.String>), TargetType60
-TargetType60.java:60:29: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, n1(java.lang.String))
-TargetType60.java:61:29: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, n2(TargetType60,java.lang.String))
+TargetType60.java:61:27: compiler.err.cant.apply.symbols: kindname.method, u, @1639,{(compiler.misc.inapplicable.method: kindname.method, TargetType60, <U>u(TargetType60.Sam1<U>), (compiler.misc.infer.no.conforming.assignment.exists: U, (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, n2, TargetType60,java.lang.String, U, kindname.class, TargetType60, (compiler.misc.arg.length.mismatch))))),(compiler.misc.inapplicable.method: kindname.method, TargetType60, <U>u(TargetType60.Sam2<U,java.lang.String>), (compiler.misc.infer.no.conforming.assignment.exists: U, (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.resolve.location.args: kindname.method, n2, , U,java.lang.String, (compiler.misc.location: kindname.class, TargetType60, null)))))}
 TargetType60.java:62:27: compiler.err.ref.ambiguous: u, kindname.method, <U>u(TargetType60.Sam1<U>), TargetType60, kindname.method, <U>u(TargetType60.Sam2<U,java.lang.String>), TargetType60
 TargetType60.java:63:27: compiler.err.ref.ambiguous: u, kindname.method, <U>u(TargetType60.Sam1<U>), TargetType60, kindname.method, <U>u(TargetType60.Sam2<U,java.lang.String>), TargetType60
-7 errors
+5 errors