diff -r ea54372637a5 -r 7ae4016c5938 src/share/classes/com/sun/tools/javac/comp/TransTypes.java --- a/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Mon Sep 06 12:55:09 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Tue Sep 07 17:31:54 2010 +0100 @@ -283,12 +283,13 @@ ListBuffer bridges) { if (sym.kind == MTH && sym.name != names.init && - (sym.flags() & (PRIVATE | SYNTHETIC | STATIC)) == 0 && + (sym.flags() & (PRIVATE | STATIC)) == 0 && + (sym.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) != SYNTHETIC && sym.isMemberOf(origin, types)) { MethodSymbol meth = (MethodSymbol)sym; MethodSymbol bridge = meth.binaryImplementation(origin, types); - MethodSymbol impl = meth.implementation(origin, types, true); + MethodSymbol impl = meth.implementation(origin, types, true, overrideBridgeFilter); if (bridge == null || bridge == meth || (impl != null && !bridge.owner.isSubClass(impl.owner, types))) { @@ -304,7 +305,7 @@ // reflection design error. addBridge(pos, meth, impl, origin, false, bridges); } - } else if ((bridge.flags() & SYNTHETIC) != 0) { + } else if ((bridge.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) == SYNTHETIC) { MethodSymbol other = overridden.get(bridge); if (other != null && other != meth) { if (impl == null || !impl.overrides(other, origin, types, true)) { @@ -327,6 +328,11 @@ } } // where + Filter overrideBridgeFilter = new Filter() { + public boolean accepts(Symbol s) { + return (s.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) != SYNTHETIC; + } + }; /** * @param method The symbol for which a bridge might have to be added * @param impl The implementation of method @@ -754,6 +760,90 @@ return types.erasure(t); } + private boolean boundsRestricted(ClassSymbol c) { + Type st = types.supertype(c.type); + if (st.isParameterized()) { + List actuals = st.allparams(); + List formals = st.tsym.type.allparams(); + while (!actuals.isEmpty() && !formals.isEmpty()) { + Type actual = actuals.head; + Type formal = formals.head; + + if (!types.isSameType(types.erasure(actual), + types.erasure(formal))) + return true; + + actuals = actuals.tail; + formals = formals.tail; + } + } + return false; + } + + private List addOverrideBridgesIfNeeded(DiagnosticPosition pos, + final ClassSymbol c) { + ListBuffer buf = ListBuffer.lb(); + if (c.isInterface() || !boundsRestricted(c)) + return buf.toList(); + Type t = types.supertype(c.type); + Scope s = t.tsym.members(); + if (s.elems != null) { + for (Symbol sym : s.getElements(new NeedsOverridBridgeFilter(c))) { + + MethodSymbol m = (MethodSymbol)sym; + MethodSymbol member = (MethodSymbol)m.asMemberOf(c.type, types); + MethodSymbol impl = m.implementation(c, types, false); + + if ((impl == null || impl.owner != c) && + !types.isSameType(member.erasure(types), m.erasure(types))) { + addOverrideBridges(pos, m, member, c, buf); + } + } + } + return buf.toList(); + } + // where + class NeedsOverridBridgeFilter implements Filter { + + ClassSymbol c; + + NeedsOverridBridgeFilter(ClassSymbol c) { + this.c = c; + } + public boolean accepts(Symbol s) { + return s.kind == MTH && + !s.isConstructor() && + s.isInheritedIn(c, types) && + (s.flags() & FINAL) == 0 && + (s.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) != SYNTHETIC; + } + } + + private void addOverrideBridges(DiagnosticPosition pos, + MethodSymbol impl, + MethodSymbol member, + ClassSymbol c, + ListBuffer bridges) { + Type implErasure = impl.erasure(types); + long flags = (impl.flags() & AccessFlags) | SYNTHETIC | BRIDGE | OVERRIDE_BRIDGE; + member = new MethodSymbol(flags, member.name, member.type, c); + JCMethodDecl md = make.MethodDef(member, null); + JCExpression receiver = make.Super(types.supertype(c.type).tsym.erasure(types), c); + Type calltype = erasure(impl.type.getReturnType()); + JCExpression call = + make.Apply(null, + make.Select(receiver, impl).setType(calltype), + translateArgs(make.Idents(md.params), + implErasure.getParameterTypes(), null)) + .setType(calltype); + JCStatement stat = (member.getReturnType().tag == VOID) + ? make.Exec(call) + : make.Return(coerce(call, member.erasure(types).getReturnType())); + md.body = make.Block(0, List.of(stat)); + c.members().enter(member); + bridges.append(md); + } + /************************************************************************** * main method *************************************************************************/ @@ -786,6 +876,7 @@ make.at(tree.pos); if (addBridges) { ListBuffer bridges = new ListBuffer(); + bridges.appendList(addOverrideBridgesIfNeeded(tree, c)); if ((tree.sym.flags() & INTERFACE) == 0) addBridges(tree.pos(), tree.sym, bridges); tree.defs = bridges.toList().prependList(tree.defs);