langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
changeset 18668 1f99c1b43ab2
parent 18646 e628560a86d1
child 18910 c967bfda9283
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Sat Jun 29 20:12:24 2013 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Jul 01 14:57:03 2013 +0100
@@ -1573,7 +1573,6 @@
                           allowBoxing,
                           useVarargs,
                           operator);
-        reportVerboseResolutionDiagnostic(env.tree.pos(), name, site, argtypes, typeargtypes, bestSoFar);
         return bestSoFar;
     }
     // where
@@ -2224,7 +2223,7 @@
         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) {
+                    Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) {
                         return findFun(env, name, argtypes, typeargtypes,
                                 phase.isBoxingRequired(),
                                 phase.isVarargsRequired());
@@ -2256,7 +2255,7 @@
                                   List<Type> typeargtypes) {
         return lookupMethod(env, pos, location, resolveContext, new BasicLookupHelper(name, site, argtypes, typeargtypes) {
             @Override
-            Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+            Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) {
                 return findMethod(env, site, name, argtypes, typeargtypes,
                         phase.isBoxingRequired(),
                         phase.isVarargsRequired(), false);
@@ -2355,7 +2354,7 @@
                               List<Type> typeargtypes) {
         return lookupMethod(env, pos, site.tsym, resolveContext, new BasicLookupHelper(names.init, site, argtypes, typeargtypes) {
             @Override
-            Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+            Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) {
                 return findConstructor(pos, env, site, argtypes, typeargtypes,
                         phase.isBoxingRequired(),
                         phase.isVarargsRequired());
@@ -2413,7 +2412,7 @@
         return lookupMethod(env, pos, site.tsym, resolveMethodCheck,
                 new BasicLookupHelper(names.init, site, argtypes, typeargtypes) {
                     @Override
-                    Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+                    Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) {
                         return findDiamond(env, site, argtypes, typeargtypes,
                                 phase.isBoxingRequired(),
                                 phase.isVarargsRequired());
@@ -2503,7 +2502,7 @@
             return lookupMethod(env, pos, syms.predefClass, currentResolutionContext,
                     new BasicLookupHelper(name, syms.predefClass.type, argtypes, null, BOX) {
                 @Override
-                Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+                Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) {
                     return findMethod(env, site, name, argtypes, typeargtypes,
                             phase.isBoxingRequired(),
                             phase.isVarargsRequired(), true);
@@ -2669,6 +2668,13 @@
         abstract Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase);
 
         /**
+         * Dump overload resolution info
+         */
+        void debug(DiagnosticPosition pos, Symbol sym) {
+            //do nothing
+        }
+
+        /**
          * Validate the result of the lookup
          */
         abstract Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym);
@@ -2685,17 +2691,30 @@
         }
 
         @Override
-        Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
+        final Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+            Symbol sym = doLookup(env, phase);
             if (sym.kind == AMBIGUOUS) {
                 AmbiguityError a_err = (AmbiguityError)sym;
                 sym = a_err.mergeAbstracts(site);
             }
+            return sym;
+        }
+
+        abstract Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase);
+
+        @Override
+        Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
             if (sym.kind >= AMBIGUOUS) {
                 //if nothing is found return the 'first' error
                 sym = accessMethod(sym, pos, location, site, name, true, argtypes, typeargtypes);
             }
             return sym;
         }
+
+        @Override
+        void debug(DiagnosticPosition pos, Symbol sym) {
+            reportVerboseResolutionDiagnostic(pos, name, site, argtypes, typeargtypes, sym);
+        }
     }
 
     /**
@@ -2924,7 +2943,9 @@
                 MethodResolutionPhase prevPhase = currentResolutionContext.step;
                 Symbol prevBest = bestSoFar;
                 currentResolutionContext.step = phase;
-                bestSoFar = phase.mergeResults(bestSoFar, lookupHelper.lookup(env, phase));
+                Symbol sym = lookupHelper.lookup(env, phase);
+                lookupHelper.debug(pos, sym);
+                bestSoFar = phase.mergeResults(bestSoFar, sym);
                 env.info.pendingResolutionPhase = (prevBest == bestSoFar) ? prevPhase : phase;
             }
             return lookupHelper.access(env, pos, location, bestSoFar);
@@ -3630,35 +3651,39 @@
          * is more specific than the others, attempt to merge their signatures.
          */
         Symbol mergeAbstracts(Type site) {
-            Symbol fst = ambiguousSyms.last();
-            Symbol res = fst;
-            for (Symbol s : ambiguousSyms.reverse()) {
-                Type mt1 = types.memberType(site, res);
-                Type mt2 = types.memberType(site, s);
-                if ((s.flags() & ABSTRACT) == 0 ||
-                        !types.overrideEquivalent(mt1, mt2) ||
-                        !types.isSameTypes(fst.erasure(types).getParameterTypes(),
-                                       s.erasure(types).getParameterTypes())) {
-                    //ambiguity cannot be resolved
-                    return this;
-                } else {
-                    Type mst = mostSpecificReturnType(mt1, mt2);
-                    if (mst == null) {
-                        // Theoretically, this can't happen, but it is possible
-                        // due to error recovery or mixing incompatible class files
+            List<Symbol> ambiguousInOrder = ambiguousSyms.reverse();
+            for (Symbol s : ambiguousInOrder) {
+                Type mt = types.memberType(site, s);
+                boolean found = true;
+                List<Type> allThrown = mt.getThrownTypes();
+                for (Symbol s2 : ambiguousInOrder) {
+                    Type mt2 = types.memberType(site, s2);
+                    if ((s2.flags() & ABSTRACT) == 0 ||
+                        !types.overrideEquivalent(mt, mt2) ||
+                        !types.isSameTypes(s.erasure(types).getParameterTypes(),
+                                       s2.erasure(types).getParameterTypes())) {
+                        //ambiguity cannot be resolved
                         return this;
                     }
-                    Symbol mostSpecific = mst == mt1 ? res : s;
-                    List<Type> allThrown = chk.intersect(mt1.getThrownTypes(), mt2.getThrownTypes());
-                    Type newSig = types.createMethodTypeWithThrown(mostSpecific.type, allThrown);
-                    res = new MethodSymbol(
-                            mostSpecific.flags(),
-                            mostSpecific.name,
-                            newSig,
-                            mostSpecific.owner);
+                    Type mst = mostSpecificReturnType(mt, mt2);
+                    if (mst == null || mst != mt) {
+                        found = false;
+                        break;
+                    }
+                    allThrown = chk.intersect(allThrown, mt2.getThrownTypes());
+                }
+                if (found) {
+                    //all ambiguous methods were abstract and one method had
+                    //most specific return type then others
+                    return (allThrown == mt.getThrownTypes()) ?
+                            s : new MethodSymbol(
+                                s.flags(),
+                                s.name,
+                                types.createMethodTypeWithThrown(mt, allThrown),
+                                s.owner);
                 }
             }
-            return res;
+            return this;
         }
 
         @Override