src/share/classes/com/sun/tools/javac/comp/Resolve.java

changeset 1393
d7d932236fee
parent 1374
c002fdee76fd
child 1394
dbc94b8363dd
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Sat Nov 03 21:09:57 2012 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Sun Nov 04 10:59:42 2012 +0000
     1.3 @@ -52,6 +52,7 @@
     1.4  import java.util.EnumSet;
     1.5  import java.util.Iterator;
     1.6  import java.util.Map;
     1.7 +import java.util.Set;
     1.8  
     1.9  import javax.lang.model.element.ElementVisitor;
    1.10  
    1.11 @@ -88,6 +89,7 @@
    1.12      public final boolean boxingEnabled; // = source.allowBoxing();
    1.13      public final boolean varargsEnabled; // = source.allowVarargs();
    1.14      public final boolean allowMethodHandles;
    1.15 +    public final boolean allowDefaultMethods;
    1.16      private final boolean debugResolve;
    1.17      final EnumSet<VerboseResolutionMode> verboseResolutionMode;
    1.18  
    1.19 @@ -122,6 +124,7 @@
    1.20          verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
    1.21          Target target = Target.instance(context);
    1.22          allowMethodHandles = target.hasMethodHandles();
    1.23 +        allowDefaultMethods = source.allowDefaultMethods();
    1.24          polymorphicSignatureScope = new Scope(syms.noSymbol);
    1.25  
    1.26          inapplicableMethodException = new InapplicableMethodException(diags);
    1.27 @@ -1327,6 +1330,42 @@
    1.28          }
    1.29      }
    1.30  
    1.31 +    Symbol lookupMethod(Env<AttrContext> env,
    1.32 +            Type site,
    1.33 +            Name name,
    1.34 +            List<Type> argtypes,
    1.35 +            List<Type> typeargtypes,
    1.36 +            Scope sc,
    1.37 +            Symbol bestSoFar,
    1.38 +            boolean allowBoxing,
    1.39 +            boolean useVarargs,
    1.40 +            boolean operator,
    1.41 +            boolean abstractok) {
    1.42 +        for (Symbol s : sc.getElementsByName(name, new LookupFilter(abstractok))) {
    1.43 +            bestSoFar = selectBest(env, site, argtypes, typeargtypes, s,
    1.44 +                    bestSoFar, allowBoxing, useVarargs, operator);
    1.45 +        }
    1.46 +        return bestSoFar;
    1.47 +    }
    1.48 +    //where
    1.49 +        class LookupFilter implements Filter<Symbol> {
    1.50 +
    1.51 +            boolean abstractOk;
    1.52 +
    1.53 +            LookupFilter(boolean abstractOk) {
    1.54 +                this.abstractOk = abstractOk;
    1.55 +            }
    1.56 +
    1.57 +            public boolean accepts(Symbol s) {
    1.58 +                long flags = s.flags();
    1.59 +                return s.kind == MTH &&
    1.60 +                        (flags & SYNTHETIC) == 0 &&
    1.61 +                        (abstractOk ||
    1.62 +                        (flags & DEFAULT) != 0 ||
    1.63 +                        (flags & ABSTRACT) == 0);
    1.64 +            }
    1.65 +        };
    1.66 +
    1.67      /** Find best qualified method matching given name, type and value
    1.68       *  arguments.
    1.69       *  @param env       The current environment.
    1.70 @@ -1371,49 +1410,76 @@
    1.71                                boolean allowBoxing,
    1.72                                boolean useVarargs,
    1.73                                boolean operator) {
    1.74 -        boolean abstractOk = true;
    1.75 -        List<Type> itypes = List.nil();
    1.76 +        @SuppressWarnings({"unchecked","rawtypes"})
    1.77 +        List<Type>[] itypes = (List<Type>[])new List[] { List.<Type>nil(), List.<Type>nil() };
    1.78 +        InterfaceLookupPhase iphase = InterfaceLookupPhase.ABSTRACT_OK;
    1.79          for (TypeSymbol s : superclasses(intype)) {
    1.80              bestSoFar = lookupMethod(env, site, name, argtypes, typeargtypes,
    1.81                      s.members(), bestSoFar, allowBoxing, useVarargs, operator, true);
    1.82 -            //We should not look for abstract methods if receiver is a concrete class
    1.83 -            //(as concrete classes are expected to implement all abstracts coming
    1.84 -            //from superinterfaces)
    1.85 -            abstractOk &= (s.flags() & (ABSTRACT | INTERFACE | ENUM)) != 0;
    1.86 -            if (abstractOk) {
    1.87 +            if (name == names.init) return bestSoFar;
    1.88 +            iphase = (iphase == null) ? null : iphase.update(s, this);
    1.89 +            if (iphase != null) {
    1.90                  for (Type itype : types.interfaces(s.type)) {
    1.91 -                    itypes = types.union(types.closure(itype), itypes);
    1.92 +                    itypes[iphase.ordinal()] = types.union(types.closure(itype), itypes[iphase.ordinal()]);
    1.93                  }
    1.94              }
    1.95 -            if (name == names.init) break;
    1.96          }
    1.97  
    1.98          Symbol concrete = bestSoFar.kind < ERR &&
    1.99                  (bestSoFar.flags() & ABSTRACT) == 0 ?
   1.100                  bestSoFar : methodNotFound;
   1.101  
   1.102 -        if (name != names.init) {
   1.103 +        for (InterfaceLookupPhase iphase2 : InterfaceLookupPhase.values()) {
   1.104 +            if (iphase2 == InterfaceLookupPhase.DEFAULT_OK && !allowDefaultMethods) break;
   1.105              //keep searching for abstract methods
   1.106 -            for (Type itype : itypes) {
   1.107 +            for (Type itype : itypes[iphase2.ordinal()]) {
   1.108                  if (!itype.isInterface()) continue; //skip j.l.Object (included by Types.closure())
   1.109 +                if (iphase2 == InterfaceLookupPhase.DEFAULT_OK &&
   1.110 +                        (itype.tsym.flags() & DEFAULT) == 0) continue;
   1.111                  bestSoFar = lookupMethod(env, site, name, argtypes, typeargtypes,
   1.112 -                    itype.tsym.members(), bestSoFar, allowBoxing, useVarargs, operator, true);
   1.113 -                    if (concrete != bestSoFar &&
   1.114 -                            concrete.kind < ERR  && bestSoFar.kind < ERR &&
   1.115 -                            types.isSubSignature(concrete.type, bestSoFar.type)) {
   1.116 -                        //this is an hack - as javac does not do full membership checks
   1.117 -                        //most specific ends up comparing abstract methods that might have
   1.118 -                        //been implemented by some concrete method in a subclass and,
   1.119 -                        //because of raw override, it is possible for an abstract method
   1.120 -                        //to be more specific than the concrete method - so we need
   1.121 -                        //to explicitly call that out (see CR 6178365)
   1.122 -                        bestSoFar = concrete;
   1.123 -                    }
   1.124 +                        itype.tsym.members(), bestSoFar, allowBoxing, useVarargs, operator, true);
   1.125 +                if (concrete != bestSoFar &&
   1.126 +                        concrete.kind < ERR  && bestSoFar.kind < ERR &&
   1.127 +                        types.isSubSignature(concrete.type, bestSoFar.type)) {
   1.128 +                    //this is an hack - as javac does not do full membership checks
   1.129 +                    //most specific ends up comparing abstract methods that might have
   1.130 +                    //been implemented by some concrete method in a subclass and,
   1.131 +                    //because of raw override, it is possible for an abstract method
   1.132 +                    //to be more specific than the concrete method - so we need
   1.133 +                    //to explicitly call that out (see CR 6178365)
   1.134 +                    bestSoFar = concrete;
   1.135 +                }
   1.136              }
   1.137          }
   1.138          return bestSoFar;
   1.139      }
   1.140  
   1.141 +    enum InterfaceLookupPhase {
   1.142 +        ABSTRACT_OK() {
   1.143 +            @Override
   1.144 +            InterfaceLookupPhase update(Symbol s, Resolve rs) {
   1.145 +                //We should not look for abstract methods if receiver is a concrete class
   1.146 +                //(as concrete classes are expected to implement all abstracts coming
   1.147 +                //from superinterfaces)
   1.148 +                if ((s.flags() & (ABSTRACT | INTERFACE | ENUM)) != 0) {
   1.149 +                    return this;
   1.150 +                } else if (rs.allowDefaultMethods) {
   1.151 +                    return DEFAULT_OK;
   1.152 +                } else {
   1.153 +                    return null;
   1.154 +                }
   1.155 +            }
   1.156 +        },
   1.157 +        DEFAULT_OK() {
   1.158 +            @Override
   1.159 +            InterfaceLookupPhase update(Symbol s, Resolve rs) {
   1.160 +                return this;
   1.161 +            }
   1.162 +        };
   1.163 +
   1.164 +        abstract InterfaceLookupPhase update(Symbol s, Resolve rs);
   1.165 +    }
   1.166 +
   1.167      /**
   1.168       * Return an Iterable object to scan the superclasses of a given type.
   1.169       * It's crucial that the scan is done lazily, as we don't want to accidentally
   1.170 @@ -1467,34 +1533,6 @@
   1.171          };
   1.172      }
   1.173  
   1.174 -    /**
   1.175 -     * Lookup a method with given name and argument types in a given scope
   1.176 -     */
   1.177 -    Symbol lookupMethod(Env<AttrContext> env,
   1.178 -            Type site,
   1.179 -            Name name,
   1.180 -            List<Type> argtypes,
   1.181 -            List<Type> typeargtypes,
   1.182 -            Scope sc,
   1.183 -            Symbol bestSoFar,
   1.184 -            boolean allowBoxing,
   1.185 -            boolean useVarargs,
   1.186 -            boolean operator,
   1.187 -            boolean abstractok) {
   1.188 -        for (Symbol s : sc.getElementsByName(name, lookupFilter)) {
   1.189 -            bestSoFar = selectBest(env, site, argtypes, typeargtypes, s,
   1.190 -                    bestSoFar, allowBoxing, useVarargs, operator);
   1.191 -        }
   1.192 -        return bestSoFar;
   1.193 -    }
   1.194 -    //where
   1.195 -        Filter<Symbol> lookupFilter = new Filter<Symbol>() {
   1.196 -            public boolean accepts(Symbol s) {
   1.197 -                return s.kind == MTH &&
   1.198 -                        (s.flags() & SYNTHETIC) == 0;
   1.199 -            }
   1.200 -        };
   1.201 -
   1.202      /** Find unqualified method matching given name, type and value arguments.
   1.203       *  @param env       The current environment.
   1.204       *  @param name      The method's name.
   1.205 @@ -1920,7 +1958,7 @@
   1.206      /** Check that sym is not an abstract method.
   1.207       */
   1.208      void checkNonAbstract(DiagnosticPosition pos, Symbol sym) {
   1.209 -        if ((sym.flags() & ABSTRACT) != 0)
   1.210 +        if ((sym.flags() & ABSTRACT) != 0 && (sym.flags() & DEFAULT) == 0)
   1.211              log.error(pos, "abstract.cant.be.accessed.directly",
   1.212                        kindName(sym), sym, sym.location());
   1.213      }
   1.214 @@ -2744,9 +2782,47 @@
   1.215              if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true;
   1.216              env1 = env1.outer;
   1.217          }
   1.218 +        if (allowDefaultMethods && c.isInterface() &&
   1.219 +                name == names._super && !isStatic(env) &&
   1.220 +                types.isDirectSuperInterface(c.type, env.enclClass.sym)) {
   1.221 +            //this might be a default super call if one of the superinterfaces is 'c'
   1.222 +            for (Type t : pruneInterfaces(env.enclClass.type)) {
   1.223 +                if (t.tsym == c) {
   1.224 +                    env.info.defaultSuperCallSite = t;
   1.225 +                    return new VarSymbol(0, names._super,
   1.226 +                            types.asSuper(env.enclClass.type, c), env.enclClass.sym);
   1.227 +                }
   1.228 +            }
   1.229 +            //find a direct superinterface that is a subtype of 'c'
   1.230 +            for (Type i : types.interfaces(env.enclClass.type)) {
   1.231 +                if (i.tsym.isSubClass(c, types) && i.tsym != c) {
   1.232 +                    log.error(pos, "illegal.default.super.call", c,
   1.233 +                            diags.fragment("redundant.supertype", c, i));
   1.234 +                    return syms.errSymbol;
   1.235 +                }
   1.236 +            }
   1.237 +            Assert.error();
   1.238 +        }
   1.239          log.error(pos, "not.encl.class", c);
   1.240          return syms.errSymbol;
   1.241      }
   1.242 +    //where
   1.243 +    private List<Type> pruneInterfaces(Type t) {
   1.244 +        ListBuffer<Type> result = ListBuffer.lb();
   1.245 +        for (Type t1 : types.interfaces(t)) {
   1.246 +            boolean shouldAdd = true;
   1.247 +            for (Type t2 : types.interfaces(t)) {
   1.248 +                if (t1 != t2 && types.isSubtypeNoCapture(t2, t1)) {
   1.249 +                    shouldAdd = false;
   1.250 +                }
   1.251 +            }
   1.252 +            if (shouldAdd) {
   1.253 +                result.append(t1);
   1.254 +            }
   1.255 +        }
   1.256 +        return result.toList();
   1.257 +    }
   1.258 +
   1.259  
   1.260      /**
   1.261       * Resolve `c.this' for an enclosing class c that contains the

mercurial