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 }