Thu, 04 Oct 2012 13:04:53 +0100
7177387: Add target-typing support in method context
Summary: Add support for deferred types and speculative attribution
Reviewed-by: jjg, dlsmith
1.1 --- a/src/share/classes/com/sun/tools/javac/code/Printer.java Sat Sep 29 09:00:58 2012 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Printer.java Thu Oct 04 13:04:53 2012 +0100 1.3 @@ -30,6 +30,10 @@ 1.4 import com.sun.tools.javac.api.Messages; 1.5 import com.sun.tools.javac.code.Type.*; 1.6 import com.sun.tools.javac.code.Symbol.*; 1.7 +import com.sun.tools.javac.comp.DeferredAttr.DeferredType; 1.8 +import com.sun.tools.javac.tree.JCTree; 1.9 +import com.sun.tools.javac.tree.Pretty; 1.10 +import com.sun.tools.javac.util.Assert; 1.11 import com.sun.tools.javac.util.List; 1.12 import com.sun.tools.javac.util.ListBuffer; 1.13 1.14 @@ -50,6 +54,11 @@ 1.15 1.16 List<Type> seenCaptured = List.nil(); 1.17 static final int PRIME = 997; // largest prime less than 1000 1.18 + boolean raw; 1.19 + 1.20 + protected Printer(boolean raw) { 1.21 + this.raw = raw; 1.22 + } 1.23 1.24 /** 1.25 * This method should be overriden in order to provide proper i18n support. 1.26 @@ -78,7 +87,7 @@ 1.27 * @return printer visitor instance 1.28 */ 1.29 public static Printer createStandardPrinter(final Messages messages) { 1.30 - return new Printer() { 1.31 + return new Printer(false) { 1.32 @Override 1.33 protected String localize(Locale locale, String key, Object... args) { 1.34 return messages.getLocalizedString(locale, key, args); 1.35 @@ -165,6 +174,34 @@ 1.36 return "<" + visitTypes(t.tvars, locale) + ">" + visit(t.qtype, locale); 1.37 } 1.38 1.39 + public String visitDeferredType(DeferredType t, Locale locale) { 1.40 + return raw ? localize(locale, getDeferredKey(t.tree)) : 1.41 + deferredTypeTree2String(t.tree); 1.42 + } 1.43 + //where 1.44 + private String deferredTypeTree2String(JCTree tree) { 1.45 + switch(tree.getTag()) { 1.46 + case PARENS: 1.47 + return deferredTypeTree2String(((JCTree.JCParens)tree).expr); 1.48 + case CONDEXPR: 1.49 + return Pretty.toSimpleString(tree, 15); 1.50 + default: 1.51 + Assert.error("unexpected tree kind " + tree.getKind()); 1.52 + return null; 1.53 + } 1.54 + } 1.55 + private String getDeferredKey (JCTree tree) { 1.56 + switch (tree.getTag()) { 1.57 + case PARENS: 1.58 + return getDeferredKey(((JCTree.JCParens)tree).expr); 1.59 + case CONDEXPR: 1.60 + return "compiler.misc.type.conditional"; 1.61 + default: 1.62 + Assert.error("unexpected tree kind " + tree.getKind()); 1.63 + return null; 1.64 + } 1.65 + } 1.66 + 1.67 @Override 1.68 public String visitUndetVar(UndetVar t, Locale locale) { 1.69 if (t.inst != null) { 1.70 @@ -228,10 +265,14 @@ 1.71 } 1.72 1.73 public String visitType(Type t, Locale locale) { 1.74 - String s = (t.tsym == null || t.tsym.name == null) 1.75 - ? localize(locale, "compiler.misc.type.none") 1.76 - : t.tsym.name.toString(); 1.77 - return s; 1.78 + if (t.tag == DEFERRED) { 1.79 + return visitDeferredType((DeferredType)t, locale); 1.80 + } else { 1.81 + String s = (t.tsym == null || t.tsym.name == null) 1.82 + ? localize(locale, "compiler.misc.type.none") 1.83 + : t.tsym.name.toString(); 1.84 + return s; 1.85 + } 1.86 } 1.87 1.88 /**
2.1 --- a/src/share/classes/com/sun/tools/javac/code/Source.java Sat Sep 29 09:00:58 2012 -0700 2.2 +++ b/src/share/classes/com/sun/tools/javac/code/Source.java Thu Oct 04 13:04:53 2012 +0100 2.3 @@ -194,6 +194,9 @@ 2.4 public boolean allowObjectToPrimitiveCast() { 2.5 return compareTo(JDK1_7) >= 0; 2.6 } 2.7 + public boolean allowPoly() { 2.8 + return compareTo(JDK1_8) >= 0; 2.9 + } 2.10 public boolean allowLambda() { 2.11 return compareTo(JDK1_8) >= 0; 2.12 }
3.1 --- a/src/share/classes/com/sun/tools/javac/code/Symtab.java Sat Sep 29 09:00:58 2012 -0700 3.2 +++ b/src/share/classes/com/sun/tools/javac/code/Symtab.java Thu Oct 04 13:04:53 2012 +0100 3.3 @@ -183,6 +183,10 @@ 3.4 */ 3.5 public final Name[] boxedName = new Name[TypeTags.TypeTagCount]; 3.6 3.7 + /** A set containing all operator names. 3.8 + */ 3.9 + public final Set<Name> operatorNames = new HashSet<Name>(); 3.10 + 3.11 /** A hashtable containing the encountered top-level and member classes, 3.12 * indexed by flat names. The table does not contain local classes. 3.13 * It should be updated from the outside to reflect classes defined 3.14 @@ -244,7 +248,7 @@ 3.15 int opcode) { 3.16 predefClass.members().enter( 3.17 new OperatorSymbol( 3.18 - names.fromString(name), 3.19 + makeOperatorName(name), 3.20 new MethodType(List.of(left, right), res, 3.21 List.<Type>nil(), methodClass), 3.22 opcode, 3.23 @@ -275,7 +279,7 @@ 3.24 Type res, 3.25 int opcode) { 3.26 OperatorSymbol sym = 3.27 - new OperatorSymbol(names.fromString(name), 3.28 + new OperatorSymbol(makeOperatorName(name), 3.29 new MethodType(List.of(arg), 3.30 res, 3.31 List.<Type>nil(), 3.32 @@ -286,6 +290,16 @@ 3.33 return sym; 3.34 } 3.35 3.36 + /** 3.37 + * Create a new operator name from corresponding String representation 3.38 + * and add the name to the set of known operator names. 3.39 + */ 3.40 + private Name makeOperatorName(String name) { 3.41 + Name opName = names.fromString(name); 3.42 + operatorNames.add(opName); 3.43 + return opName; 3.44 + } 3.45 + 3.46 /** Enter a class into symbol table. 3.47 * @param The name of the class. 3.48 */
4.1 --- a/src/share/classes/com/sun/tools/javac/code/Type.java Sat Sep 29 09:00:58 2012 -0700 4.2 +++ b/src/share/classes/com/sun/tools/javac/code/Type.java Thu Oct 04 13:04:53 2012 +0100 4.3 @@ -75,6 +75,9 @@ 4.4 /** Constant type: no type at all. */ 4.5 public static final JCNoType noType = new JCNoType(NONE); 4.6 4.7 + /** Constant type: special type to be used during recovery of deferred expressions. */ 4.8 + public static final JCNoType recoveryType = new JCNoType(NONE); 4.9 + 4.10 /** If this switch is turned on, the names of type variables 4.11 * and anonymous classes are printed with hashcodes appended. 4.12 */
5.1 --- a/src/share/classes/com/sun/tools/javac/code/TypeTags.java Sat Sep 29 09:00:58 2012 -0700 5.2 +++ b/src/share/classes/com/sun/tools/javac/code/TypeTags.java Thu Oct 04 13:04:53 2012 +0100 5.3 @@ -102,9 +102,13 @@ 5.4 */ 5.5 public static final int FORALL = WILDCARD+1; 5.6 5.7 + /** The tag of deferred expression types in method context 5.8 + */ 5.9 + public static final int DEFERRED = FORALL+1; 5.10 + 5.11 /** The tag of the bottom type <null>. 5.12 */ 5.13 - public static final int BOT = FORALL+1; 5.14 + public static final int BOT = DEFERRED+1; 5.15 5.16 /** The tag of a missing type. 5.17 */
6.1 --- a/src/share/classes/com/sun/tools/javac/code/Types.java Sat Sep 29 09:00:58 2012 -0700 6.2 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java Thu Oct 04 13:04:53 2012 +0100 6.3 @@ -3154,6 +3154,14 @@ 6.4 } 6.5 return Type.noType; 6.6 } 6.7 + 6.8 + /** 6.9 + * Return the unboxed type if 't' is a boxed class, otherwise return 't' itself. 6.10 + */ 6.11 + public Type unboxedTypeOrType(Type t) { 6.12 + Type unboxedType = unboxedType(t); 6.13 + return unboxedType.tag == NONE ? t : unboxedType; 6.14 + } 6.15 // </editor-fold> 6.16 6.17 // <editor-fold defaultstate="collapsed" desc="Capture conversion">
7.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Sat Sep 29 09:00:58 2012 -0700 7.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Oct 04 13:04:53 2012 +0100 7.3 @@ -25,12 +25,10 @@ 7.4 7.5 package com.sun.tools.javac.comp; 7.6 7.7 -import java.util.*; 7.8 -import java.util.Set; 7.9 -import javax.lang.model.element.ElementKind; 7.10 -import javax.tools.JavaFileObject; 7.11 - 7.12 import com.sun.tools.javac.code.*; 7.13 +import com.sun.tools.javac.comp.DeferredAttr.AttrMode; 7.14 +import com.sun.tools.javac.comp.Infer.InferenceContext; 7.15 +import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener; 7.16 import com.sun.tools.javac.jvm.*; 7.17 import com.sun.tools.javac.tree.*; 7.18 import com.sun.tools.javac.util.*; 7.19 @@ -49,6 +47,11 @@ 7.20 import com.sun.source.tree.TreeVisitor; 7.21 import com.sun.source.util.SimpleTreeVisitor; 7.22 7.23 +import java.util.*; 7.24 +import java.util.Set; 7.25 +import javax.lang.model.element.ElementKind; 7.26 +import javax.tools.JavaFileObject; 7.27 + 7.28 import static com.sun.tools.javac.code.Flags.*; 7.29 import static com.sun.tools.javac.code.Flags.ANNOTATION; 7.30 import static com.sun.tools.javac.code.Flags.BLOCK; 7.31 @@ -80,6 +83,7 @@ 7.32 final Symtab syms; 7.33 final Resolve rs; 7.34 final Infer infer; 7.35 + final DeferredAttr deferredAttr; 7.36 final Check chk; 7.37 final MemberEnter memberEnter; 7.38 final TreeMaker make; 7.39 @@ -110,6 +114,7 @@ 7.40 make = TreeMaker.instance(context); 7.41 enter = Enter.instance(context); 7.42 infer = Infer.instance(context); 7.43 + deferredAttr = DeferredAttr.instance(context); 7.44 cfolder = ConstFold.instance(context); 7.45 target = Target.instance(context); 7.46 types = Types.instance(context); 7.47 @@ -127,6 +132,7 @@ 7.48 allowCovariantReturns = source.allowCovariantReturns(); 7.49 allowAnonOuterThis = source.allowAnonOuterThis(); 7.50 allowStringsInSwitch = source.allowStringsInSwitch(); 7.51 + allowPoly = source.allowPoly() && options.isSet("allowPoly"); 7.52 sourceName = source.name; 7.53 relax = (options.isSet("-retrofit") || 7.54 options.isSet("-relax")); 7.55 @@ -144,6 +150,10 @@ 7.56 */ 7.57 boolean relax; 7.58 7.59 + /** Switch: support target-typing inference 7.60 + */ 7.61 + boolean allowPoly; 7.62 + 7.63 /** Switch: support generics? 7.64 */ 7.65 boolean allowGenerics; 7.66 @@ -207,15 +217,29 @@ 7.67 * @param ownkind The computed kind of the tree 7.68 * @param resultInfo The expected result of the tree 7.69 */ 7.70 - Type check(JCTree tree, Type owntype, int ownkind, ResultInfo resultInfo) { 7.71 + Type check(final JCTree tree, final Type found, final int ownkind, final ResultInfo resultInfo) { 7.72 + InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext(); 7.73 + Type owntype = found; 7.74 if (owntype.tag != ERROR && resultInfo.pt.tag != METHOD && resultInfo.pt.tag != FORALL) { 7.75 - if ((ownkind & ~resultInfo.pkind) == 0) { 7.76 - owntype = resultInfo.check(tree, owntype); 7.77 + if (inferenceContext.free(found)) { 7.78 + inferenceContext.addFreeTypeListener(List.of(found, resultInfo.pt), new FreeTypeListener() { 7.79 + @Override 7.80 + public void typesInferred(InferenceContext inferenceContext) { 7.81 + ResultInfo pendingResult = 7.82 + resultInfo.dup(inferenceContext.asInstType(resultInfo.pt, types)); 7.83 + check(tree, inferenceContext.asInstType(found, types), ownkind, pendingResult); 7.84 + } 7.85 + }); 7.86 + return tree.type = resultInfo.pt; 7.87 } else { 7.88 - log.error(tree.pos(), "unexpected.type", 7.89 - kindNames(resultInfo.pkind), 7.90 - kindName(ownkind)); 7.91 - owntype = types.createErrorType(owntype); 7.92 + if ((ownkind & ~resultInfo.pkind) == 0) { 7.93 + owntype = resultInfo.check(tree, owntype); 7.94 + } else { 7.95 + log.error(tree.pos(), "unexpected.type", 7.96 + kindNames(resultInfo.pkind), 7.97 + kindName(ownkind)); 7.98 + owntype = types.createErrorType(owntype); 7.99 + } 7.100 } 7.101 } 7.102 tree.type = owntype; 7.103 @@ -297,8 +321,6 @@ 7.104 } else { 7.105 log.error(pos, "cant.assign.val.to.final.var", v); 7.106 } 7.107 - } else if ((v.flags() & EFFECTIVELY_FINAL) != 0) { 7.108 - v.flags_field &= ~EFFECTIVELY_FINAL; 7.109 } 7.110 } 7.111 7.112 @@ -431,14 +453,38 @@ 7.113 static final long serialVersionUID = -6924771130405446405L; 7.114 private Env<AttrContext> env; 7.115 private BreakAttr(Env<AttrContext> env) { 7.116 - this.env = env; 7.117 + this.env = copyEnv(env); 7.118 + } 7.119 + 7.120 + private Env<AttrContext> copyEnv(Env<AttrContext> env) { 7.121 + Env<AttrContext> newEnv = 7.122 + env.dup(env.tree, env.info.dup(copyScope(env.info.scope))); 7.123 + if (newEnv.outer != null) { 7.124 + newEnv.outer = copyEnv(newEnv.outer); 7.125 + } 7.126 + return newEnv; 7.127 + } 7.128 + 7.129 + private Scope copyScope(Scope sc) { 7.130 + Scope newScope = new Scope(sc.owner); 7.131 + List<Symbol> elemsList = List.nil(); 7.132 + while (sc != null) { 7.133 + for (Scope.Entry e = sc.elems ; e != null ; e = e.sibling) { 7.134 + elemsList = elemsList.prepend(e.sym); 7.135 + } 7.136 + sc = sc.next; 7.137 + } 7.138 + for (Symbol s : elemsList) { 7.139 + newScope.enter(s); 7.140 + } 7.141 + return newScope; 7.142 } 7.143 } 7.144 7.145 class ResultInfo { 7.146 - int pkind; 7.147 - Type pt; 7.148 - CheckContext checkContext; 7.149 + final int pkind; 7.150 + final Type pt; 7.151 + final CheckContext checkContext; 7.152 7.153 ResultInfo(int pkind, Type pt) { 7.154 this(pkind, pt, chk.basicHandler); 7.155 @@ -450,15 +496,19 @@ 7.156 this.checkContext = checkContext; 7.157 } 7.158 7.159 - protected Type check(DiagnosticPosition pos, Type found) { 7.160 + protected Type check(final DiagnosticPosition pos, final Type found) { 7.161 return chk.checkType(pos, found, pt, checkContext); 7.162 } 7.163 + 7.164 + protected ResultInfo dup(Type newPt) { 7.165 + return new ResultInfo(pkind, newPt, checkContext); 7.166 + } 7.167 } 7.168 7.169 - private final ResultInfo statInfo; 7.170 - private final ResultInfo varInfo; 7.171 - private final ResultInfo unknownExprInfo; 7.172 - private final ResultInfo unknownTypeInfo; 7.173 + final ResultInfo statInfo; 7.174 + final ResultInfo varInfo; 7.175 + final ResultInfo unknownExprInfo; 7.176 + final ResultInfo unknownTypeInfo; 7.177 7.178 Type pt() { 7.179 return resultInfo.pt; 7.180 @@ -491,7 +541,7 @@ 7.181 * @param env The environment visitor argument. 7.182 * @param resultInfo The result info visitor argument. 7.183 */ 7.184 - private Type attribTree(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) { 7.185 + Type attribTree(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) { 7.186 Env<AttrContext> prevEnv = this.env; 7.187 ResultInfo prevResult = this.resultInfo; 7.188 try { 7.189 @@ -563,9 +613,12 @@ 7.190 */ 7.191 List<Type> attribArgs(List<JCExpression> trees, Env<AttrContext> env) { 7.192 ListBuffer<Type> argtypes = new ListBuffer<Type>(); 7.193 - for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail) 7.194 - argtypes.append(chk.checkNonVoid( 7.195 - l.head.pos(), types.upperBound(attribExpr(l.head, env, Infer.anyPoly)))); 7.196 + for (JCExpression arg : trees) { 7.197 + Type argtype = allowPoly && TreeInfo.isPoly(arg, env.tree) ? 7.198 + deferredAttr.new DeferredType(arg, env) : 7.199 + chk.checkNonVoid(arg, attribExpr(arg, env, Infer.anyPoly)); 7.200 + argtypes.append(argtype); 7.201 + } 7.202 return argtypes.toList(); 7.203 } 7.204 7.205 @@ -979,8 +1032,11 @@ 7.206 // Create a new local environment with a local scope. 7.207 Env<AttrContext> localEnv = 7.208 env.dup(tree, env.info.dup(env.info.scope.dup())); 7.209 - attribStats(tree.stats, localEnv); 7.210 - localEnv.info.scope.leave(); 7.211 + try { 7.212 + attribStats(tree.stats, localEnv); 7.213 + } finally { 7.214 + localEnv.info.scope.leave(); 7.215 + } 7.216 } 7.217 result = null; 7.218 } 7.219 @@ -1000,43 +1056,51 @@ 7.220 public void visitForLoop(JCForLoop tree) { 7.221 Env<AttrContext> loopEnv = 7.222 env.dup(env.tree, env.info.dup(env.info.scope.dup())); 7.223 - attribStats(tree.init, loopEnv); 7.224 - if (tree.cond != null) attribExpr(tree.cond, loopEnv, syms.booleanType); 7.225 - loopEnv.tree = tree; // before, we were not in loop! 7.226 - attribStats(tree.step, loopEnv); 7.227 - attribStat(tree.body, loopEnv); 7.228 - loopEnv.info.scope.leave(); 7.229 - result = null; 7.230 + try { 7.231 + attribStats(tree.init, loopEnv); 7.232 + if (tree.cond != null) attribExpr(tree.cond, loopEnv, syms.booleanType); 7.233 + loopEnv.tree = tree; // before, we were not in loop! 7.234 + attribStats(tree.step, loopEnv); 7.235 + attribStat(tree.body, loopEnv); 7.236 + result = null; 7.237 + } 7.238 + finally { 7.239 + loopEnv.info.scope.leave(); 7.240 + } 7.241 } 7.242 7.243 public void visitForeachLoop(JCEnhancedForLoop tree) { 7.244 Env<AttrContext> loopEnv = 7.245 env.dup(env.tree, env.info.dup(env.info.scope.dup())); 7.246 - attribStat(tree.var, loopEnv); 7.247 - Type exprType = types.upperBound(attribExpr(tree.expr, loopEnv)); 7.248 - chk.checkNonVoid(tree.pos(), exprType); 7.249 - Type elemtype = types.elemtype(exprType); // perhaps expr is an array? 7.250 - if (elemtype == null) { 7.251 - // or perhaps expr implements Iterable<T>? 7.252 - Type base = types.asSuper(exprType, syms.iterableType.tsym); 7.253 - if (base == null) { 7.254 - log.error(tree.expr.pos(), 7.255 - "foreach.not.applicable.to.type", 7.256 - exprType, 7.257 - diags.fragment("type.req.array.or.iterable")); 7.258 - elemtype = types.createErrorType(exprType); 7.259 - } else { 7.260 - List<Type> iterableParams = base.allparams(); 7.261 - elemtype = iterableParams.isEmpty() 7.262 - ? syms.objectType 7.263 - : types.upperBound(iterableParams.head); 7.264 + try { 7.265 + attribStat(tree.var, loopEnv); 7.266 + Type exprType = types.upperBound(attribExpr(tree.expr, loopEnv)); 7.267 + chk.checkNonVoid(tree.pos(), exprType); 7.268 + Type elemtype = types.elemtype(exprType); // perhaps expr is an array? 7.269 + if (elemtype == null) { 7.270 + // or perhaps expr implements Iterable<T>? 7.271 + Type base = types.asSuper(exprType, syms.iterableType.tsym); 7.272 + if (base == null) { 7.273 + log.error(tree.expr.pos(), 7.274 + "foreach.not.applicable.to.type", 7.275 + exprType, 7.276 + diags.fragment("type.req.array.or.iterable")); 7.277 + elemtype = types.createErrorType(exprType); 7.278 + } else { 7.279 + List<Type> iterableParams = base.allparams(); 7.280 + elemtype = iterableParams.isEmpty() 7.281 + ? syms.objectType 7.282 + : types.upperBound(iterableParams.head); 7.283 + } 7.284 } 7.285 + chk.checkType(tree.expr.pos(), elemtype, tree.var.sym.type); 7.286 + loopEnv.tree = tree; // before, we were not in loop! 7.287 + attribStat(tree.body, loopEnv); 7.288 + result = null; 7.289 } 7.290 - chk.checkType(tree.expr.pos(), elemtype, tree.var.sym.type); 7.291 - loopEnv.tree = tree; // before, we were not in loop! 7.292 - attribStat(tree.body, loopEnv); 7.293 - loopEnv.info.scope.leave(); 7.294 - result = null; 7.295 + finally { 7.296 + loopEnv.info.scope.leave(); 7.297 + } 7.298 } 7.299 7.300 public void visitLabelled(JCLabeledStatement tree) { 7.301 @@ -1062,61 +1126,69 @@ 7.302 Env<AttrContext> switchEnv = 7.303 env.dup(tree, env.info.dup(env.info.scope.dup())); 7.304 7.305 - boolean enumSwitch = 7.306 - allowEnums && 7.307 - (seltype.tsym.flags() & Flags.ENUM) != 0; 7.308 - boolean stringSwitch = false; 7.309 - if (types.isSameType(seltype, syms.stringType)) { 7.310 - if (allowStringsInSwitch) { 7.311 - stringSwitch = true; 7.312 - } else { 7.313 - log.error(tree.selector.pos(), "string.switch.not.supported.in.source", sourceName); 7.314 + try { 7.315 + 7.316 + boolean enumSwitch = 7.317 + allowEnums && 7.318 + (seltype.tsym.flags() & Flags.ENUM) != 0; 7.319 + boolean stringSwitch = false; 7.320 + if (types.isSameType(seltype, syms.stringType)) { 7.321 + if (allowStringsInSwitch) { 7.322 + stringSwitch = true; 7.323 + } else { 7.324 + log.error(tree.selector.pos(), "string.switch.not.supported.in.source", sourceName); 7.325 + } 7.326 } 7.327 + if (!enumSwitch && !stringSwitch) 7.328 + seltype = chk.checkType(tree.selector.pos(), seltype, syms.intType); 7.329 + 7.330 + // Attribute all cases and 7.331 + // check that there are no duplicate case labels or default clauses. 7.332 + Set<Object> labels = new HashSet<Object>(); // The set of case labels. 7.333 + boolean hasDefault = false; // Is there a default label? 7.334 + for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) { 7.335 + JCCase c = l.head; 7.336 + Env<AttrContext> caseEnv = 7.337 + switchEnv.dup(c, env.info.dup(switchEnv.info.scope.dup())); 7.338 + try { 7.339 + if (c.pat != null) { 7.340 + if (enumSwitch) { 7.341 + Symbol sym = enumConstant(c.pat, seltype); 7.342 + if (sym == null) { 7.343 + log.error(c.pat.pos(), "enum.label.must.be.unqualified.enum"); 7.344 + } else if (!labels.add(sym)) { 7.345 + log.error(c.pos(), "duplicate.case.label"); 7.346 + } 7.347 + } else { 7.348 + Type pattype = attribExpr(c.pat, switchEnv, seltype); 7.349 + if (pattype.tag != ERROR) { 7.350 + if (pattype.constValue() == null) { 7.351 + log.error(c.pat.pos(), 7.352 + (stringSwitch ? "string.const.req" : "const.expr.req")); 7.353 + } else if (labels.contains(pattype.constValue())) { 7.354 + log.error(c.pos(), "duplicate.case.label"); 7.355 + } else { 7.356 + labels.add(pattype.constValue()); 7.357 + } 7.358 + } 7.359 + } 7.360 + } else if (hasDefault) { 7.361 + log.error(c.pos(), "duplicate.default.label"); 7.362 + } else { 7.363 + hasDefault = true; 7.364 + } 7.365 + attribStats(c.stats, caseEnv); 7.366 + } finally { 7.367 + caseEnv.info.scope.leave(); 7.368 + addVars(c.stats, switchEnv.info.scope); 7.369 + } 7.370 + } 7.371 + 7.372 + result = null; 7.373 } 7.374 - if (!enumSwitch && !stringSwitch) 7.375 - seltype = chk.checkType(tree.selector.pos(), seltype, syms.intType); 7.376 - 7.377 - // Attribute all cases and 7.378 - // check that there are no duplicate case labels or default clauses. 7.379 - Set<Object> labels = new HashSet<Object>(); // The set of case labels. 7.380 - boolean hasDefault = false; // Is there a default label? 7.381 - for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) { 7.382 - JCCase c = l.head; 7.383 - Env<AttrContext> caseEnv = 7.384 - switchEnv.dup(c, env.info.dup(switchEnv.info.scope.dup())); 7.385 - if (c.pat != null) { 7.386 - if (enumSwitch) { 7.387 - Symbol sym = enumConstant(c.pat, seltype); 7.388 - if (sym == null) { 7.389 - log.error(c.pat.pos(), "enum.label.must.be.unqualified.enum"); 7.390 - } else if (!labels.add(sym)) { 7.391 - log.error(c.pos(), "duplicate.case.label"); 7.392 - } 7.393 - } else { 7.394 - Type pattype = attribExpr(c.pat, switchEnv, seltype); 7.395 - if (pattype.tag != ERROR) { 7.396 - if (pattype.constValue() == null) { 7.397 - log.error(c.pat.pos(), 7.398 - (stringSwitch ? "string.const.req" : "const.expr.req")); 7.399 - } else if (labels.contains(pattype.constValue())) { 7.400 - log.error(c.pos(), "duplicate.case.label"); 7.401 - } else { 7.402 - labels.add(pattype.constValue()); 7.403 - } 7.404 - } 7.405 - } 7.406 - } else if (hasDefault) { 7.407 - log.error(c.pos(), "duplicate.default.label"); 7.408 - } else { 7.409 - hasDefault = true; 7.410 - } 7.411 - attribStats(c.stats, caseEnv); 7.412 - caseEnv.info.scope.leave(); 7.413 - addVars(c.stats, switchEnv.info.scope); 7.414 + finally { 7.415 + switchEnv.info.scope.leave(); 7.416 } 7.417 - 7.418 - switchEnv.info.scope.leave(); 7.419 - result = null; 7.420 } 7.421 // where 7.422 /** Add any variables defined in stats to the switch scope. */ 7.423 @@ -1158,63 +1230,72 @@ 7.424 public void visitTry(JCTry tree) { 7.425 // Create a new local environment with a local 7.426 Env<AttrContext> localEnv = env.dup(tree, env.info.dup(env.info.scope.dup())); 7.427 - boolean isTryWithResource = tree.resources.nonEmpty(); 7.428 - // Create a nested environment for attributing the try block if needed 7.429 - Env<AttrContext> tryEnv = isTryWithResource ? 7.430 - env.dup(tree, localEnv.info.dup(localEnv.info.scope.dup())) : 7.431 - localEnv; 7.432 - // Attribute resource declarations 7.433 - for (JCTree resource : tree.resources) { 7.434 - CheckContext twrContext = new Check.NestedCheckContext(resultInfo.checkContext) { 7.435 - @Override 7.436 - public void report(DiagnosticPosition pos, JCDiagnostic details) { 7.437 - chk.basicHandler.report(pos, diags.fragment("try.not.applicable.to.type", details)); 7.438 + try { 7.439 + boolean isTryWithResource = tree.resources.nonEmpty(); 7.440 + // Create a nested environment for attributing the try block if needed 7.441 + Env<AttrContext> tryEnv = isTryWithResource ? 7.442 + env.dup(tree, localEnv.info.dup(localEnv.info.scope.dup())) : 7.443 + localEnv; 7.444 + try { 7.445 + // Attribute resource declarations 7.446 + for (JCTree resource : tree.resources) { 7.447 + CheckContext twrContext = new Check.NestedCheckContext(resultInfo.checkContext) { 7.448 + @Override 7.449 + public void report(DiagnosticPosition pos, JCDiagnostic details) { 7.450 + chk.basicHandler.report(pos, diags.fragment("try.not.applicable.to.type", details)); 7.451 + } 7.452 + }; 7.453 + ResultInfo twrResult = new ResultInfo(VAL, syms.autoCloseableType, twrContext); 7.454 + if (resource.hasTag(VARDEF)) { 7.455 + attribStat(resource, tryEnv); 7.456 + twrResult.check(resource, resource.type); 7.457 + 7.458 + //check that resource type cannot throw InterruptedException 7.459 + checkAutoCloseable(resource.pos(), localEnv, resource.type); 7.460 + 7.461 + VarSymbol var = (VarSymbol)TreeInfo.symbolFor(resource); 7.462 + var.setData(ElementKind.RESOURCE_VARIABLE); 7.463 + } else { 7.464 + attribTree(resource, tryEnv, twrResult); 7.465 + } 7.466 } 7.467 - }; 7.468 - ResultInfo twrResult = new ResultInfo(VAL, syms.autoCloseableType, twrContext); 7.469 - if (resource.hasTag(VARDEF)) { 7.470 - attribStat(resource, tryEnv); 7.471 - twrResult.check(resource, resource.type); 7.472 - 7.473 - //check that resource type cannot throw InterruptedException 7.474 - checkAutoCloseable(resource.pos(), localEnv, resource.type); 7.475 - 7.476 - VarSymbol var = (VarSymbol)TreeInfo.symbolFor(resource); 7.477 - var.setData(ElementKind.RESOURCE_VARIABLE); 7.478 - } else { 7.479 - attribTree(resource, tryEnv, twrResult); 7.480 + // Attribute body 7.481 + attribStat(tree.body, tryEnv); 7.482 + } finally { 7.483 + if (isTryWithResource) 7.484 + tryEnv.info.scope.leave(); 7.485 } 7.486 + 7.487 + // Attribute catch clauses 7.488 + for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { 7.489 + JCCatch c = l.head; 7.490 + Env<AttrContext> catchEnv = 7.491 + localEnv.dup(c, localEnv.info.dup(localEnv.info.scope.dup())); 7.492 + try { 7.493 + Type ctype = attribStat(c.param, catchEnv); 7.494 + if (TreeInfo.isMultiCatch(c)) { 7.495 + //multi-catch parameter is implicitly marked as final 7.496 + c.param.sym.flags_field |= FINAL | UNION; 7.497 + } 7.498 + if (c.param.sym.kind == Kinds.VAR) { 7.499 + c.param.sym.setData(ElementKind.EXCEPTION_PARAMETER); 7.500 + } 7.501 + chk.checkType(c.param.vartype.pos(), 7.502 + chk.checkClassType(c.param.vartype.pos(), ctype), 7.503 + syms.throwableType); 7.504 + attribStat(c.body, catchEnv); 7.505 + } finally { 7.506 + catchEnv.info.scope.leave(); 7.507 + } 7.508 + } 7.509 + 7.510 + // Attribute finalizer 7.511 + if (tree.finalizer != null) attribStat(tree.finalizer, localEnv); 7.512 + result = null; 7.513 } 7.514 - // Attribute body 7.515 - attribStat(tree.body, tryEnv); 7.516 - if (isTryWithResource) 7.517 - tryEnv.info.scope.leave(); 7.518 - 7.519 - // Attribute catch clauses 7.520 - for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { 7.521 - JCCatch c = l.head; 7.522 - Env<AttrContext> catchEnv = 7.523 - localEnv.dup(c, localEnv.info.dup(localEnv.info.scope.dup())); 7.524 - Type ctype = attribStat(c.param, catchEnv); 7.525 - if (TreeInfo.isMultiCatch(c)) { 7.526 - //multi-catch parameter is implicitly marked as final 7.527 - c.param.sym.flags_field |= FINAL | UNION; 7.528 - } 7.529 - if (c.param.sym.kind == Kinds.VAR) { 7.530 - c.param.sym.setData(ElementKind.EXCEPTION_PARAMETER); 7.531 - } 7.532 - chk.checkType(c.param.vartype.pos(), 7.533 - chk.checkClassType(c.param.vartype.pos(), ctype), 7.534 - syms.throwableType); 7.535 - attribStat(c.body, catchEnv); 7.536 - catchEnv.info.scope.leave(); 7.537 + finally { 7.538 + localEnv.info.scope.leave(); 7.539 } 7.540 - 7.541 - // Attribute finalizer 7.542 - if (tree.finalizer != null) attribStat(tree.finalizer, localEnv); 7.543 - 7.544 - localEnv.info.scope.leave(); 7.545 - result = null; 7.546 } 7.547 7.548 void checkAutoCloseable(DiagnosticPosition pos, Env<AttrContext> env, Type resource) { 7.549 @@ -1222,10 +1303,10 @@ 7.550 types.asSuper(resource, syms.autoCloseableType.tsym) != null && 7.551 !types.isSameType(resource, syms.autoCloseableType)) { // Don't emit warning for AutoCloseable itself 7.552 Symbol close = syms.noSymbol; 7.553 - boolean prevDeferDiags = log.deferDiagnostics; 7.554 + Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter; 7.555 Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics; 7.556 try { 7.557 - log.deferDiagnostics = true; 7.558 + log.deferAll(); 7.559 log.deferredDiagnostics = ListBuffer.lb(); 7.560 close = rs.resolveQualifiedMethod(pos, 7.561 env, 7.562 @@ -1235,7 +1316,7 @@ 7.563 List.<Type>nil()); 7.564 } 7.565 finally { 7.566 - log.deferDiagnostics = prevDeferDiags; 7.567 + log.deferredDiagFilter = prevDeferDiagsFilter; 7.568 log.deferredDiagnostics = prevDeferredDiags; 7.569 } 7.570 if (close.kind == MTH && 7.571 @@ -1248,50 +1329,71 @@ 7.572 } 7.573 7.574 public void visitConditional(JCConditional tree) { 7.575 - attribExpr(tree.cond, env, syms.booleanType); 7.576 - attribExpr(tree.truepart, env); 7.577 - attribExpr(tree.falsepart, env); 7.578 - result = check(tree, 7.579 - capture(condType(tree.pos(), tree.cond.type, 7.580 - tree.truepart.type, tree.falsepart.type)), 7.581 - VAL, resultInfo); 7.582 + Type condtype = attribExpr(tree.cond, env, syms.booleanType); 7.583 + 7.584 + boolean standaloneConditional = !allowPoly || 7.585 + pt().tag == NONE && pt() != Type.recoveryType || 7.586 + isBooleanOrNumeric(env, tree); 7.587 + 7.588 + if (!standaloneConditional && resultInfo.pt.tag == VOID) { 7.589 + //cannot get here (i.e. it means we are returning from void method - which is already an error) 7.590 + result = tree.type = types.createErrorType(resultInfo.pt); 7.591 + return; 7.592 + } 7.593 + 7.594 + ResultInfo condInfo = standaloneConditional ? 7.595 + unknownExprInfo : 7.596 + new ResultInfo(VAL, pt(), new Check.NestedCheckContext(resultInfo.checkContext) { 7.597 + //this will use enclosing check context to check compatibility of 7.598 + //subexpression against target type; if we are in a method check context, 7.599 + //depending on whether boxing is allowed, we could have incompatibilities 7.600 + @Override 7.601 + public void report(DiagnosticPosition pos, JCDiagnostic details) { 7.602 + enclosingContext.report(pos, diags.fragment("incompatible.type.in.conditional", details)); 7.603 + } 7.604 + }); 7.605 + 7.606 + Type truetype = attribTree(tree.truepart, env, condInfo); 7.607 + Type falsetype = attribTree(tree.falsepart, env, condInfo); 7.608 + 7.609 + Type owntype = standaloneConditional ? condType(tree, truetype, falsetype) : pt(); 7.610 + if (condtype.constValue() != null && 7.611 + truetype.constValue() != null && 7.612 + falsetype.constValue() != null) { 7.613 + //constant folding 7.614 + owntype = cfolder.coerce(condtype.isTrue() ? truetype : falsetype, owntype); 7.615 + } 7.616 + result = check(tree, owntype, VAL, resultInfo); 7.617 } 7.618 //where 7.619 + @SuppressWarnings("fallthrough") 7.620 + private boolean isBooleanOrNumeric(Env<AttrContext> env, JCExpression tree) { 7.621 + switch (tree.getTag()) { 7.622 + case LITERAL: return ((JCLiteral)tree).typetag < CLASS; 7.623 + case LAMBDA: case REFERENCE: return false; 7.624 + case PARENS: return isBooleanOrNumeric(env, ((JCParens)tree).expr); 7.625 + case CONDEXPR: 7.626 + JCConditional condTree = (JCConditional)tree; 7.627 + return isBooleanOrNumeric(env, condTree.truepart) && 7.628 + isBooleanOrNumeric(env, condTree.falsepart); 7.629 + default: 7.630 + Type speculativeType = deferredAttr.attribSpeculative(tree, env, unknownExprInfo).type; 7.631 + speculativeType = types.unboxedTypeOrType(speculativeType); 7.632 + return speculativeType.tag <= BOOLEAN; 7.633 + } 7.634 + } 7.635 + 7.636 /** Compute the type of a conditional expression, after 7.637 - * checking that it exists. See Spec 15.25. 7.638 - * 7.639 - * @param pos The source position to be used for 7.640 - * error diagnostics. 7.641 - * @param condtype The type of the expression's condition. 7.642 - * @param thentype The type of the expression's then-part. 7.643 - * @param elsetype The type of the expression's else-part. 7.644 - */ 7.645 - private Type condType(DiagnosticPosition pos, 7.646 - Type condtype, 7.647 - Type thentype, 7.648 - Type elsetype) { 7.649 - Type ctype = condType1(pos, condtype, thentype, elsetype); 7.650 - 7.651 - // If condition and both arms are numeric constants, 7.652 - // evaluate at compile-time. 7.653 - return ((condtype.constValue() != null) && 7.654 - (thentype.constValue() != null) && 7.655 - (elsetype.constValue() != null)) 7.656 - ? cfolder.coerce(condtype.isTrue()?thentype:elsetype, ctype) 7.657 - : ctype; 7.658 - } 7.659 - /** Compute the type of a conditional expression, after 7.660 - * checking that it exists. Does not take into 7.661 + * checking that it exists. See JLS 15.25. Does not take into 7.662 * account the special case where condition and both arms 7.663 * are constants. 7.664 * 7.665 * @param pos The source position to be used for error 7.666 * diagnostics. 7.667 - * @param condtype The type of the expression's condition. 7.668 * @param thentype The type of the expression's then-part. 7.669 * @param elsetype The type of the expression's else-part. 7.670 */ 7.671 - private Type condType1(DiagnosticPosition pos, Type condtype, 7.672 + private Type condType(DiagnosticPosition pos, 7.673 Type thentype, Type elsetype) { 7.674 // If same type, that is the result 7.675 if (types.isSameType(thentype, elsetype)) 7.676 @@ -1445,22 +1547,19 @@ 7.677 public void visitReturn(JCReturn tree) { 7.678 // Check that there is an enclosing method which is 7.679 // nested within than the enclosing class. 7.680 - if (env.enclMethod == null || 7.681 - env.enclMethod.sym.owner != env.enclClass.sym) { 7.682 + if (env.info.returnResult == null) { 7.683 log.error(tree.pos(), "ret.outside.meth"); 7.684 - 7.685 } else { 7.686 // Attribute return expression, if it exists, and check that 7.687 // it conforms to result type of enclosing method. 7.688 - Symbol m = env.enclMethod.sym; 7.689 - if (m.type.getReturnType().tag == VOID) { 7.690 - if (tree.expr != null) 7.691 + if (tree.expr != null) { 7.692 + if (env.info.returnResult.pt.tag == VOID) { 7.693 log.error(tree.expr.pos(), 7.694 "cant.ret.val.from.meth.decl.void"); 7.695 - } else if (tree.expr == null) { 7.696 + } 7.697 + attribTree(tree.expr, env, env.info.returnResult); 7.698 + } else if (env.info.returnResult.pt.tag != VOID) { 7.699 log.error(tree.pos(), "missing.ret.val"); 7.700 - } else { 7.701 - attribExpr(tree.expr, env, m.type.getReturnType()); 7.702 } 7.703 } 7.704 result = null; 7.705 @@ -1562,7 +1661,7 @@ 7.706 // current instance (JLS ???). 7.707 boolean selectSuperPrev = localEnv.info.selectSuper; 7.708 localEnv.info.selectSuper = true; 7.709 - localEnv.info.varArgs = false; 7.710 + localEnv.info.pendingResolutionPhase = null; 7.711 Symbol sym = rs.resolveConstructor( 7.712 tree.meth.pos(), localEnv, site, argtypes, typeargtypes); 7.713 localEnv.info.selectSuper = selectSuperPrev; 7.714 @@ -1573,8 +1672,7 @@ 7.715 // ...and check that it is legal in the current context. 7.716 // (this will also set the tree's type) 7.717 Type mpt = newMethodTemplate(resultInfo.pt, argtypes, typeargtypes); 7.718 - checkId(tree.meth, site, sym, localEnv, new ResultInfo(MTH, mpt), 7.719 - tree.varargsElement != null); 7.720 + checkId(tree.meth, site, sym, localEnv, new ResultInfo(MTH, mpt)); 7.721 } 7.722 // Otherwise, `site' is an error type and we do nothing 7.723 } 7.724 @@ -1589,8 +1687,8 @@ 7.725 // whose formal argument types is exactly the list of actual 7.726 // arguments (this will also set the method symbol). 7.727 Type mpt = newMethodTemplate(resultInfo.pt, argtypes, typeargtypes); 7.728 - localEnv.info.varArgs = false; 7.729 - Type mtype = attribExpr(tree.meth, localEnv, mpt); 7.730 + localEnv.info.pendingResolutionPhase = null; 7.731 + Type mtype = attribTree(tree.meth, localEnv, new ResultInfo(VAL, mpt, resultInfo.checkContext)); 7.732 7.733 // Compute the result type. 7.734 Type restype = mtype.getReturnType(); 7.735 @@ -1625,7 +1723,7 @@ 7.736 // current context. Also, capture the return type 7.737 result = check(tree, capture(restype), VAL, resultInfo); 7.738 7.739 - if (localEnv.info.varArgs) 7.740 + if (localEnv.info.lastResolveVarargs()) 7.741 Assert.check(result.isErroneous() || tree.varargsElement != null); 7.742 } 7.743 chk.validate(tree.typeargs, localEnv); 7.744 @@ -1652,11 +1750,11 @@ 7.745 /** Obtain a method type with given argument types. 7.746 */ 7.747 Type newMethodTemplate(Type restype, List<Type> argtypes, List<Type> typeargtypes) { 7.748 - MethodType mt = new MethodType(argtypes, restype, null, syms.methodClass); 7.749 + MethodType mt = new MethodType(argtypes, restype, List.<Type>nil(), syms.methodClass); 7.750 return (typeargtypes == null) ? mt : (Type)new ForAll(typeargtypes, mt); 7.751 } 7.752 7.753 - public void visitNewClass(JCNewClass tree) { 7.754 + public void visitNewClass(final JCNewClass tree) { 7.755 Type owntype = types.createErrorType(tree.type); 7.756 7.757 // The local environment of a class creation is 7.758 @@ -1729,19 +1827,6 @@ 7.759 List<Type> argtypes = attribArgs(tree.args, localEnv); 7.760 List<Type> typeargtypes = attribTypes(tree.typeargs, localEnv); 7.761 7.762 - if (TreeInfo.isDiamond(tree) && !clazztype.isErroneous()) { 7.763 - Pair<Symbol, Type> diamondResult = 7.764 - attribDiamond(localEnv, tree, clazztype, argtypes, typeargtypes); 7.765 - tree.clazz.type = types.createErrorType(clazztype); 7.766 - tree.constructor = diamondResult.fst; 7.767 - tree.constructorType = diamondResult.snd; 7.768 - if (!diamondResult.snd.isErroneous()) { 7.769 - tree.clazz.type = clazztype = diamondResult.snd.getReturnType(); 7.770 - tree.constructorType = types.createMethodTypeWithReturn(diamondResult.snd, syms.voidType); 7.771 - } 7.772 - clazztype = chk.checkClassType(tree.clazz, tree.clazz.type, true); 7.773 - } 7.774 - 7.775 // If we have made no mistakes in the class type... 7.776 if (clazztype.tag == CLASS) { 7.777 // Enums may not be instantiated except implicitly 7.778 @@ -1768,18 +1853,57 @@ 7.779 // Error recovery: pretend no arguments were supplied. 7.780 argtypes = List.nil(); 7.781 typeargtypes = List.nil(); 7.782 + } else if (TreeInfo.isDiamond(tree)) { 7.783 + ClassType site = new ClassType(clazztype.getEnclosingType(), 7.784 + clazztype.tsym.type.getTypeArguments(), 7.785 + clazztype.tsym); 7.786 + 7.787 + Env<AttrContext> diamondEnv = localEnv.dup(tree); 7.788 + diamondEnv.info.selectSuper = cdef != null; 7.789 + diamondEnv.info.pendingResolutionPhase = null; 7.790 + 7.791 + //if the type of the instance creation expression is a class type 7.792 + //apply method resolution inference (JLS 15.12.2.7). The return type 7.793 + //of the resolved constructor will be a partially instantiated type 7.794 + Symbol constructor = rs.resolveDiamond(tree.pos(), 7.795 + diamondEnv, 7.796 + site, 7.797 + argtypes, 7.798 + typeargtypes); 7.799 + tree.constructor = constructor.baseSymbol(); 7.800 + 7.801 + final TypeSymbol csym = clazztype.tsym; 7.802 + ResultInfo diamondResult = new ResultInfo(MTH, newMethodTemplate(resultInfo.pt, argtypes, typeargtypes), new Check.NestedCheckContext(resultInfo.checkContext) { 7.803 + @Override 7.804 + public void report(DiagnosticPosition _unused, JCDiagnostic details) { 7.805 + enclosingContext.report(tree.clazz, 7.806 + diags.fragment("cant.apply.diamond.1", diags.fragment("diamond", csym), details)); 7.807 + } 7.808 + }); 7.809 + Type constructorType = tree.constructorType = types.createErrorType(clazztype); 7.810 + constructorType = checkId(tree, site, 7.811 + constructor, 7.812 + diamondEnv, 7.813 + diamondResult); 7.814 + 7.815 + tree.clazz.type = types.createErrorType(clazztype); 7.816 + if (!constructorType.isErroneous()) { 7.817 + tree.clazz.type = clazztype = constructorType.getReturnType(); 7.818 + tree.constructorType = types.createMethodTypeWithReturn(constructorType, syms.voidType); 7.819 + } 7.820 + clazztype = chk.checkClassType(tree.clazz, tree.clazz.type, true); 7.821 } 7.822 7.823 // Resolve the called constructor under the assumption 7.824 // that we are referring to a superclass instance of the 7.825 // current instance (JLS ???). 7.826 - else if (!TreeInfo.isDiamond(tree)) { 7.827 + else { 7.828 //the following code alters some of the fields in the current 7.829 //AttrContext - hence, the current context must be dup'ed in 7.830 //order to avoid downstream failures 7.831 Env<AttrContext> rsEnv = localEnv.dup(tree); 7.832 rsEnv.info.selectSuper = cdef != null; 7.833 - rsEnv.info.varArgs = false; 7.834 + rsEnv.info.pendingResolutionPhase = null; 7.835 tree.constructor = rs.resolveConstructor( 7.836 tree.pos(), rsEnv, clazztype, argtypes, typeargtypes); 7.837 if (cdef == null) { //do not check twice! 7.838 @@ -1787,42 +1911,11 @@ 7.839 clazztype, 7.840 tree.constructor, 7.841 rsEnv, 7.842 - new ResultInfo(MTH, newMethodTemplate(syms.voidType, argtypes, typeargtypes)), 7.843 - rsEnv.info.varArgs); 7.844 - if (rsEnv.info.varArgs) 7.845 + new ResultInfo(MTH, newMethodTemplate(syms.voidType, argtypes, typeargtypes))); 7.846 + if (rsEnv.info.lastResolveVarargs()) 7.847 Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null); 7.848 } 7.849 - if (tree.def == null && 7.850 - !clazztype.isErroneous() && 7.851 - clazztype.getTypeArguments().nonEmpty() && 7.852 - findDiamonds) { 7.853 - boolean prevDeferDiags = log.deferDiagnostics; 7.854 - Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics; 7.855 - Type inferred = null; 7.856 - try { 7.857 - //disable diamond-related diagnostics 7.858 - log.deferDiagnostics = true; 7.859 - log.deferredDiagnostics = ListBuffer.lb(); 7.860 - inferred = attribDiamond(localEnv, 7.861 - tree, 7.862 - clazztype, 7.863 - argtypes, 7.864 - typeargtypes).snd; 7.865 - } finally { 7.866 - log.deferDiagnostics = prevDeferDiags; 7.867 - log.deferredDiagnostics = prevDeferredDiags; 7.868 - } 7.869 - if (!inferred.isErroneous()) { 7.870 - inferred = inferred.getReturnType(); 7.871 - } 7.872 - if (inferred != null && 7.873 - types.isAssignable(inferred, pt().tag == NONE ? syms.objectType : pt(), Warner.noWarnings)) { 7.874 - String key = types.isSameType(clazztype, inferred) ? 7.875 - "diamond.redundant.args" : 7.876 - "diamond.redundant.args.1"; 7.877 - log.warning(tree.clazz.pos(), key, clazztype, inferred); 7.878 - } 7.879 - } 7.880 + findDiamondIfNeeded(localEnv, tree, clazztype); 7.881 } 7.882 7.883 if (cdef != null) { 7.884 @@ -1887,8 +1980,7 @@ 7.885 clazztype, 7.886 tree.constructor, 7.887 localEnv, 7.888 - new ResultInfo(VAL, newMethodTemplate(syms.voidType, argtypes, typeargtypes)), 7.889 - localEnv.info.varArgs); 7.890 + new ResultInfo(VAL, newMethodTemplate(syms.voidType, argtypes, typeargtypes))); 7.891 } 7.892 7.893 if (tree.constructor != null && tree.constructor.kind == MTH) 7.894 @@ -1897,53 +1989,33 @@ 7.895 result = check(tree, owntype, VAL, resultInfo); 7.896 chk.validate(tree.typeargs, localEnv); 7.897 } 7.898 - 7.899 - Pair<Symbol, Type> attribDiamond(Env<AttrContext> env, 7.900 - final JCNewClass tree, 7.901 - final Type clazztype, 7.902 - List<Type> argtypes, 7.903 - List<Type> typeargtypes) { 7.904 - if (clazztype.isErroneous() || 7.905 - clazztype.isInterface()) { 7.906 - //if the type of the instance creation expression is erroneous, 7.907 - //or if it's an interface, or if something prevented us to form a valid 7.908 - //mapping, return the (possibly erroneous) type unchanged 7.909 - return new Pair<Symbol, Type>(syms.noSymbol, clazztype); 7.910 + //where 7.911 + void findDiamondIfNeeded(Env<AttrContext> env, JCNewClass tree, Type clazztype) { 7.912 + if (tree.def == null && 7.913 + !clazztype.isErroneous() && 7.914 + clazztype.getTypeArguments().nonEmpty() && 7.915 + findDiamonds) { 7.916 + JCTypeApply ta = (JCTypeApply)tree.clazz; 7.917 + List<JCExpression> prevTypeargs = ta.arguments; 7.918 + try { 7.919 + //create a 'fake' diamond AST node by removing type-argument trees 7.920 + ta.arguments = List.nil(); 7.921 + ResultInfo findDiamondResult = new ResultInfo(VAL, 7.922 + resultInfo.checkContext.inferenceContext().free(resultInfo.pt) ? Type.noType : pt()); 7.923 + Type inferred = deferredAttr.attribSpeculative(tree, env, findDiamondResult).type; 7.924 + if (!inferred.isErroneous() && 7.925 + types.isAssignable(inferred, pt().tag == NONE ? syms.objectType : pt(), Warner.noWarnings)) { 7.926 + String key = types.isSameType(clazztype, inferred) ? 7.927 + "diamond.redundant.args" : 7.928 + "diamond.redundant.args.1"; 7.929 + log.warning(tree.clazz.pos(), key, clazztype, inferred); 7.930 + } 7.931 + } finally { 7.932 + ta.arguments = prevTypeargs; 7.933 + } 7.934 + } 7.935 } 7.936 7.937 - //dup attribution environment and augment the set of inference variables 7.938 - Env<AttrContext> localEnv = env.dup(tree); 7.939 - 7.940 - ClassType site = new ClassType(clazztype.getEnclosingType(), 7.941 - clazztype.tsym.type.getTypeArguments(), 7.942 - clazztype.tsym); 7.943 - 7.944 - //if the type of the instance creation expression is a class type 7.945 - //apply method resolution inference (JLS 15.12.2.7). The return type 7.946 - //of the resolved constructor will be a partially instantiated type 7.947 - Symbol constructor = rs.resolveDiamond(tree.pos(), 7.948 - localEnv, 7.949 - site, 7.950 - argtypes, 7.951 - typeargtypes); 7.952 - 7.953 - Type constructorType = types.createErrorType(clazztype); 7.954 - ResultInfo diamondResult = new ResultInfo(MTH, newMethodTemplate(resultInfo.pt, argtypes, typeargtypes), new Check.NestedCheckContext(resultInfo.checkContext) { 7.955 - @Override 7.956 - public void report(DiagnosticPosition _unused, JCDiagnostic details) { 7.957 - enclosingContext.report(tree.clazz, 7.958 - diags.fragment("cant.apply.diamond.1", diags.fragment("diamond", clazztype.tsym), details)); 7.959 - } 7.960 - }); 7.961 - constructorType = checkId(tree, site, 7.962 - constructor, 7.963 - localEnv, 7.964 - diamondResult, 7.965 - localEnv.info.varArgs); 7.966 - 7.967 - return new Pair<Symbol, Type>(constructor.baseSymbol(), constructorType); 7.968 - } 7.969 - 7.970 /** Make an attributed null check tree. 7.971 */ 7.972 public JCExpression makeNullCheck(JCExpression arg) { 7.973 @@ -1960,13 +2032,14 @@ 7.974 7.975 public void visitNewArray(JCNewArray tree) { 7.976 Type owntype = types.createErrorType(tree.type); 7.977 + Env<AttrContext> localEnv = env.dup(tree); 7.978 Type elemtype; 7.979 if (tree.elemtype != null) { 7.980 - elemtype = attribType(tree.elemtype, env); 7.981 - chk.validate(tree.elemtype, env); 7.982 + elemtype = attribType(tree.elemtype, localEnv); 7.983 + chk.validate(tree.elemtype, localEnv); 7.984 owntype = elemtype; 7.985 for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) { 7.986 - attribExpr(l.head, env, syms.intType); 7.987 + attribExpr(l.head, localEnv, syms.intType); 7.988 owntype = new ArrayType(owntype, syms.arrayClass); 7.989 } 7.990 } else { 7.991 @@ -1983,7 +2056,7 @@ 7.992 } 7.993 } 7.994 if (tree.elems != null) { 7.995 - attribExprs(tree.elems, env, elemtype); 7.996 + attribExprs(tree.elems, localEnv, elemtype); 7.997 owntype = new ArrayType(elemtype, syms.arrayClass); 7.998 } 7.999 if (!types.isReifiable(elemtype)) 7.1000 @@ -2132,18 +2205,34 @@ 7.1001 result = check(tree, owntype, VAL, resultInfo); 7.1002 } 7.1003 7.1004 - public void visitTypeCast(JCTypeCast tree) { 7.1005 + public void visitTypeCast(final JCTypeCast tree) { 7.1006 Type clazztype = attribType(tree.clazz, env); 7.1007 chk.validate(tree.clazz, env, false); 7.1008 //a fresh environment is required for 292 inference to work properly --- 7.1009 //see Infer.instantiatePolymorphicSignatureInstance() 7.1010 Env<AttrContext> localEnv = env.dup(tree); 7.1011 - Type exprtype = attribExpr(tree.expr, localEnv, Infer.anyPoly); 7.1012 - Type owntype = chk.checkCastable(tree.expr.pos(), exprtype, clazztype); 7.1013 + //should we propagate the target type? 7.1014 + final ResultInfo castInfo; 7.1015 + final boolean isPoly = TreeInfo.isPoly(tree.expr, tree); 7.1016 + if (isPoly) { 7.1017 + //expression is a poly - we need to propagate target type info 7.1018 + castInfo = new ResultInfo(VAL, clazztype, new Check.NestedCheckContext(resultInfo.checkContext) { 7.1019 + @Override 7.1020 + public boolean compatible(Type found, Type req, Warner warn) { 7.1021 + return types.isCastable(found, req, warn); 7.1022 + } 7.1023 + }); 7.1024 + } else { 7.1025 + //standalone cast - target-type info is not propagated 7.1026 + castInfo = unknownExprInfo; 7.1027 + } 7.1028 + Type exprtype = attribTree(tree.expr, localEnv, castInfo); 7.1029 + Type owntype = isPoly ? clazztype : chk.checkCastable(tree.expr.pos(), exprtype, clazztype); 7.1030 if (exprtype.constValue() != null) 7.1031 owntype = cfolder.coerce(exprtype, owntype); 7.1032 result = check(tree, capture(owntype), VAL, resultInfo); 7.1033 - chk.checkRedundantCast(localEnv, tree); 7.1034 + if (!isPoly) 7.1035 + chk.checkRedundantCast(localEnv, tree); 7.1036 } 7.1037 7.1038 public void visitTypeTest(JCInstanceOf tree) { 7.1039 @@ -2170,15 +2259,13 @@ 7.1040 7.1041 public void visitIdent(JCIdent tree) { 7.1042 Symbol sym; 7.1043 - boolean varArgs = false; 7.1044 7.1045 // Find symbol 7.1046 if (pt().tag == METHOD || pt().tag == FORALL) { 7.1047 // If we are looking for a method, the prototype `pt' will be a 7.1048 // method type with the type of the call's arguments as parameters. 7.1049 - env.info.varArgs = false; 7.1050 + env.info.pendingResolutionPhase = null; 7.1051 sym = rs.resolveMethod(tree.pos(), env, tree.name, pt().getParameterTypes(), pt().getTypeArguments()); 7.1052 - varArgs = env.info.varArgs; 7.1053 } else if (tree.sym != null && tree.sym.kind != VAR) { 7.1054 sym = tree.sym; 7.1055 } else { 7.1056 @@ -2240,7 +2327,7 @@ 7.1057 while (env1.outer != null && !rs.isAccessible(env, env1.enclClass.sym.type, sym)) 7.1058 env1 = env1.outer; 7.1059 } 7.1060 - result = checkId(tree, env1.enclClass.sym.type, sym, env, resultInfo, varArgs); 7.1061 + result = checkId(tree, env1.enclClass.sym.type, sym, env, resultInfo); 7.1062 } 7.1063 7.1064 public void visitSelect(JCFieldAccess tree) { 7.1065 @@ -2283,13 +2370,13 @@ 7.1066 sitesym.name == names._super; 7.1067 7.1068 // Determine the symbol represented by the selection. 7.1069 - env.info.varArgs = false; 7.1070 + env.info.pendingResolutionPhase = null; 7.1071 Symbol sym = selectSym(tree, sitesym, site, env, resultInfo); 7.1072 if (sym.exists() && !isType(sym) && (pkind() & (PCK | TYP)) != 0) { 7.1073 site = capture(site); 7.1074 sym = selectSym(tree, sitesym, site, env, resultInfo); 7.1075 } 7.1076 - boolean varArgs = env.info.varArgs; 7.1077 + boolean varArgs = env.info.lastResolveVarargs(); 7.1078 tree.sym = sym; 7.1079 7.1080 if (site.tag == TYPEVAR && !isType(sym) && sym.kind != ERR) { 7.1081 @@ -2340,7 +2427,7 @@ 7.1082 if ((sym.flags() & STATIC) == 0 && 7.1083 sym.name != names._super && 7.1084 (sym.kind == VAR || sym.kind == MTH)) { 7.1085 - rs.access(rs.new StaticError(sym), 7.1086 + rs.accessBase(rs.new StaticError(sym), 7.1087 tree.pos(), site, sym.name, true); 7.1088 } 7.1089 } 7.1090 @@ -2364,7 +2451,7 @@ 7.1091 } 7.1092 7.1093 env.info.selectSuper = selectSuperPrev; 7.1094 - result = checkId(tree, site, sym, env, resultInfo, varArgs); 7.1095 + result = checkId(tree, site, sym, env, resultInfo); 7.1096 } 7.1097 //where 7.1098 /** Determine symbol referenced by a Select expression, 7.1099 @@ -2383,7 +2470,7 @@ 7.1100 Name name = tree.name; 7.1101 switch (site.tag) { 7.1102 case PACKAGE: 7.1103 - return rs.access( 7.1104 + return rs.accessBase( 7.1105 rs.findIdentInPackage(env, site.tsym, name, resultInfo.pkind), 7.1106 pos, location, site, name, true); 7.1107 case ARRAY: 7.1108 @@ -2407,7 +2494,7 @@ 7.1109 // We are seeing a plain identifier as selector. 7.1110 Symbol sym = rs.findIdentInType(env, site, name, resultInfo.pkind); 7.1111 if ((resultInfo.pkind & ERRONEOUS) == 0) 7.1112 - sym = rs.access(sym, pos, location, site, name, true); 7.1113 + sym = rs.accessBase(sym, pos, location, site, name, true); 7.1114 return sym; 7.1115 } 7.1116 case WILDCARD: 7.1117 @@ -2429,7 +2516,7 @@ 7.1118 Symbol sym2 = (sym.flags() & Flags.PRIVATE) != 0 ? 7.1119 rs.new AccessError(env, site, sym) : 7.1120 sym; 7.1121 - rs.access(sym2, pos, location, site, name, true); 7.1122 + rs.accessBase(sym2, pos, location, site, name, true); 7.1123 return sym; 7.1124 } 7.1125 case ERROR: 7.1126 @@ -2480,9 +2567,18 @@ 7.1127 Type site, 7.1128 Symbol sym, 7.1129 Env<AttrContext> env, 7.1130 - ResultInfo resultInfo, 7.1131 - boolean useVarargs) { 7.1132 - if (resultInfo.pt.isErroneous()) return types.createErrorType(site); 7.1133 + ResultInfo resultInfo) { 7.1134 + Type pt = resultInfo.pt.tag == FORALL || resultInfo.pt.tag == METHOD ? 7.1135 + resultInfo.pt.map(deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, sym, env.info.pendingResolutionPhase)) : 7.1136 + resultInfo.pt; 7.1137 + 7.1138 + DeferredAttr.DeferredTypeMap recoveryMap = 7.1139 + deferredAttr.new RecoveryDeferredTypeMap(AttrMode.CHECK, sym, env.info.pendingResolutionPhase); 7.1140 + 7.1141 + if (pt.isErroneous()) { 7.1142 + Type.map(resultInfo.pt.getParameterTypes(), recoveryMap); 7.1143 + return types.createErrorType(site); 7.1144 + } 7.1145 Type owntype; // The computed type of this identifier occurrence. 7.1146 switch (sym.kind) { 7.1147 case TYP: 7.1148 @@ -2560,10 +2656,11 @@ 7.1149 owntype = checkMethod(site, sym, 7.1150 new ResultInfo(VAL, resultInfo.pt.getReturnType(), resultInfo.checkContext), 7.1151 env, TreeInfo.args(env.tree), resultInfo.pt.getParameterTypes(), 7.1152 - resultInfo.pt.getTypeArguments(), env.info.varArgs); 7.1153 + resultInfo.pt.getTypeArguments()); 7.1154 break; 7.1155 } 7.1156 case PCK: case ERR: 7.1157 + Type.map(resultInfo.pt.getParameterTypes(), recoveryMap); 7.1158 owntype = sym.type; 7.1159 break; 7.1160 default: 7.1161 @@ -2703,8 +2800,7 @@ 7.1162 Env<AttrContext> env, 7.1163 final List<JCExpression> argtrees, 7.1164 List<Type> argtypes, 7.1165 - List<Type> typeargtypes, 7.1166 - boolean useVarargs) { 7.1167 + List<Type> typeargtypes) { 7.1168 // Test (5): if symbol is an instance method of a raw type, issue 7.1169 // an unchecked warning if its argument types change under erasure. 7.1170 if (allowGenerics && 7.1171 @@ -2726,18 +2822,16 @@ 7.1172 // any type arguments and value arguments. 7.1173 noteWarner.clear(); 7.1174 try { 7.1175 - Type owntype = rs.rawInstantiate( 7.1176 + Type owntype = rs.checkMethod( 7.1177 env, 7.1178 site, 7.1179 sym, 7.1180 resultInfo, 7.1181 argtypes, 7.1182 typeargtypes, 7.1183 - allowBoxing, 7.1184 - useVarargs, 7.1185 noteWarner); 7.1186 7.1187 - return chk.checkMethod(owntype, sym, env, argtrees, argtypes, useVarargs, 7.1188 + return chk.checkMethod(owntype, sym, env, argtrees, argtypes, env.info.lastResolveVarargs(), 7.1189 noteWarner.hasNonSilentLint(LintCategory.UNCHECKED)); 7.1190 } catch (Infer.InferenceException ex) { 7.1191 //invalid target type - propagate exception outwards or report error 7.1192 @@ -2745,7 +2839,7 @@ 7.1193 resultInfo.checkContext.report(env.tree.pos(), ex.getDiagnostic()); 7.1194 return types.createErrorType(site); 7.1195 } catch (Resolve.InapplicableMethodException ex) { 7.1196 - Assert.error(); 7.1197 + Assert.error(ex.getDiagnostic().getMessage(Locale.getDefault())); 7.1198 return null; 7.1199 } 7.1200 } 7.1201 @@ -3053,8 +3147,10 @@ 7.1202 7.1203 Lint prevLint = chk.setLint(env.info.lint); 7.1204 JavaFileObject prev = log.useSource(c.sourcefile); 7.1205 + ResultInfo prevReturnRes = env.info.returnResult; 7.1206 7.1207 try { 7.1208 + env.info.returnResult = null; 7.1209 // java.lang.Enum may not be subclassed by a non-enum 7.1210 if (st.tsym == syms.enumSym && 7.1211 ((c.flags_field & (Flags.ENUM|Flags.COMPOUND)) == 0)) 7.1212 @@ -3071,6 +3167,7 @@ 7.1213 7.1214 chk.checkDeprecatedAnnotation(env.tree.pos(), c); 7.1215 } finally { 7.1216 + env.info.returnResult = prevReturnRes; 7.1217 log.useSource(prev); 7.1218 chk.setLint(prevLint); 7.1219 }
8.1 --- a/src/share/classes/com/sun/tools/javac/comp/AttrContext.java Sat Sep 29 09:00:58 2012 -0700 8.2 +++ b/src/share/classes/com/sun/tools/javac/comp/AttrContext.java Thu Oct 04 13:04:53 2012 +0100 8.3 @@ -56,7 +56,7 @@ 8.4 8.5 /** Are arguments to current function applications boxed into an array for varargs? 8.6 */ 8.7 - boolean varArgs = false; 8.8 + Resolve.MethodResolutionPhase pendingResolutionPhase = null; 8.9 8.10 /** A record of the lint/SuppressWarnings currently in effect 8.11 */ 8.12 @@ -67,6 +67,11 @@ 8.13 */ 8.14 Symbol enclVar = null; 8.15 8.16 + /** ResultInfo to be used for attributing 'return' statement expressions 8.17 + * (set by Attr.visitMethod and Attr.visitLambda) 8.18 + */ 8.19 + Attr.ResultInfo returnResult = null; 8.20 + 8.21 /** Duplicate this context, replacing scope field and copying all others. 8.22 */ 8.23 AttrContext dup(Scope scope) { 8.24 @@ -75,9 +80,10 @@ 8.25 info.staticLevel = staticLevel; 8.26 info.isSelfCall = isSelfCall; 8.27 info.selectSuper = selectSuper; 8.28 - info.varArgs = varArgs; 8.29 + info.pendingResolutionPhase = pendingResolutionPhase; 8.30 info.lint = lint; 8.31 info.enclVar = enclVar; 8.32 + info.returnResult = returnResult; 8.33 return info; 8.34 } 8.35 8.36 @@ -93,6 +99,11 @@ 8.37 return scope.getElements(); 8.38 } 8.39 8.40 + boolean lastResolveVarargs() { 8.41 + return pendingResolutionPhase != null && 8.42 + pendingResolutionPhase.isVarargsRequired(); 8.43 + } 8.44 + 8.45 public String toString() { 8.46 return "AttrContext[" + scope.toString() + "]"; 8.47 }
9.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Sat Sep 29 09:00:58 2012 -0700 9.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Thu Oct 04 13:04:53 2012 +0100 9.3 @@ -40,6 +40,7 @@ 9.4 import com.sun.tools.javac.code.Lint.LintCategory; 9.5 import com.sun.tools.javac.code.Type.*; 9.6 import com.sun.tools.javac.code.Symbol.*; 9.7 +import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext; 9.8 import com.sun.tools.javac.comp.Infer.InferenceContext; 9.9 import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener; 9.10 9.11 @@ -68,6 +69,7 @@ 9.12 private final Resolve rs; 9.13 private final Symtab syms; 9.14 private final Enter enter; 9.15 + private final DeferredAttr deferredAttr; 9.16 private final Infer infer; 9.17 private final Types types; 9.18 private final JCDiagnostic.Factory diags; 9.19 @@ -100,6 +102,7 @@ 9.20 rs = Resolve.instance(context); 9.21 syms = Symtab.instance(context); 9.22 enter = Enter.instance(context); 9.23 + deferredAttr = DeferredAttr.instance(context); 9.24 infer = Infer.instance(context); 9.25 this.types = Types.instance(context); 9.26 diags = JCDiagnostic.Factory.instance(context); 9.27 @@ -433,6 +436,8 @@ 9.28 public Warner checkWarner(DiagnosticPosition pos, Type found, Type req); 9.29 9.30 public Infer.InferenceContext inferenceContext(); 9.31 + 9.32 + public DeferredAttr.DeferredAttrContext deferredAttrContext(); 9.33 } 9.34 9.35 /** 9.36 @@ -463,6 +468,10 @@ 9.37 public Infer.InferenceContext inferenceContext() { 9.38 return enclosingContext.inferenceContext(); 9.39 } 9.40 + 9.41 + public DeferredAttrContext deferredAttrContext() { 9.42 + return enclosingContext.deferredAttrContext(); 9.43 + } 9.44 } 9.45 9.46 /** 9.47 @@ -483,6 +492,10 @@ 9.48 public InferenceContext inferenceContext() { 9.49 return infer.emptyContext; 9.50 } 9.51 + 9.52 + public DeferredAttrContext deferredAttrContext() { 9.53 + return deferredAttr.emptyDeferredAttrContext; 9.54 + } 9.55 }; 9.56 9.57 /** Check that a given type is assignable to a given proto-type. 9.58 @@ -817,6 +830,8 @@ 9.59 sym.owner == syms.enumSym) 9.60 formals = formals.tail.tail; 9.61 List<JCExpression> args = argtrees; 9.62 + DeferredAttr.DeferredTypeMap checkDeferredMap = 9.63 + deferredAttr.new DeferredTypeMap(DeferredAttr.AttrMode.CHECK, sym, env.info.pendingResolutionPhase); 9.64 while (formals.head != last) { 9.65 JCTree arg = args.head; 9.66 Warner warn = convertWarner(arg.pos(), arg.type, formals.head); 9.67 @@ -835,7 +850,7 @@ 9.68 } else if ((sym.flags() & VARARGS) != 0 && allowVarargs) { 9.69 // non-varargs call to varargs method 9.70 Type varParam = owntype.getParameterTypes().last(); 9.71 - Type lastArg = argtypes.last(); 9.72 + Type lastArg = checkDeferredMap.apply(argtypes.last()); 9.73 if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) && 9.74 !types.isSameType(types.erasure(varParam), types.erasure(lastArg))) 9.75 log.warning(argtrees.last().pos(), "inexact.non-varargs.call", 9.76 @@ -847,7 +862,7 @@ 9.77 kindName(sym), 9.78 sym.name, 9.79 rs.methodArguments(sym.type.getParameterTypes()), 9.80 - rs.methodArguments(argtypes), 9.81 + rs.methodArguments(Type.map(argtypes, checkDeferredMap)), 9.82 kindName(sym.location()), 9.83 sym.location()); 9.84 owntype = new MethodType(owntype.getParameterTypes(),
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Thu Oct 04 13:04:53 2012 +0100 10.3 @@ -0,0 +1,553 @@ 10.4 +/* 10.5 + * Copyright (c) 2012, 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. Oracle designates this 10.11 + * particular file as subject to the "Classpath" exception as provided 10.12 + * by Oracle in the LICENSE file that accompanied this code. 10.13 + * 10.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 10.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 10.17 + * version 2 for more details (a copy is included in the LICENSE file that 10.18 + * accompanied this code). 10.19 + * 10.20 + * You should have received a copy of the GNU General Public License version 10.21 + * 2 along with this work; if not, write to the Free Software Foundation, 10.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 10.23 + * 10.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 10.25 + * or visit www.oracle.com if you need additional information or have any 10.26 + * questions. 10.27 + */ 10.28 + 10.29 +package com.sun.tools.javac.comp; 10.30 + 10.31 +import com.sun.tools.javac.code.*; 10.32 +import com.sun.tools.javac.tree.*; 10.33 +import com.sun.tools.javac.util.*; 10.34 +import com.sun.tools.javac.code.Symbol.*; 10.35 +import com.sun.tools.javac.code.Type.*; 10.36 +import com.sun.tools.javac.comp.Attr.ResultInfo; 10.37 +import com.sun.tools.javac.comp.Infer.InferenceContext; 10.38 +import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase; 10.39 +import com.sun.tools.javac.tree.JCTree.*; 10.40 + 10.41 +import javax.tools.JavaFileObject; 10.42 + 10.43 +import java.util.ArrayList; 10.44 +import java.util.HashSet; 10.45 +import java.util.Map; 10.46 +import java.util.Queue; 10.47 +import java.util.Set; 10.48 +import java.util.WeakHashMap; 10.49 + 10.50 +import static com.sun.tools.javac.code.TypeTags.*; 10.51 +import static com.sun.tools.javac.tree.JCTree.Tag.*; 10.52 +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 10.53 + 10.54 +/** 10.55 + * This is an helper class that is used to perform deferred type-analysis. 10.56 + * Each time a poly expression occurs in argument position, javac attributes it 10.57 + * with a temporary 'deferred type' that is checked (possibly multiple times) 10.58 + * against an expected formal type. 10.59 + * 10.60 + * <p><b>This is NOT part of any supported API. 10.61 + * If you write code that depends on this, you do so at your own risk. 10.62 + * This code and its internal interfaces are subject to change or 10.63 + * deletion without notice.</b> 10.64 + */ 10.65 +public class DeferredAttr extends JCTree.Visitor { 10.66 + protected static final Context.Key<DeferredAttr> deferredAttrKey = 10.67 + new Context.Key<DeferredAttr>(); 10.68 + 10.69 + final Attr attr; 10.70 + final Check chk; 10.71 + final Enter enter; 10.72 + final Infer infer; 10.73 + final Log log; 10.74 + final Symtab syms; 10.75 + final TreeMaker make; 10.76 + final Types types; 10.77 + 10.78 + public static DeferredAttr instance(Context context) { 10.79 + DeferredAttr instance = context.get(deferredAttrKey); 10.80 + if (instance == null) 10.81 + instance = new DeferredAttr(context); 10.82 + return instance; 10.83 + } 10.84 + 10.85 + protected DeferredAttr(Context context) { 10.86 + context.put(deferredAttrKey, this); 10.87 + attr = Attr.instance(context); 10.88 + chk = Check.instance(context); 10.89 + enter = Enter.instance(context); 10.90 + infer = Infer.instance(context); 10.91 + log = Log.instance(context); 10.92 + syms = Symtab.instance(context); 10.93 + make = TreeMaker.instance(context); 10.94 + types = Types.instance(context); 10.95 + } 10.96 + 10.97 + /** 10.98 + * This type represents a deferred type. A deferred type starts off with 10.99 + * no information on the underlying expression type. Such info needs to be 10.100 + * discovered through type-checking the deferred type against a target-type. 10.101 + * Every deferred type keeps a pointer to the AST node from which it originated. 10.102 + */ 10.103 + public class DeferredType extends Type { 10.104 + 10.105 + public JCExpression tree; 10.106 + Env<AttrContext> env; 10.107 + AttrMode mode; 10.108 + SpeculativeCache speculativeCache; 10.109 + 10.110 + DeferredType(JCExpression tree, Env<AttrContext> env) { 10.111 + super(DEFERRED, null); 10.112 + this.tree = tree; 10.113 + this.env = env.dup(tree, env.info.dup()); 10.114 + this.speculativeCache = new SpeculativeCache(); 10.115 + } 10.116 + 10.117 + /** 10.118 + * A speculative cache is used to keep track of all overload resolution rounds 10.119 + * that triggered speculative attribution on a given deferred type. Each entry 10.120 + * stores a pointer to the speculative tree and the resolution phase in which the entry 10.121 + * has been added. 10.122 + */ 10.123 + class SpeculativeCache { 10.124 + 10.125 + private Map<Symbol, List<Entry>> cache = 10.126 + new WeakHashMap<Symbol, List<Entry>>(); 10.127 + 10.128 + class Entry { 10.129 + JCTree speculativeTree; 10.130 + Resolve.MethodResolutionPhase phase; 10.131 + 10.132 + public Entry(JCTree speculativeTree, MethodResolutionPhase phase) { 10.133 + this.speculativeTree = speculativeTree; 10.134 + this.phase = phase; 10.135 + } 10.136 + 10.137 + boolean matches(Resolve.MethodResolutionPhase phase) { 10.138 + return this.phase == phase; 10.139 + } 10.140 + } 10.141 + 10.142 + /** 10.143 + * Clone a speculative cache entry as a fresh entry associated 10.144 + * with a new method (this maybe required to fixup speculative cache 10.145 + * misses after Resolve.access()) 10.146 + */ 10.147 + void dupAllTo(Symbol from, Symbol to) { 10.148 + Assert.check(cache.get(to) == null); 10.149 + List<Entry> entries = cache.get(from); 10.150 + if (entries != null) { 10.151 + cache.put(to, entries); 10.152 + } 10.153 + } 10.154 + 10.155 + /** 10.156 + * Retrieve a speculative cache entry corresponding to given symbol 10.157 + * and resolution phase 10.158 + */ 10.159 + Entry get(Symbol msym, MethodResolutionPhase phase) { 10.160 + List<Entry> entries = cache.get(msym); 10.161 + if (entries == null) return null; 10.162 + for (Entry e : entries) { 10.163 + if (e.matches(phase)) return e; 10.164 + } 10.165 + return null; 10.166 + } 10.167 + 10.168 + /** 10.169 + * Stores a speculative cache entry corresponding to given symbol 10.170 + * and resolution phase 10.171 + */ 10.172 + void put(Symbol msym, JCTree speculativeTree, MethodResolutionPhase phase) { 10.173 + List<Entry> entries = cache.get(msym); 10.174 + if (entries == null) { 10.175 + entries = List.nil(); 10.176 + } 10.177 + cache.put(msym, entries.prepend(new Entry(speculativeTree, phase))); 10.178 + } 10.179 + } 10.180 + 10.181 + /** 10.182 + * Get the type that has been computed during a speculative attribution round 10.183 + */ 10.184 + Type speculativeType(Symbol msym, MethodResolutionPhase phase) { 10.185 + SpeculativeCache.Entry e = speculativeCache.get(msym, phase); 10.186 + return e != null ? e.speculativeTree.type : Type.noType; 10.187 + } 10.188 + 10.189 + /** 10.190 + * Check a deferred type against a potential target-type. Depending on 10.191 + * the current attribution mode, a normal vs. speculative attribution 10.192 + * round is performed on the underlying AST node. There can be only one 10.193 + * speculative round for a given target method symbol; moreover, a normal 10.194 + * attribution round must follow one or more speculative rounds. 10.195 + */ 10.196 + Type check(ResultInfo resultInfo) { 10.197 + DeferredAttrContext deferredAttrContext = 10.198 + resultInfo.checkContext.deferredAttrContext(); 10.199 + Assert.check(deferredAttrContext != emptyDeferredAttrContext); 10.200 + List<Type> stuckVars = stuckVars(tree, resultInfo); 10.201 + if (stuckVars.nonEmpty()) { 10.202 + deferredAttrContext.addDeferredAttrNode(this, resultInfo, stuckVars); 10.203 + return Type.noType; 10.204 + } else { 10.205 + try { 10.206 + switch (deferredAttrContext.mode) { 10.207 + case SPECULATIVE: 10.208 + Assert.check(mode == null || 10.209 + (mode == AttrMode.SPECULATIVE && 10.210 + speculativeType(deferredAttrContext.msym, deferredAttrContext.phase).tag == NONE)); 10.211 + JCTree speculativeTree = attribSpeculative(tree, env, resultInfo); 10.212 + speculativeCache.put(deferredAttrContext.msym, speculativeTree, deferredAttrContext.phase); 10.213 + return speculativeTree.type; 10.214 + case CHECK: 10.215 + Assert.check(mode == AttrMode.SPECULATIVE); 10.216 + return attr.attribTree(tree, env, resultInfo); 10.217 + } 10.218 + Assert.error(); 10.219 + return null; 10.220 + } finally { 10.221 + mode = deferredAttrContext.mode; 10.222 + } 10.223 + } 10.224 + } 10.225 + } 10.226 + 10.227 + /** 10.228 + * The 'mode' in which the deferred type is to be type-checked 10.229 + */ 10.230 + public enum AttrMode { 10.231 + /** 10.232 + * A speculative type-checking round is used during overload resolution 10.233 + * mainly to generate constraints on inference variables. Side-effects 10.234 + * arising from type-checking the expression associated with the deferred 10.235 + * type are reversed after the speculative round finishes. This means the 10.236 + * expression tree will be left in a blank state. 10.237 + */ 10.238 + SPECULATIVE, 10.239 + /** 10.240 + * This is the plain type-checking mode. Produces side-effects on the underlying AST node 10.241 + */ 10.242 + CHECK; 10.243 + } 10.244 + 10.245 + /** 10.246 + * Routine that performs speculative type-checking; the input AST node is 10.247 + * cloned (to avoid side-effects cause by Attr) and compiler state is 10.248 + * restored after type-checking. All diagnostics (but critical ones) are 10.249 + * disabled during speculative type-checking. 10.250 + */ 10.251 + JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) { 10.252 + JCTree newTree = new TreeCopier<Object>(make).copy(tree); 10.253 + Env<AttrContext> speculativeEnv = env.dup(newTree, env.info.dup(env.info.scope.dupUnshared())); 10.254 + speculativeEnv.info.scope.owner = env.info.scope.owner; 10.255 + Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter; 10.256 + Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics; 10.257 + final JavaFileObject currentSource = log.currentSourceFile(); 10.258 + try { 10.259 + log.deferredDiagnostics = new ListBuffer<JCDiagnostic>(); 10.260 + log.deferredDiagFilter = new Filter<JCDiagnostic>() { 10.261 + public boolean accepts(JCDiagnostic t) { 10.262 + return t.getDiagnosticSource().getFile().equals(currentSource); 10.263 + } 10.264 + }; 10.265 + attr.attribTree(newTree, speculativeEnv, resultInfo); 10.266 + unenterScanner.scan(newTree); 10.267 + return newTree; 10.268 + } catch (Abort ex) { 10.269 + //if some very bad condition occurred during deferred attribution 10.270 + //we should dump all errors before killing javac 10.271 + log.reportDeferredDiagnostics(); 10.272 + throw ex; 10.273 + } finally { 10.274 + unenterScanner.scan(newTree); 10.275 + log.deferredDiagFilter = prevDeferDiagsFilter; 10.276 + log.deferredDiagnostics = prevDeferredDiags; 10.277 + } 10.278 + } 10.279 + //where 10.280 + protected TreeScanner unenterScanner = new TreeScanner() { 10.281 + @Override 10.282 + public void visitClassDef(JCClassDecl tree) { 10.283 + ClassSymbol csym = tree.sym; 10.284 + enter.typeEnvs.remove(csym); 10.285 + chk.compiled.remove(csym.flatname); 10.286 + syms.classes.remove(csym.flatname); 10.287 + super.visitClassDef(tree); 10.288 + } 10.289 + }; 10.290 + 10.291 + /** 10.292 + * A deferred context is created on each method check. A deferred context is 10.293 + * used to keep track of information associated with the method check, such as 10.294 + * the symbol of the method being checked, the overload resolution phase, 10.295 + * the kind of attribution mode to be applied to deferred types and so forth. 10.296 + * As deferred types are processed (by the method check routine) stuck AST nodes 10.297 + * are added (as new deferred attribution nodes) to this context. The complete() 10.298 + * routine makes sure that all pending nodes are properly processed, by 10.299 + * progressively instantiating all inference variables on which one or more 10.300 + * deferred attribution node is stuck. 10.301 + */ 10.302 + class DeferredAttrContext { 10.303 + 10.304 + /** attribution mode */ 10.305 + final AttrMode mode; 10.306 + 10.307 + /** symbol of the method being checked */ 10.308 + final Symbol msym; 10.309 + 10.310 + /** method resolution step */ 10.311 + final Resolve.MethodResolutionPhase phase; 10.312 + 10.313 + /** inference context */ 10.314 + final InferenceContext inferenceContext; 10.315 + 10.316 + /** list of deferred attribution nodes to be processed */ 10.317 + ArrayList<DeferredAttrNode> deferredAttrNodes = new ArrayList<DeferredAttrNode>(); 10.318 + 10.319 + DeferredAttrContext(AttrMode mode, Symbol msym, MethodResolutionPhase phase, InferenceContext inferenceContext) { 10.320 + this.mode = mode; 10.321 + this.msym = msym; 10.322 + this.phase = phase; 10.323 + this.inferenceContext = inferenceContext; 10.324 + } 10.325 + 10.326 + /** 10.327 + * Adds a node to the list of deferred attribution nodes - used by Resolve.rawCheckArgumentsApplicable 10.328 + * Nodes added this way act as 'roots' for the out-of-order method checking process. 10.329 + */ 10.330 + void addDeferredAttrNode(final DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) { 10.331 + deferredAttrNodes.add(new DeferredAttrNode(dt, resultInfo, stuckVars)); 10.332 + } 10.333 + 10.334 + /** 10.335 + * Incrementally process all nodes, by skipping 'stuck' nodes and attributing 10.336 + * 'unstuck' ones. If at any point no progress can be made (no 'unstuck' nodes) 10.337 + * some inference variable might get eagerly instantiated so that all nodes 10.338 + * can be type-checked. 10.339 + */ 10.340 + void complete() { 10.341 + while (!deferredAttrNodes.isEmpty()) { 10.342 + Set<Type> stuckVars = new HashSet<Type>(); 10.343 + boolean progress = false; 10.344 + //scan a defensive copy of the node list - this is because a deferred 10.345 + //attribution round can add new nodes to the list 10.346 + for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) { 10.347 + if (!deferredAttrNode.isStuck()) { 10.348 + deferredAttrNode.process(); 10.349 + deferredAttrNodes.remove(deferredAttrNode); 10.350 + progress = true; 10.351 + } else { 10.352 + stuckVars.addAll(deferredAttrNode.stuckVars); 10.353 + } 10.354 + } 10.355 + if (!progress) { 10.356 + //remove all variables that have already been instantiated 10.357 + //from the list of stuck variables 10.358 + inferenceContext.solveAny(inferenceContext.freeVarsIn(List.from(stuckVars)), types, infer); 10.359 + inferenceContext.notifyChange(types); 10.360 + } 10.361 + } 10.362 + } 10.363 + 10.364 + /** 10.365 + * Class representing a deferred attribution node. It keeps track of 10.366 + * a deferred type, along with the expected target type information. 10.367 + */ 10.368 + class DeferredAttrNode implements Infer.InferenceContext.FreeTypeListener { 10.369 + 10.370 + /** underlying deferred type */ 10.371 + DeferredType dt; 10.372 + 10.373 + /** underlying target type information */ 10.374 + ResultInfo resultInfo; 10.375 + 10.376 + /** list of uninferred inference variables causing this node to be stuck */ 10.377 + List<Type> stuckVars; 10.378 + 10.379 + DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) { 10.380 + this.dt = dt; 10.381 + this.resultInfo = resultInfo; 10.382 + this.stuckVars = stuckVars; 10.383 + if (!stuckVars.isEmpty()) { 10.384 + resultInfo.checkContext.inferenceContext().addFreeTypeListener(stuckVars, this); 10.385 + } 10.386 + } 10.387 + 10.388 + @Override 10.389 + public void typesInferred(InferenceContext inferenceContext) { 10.390 + stuckVars = List.nil(); 10.391 + resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt, types)); 10.392 + } 10.393 + 10.394 + /** 10.395 + * is this node stuck? 10.396 + */ 10.397 + boolean isStuck() { 10.398 + return stuckVars.nonEmpty(); 10.399 + } 10.400 + 10.401 + /** 10.402 + * Process a deferred attribution node. 10.403 + * Invariant: a stuck node cannot be processed. 10.404 + */ 10.405 + void process() { 10.406 + if (isStuck()) { 10.407 + throw new IllegalStateException("Cannot process a stuck deferred node"); 10.408 + } 10.409 + dt.check(resultInfo); 10.410 + } 10.411 + } 10.412 + } 10.413 + 10.414 + /** an empty deferred attribution context - all methods throw exceptions */ 10.415 + final DeferredAttrContext emptyDeferredAttrContext = 10.416 + new DeferredAttrContext(null, null, null, null) { 10.417 + @Override 10.418 + void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) { 10.419 + Assert.error("Empty deferred context!"); 10.420 + } 10.421 + @Override 10.422 + void complete() { 10.423 + Assert.error("Empty deferred context!"); 10.424 + } 10.425 + }; 10.426 + 10.427 + /** 10.428 + * Map a list of types possibly containing one or more deferred types 10.429 + * into a list of ordinary types. Each deferred type D is mapped into a type T, 10.430 + * where T is computed by retrieving the type that has already been 10.431 + * computed for D during a previous deferred attribution round of the given kind. 10.432 + */ 10.433 + class DeferredTypeMap extends Type.Mapping { 10.434 + 10.435 + DeferredAttrContext deferredAttrContext; 10.436 + 10.437 + protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) { 10.438 + super(String.format("deferredTypeMap[%s]", mode)); 10.439 + this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase, infer.emptyContext); 10.440 + } 10.441 + 10.442 + protected boolean validState(DeferredType dt) { 10.443 + return dt.mode != null && 10.444 + deferredAttrContext.mode.ordinal() <= dt.mode.ordinal(); 10.445 + } 10.446 + 10.447 + @Override 10.448 + public Type apply(Type t) { 10.449 + if (t.tag != DEFERRED) { 10.450 + return t.map(this); 10.451 + } else { 10.452 + DeferredType dt = (DeferredType)t; 10.453 + Assert.check(validState(dt)); 10.454 + return typeOf(dt); 10.455 + } 10.456 + } 10.457 + 10.458 + protected Type typeOf(DeferredType dt) { 10.459 + switch (deferredAttrContext.mode) { 10.460 + case CHECK: 10.461 + return dt.tree.type == null ? Type.noType : dt.tree.type; 10.462 + case SPECULATIVE: 10.463 + return dt.speculativeType(deferredAttrContext.msym, deferredAttrContext.phase); 10.464 + } 10.465 + Assert.error(); 10.466 + return null; 10.467 + } 10.468 + } 10.469 + 10.470 + /** 10.471 + * Specialized recovery deferred mapping. 10.472 + * Each deferred type D is mapped into a type T, where T is computed either by 10.473 + * (i) retrieving the type that has already been computed for D during a previous 10.474 + * attribution round (as before), or (ii) by synthesizing a new type R for D 10.475 + * (the latter step is useful in a recovery scenario). 10.476 + */ 10.477 + public class RecoveryDeferredTypeMap extends DeferredTypeMap { 10.478 + 10.479 + public RecoveryDeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) { 10.480 + super(mode, msym, phase); 10.481 + } 10.482 + 10.483 + @Override 10.484 + protected Type typeOf(DeferredType dt) { 10.485 + Type owntype = super.typeOf(dt); 10.486 + return owntype.tag == NONE ? 10.487 + recover(dt) : owntype; 10.488 + } 10.489 + 10.490 + @Override 10.491 + protected boolean validState(DeferredType dt) { 10.492 + return true; 10.493 + } 10.494 + 10.495 + /** 10.496 + * Synthesize a type for a deferred type that hasn't been previously 10.497 + * reduced to an ordinary type. Functional deferred types and conditionals 10.498 + * are mapped to themselves, in order to have a richer diagnostic 10.499 + * representation. Remaining deferred types are attributed using 10.500 + * a default expected type (j.l.Object). 10.501 + */ 10.502 + private Type recover(DeferredType dt) { 10.503 + dt.check(new RecoveryInfo()); 10.504 + switch (TreeInfo.skipParens(dt.tree).getTag()) { 10.505 + case LAMBDA: 10.506 + case REFERENCE: 10.507 + case CONDEXPR: 10.508 + //propagate those deferred types to the 10.509 + //diagnostic formatter 10.510 + return dt; 10.511 + default: 10.512 + return super.apply(dt); 10.513 + } 10.514 + } 10.515 + 10.516 + class RecoveryInfo extends ResultInfo { 10.517 + 10.518 + public RecoveryInfo() { 10.519 + attr.super(Kinds.VAL, Type.recoveryType, new Check.NestedCheckContext(chk.basicHandler) { 10.520 + @Override 10.521 + public DeferredAttrContext deferredAttrContext() { 10.522 + return deferredAttrContext; 10.523 + } 10.524 + @Override 10.525 + public boolean compatible(Type found, Type req, Warner warn) { 10.526 + return true; 10.527 + } 10.528 + @Override 10.529 + public void report(DiagnosticPosition pos, JCDiagnostic details) { 10.530 + //do nothing 10.531 + } 10.532 + }); 10.533 + } 10.534 + 10.535 + @Override 10.536 + protected Type check(DiagnosticPosition pos, Type found) { 10.537 + return chk.checkNonVoid(pos, super.check(pos, found)); 10.538 + } 10.539 + } 10.540 + } 10.541 + 10.542 + /** 10.543 + * Retrieves the list of inference variables that need to be inferred before 10.544 + * an AST node can be type-checked 10.545 + */ 10.546 + @SuppressWarnings("fallthrough") 10.547 + List<Type> stuckVars(JCExpression tree, ResultInfo resultInfo) { 10.548 + switch (tree.getTag()) { 10.549 + case LAMBDA: 10.550 + case REFERENCE: 10.551 + Assert.error("not supported yet"); 10.552 + default: 10.553 + return List.nil(); 10.554 + } 10.555 + } 10.556 +}
11.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java Sat Sep 29 09:00:58 2012 -0700 11.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java Thu Oct 04 13:04:53 2012 +0100 11.3 @@ -29,6 +29,7 @@ 11.4 import com.sun.tools.javac.code.Symbol.*; 11.5 import com.sun.tools.javac.code.Type.*; 11.6 import com.sun.tools.javac.code.Type.UndetVar.InferenceBound; 11.7 +import com.sun.tools.javac.comp.DeferredAttr.AttrMode; 11.8 import com.sun.tools.javac.comp.Resolve.InapplicableMethodException; 11.9 import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode; 11.10 import com.sun.tools.javac.tree.JCTree; 11.11 @@ -62,6 +63,7 @@ 11.12 Types types; 11.13 Check chk; 11.14 Resolve rs; 11.15 + DeferredAttr deferredAttr; 11.16 Log log; 11.17 JCDiagnostic.Factory diags; 11.18 11.19 @@ -77,6 +79,7 @@ 11.20 syms = Symtab.instance(context); 11.21 types = Types.instance(context); 11.22 rs = Resolve.instance(context); 11.23 + deferredAttr = DeferredAttr.instance(context); 11.24 log = Log.instance(context); 11.25 chk = Check.instance(context); 11.26 diags = JCDiagnostic.Factory.instance(context); 11.27 @@ -187,7 +190,7 @@ 11.28 Attr.ResultInfo resultInfo, 11.29 Warner warn) throws InferenceException { 11.30 Type to = resultInfo.pt; 11.31 - if (to.tag == NONE) { 11.32 + if (to.tag == NONE || resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) { 11.33 to = mtype.getReturnType().tag <= VOID ? 11.34 mtype.getReturnType() : syms.objectType; 11.35 } 11.36 @@ -268,14 +271,16 @@ 11.37 List<Type> argtypes, 11.38 boolean allowBoxing, 11.39 boolean useVarargs, 11.40 + Resolve.MethodResolutionContext resolveContext, 11.41 Warner warn) throws InferenceException { 11.42 //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG 11.43 final InferenceContext inferenceContext = new InferenceContext(tvars, this); 11.44 inferenceException.clear(); 11.45 11.46 try { 11.47 - rs.checkRawArgumentsAcceptable(env, inferenceContext, argtypes, mt.getParameterTypes(), 11.48 - allowBoxing, useVarargs, warn, new InferenceCheckHandler(inferenceContext)); 11.49 + rs.checkRawArgumentsAcceptable(env, msym, resolveContext.attrMode(), inferenceContext, 11.50 + argtypes, mt.getParameterTypes(), allowBoxing, useVarargs, warn, 11.51 + new InferenceCheckHandler(inferenceContext)); 11.52 11.53 // minimize as yet undetermined type variables 11.54 for (Type t : inferenceContext.undetvars) { 11.55 @@ -469,6 +474,7 @@ 11.56 */ 11.57 Type instantiatePolymorphicSignatureInstance(Env<AttrContext> env, 11.58 MethodSymbol spMethod, // sig. poly. method or null if none 11.59 + Resolve.MethodResolutionContext resolveContext, 11.60 List<Type> argtypes) { 11.61 final Type restype; 11.62 11.63 @@ -498,7 +504,7 @@ 11.64 restype = syms.objectType; 11.65 } 11.66 11.67 - List<Type> paramtypes = Type.map(argtypes, implicitArgType); 11.68 + List<Type> paramtypes = Type.map(argtypes, new ImplicitArgType(spMethod, resolveContext.step)); 11.69 List<Type> exType = spMethod != null ? 11.70 spMethod.getThrownTypes() : 11.71 List.of(syms.throwableType); // make it throw all exceptions 11.72 @@ -510,16 +516,21 @@ 11.73 return mtype; 11.74 } 11.75 //where 11.76 - Mapping implicitArgType = new Mapping ("implicitArgType") { 11.77 - public Type apply(Type t) { 11.78 - t = types.erasure(t); 11.79 - if (t.tag == BOT) 11.80 - // nulls type as the marker type Null (which has no instances) 11.81 - // infer as java.lang.Void for now 11.82 - t = types.boxedClass(syms.voidType).type; 11.83 - return t; 11.84 - } 11.85 - }; 11.86 + class ImplicitArgType extends DeferredAttr.DeferredTypeMap { 11.87 + 11.88 + public ImplicitArgType(Symbol msym, Resolve.MethodResolutionPhase phase) { 11.89 + deferredAttr.super(AttrMode.SPECULATIVE, msym, phase); 11.90 + } 11.91 + 11.92 + public Type apply(Type t) { 11.93 + t = types.erasure(super.apply(t)); 11.94 + if (t.tag == BOT) 11.95 + // nulls type as the marker type Null (which has no instances) 11.96 + // infer as java.lang.Void for now 11.97 + t = types.boxedClass(syms.voidType).type; 11.98 + return t; 11.99 + } 11.100 + } 11.101 11.102 /** 11.103 * Mapping that turns inference variables into undet vars 11.104 @@ -708,6 +719,22 @@ 11.105 throw thrownEx; 11.106 } 11.107 } 11.108 + 11.109 + void solveAny(List<Type> varsToSolve, Types types, Infer infer) { 11.110 + boolean progress = false; 11.111 + for (Type t : varsToSolve) { 11.112 + UndetVar uv = (UndetVar)asFree(t, types); 11.113 + if (uv.inst == null) { 11.114 + infer.minimizeInst(uv, Warner.noWarnings); 11.115 + if (uv.inst != null) { 11.116 + progress = true; 11.117 + } 11.118 + } 11.119 + } 11.120 + if (!progress) { 11.121 + throw infer.inferenceException.setMessage("cyclic.inference", varsToSolve); 11.122 + } 11.123 + } 11.124 } 11.125 11.126 final InferenceContext emptyContext = new InferenceContext(List.<Type>nil(), this);
12.1 --- a/src/share/classes/com/sun/tools/javac/comp/Lower.java Sat Sep 29 09:00:58 2012 -0700 12.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java Thu Oct 04 13:04:53 2012 +0100 12.3 @@ -1998,7 +1998,7 @@ 12.4 // replace with <BoxedClass>.TYPE 12.5 ClassSymbol c = types.boxedClass(type); 12.6 Symbol typeSym = 12.7 - rs.access( 12.8 + rs.accessBase( 12.9 rs.findIdentInType(attrEnv, c.type, names.TYPE, VAR), 12.10 pos, c.type, names.TYPE, true); 12.11 if (typeSym.kind == VAR)
13.1 --- a/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Sat Sep 29 09:00:58 2012 -0700 13.2 +++ b/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Thu Oct 04 13:04:53 2012 +0100 13.3 @@ -604,6 +604,10 @@ 13.4 env.dup(tree, env.info.dup(env.info.scope.dupUnshared())); 13.5 localEnv.enclMethod = tree; 13.6 localEnv.info.scope.owner = tree.sym; 13.7 + if (tree.sym.type != null) { 13.8 + //when this is called in the enter stage, there's no type to be set 13.9 + localEnv.info.returnResult = attr.new ResultInfo(VAL, tree.sym.type.getReturnType()); 13.10 + } 13.11 if ((tree.mods.flags & STATIC) != 0) localEnv.info.staticLevel++; 13.12 return localEnv; 13.13 }
14.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Sat Sep 29 09:00:58 2012 -0700 14.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Oct 04 13:04:53 2012 +0100 14.3 @@ -31,6 +31,9 @@ 14.4 import com.sun.tools.javac.code.Type.*; 14.5 import com.sun.tools.javac.comp.Attr.ResultInfo; 14.6 import com.sun.tools.javac.comp.Check.CheckContext; 14.7 +import com.sun.tools.javac.comp.DeferredAttr.AttrMode; 14.8 +import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext; 14.9 +import com.sun.tools.javac.comp.DeferredAttr.DeferredType; 14.10 import com.sun.tools.javac.comp.Infer.InferenceContext; 14.11 import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener; 14.12 import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate; 14.13 @@ -42,15 +45,12 @@ 14.14 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 14.15 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; 14.16 14.17 -import java.util.ArrayList; 14.18 import java.util.Arrays; 14.19 import java.util.Collection; 14.20 import java.util.EnumMap; 14.21 import java.util.EnumSet; 14.22 -import java.util.HashSet; 14.23 import java.util.Iterator; 14.24 import java.util.Map; 14.25 -import java.util.Set; 14.26 14.27 import javax.lang.model.element.ElementVisitor; 14.28 14.29 @@ -77,6 +77,7 @@ 14.30 Log log; 14.31 Symtab syms; 14.32 Attr attr; 14.33 + DeferredAttr deferredAttr; 14.34 Check chk; 14.35 Infer infer; 14.36 ClassReader reader; 14.37 @@ -109,6 +110,7 @@ 14.38 names = Names.instance(context); 14.39 log = Log.instance(context); 14.40 attr = Attr.instance(context); 14.41 + deferredAttr = DeferredAttr.instance(context); 14.42 chk = Check.instance(context); 14.43 infer = Infer.instance(context); 14.44 reader = ClassReader.instance(context); 14.45 @@ -219,9 +221,12 @@ 14.46 } 14.47 } 14.48 String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1"; 14.49 + List<Type> argtypes2 = Type.map(argtypes, 14.50 + deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, bestSoFar, currentResolutionContext.step)); 14.51 JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name, 14.52 site.tsym, mostSpecificPos, currentResolutionContext.step, 14.53 - methodArguments(argtypes), methodArguments(typeargtypes)); 14.54 + methodArguments(argtypes2), 14.55 + methodArguments(typeargtypes)); 14.56 JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, subDiags.toList()); 14.57 log.report(d); 14.58 } 14.59 @@ -501,13 +506,34 @@ 14.60 argtypes, 14.61 allowBoxing, 14.62 useVarargs, 14.63 + currentResolutionContext, 14.64 warn); 14.65 14.66 - checkRawArgumentsAcceptable(env, argtypes, mt.getParameterTypes(), 14.67 + checkRawArgumentsAcceptable(env, m, argtypes, mt.getParameterTypes(), 14.68 allowBoxing, useVarargs, warn); 14.69 return mt; 14.70 } 14.71 14.72 + Type checkMethod(Env<AttrContext> env, 14.73 + Type site, 14.74 + Symbol m, 14.75 + ResultInfo resultInfo, 14.76 + List<Type> argtypes, 14.77 + List<Type> typeargtypes, 14.78 + Warner warn) { 14.79 + MethodResolutionContext prevContext = currentResolutionContext; 14.80 + try { 14.81 + currentResolutionContext = new MethodResolutionContext(); 14.82 + currentResolutionContext.attrMode = DeferredAttr.AttrMode.CHECK; 14.83 + MethodResolutionPhase step = currentResolutionContext.step = env.info.pendingResolutionPhase; 14.84 + return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes, 14.85 + step.isBoxingRequired(), step.isVarargsRequired(), warn); 14.86 + } 14.87 + finally { 14.88 + currentResolutionContext = prevContext; 14.89 + } 14.90 + } 14.91 + 14.92 /** Same but returns null instead throwing a NoInstanceException 14.93 */ 14.94 Type instantiate(Env<AttrContext> env, 14.95 @@ -530,13 +556,14 @@ 14.96 /** Check if a parameter list accepts a list of args. 14.97 */ 14.98 boolean argumentsAcceptable(Env<AttrContext> env, 14.99 + Symbol msym, 14.100 List<Type> argtypes, 14.101 List<Type> formals, 14.102 boolean allowBoxing, 14.103 boolean useVarargs, 14.104 Warner warn) { 14.105 try { 14.106 - checkRawArgumentsAcceptable(env, argtypes, formals, allowBoxing, useVarargs, warn); 14.107 + checkRawArgumentsAcceptable(env, msym, argtypes, formals, allowBoxing, useVarargs, warn); 14.108 return true; 14.109 } catch (InapplicableMethodException ex) { 14.110 return false; 14.111 @@ -583,12 +610,13 @@ 14.112 }; 14.113 14.114 void checkRawArgumentsAcceptable(Env<AttrContext> env, 14.115 + Symbol msym, 14.116 List<Type> argtypes, 14.117 List<Type> formals, 14.118 boolean allowBoxing, 14.119 boolean useVarargs, 14.120 Warner warn) { 14.121 - checkRawArgumentsAcceptable(env, infer.emptyContext, argtypes, formals, 14.122 + checkRawArgumentsAcceptable(env, msym, currentResolutionContext.attrMode(), infer.emptyContext, argtypes, formals, 14.123 allowBoxing, useVarargs, warn, resolveHandler); 14.124 } 14.125 14.126 @@ -598,35 +626,41 @@ 14.127 * compatible (by method invocation conversion) with the types in F. 14.128 * 14.129 * Since this routine is shared between overload resolution and method 14.130 - * type-inference, it is crucial that actual types are converted to the 14.131 - * corresponding 'undet' form (i.e. where inference variables are replaced 14.132 - * with undetvars) so that constraints can be propagated and collected. 14.133 + * type-inference, a (possibly empty) inference context is used to convert 14.134 + * formal types to the corresponding 'undet' form ahead of a compatibility 14.135 + * check so that constraints can be propagated and collected. 14.136 * 14.137 - * Moreover, if one or more types in A is a poly type, this routine calls 14.138 - * Infer.instantiateArg in order to complete the poly type (this might involve 14.139 - * deferred attribution). 14.140 + * Moreover, if one or more types in A is a deferred type, this routine uses 14.141 + * DeferredAttr in order to perform deferred attribution. If one or more actual 14.142 + * deferred types are stuck, they are placed in a queue and revisited later 14.143 + * after the remainder of the arguments have been seen. If this is not sufficient 14.144 + * to 'unstuck' the argument, a cyclic inference error is called out. 14.145 * 14.146 * A method check handler (see above) is used in order to report errors. 14.147 */ 14.148 void checkRawArgumentsAcceptable(final Env<AttrContext> env, 14.149 + Symbol msym, 14.150 + DeferredAttr.AttrMode mode, 14.151 final Infer.InferenceContext inferenceContext, 14.152 List<Type> argtypes, 14.153 List<Type> formals, 14.154 boolean allowBoxing, 14.155 boolean useVarargs, 14.156 Warner warn, 14.157 - MethodCheckHandler handler) { 14.158 + final MethodCheckHandler handler) { 14.159 Type varargsFormal = useVarargs ? formals.last() : null; 14.160 - ListBuffer<Type> checkedArgs = ListBuffer.lb(); 14.161 14.162 if (varargsFormal == null && 14.163 argtypes.size() != formals.size()) { 14.164 throw handler.arityMismatch(); // not enough args 14.165 } 14.166 14.167 + DeferredAttr.DeferredAttrContext deferredAttrContext = 14.168 + deferredAttr.new DeferredAttrContext(mode, msym, currentResolutionContext.step, inferenceContext); 14.169 + 14.170 while (argtypes.nonEmpty() && formals.head != varargsFormal) { 14.171 - ResultInfo resultInfo = methodCheckResult(formals.head, allowBoxing, false, inferenceContext, handler, warn); 14.172 - checkedArgs.append(resultInfo.check(env.tree.pos(), argtypes.head)); 14.173 + ResultInfo mresult = methodCheckResult(formals.head, allowBoxing, false, inferenceContext, deferredAttrContext, handler, warn); 14.174 + mresult.check(null, argtypes.head); 14.175 argtypes = argtypes.tail; 14.176 formals = formals.tail; 14.177 } 14.178 @@ -638,15 +672,17 @@ 14.179 if (useVarargs) { 14.180 //note: if applicability check is triggered by most specific test, 14.181 //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5) 14.182 - Type elt = types.elemtype(varargsFormal); 14.183 + final Type elt = types.elemtype(varargsFormal); 14.184 + ResultInfo mresult = methodCheckResult(elt, allowBoxing, true, inferenceContext, deferredAttrContext, handler, warn); 14.185 while (argtypes.nonEmpty()) { 14.186 - ResultInfo resultInfo = methodCheckResult(elt, allowBoxing, true, inferenceContext, handler, warn); 14.187 - checkedArgs.append(resultInfo.check(env.tree.pos(), argtypes.head)); 14.188 + mresult.check(null, argtypes.head); 14.189 argtypes = argtypes.tail; 14.190 } 14.191 //check varargs element type accessibility 14.192 varargsAccessible(env, elt, handler, inferenceContext); 14.193 } 14.194 + 14.195 + deferredAttrContext.complete(); 14.196 } 14.197 14.198 void varargsAccessible(final Env<AttrContext> env, final Type t, final Resolve.MethodCheckHandler handler, final InferenceContext inferenceContext) { 14.199 @@ -674,12 +710,15 @@ 14.200 MethodCheckHandler handler; 14.201 boolean useVarargs; 14.202 Infer.InferenceContext inferenceContext; 14.203 + DeferredAttrContext deferredAttrContext; 14.204 Warner rsWarner; 14.205 14.206 - public MethodCheckContext(MethodCheckHandler handler, boolean useVarargs, Infer.InferenceContext inferenceContext, Warner rsWarner) { 14.207 + public MethodCheckContext(MethodCheckHandler handler, boolean useVarargs, 14.208 + Infer.InferenceContext inferenceContext, DeferredAttrContext deferredAttrContext, Warner rsWarner) { 14.209 this.handler = handler; 14.210 this.useVarargs = useVarargs; 14.211 this.inferenceContext = inferenceContext; 14.212 + this.deferredAttrContext = deferredAttrContext; 14.213 this.rsWarner = rsWarner; 14.214 } 14.215 14.216 @@ -694,6 +733,10 @@ 14.217 public InferenceContext inferenceContext() { 14.218 return inferenceContext; 14.219 } 14.220 + 14.221 + public DeferredAttrContext deferredAttrContext() { 14.222 + return deferredAttrContext; 14.223 + } 14.224 } 14.225 14.226 /** 14.227 @@ -702,8 +745,9 @@ 14.228 */ 14.229 class StrictMethodContext extends MethodCheckContext { 14.230 14.231 - public StrictMethodContext(MethodCheckHandler handler, boolean useVarargs, Infer.InferenceContext inferenceContext, Warner rsWarner) { 14.232 - super(handler, useVarargs, inferenceContext, rsWarner); 14.233 + public StrictMethodContext(MethodCheckHandler handler, boolean useVarargs, 14.234 + Infer.InferenceContext inferenceContext, DeferredAttrContext deferredAttrContext, Warner rsWarner) { 14.235 + super(handler, useVarargs, inferenceContext, deferredAttrContext, rsWarner); 14.236 } 14.237 14.238 public boolean compatible(Type found, Type req, Warner warn) { 14.239 @@ -717,8 +761,9 @@ 14.240 */ 14.241 class LooseMethodContext extends MethodCheckContext { 14.242 14.243 - public LooseMethodContext(MethodCheckHandler handler, boolean useVarargs, Infer.InferenceContext inferenceContext, Warner rsWarner) { 14.244 - super(handler, useVarargs, inferenceContext, rsWarner); 14.245 + public LooseMethodContext(MethodCheckHandler handler, boolean useVarargs, 14.246 + Infer.InferenceContext inferenceContext, DeferredAttrContext deferredAttrContext, Warner rsWarner) { 14.247 + super(handler, useVarargs, inferenceContext, deferredAttrContext, rsWarner); 14.248 } 14.249 14.250 public boolean compatible(Type found, Type req, Warner warn) { 14.251 @@ -730,16 +775,37 @@ 14.252 * Create a method check context to be used during method applicability check 14.253 */ 14.254 ResultInfo methodCheckResult(Type to, boolean allowBoxing, boolean useVarargs, 14.255 - Infer.InferenceContext inferenceContext, MethodCheckHandler methodHandler, Warner rsWarner) { 14.256 + Infer.InferenceContext inferenceContext, DeferredAttr.DeferredAttrContext deferredAttrContext, 14.257 + MethodCheckHandler methodHandler, Warner rsWarner) { 14.258 MethodCheckContext checkContext = allowBoxing ? 14.259 - new LooseMethodContext(methodHandler, useVarargs, inferenceContext, rsWarner) : 14.260 - new StrictMethodContext(methodHandler, useVarargs, inferenceContext, rsWarner); 14.261 - return attr.new ResultInfo(VAL, to, checkContext) { 14.262 - @Override 14.263 - protected Type check(DiagnosticPosition pos, Type found) { 14.264 + new LooseMethodContext(methodHandler, useVarargs, inferenceContext, deferredAttrContext, rsWarner) : 14.265 + new StrictMethodContext(methodHandler, useVarargs, inferenceContext, deferredAttrContext, rsWarner); 14.266 + return new MethodResultInfo(to, checkContext, deferredAttrContext); 14.267 + } 14.268 + 14.269 + class MethodResultInfo extends ResultInfo { 14.270 + 14.271 + DeferredAttr.DeferredAttrContext deferredAttrContext; 14.272 + 14.273 + public MethodResultInfo(Type pt, MethodCheckContext checkContext, DeferredAttr.DeferredAttrContext deferredAttrContext) { 14.274 + attr.super(VAL, pt, checkContext); 14.275 + this.deferredAttrContext = deferredAttrContext; 14.276 + } 14.277 + 14.278 + @Override 14.279 + protected Type check(DiagnosticPosition pos, Type found) { 14.280 + if (found.tag == DEFERRED) { 14.281 + DeferredType dt = (DeferredType)found; 14.282 + return dt.check(this); 14.283 + } else { 14.284 return super.check(pos, chk.checkNonVoid(pos, types.capture(types.upperBound(found.baseType())))); 14.285 } 14.286 - }; 14.287 + } 14.288 + 14.289 + @Override 14.290 + protected MethodResultInfo dup(Type newPt) { 14.291 + return new MethodResultInfo(newPt, (MethodCheckContext)checkContext, deferredAttrContext); 14.292 + } 14.293 } 14.294 14.295 public static class InapplicableMethodException extends RuntimeException { 14.296 @@ -1614,14 +1680,41 @@ 14.297 * 14.298 * @param sym The symbol that was found, or a ResolveError. 14.299 * @param pos The position to use for error reporting. 14.300 + * @param location The symbol the served as a context for this lookup 14.301 * @param site The original type from where the selection took place. 14.302 * @param name The symbol's name. 14.303 + * @param qualified Did we get here through a qualified expression resolution? 14.304 * @param argtypes The invocation's value arguments, 14.305 * if we looked for a method. 14.306 * @param typeargtypes The invocation's type arguments, 14.307 * if we looked for a method. 14.308 + * @param logResolveHelper helper class used to log resolve errors 14.309 */ 14.310 - Symbol access(Symbol sym, 14.311 + Symbol accessInternal(Symbol sym, 14.312 + DiagnosticPosition pos, 14.313 + Symbol location, 14.314 + Type site, 14.315 + Name name, 14.316 + boolean qualified, 14.317 + List<Type> argtypes, 14.318 + List<Type> typeargtypes, 14.319 + LogResolveHelper logResolveHelper) { 14.320 + if (sym.kind >= AMBIGUOUS) { 14.321 + ResolveError errSym = (ResolveError)sym; 14.322 + sym = errSym.access(name, qualified ? site.tsym : syms.noSymbol); 14.323 + argtypes = logResolveHelper.getArgumentTypes(errSym, sym, name, argtypes); 14.324 + if (logResolveHelper.resolveDiagnosticNeeded(site, argtypes, typeargtypes)) { 14.325 + logResolveError(errSym, pos, location, site, name, argtypes, typeargtypes); 14.326 + } 14.327 + } 14.328 + return sym; 14.329 + } 14.330 + 14.331 + /** 14.332 + * Variant of the generalized access routine, to be used for generating method 14.333 + * resolution diagnostics 14.334 + */ 14.335 + Symbol accessMethod(Symbol sym, 14.336 DiagnosticPosition pos, 14.337 Symbol location, 14.338 Type site, 14.339 @@ -1629,53 +1722,91 @@ 14.340 boolean qualified, 14.341 List<Type> argtypes, 14.342 List<Type> typeargtypes) { 14.343 - if (sym.kind >= AMBIGUOUS) { 14.344 - ResolveError errSym = (ResolveError)sym; 14.345 - if (!site.isErroneous() && 14.346 - !Type.isErroneous(argtypes) && 14.347 - (typeargtypes==null || !Type.isErroneous(typeargtypes))) 14.348 - logResolveError(errSym, pos, location, site, name, argtypes, typeargtypes); 14.349 - sym = errSym.access(name, qualified ? site.tsym : syms.noSymbol); 14.350 - } 14.351 - return sym; 14.352 + return accessInternal(sym, pos, location, site, name, qualified, argtypes, typeargtypes, methodLogResolveHelper); 14.353 } 14.354 14.355 - /** Same as original access(), but without location. 14.356 + /** Same as original accessMethod(), but without location. 14.357 */ 14.358 - Symbol access(Symbol sym, 14.359 + Symbol accessMethod(Symbol sym, 14.360 DiagnosticPosition pos, 14.361 Type site, 14.362 Name name, 14.363 boolean qualified, 14.364 List<Type> argtypes, 14.365 List<Type> typeargtypes) { 14.366 - return access(sym, pos, site.tsym, site, name, qualified, argtypes, typeargtypes); 14.367 + return accessMethod(sym, pos, site.tsym, site, name, qualified, argtypes, typeargtypes); 14.368 } 14.369 14.370 - /** Same as original access(), but without type arguments and arguments. 14.371 + /** 14.372 + * Variant of the generalized access routine, to be used for generating variable, 14.373 + * type resolution diagnostics 14.374 */ 14.375 - Symbol access(Symbol sym, 14.376 + Symbol accessBase(Symbol sym, 14.377 DiagnosticPosition pos, 14.378 Symbol location, 14.379 Type site, 14.380 Name name, 14.381 boolean qualified) { 14.382 - if (sym.kind >= AMBIGUOUS) 14.383 - return access(sym, pos, location, site, name, qualified, List.<Type>nil(), null); 14.384 - else 14.385 - return sym; 14.386 + return accessInternal(sym, pos, location, site, name, qualified, List.<Type>nil(), null, basicLogResolveHelper); 14.387 } 14.388 14.389 - /** Same as original access(), but without location, type arguments and arguments. 14.390 + /** Same as original accessBase(), but without location. 14.391 */ 14.392 - Symbol access(Symbol sym, 14.393 + Symbol accessBase(Symbol sym, 14.394 DiagnosticPosition pos, 14.395 Type site, 14.396 Name name, 14.397 boolean qualified) { 14.398 - return access(sym, pos, site.tsym, site, name, qualified); 14.399 + return accessBase(sym, pos, site.tsym, site, name, qualified); 14.400 } 14.401 14.402 + interface LogResolveHelper { 14.403 + boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes); 14.404 + List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes); 14.405 + } 14.406 + 14.407 + LogResolveHelper basicLogResolveHelper = new LogResolveHelper() { 14.408 + public boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes) { 14.409 + return !site.isErroneous(); 14.410 + } 14.411 + public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) { 14.412 + return argtypes; 14.413 + } 14.414 + }; 14.415 + 14.416 + LogResolveHelper methodLogResolveHelper = new LogResolveHelper() { 14.417 + public boolean resolveDiagnosticNeeded(Type site, List<Type> argtypes, List<Type> typeargtypes) { 14.418 + return !site.isErroneous() && 14.419 + !Type.isErroneous(argtypes) && 14.420 + (typeargtypes == null || !Type.isErroneous(typeargtypes)); 14.421 + } 14.422 + public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) { 14.423 + if (syms.operatorNames.contains(name)) { 14.424 + return argtypes; 14.425 + } else { 14.426 + Symbol msym = errSym.kind == WRONG_MTH ? 14.427 + ((InapplicableSymbolError)errSym).errCandidate().sym : accessedSym; 14.428 + 14.429 + List<Type> argtypes2 = Type.map(argtypes, 14.430 + deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, msym, currentResolutionContext.firstErroneousResolutionPhase())); 14.431 + 14.432 + if (msym != accessedSym) { 14.433 + //fixup deferred type caches - this 'hack' is required because the symbol 14.434 + //returned by InapplicableSymbolError.access() will hide the candidate 14.435 + //method symbol that can be used for lookups in the speculative cache, 14.436 + //causing problems in Attr.checkId() 14.437 + for (Type t : argtypes) { 14.438 + if (t.tag == DEFERRED) { 14.439 + DeferredType dt = (DeferredType)t; 14.440 + dt.speculativeCache.dupAllTo(msym, accessedSym); 14.441 + } 14.442 + } 14.443 + } 14.444 + return argtypes2; 14.445 + } 14.446 + } 14.447 + }; 14.448 + 14.449 /** Check that sym is not an abstract method. 14.450 */ 14.451 void checkNonAbstract(DiagnosticPosition pos, Symbol sym) { 14.452 @@ -1734,7 +1865,7 @@ 14.453 */ 14.454 Symbol resolveIdent(DiagnosticPosition pos, Env<AttrContext> env, 14.455 Name name, int kind) { 14.456 - return access( 14.457 + return accessBase( 14.458 findIdent(env, name, kind), 14.459 pos, env.enclClass.sym.type, name, false); 14.460 } 14.461 @@ -1759,19 +1890,19 @@ 14.462 while (steps.nonEmpty() && 14.463 steps.head.isApplicable(boxingEnabled, varargsEnabled) && 14.464 sym.kind >= ERRONEOUS) { 14.465 - currentResolutionContext.step = steps.head; 14.466 + currentResolutionContext.step = env.info.pendingResolutionPhase = steps.head; 14.467 sym = findFun(env, name, argtypes, typeargtypes, 14.468 steps.head.isBoxingRequired, 14.469 - env.info.varArgs = steps.head.isVarargsRequired); 14.470 + steps.head.isVarargsRequired); 14.471 currentResolutionContext.resolutionCache.put(steps.head, sym); 14.472 steps = steps.tail; 14.473 } 14.474 if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error 14.475 MethodResolutionPhase errPhase = 14.476 currentResolutionContext.firstErroneousResolutionPhase(); 14.477 - sym = access(currentResolutionContext.resolutionCache.get(errPhase), 14.478 + sym = accessMethod(currentResolutionContext.resolutionCache.get(errPhase), 14.479 pos, env.enclClass.sym.type, name, false, argtypes, typeargtypes); 14.480 - env.info.varArgs = errPhase.isVarargsRequired; 14.481 + env.info.pendingResolutionPhase = errPhase; 14.482 } 14.483 return sym; 14.484 } 14.485 @@ -1811,10 +1942,10 @@ 14.486 while (steps.nonEmpty() && 14.487 steps.head.isApplicable(boxingEnabled, varargsEnabled) && 14.488 sym.kind >= ERRONEOUS) { 14.489 - currentResolutionContext.step = steps.head; 14.490 + currentResolutionContext.step = env.info.pendingResolutionPhase = steps.head; 14.491 sym = findMethod(env, site, name, argtypes, typeargtypes, 14.492 steps.head.isBoxingRequired(), 14.493 - env.info.varArgs = steps.head.isVarargsRequired(), false); 14.494 + steps.head.isVarargsRequired(), false); 14.495 currentResolutionContext.resolutionCache.put(steps.head, sym); 14.496 steps = steps.tail; 14.497 } 14.498 @@ -1822,13 +1953,13 @@ 14.499 //if nothing is found return the 'first' error 14.500 MethodResolutionPhase errPhase = 14.501 currentResolutionContext.firstErroneousResolutionPhase(); 14.502 - sym = access(currentResolutionContext.resolutionCache.get(errPhase), 14.503 + sym = accessMethod(currentResolutionContext.resolutionCache.get(errPhase), 14.504 pos, location, site, name, true, argtypes, typeargtypes); 14.505 - env.info.varArgs = errPhase.isVarargsRequired; 14.506 + env.info.pendingResolutionPhase = errPhase; 14.507 } else if (allowMethodHandles) { 14.508 MethodSymbol msym = (MethodSymbol)sym; 14.509 if (msym.isSignaturePolymorphic(types)) { 14.510 - env.info.varArgs = false; 14.511 + env.info.pendingResolutionPhase = BASIC; 14.512 return findPolymorphicSignatureInstance(env, sym, argtypes); 14.513 } 14.514 } 14.515 @@ -1850,7 +1981,7 @@ 14.516 Symbol spMethod, 14.517 List<Type> argtypes) { 14.518 Type mtype = infer.instantiatePolymorphicSignatureInstance(env, 14.519 - (MethodSymbol)spMethod, argtypes); 14.520 + (MethodSymbol)spMethod, currentResolutionContext, argtypes); 14.521 for (Symbol sym : polymorphicSignatureScope.getElementsByName(spMethod.name)) { 14.522 if (types.isSameType(mtype, sym.type)) { 14.523 return sym; 14.524 @@ -1918,18 +2049,18 @@ 14.525 while (steps.nonEmpty() && 14.526 steps.head.isApplicable(boxingEnabled, varargsEnabled) && 14.527 sym.kind >= ERRONEOUS) { 14.528 - currentResolutionContext.step = steps.head; 14.529 + currentResolutionContext.step = env.info.pendingResolutionPhase = steps.head; 14.530 sym = findConstructor(pos, env, site, argtypes, typeargtypes, 14.531 steps.head.isBoxingRequired(), 14.532 - env.info.varArgs = steps.head.isVarargsRequired()); 14.533 + steps.head.isVarargsRequired()); 14.534 currentResolutionContext.resolutionCache.put(steps.head, sym); 14.535 steps = steps.tail; 14.536 } 14.537 if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error 14.538 MethodResolutionPhase errPhase = currentResolutionContext.firstErroneousResolutionPhase(); 14.539 - sym = access(currentResolutionContext.resolutionCache.get(errPhase), 14.540 + sym = accessMethod(currentResolutionContext.resolutionCache.get(errPhase), 14.541 pos, site, names.init, true, argtypes, typeargtypes); 14.542 - env.info.varArgs = errPhase.isVarargsRequired(); 14.543 + env.info.pendingResolutionPhase = errPhase; 14.544 } 14.545 return sym; 14.546 } 14.547 @@ -1961,10 +2092,10 @@ 14.548 while (steps.nonEmpty() && 14.549 steps.head.isApplicable(boxingEnabled, varargsEnabled) && 14.550 sym.kind >= ERRONEOUS) { 14.551 - currentResolutionContext.step = steps.head; 14.552 + currentResolutionContext.step = env.info.pendingResolutionPhase = steps.head; 14.553 sym = findDiamond(env, site, argtypes, typeargtypes, 14.554 steps.head.isBoxingRequired(), 14.555 - env.info.varArgs = steps.head.isVarargsRequired()); 14.556 + steps.head.isVarargsRequired()); 14.557 currentResolutionContext.resolutionCache.put(steps.head, sym); 14.558 steps = steps.tail; 14.559 } 14.560 @@ -1986,8 +2117,8 @@ 14.561 } 14.562 }; 14.563 MethodResolutionPhase errPhase = currentResolutionContext.firstErroneousResolutionPhase(); 14.564 - sym = access(errSym, pos, site, names.init, true, argtypes, typeargtypes); 14.565 - env.info.varArgs = errPhase.isVarargsRequired(); 14.566 + sym = accessMethod(errSym, pos, site, names.init, true, argtypes, typeargtypes); 14.567 + env.info.pendingResolutionPhase = errPhase; 14.568 } 14.569 return sym; 14.570 } 14.571 @@ -2115,7 +2246,7 @@ 14.572 if (boxingEnabled && sym.kind >= WRONG_MTHS) 14.573 sym = findMethod(env, syms.predefClass.type, name, argtypes, 14.574 null, true, false, true); 14.575 - return access(sym, pos, env.enclClass.sym.type, name, 14.576 + return accessMethod(sym, pos, env.enclClass.sym.type, name, 14.577 false, argtypes, null); 14.578 } 14.579 finally { 14.580 @@ -2167,7 +2298,7 @@ 14.581 Symbol sym = env1.info.scope.lookup(name).sym; 14.582 if (sym != null) { 14.583 if (staticOnly) sym = new StaticError(sym); 14.584 - return access(sym, pos, env.enclClass.sym.type, 14.585 + return accessBase(sym, pos, env.enclClass.sym.type, 14.586 name, true); 14.587 } 14.588 } 14.589 @@ -2199,7 +2330,7 @@ 14.590 Symbol sym = env1.info.scope.lookup(name).sym; 14.591 if (sym != null) { 14.592 if (staticOnly) sym = new StaticError(sym); 14.593 - return access(sym, pos, env.enclClass.sym.type, 14.594 + return accessBase(sym, pos, env.enclClass.sym.type, 14.595 name, true); 14.596 } 14.597 } 14.598 @@ -2322,17 +2453,6 @@ 14.599 Name name, 14.600 List<Type> argtypes, 14.601 List<Type> typeargtypes); 14.602 - 14.603 - /** 14.604 - * A name designates an operator if it consists 14.605 - * of a non-empty sequence of operator symbols {@literal +-~!/*%&|^<>= } 14.606 - */ 14.607 - boolean isOperator(Name name) { 14.608 - int i = 0; 14.609 - while (i < name.getByteLength() && 14.610 - "+-~!*/%&|^<>=".indexOf(name.getByteAt(i)) >= 0) i++; 14.611 - return i > 0 && i == name.getByteLength(); 14.612 - } 14.613 } 14.614 14.615 /** 14.616 @@ -2393,7 +2513,7 @@ 14.617 if (name == names.error) 14.618 return null; 14.619 14.620 - if (isOperator(name)) { 14.621 + if (syms.operatorNames.contains(name)) { 14.622 boolean isUnaryOp = argtypes.size() == 1; 14.623 String key = argtypes.size() == 1 ? 14.624 "operator.cant.be.applied" : 14.625 @@ -2415,8 +2535,7 @@ 14.626 hasLocation = !location.name.equals(names._this) && 14.627 !location.name.equals(names._super); 14.628 } 14.629 - boolean isConstructor = kind == ABSENT_MTH && 14.630 - name == names.table.names.init; 14.631 + boolean isConstructor = kind == ABSENT_MTH && name == names.init; 14.632 KindName kindname = isConstructor ? KindName.CONSTRUCTOR : absentKind(kind); 14.633 Name idname = isConstructor ? site.tsym.name : name; 14.634 String errKey = getErrorKey(kindname, typeargtypes.nonEmpty(), hasLocation); 14.635 @@ -2496,7 +2615,7 @@ 14.636 if (name == names.error) 14.637 return null; 14.638 14.639 - if (isOperator(name)) { 14.640 + if (syms.operatorNames.contains(name)) { 14.641 boolean isUnaryOp = argtypes.size() == 1; 14.642 String key = argtypes.size() == 1 ? 14.643 "operator.cant.be.applied" : 14.644 @@ -2774,9 +2893,10 @@ 14.645 private Map<MethodResolutionPhase, Symbol> resolutionCache = 14.646 new EnumMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.class); 14.647 14.648 - private MethodResolutionPhase step = null; 14.649 + MethodResolutionPhase step = null; 14.650 14.651 private boolean internalResolution = false; 14.652 + private DeferredAttr.AttrMode attrMode = DeferredAttr.AttrMode.SPECULATIVE; 14.653 14.654 private MethodResolutionPhase firstErroneousResolutionPhase() { 14.655 MethodResolutionPhase bestSoFar = BASIC; 14.656 @@ -2842,6 +2962,14 @@ 14.657 return mtype != null; 14.658 } 14.659 } 14.660 + 14.661 + DeferredAttr.AttrMode attrMode() { 14.662 + return attrMode; 14.663 + } 14.664 + 14.665 + boolean internal() { 14.666 + return internalResolution; 14.667 + } 14.668 } 14.669 14.670 MethodResolutionContext currentResolutionContext = null;
15.1 --- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Sat Sep 29 09:00:58 2012 -0700 15.2 +++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Oct 04 13:04:53 2012 +0100 15.3 @@ -1041,7 +1041,7 @@ 15.4 genEndPos = true; 15.5 if (!taskListener.isEmpty()) 15.6 taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING)); 15.7 - log.deferDiagnostics = true; 15.8 + log.deferAll(); 15.9 } else { // free resources 15.10 procEnvImpl.close(); 15.11 } 15.12 @@ -1151,7 +1151,7 @@ 15.13 if (c != this) 15.14 annotationProcessingOccurred = c.annotationProcessingOccurred = true; 15.15 // doProcessing will have handled deferred diagnostics 15.16 - Assert.check(c.log.deferDiagnostics == false 15.17 + Assert.check(c.log.deferredDiagFilter == null 15.18 && c.log.deferredDiagnostics.size() == 0); 15.19 return c; 15.20 } finally {
16.1 --- a/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Sat Sep 29 09:00:58 2012 -0700 16.2 +++ b/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Thu Oct 04 13:04:53 2012 +0100 16.3 @@ -806,7 +806,7 @@ 16.4 log = Log.instance(context); 16.5 log.nerrors = priorErrors; 16.6 log.nwarnings += priorWarnings; 16.7 - log.deferDiagnostics = true; 16.8 + log.deferAll(); 16.9 16.10 // the following is for the benefit of JavacProcessingEnvironment.getContext() 16.11 JavacProcessingEnvironment.this.context = context;
17.1 --- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties Sat Sep 29 09:00:58 2012 -0700 17.2 +++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Oct 04 13:04:53 2012 +0100 17.3 @@ -635,6 +635,10 @@ 17.4 second operand: {0}\n\ 17.5 third operand : {1} 17.6 17.7 +# 0: message segment 17.8 +compiler.misc.incompatible.type.in.conditional=\ 17.9 + bad type in conditional expression; {0} 17.10 + 17.11 compiler.err.new.not.allowed.in.annotation=\ 17.12 ''new'' not allowed in an annotation 17.13 17.14 @@ -1701,6 +1705,10 @@ 17.15 inferred: {0}\n\ 17.16 equality constraints(s): {1} 17.17 17.18 +# 0: list of type 17.19 +compiler.misc.cyclic.inference=\ 17.20 + Cannot instantiate inference variables {0} because of an inference loop 17.21 + 17.22 # 0: symbol 17.23 compiler.misc.diamond=\ 17.24 {0}<> 17.25 @@ -2086,6 +2094,9 @@ 17.26 compiler.misc.type.null=\ 17.27 <null> 17.28 17.29 +compiler.misc.type.conditional=\ 17.30 + conditional expression 17.31 + 17.32 # X#n (where n is an int id) is disambiguated tvar name 17.33 # 0: name, 1: number 17.34 compiler.misc.type.var=\
18.1 --- a/src/share/classes/com/sun/tools/javac/tree/Pretty.java Sat Sep 29 09:00:58 2012 -0700 18.2 +++ b/src/share/classes/com/sun/tools/javac/tree/Pretty.java Thu Oct 04 13:04:53 2012 +0100 18.3 @@ -81,6 +81,12 @@ 18.4 */ 18.5 DocCommentTable docComments = null; 18.6 18.7 + /** 18.8 + * A string sequence to be used when Pretty output should be constrained 18.9 + * to fit into a given size 18.10 + */ 18.11 + private final static String trimSequence = "[...]"; 18.12 + 18.13 /** Align code to be indented to left margin. 18.14 */ 18.15 void align() throws IOException { 18.16 @@ -129,6 +135,27 @@ 18.17 out.write(lineSep); 18.18 } 18.19 18.20 + public static String toSimpleString(JCTree tree, int maxLength) { 18.21 + StringWriter s = new StringWriter(); 18.22 + try { 18.23 + new Pretty(s, false).printExpr(tree); 18.24 + } 18.25 + catch (IOException e) { 18.26 + // should never happen, because StringWriter is defined 18.27 + // never to throw any IOExceptions 18.28 + throw new AssertionError(e); 18.29 + } 18.30 + //we need to (i) replace all line terminators with a space and (ii) remove 18.31 + //occurrences of 'missing' in the Pretty output (generated when types are missing) 18.32 + String res = s.toString().replaceAll("\\s+", " ").replaceAll("/\\*missing\\*/", ""); 18.33 + if (res.length() < maxLength) { 18.34 + return res; 18.35 + } else { 18.36 + int split = (maxLength - trimSequence.length()) * 2 / 3; 18.37 + return res.substring(0, split) + trimSequence + res.substring(split); 18.38 + } 18.39 + } 18.40 + 18.41 String lineSep = System.getProperty("line.separator"); 18.42 18.43 /**************************************************************************
19.1 --- a/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Sat Sep 29 09:00:58 2012 -0700 19.2 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Thu Oct 04 13:04:53 2012 +0100 19.3 @@ -245,6 +245,23 @@ 19.4 } 19.5 } 19.6 19.7 + /** Return true if a a tree corresponds to a poly expression. */ 19.8 + public static boolean isPoly(JCTree tree, JCTree origin) { 19.9 + switch (tree.getTag()) { 19.10 + case APPLY: 19.11 + case NEWCLASS: 19.12 + case CONDEXPR: 19.13 + return !origin.hasTag(TYPECAST); 19.14 + case LAMBDA: 19.15 + case REFERENCE: 19.16 + return true; 19.17 + case PARENS: 19.18 + return isPoly(((JCParens)tree).expr, origin); 19.19 + default: 19.20 + return false; 19.21 + } 19.22 + } 19.23 + 19.24 /** 19.25 * Return true if the AST corresponds to a static select of the kind A.B 19.26 */
20.1 --- a/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Sat Sep 29 09:00:58 2012 -0700 20.2 +++ b/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Thu Oct 04 13:04:53 2012 +0100 20.3 @@ -489,7 +489,8 @@ 20.4 * type referred by a given captured type C contains C itself) which might 20.5 * lead to infinite loops. 20.6 */ 20.7 - protected Printer printer = new Printer() { 20.8 + protected Printer printer = new Printer(isRaw()) { 20.9 + 20.10 @Override 20.11 protected String localize(Locale locale, String key, Object... args) { 20.12 return AbstractDiagnosticFormatter.this.localize(locale, key, args);
21.1 --- a/src/share/classes/com/sun/tools/javac/util/List.java Sat Sep 29 09:00:58 2012 -0700 21.2 +++ b/src/share/classes/com/sun/tools/javac/util/List.java Thu Oct 04 13:04:53 2012 +0100 21.3 @@ -83,6 +83,19 @@ 21.4 } 21.5 }; 21.6 21.7 + /** Returns the list obtained from 'l' after removing all elements 'elem' 21.8 + */ 21.9 + public static <A> List<A> filter(List<A> l, A elem) { 21.10 + Assert.checkNonNull(elem); 21.11 + List<A> res = List.nil(); 21.12 + for (A a : l) { 21.13 + if (a != null && !a.equals(elem)) { 21.14 + res = res.prepend(a); 21.15 + } 21.16 + } 21.17 + return res.reverse(); 21.18 + } 21.19 + 21.20 /** Construct a list consisting of given element. 21.21 */ 21.22 public static <A> List<A> of(A x1) { 21.23 @@ -120,6 +133,14 @@ 21.24 return xs; 21.25 } 21.26 21.27 + public static <A> List<A> from(Iterable<? extends A> coll) { 21.28 + List<A> xs = nil(); 21.29 + for (A a : coll) { 21.30 + xs = new List<A>(a, xs); 21.31 + } 21.32 + return xs; 21.33 + } 21.34 + 21.35 /** Construct a list consisting of a given number of identical elements. 21.36 * @param len The number of elements in the list. 21.37 * @param init The value of each element.
22.1 --- a/src/share/classes/com/sun/tools/javac/util/Log.java Sat Sep 29 09:00:58 2012 -0700 22.2 +++ b/src/share/classes/com/sun/tools/javac/util/Log.java Thu Oct 04 13:04:53 2012 +0100 22.3 @@ -130,7 +130,7 @@ 22.4 /** 22.5 * Deferred diagnostics 22.6 */ 22.7 - public boolean deferDiagnostics; 22.8 + public Filter<JCDiagnostic> deferredDiagFilter; 22.9 public Queue<JCDiagnostic> deferredDiagnostics = new ListBuffer<JCDiagnostic>(); 22.10 22.11 /** Construct a log with given I/O redirections. 22.12 @@ -450,7 +450,7 @@ 22.13 22.14 /** Report selected deferred diagnostics, and clear the deferDiagnostics flag. */ 22.15 public void reportDeferredDiagnostics(Set<JCDiagnostic.Kind> kinds) { 22.16 - deferDiagnostics = false; 22.17 + deferredDiagFilter = null; 22.18 JCDiagnostic d; 22.19 while ((d = deferredDiagnostics.poll()) != null) { 22.20 if (kinds.contains(d.getKind())) 22.21 @@ -464,7 +464,7 @@ 22.22 * reported so far, the diagnostic may be handed off to writeDiagnostic. 22.23 */ 22.24 public void report(JCDiagnostic diagnostic) { 22.25 - if (deferDiagnostics) { 22.26 + if (deferredDiagFilter != null && deferredDiagFilter.accepts(diagnostic)) { 22.27 deferredDiagnostics.add(diagnostic); 22.28 return; 22.29 } 22.30 @@ -551,6 +551,18 @@ 22.31 } 22.32 } 22.33 22.34 + public void deferAll() { 22.35 + deferredDiagFilter = new Filter<JCDiagnostic>() { 22.36 + public boolean accepts(JCDiagnostic t) { 22.37 + return true; 22.38 + } 22.39 + }; 22.40 + } 22.41 + 22.42 + public void deferNone() { 22.43 + deferredDiagFilter = null; 22.44 + } 22.45 + 22.46 /** Find a localized string in the resource bundle. 22.47 * Because this method is static, it ignores the locale. 22.48 * Use localize(key, args) when possible.
23.1 --- a/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java Sat Sep 29 09:00:58 2012 -0700 23.2 +++ b/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java Thu Oct 04 13:04:53 2012 +0100 23.3 @@ -325,6 +325,10 @@ 23.4 */ 23.5 protected class RichPrinter extends Printer { 23.6 23.7 + public RichPrinter() { 23.8 + super(formatter.isRaw()); 23.9 + } 23.10 + 23.11 @Override 23.12 public String localize(Locale locale, String key, Object... args) { 23.13 return formatter.localize(locale, key, args); 23.14 @@ -393,11 +397,6 @@ 23.15 } 23.16 23.17 @Override 23.18 - protected String printMethodArgs(List<Type> args, boolean varArgs, Locale locale) { 23.19 - return super.printMethodArgs(args, varArgs, locale); 23.20 - } 23.21 - 23.22 - @Override 23.23 public String visitClassSymbol(ClassSymbol s, Locale locale) { 23.24 String name = nameSimplifier.simplify(s); 23.25 if (name.length() == 0 ||
24.1 --- a/test/tools/javac/conditional/Conditional.java Sat Sep 29 09:00:58 2012 -0700 24.2 +++ b/test/tools/javac/conditional/Conditional.java Thu Oct 04 13:04:53 2012 +0100 24.3 @@ -27,6 +27,7 @@ 24.4 * @summary Conditional operator applies assignment conversion 24.5 * @author Tim Hanson, BEA 24.6 * 24.7 + * @compile -XDallowPoly Conditional.java 24.8 * @compile/fail Conditional.java 24.9 */ 24.10
25.1 --- a/test/tools/javac/diags/examples.not-yet.txt Sat Sep 29 09:00:58 2012 -0700 25.2 +++ b/test/tools/javac/diags/examples.not-yet.txt Thu Oct 04 13:04:53 2012 +0100 25.3 @@ -58,6 +58,7 @@ 25.4 compiler.misc.fatal.err.cant.close # JavaCompiler 25.5 compiler.misc.file.does.not.contain.package 25.6 compiler.misc.illegal.start.of.class.file 25.7 +compiler.misc.cyclic.inference # Cannot happen w/o lambdas 25.8 compiler.misc.kindname.annotation 25.9 compiler.misc.kindname.enum 25.10 compiler.misc.kindname.package
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/test/tools/javac/diags/examples/IncompatibleTypesInConditional.java Thu Oct 04 13:04:53 2012 +0100 26.3 @@ -0,0 +1,35 @@ 26.4 +/* 26.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 26.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 26.7 + * 26.8 + * This code is free software; you can redistribute it and/or modify it 26.9 + * under the terms of the GNU General Public License version 2 only, as 26.10 + * published by the Free Software Foundation. 26.11 + * 26.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 26.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 26.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 26.15 + * version 2 for more details (a copy is included in the LICENSE file that 26.16 + * accompanied this code). 26.17 + * 26.18 + * You should have received a copy of the GNU General Public License version 26.19 + * 2 along with this work; if not, write to the Free Software Foundation, 26.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 26.21 + * 26.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 26.23 + * or visit www.oracle.com if you need additional information or have any 26.24 + * questions. 26.25 + */ 26.26 + 26.27 +// key: compiler.err.prob.found.req 26.28 +// key: compiler.misc.incompatible.type.in.conditional 26.29 +// key: compiler.misc.inconvertible.types 26.30 +// options: -XDallowPoly 26.31 + 26.32 +class IncompatibleTypesInConditional { 26.33 + 26.34 + interface A { } 26.35 + interface B { } 26.36 + 26.37 + B b = true ? (A)null : (B)null; 26.38 +}
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/test/tools/javac/diags/examples/TypeConditional.java Thu Oct 04 13:04:53 2012 +0100 27.3 @@ -0,0 +1,38 @@ 27.4 +/* 27.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 27.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 27.7 + * 27.8 + * This code is free software; you can redistribute it and/or modify it 27.9 + * under the terms of the GNU General Public License version 2 only, as 27.10 + * published by the Free Software Foundation. 27.11 + * 27.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 27.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 27.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 27.15 + * version 2 for more details (a copy is included in the LICENSE file that 27.16 + * accompanied this code). 27.17 + * 27.18 + * You should have received a copy of the GNU General Public License version 27.19 + * 2 along with this work; if not, write to the Free Software Foundation, 27.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 27.21 + * 27.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 27.23 + * or visit www.oracle.com if you need additional information or have any 27.24 + * questions. 27.25 + */ 27.26 + 27.27 +// key: compiler.err.cant.apply.symbol.1 27.28 +// key: compiler.misc.type.conditional 27.29 +// key: compiler.misc.no.args 27.30 +// key: compiler.misc.arg.length.mismatch 27.31 +// options: -XDallowPoly 27.32 +// run: simple 27.33 + 27.34 +class TypeConditional { 27.35 + 27.36 + void m() { } 27.37 + 27.38 + void test() { 27.39 + m(true ? 1 : 2); 27.40 + } 27.41 +}