1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Sat Sep 29 09:00:58 2012 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Oct 04 13:04:53 2012 +0100 1.3 @@ -25,12 +25,10 @@ 1.4 1.5 package com.sun.tools.javac.comp; 1.6 1.7 -import java.util.*; 1.8 -import java.util.Set; 1.9 -import javax.lang.model.element.ElementKind; 1.10 -import javax.tools.JavaFileObject; 1.11 - 1.12 import com.sun.tools.javac.code.*; 1.13 +import com.sun.tools.javac.comp.DeferredAttr.AttrMode; 1.14 +import com.sun.tools.javac.comp.Infer.InferenceContext; 1.15 +import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener; 1.16 import com.sun.tools.javac.jvm.*; 1.17 import com.sun.tools.javac.tree.*; 1.18 import com.sun.tools.javac.util.*; 1.19 @@ -49,6 +47,11 @@ 1.20 import com.sun.source.tree.TreeVisitor; 1.21 import com.sun.source.util.SimpleTreeVisitor; 1.22 1.23 +import java.util.*; 1.24 +import java.util.Set; 1.25 +import javax.lang.model.element.ElementKind; 1.26 +import javax.tools.JavaFileObject; 1.27 + 1.28 import static com.sun.tools.javac.code.Flags.*; 1.29 import static com.sun.tools.javac.code.Flags.ANNOTATION; 1.30 import static com.sun.tools.javac.code.Flags.BLOCK; 1.31 @@ -80,6 +83,7 @@ 1.32 final Symtab syms; 1.33 final Resolve rs; 1.34 final Infer infer; 1.35 + final DeferredAttr deferredAttr; 1.36 final Check chk; 1.37 final MemberEnter memberEnter; 1.38 final TreeMaker make; 1.39 @@ -110,6 +114,7 @@ 1.40 make = TreeMaker.instance(context); 1.41 enter = Enter.instance(context); 1.42 infer = Infer.instance(context); 1.43 + deferredAttr = DeferredAttr.instance(context); 1.44 cfolder = ConstFold.instance(context); 1.45 target = Target.instance(context); 1.46 types = Types.instance(context); 1.47 @@ -127,6 +132,7 @@ 1.48 allowCovariantReturns = source.allowCovariantReturns(); 1.49 allowAnonOuterThis = source.allowAnonOuterThis(); 1.50 allowStringsInSwitch = source.allowStringsInSwitch(); 1.51 + allowPoly = source.allowPoly() && options.isSet("allowPoly"); 1.52 sourceName = source.name; 1.53 relax = (options.isSet("-retrofit") || 1.54 options.isSet("-relax")); 1.55 @@ -144,6 +150,10 @@ 1.56 */ 1.57 boolean relax; 1.58 1.59 + /** Switch: support target-typing inference 1.60 + */ 1.61 + boolean allowPoly; 1.62 + 1.63 /** Switch: support generics? 1.64 */ 1.65 boolean allowGenerics; 1.66 @@ -207,15 +217,29 @@ 1.67 * @param ownkind The computed kind of the tree 1.68 * @param resultInfo The expected result of the tree 1.69 */ 1.70 - Type check(JCTree tree, Type owntype, int ownkind, ResultInfo resultInfo) { 1.71 + Type check(final JCTree tree, final Type found, final int ownkind, final ResultInfo resultInfo) { 1.72 + InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext(); 1.73 + Type owntype = found; 1.74 if (owntype.tag != ERROR && resultInfo.pt.tag != METHOD && resultInfo.pt.tag != FORALL) { 1.75 - if ((ownkind & ~resultInfo.pkind) == 0) { 1.76 - owntype = resultInfo.check(tree, owntype); 1.77 + if (inferenceContext.free(found)) { 1.78 + inferenceContext.addFreeTypeListener(List.of(found, resultInfo.pt), new FreeTypeListener() { 1.79 + @Override 1.80 + public void typesInferred(InferenceContext inferenceContext) { 1.81 + ResultInfo pendingResult = 1.82 + resultInfo.dup(inferenceContext.asInstType(resultInfo.pt, types)); 1.83 + check(tree, inferenceContext.asInstType(found, types), ownkind, pendingResult); 1.84 + } 1.85 + }); 1.86 + return tree.type = resultInfo.pt; 1.87 } else { 1.88 - log.error(tree.pos(), "unexpected.type", 1.89 - kindNames(resultInfo.pkind), 1.90 - kindName(ownkind)); 1.91 - owntype = types.createErrorType(owntype); 1.92 + if ((ownkind & ~resultInfo.pkind) == 0) { 1.93 + owntype = resultInfo.check(tree, owntype); 1.94 + } else { 1.95 + log.error(tree.pos(), "unexpected.type", 1.96 + kindNames(resultInfo.pkind), 1.97 + kindName(ownkind)); 1.98 + owntype = types.createErrorType(owntype); 1.99 + } 1.100 } 1.101 } 1.102 tree.type = owntype; 1.103 @@ -297,8 +321,6 @@ 1.104 } else { 1.105 log.error(pos, "cant.assign.val.to.final.var", v); 1.106 } 1.107 - } else if ((v.flags() & EFFECTIVELY_FINAL) != 0) { 1.108 - v.flags_field &= ~EFFECTIVELY_FINAL; 1.109 } 1.110 } 1.111 1.112 @@ -431,14 +453,38 @@ 1.113 static final long serialVersionUID = -6924771130405446405L; 1.114 private Env<AttrContext> env; 1.115 private BreakAttr(Env<AttrContext> env) { 1.116 - this.env = env; 1.117 + this.env = copyEnv(env); 1.118 + } 1.119 + 1.120 + private Env<AttrContext> copyEnv(Env<AttrContext> env) { 1.121 + Env<AttrContext> newEnv = 1.122 + env.dup(env.tree, env.info.dup(copyScope(env.info.scope))); 1.123 + if (newEnv.outer != null) { 1.124 + newEnv.outer = copyEnv(newEnv.outer); 1.125 + } 1.126 + return newEnv; 1.127 + } 1.128 + 1.129 + private Scope copyScope(Scope sc) { 1.130 + Scope newScope = new Scope(sc.owner); 1.131 + List<Symbol> elemsList = List.nil(); 1.132 + while (sc != null) { 1.133 + for (Scope.Entry e = sc.elems ; e != null ; e = e.sibling) { 1.134 + elemsList = elemsList.prepend(e.sym); 1.135 + } 1.136 + sc = sc.next; 1.137 + } 1.138 + for (Symbol s : elemsList) { 1.139 + newScope.enter(s); 1.140 + } 1.141 + return newScope; 1.142 } 1.143 } 1.144 1.145 class ResultInfo { 1.146 - int pkind; 1.147 - Type pt; 1.148 - CheckContext checkContext; 1.149 + final int pkind; 1.150 + final Type pt; 1.151 + final CheckContext checkContext; 1.152 1.153 ResultInfo(int pkind, Type pt) { 1.154 this(pkind, pt, chk.basicHandler); 1.155 @@ -450,15 +496,19 @@ 1.156 this.checkContext = checkContext; 1.157 } 1.158 1.159 - protected Type check(DiagnosticPosition pos, Type found) { 1.160 + protected Type check(final DiagnosticPosition pos, final Type found) { 1.161 return chk.checkType(pos, found, pt, checkContext); 1.162 } 1.163 + 1.164 + protected ResultInfo dup(Type newPt) { 1.165 + return new ResultInfo(pkind, newPt, checkContext); 1.166 + } 1.167 } 1.168 1.169 - private final ResultInfo statInfo; 1.170 - private final ResultInfo varInfo; 1.171 - private final ResultInfo unknownExprInfo; 1.172 - private final ResultInfo unknownTypeInfo; 1.173 + final ResultInfo statInfo; 1.174 + final ResultInfo varInfo; 1.175 + final ResultInfo unknownExprInfo; 1.176 + final ResultInfo unknownTypeInfo; 1.177 1.178 Type pt() { 1.179 return resultInfo.pt; 1.180 @@ -491,7 +541,7 @@ 1.181 * @param env The environment visitor argument. 1.182 * @param resultInfo The result info visitor argument. 1.183 */ 1.184 - private Type attribTree(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) { 1.185 + Type attribTree(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) { 1.186 Env<AttrContext> prevEnv = this.env; 1.187 ResultInfo prevResult = this.resultInfo; 1.188 try { 1.189 @@ -563,9 +613,12 @@ 1.190 */ 1.191 List<Type> attribArgs(List<JCExpression> trees, Env<AttrContext> env) { 1.192 ListBuffer<Type> argtypes = new ListBuffer<Type>(); 1.193 - for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail) 1.194 - argtypes.append(chk.checkNonVoid( 1.195 - l.head.pos(), types.upperBound(attribExpr(l.head, env, Infer.anyPoly)))); 1.196 + for (JCExpression arg : trees) { 1.197 + Type argtype = allowPoly && TreeInfo.isPoly(arg, env.tree) ? 1.198 + deferredAttr.new DeferredType(arg, env) : 1.199 + chk.checkNonVoid(arg, attribExpr(arg, env, Infer.anyPoly)); 1.200 + argtypes.append(argtype); 1.201 + } 1.202 return argtypes.toList(); 1.203 } 1.204 1.205 @@ -979,8 +1032,11 @@ 1.206 // Create a new local environment with a local scope. 1.207 Env<AttrContext> localEnv = 1.208 env.dup(tree, env.info.dup(env.info.scope.dup())); 1.209 - attribStats(tree.stats, localEnv); 1.210 - localEnv.info.scope.leave(); 1.211 + try { 1.212 + attribStats(tree.stats, localEnv); 1.213 + } finally { 1.214 + localEnv.info.scope.leave(); 1.215 + } 1.216 } 1.217 result = null; 1.218 } 1.219 @@ -1000,43 +1056,51 @@ 1.220 public void visitForLoop(JCForLoop tree) { 1.221 Env<AttrContext> loopEnv = 1.222 env.dup(env.tree, env.info.dup(env.info.scope.dup())); 1.223 - attribStats(tree.init, loopEnv); 1.224 - if (tree.cond != null) attribExpr(tree.cond, loopEnv, syms.booleanType); 1.225 - loopEnv.tree = tree; // before, we were not in loop! 1.226 - attribStats(tree.step, loopEnv); 1.227 - attribStat(tree.body, loopEnv); 1.228 - loopEnv.info.scope.leave(); 1.229 - result = null; 1.230 + try { 1.231 + attribStats(tree.init, loopEnv); 1.232 + if (tree.cond != null) attribExpr(tree.cond, loopEnv, syms.booleanType); 1.233 + loopEnv.tree = tree; // before, we were not in loop! 1.234 + attribStats(tree.step, loopEnv); 1.235 + attribStat(tree.body, loopEnv); 1.236 + result = null; 1.237 + } 1.238 + finally { 1.239 + loopEnv.info.scope.leave(); 1.240 + } 1.241 } 1.242 1.243 public void visitForeachLoop(JCEnhancedForLoop tree) { 1.244 Env<AttrContext> loopEnv = 1.245 env.dup(env.tree, env.info.dup(env.info.scope.dup())); 1.246 - attribStat(tree.var, loopEnv); 1.247 - Type exprType = types.upperBound(attribExpr(tree.expr, loopEnv)); 1.248 - chk.checkNonVoid(tree.pos(), exprType); 1.249 - Type elemtype = types.elemtype(exprType); // perhaps expr is an array? 1.250 - if (elemtype == null) { 1.251 - // or perhaps expr implements Iterable<T>? 1.252 - Type base = types.asSuper(exprType, syms.iterableType.tsym); 1.253 - if (base == null) { 1.254 - log.error(tree.expr.pos(), 1.255 - "foreach.not.applicable.to.type", 1.256 - exprType, 1.257 - diags.fragment("type.req.array.or.iterable")); 1.258 - elemtype = types.createErrorType(exprType); 1.259 - } else { 1.260 - List<Type> iterableParams = base.allparams(); 1.261 - elemtype = iterableParams.isEmpty() 1.262 - ? syms.objectType 1.263 - : types.upperBound(iterableParams.head); 1.264 + try { 1.265 + attribStat(tree.var, loopEnv); 1.266 + Type exprType = types.upperBound(attribExpr(tree.expr, loopEnv)); 1.267 + chk.checkNonVoid(tree.pos(), exprType); 1.268 + Type elemtype = types.elemtype(exprType); // perhaps expr is an array? 1.269 + if (elemtype == null) { 1.270 + // or perhaps expr implements Iterable<T>? 1.271 + Type base = types.asSuper(exprType, syms.iterableType.tsym); 1.272 + if (base == null) { 1.273 + log.error(tree.expr.pos(), 1.274 + "foreach.not.applicable.to.type", 1.275 + exprType, 1.276 + diags.fragment("type.req.array.or.iterable")); 1.277 + elemtype = types.createErrorType(exprType); 1.278 + } else { 1.279 + List<Type> iterableParams = base.allparams(); 1.280 + elemtype = iterableParams.isEmpty() 1.281 + ? syms.objectType 1.282 + : types.upperBound(iterableParams.head); 1.283 + } 1.284 } 1.285 + chk.checkType(tree.expr.pos(), elemtype, tree.var.sym.type); 1.286 + loopEnv.tree = tree; // before, we were not in loop! 1.287 + attribStat(tree.body, loopEnv); 1.288 + result = null; 1.289 } 1.290 - chk.checkType(tree.expr.pos(), elemtype, tree.var.sym.type); 1.291 - loopEnv.tree = tree; // before, we were not in loop! 1.292 - attribStat(tree.body, loopEnv); 1.293 - loopEnv.info.scope.leave(); 1.294 - result = null; 1.295 + finally { 1.296 + loopEnv.info.scope.leave(); 1.297 + } 1.298 } 1.299 1.300 public void visitLabelled(JCLabeledStatement tree) { 1.301 @@ -1062,61 +1126,69 @@ 1.302 Env<AttrContext> switchEnv = 1.303 env.dup(tree, env.info.dup(env.info.scope.dup())); 1.304 1.305 - boolean enumSwitch = 1.306 - allowEnums && 1.307 - (seltype.tsym.flags() & Flags.ENUM) != 0; 1.308 - boolean stringSwitch = false; 1.309 - if (types.isSameType(seltype, syms.stringType)) { 1.310 - if (allowStringsInSwitch) { 1.311 - stringSwitch = true; 1.312 - } else { 1.313 - log.error(tree.selector.pos(), "string.switch.not.supported.in.source", sourceName); 1.314 + try { 1.315 + 1.316 + boolean enumSwitch = 1.317 + allowEnums && 1.318 + (seltype.tsym.flags() & Flags.ENUM) != 0; 1.319 + boolean stringSwitch = false; 1.320 + if (types.isSameType(seltype, syms.stringType)) { 1.321 + if (allowStringsInSwitch) { 1.322 + stringSwitch = true; 1.323 + } else { 1.324 + log.error(tree.selector.pos(), "string.switch.not.supported.in.source", sourceName); 1.325 + } 1.326 } 1.327 + if (!enumSwitch && !stringSwitch) 1.328 + seltype = chk.checkType(tree.selector.pos(), seltype, syms.intType); 1.329 + 1.330 + // Attribute all cases and 1.331 + // check that there are no duplicate case labels or default clauses. 1.332 + Set<Object> labels = new HashSet<Object>(); // The set of case labels. 1.333 + boolean hasDefault = false; // Is there a default label? 1.334 + for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) { 1.335 + JCCase c = l.head; 1.336 + Env<AttrContext> caseEnv = 1.337 + switchEnv.dup(c, env.info.dup(switchEnv.info.scope.dup())); 1.338 + try { 1.339 + if (c.pat != null) { 1.340 + if (enumSwitch) { 1.341 + Symbol sym = enumConstant(c.pat, seltype); 1.342 + if (sym == null) { 1.343 + log.error(c.pat.pos(), "enum.label.must.be.unqualified.enum"); 1.344 + } else if (!labels.add(sym)) { 1.345 + log.error(c.pos(), "duplicate.case.label"); 1.346 + } 1.347 + } else { 1.348 + Type pattype = attribExpr(c.pat, switchEnv, seltype); 1.349 + if (pattype.tag != ERROR) { 1.350 + if (pattype.constValue() == null) { 1.351 + log.error(c.pat.pos(), 1.352 + (stringSwitch ? "string.const.req" : "const.expr.req")); 1.353 + } else if (labels.contains(pattype.constValue())) { 1.354 + log.error(c.pos(), "duplicate.case.label"); 1.355 + } else { 1.356 + labels.add(pattype.constValue()); 1.357 + } 1.358 + } 1.359 + } 1.360 + } else if (hasDefault) { 1.361 + log.error(c.pos(), "duplicate.default.label"); 1.362 + } else { 1.363 + hasDefault = true; 1.364 + } 1.365 + attribStats(c.stats, caseEnv); 1.366 + } finally { 1.367 + caseEnv.info.scope.leave(); 1.368 + addVars(c.stats, switchEnv.info.scope); 1.369 + } 1.370 + } 1.371 + 1.372 + result = null; 1.373 } 1.374 - if (!enumSwitch && !stringSwitch) 1.375 - seltype = chk.checkType(tree.selector.pos(), seltype, syms.intType); 1.376 - 1.377 - // Attribute all cases and 1.378 - // check that there are no duplicate case labels or default clauses. 1.379 - Set<Object> labels = new HashSet<Object>(); // The set of case labels. 1.380 - boolean hasDefault = false; // Is there a default label? 1.381 - for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) { 1.382 - JCCase c = l.head; 1.383 - Env<AttrContext> caseEnv = 1.384 - switchEnv.dup(c, env.info.dup(switchEnv.info.scope.dup())); 1.385 - if (c.pat != null) { 1.386 - if (enumSwitch) { 1.387 - Symbol sym = enumConstant(c.pat, seltype); 1.388 - if (sym == null) { 1.389 - log.error(c.pat.pos(), "enum.label.must.be.unqualified.enum"); 1.390 - } else if (!labels.add(sym)) { 1.391 - log.error(c.pos(), "duplicate.case.label"); 1.392 - } 1.393 - } else { 1.394 - Type pattype = attribExpr(c.pat, switchEnv, seltype); 1.395 - if (pattype.tag != ERROR) { 1.396 - if (pattype.constValue() == null) { 1.397 - log.error(c.pat.pos(), 1.398 - (stringSwitch ? "string.const.req" : "const.expr.req")); 1.399 - } else if (labels.contains(pattype.constValue())) { 1.400 - log.error(c.pos(), "duplicate.case.label"); 1.401 - } else { 1.402 - labels.add(pattype.constValue()); 1.403 - } 1.404 - } 1.405 - } 1.406 - } else if (hasDefault) { 1.407 - log.error(c.pos(), "duplicate.default.label"); 1.408 - } else { 1.409 - hasDefault = true; 1.410 - } 1.411 - attribStats(c.stats, caseEnv); 1.412 - caseEnv.info.scope.leave(); 1.413 - addVars(c.stats, switchEnv.info.scope); 1.414 + finally { 1.415 + switchEnv.info.scope.leave(); 1.416 } 1.417 - 1.418 - switchEnv.info.scope.leave(); 1.419 - result = null; 1.420 } 1.421 // where 1.422 /** Add any variables defined in stats to the switch scope. */ 1.423 @@ -1158,63 +1230,72 @@ 1.424 public void visitTry(JCTry tree) { 1.425 // Create a new local environment with a local 1.426 Env<AttrContext> localEnv = env.dup(tree, env.info.dup(env.info.scope.dup())); 1.427 - boolean isTryWithResource = tree.resources.nonEmpty(); 1.428 - // Create a nested environment for attributing the try block if needed 1.429 - Env<AttrContext> tryEnv = isTryWithResource ? 1.430 - env.dup(tree, localEnv.info.dup(localEnv.info.scope.dup())) : 1.431 - localEnv; 1.432 - // Attribute resource declarations 1.433 - for (JCTree resource : tree.resources) { 1.434 - CheckContext twrContext = new Check.NestedCheckContext(resultInfo.checkContext) { 1.435 - @Override 1.436 - public void report(DiagnosticPosition pos, JCDiagnostic details) { 1.437 - chk.basicHandler.report(pos, diags.fragment("try.not.applicable.to.type", details)); 1.438 + try { 1.439 + boolean isTryWithResource = tree.resources.nonEmpty(); 1.440 + // Create a nested environment for attributing the try block if needed 1.441 + Env<AttrContext> tryEnv = isTryWithResource ? 1.442 + env.dup(tree, localEnv.info.dup(localEnv.info.scope.dup())) : 1.443 + localEnv; 1.444 + try { 1.445 + // Attribute resource declarations 1.446 + for (JCTree resource : tree.resources) { 1.447 + CheckContext twrContext = new Check.NestedCheckContext(resultInfo.checkContext) { 1.448 + @Override 1.449 + public void report(DiagnosticPosition pos, JCDiagnostic details) { 1.450 + chk.basicHandler.report(pos, diags.fragment("try.not.applicable.to.type", details)); 1.451 + } 1.452 + }; 1.453 + ResultInfo twrResult = new ResultInfo(VAL, syms.autoCloseableType, twrContext); 1.454 + if (resource.hasTag(VARDEF)) { 1.455 + attribStat(resource, tryEnv); 1.456 + twrResult.check(resource, resource.type); 1.457 + 1.458 + //check that resource type cannot throw InterruptedException 1.459 + checkAutoCloseable(resource.pos(), localEnv, resource.type); 1.460 + 1.461 + VarSymbol var = (VarSymbol)TreeInfo.symbolFor(resource); 1.462 + var.setData(ElementKind.RESOURCE_VARIABLE); 1.463 + } else { 1.464 + attribTree(resource, tryEnv, twrResult); 1.465 + } 1.466 } 1.467 - }; 1.468 - ResultInfo twrResult = new ResultInfo(VAL, syms.autoCloseableType, twrContext); 1.469 - if (resource.hasTag(VARDEF)) { 1.470 - attribStat(resource, tryEnv); 1.471 - twrResult.check(resource, resource.type); 1.472 - 1.473 - //check that resource type cannot throw InterruptedException 1.474 - checkAutoCloseable(resource.pos(), localEnv, resource.type); 1.475 - 1.476 - VarSymbol var = (VarSymbol)TreeInfo.symbolFor(resource); 1.477 - var.setData(ElementKind.RESOURCE_VARIABLE); 1.478 - } else { 1.479 - attribTree(resource, tryEnv, twrResult); 1.480 + // Attribute body 1.481 + attribStat(tree.body, tryEnv); 1.482 + } finally { 1.483 + if (isTryWithResource) 1.484 + tryEnv.info.scope.leave(); 1.485 } 1.486 + 1.487 + // Attribute catch clauses 1.488 + for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { 1.489 + JCCatch c = l.head; 1.490 + Env<AttrContext> catchEnv = 1.491 + localEnv.dup(c, localEnv.info.dup(localEnv.info.scope.dup())); 1.492 + try { 1.493 + Type ctype = attribStat(c.param, catchEnv); 1.494 + if (TreeInfo.isMultiCatch(c)) { 1.495 + //multi-catch parameter is implicitly marked as final 1.496 + c.param.sym.flags_field |= FINAL | UNION; 1.497 + } 1.498 + if (c.param.sym.kind == Kinds.VAR) { 1.499 + c.param.sym.setData(ElementKind.EXCEPTION_PARAMETER); 1.500 + } 1.501 + chk.checkType(c.param.vartype.pos(), 1.502 + chk.checkClassType(c.param.vartype.pos(), ctype), 1.503 + syms.throwableType); 1.504 + attribStat(c.body, catchEnv); 1.505 + } finally { 1.506 + catchEnv.info.scope.leave(); 1.507 + } 1.508 + } 1.509 + 1.510 + // Attribute finalizer 1.511 + if (tree.finalizer != null) attribStat(tree.finalizer, localEnv); 1.512 + result = null; 1.513 } 1.514 - // Attribute body 1.515 - attribStat(tree.body, tryEnv); 1.516 - if (isTryWithResource) 1.517 - tryEnv.info.scope.leave(); 1.518 - 1.519 - // Attribute catch clauses 1.520 - for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { 1.521 - JCCatch c = l.head; 1.522 - Env<AttrContext> catchEnv = 1.523 - localEnv.dup(c, localEnv.info.dup(localEnv.info.scope.dup())); 1.524 - Type ctype = attribStat(c.param, catchEnv); 1.525 - if (TreeInfo.isMultiCatch(c)) { 1.526 - //multi-catch parameter is implicitly marked as final 1.527 - c.param.sym.flags_field |= FINAL | UNION; 1.528 - } 1.529 - if (c.param.sym.kind == Kinds.VAR) { 1.530 - c.param.sym.setData(ElementKind.EXCEPTION_PARAMETER); 1.531 - } 1.532 - chk.checkType(c.param.vartype.pos(), 1.533 - chk.checkClassType(c.param.vartype.pos(), ctype), 1.534 - syms.throwableType); 1.535 - attribStat(c.body, catchEnv); 1.536 - catchEnv.info.scope.leave(); 1.537 + finally { 1.538 + localEnv.info.scope.leave(); 1.539 } 1.540 - 1.541 - // Attribute finalizer 1.542 - if (tree.finalizer != null) attribStat(tree.finalizer, localEnv); 1.543 - 1.544 - localEnv.info.scope.leave(); 1.545 - result = null; 1.546 } 1.547 1.548 void checkAutoCloseable(DiagnosticPosition pos, Env<AttrContext> env, Type resource) { 1.549 @@ -1222,10 +1303,10 @@ 1.550 types.asSuper(resource, syms.autoCloseableType.tsym) != null && 1.551 !types.isSameType(resource, syms.autoCloseableType)) { // Don't emit warning for AutoCloseable itself 1.552 Symbol close = syms.noSymbol; 1.553 - boolean prevDeferDiags = log.deferDiagnostics; 1.554 + Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter; 1.555 Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics; 1.556 try { 1.557 - log.deferDiagnostics = true; 1.558 + log.deferAll(); 1.559 log.deferredDiagnostics = ListBuffer.lb(); 1.560 close = rs.resolveQualifiedMethod(pos, 1.561 env, 1.562 @@ -1235,7 +1316,7 @@ 1.563 List.<Type>nil()); 1.564 } 1.565 finally { 1.566 - log.deferDiagnostics = prevDeferDiags; 1.567 + log.deferredDiagFilter = prevDeferDiagsFilter; 1.568 log.deferredDiagnostics = prevDeferredDiags; 1.569 } 1.570 if (close.kind == MTH && 1.571 @@ -1248,50 +1329,71 @@ 1.572 } 1.573 1.574 public void visitConditional(JCConditional tree) { 1.575 - attribExpr(tree.cond, env, syms.booleanType); 1.576 - attribExpr(tree.truepart, env); 1.577 - attribExpr(tree.falsepart, env); 1.578 - result = check(tree, 1.579 - capture(condType(tree.pos(), tree.cond.type, 1.580 - tree.truepart.type, tree.falsepart.type)), 1.581 - VAL, resultInfo); 1.582 + Type condtype = attribExpr(tree.cond, env, syms.booleanType); 1.583 + 1.584 + boolean standaloneConditional = !allowPoly || 1.585 + pt().tag == NONE && pt() != Type.recoveryType || 1.586 + isBooleanOrNumeric(env, tree); 1.587 + 1.588 + if (!standaloneConditional && resultInfo.pt.tag == VOID) { 1.589 + //cannot get here (i.e. it means we are returning from void method - which is already an error) 1.590 + result = tree.type = types.createErrorType(resultInfo.pt); 1.591 + return; 1.592 + } 1.593 + 1.594 + ResultInfo condInfo = standaloneConditional ? 1.595 + unknownExprInfo : 1.596 + new ResultInfo(VAL, pt(), new Check.NestedCheckContext(resultInfo.checkContext) { 1.597 + //this will use enclosing check context to check compatibility of 1.598 + //subexpression against target type; if we are in a method check context, 1.599 + //depending on whether boxing is allowed, we could have incompatibilities 1.600 + @Override 1.601 + public void report(DiagnosticPosition pos, JCDiagnostic details) { 1.602 + enclosingContext.report(pos, diags.fragment("incompatible.type.in.conditional", details)); 1.603 + } 1.604 + }); 1.605 + 1.606 + Type truetype = attribTree(tree.truepart, env, condInfo); 1.607 + Type falsetype = attribTree(tree.falsepart, env, condInfo); 1.608 + 1.609 + Type owntype = standaloneConditional ? condType(tree, truetype, falsetype) : pt(); 1.610 + if (condtype.constValue() != null && 1.611 + truetype.constValue() != null && 1.612 + falsetype.constValue() != null) { 1.613 + //constant folding 1.614 + owntype = cfolder.coerce(condtype.isTrue() ? truetype : falsetype, owntype); 1.615 + } 1.616 + result = check(tree, owntype, VAL, resultInfo); 1.617 } 1.618 //where 1.619 + @SuppressWarnings("fallthrough") 1.620 + private boolean isBooleanOrNumeric(Env<AttrContext> env, JCExpression tree) { 1.621 + switch (tree.getTag()) { 1.622 + case LITERAL: return ((JCLiteral)tree).typetag < CLASS; 1.623 + case LAMBDA: case REFERENCE: return false; 1.624 + case PARENS: return isBooleanOrNumeric(env, ((JCParens)tree).expr); 1.625 + case CONDEXPR: 1.626 + JCConditional condTree = (JCConditional)tree; 1.627 + return isBooleanOrNumeric(env, condTree.truepart) && 1.628 + isBooleanOrNumeric(env, condTree.falsepart); 1.629 + default: 1.630 + Type speculativeType = deferredAttr.attribSpeculative(tree, env, unknownExprInfo).type; 1.631 + speculativeType = types.unboxedTypeOrType(speculativeType); 1.632 + return speculativeType.tag <= BOOLEAN; 1.633 + } 1.634 + } 1.635 + 1.636 /** Compute the type of a conditional expression, after 1.637 - * checking that it exists. See Spec 15.25. 1.638 - * 1.639 - * @param pos The source position to be used for 1.640 - * error diagnostics. 1.641 - * @param condtype The type of the expression's condition. 1.642 - * @param thentype The type of the expression's then-part. 1.643 - * @param elsetype The type of the expression's else-part. 1.644 - */ 1.645 - private Type condType(DiagnosticPosition pos, 1.646 - Type condtype, 1.647 - Type thentype, 1.648 - Type elsetype) { 1.649 - Type ctype = condType1(pos, condtype, thentype, elsetype); 1.650 - 1.651 - // If condition and both arms are numeric constants, 1.652 - // evaluate at compile-time. 1.653 - return ((condtype.constValue() != null) && 1.654 - (thentype.constValue() != null) && 1.655 - (elsetype.constValue() != null)) 1.656 - ? cfolder.coerce(condtype.isTrue()?thentype:elsetype, ctype) 1.657 - : ctype; 1.658 - } 1.659 - /** Compute the type of a conditional expression, after 1.660 - * checking that it exists. Does not take into 1.661 + * checking that it exists. See JLS 15.25. Does not take into 1.662 * account the special case where condition and both arms 1.663 * are constants. 1.664 * 1.665 * @param pos The source position to be used for error 1.666 * diagnostics. 1.667 - * @param condtype The type of the expression's condition. 1.668 * @param thentype The type of the expression's then-part. 1.669 * @param elsetype The type of the expression's else-part. 1.670 */ 1.671 - private Type condType1(DiagnosticPosition pos, Type condtype, 1.672 + private Type condType(DiagnosticPosition pos, 1.673 Type thentype, Type elsetype) { 1.674 // If same type, that is the result 1.675 if (types.isSameType(thentype, elsetype)) 1.676 @@ -1445,22 +1547,19 @@ 1.677 public void visitReturn(JCReturn tree) { 1.678 // Check that there is an enclosing method which is 1.679 // nested within than the enclosing class. 1.680 - if (env.enclMethod == null || 1.681 - env.enclMethod.sym.owner != env.enclClass.sym) { 1.682 + if (env.info.returnResult == null) { 1.683 log.error(tree.pos(), "ret.outside.meth"); 1.684 - 1.685 } else { 1.686 // Attribute return expression, if it exists, and check that 1.687 // it conforms to result type of enclosing method. 1.688 - Symbol m = env.enclMethod.sym; 1.689 - if (m.type.getReturnType().tag == VOID) { 1.690 - if (tree.expr != null) 1.691 + if (tree.expr != null) { 1.692 + if (env.info.returnResult.pt.tag == VOID) { 1.693 log.error(tree.expr.pos(), 1.694 "cant.ret.val.from.meth.decl.void"); 1.695 - } else if (tree.expr == null) { 1.696 + } 1.697 + attribTree(tree.expr, env, env.info.returnResult); 1.698 + } else if (env.info.returnResult.pt.tag != VOID) { 1.699 log.error(tree.pos(), "missing.ret.val"); 1.700 - } else { 1.701 - attribExpr(tree.expr, env, m.type.getReturnType()); 1.702 } 1.703 } 1.704 result = null; 1.705 @@ -1562,7 +1661,7 @@ 1.706 // current instance (JLS ???). 1.707 boolean selectSuperPrev = localEnv.info.selectSuper; 1.708 localEnv.info.selectSuper = true; 1.709 - localEnv.info.varArgs = false; 1.710 + localEnv.info.pendingResolutionPhase = null; 1.711 Symbol sym = rs.resolveConstructor( 1.712 tree.meth.pos(), localEnv, site, argtypes, typeargtypes); 1.713 localEnv.info.selectSuper = selectSuperPrev; 1.714 @@ -1573,8 +1672,7 @@ 1.715 // ...and check that it is legal in the current context. 1.716 // (this will also set the tree's type) 1.717 Type mpt = newMethodTemplate(resultInfo.pt, argtypes, typeargtypes); 1.718 - checkId(tree.meth, site, sym, localEnv, new ResultInfo(MTH, mpt), 1.719 - tree.varargsElement != null); 1.720 + checkId(tree.meth, site, sym, localEnv, new ResultInfo(MTH, mpt)); 1.721 } 1.722 // Otherwise, `site' is an error type and we do nothing 1.723 } 1.724 @@ -1589,8 +1687,8 @@ 1.725 // whose formal argument types is exactly the list of actual 1.726 // arguments (this will also set the method symbol). 1.727 Type mpt = newMethodTemplate(resultInfo.pt, argtypes, typeargtypes); 1.728 - localEnv.info.varArgs = false; 1.729 - Type mtype = attribExpr(tree.meth, localEnv, mpt); 1.730 + localEnv.info.pendingResolutionPhase = null; 1.731 + Type mtype = attribTree(tree.meth, localEnv, new ResultInfo(VAL, mpt, resultInfo.checkContext)); 1.732 1.733 // Compute the result type. 1.734 Type restype = mtype.getReturnType(); 1.735 @@ -1625,7 +1723,7 @@ 1.736 // current context. Also, capture the return type 1.737 result = check(tree, capture(restype), VAL, resultInfo); 1.738 1.739 - if (localEnv.info.varArgs) 1.740 + if (localEnv.info.lastResolveVarargs()) 1.741 Assert.check(result.isErroneous() || tree.varargsElement != null); 1.742 } 1.743 chk.validate(tree.typeargs, localEnv); 1.744 @@ -1652,11 +1750,11 @@ 1.745 /** Obtain a method type with given argument types. 1.746 */ 1.747 Type newMethodTemplate(Type restype, List<Type> argtypes, List<Type> typeargtypes) { 1.748 - MethodType mt = new MethodType(argtypes, restype, null, syms.methodClass); 1.749 + MethodType mt = new MethodType(argtypes, restype, List.<Type>nil(), syms.methodClass); 1.750 return (typeargtypes == null) ? mt : (Type)new ForAll(typeargtypes, mt); 1.751 } 1.752 1.753 - public void visitNewClass(JCNewClass tree) { 1.754 + public void visitNewClass(final JCNewClass tree) { 1.755 Type owntype = types.createErrorType(tree.type); 1.756 1.757 // The local environment of a class creation is 1.758 @@ -1729,19 +1827,6 @@ 1.759 List<Type> argtypes = attribArgs(tree.args, localEnv); 1.760 List<Type> typeargtypes = attribTypes(tree.typeargs, localEnv); 1.761 1.762 - if (TreeInfo.isDiamond(tree) && !clazztype.isErroneous()) { 1.763 - Pair<Symbol, Type> diamondResult = 1.764 - attribDiamond(localEnv, tree, clazztype, argtypes, typeargtypes); 1.765 - tree.clazz.type = types.createErrorType(clazztype); 1.766 - tree.constructor = diamondResult.fst; 1.767 - tree.constructorType = diamondResult.snd; 1.768 - if (!diamondResult.snd.isErroneous()) { 1.769 - tree.clazz.type = clazztype = diamondResult.snd.getReturnType(); 1.770 - tree.constructorType = types.createMethodTypeWithReturn(diamondResult.snd, syms.voidType); 1.771 - } 1.772 - clazztype = chk.checkClassType(tree.clazz, tree.clazz.type, true); 1.773 - } 1.774 - 1.775 // If we have made no mistakes in the class type... 1.776 if (clazztype.tag == CLASS) { 1.777 // Enums may not be instantiated except implicitly 1.778 @@ -1768,18 +1853,57 @@ 1.779 // Error recovery: pretend no arguments were supplied. 1.780 argtypes = List.nil(); 1.781 typeargtypes = List.nil(); 1.782 + } else if (TreeInfo.isDiamond(tree)) { 1.783 + ClassType site = new ClassType(clazztype.getEnclosingType(), 1.784 + clazztype.tsym.type.getTypeArguments(), 1.785 + clazztype.tsym); 1.786 + 1.787 + Env<AttrContext> diamondEnv = localEnv.dup(tree); 1.788 + diamondEnv.info.selectSuper = cdef != null; 1.789 + diamondEnv.info.pendingResolutionPhase = null; 1.790 + 1.791 + //if the type of the instance creation expression is a class type 1.792 + //apply method resolution inference (JLS 15.12.2.7). The return type 1.793 + //of the resolved constructor will be a partially instantiated type 1.794 + Symbol constructor = rs.resolveDiamond(tree.pos(), 1.795 + diamondEnv, 1.796 + site, 1.797 + argtypes, 1.798 + typeargtypes); 1.799 + tree.constructor = constructor.baseSymbol(); 1.800 + 1.801 + final TypeSymbol csym = clazztype.tsym; 1.802 + ResultInfo diamondResult = new ResultInfo(MTH, newMethodTemplate(resultInfo.pt, argtypes, typeargtypes), new Check.NestedCheckContext(resultInfo.checkContext) { 1.803 + @Override 1.804 + public void report(DiagnosticPosition _unused, JCDiagnostic details) { 1.805 + enclosingContext.report(tree.clazz, 1.806 + diags.fragment("cant.apply.diamond.1", diags.fragment("diamond", csym), details)); 1.807 + } 1.808 + }); 1.809 + Type constructorType = tree.constructorType = types.createErrorType(clazztype); 1.810 + constructorType = checkId(tree, site, 1.811 + constructor, 1.812 + diamondEnv, 1.813 + diamondResult); 1.814 + 1.815 + tree.clazz.type = types.createErrorType(clazztype); 1.816 + if (!constructorType.isErroneous()) { 1.817 + tree.clazz.type = clazztype = constructorType.getReturnType(); 1.818 + tree.constructorType = types.createMethodTypeWithReturn(constructorType, syms.voidType); 1.819 + } 1.820 + clazztype = chk.checkClassType(tree.clazz, tree.clazz.type, true); 1.821 } 1.822 1.823 // Resolve the called constructor under the assumption 1.824 // that we are referring to a superclass instance of the 1.825 // current instance (JLS ???). 1.826 - else if (!TreeInfo.isDiamond(tree)) { 1.827 + else { 1.828 //the following code alters some of the fields in the current 1.829 //AttrContext - hence, the current context must be dup'ed in 1.830 //order to avoid downstream failures 1.831 Env<AttrContext> rsEnv = localEnv.dup(tree); 1.832 rsEnv.info.selectSuper = cdef != null; 1.833 - rsEnv.info.varArgs = false; 1.834 + rsEnv.info.pendingResolutionPhase = null; 1.835 tree.constructor = rs.resolveConstructor( 1.836 tree.pos(), rsEnv, clazztype, argtypes, typeargtypes); 1.837 if (cdef == null) { //do not check twice! 1.838 @@ -1787,42 +1911,11 @@ 1.839 clazztype, 1.840 tree.constructor, 1.841 rsEnv, 1.842 - new ResultInfo(MTH, newMethodTemplate(syms.voidType, argtypes, typeargtypes)), 1.843 - rsEnv.info.varArgs); 1.844 - if (rsEnv.info.varArgs) 1.845 + new ResultInfo(MTH, newMethodTemplate(syms.voidType, argtypes, typeargtypes))); 1.846 + if (rsEnv.info.lastResolveVarargs()) 1.847 Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null); 1.848 } 1.849 - if (tree.def == null && 1.850 - !clazztype.isErroneous() && 1.851 - clazztype.getTypeArguments().nonEmpty() && 1.852 - findDiamonds) { 1.853 - boolean prevDeferDiags = log.deferDiagnostics; 1.854 - Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics; 1.855 - Type inferred = null; 1.856 - try { 1.857 - //disable diamond-related diagnostics 1.858 - log.deferDiagnostics = true; 1.859 - log.deferredDiagnostics = ListBuffer.lb(); 1.860 - inferred = attribDiamond(localEnv, 1.861 - tree, 1.862 - clazztype, 1.863 - argtypes, 1.864 - typeargtypes).snd; 1.865 - } finally { 1.866 - log.deferDiagnostics = prevDeferDiags; 1.867 - log.deferredDiagnostics = prevDeferredDiags; 1.868 - } 1.869 - if (!inferred.isErroneous()) { 1.870 - inferred = inferred.getReturnType(); 1.871 - } 1.872 - if (inferred != null && 1.873 - types.isAssignable(inferred, pt().tag == NONE ? syms.objectType : pt(), Warner.noWarnings)) { 1.874 - String key = types.isSameType(clazztype, inferred) ? 1.875 - "diamond.redundant.args" : 1.876 - "diamond.redundant.args.1"; 1.877 - log.warning(tree.clazz.pos(), key, clazztype, inferred); 1.878 - } 1.879 - } 1.880 + findDiamondIfNeeded(localEnv, tree, clazztype); 1.881 } 1.882 1.883 if (cdef != null) { 1.884 @@ -1887,8 +1980,7 @@ 1.885 clazztype, 1.886 tree.constructor, 1.887 localEnv, 1.888 - new ResultInfo(VAL, newMethodTemplate(syms.voidType, argtypes, typeargtypes)), 1.889 - localEnv.info.varArgs); 1.890 + new ResultInfo(VAL, newMethodTemplate(syms.voidType, argtypes, typeargtypes))); 1.891 } 1.892 1.893 if (tree.constructor != null && tree.constructor.kind == MTH) 1.894 @@ -1897,53 +1989,33 @@ 1.895 result = check(tree, owntype, VAL, resultInfo); 1.896 chk.validate(tree.typeargs, localEnv); 1.897 } 1.898 - 1.899 - Pair<Symbol, Type> attribDiamond(Env<AttrContext> env, 1.900 - final JCNewClass tree, 1.901 - final Type clazztype, 1.902 - List<Type> argtypes, 1.903 - List<Type> typeargtypes) { 1.904 - if (clazztype.isErroneous() || 1.905 - clazztype.isInterface()) { 1.906 - //if the type of the instance creation expression is erroneous, 1.907 - //or if it's an interface, or if something prevented us to form a valid 1.908 - //mapping, return the (possibly erroneous) type unchanged 1.909 - return new Pair<Symbol, Type>(syms.noSymbol, clazztype); 1.910 + //where 1.911 + void findDiamondIfNeeded(Env<AttrContext> env, JCNewClass tree, Type clazztype) { 1.912 + if (tree.def == null && 1.913 + !clazztype.isErroneous() && 1.914 + clazztype.getTypeArguments().nonEmpty() && 1.915 + findDiamonds) { 1.916 + JCTypeApply ta = (JCTypeApply)tree.clazz; 1.917 + List<JCExpression> prevTypeargs = ta.arguments; 1.918 + try { 1.919 + //create a 'fake' diamond AST node by removing type-argument trees 1.920 + ta.arguments = List.nil(); 1.921 + ResultInfo findDiamondResult = new ResultInfo(VAL, 1.922 + resultInfo.checkContext.inferenceContext().free(resultInfo.pt) ? Type.noType : pt()); 1.923 + Type inferred = deferredAttr.attribSpeculative(tree, env, findDiamondResult).type; 1.924 + if (!inferred.isErroneous() && 1.925 + types.isAssignable(inferred, pt().tag == NONE ? syms.objectType : pt(), Warner.noWarnings)) { 1.926 + String key = types.isSameType(clazztype, inferred) ? 1.927 + "diamond.redundant.args" : 1.928 + "diamond.redundant.args.1"; 1.929 + log.warning(tree.clazz.pos(), key, clazztype, inferred); 1.930 + } 1.931 + } finally { 1.932 + ta.arguments = prevTypeargs; 1.933 + } 1.934 + } 1.935 } 1.936 1.937 - //dup attribution environment and augment the set of inference variables 1.938 - Env<AttrContext> localEnv = env.dup(tree); 1.939 - 1.940 - ClassType site = new ClassType(clazztype.getEnclosingType(), 1.941 - clazztype.tsym.type.getTypeArguments(), 1.942 - clazztype.tsym); 1.943 - 1.944 - //if the type of the instance creation expression is a class type 1.945 - //apply method resolution inference (JLS 15.12.2.7). The return type 1.946 - //of the resolved constructor will be a partially instantiated type 1.947 - Symbol constructor = rs.resolveDiamond(tree.pos(), 1.948 - localEnv, 1.949 - site, 1.950 - argtypes, 1.951 - typeargtypes); 1.952 - 1.953 - Type constructorType = types.createErrorType(clazztype); 1.954 - ResultInfo diamondResult = new ResultInfo(MTH, newMethodTemplate(resultInfo.pt, argtypes, typeargtypes), new Check.NestedCheckContext(resultInfo.checkContext) { 1.955 - @Override 1.956 - public void report(DiagnosticPosition _unused, JCDiagnostic details) { 1.957 - enclosingContext.report(tree.clazz, 1.958 - diags.fragment("cant.apply.diamond.1", diags.fragment("diamond", clazztype.tsym), details)); 1.959 - } 1.960 - }); 1.961 - constructorType = checkId(tree, site, 1.962 - constructor, 1.963 - localEnv, 1.964 - diamondResult, 1.965 - localEnv.info.varArgs); 1.966 - 1.967 - return new Pair<Symbol, Type>(constructor.baseSymbol(), constructorType); 1.968 - } 1.969 - 1.970 /** Make an attributed null check tree. 1.971 */ 1.972 public JCExpression makeNullCheck(JCExpression arg) { 1.973 @@ -1960,13 +2032,14 @@ 1.974 1.975 public void visitNewArray(JCNewArray tree) { 1.976 Type owntype = types.createErrorType(tree.type); 1.977 + Env<AttrContext> localEnv = env.dup(tree); 1.978 Type elemtype; 1.979 if (tree.elemtype != null) { 1.980 - elemtype = attribType(tree.elemtype, env); 1.981 - chk.validate(tree.elemtype, env); 1.982 + elemtype = attribType(tree.elemtype, localEnv); 1.983 + chk.validate(tree.elemtype, localEnv); 1.984 owntype = elemtype; 1.985 for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) { 1.986 - attribExpr(l.head, env, syms.intType); 1.987 + attribExpr(l.head, localEnv, syms.intType); 1.988 owntype = new ArrayType(owntype, syms.arrayClass); 1.989 } 1.990 } else { 1.991 @@ -1983,7 +2056,7 @@ 1.992 } 1.993 } 1.994 if (tree.elems != null) { 1.995 - attribExprs(tree.elems, env, elemtype); 1.996 + attribExprs(tree.elems, localEnv, elemtype); 1.997 owntype = new ArrayType(elemtype, syms.arrayClass); 1.998 } 1.999 if (!types.isReifiable(elemtype)) 1.1000 @@ -2132,18 +2205,34 @@ 1.1001 result = check(tree, owntype, VAL, resultInfo); 1.1002 } 1.1003 1.1004 - public void visitTypeCast(JCTypeCast tree) { 1.1005 + public void visitTypeCast(final JCTypeCast tree) { 1.1006 Type clazztype = attribType(tree.clazz, env); 1.1007 chk.validate(tree.clazz, env, false); 1.1008 //a fresh environment is required for 292 inference to work properly --- 1.1009 //see Infer.instantiatePolymorphicSignatureInstance() 1.1010 Env<AttrContext> localEnv = env.dup(tree); 1.1011 - Type exprtype = attribExpr(tree.expr, localEnv, Infer.anyPoly); 1.1012 - Type owntype = chk.checkCastable(tree.expr.pos(), exprtype, clazztype); 1.1013 + //should we propagate the target type? 1.1014 + final ResultInfo castInfo; 1.1015 + final boolean isPoly = TreeInfo.isPoly(tree.expr, tree); 1.1016 + if (isPoly) { 1.1017 + //expression is a poly - we need to propagate target type info 1.1018 + castInfo = new ResultInfo(VAL, clazztype, new Check.NestedCheckContext(resultInfo.checkContext) { 1.1019 + @Override 1.1020 + public boolean compatible(Type found, Type req, Warner warn) { 1.1021 + return types.isCastable(found, req, warn); 1.1022 + } 1.1023 + }); 1.1024 + } else { 1.1025 + //standalone cast - target-type info is not propagated 1.1026 + castInfo = unknownExprInfo; 1.1027 + } 1.1028 + Type exprtype = attribTree(tree.expr, localEnv, castInfo); 1.1029 + Type owntype = isPoly ? clazztype : chk.checkCastable(tree.expr.pos(), exprtype, clazztype); 1.1030 if (exprtype.constValue() != null) 1.1031 owntype = cfolder.coerce(exprtype, owntype); 1.1032 result = check(tree, capture(owntype), VAL, resultInfo); 1.1033 - chk.checkRedundantCast(localEnv, tree); 1.1034 + if (!isPoly) 1.1035 + chk.checkRedundantCast(localEnv, tree); 1.1036 } 1.1037 1.1038 public void visitTypeTest(JCInstanceOf tree) { 1.1039 @@ -2170,15 +2259,13 @@ 1.1040 1.1041 public void visitIdent(JCIdent tree) { 1.1042 Symbol sym; 1.1043 - boolean varArgs = false; 1.1044 1.1045 // Find symbol 1.1046 if (pt().tag == METHOD || pt().tag == FORALL) { 1.1047 // If we are looking for a method, the prototype `pt' will be a 1.1048 // method type with the type of the call's arguments as parameters. 1.1049 - env.info.varArgs = false; 1.1050 + env.info.pendingResolutionPhase = null; 1.1051 sym = rs.resolveMethod(tree.pos(), env, tree.name, pt().getParameterTypes(), pt().getTypeArguments()); 1.1052 - varArgs = env.info.varArgs; 1.1053 } else if (tree.sym != null && tree.sym.kind != VAR) { 1.1054 sym = tree.sym; 1.1055 } else { 1.1056 @@ -2240,7 +2327,7 @@ 1.1057 while (env1.outer != null && !rs.isAccessible(env, env1.enclClass.sym.type, sym)) 1.1058 env1 = env1.outer; 1.1059 } 1.1060 - result = checkId(tree, env1.enclClass.sym.type, sym, env, resultInfo, varArgs); 1.1061 + result = checkId(tree, env1.enclClass.sym.type, sym, env, resultInfo); 1.1062 } 1.1063 1.1064 public void visitSelect(JCFieldAccess tree) { 1.1065 @@ -2283,13 +2370,13 @@ 1.1066 sitesym.name == names._super; 1.1067 1.1068 // Determine the symbol represented by the selection. 1.1069 - env.info.varArgs = false; 1.1070 + env.info.pendingResolutionPhase = null; 1.1071 Symbol sym = selectSym(tree, sitesym, site, env, resultInfo); 1.1072 if (sym.exists() && !isType(sym) && (pkind() & (PCK | TYP)) != 0) { 1.1073 site = capture(site); 1.1074 sym = selectSym(tree, sitesym, site, env, resultInfo); 1.1075 } 1.1076 - boolean varArgs = env.info.varArgs; 1.1077 + boolean varArgs = env.info.lastResolveVarargs(); 1.1078 tree.sym = sym; 1.1079 1.1080 if (site.tag == TYPEVAR && !isType(sym) && sym.kind != ERR) { 1.1081 @@ -2340,7 +2427,7 @@ 1.1082 if ((sym.flags() & STATIC) == 0 && 1.1083 sym.name != names._super && 1.1084 (sym.kind == VAR || sym.kind == MTH)) { 1.1085 - rs.access(rs.new StaticError(sym), 1.1086 + rs.accessBase(rs.new StaticError(sym), 1.1087 tree.pos(), site, sym.name, true); 1.1088 } 1.1089 } 1.1090 @@ -2364,7 +2451,7 @@ 1.1091 } 1.1092 1.1093 env.info.selectSuper = selectSuperPrev; 1.1094 - result = checkId(tree, site, sym, env, resultInfo, varArgs); 1.1095 + result = checkId(tree, site, sym, env, resultInfo); 1.1096 } 1.1097 //where 1.1098 /** Determine symbol referenced by a Select expression, 1.1099 @@ -2383,7 +2470,7 @@ 1.1100 Name name = tree.name; 1.1101 switch (site.tag) { 1.1102 case PACKAGE: 1.1103 - return rs.access( 1.1104 + return rs.accessBase( 1.1105 rs.findIdentInPackage(env, site.tsym, name, resultInfo.pkind), 1.1106 pos, location, site, name, true); 1.1107 case ARRAY: 1.1108 @@ -2407,7 +2494,7 @@ 1.1109 // We are seeing a plain identifier as selector. 1.1110 Symbol sym = rs.findIdentInType(env, site, name, resultInfo.pkind); 1.1111 if ((resultInfo.pkind & ERRONEOUS) == 0) 1.1112 - sym = rs.access(sym, pos, location, site, name, true); 1.1113 + sym = rs.accessBase(sym, pos, location, site, name, true); 1.1114 return sym; 1.1115 } 1.1116 case WILDCARD: 1.1117 @@ -2429,7 +2516,7 @@ 1.1118 Symbol sym2 = (sym.flags() & Flags.PRIVATE) != 0 ? 1.1119 rs.new AccessError(env, site, sym) : 1.1120 sym; 1.1121 - rs.access(sym2, pos, location, site, name, true); 1.1122 + rs.accessBase(sym2, pos, location, site, name, true); 1.1123 return sym; 1.1124 } 1.1125 case ERROR: 1.1126 @@ -2480,9 +2567,18 @@ 1.1127 Type site, 1.1128 Symbol sym, 1.1129 Env<AttrContext> env, 1.1130 - ResultInfo resultInfo, 1.1131 - boolean useVarargs) { 1.1132 - if (resultInfo.pt.isErroneous()) return types.createErrorType(site); 1.1133 + ResultInfo resultInfo) { 1.1134 + Type pt = resultInfo.pt.tag == FORALL || resultInfo.pt.tag == METHOD ? 1.1135 + resultInfo.pt.map(deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, sym, env.info.pendingResolutionPhase)) : 1.1136 + resultInfo.pt; 1.1137 + 1.1138 + DeferredAttr.DeferredTypeMap recoveryMap = 1.1139 + deferredAttr.new RecoveryDeferredTypeMap(AttrMode.CHECK, sym, env.info.pendingResolutionPhase); 1.1140 + 1.1141 + if (pt.isErroneous()) { 1.1142 + Type.map(resultInfo.pt.getParameterTypes(), recoveryMap); 1.1143 + return types.createErrorType(site); 1.1144 + } 1.1145 Type owntype; // The computed type of this identifier occurrence. 1.1146 switch (sym.kind) { 1.1147 case TYP: 1.1148 @@ -2560,10 +2656,11 @@ 1.1149 owntype = checkMethod(site, sym, 1.1150 new ResultInfo(VAL, resultInfo.pt.getReturnType(), resultInfo.checkContext), 1.1151 env, TreeInfo.args(env.tree), resultInfo.pt.getParameterTypes(), 1.1152 - resultInfo.pt.getTypeArguments(), env.info.varArgs); 1.1153 + resultInfo.pt.getTypeArguments()); 1.1154 break; 1.1155 } 1.1156 case PCK: case ERR: 1.1157 + Type.map(resultInfo.pt.getParameterTypes(), recoveryMap); 1.1158 owntype = sym.type; 1.1159 break; 1.1160 default: 1.1161 @@ -2703,8 +2800,7 @@ 1.1162 Env<AttrContext> env, 1.1163 final List<JCExpression> argtrees, 1.1164 List<Type> argtypes, 1.1165 - List<Type> typeargtypes, 1.1166 - boolean useVarargs) { 1.1167 + List<Type> typeargtypes) { 1.1168 // Test (5): if symbol is an instance method of a raw type, issue 1.1169 // an unchecked warning if its argument types change under erasure. 1.1170 if (allowGenerics && 1.1171 @@ -2726,18 +2822,16 @@ 1.1172 // any type arguments and value arguments. 1.1173 noteWarner.clear(); 1.1174 try { 1.1175 - Type owntype = rs.rawInstantiate( 1.1176 + Type owntype = rs.checkMethod( 1.1177 env, 1.1178 site, 1.1179 sym, 1.1180 resultInfo, 1.1181 argtypes, 1.1182 typeargtypes, 1.1183 - allowBoxing, 1.1184 - useVarargs, 1.1185 noteWarner); 1.1186 1.1187 - return chk.checkMethod(owntype, sym, env, argtrees, argtypes, useVarargs, 1.1188 + return chk.checkMethod(owntype, sym, env, argtrees, argtypes, env.info.lastResolveVarargs(), 1.1189 noteWarner.hasNonSilentLint(LintCategory.UNCHECKED)); 1.1190 } catch (Infer.InferenceException ex) { 1.1191 //invalid target type - propagate exception outwards or report error 1.1192 @@ -2745,7 +2839,7 @@ 1.1193 resultInfo.checkContext.report(env.tree.pos(), ex.getDiagnostic()); 1.1194 return types.createErrorType(site); 1.1195 } catch (Resolve.InapplicableMethodException ex) { 1.1196 - Assert.error(); 1.1197 + Assert.error(ex.getDiagnostic().getMessage(Locale.getDefault())); 1.1198 return null; 1.1199 } 1.1200 } 1.1201 @@ -3053,8 +3147,10 @@ 1.1202 1.1203 Lint prevLint = chk.setLint(env.info.lint); 1.1204 JavaFileObject prev = log.useSource(c.sourcefile); 1.1205 + ResultInfo prevReturnRes = env.info.returnResult; 1.1206 1.1207 try { 1.1208 + env.info.returnResult = null; 1.1209 // java.lang.Enum may not be subclassed by a non-enum 1.1210 if (st.tsym == syms.enumSym && 1.1211 ((c.flags_field & (Flags.ENUM|Flags.COMPOUND)) == 0)) 1.1212 @@ -3071,6 +3167,7 @@ 1.1213 1.1214 chk.checkDeprecatedAnnotation(env.tree.pos(), c); 1.1215 } finally { 1.1216 + env.info.returnResult = prevReturnRes; 1.1217 log.useSource(prev); 1.1218 chk.setLint(prevLint); 1.1219 }