src/share/classes/com/sun/tools/javac/code/Types.java

changeset 1882
39ec5d8a691b
parent 1869
5c548a8542b8
child 1907
e990e6bcecbe
     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                  }

mercurial