langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
changeset 14062 b7439971a094
parent 14058 c7ec7facdd20
child 14359 d4099818ab70
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Oct 05 14:21:09 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Sat Oct 06 10:35:38 2012 +0100
@@ -40,6 +40,7 @@
 import com.sun.tools.javac.jvm.*;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.tree.JCTree.*;
+import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
@@ -98,10 +99,6 @@
 
         varNotFound = new
             SymbolNotFoundError(ABSENT_VAR);
-        wrongMethod = new
-            InapplicableSymbolError();
-        wrongMethods = new
-            InapplicableSymbolsError();
         methodNotFound = new
             SymbolNotFoundError(ABSENT_MTH);
         typeNotFound = new
@@ -133,8 +130,6 @@
     /** error symbols, which are returned when resolution fails
      */
     private final SymbolNotFoundError varNotFound;
-    private final InapplicableSymbolError wrongMethod;
-    private final InapplicableSymbolsError wrongMethods;
     private final SymbolNotFoundError methodNotFound;
     private final SymbolNotFoundError typeNotFound;
 
@@ -454,8 +449,18 @@
                         boolean useVarargs,
                         Warner warn)
         throws Infer.InferenceException {
-        if (useVarargs && (m.flags() & VARARGS) == 0)
-            throw inapplicableMethodException.setMessage();
+        if (useVarargs && (m.flags() & VARARGS) == 0) {
+            //better error recovery - if we stumbled upon a non-varargs method
+            //during varargs applicability phase, the method should be treated as
+            //not applicable; the reason for inapplicability can be found in the
+            //candidate for 'm' that was created during the BOX phase.
+            Candidate prevCandidate = currentResolutionContext.getCandidate(m, BOX);
+            JCDiagnostic details = null;
+            if (prevCandidate != null && !prevCandidate.isApplicable()) {
+                details = prevCandidate.details;
+            }
+            throw inapplicableMethodException.setMessage(details);
+        }
         Type mt = types.memberType(site, m);
 
         // tvars is the list of formal type variables for which type arguments
@@ -1028,11 +1033,10 @@
                 currentResolutionContext.addInapplicableCandidate(sym, ex.getDiagnostic());
             switch (bestSoFar.kind) {
             case ABSENT_MTH:
-                return wrongMethod;
+                return new InapplicableSymbolError(currentResolutionContext);
             case WRONG_MTH:
                 if (operator) return bestSoFar;
-            case WRONG_MTHS:
-                return wrongMethods;
+                bestSoFar = new InapplicableSymbolsError(currentResolutionContext);
             default:
                 return bestSoFar;
             }
@@ -1181,7 +1185,8 @@
 
             //is this a structural actual argument?
             boolean isStructuralPoly = actual.tag == DEFERRED &&
-                    ((DeferredType)actual).tree.hasTag(LAMBDA);
+                    (((DeferredType)actual).tree.hasTag(LAMBDA) ||
+                    ((DeferredType)actual).tree.hasTag(REFERENCE));
 
             Type newFormal = f1;
 
@@ -2210,7 +2215,7 @@
                 final JCDiagnostic details = errSym.kind == WRONG_MTH ?
                                 ((InapplicableSymbolError)errSym).errCandidate().details :
                                 null;
-                errSym = new InapplicableSymbolError(errSym.kind, "diamondError") {
+                errSym = new InapplicableSymbolError(errSym.kind, "diamondError", currentResolutionContext) {
                     @Override
                     JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos,
                             Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
@@ -2276,6 +2281,335 @@
         return bestSoFar;
     }
 
+    /**
+     * Resolution of member references is typically done as a single
+     * overload resolution step, where the argument types A are inferred from
+     * the target functional descriptor.
+     *
+     * If the member reference is a method reference with a type qualifier,
+     * a two-step lookup process is performed. The first step uses the
+     * expected argument list A, while the second step discards the first
+     * type from A (which is treated as a receiver type).
+     *
+     * There are two cases in which inference is performed: (i) if the member
+     * reference is a constructor reference and the qualifier type is raw - in
+     * which case diamond inference is used to infer a parameterization for the
+     * type qualifier; (ii) if the member reference is an unbound reference
+     * where the type qualifier is raw - in that case, during the unbound lookup
+     * the receiver argument type is used to infer an instantiation for the raw
+     * qualifier type.
+     *
+     * When a multi-step resolution process is exploited, it is an error
+     * if two candidates are found (ambiguity).
+     *
+     * This routine returns a pair (T,S), where S is the member reference symbol,
+     * and T is the type of the class in which S is defined. This is necessary as
+     * 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,
+                                  JCMemberReference referenceTree,
+                                  Type site,
+                                  Name name, List<Type> argtypes,
+                                  List<Type> typeargtypes,
+                                  boolean boxingAllowed) {
+        //step 1 - bound lookup
+        ReferenceLookupHelper boundLookupHelper = name.equals(names.init) ?
+                new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, boxingAllowed) :
+                new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, boxingAllowed);
+        Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup());
+        Symbol boundSym = findMemberReference(boundEnv, boundLookupHelper);
+
+        //step 2 - unbound lookup
+        ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup();
+        Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup());
+        Symbol unboundSym = findMemberReference(unboundEnv, unboundLookupHelper);
+
+        //merge results
+        Pair<Symbol, ReferenceLookupHelper> res;
+        if (unboundSym.kind != MTH) {
+            res = new Pair<Symbol, ReferenceLookupHelper>(boundSym, boundLookupHelper);
+            env.info.pendingResolutionPhase = boundEnv.info.pendingResolutionPhase;
+        } else if (boundSym.kind == MTH) {
+            res = new Pair<Symbol, ReferenceLookupHelper>(ambiguityError(boundSym, unboundSym), boundLookupHelper);
+            env.info.pendingResolutionPhase = boundEnv.info.pendingResolutionPhase;
+        } else {
+            res = new Pair<Symbol, ReferenceLookupHelper>(unboundSym, unboundLookupHelper);
+            env.info.pendingResolutionPhase = unboundEnv.info.pendingResolutionPhase;
+        }
+
+        return res;
+    }
+
+    /**
+     * Helper for defining custom method-like lookup logic; a lookup helper
+     * provides hooks for (i) the actual lookup logic and (ii) accessing the
+     * lookup result (this step might result in compiler diagnostics to be generated)
+     */
+    abstract class LookupHelper {
+
+        /** name of the symbol to lookup */
+        Name name;
+
+        /** location in which the lookup takes place */
+        Type site;
+
+        /** actual types used during the lookup */
+        List<Type> argtypes;
+
+        /** type arguments used during the lookup */
+        List<Type> typeargtypes;
+
+        LookupHelper(Name name, Type site, List<Type> argtypes, List<Type> typeargtypes) {
+            this.name = name;
+            this.site = site;
+            this.argtypes = argtypes;
+            this.typeargtypes = typeargtypes;
+        }
+
+        /**
+         * Search for a symbol under a given overload resolution phase - this method
+         * is usually called several times, once per each overload resolution phase
+         */
+        abstract Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase);
+
+        /**
+         * Validate the result of the lookup
+         */
+        abstract Symbol access(Env<AttrContext> env, Symbol symbol);
+    }
+
+    /**
+     * Helper class for member reference lookup. A reference lookup helper
+     * defines the basic logic for member reference lookup; a method gives
+     * access to an 'unbound' helper used to perform an unbound member
+     * reference lookup.
+     */
+    abstract class ReferenceLookupHelper extends LookupHelper {
+
+        /** The member reference tree */
+        JCMemberReference referenceTree;
+
+        /** Max overload resolution phase handled by this helper */
+        MethodResolutionPhase maxPhase;
+
+        ReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
+                List<Type> argtypes, List<Type> typeargtypes, boolean boxingAllowed) {
+            super(name, site, argtypes, typeargtypes);
+            this.referenceTree = referenceTree;
+            this.maxPhase = boxingAllowed ? VARARITY : BASIC;
+        }
+
+        /**
+         * Returns an unbound version of this lookup helper. By default, this
+         * method returns an dummy lookup helper.
+         */
+        ReferenceLookupHelper unboundLookup() {
+            //dummy loopkup helper that always return 'methodNotFound'
+            return new ReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase.isBoxingRequired()) {
+                @Override
+                ReferenceLookupHelper unboundLookup() {
+                    return this;
+                }
+                @Override
+                Symbol lookupReference(Env<AttrContext> env, MethodResolutionPhase phase) {
+                    return methodNotFound;
+                }
+                @Override
+                ReferenceKind referenceKind(Symbol sym) {
+                    Assert.error();
+                    return null;
+                }
+            };
+        }
+
+        /**
+         * Get the kind of the member reference
+         */
+        abstract JCMemberReference.ReferenceKind referenceKind(Symbol sym);
+
+        @Override
+        Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
+            return (env.info.pendingResolutionPhase.ordinal() > maxPhase.ordinal()) ?
+                    methodNotFound : lookupReference(env, phase);
+        }
+
+        abstract Symbol lookupReference(Env<AttrContext> env, MethodResolutionPhase phase);
+
+        Symbol access(Env<AttrContext> env, Symbol sym) {
+            if (sym.kind >= AMBIGUOUS) {
+                MethodResolutionPhase errPhase = currentResolutionContext.firstErroneousResolutionPhase();
+                if (errPhase.ordinal() > maxPhase.ordinal()) {
+                    errPhase = maxPhase;
+                }
+                env.info.pendingResolutionPhase = errPhase;
+                sym = currentResolutionContext.resolutionCache.get(errPhase);
+            }
+            return sym;
+        }
+    }
+
+    /**
+     * Helper class for method reference lookup. The lookup logic is based
+     * upon Resolve.findMethod; in certain cases, this helper class has a
+     * corresponding unbound helper class (see UnboundMethodReferenceLookupHelper).
+     * In such cases, non-static lookup results are thrown away.
+     */
+    class MethodReferenceLookupHelper extends ReferenceLookupHelper {
+
+        MethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
+                List<Type> argtypes, List<Type> typeargtypes, boolean boxingAllowed) {
+            super(referenceTree, name, site, argtypes, typeargtypes, boxingAllowed);
+        }
+
+        protected Symbol lookupReferenceInternal(Env<AttrContext> env, MethodResolutionPhase phase) {
+            return findMethod(env, site, name, argtypes, typeargtypes,
+                    phase.isBoxingRequired(), phase.isVarargsRequired(), syms.operatorNames.contains(name));
+        }
+
+        protected Symbol adjustLookupResult(Env<AttrContext> env, Symbol sym) {
+            return !TreeInfo.isStaticSelector(referenceTree.expr, names) ||
+                        sym.kind != MTH ||
+                        sym.isStatic() ? sym : new StaticError(sym);
+        }
+
+        @Override
+        final Symbol lookupReference(Env<AttrContext> env, MethodResolutionPhase phase) {
+            return adjustLookupResult(env, lookupReferenceInternal(env, phase));
+        }
+
+        @Override
+        ReferenceLookupHelper unboundLookup() {
+            if (TreeInfo.isStaticSelector(referenceTree.expr, names) &&
+                    argtypes.nonEmpty() &&
+                    types.isSubtypeUnchecked(argtypes.head, site)) {
+                return new UnboundMethodReferenceLookupHelper(referenceTree, name,
+                        site, argtypes, typeargtypes, maxPhase.isBoxingRequired());
+            } else {
+                return super.unboundLookup();
+            }
+        }
+
+        @Override
+        ReferenceKind referenceKind(Symbol sym) {
+            if (sym.isStatic()) {
+                return TreeInfo.isStaticSelector(referenceTree.expr, names) ?
+                        ReferenceKind.STATIC : ReferenceKind.STATIC_EVAL;
+            } else {
+                Name selName = TreeInfo.name(referenceTree.getQualifierExpression());
+                return selName != null && selName == names._super ?
+                        ReferenceKind.SUPER :
+                        ReferenceKind.BOUND;
+            }
+        }
+    }
+
+    /**
+     * Helper class for unbound method reference lookup. Essentially the same
+     * as the basic method reference lookup helper; main difference is that static
+     * lookup results are thrown away. If qualifier type is raw, an attempt to
+     * infer a parameterized type is made using the first actual argument (that
+     * would otherwise be ignored during the lookup).
+     */
+    class UnboundMethodReferenceLookupHelper extends MethodReferenceLookupHelper {
+
+        UnboundMethodReferenceLookupHelper(JCMemberReference referenceTree, Name name, Type site,
+                List<Type> argtypes, List<Type> typeargtypes, boolean boxingAllowed) {
+            super(referenceTree, name,
+                    site.isRaw() ? types.asSuper(argtypes.head, site.tsym) : site,
+                    argtypes.tail, typeargtypes, boxingAllowed);
+        }
+
+        @Override
+        protected Symbol adjustLookupResult(Env<AttrContext> env, Symbol sym) {
+            return sym.kind != MTH || !sym.isStatic() ? sym : new StaticError(sym);
+        }
+
+        @Override
+        ReferenceLookupHelper unboundLookup() {
+            return this;
+        }
+
+        @Override
+        ReferenceKind referenceKind(Symbol sym) {
+            return ReferenceKind.UNBOUND;
+        }
+    }
+
+    /**
+     * Helper class for constructor reference lookup. The lookup logic is based
+     * upon either Resolve.findMethod or Resolve.findDiamond - depending on
+     * whether the constructor reference needs diamond inference (this is the case
+     * if the qualifier type is raw). A special erroneous symbol is returned
+     * if the lookup returns the constructor of an inner class and there's no
+     * enclosing instance in scope.
+     */
+    class ConstructorReferenceLookupHelper extends ReferenceLookupHelper {
+
+        boolean needsInference;
+
+        ConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List<Type> argtypes,
+                List<Type> typeargtypes, boolean boxingAllowed) {
+            super(referenceTree, names.init, site, argtypes, typeargtypes, boxingAllowed);
+            if (site.isRaw()) {
+                this.site = new ClassType(site.getEnclosingType(), site.tsym.type.getTypeArguments(), site.tsym);
+                needsInference = true;
+            }
+        }
+
+        @Override
+        protected Symbol lookupReference(Env<AttrContext> env, MethodResolutionPhase phase) {
+            Symbol sym = needsInference ?
+                findDiamond(env, site, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) :
+                findMethod(env, site, name, argtypes, typeargtypes,
+                        phase.isBoxingRequired(), phase.isVarargsRequired(), syms.operatorNames.contains(name));
+            return sym.kind != MTH ||
+                          site.getEnclosingType().tag == NONE ||
+                          hasEnclosingInstance(env, site) ?
+                          sym : new InvalidSymbolError(Kinds.MISSING_ENCL, sym, null) {
+                    @Override
+                    JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
+                       return diags.create(dkind, log.currentSource(), pos,
+                            "cant.access.inner.cls.constr", site.tsym.name, argtypes, site.getEnclosingType());
+                    }
+                };
+        }
+
+        @Override
+        ReferenceKind referenceKind(Symbol sym) {
+            return site.getEnclosingType().tag == NONE ?
+                    ReferenceKind.TOPLEVEL : ReferenceKind.IMPLICIT_INNER;
+        }
+    }
+
+    /**
+     * Resolution step for member reference. This generalizes a standard
+     * method/constructor lookup - on each overload resolution step, a
+     * lookup helper class is used to perform the reference lookup; at the end
+     * of the lookup, the helper is used to validate the results.
+     */
+    Symbol findMemberReference(Env<AttrContext> env, LookupHelper lookupHelper) {
+        MethodResolutionContext prevResolutionContext = currentResolutionContext;
+        try {
+            currentResolutionContext = new MethodResolutionContext();
+            Symbol sym = methodNotFound;
+            List<MethodResolutionPhase> steps = methodResolutionSteps;
+            while (steps.nonEmpty() &&
+                   steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
+                   sym.kind >= ERRONEOUS) {
+                currentResolutionContext.step = env.info.pendingResolutionPhase = steps.head;
+                sym = lookupHelper.lookup(env, steps.head);
+                currentResolutionContext.resolutionCache.put(steps.head, sym);
+                steps = steps.tail;
+            }
+            return lookupHelper.access(env, sym);
+        }
+        finally {
+            currentResolutionContext = prevResolutionContext;
+        }
+    }
+
     /** Resolve constructor.
      *  @param pos       The position to use for error reporting.
      *  @param env       The environment current at the constructor invocation.
@@ -2425,6 +2759,23 @@
                                  Env<AttrContext> env,
                                  Symbol member,
                                  boolean isSuperCall) {
+        Symbol sym = resolveSelfContainingInternal(env, member, isSuperCall);
+        if (sym == null) {
+            log.error(pos, "encl.class.required", member);
+            return syms.errSymbol;
+        } else {
+            return accessBase(sym, pos, env.enclClass.sym.type, sym.name, true);
+        }
+    }
+
+    boolean hasEnclosingInstance(Env<AttrContext> env, Type type) {
+        Symbol encl = resolveSelfContainingInternal(env, type.tsym, false);
+        return encl != null && encl.kind < ERRONEOUS;
+    }
+
+    private Symbol resolveSelfContainingInternal(Env<AttrContext> env,
+                                 Symbol member,
+                                 boolean isSuperCall) {
         Name name = names._this;
         Env<AttrContext> env1 = isSuperCall ? env.outer : env;
         boolean staticOnly = false;
@@ -2435,8 +2786,7 @@
                     Symbol sym = env1.info.scope.lookup(name).sym;
                     if (sym != null) {
                         if (staticOnly) sym = new StaticError(sym);
-                        return accessBase(sym, pos, env.enclClass.sym.type,
-                                      name, true);
+                        return sym;
                     }
                 }
                 if ((env1.enclClass.sym.flags() & STATIC) != 0)
@@ -2444,8 +2794,7 @@
                 env1 = env1.outer;
             }
         }
-        log.error(pos, "encl.class.required", member);
-        return syms.errSymbol;
+        return null;
     }
 
     /**
@@ -2513,7 +2862,7 @@
      * represent a different kinds of resolution error - as such they must
      * specify how they map into concrete compiler diagnostics.
      */
-    private abstract class ResolveError extends Symbol {
+    abstract class ResolveError extends Symbol {
 
         /** The name of the kind of error, for debugging only. */
         final String debugName;
@@ -2703,12 +3052,15 @@
      */
     class InapplicableSymbolError extends ResolveError {
 
-        InapplicableSymbolError() {
-            super(WRONG_MTH, "inapplicable symbol error");
+        protected MethodResolutionContext resolveContext;
+
+        InapplicableSymbolError(MethodResolutionContext context) {
+            this(WRONG_MTH, "inapplicable symbol error", context);
         }
 
-        protected InapplicableSymbolError(int kind, String debugName) {
+        protected InapplicableSymbolError(int kind, String debugName, MethodResolutionContext context) {
             super(kind, debugName);
+            this.resolveContext = context;
         }
 
         @Override
@@ -2746,7 +3098,7 @@
                 Candidate c = errCandidate();
                 Symbol ws = c.sym.asMemberOf(site, types);
                 return diags.create(dkind, log.currentSource(), pos,
-                          "cant.apply.symbol" + (c.details != null ? ".1" : ""),
+                          "cant.apply.symbol",
                           kindName(ws),
                           ws.name == names.init ? ws.owner.name : ws.name,
                           methodArguments(ws.type.getParameterTypes()),
@@ -2763,13 +3115,13 @@
         }
 
         protected boolean shouldReport(Candidate c) {
+            MethodResolutionPhase errPhase = resolveContext.firstErroneousResolutionPhase();
             return !c.isApplicable() &&
-                    (((c.sym.flags() & VARARGS) != 0 && c.step == VARARITY) ||
-                      (c.sym.flags() & VARARGS) == 0 && c.step == (boxingEnabled ? BOX : BASIC));
+                    c.step == errPhase;
         }
 
         private Candidate errCandidate() {
-            for (Candidate c : currentResolutionContext.candidates) {
+            for (Candidate c : resolveContext.candidates) {
                 if (shouldReport(c)) {
                     return c;
                 }
@@ -2786,8 +3138,8 @@
      */
     class InapplicableSymbolsError extends InapplicableSymbolError {
 
-        InapplicableSymbolsError() {
-            super(WRONG_MTHS, "inapplicable symbols");
+        InapplicableSymbolsError(MethodResolutionContext context) {
+            super(WRONG_MTHS, "inapplicable symbols", context);
         }
 
         @Override
@@ -2798,7 +3150,7 @@
                 Name name,
                 List<Type> argtypes,
                 List<Type> typeargtypes) {
-            if (currentResolutionContext.candidates.nonEmpty()) {
+            if (!resolveContext.candidates.isEmpty()) {
                 JCDiagnostic err = diags.create(dkind,
                         log.currentSource(),
                         pos,
@@ -2816,7 +3168,7 @@
         //where
         List<JCDiagnostic> candidateDetails(Type site) {
             List<JCDiagnostic> details = List.nil();
-            for (Candidate c : currentResolutionContext.candidates) {
+            for (Candidate c : resolveContext.candidates) {
                 if (!shouldReport(c)) continue;
                 JCDiagnostic detailDiag = diags.fragment("inapplicable.method",
                         Kinds.kindName(c.sym),
@@ -2829,7 +3181,7 @@
         }
 
         private Name getName() {
-            Symbol sym = currentResolutionContext.candidates.head.sym;
+            Symbol sym = resolveContext.candidates.head.sym;
             return sym.name == names.init ?
                 sym.owner.name :
                 sym.name;
@@ -3023,6 +3375,7 @@
                    steps.head.isApplicable(boxingEnabled, varargsEnabled) &&
                    sym.kind >= WRONG_MTHS) {
                 sym = resolutionCache.get(steps.head);
+                if (sym.kind == ABSENT_MTH) break; //ignore spurious empty entries
                 bestSoFar = steps.head;
                 steps = steps.tail;
             }
@@ -3031,8 +3384,7 @@
 
         void addInapplicableCandidate(Symbol sym, JCDiagnostic details) {
             Candidate c = new Candidate(currentResolutionContext.step, sym, details, null);
-            if (!candidates.contains(c))
-                candidates = candidates.append(c);
+            candidates = candidates.append(c);
         }
 
         void addApplicableCandidate(Symbol sym, Type mtype) {
@@ -3040,6 +3392,16 @@
             candidates = candidates.append(c);
         }
 
+        Candidate getCandidate(Symbol sym, MethodResolutionPhase phase) {
+            for (Candidate c : currentResolutionContext.candidates) {
+                if (c.step == phase &&
+                        c.sym.baseSymbol() == sym.baseSymbol()) {
+                    return c;
+                }
+            }
+            return null;
+        }
+
         /**
          * This class represents an overload resolution candidate. There are two
          * kinds of candidates: applicable methods and inapplicable methods;
@@ -3067,9 +3429,9 @@
                     Symbol s1 = this.sym;
                     Symbol s2 = ((Candidate)o).sym;
                     if  ((s1 != s2 &&
-                        (s1.overrides(s2, s1.owner.type.tsym, types, false) ||
-                        (s2.overrides(s1, s2.owner.type.tsym, types, false)))) ||
-                        ((s1.isConstructor() || s2.isConstructor()) && s1.owner != s2.owner))
+                            (s1.overrides(s2, s1.owner.type.tsym, types, false) ||
+                            (s2.overrides(s1, s2.owner.type.tsym, types, false)))) ||
+                            ((s1.isConstructor() || s2.isConstructor()) && s1.owner != s2.owner))
                         return true;
                 }
                 return false;