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