--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Fri Aug 30 17:36:47 2013 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Mon Sep 02 22:38:36 2013 +0100
@@ -2368,7 +2368,10 @@
//for each method m1 that is overridden (directly or indirectly)
//by method 'sym' in 'site'...
for (Symbol m1 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) {
- if (!sym.overrides(m1, site.tsym, types, false)) continue;
+ if (!sym.overrides(m1, site.tsym, types, false)) {
+ checkPotentiallyAmbiguousOverloads(pos, site, sym, (MethodSymbol)m1);
+ continue;
+ }
//...check each method m2 that is a member of 'site'
for (Symbol m2 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) {
if (m2 == m1) continue;
@@ -2406,14 +2409,17 @@
for (Symbol s : types.membersClosure(site, true).getElementsByName(sym.name, cf)) {
//if (i) the signature of 'sym' is not a subsignature of m1 (seen as
//a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error
- if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck) &&
- types.hasSameArgs(s.erasure(types), sym.erasure(types))) {
- log.error(pos,
- "name.clash.same.erasure.no.hide",
- sym, sym.location(),
- s, s.location());
- return;
- }
+ if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck)) {
+ if (types.hasSameArgs(s.erasure(types), sym.erasure(types))) {
+ log.error(pos,
+ "name.clash.same.erasure.no.hide",
+ sym, sym.location(),
+ s, s.location());
+ return;
+ } else {
+ checkPotentiallyAmbiguousOverloads(pos, site, sym, (MethodSymbol)s);
+ }
+ }
}
}
@@ -2496,6 +2502,62 @@
}
}
+ /**
+ * Report warnings for potentially ambiguous method declarations. Two declarations
+ * are potentially ambiguous if they feature two unrelated functional interface
+ * in same argument position (in which case, a call site passing an implicit
+ * lambda would be ambiguous).
+ */
+ void checkPotentiallyAmbiguousOverloads(DiagnosticPosition pos, Type site,
+ MethodSymbol msym1, MethodSymbol msym2) {
+ if (msym1 != msym2 &&
+ allowDefaultMethods &&
+ lint.isEnabled(LintCategory.OVERLOADS) &&
+ (msym1.flags() & POTENTIALLY_AMBIGUOUS) == 0 &&
+ (msym2.flags() & POTENTIALLY_AMBIGUOUS) == 0) {
+ Type mt1 = types.memberType(site, msym1);
+ Type mt2 = types.memberType(site, msym2);
+ //if both generic methods, adjust type variables
+ if (mt1.hasTag(FORALL) && mt2.hasTag(FORALL) &&
+ types.hasSameBounds((ForAll)mt1, (ForAll)mt2)) {
+ mt2 = types.subst(mt2, ((ForAll)mt2).tvars, ((ForAll)mt1).tvars);
+ }
+ //expand varargs methods if needed
+ int maxLength = Math.max(mt1.getParameterTypes().length(), mt2.getParameterTypes().length());
+ List<Type> args1 = rs.adjustArgs(mt1.getParameterTypes(), msym1, maxLength, true);
+ List<Type> args2 = rs.adjustArgs(mt2.getParameterTypes(), msym2, maxLength, true);
+ //if arities don't match, exit
+ if (args1.length() != args2.length()) return;
+ boolean potentiallyAmbiguous = false;
+ while (args1.nonEmpty() && args2.nonEmpty()) {
+ Type s = args1.head;
+ Type t = args2.head;
+ if (!types.isSubtype(t, s) && !types.isSubtype(s, t)) {
+ if (types.isFunctionalInterface(s) && types.isFunctionalInterface(t) &&
+ types.findDescriptorType(s).getParameterTypes().length() > 0 &&
+ types.findDescriptorType(s).getParameterTypes().length() ==
+ types.findDescriptorType(t).getParameterTypes().length()) {
+ potentiallyAmbiguous = true;
+ } else {
+ break;
+ }
+ }
+ args1 = args1.tail;
+ args2 = args2.tail;
+ }
+ if (potentiallyAmbiguous) {
+ //we found two incompatible functional interfaces with same arity
+ //this means a call site passing an implicit lambda would be ambigiuous
+ msym1.flags_field |= POTENTIALLY_AMBIGUOUS;
+ msym2.flags_field |= POTENTIALLY_AMBIGUOUS;
+ log.warning(LintCategory.OVERLOADS, pos, "potentially.ambiguous.overload",
+ msym1, msym1.location(),
+ msym2, msym2.location());
+ return;
+ }
+ }
+ }
+
/** Report a conflict between a user symbol and a synthetic symbol.
*/
private void syntheticError(DiagnosticPosition pos, Symbol sym) {