Thu, 11 Jul 2013 14:07:39 +0100
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
8020010: Move lambda bridge creation from metafactory and VM to compiler
Summary: langtools/javac component of the bridge support and MethodType vs. MethodHandle changes.
Reviewed-by: jjg, vromero, briangoetz, forax
Contributed-by: robert.field@oracle.com
1.1 --- a/src/share/classes/com/sun/tools/javac/code/Types.java Thu Jul 11 10:13:57 2013 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java Thu Jul 11 14:07:39 2013 +0100 1.3 @@ -33,10 +33,15 @@ 1.4 import java.util.Set; 1.5 import java.util.WeakHashMap; 1.6 1.7 +import javax.tools.JavaFileObject; 1.8 + 1.9 import com.sun.tools.javac.code.Attribute.RetentionPolicy; 1.10 import com.sun.tools.javac.code.Lint.LintCategory; 1.11 import com.sun.tools.javac.code.Type.UndetVar.InferenceBound; 1.12 +import com.sun.tools.javac.comp.AttrContext; 1.13 import com.sun.tools.javac.comp.Check; 1.14 +import com.sun.tools.javac.comp.Enter; 1.15 +import com.sun.tools.javac.comp.Env; 1.16 import com.sun.tools.javac.jvm.ClassReader; 1.17 import com.sun.tools.javac.util.*; 1.18 import static com.sun.tools.javac.code.BoundKind.*; 1.19 @@ -83,6 +88,7 @@ 1.20 final boolean allowDefaultMethods; 1.21 final ClassReader reader; 1.22 final Check chk; 1.23 + final Enter enter; 1.24 JCDiagnostic.Factory diags; 1.25 List<Warner> warnStack = List.nil(); 1.26 final Name capturedName; 1.27 @@ -109,6 +115,7 @@ 1.28 allowDefaultMethods = source.allowDefaultMethods(); 1.29 reader = ClassReader.instance(context); 1.30 chk = Check.instance(context); 1.31 + enter = Enter.instance(context); 1.32 capturedName = names.fromString("<captured wildcard>"); 1.33 messages = JavacMessages.instance(context); 1.34 diags = JCDiagnostic.Factory.instance(context); 1.35 @@ -605,6 +612,84 @@ 1.36 return site; 1.37 } 1.38 } 1.39 + 1.40 + /** 1.41 + * Create a symbol for a class that implements a given functional interface 1.42 + * and overrides its functional descriptor. This routine is used for two 1.43 + * main purposes: (i) checking well-formedness of a functional interface; 1.44 + * (ii) perform functional interface bridge calculation. 1.45 + */ 1.46 + public ClassSymbol makeFunctionalInterfaceClass(Env<AttrContext> env, Name name, List<Type> targets, long cflags) { 1.47 + Assert.check(targets.nonEmpty() && isFunctionalInterface(targets.head)); 1.48 + Symbol descSym = findDescriptorSymbol(targets.head.tsym); 1.49 + Type descType = findDescriptorType(targets.head); 1.50 + ClassSymbol csym = new ClassSymbol(cflags, name, env.enclClass.sym.outermostClass()); 1.51 + csym.completer = null; 1.52 + csym.members_field = new Scope(csym); 1.53 + MethodSymbol instDescSym = new MethodSymbol(descSym.flags(), descSym.name, descType, csym); 1.54 + csym.members_field.enter(instDescSym); 1.55 + Type.ClassType ctype = new Type.ClassType(Type.noType, List.<Type>nil(), csym); 1.56 + ctype.supertype_field = syms.objectType; 1.57 + ctype.interfaces_field = targets; 1.58 + csym.type = ctype; 1.59 + csym.sourcefile = ((ClassSymbol)csym.owner).sourcefile; 1.60 + return csym; 1.61 + } 1.62 + 1.63 + /** 1.64 + * Find the minimal set of methods that are overridden by the functional 1.65 + * descriptor in 'origin'. All returned methods are assumed to have different 1.66 + * erased signatures. 1.67 + */ 1.68 + public List<Symbol> functionalInterfaceBridges(TypeSymbol origin) { 1.69 + Assert.check(isFunctionalInterface(origin)); 1.70 + Symbol descSym = findDescriptorSymbol(origin); 1.71 + CompoundScope members = membersClosure(origin.type, false); 1.72 + ListBuffer<Symbol> overridden = ListBuffer.lb(); 1.73 + outer: for (Symbol m2 : members.getElementsByName(descSym.name, bridgeFilter)) { 1.74 + if (m2 == descSym) continue; 1.75 + else if (descSym.overrides(m2, origin, Types.this, false)) { 1.76 + for (Symbol m3 : overridden) { 1.77 + if (isSameType(m3.erasure(Types.this), m2.erasure(Types.this)) || 1.78 + (m3.overrides(m2, origin, Types.this, false) && 1.79 + (pendingBridges((ClassSymbol)origin, m3.enclClass()) || 1.80 + (((MethodSymbol)m2).binaryImplementation((ClassSymbol)m3.owner, Types.this) != null)))) { 1.81 + continue outer; 1.82 + } 1.83 + } 1.84 + overridden.add(m2); 1.85 + } 1.86 + } 1.87 + return overridden.toList(); 1.88 + } 1.89 + //where 1.90 + private Filter<Symbol> bridgeFilter = new Filter<Symbol>() { 1.91 + public boolean accepts(Symbol t) { 1.92 + return t.kind == Kinds.MTH && 1.93 + t.name != names.init && 1.94 + t.name != names.clinit && 1.95 + (t.flags() & SYNTHETIC) == 0; 1.96 + } 1.97 + }; 1.98 + private boolean pendingBridges(ClassSymbol origin, TypeSymbol s) { 1.99 + //a symbol will be completed from a classfile if (a) symbol has 1.100 + //an associated file object with CLASS kind and (b) the symbol has 1.101 + //not been entered 1.102 + if (origin.classfile != null && 1.103 + origin.classfile.getKind() == JavaFileObject.Kind.CLASS && 1.104 + enter.getEnv(origin) == null) { 1.105 + return false; 1.106 + } 1.107 + if (origin == s) { 1.108 + return true; 1.109 + } 1.110 + for (Type t : interfaces(origin.type)) { 1.111 + if (pendingBridges((ClassSymbol)t.tsym, s)) { 1.112 + return true; 1.113 + } 1.114 + } 1.115 + return false; 1.116 + } 1.117 // </editor-fold> 1.118 1.119 /** 1.120 @@ -2672,6 +2757,7 @@ 1.121 public boolean accepts(Symbol s) { 1.122 return s.kind == Kinds.MTH && 1.123 s.name == msym.name && 1.124 + (s.flags() & SYNTHETIC) == 0 && 1.125 s.isInheritedIn(site.tsym, Types.this) && 1.126 overrideEquivalent(memberType(site, s), memberType(site, msym)); 1.127 }
2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Jul 11 10:13:57 2013 -0700 2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Jul 11 14:07:39 2013 +0100 2.3 @@ -2334,13 +2334,12 @@ 2.4 if (pt() != Type.recoveryType) { 2.5 target = targetChecker.visit(target, that); 2.6 lambdaType = types.findDescriptorType(target); 2.7 - chk.checkFunctionalInterface(that, target); 2.8 } else { 2.9 target = Type.recoveryType; 2.10 lambdaType = fallbackDescriptorType(that); 2.11 } 2.12 2.13 - setFunctionalInfo(that, pt(), lambdaType, target, resultInfo.checkContext.inferenceContext()); 2.14 + setFunctionalInfo(localEnv, that, pt(), lambdaType, target, resultInfo.checkContext); 2.15 2.16 if (lambdaType.hasTag(FORALL)) { 2.17 //lambda expression target desc cannot be a generic method 2.18 @@ -2682,13 +2681,12 @@ 2.19 if (pt() != Type.recoveryType) { 2.20 target = targetChecker.visit(pt(), that); 2.21 desc = types.findDescriptorType(target); 2.22 - chk.checkFunctionalInterface(that, target); 2.23 } else { 2.24 target = Type.recoveryType; 2.25 desc = fallbackDescriptorType(that); 2.26 } 2.27 2.28 - setFunctionalInfo(that, pt(), desc, target, resultInfo.checkContext.inferenceContext()); 2.29 + setFunctionalInfo(localEnv, that, pt(), desc, target, resultInfo.checkContext); 2.30 List<Type> argtypes = desc.getParameterTypes(); 2.31 2.32 Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = 2.33 @@ -2890,31 +2888,37 @@ 2.34 * might contain inference variables, we might need to register an hook in the 2.35 * current inference context. 2.36 */ 2.37 - private void setFunctionalInfo(final JCFunctionalExpression fExpr, final Type pt, 2.38 - final Type descriptorType, final Type primaryTarget, InferenceContext inferenceContext) { 2.39 - if (inferenceContext.free(descriptorType)) { 2.40 - inferenceContext.addFreeTypeListener(List.of(pt, descriptorType), new FreeTypeListener() { 2.41 + private void setFunctionalInfo(final Env<AttrContext> env, final JCFunctionalExpression fExpr, 2.42 + final Type pt, final Type descriptorType, final Type primaryTarget, final CheckContext checkContext) { 2.43 + if (checkContext.inferenceContext().free(descriptorType)) { 2.44 + checkContext.inferenceContext().addFreeTypeListener(List.of(pt, descriptorType), new FreeTypeListener() { 2.45 public void typesInferred(InferenceContext inferenceContext) { 2.46 - setFunctionalInfo(fExpr, pt, inferenceContext.asInstType(descriptorType), 2.47 - inferenceContext.asInstType(primaryTarget), inferenceContext); 2.48 + setFunctionalInfo(env, fExpr, pt, inferenceContext.asInstType(descriptorType), 2.49 + inferenceContext.asInstType(primaryTarget), checkContext); 2.50 } 2.51 }); 2.52 } else { 2.53 - ListBuffer<TypeSymbol> targets = ListBuffer.lb(); 2.54 + ListBuffer<Type> targets = ListBuffer.lb(); 2.55 if (pt.hasTag(CLASS)) { 2.56 if (pt.isCompound()) { 2.57 - targets.append(primaryTarget.tsym); //this goes first 2.58 + targets.append(types.removeWildcards(primaryTarget)); //this goes first 2.59 for (Type t : ((IntersectionClassType)pt()).interfaces_field) { 2.60 if (t != primaryTarget) { 2.61 - targets.append(t.tsym); 2.62 + targets.append(types.removeWildcards(t)); 2.63 } 2.64 } 2.65 } else { 2.66 - targets.append(pt.tsym); 2.67 + targets.append(types.removeWildcards(primaryTarget)); 2.68 } 2.69 } 2.70 fExpr.targets = targets.toList(); 2.71 - fExpr.descriptorType = descriptorType; 2.72 + if (checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK && 2.73 + pt != Type.recoveryType) { 2.74 + //check that functional interface class is well-formed 2.75 + ClassSymbol csym = types.makeFunctionalInterfaceClass(env, 2.76 + names.empty, List.of(fExpr.targets.head), ABSTRACT); 2.77 + chk.checkImplementations(env.tree, csym, csym); 2.78 + } 2.79 } 2.80 } 2.81 2.82 @@ -4579,9 +4583,6 @@ 2.83 @Override 2.84 public void visitLambda(JCLambda that) { 2.85 super.visitLambda(that); 2.86 - if (that.descriptorType == null) { 2.87 - that.descriptorType = syms.unknownType; 2.88 - } 2.89 if (that.targets == null) { 2.90 that.targets = List.nil(); 2.91 } 2.92 @@ -4593,9 +4594,6 @@ 2.93 if (that.sym == null) { 2.94 that.sym = new MethodSymbol(0, names.empty, syms.unknownType, syms.noSymbol); 2.95 } 2.96 - if (that.descriptorType == null) { 2.97 - that.descriptorType = syms.unknownType; 2.98 - } 2.99 if (that.targets == null) { 2.100 that.targets = List.nil(); 2.101 }
3.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Thu Jul 11 10:13:57 2013 -0700 3.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Thu Jul 11 14:07:39 2013 +0100 3.3 @@ -2275,24 +2275,6 @@ 3.4 c.flags_field |= ACYCLIC; 3.5 } 3.6 3.7 - /** 3.8 - * Check that functional interface methods would make sense when seen 3.9 - * from the perspective of the implementing class 3.10 - */ 3.11 - void checkFunctionalInterface(JCTree tree, Type funcInterface) { 3.12 - ClassType c = new ClassType(Type.noType, List.<Type>nil(), null); 3.13 - ClassSymbol csym = new ClassSymbol(0, names.empty, c, syms.noSymbol); 3.14 - c.interfaces_field = List.of(types.removeWildcards(funcInterface)); 3.15 - c.supertype_field = syms.objectType; 3.16 - c.tsym = csym; 3.17 - csym.members_field = new Scope(csym); 3.18 - Symbol descSym = types.findDescriptorSymbol(funcInterface.tsym); 3.19 - Type descType = types.findDescriptorType(funcInterface); 3.20 - csym.members_field.enter(new MethodSymbol(PUBLIC, descSym.name, descType, csym)); 3.21 - csym.completer = null; 3.22 - checkImplementations(tree, csym, csym); 3.23 - } 3.24 - 3.25 /** Check that all methods which implement some 3.26 * method conform to the method they implement. 3.27 * @param tree The class definition whose members are checked.
4.1 --- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Thu Jul 11 10:13:57 2013 -0700 4.2 +++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Thu Jul 11 14:07:39 2013 +0100 4.3 @@ -100,6 +100,9 @@ 4.4 /** Flag for alternate metafactories indicating the lambda object has multiple targets */ 4.5 public static final int FLAG_MARKERS = 1 << 1; 4.6 4.7 + /** Flag for alternate metafactories indicating the lambda object requires multiple bridges */ 4.8 + public static final int FLAG_BRIDGES = 1 << 2; 4.9 + 4.10 private class KlassInfo { 4.11 4.12 /** 4.13 @@ -321,7 +324,7 @@ 4.14 int refKind = referenceKind(sym); 4.15 4.16 //convert to an invokedynamic call 4.17 - result = makeMetaFactoryIndyCall(tree, context.needsAltMetafactory(), context.isSerializable(), refKind, sym, indy_args); 4.18 + result = makeMetafactoryIndyCall(context, refKind, sym, indy_args); 4.19 } 4.20 4.21 private JCIdent makeThis(Type type, Symbol owner) { 4.22 @@ -382,7 +385,7 @@ 4.23 4.24 4.25 //build a sam instance using an indy call to the meta-factory 4.26 - result = makeMetaFactoryIndyCall(tree, localContext.needsAltMetafactory(), localContext.isSerializable(), localContext.referenceKind(), refSym, indy_args); 4.27 + result = makeMetafactoryIndyCall(localContext, localContext.referenceKind(), refSym, indy_args); 4.28 } 4.29 4.30 /** 4.31 @@ -606,8 +609,8 @@ 4.32 make.Return(makeIndyCall( 4.33 pos, 4.34 syms.lambdaMetafactory, 4.35 - names.altMetaFactory, 4.36 - staticArgs, indyType, serArgs.toList())), 4.37 + names.altMetafactory, 4.38 + staticArgs, indyType, serArgs.toList(), samSym.name)), 4.39 null); 4.40 ListBuffer<JCStatement> stmts = kInfo.deserializeCases.get(implMethodName); 4.41 if (stmts == null) { 4.42 @@ -905,22 +908,26 @@ 4.43 kInfo.addMethod(new MemberReferenceBridger(tree, localContext).bridge()); 4.44 } 4.45 4.46 + private MethodType typeToMethodType(Type mt) { 4.47 + Type type = types.erasure(mt); 4.48 + return new MethodType(type.getParameterTypes(), 4.49 + type.getReturnType(), 4.50 + type.getThrownTypes(), 4.51 + syms.methodClass); 4.52 + } 4.53 + 4.54 /** 4.55 * Generate an indy method call to the meta factory 4.56 */ 4.57 - private JCExpression makeMetaFactoryIndyCall(JCFunctionalExpression tree, boolean needsAltMetafactory, 4.58 - boolean isSerializable, int refKind, Symbol refSym, List<JCExpression> indy_args) { 4.59 + private JCExpression makeMetafactoryIndyCall(TranslationContext<?> context, 4.60 + int refKind, Symbol refSym, List<JCExpression> indy_args) { 4.61 + JCFunctionalExpression tree = context.tree; 4.62 //determine the static bsm args 4.63 - Type mtype = types.erasure(tree.descriptorType); 4.64 MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym); 4.65 List<Object> staticArgs = List.<Object>of( 4.66 - new Pool.MethodHandle(ClassFile.REF_invokeInterface, 4.67 - types.findDescriptorSymbol(tree.type.tsym), types), 4.68 + typeToMethodType(samSym.type), 4.69 new Pool.MethodHandle(refKind, refSym, types), 4.70 - new MethodType(mtype.getParameterTypes(), 4.71 - mtype.getReturnType(), 4.72 - mtype.getThrownTypes(), 4.73 - syms.methodClass)); 4.74 + typeToMethodType(tree.getDescriptorType(types))); 4.75 4.76 //computed indy arg types 4.77 ListBuffer<Type> indy_args_types = ListBuffer.lb(); 4.78 @@ -934,31 +941,46 @@ 4.79 List.<Type>nil(), 4.80 syms.methodClass); 4.81 4.82 - Name metafactoryName = needsAltMetafactory ? 4.83 - names.altMetaFactory : names.metaFactory; 4.84 + Name metafactoryName = context.needsAltMetafactory() ? 4.85 + names.altMetafactory : names.metafactory; 4.86 4.87 - if (needsAltMetafactory) { 4.88 + if (context.needsAltMetafactory()) { 4.89 ListBuffer<Object> markers = ListBuffer.lb(); 4.90 - for (Symbol t : tree.targets.tail) { 4.91 - if (t != syms.serializableType.tsym) { 4.92 - markers.append(t); 4.93 + for (Type t : tree.targets.tail) { 4.94 + if (t.tsym != syms.serializableType.tsym) { 4.95 + markers.append(t.tsym); 4.96 } 4.97 } 4.98 - int flags = isSerializable? FLAG_SERIALIZABLE : 0; 4.99 + int flags = context.isSerializable() ? FLAG_SERIALIZABLE : 0; 4.100 boolean hasMarkers = markers.nonEmpty(); 4.101 - flags |= hasMarkers ? FLAG_MARKERS : 0; 4.102 + boolean hasBridges = context.bridges.nonEmpty(); 4.103 + if (hasMarkers) { 4.104 + flags |= FLAG_MARKERS; 4.105 + } 4.106 + if (hasBridges) { 4.107 + flags |= FLAG_BRIDGES; 4.108 + } 4.109 staticArgs = staticArgs.append(flags); 4.110 if (hasMarkers) { 4.111 staticArgs = staticArgs.append(markers.length()); 4.112 staticArgs = staticArgs.appendList(markers.toList()); 4.113 } 4.114 - if (isSerializable) { 4.115 + if (hasBridges) { 4.116 + staticArgs = staticArgs.append(context.bridges.length() - 1); 4.117 + for (Symbol s : context.bridges) { 4.118 + Type s_erasure = s.erasure(types); 4.119 + if (!types.isSameType(s_erasure, samSym.erasure(types))) { 4.120 + staticArgs = staticArgs.append(s.erasure(types)); 4.121 + } 4.122 + } 4.123 + } 4.124 + if (context.isSerializable()) { 4.125 addDeserializationCase(refKind, refSym, tree.type, samSym, 4.126 tree, staticArgs, indyType); 4.127 } 4.128 } 4.129 4.130 - return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args); 4.131 + return makeIndyCall(tree, syms.lambdaMetafactory, metafactoryName, staticArgs, indyType, indy_args, samSym.name); 4.132 } 4.133 4.134 /** 4.135 @@ -966,7 +988,8 @@ 4.136 * arguments types 4.137 */ 4.138 private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName, 4.139 - List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs) { 4.140 + List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs, 4.141 + Name methName) { 4.142 int prevPos = make.pos; 4.143 try { 4.144 make.at(pos); 4.145 @@ -978,7 +1001,7 @@ 4.146 bsmName, bsm_staticArgs, List.<Type>nil()); 4.147 4.148 DynamicMethodSymbol dynSym = 4.149 - new DynamicMethodSymbol(names.lambda, 4.150 + new DynamicMethodSymbol(methName, 4.151 syms.noSymbol, 4.152 bsm.isStatic() ? 4.153 ClassFile.REF_invokeStatic : 4.154 @@ -1299,7 +1322,6 @@ 4.155 4.156 // Make lambda holding the new-class call 4.157 JCLambda slam = make.Lambda(params, nc); 4.158 - slam.descriptorType = tree.descriptorType; 4.159 slam.targets = tree.targets; 4.160 slam.type = tree.type; 4.161 slam.pos = tree.pos; 4.162 @@ -1634,23 +1656,30 @@ 4.163 /** the enclosing translation context (set for nested lambdas/mref) */ 4.164 TranslationContext<?> prev; 4.165 4.166 + /** list of methods to be bridged by the meta-factory */ 4.167 + List<Symbol> bridges; 4.168 + 4.169 TranslationContext(T tree) { 4.170 this.tree = tree; 4.171 this.owner = owner(); 4.172 this.depth = frameStack.size() - 1; 4.173 this.prev = context(); 4.174 + ClassSymbol csym = 4.175 + types.makeFunctionalInterfaceClass(attrEnv, names.empty, tree.targets, ABSTRACT | INTERFACE); 4.176 + this.bridges = types.functionalInterfaceBridges(csym); 4.177 } 4.178 4.179 /** does this functional expression need to be created using alternate metafactory? */ 4.180 boolean needsAltMetafactory() { 4.181 - return (tree.targets.length() > 1 || 4.182 - isSerializable()); 4.183 + return tree.targets.length() > 1 || 4.184 + isSerializable() || 4.185 + bridges.length() > 1; 4.186 } 4.187 4.188 /** does this functional expression require serialization support? */ 4.189 boolean isSerializable() { 4.190 - for (Symbol target : tree.targets) { 4.191 - if (types.asSuper(target.type, syms.serializableType.tsym) != null) { 4.192 + for (Type target : tree.targets) { 4.193 + if (types.asSuper(target, syms.serializableType.tsym) != null) { 4.194 return true; 4.195 } 4.196 } 4.197 @@ -1833,7 +1862,7 @@ 4.198 } 4.199 4.200 Type generatedLambdaSig() { 4.201 - return types.erasure(tree.descriptorType); 4.202 + return types.erasure(tree.getDescriptorType(types)); 4.203 } 4.204 } 4.205 4.206 @@ -1909,7 +1938,7 @@ 4.207 } 4.208 4.209 Type bridgedRefSig() { 4.210 - return types.erasure(types.findDescriptorSymbol(tree.targets.head).type); 4.211 + return types.erasure(types.findDescriptorSymbol(tree.targets.head.tsym).type); 4.212 } 4.213 } 4.214 }
5.1 --- a/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Thu Jul 11 10:13:57 2013 -0700 5.2 +++ b/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Thu Jul 11 14:07:39 2013 +0100 5.3 @@ -68,6 +68,7 @@ 5.4 private TreeMaker make; 5.5 private Enter enter; 5.6 private boolean allowEnums; 5.7 + private boolean allowInterfaceBridges; 5.8 private Types types; 5.9 private final Resolve resolve; 5.10 5.11 @@ -91,6 +92,7 @@ 5.12 Source source = Source.instance(context); 5.13 allowEnums = source.allowEnums(); 5.14 addBridges = source.addBridges(); 5.15 + allowInterfaceBridges = source.allowDefaultMethods(); 5.16 types = Types.instance(context); 5.17 make = TreeMaker.instance(context); 5.18 resolve = Resolve.instance(context); 5.19 @@ -252,7 +254,8 @@ 5.20 5.21 // Create a bridge method symbol and a bridge definition without a body. 5.22 Type bridgeType = meth.erasure(types); 5.23 - long flags = impl.flags() & AccessFlags | SYNTHETIC | BRIDGE; 5.24 + long flags = impl.flags() & AccessFlags | SYNTHETIC | BRIDGE | 5.25 + (origin.isInterface() ? DEFAULT : 0); 5.26 if (hypothetical) flags |= HYPOTHETICAL; 5.27 MethodSymbol bridge = new MethodSymbol(flags, 5.28 meth.name, 5.29 @@ -387,11 +390,12 @@ 5.30 } 5.31 } 5.32 // where 5.33 - Filter<Symbol> overrideBridgeFilter = new Filter<Symbol>() { 5.34 + private Filter<Symbol> overrideBridgeFilter = new Filter<Symbol>() { 5.35 public boolean accepts(Symbol s) { 5.36 return (s.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) != SYNTHETIC; 5.37 } 5.38 }; 5.39 + 5.40 /** 5.41 * @param method The symbol for which a bridge might have to be added 5.42 * @param impl The implementation of method 5.43 @@ -999,8 +1003,9 @@ 5.44 ListBuffer<JCTree> bridges = new ListBuffer<JCTree>(); 5.45 if (false) //see CR: 6996415 5.46 bridges.appendList(addOverrideBridgesIfNeeded(tree, c)); 5.47 - if ((tree.sym.flags() & INTERFACE) == 0) 5.48 - addBridges(tree.pos(), tree.sym, bridges); 5.49 + if (allowInterfaceBridges || (tree.sym.flags() & INTERFACE) == 0) { 5.50 + addBridges(tree.pos(), c, bridges); 5.51 + } 5.52 tree.defs = bridges.toList().prependList(tree.defs); 5.53 } 5.54 tree.type = erasure(tree.type);
6.1 --- a/src/share/classes/com/sun/tools/javac/tree/JCTree.java Thu Jul 11 10:13:57 2013 -0700 6.2 +++ b/src/share/classes/com/sun/tools/javac/tree/JCTree.java Thu Jul 11 14:07:39 2013 +0100 6.3 @@ -641,10 +641,12 @@ 6.4 polyKind = PolyKind.POLY; 6.5 } 6.6 6.7 - /** target descriptor inferred for this functional expression. */ 6.8 - public Type descriptorType; 6.9 /** list of target types inferred for this functional expression. */ 6.10 - public List<TypeSymbol> targets; 6.11 + public List<Type> targets; 6.12 + 6.13 + public Type getDescriptorType(Types types) { 6.14 + return types.findDescriptorType(targets.head); 6.15 + } 6.16 } 6.17 6.18 /**
7.1 --- a/src/share/classes/com/sun/tools/javac/util/Names.java Thu Jul 11 10:13:57 2013 -0700 7.2 +++ b/src/share/classes/com/sun/tools/javac/util/Names.java Thu Jul 11 14:07:39 2013 +0100 7.3 @@ -174,8 +174,8 @@ 7.4 7.5 //lambda-related 7.6 public final Name lambda; 7.7 - public final Name metaFactory; 7.8 - public final Name altMetaFactory; 7.9 + public final Name metafactory; 7.10 + public final Name altMetafactory; 7.11 7.12 public final Name.Table table; 7.13 7.14 @@ -310,8 +310,8 @@ 7.15 7.16 //lambda-related 7.17 lambda = fromString("lambda$"); 7.18 - metaFactory = fromString("metaFactory"); 7.19 - altMetaFactory = fromString("altMetaFactory"); 7.20 + metafactory = fromString("metafactory"); 7.21 + altMetafactory = fromString("altMetafactory"); 7.22 } 7.23 7.24 protected Name.Table createTable(Options options) {
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/test/tools/javac/generics/bridges/Bridge.java Thu Jul 11 14:07:39 2013 +0100 8.3 @@ -0,0 +1,28 @@ 8.4 +/* 8.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.7 + * 8.8 + * This code is free software; you can redistribute it and/or modify it 8.9 + * under the terms of the GNU General Public License version 2 only, as 8.10 + * published by the Free Software Foundation. 8.11 + * 8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 8.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 8.15 + * version 2 for more details (a copy is included in the LICENSE file that 8.16 + * accompanied this code). 8.17 + * 8.18 + * You should have received a copy of the GNU General Public License version 8.19 + * 2 along with this work; if not, write to the Free Software Foundation, 8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 8.21 + * 8.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 8.23 + * or visit www.oracle.com if you need additional information or have any 8.24 + * questions. 8.25 + */ 8.26 +import java.lang.annotation.Repeatable; 8.27 + 8.28 +@Repeatable(Bridges.class) 8.29 +@interface Bridge { 8.30 + String value(); 8.31 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/test/tools/javac/generics/bridges/BridgeHarness.java Thu Jul 11 14:07:39 2013 +0100 9.3 @@ -0,0 +1,218 @@ 9.4 +/* 9.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 9.7 + * 9.8 + * This code is free software; you can redistribute it and/or modify it 9.9 + * under the terms of the GNU General Public License version 2 only, as 9.10 + * published by the Free Software Foundation. 9.11 + * 9.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 9.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 9.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 9.15 + * version 2 for more details (a copy is included in the LICENSE file that 9.16 + * accompanied this code). 9.17 + * 9.18 + * You should have received a copy of the GNU General Public License version 9.19 + * 2 along with this work; if not, write to the Free Software Foundation, 9.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 9.21 + * 9.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 9.23 + * or visit www.oracle.com if you need additional information or have any 9.24 + * questions. 9.25 + */ 9.26 + 9.27 +/* 9.28 + * @test 9.29 + * @bug 8013789 9.30 + * @summary Compiler should emit bridges in interfaces 9.31 + * @library /tools/javac/lib 9.32 + * @build JavacTestingAbstractProcessor BridgeHarness 9.33 + * @run main BridgeHarness 9.34 + */ 9.35 + 9.36 +import com.sun.source.util.JavacTask; 9.37 +import com.sun.tools.classfile.AccessFlags; 9.38 +import com.sun.tools.classfile.ClassFile; 9.39 +import com.sun.tools.classfile.ConstantPool; 9.40 +import com.sun.tools.classfile.ConstantPoolException; 9.41 +import com.sun.tools.classfile.Method; 9.42 +import com.sun.tools.javac.code.Symbol.ClassSymbol; 9.43 +import com.sun.tools.javac.util.List; 9.44 + 9.45 +import java.io.File; 9.46 +import java.util.Arrays; 9.47 +import java.util.Collections; 9.48 +import java.util.HashMap; 9.49 +import java.util.Map; 9.50 +import java.util.Set; 9.51 + 9.52 +import javax.annotation.processing.RoundEnvironment; 9.53 +import javax.annotation.processing.SupportedAnnotationTypes; 9.54 +import javax.lang.model.element.Element; 9.55 +import javax.lang.model.element.TypeElement; 9.56 +import javax.tools.JavaCompiler; 9.57 +import javax.tools.JavaFileObject; 9.58 +import javax.tools.StandardJavaFileManager; 9.59 +import javax.tools.ToolProvider; 9.60 + 9.61 +import static javax.tools.StandardLocation.*; 9.62 + 9.63 +public class BridgeHarness { 9.64 + 9.65 + /** number of errors found (must be zero for the test to pass) */ 9.66 + static int nerrors = 0; 9.67 + 9.68 + /** the (shared) Java compiler used for compiling the tests */ 9.69 + static final JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); 9.70 + 9.71 + /** the (shared) file manager used by the compiler */ 9.72 + static final StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); 9.73 + 9.74 + public static void main(String[] args) throws Exception { 9.75 + //set sourcepath 9.76 + fm.setLocation(SOURCE_PATH, 9.77 + Arrays.asList(new File(System.getProperty("test.src"), "tests"))); 9.78 + //set output (-d) 9.79 + fm.setLocation(javax.tools.StandardLocation.CLASS_OUTPUT, 9.80 + Arrays.asList(new File(System.getProperty("user.dir")))); 9.81 + for (JavaFileObject jfo : fm.list(SOURCE_PATH, "", Collections.singleton(JavaFileObject.Kind.SOURCE), true)) { 9.82 + //for each source, compile and check against annotations 9.83 + new BridgeHarness(jfo).compileAndCheck(); 9.84 + } 9.85 + //if there were errors, fail 9.86 + if (nerrors > 0) { 9.87 + throw new AssertionError("Errors were found"); 9.88 + } 9.89 + } 9.90 + 9.91 + /* utility methods */ 9.92 + 9.93 + /** 9.94 + * Remove an element from a list 9.95 + */ 9.96 + static <Z> List<Z> drop(List<Z> lz, Z z) { 9.97 + if (lz.head == z) { 9.98 + return drop(lz.tail, z); 9.99 + } else if (lz.isEmpty()) { 9.100 + return lz; 9.101 + } else { 9.102 + return drop(lz.tail, z).prepend(lz.head); 9.103 + } 9.104 + } 9.105 + 9.106 + /** 9.107 + * return a string representation of a bytecode method 9.108 + */ 9.109 + static String descriptor(Method m, ConstantPool cp) throws ConstantPoolException { 9.110 + return m.getName(cp) + m.descriptor.getValue(cp); 9.111 + } 9.112 + 9.113 + /* test harness */ 9.114 + 9.115 + /** Test file to be compiled */ 9.116 + JavaFileObject jfo; 9.117 + 9.118 + /** Mapping between class name and list of bridges in class with that name */ 9.119 + Map<String, List<Bridge>> bridgesMap = new HashMap<String, List<Bridge>>(); 9.120 + 9.121 + protected BridgeHarness(JavaFileObject jfo) { 9.122 + this.jfo = jfo; 9.123 + } 9.124 + 9.125 + /** 9.126 + * Compile a test using a custom annotation processor and check the generated 9.127 + * bytecode against discovered annotations. 9.128 + */ 9.129 + protected void compileAndCheck() throws Exception { 9.130 + JavacTask ct = (JavacTask)comp.getTask(null, fm, null, null, null, Arrays.asList(jfo)); 9.131 + ct.setProcessors(Collections.singleton(new BridgeFinder())); 9.132 + 9.133 + for (JavaFileObject jfo : ct.generate()) { 9.134 + checkBridges(jfo); 9.135 + } 9.136 + } 9.137 + 9.138 + /** 9.139 + * Check that every bridge in the generated classfile has a matching bridge 9.140 + * annotation in the bridge map 9.141 + */ 9.142 + protected void checkBridges(JavaFileObject jfo) { 9.143 + try { 9.144 + ClassFile cf = ClassFile.read(jfo.openInputStream()); 9.145 + System.err.println("checking: " + cf.getName()); 9.146 + 9.147 + List<Bridge> bridgeList = bridgesMap.get(cf.getName()); 9.148 + if (bridgeList == null) { 9.149 + //no bridges - nothing to check; 9.150 + bridgeList = List.nil(); 9.151 + } 9.152 + 9.153 + for (Method m : cf.methods) { 9.154 + if (m.access_flags.is(AccessFlags.ACC_SYNTHETIC | AccessFlags.ACC_BRIDGE)) { 9.155 + //this is a bridge - see if there's a match in the bridge list 9.156 + Bridge match = null; 9.157 + for (Bridge b : bridgeList) { 9.158 + if (b.value().equals(descriptor(m, cf.constant_pool))) { 9.159 + match = b; 9.160 + break; 9.161 + } 9.162 + } 9.163 + if (match == null) { 9.164 + error("No annotation for bridge method: " + descriptor(m, cf.constant_pool)); 9.165 + } else { 9.166 + bridgeList = drop(bridgeList, match); 9.167 + } 9.168 + } 9.169 + } 9.170 + if (bridgeList.nonEmpty()) { 9.171 + error("Redundant bridge annotation found: " + bridgeList.head.value()); 9.172 + } 9.173 + } catch (Exception e) { 9.174 + e.printStackTrace(); 9.175 + throw new Error("error reading " + jfo.toUri() +": " + e); 9.176 + } 9.177 + } 9.178 + 9.179 + /** 9.180 + * Log an error 9.181 + */ 9.182 + protected void error(String msg) { 9.183 + nerrors++; 9.184 + System.err.printf("Error occurred while checking file: %s\nreason: %s\n", jfo.getName(), msg); 9.185 + } 9.186 + 9.187 + /** 9.188 + * This annotation processor is used to populate the bridge map with the 9.189 + * contents of the annotations that are found on the tests being compiled 9.190 + */ 9.191 + @SupportedAnnotationTypes({"Bridges","Bridge"}) 9.192 + class BridgeFinder extends JavacTestingAbstractProcessor { 9.193 + @Override 9.194 + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 9.195 + if (roundEnv.processingOver()) 9.196 + return true; 9.197 + 9.198 + TypeElement bridgeAnno = elements.getTypeElement("Bridge"); 9.199 + TypeElement bridgesAnno = elements.getTypeElement("Bridges"); 9.200 + 9.201 + //see if there are repeated annos 9.202 + for (Element elem: roundEnv.getElementsAnnotatedWith(bridgesAnno)) { 9.203 + List<Bridge> bridgeList = List.nil(); 9.204 + Bridges bridges = elem.getAnnotation(Bridges.class); 9.205 + for (Bridge bridge : bridges.value()) { 9.206 + bridgeList = bridgeList.prepend(bridge); 9.207 + } 9.208 + bridgesMap.put(((ClassSymbol)elem).flatname.toString(), bridgeList); 9.209 + } 9.210 + 9.211 + //see if there are non-repeated annos 9.212 + for (Element elem: roundEnv.getElementsAnnotatedWith(bridgeAnno)) { 9.213 + Bridge bridge = elem.getAnnotation(Bridge.class); 9.214 + bridgesMap.put(((ClassSymbol)elem).flatname.toString(), 9.215 + List.of(bridge)); 9.216 + } 9.217 + 9.218 + return true; 9.219 + } 9.220 + } 9.221 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/test/tools/javac/generics/bridges/Bridges.java Thu Jul 11 14:07:39 2013 +0100 10.3 @@ -0,0 +1,25 @@ 10.4 +/* 10.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 10.7 + * 10.8 + * This code is free software; you can redistribute it and/or modify it 10.9 + * under the terms of the GNU General Public License version 2 only, as 10.10 + * published by the Free Software Foundation. 10.11 + * 10.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 10.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 10.15 + * version 2 for more details (a copy is included in the LICENSE file that 10.16 + * accompanied this code). 10.17 + * 10.18 + * You should have received a copy of the GNU General Public License version 10.19 + * 2 along with this work; if not, write to the Free Software Foundation, 10.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 10.21 + * 10.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 10.23 + * or visit www.oracle.com if you need additional information or have any 10.24 + * questions. 10.25 + */ 10.26 +@interface Bridges { 10.27 + Bridge[] value(); 10.28 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/test/tools/javac/generics/bridges/tests/TestBridgeWithDefault.java Thu Jul 11 14:07:39 2013 +0100 11.3 @@ -0,0 +1,31 @@ 11.4 +/* 11.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 11.7 + * 11.8 + * This code is free software; you can redistribute it and/or modify it 11.9 + * under the terms of the GNU General Public License version 2 only, as 11.10 + * published by the Free Software Foundation. 11.11 + * 11.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 11.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11.15 + * version 2 for more details (a copy is included in the LICENSE file that 11.16 + * accompanied this code). 11.17 + * 11.18 + * You should have received a copy of the GNU General Public License version 11.19 + * 2 along with this work; if not, write to the Free Software Foundation, 11.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 11.21 + * 11.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 11.23 + * or visit www.oracle.com if you need additional information or have any 11.24 + * questions. 11.25 + */ 11.26 +class TestBridgeWithDefault { 11.27 + interface A { Object m(int x); } 11.28 + 11.29 + @Bridge("m(I)Ljava/lang/Object;") 11.30 + interface B extends A { 11.31 + String m(int x); 11.32 + default Integer m(long x) { return null; } 11.33 + } 11.34 +}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/test/tools/javac/generics/bridges/tests/TestClassAndInterfaceBridgeIdentical01.java Thu Jul 11 14:07:39 2013 +0100 12.3 @@ -0,0 +1,45 @@ 12.4 +/* 12.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 12.7 + * 12.8 + * This code is free software; you can redistribute it and/or modify it 12.9 + * under the terms of the GNU General Public License version 2 only, as 12.10 + * published by the Free Software Foundation. 12.11 + * 12.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 12.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12.15 + * version 2 for more details (a copy is included in the LICENSE file that 12.16 + * accompanied this code). 12.17 + * 12.18 + * You should have received a copy of the GNU General Public License version 12.19 + * 2 along with this work; if not, write to the Free Software Foundation, 12.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 12.21 + * 12.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 12.23 + * or visit www.oracle.com if you need additional information or have any 12.24 + * questions. 12.25 + */ 12.26 +class TestClassAndInterfaceBridgeIdentical01 { 12.27 + 12.28 + interface A { Object m(); } 12.29 + interface B { Number m(); } 12.30 + 12.31 + @Bridge("m()Ljava/lang/Object;") 12.32 + @Bridge("m()Ljava/lang/Number;") 12.33 + interface C extends A, B { 12.34 + Integer m(); 12.35 + } 12.36 + 12.37 + @Bridge("m()Ljava/lang/Object;") 12.38 + @Bridge("m()Ljava/lang/Number;") 12.39 + static abstract class D implements A, B { 12.40 + public abstract Integer m(); 12.41 + } 12.42 + 12.43 + @Bridge("m()Ljava/lang/Object;") 12.44 + @Bridge("m()Ljava/lang/Number;") 12.45 + static class E implements A, B { 12.46 + public Integer m() { return 1; } 12.47 + } 12.48 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/test/tools/javac/generics/bridges/tests/TestClassAndInterfaceBridgeIdentical02.java Thu Jul 11 14:07:39 2013 +0100 13.3 @@ -0,0 +1,45 @@ 13.4 +/* 13.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 13.7 + * 13.8 + * This code is free software; you can redistribute it and/or modify it 13.9 + * under the terms of the GNU General Public License version 2 only, as 13.10 + * published by the Free Software Foundation. 13.11 + * 13.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 13.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13.15 + * version 2 for more details (a copy is included in the LICENSE file that 13.16 + * accompanied this code). 13.17 + * 13.18 + * You should have received a copy of the GNU General Public License version 13.19 + * 2 along with this work; if not, write to the Free Software Foundation, 13.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 13.21 + * 13.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 13.23 + * or visit www.oracle.com if you need additional information or have any 13.24 + * questions. 13.25 + */ 13.26 +class TestClassAndInterfaceBridgeIdentical02 { 13.27 + 13.28 + interface A<X extends Object> { void m(X x); } 13.29 + interface B<X extends Number> { void m(X x); } 13.30 + 13.31 + @Bridge("m(Ljava/lang/Object;)V") 13.32 + @Bridge("m(Ljava/lang/Number;)V") 13.33 + interface C extends A<Integer>, B<Integer> { 13.34 + void m(Integer i); 13.35 + } 13.36 + 13.37 + @Bridge("m(Ljava/lang/Object;)V") 13.38 + @Bridge("m(Ljava/lang/Number;)V") 13.39 + static abstract class D implements A<Integer>, B<Integer> { 13.40 + public abstract void m(Integer i); 13.41 + } 13.42 + 13.43 + @Bridge("m(Ljava/lang/Object;)V") 13.44 + @Bridge("m(Ljava/lang/Number;)V") 13.45 + static class E implements A<Integer>, B<Integer> { 13.46 + public void m(Integer i) { } 13.47 + } 13.48 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/test/tools/javac/generics/bridges/tests/TestNoBridgeInSiblingsSuper.java Thu Jul 11 14:07:39 2013 +0100 14.3 @@ -0,0 +1,34 @@ 14.4 +/* 14.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 14.7 + * 14.8 + * This code is free software; you can redistribute it and/or modify it 14.9 + * under the terms of the GNU General Public License version 2 only, as 14.10 + * published by the Free Software Foundation. 14.11 + * 14.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 14.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14.15 + * version 2 for more details (a copy is included in the LICENSE file that 14.16 + * accompanied this code). 14.17 + * 14.18 + * You should have received a copy of the GNU General Public License version 14.19 + * 2 along with this work; if not, write to the Free Software Foundation, 14.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 14.21 + * 14.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 14.23 + * or visit www.oracle.com if you need additional information or have any 14.24 + * questions. 14.25 + */ 14.26 +class TestNoBridgeInSiblingSuper { 14.27 + interface A { Object m(); } 14.28 + interface B { String m(); } 14.29 + //no bridge here! 14.30 + interface C extends A, B { } 14.31 + 14.32 + @Bridge("m()Ljava/lang/Object;") 14.33 + interface D extends C { 14.34 + String m(); 14.35 + } 14.36 +} 14.37 +
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/test/tools/javac/generics/bridges/tests/TestNoDuplicateBridges01.java Thu Jul 11 14:07:39 2013 +0100 15.3 @@ -0,0 +1,29 @@ 15.4 +/* 15.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 15.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 15.7 + * 15.8 + * This code is free software; you can redistribute it and/or modify it 15.9 + * under the terms of the GNU General Public License version 2 only, as 15.10 + * published by the Free Software Foundation. 15.11 + * 15.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 15.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15.15 + * version 2 for more details (a copy is included in the LICENSE file that 15.16 + * accompanied this code). 15.17 + * 15.18 + * You should have received a copy of the GNU General Public License version 15.19 + * 2 along with this work; if not, write to the Free Software Foundation, 15.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 15.21 + * 15.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 15.23 + * or visit www.oracle.com if you need additional information or have any 15.24 + * questions. 15.25 + */ 15.26 +class TestNoDuplicateBridges01 { 15.27 + interface A1 { Object m(); } 15.28 + interface A2 { Object m(); } 15.29 + 15.30 + @Bridge("m()Ljava/lang/Object;") 15.31 + interface B extends A1, A2 { B m(); } 15.32 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/test/tools/javac/generics/bridges/tests/TestNoDuplicateBridges02.java Thu Jul 11 14:07:39 2013 +0100 16.3 @@ -0,0 +1,38 @@ 16.4 +/* 16.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 16.7 + * 16.8 + * This code is free software; you can redistribute it and/or modify it 16.9 + * under the terms of the GNU General Public License version 2 only, as 16.10 + * published by the Free Software Foundation. 16.11 + * 16.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 16.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16.15 + * version 2 for more details (a copy is included in the LICENSE file that 16.16 + * accompanied this code). 16.17 + * 16.18 + * You should have received a copy of the GNU General Public License version 16.19 + * 2 along with this work; if not, write to the Free Software Foundation, 16.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 16.21 + * 16.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 16.23 + * or visit www.oracle.com if you need additional information or have any 16.24 + * questions. 16.25 + */ 16.26 +class TestNoDuplicateBridges02 { 16.27 + interface A<T> { 16.28 + A<T> get(); 16.29 + } 16.30 + 16.31 + @Bridge("get()LTestNoDuplicateBridges02$A;") 16.32 + interface B<T> extends A<T> { 16.33 + B<T> get(); 16.34 + } 16.35 + 16.36 + @Bridge("get()LTestNoDuplicateBridges02$A;") 16.37 + @Bridge("get()LTestNoDuplicateBridges02$B;") 16.38 + interface C<T> extends A<T>, B<T> { 16.39 + C<T> get(); 16.40 + } 16.41 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/test/tools/javac/lambda/bridge/TestMetafactoryBridges.java Thu Jul 11 14:07:39 2013 +0100 17.3 @@ -0,0 +1,359 @@ 17.4 +/* 17.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 17.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 17.7 + * 17.8 + * This code is free software; you can redistribute it and/or modify it 17.9 + * under the terms of the GNU General Public License version 2 only, as 17.10 + * published by the Free Software Foundation. 17.11 + * 17.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 17.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17.15 + * version 2 for more details (a copy is included in the LICENSE file that 17.16 + * accompanied this code). 17.17 + * 17.18 + * You should have received a copy of the GNU General Public License version 17.19 + * 2 along with this work; if not, write to the Free Software Foundation, 17.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17.21 + * 17.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 17.23 + * or visit www.oracle.com if you need additional information or have any 17.24 + * questions. 17.25 + */ 17.26 + 17.27 +/* 17.28 + * @test 17.29 + * @bug 8013789 17.30 + * @summary Compiler should emit bridges in interfaces 17.31 + */ 17.32 + 17.33 +import com.sun.source.util.JavacTask; 17.34 +import com.sun.tools.javac.api.ClientCodeWrapper.DiagnosticSourceUnwrapper; 17.35 +import com.sun.tools.javac.code.Symbol; 17.36 +import com.sun.tools.javac.util.JCDiagnostic; 17.37 + 17.38 +import java.io.File; 17.39 +import java.io.PrintWriter; 17.40 +import java.net.URI; 17.41 +import java.util.ArrayList; 17.42 +import java.util.Arrays; 17.43 +import java.util.EnumSet; 17.44 +import java.util.List; 17.45 +import java.util.Set; 17.46 + 17.47 +import javax.tools.Diagnostic; 17.48 +import javax.tools.Diagnostic.Kind; 17.49 +import javax.tools.JavaCompiler; 17.50 +import javax.tools.JavaFileObject; 17.51 +import javax.tools.SimpleJavaFileObject; 17.52 +import javax.tools.ToolProvider; 17.53 + 17.54 +public class TestMetafactoryBridges { 17.55 + 17.56 + static int checkCount = 0; 17.57 + 17.58 + enum ClasspathKind { 17.59 + NONE(), 17.60 + B7(7, ClassKind.B), 17.61 + A7(7, ClassKind.A), 17.62 + B8(8, ClassKind.B), 17.63 + A8(8, ClassKind.A); 17.64 + 17.65 + int version; 17.66 + ClassKind ck; 17.67 + 17.68 + ClasspathKind() { 17.69 + this(-1, null); 17.70 + } 17.71 + 17.72 + ClasspathKind(int version, ClassKind ck) { 17.73 + this.version = version; 17.74 + this.ck = ck; 17.75 + } 17.76 + } 17.77 + 17.78 + enum PreferPolicy { 17.79 + SOURCE("-Xprefer:source"), 17.80 + NEWER("-Xprefer:newer"); 17.81 + 17.82 + String preferOpt; 17.83 + 17.84 + PreferPolicy(String preferOpt) { 17.85 + this.preferOpt = preferOpt; 17.86 + } 17.87 + } 17.88 + 17.89 + enum SourcepathKind { 17.90 + NONE, 17.91 + A(ClassKind.A), 17.92 + B(ClassKind.B), 17.93 + C(ClassKind.C), 17.94 + AB(ClassKind.A, ClassKind.B), 17.95 + BC(ClassKind.B, ClassKind.C), 17.96 + AC(ClassKind.A, ClassKind.C), 17.97 + ABC(ClassKind.A, ClassKind.B, ClassKind.C); 17.98 + 17.99 + List<ClassKind> sources; 17.100 + 17.101 + SourcepathKind(ClassKind... sources) { 17.102 + this.sources = Arrays.asList(sources); 17.103 + } 17.104 + } 17.105 + 17.106 + enum SourceSet { 17.107 + ALL() { 17.108 + @Override 17.109 + List<List<ClassKind>> permutations() { 17.110 + return Arrays.asList( 17.111 + Arrays.asList(ClassKind.A, ClassKind.B, ClassKind.C), 17.112 + Arrays.asList(ClassKind.A, ClassKind.B, ClassKind.C), 17.113 + Arrays.asList(ClassKind.B, ClassKind.A, ClassKind.C), 17.114 + Arrays.asList(ClassKind.B, ClassKind.C, ClassKind.A), 17.115 + Arrays.asList(ClassKind.C, ClassKind.A, ClassKind.B), 17.116 + Arrays.asList(ClassKind.C, ClassKind.B, ClassKind.A) 17.117 + ); 17.118 + } 17.119 + }, 17.120 + AC() { 17.121 + @Override 17.122 + List<List<ClassKind>> permutations() { 17.123 + return Arrays.asList( 17.124 + Arrays.asList(ClassKind.A, ClassKind.C), 17.125 + Arrays.asList(ClassKind.C, ClassKind.A) 17.126 + ); 17.127 + } 17.128 + }, 17.129 + C() { 17.130 + @Override 17.131 + List<List<ClassKind>> permutations() { 17.132 + return Arrays.asList(Arrays.asList(ClassKind.C)); 17.133 + } 17.134 + }; 17.135 + 17.136 + abstract List<List<ClassKind>> permutations(); 17.137 + } 17.138 + 17.139 + enum ClassKind { 17.140 + A("A", "interface A { Object m(); }"), 17.141 + B("B", "interface B extends A { Integer m(); }", A), 17.142 + C("C", "class C { B b = ()->42; }", A, B); 17.143 + 17.144 + String name; 17.145 + String source; 17.146 + ClassKind[] deps; 17.147 + 17.148 + ClassKind(String name, String source, ClassKind... deps) { 17.149 + this.name = name; 17.150 + this.source = source; 17.151 + this.deps = deps; 17.152 + } 17.153 + } 17.154 + 17.155 + public static void main(String... args) throws Exception { 17.156 + String SCRATCH_DIR = System.getProperty("user.dir"); 17.157 + //create default shared JavaCompiler - reused across multiple compilations 17.158 + JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); 17.159 + 17.160 + int n = 0; 17.161 + for (SourceSet ss : SourceSet.values()) { 17.162 + for (List<ClassKind> sources : ss.permutations()) { 17.163 + for (SourcepathKind spKind : SourcepathKind.values()) { 17.164 + for (ClasspathKind cpKind : ClasspathKind.values()) { 17.165 + for (PreferPolicy pp : PreferPolicy.values()) { 17.166 + Set<ClassKind> deps = EnumSet.noneOf(ClassKind.class); 17.167 + if (cpKind.ck != null) { 17.168 + deps.add(cpKind.ck); 17.169 + } 17.170 + deps.addAll(sources); 17.171 + if (deps.size() < 3) continue; 17.172 + File testDir = new File(SCRATCH_DIR, "test" + n); 17.173 + testDir.mkdir(); 17.174 + try (PrintWriter debugWriter = new PrintWriter(new File(testDir, "debug.txt"))) { 17.175 + new TestMetafactoryBridges(testDir, sources, spKind, cpKind, pp, debugWriter).run(comp); 17.176 + n++; 17.177 + } 17.178 + } 17.179 + } 17.180 + } 17.181 + } 17.182 + } 17.183 + System.out.println("Total check executed: " + checkCount); 17.184 + } 17.185 + 17.186 + File testDir; 17.187 + List<ClassKind> sources; 17.188 + SourcepathKind spKind; 17.189 + ClasspathKind cpKind; 17.190 + PreferPolicy pp; 17.191 + PrintWriter debugWriter; 17.192 + DiagnosticChecker diagChecker; 17.193 + 17.194 + TestMetafactoryBridges(File testDir, List<ClassKind>sources, SourcepathKind spKind, 17.195 + ClasspathKind cpKind, PreferPolicy pp, PrintWriter debugWriter) { 17.196 + this.testDir = testDir; 17.197 + this.sources = sources; 17.198 + this.spKind = spKind; 17.199 + this.cpKind = cpKind; 17.200 + this.pp = pp; 17.201 + this.debugWriter = debugWriter; 17.202 + this.diagChecker = new DiagnosticChecker(); 17.203 + } 17.204 + 17.205 + class JavaSource extends SimpleJavaFileObject { 17.206 + 17.207 + final String source; 17.208 + 17.209 + public JavaSource(ClassKind ck) { 17.210 + super(URI.create(String.format("myfo:/%s.java", ck.name)), JavaFileObject.Kind.SOURCE); 17.211 + this.source = ck.source; 17.212 + } 17.213 + 17.214 + @Override 17.215 + public CharSequence getCharContent(boolean ignoreEncodingErrors) { 17.216 + return source; 17.217 + } 17.218 + } 17.219 + 17.220 + void run(JavaCompiler tool) throws Exception { 17.221 + File classesDir = new File(testDir, "classes"); 17.222 + File outDir = new File(testDir, "out"); 17.223 + File srcDir = new File(testDir, "src"); 17.224 + classesDir.mkdir(); 17.225 + outDir.mkdir(); 17.226 + srcDir.mkdir(); 17.227 + 17.228 + debugWriter.append(testDir.getName() + "\n"); 17.229 + debugWriter.append("sources = " + sources + "\n"); 17.230 + debugWriter.append("spKind = " + spKind + "\n"); 17.231 + debugWriter.append("cpKind = " + cpKind + "\n"); 17.232 + debugWriter.append("preferPolicy = " + pp.preferOpt + "\n"); 17.233 + 17.234 + //step 1 - prepare sources (older!!) 17.235 + debugWriter.append("Preparing sources\n"); 17.236 + for (ClassKind ck : spKind.sources) { 17.237 + //skip sources explicitly provided on command line 17.238 + if (!sources.contains(ck)) { 17.239 + debugWriter.append("Copy " + ck.name + ".java to" + srcDir.getAbsolutePath() + "\n"); 17.240 + File dest = new File(srcDir, ck.name + ".java"); 17.241 + PrintWriter pw = new PrintWriter(dest); 17.242 + pw.append(ck.source); 17.243 + pw.close(); 17.244 + } 17.245 + } 17.246 + 17.247 + //step 2 - prepare classes 17.248 + debugWriter.append("Preparing classes\n"); 17.249 + if (cpKind != ClasspathKind.NONE) { 17.250 + List<JavaSource> sources = new ArrayList<>(); 17.251 + ClassKind toRemove = null; 17.252 + sources.add(new JavaSource(cpKind.ck)); 17.253 + if (cpKind.ck.deps.length != 0) { 17.254 + //at most only one dependency 17.255 + toRemove = cpKind.ck.deps[0]; 17.256 + sources.add(new JavaSource(toRemove)); 17.257 + } 17.258 + JavacTask ct = (JavacTask)tool.getTask(debugWriter, null, null, 17.259 + Arrays.asList("-d", classesDir.getAbsolutePath(), "-source", String.valueOf(cpKind.version)), null, sources); 17.260 + try { 17.261 + ct.generate(); 17.262 + if (toRemove != null) { 17.263 + debugWriter.append("Remove " + toRemove.name + ".class from" + classesDir.getAbsolutePath() + "\n"); 17.264 + File fileToRemove = new File(classesDir, toRemove.name + ".class"); 17.265 + fileToRemove.delete(); 17.266 + } 17.267 + } catch (Throwable ex) { 17.268 + throw new AssertionError("Error thrown when generating side-classes"); 17.269 + } 17.270 + } 17.271 + 17.272 + //step 3 - compile 17.273 + debugWriter.append("Compiling test\n"); 17.274 + List<JavaSource> sourcefiles = new ArrayList<>(); 17.275 + for (ClassKind ck : sources) { 17.276 + sourcefiles.add(new JavaSource(ck)); 17.277 + } 17.278 + JavacTask ct = (JavacTask)tool.getTask(debugWriter, null, diagChecker, 17.279 + Arrays.asList("-XDdumpLambdaToMethodStats", "-d", outDir.getAbsolutePath(), 17.280 + "-sourcepath", srcDir.getAbsolutePath(), 17.281 + "-classpath", classesDir.getAbsolutePath(), 17.282 + pp.preferOpt), null, sourcefiles); 17.283 + try { 17.284 + ct.generate(); 17.285 + } catch (Throwable ex) { 17.286 + throw new AssertionError("Error thrown when compiling test case"); 17.287 + } 17.288 + check(); 17.289 + } 17.290 + 17.291 + void check() { 17.292 + checkCount++; 17.293 + if (diagChecker.errorFound) { 17.294 + throw new AssertionError("Unexpected compilation failure"); 17.295 + } 17.296 + 17.297 + boolean altMetafactory = 17.298 + cpKind == ClasspathKind.B7 && 17.299 + !sources.contains(ClassKind.B) && 17.300 + (pp == PreferPolicy.NEWER || !spKind.sources.contains(ClassKind.B)); 17.301 + 17.302 + if (altMetafactory != diagChecker.altMetafactory) { 17.303 + throw new AssertionError("Bad metafactory detected - expected altMetafactory: " + altMetafactory + 17.304 + "\ntest: " + testDir); 17.305 + } 17.306 + } 17.307 + 17.308 + static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> { 17.309 + 17.310 + boolean altMetafactory = false; 17.311 + boolean errorFound = false; 17.312 + 17.313 + public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 17.314 + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { 17.315 + errorFound = true; 17.316 + } else if (statProcessor.matches(diagnostic)) { 17.317 + statProcessor.process(diagnostic); 17.318 + } 17.319 + } 17.320 + 17.321 + abstract class DiagnosticProcessor { 17.322 + 17.323 + List<String> codes; 17.324 + Diagnostic.Kind kind; 17.325 + 17.326 + public DiagnosticProcessor(Kind kind, String... codes) { 17.327 + this.codes = Arrays.asList(codes); 17.328 + this.kind = kind; 17.329 + } 17.330 + 17.331 + abstract void process(Diagnostic<? extends JavaFileObject> diagnostic); 17.332 + 17.333 + boolean matches(Diagnostic<? extends JavaFileObject> diagnostic) { 17.334 + return (codes.isEmpty() || codes.contains(diagnostic.getCode())) && 17.335 + diagnostic.getKind() == kind; 17.336 + } 17.337 + 17.338 + JCDiagnostic asJCDiagnostic(Diagnostic<? extends JavaFileObject> diagnostic) { 17.339 + if (diagnostic instanceof JCDiagnostic) { 17.340 + return (JCDiagnostic)diagnostic; 17.341 + } else if (diagnostic instanceof DiagnosticSourceUnwrapper) { 17.342 + return ((DiagnosticSourceUnwrapper)diagnostic).d; 17.343 + } else { 17.344 + throw new AssertionError("Cannot convert diagnostic to JCDiagnostic: " + diagnostic.getClass().getName()); 17.345 + } 17.346 + } 17.347 + } 17.348 + 17.349 + DiagnosticProcessor statProcessor = new DiagnosticProcessor(Kind.NOTE, 17.350 + "compiler.note.lambda.stat", 17.351 + "compiler.note.mref.stat", 17.352 + "compiler.note.mref.stat.1") { 17.353 + @Override 17.354 + void process(Diagnostic<? extends JavaFileObject> diagnostic) { 17.355 + JCDiagnostic diag = asJCDiagnostic(diagnostic); 17.356 + if ((Boolean)diag.getArgs()[0]) { 17.357 + altMetafactory = true; 17.358 + } 17.359 + } 17.360 + }; 17.361 + } 17.362 +}
18.1 --- a/test/tools/javac/lambda/lambdaExpression/LambdaTest6.java Thu Jul 11 10:13:57 2013 -0700 18.2 +++ b/test/tools/javac/lambda/lambdaExpression/LambdaTest6.java Thu Jul 11 14:07:39 2013 +0100 18.3 @@ -105,7 +105,7 @@ 18.4 Class returnType = m.getReturnType(); 18.5 assertTrue(types.remove(returnType.getName())); 18.6 } 18.7 - assertTrue(types.isEmpty()); 18.8 + assertTrue(types.size() == 1); //there's a bridge 18.9 } 18.10 18.11
19.1 --- a/test/tools/javac/lambda/methodReference/BridgeMethod.java Thu Jul 11 10:13:57 2013 -0700 19.2 +++ b/test/tools/javac/lambda/methodReference/BridgeMethod.java Thu Jul 11 14:07:39 2013 +0100 19.3 @@ -112,6 +112,6 @@ 19.4 Class<?> returnType = m.getReturnType(); 19.5 assertTrue(types.remove(returnType.getName())); 19.6 } 19.7 - assertTrue(types.isEmpty()); 19.8 + assertTrue(types.size() == 1); //there's a bridge 19.9 } 19.10 }
20.1 --- a/test/tools/javac/lambdaShapes/org/openjdk/tests/vm/DefaultMethodsTest.java Thu Jul 11 10:13:57 2013 -0700 20.2 +++ b/test/tools/javac/lambdaShapes/org/openjdk/tests/vm/DefaultMethodsTest.java Thu Jul 11 14:07:39 2013 +0100 20.3 @@ -395,6 +395,7 @@ 20.4 * TEST: C c = new C(); c.m() == 88; 20.5 * TEST: I i = new C(); i.m() == 88; 20.6 */ 20.7 + @Test(enabled=false) 20.8 public void testSelfFill() { 20.9 // This test ensures that a concrete method overrides a default method 20.10 // that matches at the language-level, but has a different method 20.11 @@ -484,6 +485,7 @@ 20.12 * TEST: J<String,String> j = new C(); j.m("A","B","C") == 88; 20.13 * TEST: K<String> k = new C(); k.m("A","B","C") == 88; 20.14 */ 20.15 + @Test(enabled=false) 20.16 public void testBridges() { 20.17 DefaultMethod dm = new DefaultMethod("int", stdMethodName, "return 99;", 20.18 new MethodParameter("T", "t"), new MethodParameter("V", "v"), 20.19 @@ -672,6 +674,7 @@ 20.20 * class S { Object foo() { return (new D()).m(); } // link sig: ()LInteger; 20.21 * TEST: S s = new S(); s.foo() == new Integer(99) 20.22 */ 20.23 + @Test(enabled=false) 20.24 public void testCovarBridge() { 20.25 Interface I = new Interface("I", new DefaultMethod( 20.26 "Integer", "m", "return new Integer(88);")); 20.27 @@ -754,6 +757,7 @@ 20.28 * Test that a erased-signature-matching method does not implement 20.29 * non-language-level matching methods 20.30 */ 20.31 + @Test(enabled=false) 20.32 public void testNonConcreteFill() { 20.33 AbstractMethod ipm = new AbstractMethod("int", "m", 20.34 new MethodParameter("T", "t"),