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) {