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

changeset 2000
4a6acc42c3a1
parent 1978
7bf6313e1ced
child 2016
f4efd6ef6e80
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Fri Aug 30 17:36:47 2013 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Sep 02 22:38:36 2013 +0100
     1.3 @@ -2368,7 +2368,10 @@
     1.4          //for each method m1 that is overridden (directly or indirectly)
     1.5          //by method 'sym' in 'site'...
     1.6          for (Symbol m1 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) {
     1.7 -            if (!sym.overrides(m1, site.tsym, types, false)) continue;
     1.8 +             if (!sym.overrides(m1, site.tsym, types, false)) {
     1.9 +                 checkPotentiallyAmbiguousOverloads(pos, site, sym, (MethodSymbol)m1);
    1.10 +                 continue;
    1.11 +             }
    1.12               //...check each method m2 that is a member of 'site'
    1.13               for (Symbol m2 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) {
    1.14                  if (m2 == m1) continue;
    1.15 @@ -2406,14 +2409,17 @@
    1.16          for (Symbol s : types.membersClosure(site, true).getElementsByName(sym.name, cf)) {
    1.17              //if (i) the signature of 'sym' is not a subsignature of m1 (seen as
    1.18              //a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error
    1.19 -            if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck) &&
    1.20 -                    types.hasSameArgs(s.erasure(types), sym.erasure(types))) {
    1.21 -                log.error(pos,
    1.22 -                        "name.clash.same.erasure.no.hide",
    1.23 -                        sym, sym.location(),
    1.24 -                        s, s.location());
    1.25 -                return;
    1.26 -             }
    1.27 +            if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck)) {
    1.28 +                if (types.hasSameArgs(s.erasure(types), sym.erasure(types))) {
    1.29 +                    log.error(pos,
    1.30 +                            "name.clash.same.erasure.no.hide",
    1.31 +                            sym, sym.location(),
    1.32 +                            s, s.location());
    1.33 +                    return;
    1.34 +                } else {
    1.35 +                    checkPotentiallyAmbiguousOverloads(pos, site, sym, (MethodSymbol)s);
    1.36 +                }
    1.37 +            }
    1.38           }
    1.39       }
    1.40  
    1.41 @@ -2496,6 +2502,62 @@
    1.42           }
    1.43       }
    1.44  
    1.45 +    /**
    1.46 +      * Report warnings for potentially ambiguous method declarations. Two declarations
    1.47 +      * are potentially ambiguous if they feature two unrelated functional interface
    1.48 +      * in same argument position (in which case, a call site passing an implicit
    1.49 +      * lambda would be ambiguous).
    1.50 +      */
    1.51 +    void checkPotentiallyAmbiguousOverloads(DiagnosticPosition pos, Type site,
    1.52 +            MethodSymbol msym1, MethodSymbol msym2) {
    1.53 +        if (msym1 != msym2 &&
    1.54 +                allowDefaultMethods &&
    1.55 +                lint.isEnabled(LintCategory.OVERLOADS) &&
    1.56 +                (msym1.flags() & POTENTIALLY_AMBIGUOUS) == 0 &&
    1.57 +                (msym2.flags() & POTENTIALLY_AMBIGUOUS) == 0) {
    1.58 +            Type mt1 = types.memberType(site, msym1);
    1.59 +            Type mt2 = types.memberType(site, msym2);
    1.60 +            //if both generic methods, adjust type variables
    1.61 +            if (mt1.hasTag(FORALL) && mt2.hasTag(FORALL) &&
    1.62 +                    types.hasSameBounds((ForAll)mt1, (ForAll)mt2)) {
    1.63 +                mt2 = types.subst(mt2, ((ForAll)mt2).tvars, ((ForAll)mt1).tvars);
    1.64 +            }
    1.65 +            //expand varargs methods if needed
    1.66 +            int maxLength = Math.max(mt1.getParameterTypes().length(), mt2.getParameterTypes().length());
    1.67 +            List<Type> args1 = rs.adjustArgs(mt1.getParameterTypes(), msym1, maxLength, true);
    1.68 +            List<Type> args2 = rs.adjustArgs(mt2.getParameterTypes(), msym2, maxLength, true);
    1.69 +            //if arities don't match, exit
    1.70 +            if (args1.length() != args2.length()) return;
    1.71 +            boolean potentiallyAmbiguous = false;
    1.72 +            while (args1.nonEmpty() && args2.nonEmpty()) {
    1.73 +                Type s = args1.head;
    1.74 +                Type t = args2.head;
    1.75 +                if (!types.isSubtype(t, s) && !types.isSubtype(s, t)) {
    1.76 +                    if (types.isFunctionalInterface(s) && types.isFunctionalInterface(t) &&
    1.77 +                            types.findDescriptorType(s).getParameterTypes().length() > 0 &&
    1.78 +                            types.findDescriptorType(s).getParameterTypes().length() ==
    1.79 +                            types.findDescriptorType(t).getParameterTypes().length()) {
    1.80 +                        potentiallyAmbiguous = true;
    1.81 +                    } else {
    1.82 +                        break;
    1.83 +                    }
    1.84 +                }
    1.85 +                args1 = args1.tail;
    1.86 +                args2 = args2.tail;
    1.87 +            }
    1.88 +            if (potentiallyAmbiguous) {
    1.89 +                //we found two incompatible functional interfaces with same arity
    1.90 +                //this means a call site passing an implicit lambda would be ambigiuous
    1.91 +                msym1.flags_field |= POTENTIALLY_AMBIGUOUS;
    1.92 +                msym2.flags_field |= POTENTIALLY_AMBIGUOUS;
    1.93 +                log.warning(LintCategory.OVERLOADS, pos, "potentially.ambiguous.overload",
    1.94 +                            msym1, msym1.location(),
    1.95 +                            msym2, msym2.location());
    1.96 +                return;
    1.97 +            }
    1.98 +        }
    1.99 +    }
   1.100 +
   1.101      /** Report a conflict between a user symbol and a synthetic symbol.
   1.102       */
   1.103      private void syntheticError(DiagnosticPosition pos, Symbol sym) {

mercurial