Attr.java revision 2994:dd96ac308ab8
1/* 2 * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.tools.javac.comp; 27 28import java.util.*; 29 30import javax.lang.model.element.ElementKind; 31import javax.tools.JavaFileObject; 32 33import com.sun.source.tree.IdentifierTree; 34import com.sun.source.tree.MemberReferenceTree.ReferenceMode; 35import com.sun.source.tree.MemberSelectTree; 36import com.sun.source.tree.TreeVisitor; 37import com.sun.source.util.SimpleTreeVisitor; 38import com.sun.tools.javac.code.*; 39import com.sun.tools.javac.code.Lint.LintCategory; 40import com.sun.tools.javac.code.Scope.WriteableScope; 41import com.sun.tools.javac.code.Symbol.*; 42import com.sun.tools.javac.code.Type.*; 43import com.sun.tools.javac.code.TypeMetadata.Annotations; 44import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError; 45import com.sun.tools.javac.comp.Check.CheckContext; 46import com.sun.tools.javac.comp.DeferredAttr.AttrMode; 47import com.sun.tools.javac.comp.Infer.FreeTypeListener; 48import com.sun.tools.javac.jvm.*; 49import static com.sun.tools.javac.resources.CompilerProperties.Fragments.Diamond; 50import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArg; 51import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArgs; 52import com.sun.tools.javac.resources.CompilerProperties.Errors; 53import com.sun.tools.javac.resources.CompilerProperties.Fragments; 54import com.sun.tools.javac.tree.*; 55import com.sun.tools.javac.tree.JCTree.*; 56import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; 57import com.sun.tools.javac.util.*; 58import com.sun.tools.javac.util.DefinedBy.Api; 59import com.sun.tools.javac.util.Dependencies.AttributionKind; 60import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 61import com.sun.tools.javac.util.JCDiagnostic.Fragment; 62import com.sun.tools.javac.util.List; 63import static com.sun.tools.javac.code.Flags.*; 64import static com.sun.tools.javac.code.Flags.ANNOTATION; 65import static com.sun.tools.javac.code.Flags.BLOCK; 66import static com.sun.tools.javac.code.Kinds.*; 67import static com.sun.tools.javac.code.Kinds.Kind.*; 68import static com.sun.tools.javac.code.TypeTag.*; 69import static com.sun.tools.javac.code.TypeTag.WILDCARD; 70import static com.sun.tools.javac.tree.JCTree.Tag.*; 71 72/** This is the main context-dependent analysis phase in GJC. It 73 * encompasses name resolution, type checking and constant folding as 74 * subtasks. Some subtasks involve auxiliary classes. 75 * @see Check 76 * @see Resolve 77 * @see ConstFold 78 * @see Infer 79 * 80 * <p><b>This is NOT part of any supported API. 81 * If you write code that depends on this, you do so at your own risk. 82 * This code and its internal interfaces are subject to change or 83 * deletion without notice.</b> 84 */ 85public class Attr extends JCTree.Visitor { 86 protected static final Context.Key<Attr> attrKey = new Context.Key<>(); 87 88 final Names names; 89 final Log log; 90 final Symtab syms; 91 final Resolve rs; 92 final Operators operators; 93 final Infer infer; 94 final Analyzer analyzer; 95 final DeferredAttr deferredAttr; 96 final Check chk; 97 final Flow flow; 98 final MemberEnter memberEnter; 99 final TypeEnter typeEnter; 100 final TreeMaker make; 101 final ConstFold cfolder; 102 final Enter enter; 103 final Target target; 104 final Types types; 105 final JCDiagnostic.Factory diags; 106 final TypeAnnotations typeAnnotations; 107 final DeferredLintHandler deferredLintHandler; 108 final TypeEnvs typeEnvs; 109 final Dependencies dependencies; 110 final Annotate annotate; 111 112 public static Attr instance(Context context) { 113 Attr instance = context.get(attrKey); 114 if (instance == null) 115 instance = new Attr(context); 116 return instance; 117 } 118 119 protected Attr(Context context) { 120 context.put(attrKey, this); 121 122 names = Names.instance(context); 123 log = Log.instance(context); 124 syms = Symtab.instance(context); 125 rs = Resolve.instance(context); 126 operators = Operators.instance(context); 127 chk = Check.instance(context); 128 flow = Flow.instance(context); 129 memberEnter = MemberEnter.instance(context); 130 typeEnter = TypeEnter.instance(context); 131 make = TreeMaker.instance(context); 132 enter = Enter.instance(context); 133 infer = Infer.instance(context); 134 analyzer = Analyzer.instance(context); 135 deferredAttr = DeferredAttr.instance(context); 136 cfolder = ConstFold.instance(context); 137 target = Target.instance(context); 138 types = Types.instance(context); 139 diags = JCDiagnostic.Factory.instance(context); 140 annotate = Annotate.instance(context); 141 typeAnnotations = TypeAnnotations.instance(context); 142 deferredLintHandler = DeferredLintHandler.instance(context); 143 typeEnvs = TypeEnvs.instance(context); 144 dependencies = Dependencies.instance(context); 145 146 Options options = Options.instance(context); 147 148 Source source = Source.instance(context); 149 allowStringsInSwitch = source.allowStringsInSwitch(); 150 allowPoly = source.allowPoly(); 151 allowTypeAnnos = source.allowTypeAnnotations(); 152 allowLambda = source.allowLambda(); 153 allowDefaultMethods = source.allowDefaultMethods(); 154 allowStaticInterfaceMethods = source.allowStaticInterfaceMethods(); 155 sourceName = source.name; 156 relax = (options.isSet("-retrofit") || 157 options.isSet("-relax")); 158 useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning"); 159 160 statInfo = new ResultInfo(KindSelector.NIL, Type.noType); 161 varAssignmentInfo = new ResultInfo(KindSelector.ASG, Type.noType); 162 unknownExprInfo = new ResultInfo(KindSelector.VAL, Type.noType); 163 unknownAnyPolyInfo = new ResultInfo(KindSelector.VAL, Infer.anyPoly); 164 unknownTypeInfo = new ResultInfo(KindSelector.TYP, Type.noType); 165 unknownTypeExprInfo = new ResultInfo(KindSelector.VAL_TYP, Type.noType); 166 recoveryInfo = new RecoveryInfo(deferredAttr.emptyDeferredAttrContext); 167 } 168 169 /** Switch: relax some constraints for retrofit mode. 170 */ 171 boolean relax; 172 173 /** Switch: support target-typing inference 174 */ 175 boolean allowPoly; 176 177 /** Switch: support type annotations. 178 */ 179 boolean allowTypeAnnos; 180 181 /** Switch: support lambda expressions ? 182 */ 183 boolean allowLambda; 184 185 /** Switch: support default methods ? 186 */ 187 boolean allowDefaultMethods; 188 189 /** Switch: static interface methods enabled? 190 */ 191 boolean allowStaticInterfaceMethods; 192 193 /** 194 * Switch: warn about use of variable before declaration? 195 * RFE: 6425594 196 */ 197 boolean useBeforeDeclarationWarning; 198 199 /** 200 * Switch: allow strings in switch? 201 */ 202 boolean allowStringsInSwitch; 203 204 /** 205 * Switch: name of source level; used for error reporting. 206 */ 207 String sourceName; 208 209 /** Check kind and type of given tree against protokind and prototype. 210 * If check succeeds, store type in tree and return it. 211 * If check fails, store errType in tree and return it. 212 * No checks are performed if the prototype is a method type. 213 * It is not necessary in this case since we know that kind and type 214 * are correct. 215 * 216 * @param tree The tree whose kind and type is checked 217 * @param found The computed type of the tree 218 * @param ownkind The computed kind of the tree 219 * @param resultInfo The expected result of the tree 220 */ 221 Type check(final JCTree tree, 222 final Type found, 223 final KindSelector ownkind, 224 final ResultInfo resultInfo) { 225 InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext(); 226 Type owntype; 227 boolean shouldCheck = !found.hasTag(ERROR) && 228 !resultInfo.pt.hasTag(METHOD) && 229 !resultInfo.pt.hasTag(FORALL); 230 if (shouldCheck && !ownkind.subset(resultInfo.pkind)) { 231 log.error(tree.pos(), "unexpected.type", 232 resultInfo.pkind.kindNames(), 233 ownkind.kindNames()); 234 owntype = types.createErrorType(found); 235 } else if (allowPoly && inferenceContext.free(found)) { 236 //delay the check if there are inference variables in the found type 237 //this means we are dealing with a partially inferred poly expression 238 owntype = shouldCheck ? resultInfo.pt : found; 239 if (resultInfo.checkMode.installPostInferenceHook()) { 240 inferenceContext.addFreeTypeListener(List.of(found, resultInfo.pt), 241 instantiatedContext -> { 242 ResultInfo pendingResult = 243 resultInfo.dup(inferenceContext.asInstType(resultInfo.pt)); 244 check(tree, inferenceContext.asInstType(found), ownkind, pendingResult); 245 }); 246 } 247 } else { 248 owntype = shouldCheck ? 249 resultInfo.check(tree, found) : 250 found; 251 } 252 if (resultInfo.checkMode.updateTreeType()) { 253 tree.type = owntype; 254 } 255 return owntype; 256 } 257 258 /** Is given blank final variable assignable, i.e. in a scope where it 259 * may be assigned to even though it is final? 260 * @param v The blank final variable. 261 * @param env The current environment. 262 */ 263 boolean isAssignableAsBlankFinal(VarSymbol v, Env<AttrContext> env) { 264 Symbol owner = env.info.scope.owner; 265 // owner refers to the innermost variable, method or 266 // initializer block declaration at this point. 267 return 268 v.owner == owner 269 || 270 ((owner.name == names.init || // i.e. we are in a constructor 271 owner.kind == VAR || // i.e. we are in a variable initializer 272 (owner.flags() & BLOCK) != 0) // i.e. we are in an initializer block 273 && 274 v.owner == owner.owner 275 && 276 ((v.flags() & STATIC) != 0) == Resolve.isStatic(env)); 277 } 278 279 /** Check that variable can be assigned to. 280 * @param pos The current source code position. 281 * @param v The assigned variable 282 * @param base If the variable is referred to in a Select, the part 283 * to the left of the `.', null otherwise. 284 * @param env The current environment. 285 */ 286 void checkAssignable(DiagnosticPosition pos, VarSymbol v, JCTree base, Env<AttrContext> env) { 287 if ((v.flags() & FINAL) != 0 && 288 ((v.flags() & HASINIT) != 0 289 || 290 !((base == null || 291 (base.hasTag(IDENT) && TreeInfo.name(base) == names._this)) && 292 isAssignableAsBlankFinal(v, env)))) { 293 if (v.isResourceVariable()) { //TWR resource 294 log.error(pos, "try.resource.may.not.be.assigned", v); 295 } else { 296 log.error(pos, "cant.assign.val.to.final.var", v); 297 } 298 } 299 } 300 301 /** Does tree represent a static reference to an identifier? 302 * It is assumed that tree is either a SELECT or an IDENT. 303 * We have to weed out selects from non-type names here. 304 * @param tree The candidate tree. 305 */ 306 boolean isStaticReference(JCTree tree) { 307 if (tree.hasTag(SELECT)) { 308 Symbol lsym = TreeInfo.symbol(((JCFieldAccess) tree).selected); 309 if (lsym == null || lsym.kind != TYP) { 310 return false; 311 } 312 } 313 return true; 314 } 315 316 /** Is this symbol a type? 317 */ 318 static boolean isType(Symbol sym) { 319 return sym != null && sym.kind == TYP; 320 } 321 322 /** The current `this' symbol. 323 * @param env The current environment. 324 */ 325 Symbol thisSym(DiagnosticPosition pos, Env<AttrContext> env) { 326 return rs.resolveSelf(pos, env, env.enclClass.sym, names._this); 327 } 328 329 /** Attribute a parsed identifier. 330 * @param tree Parsed identifier name 331 * @param topLevel The toplevel to use 332 */ 333 public Symbol attribIdent(JCTree tree, JCCompilationUnit topLevel) { 334 Env<AttrContext> localEnv = enter.topLevelEnv(topLevel); 335 localEnv.enclClass = make.ClassDef(make.Modifiers(0), 336 syms.errSymbol.name, 337 null, null, null, null); 338 localEnv.enclClass.sym = syms.errSymbol; 339 return tree.accept(identAttributer, localEnv); 340 } 341 // where 342 private TreeVisitor<Symbol,Env<AttrContext>> identAttributer = new IdentAttributer(); 343 private class IdentAttributer extends SimpleTreeVisitor<Symbol,Env<AttrContext>> { 344 @Override @DefinedBy(Api.COMPILER_TREE) 345 public Symbol visitMemberSelect(MemberSelectTree node, Env<AttrContext> env) { 346 Symbol site = visit(node.getExpression(), env); 347 if (site.kind == ERR || site.kind == ABSENT_TYP) 348 return site; 349 Name name = (Name)node.getIdentifier(); 350 if (site.kind == PCK) { 351 env.toplevel.packge = (PackageSymbol)site; 352 return rs.findIdentInPackage(env, (TypeSymbol)site, name, 353 KindSelector.TYP_PCK); 354 } else { 355 env.enclClass.sym = (ClassSymbol)site; 356 return rs.findMemberType(env, site.asType(), name, (TypeSymbol)site); 357 } 358 } 359 360 @Override @DefinedBy(Api.COMPILER_TREE) 361 public Symbol visitIdentifier(IdentifierTree node, Env<AttrContext> env) { 362 return rs.findIdent(env, (Name)node.getName(), KindSelector.TYP_PCK); 363 } 364 } 365 366 public Type coerce(Type etype, Type ttype) { 367 return cfolder.coerce(etype, ttype); 368 } 369 370 public Type attribType(JCTree node, TypeSymbol sym) { 371 Env<AttrContext> env = typeEnvs.get(sym); 372 Env<AttrContext> localEnv = env.dup(node, env.info.dup()); 373 return attribTree(node, localEnv, unknownTypeInfo); 374 } 375 376 public Type attribImportQualifier(JCImport tree, Env<AttrContext> env) { 377 // Attribute qualifying package or class. 378 JCFieldAccess s = (JCFieldAccess)tree.qualid; 379 return attribTree(s.selected, env, 380 new ResultInfo(tree.staticImport ? 381 KindSelector.TYP : KindSelector.TYP_PCK, 382 Type.noType)); 383 } 384 385 public Env<AttrContext> attribExprToTree(JCTree expr, Env<AttrContext> env, JCTree tree) { 386 breakTree = tree; 387 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 388 try { 389 attribExpr(expr, env); 390 } catch (BreakAttr b) { 391 return b.env; 392 } catch (AssertionError ae) { 393 if (ae.getCause() instanceof BreakAttr) { 394 return ((BreakAttr)(ae.getCause())).env; 395 } else { 396 throw ae; 397 } 398 } finally { 399 breakTree = null; 400 log.useSource(prev); 401 } 402 return env; 403 } 404 405 public Env<AttrContext> attribStatToTree(JCTree stmt, Env<AttrContext> env, JCTree tree) { 406 breakTree = tree; 407 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 408 try { 409 attribStat(stmt, env); 410 } catch (BreakAttr b) { 411 return b.env; 412 } catch (AssertionError ae) { 413 if (ae.getCause() instanceof BreakAttr) { 414 return ((BreakAttr)(ae.getCause())).env; 415 } else { 416 throw ae; 417 } 418 } finally { 419 breakTree = null; 420 log.useSource(prev); 421 } 422 return env; 423 } 424 425 private JCTree breakTree = null; 426 427 private static class BreakAttr extends RuntimeException { 428 static final long serialVersionUID = -6924771130405446405L; 429 private Env<AttrContext> env; 430 private BreakAttr(Env<AttrContext> env) { 431 this.env = env; 432 } 433 } 434 435 /** 436 * Mode controlling behavior of Attr.Check 437 */ 438 enum CheckMode { 439 440 NORMAL, 441 442 NO_TREE_UPDATE { // Mode signalling 'fake check' - skip tree update 443 @Override 444 public boolean updateTreeType() { 445 return false; 446 } 447 }, 448 NO_INFERENCE_HOOK { // Mode signalling that caller will manage free types in tree decorations. 449 @Override 450 public boolean installPostInferenceHook() { 451 return false; 452 } 453 }; 454 455 public boolean updateTreeType() { 456 return true; 457 } 458 public boolean installPostInferenceHook() { 459 return true; 460 } 461 } 462 463 464 class ResultInfo { 465 final KindSelector pkind; 466 final Type pt; 467 final CheckContext checkContext; 468 final CheckMode checkMode; 469 470 ResultInfo(KindSelector pkind, Type pt) { 471 this(pkind, pt, chk.basicHandler, CheckMode.NORMAL); 472 } 473 474 ResultInfo(KindSelector pkind, Type pt, CheckMode checkMode) { 475 this(pkind, pt, chk.basicHandler, checkMode); 476 } 477 478 protected ResultInfo(KindSelector pkind, 479 Type pt, CheckContext checkContext) { 480 this(pkind, pt, checkContext, CheckMode.NORMAL); 481 } 482 483 protected ResultInfo(KindSelector pkind, 484 Type pt, CheckContext checkContext, CheckMode checkMode) { 485 this.pkind = pkind; 486 this.pt = pt; 487 this.checkContext = checkContext; 488 this.checkMode = checkMode; 489 } 490 491 protected Type check(final DiagnosticPosition pos, final Type found) { 492 return chk.checkType(pos, found, pt, checkContext); 493 } 494 495 protected ResultInfo dup(Type newPt) { 496 return new ResultInfo(pkind, newPt, checkContext, checkMode); 497 } 498 499 protected ResultInfo dup(CheckContext newContext) { 500 return new ResultInfo(pkind, pt, newContext, checkMode); 501 } 502 503 protected ResultInfo dup(Type newPt, CheckContext newContext) { 504 return new ResultInfo(pkind, newPt, newContext, checkMode); 505 } 506 507 protected ResultInfo dup(Type newPt, CheckContext newContext, CheckMode newMode) { 508 return new ResultInfo(pkind, newPt, newContext, newMode); 509 } 510 511 protected ResultInfo dup(CheckMode newMode) { 512 return new ResultInfo(pkind, pt, checkContext, newMode); 513 } 514 515 @Override 516 public String toString() { 517 if (pt != null) { 518 return pt.toString(); 519 } else { 520 return ""; 521 } 522 } 523 } 524 525 class RecoveryInfo extends ResultInfo { 526 527 public RecoveryInfo(final DeferredAttr.DeferredAttrContext deferredAttrContext) { 528 super(KindSelector.VAL, Type.recoveryType, 529 new Check.NestedCheckContext(chk.basicHandler) { 530 @Override 531 public DeferredAttr.DeferredAttrContext deferredAttrContext() { 532 return deferredAttrContext; 533 } 534 @Override 535 public boolean compatible(Type found, Type req, Warner warn) { 536 return true; 537 } 538 @Override 539 public void report(DiagnosticPosition pos, JCDiagnostic details) { 540 chk.basicHandler.report(pos, details); 541 } 542 }); 543 } 544 } 545 546 final ResultInfo statInfo; 547 final ResultInfo varAssignmentInfo; 548 final ResultInfo unknownAnyPolyInfo; 549 final ResultInfo unknownExprInfo; 550 final ResultInfo unknownTypeInfo; 551 final ResultInfo unknownTypeExprInfo; 552 final ResultInfo recoveryInfo; 553 554 Type pt() { 555 return resultInfo.pt; 556 } 557 558 KindSelector pkind() { 559 return resultInfo.pkind; 560 } 561 562/* ************************************************************************ 563 * Visitor methods 564 *************************************************************************/ 565 566 /** Visitor argument: the current environment. 567 */ 568 Env<AttrContext> env; 569 570 /** Visitor argument: the currently expected attribution result. 571 */ 572 ResultInfo resultInfo; 573 574 /** Visitor result: the computed type. 575 */ 576 Type result; 577 578 /** Visitor method: attribute a tree, catching any completion failure 579 * exceptions. Return the tree's type. 580 * 581 * @param tree The tree to be visited. 582 * @param env The environment visitor argument. 583 * @param resultInfo The result info visitor argument. 584 */ 585 Type attribTree(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) { 586 Env<AttrContext> prevEnv = this.env; 587 ResultInfo prevResult = this.resultInfo; 588 try { 589 this.env = env; 590 this.resultInfo = resultInfo; 591 tree.accept(this); 592 if (tree == breakTree && 593 resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) { 594 throw new BreakAttr(copyEnv(env)); 595 } 596 return result; 597 } catch (CompletionFailure ex) { 598 tree.type = syms.errType; 599 return chk.completionError(tree.pos(), ex); 600 } finally { 601 this.env = prevEnv; 602 this.resultInfo = prevResult; 603 } 604 } 605 606 Env<AttrContext> copyEnv(Env<AttrContext> env) { 607 Env<AttrContext> newEnv = 608 env.dup(env.tree, env.info.dup(copyScope(env.info.scope))); 609 if (newEnv.outer != null) { 610 newEnv.outer = copyEnv(newEnv.outer); 611 } 612 return newEnv; 613 } 614 615 WriteableScope copyScope(WriteableScope sc) { 616 WriteableScope newScope = WriteableScope.create(sc.owner); 617 List<Symbol> elemsList = List.nil(); 618 for (Symbol sym : sc.getSymbols()) { 619 elemsList = elemsList.prepend(sym); 620 } 621 for (Symbol s : elemsList) { 622 newScope.enter(s); 623 } 624 return newScope; 625 } 626 627 /** Derived visitor method: attribute an expression tree. 628 */ 629 public Type attribExpr(JCTree tree, Env<AttrContext> env, Type pt) { 630 return attribTree(tree, env, new ResultInfo(KindSelector.VAL, !pt.hasTag(ERROR) ? pt : Type.noType)); 631 } 632 633 /** Derived visitor method: attribute an expression tree with 634 * no constraints on the computed type. 635 */ 636 public Type attribExpr(JCTree tree, Env<AttrContext> env) { 637 return attribTree(tree, env, unknownExprInfo); 638 } 639 640 /** Derived visitor method: attribute a type tree. 641 */ 642 public Type attribType(JCTree tree, Env<AttrContext> env) { 643 Type result = attribType(tree, env, Type.noType); 644 return result; 645 } 646 647 /** Derived visitor method: attribute a type tree. 648 */ 649 Type attribType(JCTree tree, Env<AttrContext> env, Type pt) { 650 Type result = attribTree(tree, env, new ResultInfo(KindSelector.TYP, pt)); 651 return result; 652 } 653 654 /** Derived visitor method: attribute a statement or definition tree. 655 */ 656 public Type attribStat(JCTree tree, Env<AttrContext> env) { 657 Env<AttrContext> analyzeEnv = 658 env.dup(tree, env.info.dup(env.info.scope.dupUnshared(env.info.scope.owner))); 659 try { 660 return attribTree(tree, env, statInfo); 661 } finally { 662 analyzer.analyzeIfNeeded(tree, analyzeEnv); 663 } 664 } 665 666 /** Attribute a list of expressions, returning a list of types. 667 */ 668 List<Type> attribExprs(List<JCExpression> trees, Env<AttrContext> env, Type pt) { 669 ListBuffer<Type> ts = new ListBuffer<>(); 670 for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail) 671 ts.append(attribExpr(l.head, env, pt)); 672 return ts.toList(); 673 } 674 675 /** Attribute a list of statements, returning nothing. 676 */ 677 <T extends JCTree> void attribStats(List<T> trees, Env<AttrContext> env) { 678 for (List<T> l = trees; l.nonEmpty(); l = l.tail) 679 attribStat(l.head, env); 680 } 681 682 /** Attribute the arguments in a method call, returning the method kind. 683 */ 684 KindSelector attribArgs(KindSelector initialKind, List<JCExpression> trees, Env<AttrContext> env, ListBuffer<Type> argtypes) { 685 KindSelector kind = initialKind; 686 for (JCExpression arg : trees) { 687 Type argtype; 688 if (allowPoly && deferredAttr.isDeferred(env, arg)) { 689 argtype = deferredAttr.new DeferredType(arg, env); 690 kind = KindSelector.of(KindSelector.POLY, kind); 691 } else { 692 argtype = chk.checkNonVoid(arg, attribTree(arg, env, unknownAnyPolyInfo)); 693 } 694 argtypes.append(argtype); 695 } 696 return kind; 697 } 698 699 /** Attribute a type argument list, returning a list of types. 700 * Caller is responsible for calling checkRefTypes. 701 */ 702 List<Type> attribAnyTypes(List<JCExpression> trees, Env<AttrContext> env) { 703 ListBuffer<Type> argtypes = new ListBuffer<>(); 704 for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail) 705 argtypes.append(attribType(l.head, env)); 706 return argtypes.toList(); 707 } 708 709 /** Attribute a type argument list, returning a list of types. 710 * Check that all the types are references. 711 */ 712 List<Type> attribTypes(List<JCExpression> trees, Env<AttrContext> env) { 713 List<Type> types = attribAnyTypes(trees, env); 714 return chk.checkRefTypes(trees, types); 715 } 716 717 /** 718 * Attribute type variables (of generic classes or methods). 719 * Compound types are attributed later in attribBounds. 720 * @param typarams the type variables to enter 721 * @param env the current environment 722 */ 723 void attribTypeVariables(List<JCTypeParameter> typarams, Env<AttrContext> env) { 724 for (JCTypeParameter tvar : typarams) { 725 dependencies.push(AttributionKind.TVAR, tvar); 726 TypeVar a = (TypeVar)tvar.type; 727 a.tsym.flags_field |= UNATTRIBUTED; 728 a.bound = Type.noType; 729 if (!tvar.bounds.isEmpty()) { 730 List<Type> bounds = List.of(attribType(tvar.bounds.head, env)); 731 for (JCExpression bound : tvar.bounds.tail) 732 bounds = bounds.prepend(attribType(bound, env)); 733 types.setBounds(a, bounds.reverse()); 734 } else { 735 // if no bounds are given, assume a single bound of 736 // java.lang.Object. 737 types.setBounds(a, List.of(syms.objectType)); 738 } 739 a.tsym.flags_field &= ~UNATTRIBUTED; 740 dependencies.pop(); 741 } 742 for (JCTypeParameter tvar : typarams) { 743 chk.checkNonCyclic(tvar.pos(), (TypeVar)tvar.type); 744 } 745 } 746 747 /** 748 * Attribute the type references in a list of annotations. 749 */ 750 void attribAnnotationTypes(List<JCAnnotation> annotations, 751 Env<AttrContext> env) { 752 for (List<JCAnnotation> al = annotations; al.nonEmpty(); al = al.tail) { 753 JCAnnotation a = al.head; 754 attribType(a.annotationType, env); 755 } 756 } 757 758 /** 759 * Attribute a "lazy constant value". 760 * @param env The env for the const value 761 * @param variable The initializer for the const value 762 * @param type The expected type, or null 763 * @see VarSymbol#setLazyConstValue 764 */ 765 public Object attribLazyConstantValue(Env<AttrContext> env, 766 JCVariableDecl variable, 767 Type type) { 768 769 DiagnosticPosition prevLintPos 770 = deferredLintHandler.setPos(variable.pos()); 771 772 try { 773 Type itype = attribExpr(variable.init, env, type); 774 if (itype.constValue() != null) { 775 return coerce(itype, type).constValue(); 776 } else { 777 return null; 778 } 779 } finally { 780 deferredLintHandler.setPos(prevLintPos); 781 } 782 } 783 784 /** Attribute type reference in an `extends' or `implements' clause. 785 * Supertypes of anonymous inner classes are usually already attributed. 786 * 787 * @param tree The tree making up the type reference. 788 * @param env The environment current at the reference. 789 * @param classExpected true if only a class is expected here. 790 * @param interfaceExpected true if only an interface is expected here. 791 */ 792 Type attribBase(JCTree tree, 793 Env<AttrContext> env, 794 boolean classExpected, 795 boolean interfaceExpected, 796 boolean checkExtensible) { 797 Type t = tree.type != null ? 798 tree.type : 799 attribType(tree, env); 800 return checkBase(t, tree, env, classExpected, interfaceExpected, checkExtensible); 801 } 802 Type checkBase(Type t, 803 JCTree tree, 804 Env<AttrContext> env, 805 boolean classExpected, 806 boolean interfaceExpected, 807 boolean checkExtensible) { 808 if (t.tsym.isAnonymous()) { 809 log.error(tree.pos(), "cant.inherit.from.anon"); 810 return types.createErrorType(t); 811 } 812 if (t.isErroneous()) 813 return t; 814 if (t.hasTag(TYPEVAR) && !classExpected && !interfaceExpected) { 815 // check that type variable is already visible 816 if (t.getUpperBound() == null) { 817 log.error(tree.pos(), "illegal.forward.ref"); 818 return types.createErrorType(t); 819 } 820 } else { 821 t = chk.checkClassType(tree.pos(), t, checkExtensible); 822 } 823 if (interfaceExpected && (t.tsym.flags() & INTERFACE) == 0) { 824 log.error(tree.pos(), "intf.expected.here"); 825 // return errType is necessary since otherwise there might 826 // be undetected cycles which cause attribution to loop 827 return types.createErrorType(t); 828 } else if (checkExtensible && 829 classExpected && 830 (t.tsym.flags() & INTERFACE) != 0) { 831 log.error(tree.pos(), "no.intf.expected.here"); 832 return types.createErrorType(t); 833 } 834 if (checkExtensible && 835 ((t.tsym.flags() & FINAL) != 0)) { 836 log.error(tree.pos(), 837 "cant.inherit.from.final", t.tsym); 838 } 839 chk.checkNonCyclic(tree.pos(), t); 840 return t; 841 } 842 843 Type attribIdentAsEnumType(Env<AttrContext> env, JCIdent id) { 844 Assert.check((env.enclClass.sym.flags() & ENUM) != 0); 845 id.type = env.info.scope.owner.enclClass().type; 846 id.sym = env.info.scope.owner.enclClass(); 847 return id.type; 848 } 849 850 public void visitClassDef(JCClassDecl tree) { 851 // Local and anonymous classes have not been entered yet, so we need to 852 // do it now. 853 if (env.info.scope.owner.kind.matches(KindSelector.VAL_MTH)) { 854 enter.classEnter(tree, env); 855 } else { 856 // If this class declaration is part of a class level annotation, 857 // as in @MyAnno(new Object() {}) class MyClass {}, enter it in 858 // order to simplify later steps and allow for sensible error 859 // messages. 860 if (env.tree.hasTag(NEWCLASS) && TreeInfo.isInAnnotation(env, tree)) 861 enter.classEnter(tree, env); 862 } 863 864 ClassSymbol c = tree.sym; 865 if (c == null) { 866 // exit in case something drastic went wrong during enter. 867 result = null; 868 } else { 869 // make sure class has been completed: 870 c.complete(); 871 872 // If this class appears as an anonymous class 873 // in a superclass constructor call where 874 // no explicit outer instance is given, 875 // disable implicit outer instance from being passed. 876 // (This would be an illegal access to "this before super"). 877 if (env.info.isSelfCall && 878 env.tree.hasTag(NEWCLASS) && 879 ((JCNewClass) env.tree).encl == null) 880 { 881 c.flags_field |= NOOUTERTHIS; 882 } 883 attribClass(tree.pos(), c); 884 result = tree.type = c.type; 885 } 886 } 887 888 public void visitMethodDef(JCMethodDecl tree) { 889 MethodSymbol m = tree.sym; 890 boolean isDefaultMethod = (m.flags() & DEFAULT) != 0; 891 892 Lint lint = env.info.lint.augment(m); 893 Lint prevLint = chk.setLint(lint); 894 MethodSymbol prevMethod = chk.setMethod(m); 895 try { 896 deferredLintHandler.flush(tree.pos()); 897 chk.checkDeprecatedAnnotation(tree.pos(), m); 898 899 900 // Create a new environment with local scope 901 // for attributing the method. 902 Env<AttrContext> localEnv = memberEnter.methodEnv(tree, env); 903 localEnv.info.lint = lint; 904 905 attribStats(tree.typarams, localEnv); 906 907 // If we override any other methods, check that we do so properly. 908 // JLS ??? 909 if (m.isStatic()) { 910 chk.checkHideClashes(tree.pos(), env.enclClass.type, m); 911 } else { 912 chk.checkOverrideClashes(tree.pos(), env.enclClass.type, m); 913 } 914 chk.checkOverride(env, tree, m); 915 916 if (isDefaultMethod && types.overridesObjectMethod(m.enclClass(), m)) { 917 log.error(tree, "default.overrides.object.member", m.name, Kinds.kindName(m.location()), m.location()); 918 } 919 920 // Enter all type parameters into the local method scope. 921 for (List<JCTypeParameter> l = tree.typarams; l.nonEmpty(); l = l.tail) 922 localEnv.info.scope.enterIfAbsent(l.head.type.tsym); 923 924 ClassSymbol owner = env.enclClass.sym; 925 if ((owner.flags() & ANNOTATION) != 0 && 926 tree.params.nonEmpty()) 927 log.error(tree.params.head.pos(), 928 "intf.annotation.members.cant.have.params"); 929 930 // Attribute all value parameters. 931 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { 932 attribStat(l.head, localEnv); 933 } 934 935 chk.checkVarargsMethodDecl(localEnv, tree); 936 937 // Check that type parameters are well-formed. 938 chk.validate(tree.typarams, localEnv); 939 940 // Check that result type is well-formed. 941 if (tree.restype != null && !tree.restype.type.hasTag(VOID)) 942 chk.validate(tree.restype, localEnv); 943 944 // Check that receiver type is well-formed. 945 if (tree.recvparam != null) { 946 // Use a new environment to check the receiver parameter. 947 // Otherwise I get "might not have been initialized" errors. 948 // Is there a better way? 949 Env<AttrContext> newEnv = memberEnter.methodEnv(tree, env); 950 attribType(tree.recvparam, newEnv); 951 chk.validate(tree.recvparam, newEnv); 952 } 953 954 // annotation method checks 955 if ((owner.flags() & ANNOTATION) != 0) { 956 // annotation method cannot have throws clause 957 if (tree.thrown.nonEmpty()) { 958 log.error(tree.thrown.head.pos(), 959 "throws.not.allowed.in.intf.annotation"); 960 } 961 // annotation method cannot declare type-parameters 962 if (tree.typarams.nonEmpty()) { 963 log.error(tree.typarams.head.pos(), 964 "intf.annotation.members.cant.have.type.params"); 965 } 966 // validate annotation method's return type (could be an annotation type) 967 chk.validateAnnotationType(tree.restype); 968 // ensure that annotation method does not clash with members of Object/Annotation 969 chk.validateAnnotationMethod(tree.pos(), m); 970 } 971 972 for (List<JCExpression> l = tree.thrown; l.nonEmpty(); l = l.tail) 973 chk.checkType(l.head.pos(), l.head.type, syms.throwableType); 974 975 if (tree.body == null) { 976 // Empty bodies are only allowed for 977 // abstract, native, or interface methods, or for methods 978 // in a retrofit signature class. 979 if (tree.defaultValue != null) { 980 if ((owner.flags() & ANNOTATION) == 0) 981 log.error(tree.pos(), 982 "default.allowed.in.intf.annotation.member"); 983 } 984 if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0 && 985 !relax) 986 log.error(tree.pos(), "missing.meth.body.or.decl.abstract"); 987 } else if ((tree.sym.flags() & (ABSTRACT|DEFAULT|PRIVATE)) == ABSTRACT) { 988 if ((owner.flags() & INTERFACE) != 0) { 989 log.error(tree.body.pos(), "intf.meth.cant.have.body"); 990 } else { 991 log.error(tree.pos(), "abstract.meth.cant.have.body"); 992 } 993 } else if ((tree.mods.flags & NATIVE) != 0) { 994 log.error(tree.pos(), "native.meth.cant.have.body"); 995 } else { 996 // Add an implicit super() call unless an explicit call to 997 // super(...) or this(...) is given 998 // or we are compiling class java.lang.Object. 999 if (tree.name == names.init && owner.type != syms.objectType) { 1000 JCBlock body = tree.body; 1001 if (body.stats.isEmpty() || 1002 !TreeInfo.isSelfCall(body.stats.head)) { 1003 body.stats = body.stats. 1004 prepend(typeEnter.SuperCall(make.at(body.pos), 1005 List.<Type>nil(), 1006 List.<JCVariableDecl>nil(), 1007 false)); 1008 } else if ((env.enclClass.sym.flags() & ENUM) != 0 && 1009 (tree.mods.flags & GENERATEDCONSTR) == 0 && 1010 TreeInfo.isSuperCall(body.stats.head)) { 1011 // enum constructors are not allowed to call super 1012 // directly, so make sure there aren't any super calls 1013 // in enum constructors, except in the compiler 1014 // generated one. 1015 log.error(tree.body.stats.head.pos(), 1016 "call.to.super.not.allowed.in.enum.ctor", 1017 env.enclClass.sym); 1018 } 1019 } 1020 1021 // Attribute all type annotations in the body 1022 annotate.queueScanTreeAndTypeAnnotate(tree.body, localEnv, m, null); 1023 annotate.flush(); 1024 1025 // Attribute method body. 1026 attribStat(tree.body, localEnv); 1027 } 1028 1029 localEnv.info.scope.leave(); 1030 result = tree.type = m.type; 1031 } finally { 1032 chk.setLint(prevLint); 1033 chk.setMethod(prevMethod); 1034 } 1035 } 1036 1037 public void visitVarDef(JCVariableDecl tree) { 1038 // Local variables have not been entered yet, so we need to do it now: 1039 if (env.info.scope.owner.kind == MTH) { 1040 if (tree.sym != null) { 1041 // parameters have already been entered 1042 env.info.scope.enter(tree.sym); 1043 } else { 1044 try { 1045 annotate.blockAnnotations(); 1046 memberEnter.memberEnter(tree, env); 1047 } finally { 1048 annotate.unblockAnnotations(); 1049 } 1050 } 1051 } else { 1052 if (tree.init != null) { 1053 // Field initializer expression need to be entered. 1054 annotate.queueScanTreeAndTypeAnnotate(tree.init, env, tree.sym, tree.pos()); 1055 annotate.flush(); 1056 } 1057 } 1058 1059 VarSymbol v = tree.sym; 1060 Lint lint = env.info.lint.augment(v); 1061 Lint prevLint = chk.setLint(lint); 1062 1063 // Check that the variable's declared type is well-formed. 1064 boolean isImplicitLambdaParameter = env.tree.hasTag(LAMBDA) && 1065 ((JCLambda)env.tree).paramKind == JCLambda.ParameterKind.IMPLICIT && 1066 (tree.sym.flags() & PARAMETER) != 0; 1067 chk.validate(tree.vartype, env, !isImplicitLambdaParameter); 1068 1069 try { 1070 v.getConstValue(); // ensure compile-time constant initializer is evaluated 1071 deferredLintHandler.flush(tree.pos()); 1072 chk.checkDeprecatedAnnotation(tree.pos(), v); 1073 1074 if (tree.init != null) { 1075 if ((v.flags_field & FINAL) == 0 || 1076 !memberEnter.needsLazyConstValue(tree.init)) { 1077 // Not a compile-time constant 1078 // Attribute initializer in a new environment 1079 // with the declared variable as owner. 1080 // Check that initializer conforms to variable's declared type. 1081 Env<AttrContext> initEnv = memberEnter.initEnv(tree, env); 1082 initEnv.info.lint = lint; 1083 // In order to catch self-references, we set the variable's 1084 // declaration position to maximal possible value, effectively 1085 // marking the variable as undefined. 1086 initEnv.info.enclVar = v; 1087 attribExpr(tree.init, initEnv, v.type); 1088 } 1089 } 1090 result = tree.type = v.type; 1091 } 1092 finally { 1093 chk.setLint(prevLint); 1094 } 1095 } 1096 1097 public void visitSkip(JCSkip tree) { 1098 result = null; 1099 } 1100 1101 public void visitBlock(JCBlock tree) { 1102 if (env.info.scope.owner.kind == TYP) { 1103 // Block is a static or instance initializer; 1104 // let the owner of the environment be a freshly 1105 // created BLOCK-method. 1106 Symbol fakeOwner = 1107 new MethodSymbol(tree.flags | BLOCK | 1108 env.info.scope.owner.flags() & STRICTFP, names.empty, null, 1109 env.info.scope.owner); 1110 final Env<AttrContext> localEnv = 1111 env.dup(tree, env.info.dup(env.info.scope.dupUnshared(fakeOwner))); 1112 1113 if ((tree.flags & STATIC) != 0) localEnv.info.staticLevel++; 1114 // Attribute all type annotations in the block 1115 annotate.queueScanTreeAndTypeAnnotate(tree, localEnv, localEnv.info.scope.owner, null); 1116 annotate.flush(); 1117 attribStats(tree.stats, localEnv); 1118 1119 { 1120 // Store init and clinit type annotations with the ClassSymbol 1121 // to allow output in Gen.normalizeDefs. 1122 ClassSymbol cs = (ClassSymbol)env.info.scope.owner; 1123 List<Attribute.TypeCompound> tas = localEnv.info.scope.owner.getRawTypeAttributes(); 1124 if ((tree.flags & STATIC) != 0) { 1125 cs.appendClassInitTypeAttributes(tas); 1126 } else { 1127 cs.appendInitTypeAttributes(tas); 1128 } 1129 } 1130 } else { 1131 // Create a new local environment with a local scope. 1132 Env<AttrContext> localEnv = 1133 env.dup(tree, env.info.dup(env.info.scope.dup())); 1134 try { 1135 attribStats(tree.stats, localEnv); 1136 } finally { 1137 localEnv.info.scope.leave(); 1138 } 1139 } 1140 result = null; 1141 } 1142 1143 public void visitDoLoop(JCDoWhileLoop tree) { 1144 attribStat(tree.body, env.dup(tree)); 1145 attribExpr(tree.cond, env, syms.booleanType); 1146 result = null; 1147 } 1148 1149 public void visitWhileLoop(JCWhileLoop tree) { 1150 attribExpr(tree.cond, env, syms.booleanType); 1151 attribStat(tree.body, env.dup(tree)); 1152 result = null; 1153 } 1154 1155 public void visitForLoop(JCForLoop tree) { 1156 Env<AttrContext> loopEnv = 1157 env.dup(env.tree, env.info.dup(env.info.scope.dup())); 1158 try { 1159 attribStats(tree.init, loopEnv); 1160 if (tree.cond != null) attribExpr(tree.cond, loopEnv, syms.booleanType); 1161 loopEnv.tree = tree; // before, we were not in loop! 1162 attribStats(tree.step, loopEnv); 1163 attribStat(tree.body, loopEnv); 1164 result = null; 1165 } 1166 finally { 1167 loopEnv.info.scope.leave(); 1168 } 1169 } 1170 1171 public void visitForeachLoop(JCEnhancedForLoop tree) { 1172 Env<AttrContext> loopEnv = 1173 env.dup(env.tree, env.info.dup(env.info.scope.dup())); 1174 try { 1175 //the Formal Parameter of a for-each loop is not in the scope when 1176 //attributing the for-each expression; we mimick this by attributing 1177 //the for-each expression first (against original scope). 1178 Type exprType = types.cvarUpperBound(attribExpr(tree.expr, loopEnv)); 1179 attribStat(tree.var, loopEnv); 1180 chk.checkNonVoid(tree.pos(), exprType); 1181 Type elemtype = types.elemtype(exprType); // perhaps expr is an array? 1182 if (elemtype == null) { 1183 // or perhaps expr implements Iterable<T>? 1184 Type base = types.asSuper(exprType, syms.iterableType.tsym); 1185 if (base == null) { 1186 log.error(tree.expr.pos(), 1187 "foreach.not.applicable.to.type", 1188 exprType, 1189 diags.fragment("type.req.array.or.iterable")); 1190 elemtype = types.createErrorType(exprType); 1191 } else { 1192 List<Type> iterableParams = base.allparams(); 1193 elemtype = iterableParams.isEmpty() 1194 ? syms.objectType 1195 : types.wildUpperBound(iterableParams.head); 1196 } 1197 } 1198 chk.checkType(tree.expr.pos(), elemtype, tree.var.sym.type); 1199 loopEnv.tree = tree; // before, we were not in loop! 1200 attribStat(tree.body, loopEnv); 1201 result = null; 1202 } 1203 finally { 1204 loopEnv.info.scope.leave(); 1205 } 1206 } 1207 1208 public void visitLabelled(JCLabeledStatement tree) { 1209 // Check that label is not used in an enclosing statement 1210 Env<AttrContext> env1 = env; 1211 while (env1 != null && !env1.tree.hasTag(CLASSDEF)) { 1212 if (env1.tree.hasTag(LABELLED) && 1213 ((JCLabeledStatement) env1.tree).label == tree.label) { 1214 log.error(tree.pos(), "label.already.in.use", 1215 tree.label); 1216 break; 1217 } 1218 env1 = env1.next; 1219 } 1220 1221 attribStat(tree.body, env.dup(tree)); 1222 result = null; 1223 } 1224 1225 public void visitSwitch(JCSwitch tree) { 1226 Type seltype = attribExpr(tree.selector, env); 1227 1228 Env<AttrContext> switchEnv = 1229 env.dup(tree, env.info.dup(env.info.scope.dup())); 1230 1231 try { 1232 1233 boolean enumSwitch = (seltype.tsym.flags() & Flags.ENUM) != 0; 1234 boolean stringSwitch = false; 1235 if (types.isSameType(seltype, syms.stringType)) { 1236 if (allowStringsInSwitch) { 1237 stringSwitch = true; 1238 } else { 1239 log.error(tree.selector.pos(), "string.switch.not.supported.in.source", sourceName); 1240 } 1241 } 1242 if (!enumSwitch && !stringSwitch) 1243 seltype = chk.checkType(tree.selector.pos(), seltype, syms.intType); 1244 1245 // Attribute all cases and 1246 // check that there are no duplicate case labels or default clauses. 1247 Set<Object> labels = new HashSet<>(); // The set of case labels. 1248 boolean hasDefault = false; // Is there a default label? 1249 for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) { 1250 JCCase c = l.head; 1251 if (c.pat != null) { 1252 if (enumSwitch) { 1253 Symbol sym = enumConstant(c.pat, seltype); 1254 if (sym == null) { 1255 log.error(c.pat.pos(), "enum.label.must.be.unqualified.enum"); 1256 } else if (!labels.add(sym)) { 1257 log.error(c.pos(), "duplicate.case.label"); 1258 } 1259 } else { 1260 Type pattype = attribExpr(c.pat, switchEnv, seltype); 1261 if (!pattype.hasTag(ERROR)) { 1262 if (pattype.constValue() == null) { 1263 log.error(c.pat.pos(), 1264 (stringSwitch ? "string.const.req" : "const.expr.req")); 1265 } else if (!labels.add(pattype.constValue())) { 1266 log.error(c.pos(), "duplicate.case.label"); 1267 } 1268 } 1269 } 1270 } else if (hasDefault) { 1271 log.error(c.pos(), "duplicate.default.label"); 1272 } else { 1273 hasDefault = true; 1274 } 1275 Env<AttrContext> caseEnv = 1276 switchEnv.dup(c, env.info.dup(switchEnv.info.scope.dup())); 1277 try { 1278 attribStats(c.stats, caseEnv); 1279 } finally { 1280 caseEnv.info.scope.leave(); 1281 addVars(c.stats, switchEnv.info.scope); 1282 } 1283 } 1284 1285 result = null; 1286 } 1287 finally { 1288 switchEnv.info.scope.leave(); 1289 } 1290 } 1291 // where 1292 /** Add any variables defined in stats to the switch scope. */ 1293 private static void addVars(List<JCStatement> stats, WriteableScope switchScope) { 1294 for (;stats.nonEmpty(); stats = stats.tail) { 1295 JCTree stat = stats.head; 1296 if (stat.hasTag(VARDEF)) 1297 switchScope.enter(((JCVariableDecl) stat).sym); 1298 } 1299 } 1300 // where 1301 /** Return the selected enumeration constant symbol, or null. */ 1302 private Symbol enumConstant(JCTree tree, Type enumType) { 1303 if (tree.hasTag(IDENT)) { 1304 JCIdent ident = (JCIdent)tree; 1305 Name name = ident.name; 1306 for (Symbol sym : enumType.tsym.members().getSymbolsByName(name)) { 1307 if (sym.kind == VAR) { 1308 Symbol s = ident.sym = sym; 1309 ((VarSymbol)s).getConstValue(); // ensure initializer is evaluated 1310 ident.type = s.type; 1311 return ((s.flags_field & Flags.ENUM) == 0) 1312 ? null : s; 1313 } 1314 } 1315 } 1316 return null; 1317 } 1318 1319 public void visitSynchronized(JCSynchronized tree) { 1320 chk.checkRefType(tree.pos(), attribExpr(tree.lock, env)); 1321 attribStat(tree.body, env); 1322 result = null; 1323 } 1324 1325 public void visitTry(JCTry tree) { 1326 // Create a new local environment with a local 1327 Env<AttrContext> localEnv = env.dup(tree, env.info.dup(env.info.scope.dup())); 1328 try { 1329 boolean isTryWithResource = tree.resources.nonEmpty(); 1330 // Create a nested environment for attributing the try block if needed 1331 Env<AttrContext> tryEnv = isTryWithResource ? 1332 env.dup(tree, localEnv.info.dup(localEnv.info.scope.dup())) : 1333 localEnv; 1334 try { 1335 // Attribute resource declarations 1336 for (JCTree resource : tree.resources) { 1337 CheckContext twrContext = new Check.NestedCheckContext(resultInfo.checkContext) { 1338 @Override 1339 public void report(DiagnosticPosition pos, JCDiagnostic details) { 1340 chk.basicHandler.report(pos, diags.fragment("try.not.applicable.to.type", details)); 1341 } 1342 }; 1343 ResultInfo twrResult = 1344 new ResultInfo(KindSelector.VAR, 1345 syms.autoCloseableType, 1346 twrContext); 1347 if (resource.hasTag(VARDEF)) { 1348 attribStat(resource, tryEnv); 1349 twrResult.check(resource, resource.type); 1350 1351 //check that resource type cannot throw InterruptedException 1352 checkAutoCloseable(resource.pos(), localEnv, resource.type); 1353 1354 VarSymbol var = ((JCVariableDecl) resource).sym; 1355 var.setData(ElementKind.RESOURCE_VARIABLE); 1356 } else { 1357 attribTree(resource, tryEnv, twrResult); 1358 } 1359 } 1360 // Attribute body 1361 attribStat(tree.body, tryEnv); 1362 } finally { 1363 if (isTryWithResource) 1364 tryEnv.info.scope.leave(); 1365 } 1366 1367 // Attribute catch clauses 1368 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { 1369 JCCatch c = l.head; 1370 Env<AttrContext> catchEnv = 1371 localEnv.dup(c, localEnv.info.dup(localEnv.info.scope.dup())); 1372 try { 1373 Type ctype = attribStat(c.param, catchEnv); 1374 if (TreeInfo.isMultiCatch(c)) { 1375 //multi-catch parameter is implicitly marked as final 1376 c.param.sym.flags_field |= FINAL | UNION; 1377 } 1378 if (c.param.sym.kind == VAR) { 1379 c.param.sym.setData(ElementKind.EXCEPTION_PARAMETER); 1380 } 1381 chk.checkType(c.param.vartype.pos(), 1382 chk.checkClassType(c.param.vartype.pos(), ctype), 1383 syms.throwableType); 1384 attribStat(c.body, catchEnv); 1385 } finally { 1386 catchEnv.info.scope.leave(); 1387 } 1388 } 1389 1390 // Attribute finalizer 1391 if (tree.finalizer != null) attribStat(tree.finalizer, localEnv); 1392 result = null; 1393 } 1394 finally { 1395 localEnv.info.scope.leave(); 1396 } 1397 } 1398 1399 void checkAutoCloseable(DiagnosticPosition pos, Env<AttrContext> env, Type resource) { 1400 if (!resource.isErroneous() && 1401 types.asSuper(resource, syms.autoCloseableType.tsym) != null && 1402 !types.isSameType(resource, syms.autoCloseableType)) { // Don't emit warning for AutoCloseable itself 1403 Symbol close = syms.noSymbol; 1404 Log.DiagnosticHandler discardHandler = new Log.DiscardDiagnosticHandler(log); 1405 try { 1406 close = rs.resolveQualifiedMethod(pos, 1407 env, 1408 resource, 1409 names.close, 1410 List.<Type>nil(), 1411 List.<Type>nil()); 1412 } 1413 finally { 1414 log.popDiagnosticHandler(discardHandler); 1415 } 1416 if (close.kind == MTH && 1417 close.overrides(syms.autoCloseableClose, resource.tsym, types, true) && 1418 chk.isHandled(syms.interruptedExceptionType, types.memberType(resource, close).getThrownTypes()) && 1419 env.info.lint.isEnabled(LintCategory.TRY)) { 1420 log.warning(LintCategory.TRY, pos, "try.resource.throws.interrupted.exc", resource); 1421 } 1422 } 1423 } 1424 1425 public void visitConditional(JCConditional tree) { 1426 Type condtype = attribExpr(tree.cond, env, syms.booleanType); 1427 1428 tree.polyKind = (!allowPoly || 1429 pt().hasTag(NONE) && pt() != Type.recoveryType || 1430 isBooleanOrNumeric(env, tree)) ? 1431 PolyKind.STANDALONE : PolyKind.POLY; 1432 1433 if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) { 1434 //cannot get here (i.e. it means we are returning from void method - which is already an error) 1435 resultInfo.checkContext.report(tree, diags.fragment("conditional.target.cant.be.void")); 1436 result = tree.type = types.createErrorType(resultInfo.pt); 1437 return; 1438 } 1439 1440 ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ? 1441 unknownExprInfo : 1442 resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) { 1443 //this will use enclosing check context to check compatibility of 1444 //subexpression against target type; if we are in a method check context, 1445 //depending on whether boxing is allowed, we could have incompatibilities 1446 @Override 1447 public void report(DiagnosticPosition pos, JCDiagnostic details) { 1448 enclosingContext.report(pos, diags.fragment("incompatible.type.in.conditional", details)); 1449 } 1450 }); 1451 1452 Type truetype = attribTree(tree.truepart, env, condInfo); 1453 Type falsetype = attribTree(tree.falsepart, env, condInfo); 1454 1455 Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(tree, truetype, falsetype) : pt(); 1456 if (condtype.constValue() != null && 1457 truetype.constValue() != null && 1458 falsetype.constValue() != null && 1459 !owntype.hasTag(NONE)) { 1460 //constant folding 1461 owntype = cfolder.coerce(condtype.isTrue() ? truetype : falsetype, owntype); 1462 } 1463 result = check(tree, owntype, KindSelector.VAL, resultInfo); 1464 } 1465 //where 1466 private boolean isBooleanOrNumeric(Env<AttrContext> env, JCExpression tree) { 1467 switch (tree.getTag()) { 1468 case LITERAL: return ((JCLiteral)tree).typetag.isSubRangeOf(DOUBLE) || 1469 ((JCLiteral)tree).typetag == BOOLEAN || 1470 ((JCLiteral)tree).typetag == BOT; 1471 case LAMBDA: case REFERENCE: return false; 1472 case PARENS: return isBooleanOrNumeric(env, ((JCParens)tree).expr); 1473 case CONDEXPR: 1474 JCConditional condTree = (JCConditional)tree; 1475 return isBooleanOrNumeric(env, condTree.truepart) && 1476 isBooleanOrNumeric(env, condTree.falsepart); 1477 case APPLY: 1478 JCMethodInvocation speculativeMethodTree = 1479 (JCMethodInvocation)deferredAttr.attribSpeculative(tree, env, unknownExprInfo); 1480 Symbol msym = TreeInfo.symbol(speculativeMethodTree.meth); 1481 Type receiverType = speculativeMethodTree.meth.hasTag(IDENT) ? 1482 env.enclClass.type : 1483 ((JCFieldAccess)speculativeMethodTree.meth).selected.type; 1484 Type owntype = types.memberType(receiverType, msym).getReturnType(); 1485 return primitiveOrBoxed(owntype); 1486 case NEWCLASS: 1487 JCExpression className = 1488 removeClassParams.translate(((JCNewClass)tree).clazz); 1489 JCExpression speculativeNewClassTree = 1490 (JCExpression)deferredAttr.attribSpeculative(className, env, unknownTypeInfo); 1491 return primitiveOrBoxed(speculativeNewClassTree.type); 1492 default: 1493 Type speculativeType = deferredAttr.attribSpeculative(tree, env, unknownExprInfo).type; 1494 return primitiveOrBoxed(speculativeType); 1495 } 1496 } 1497 //where 1498 boolean primitiveOrBoxed(Type t) { 1499 return (!t.hasTag(TYPEVAR) && types.unboxedTypeOrType(t).isPrimitive()); 1500 } 1501 1502 TreeTranslator removeClassParams = new TreeTranslator() { 1503 @Override 1504 public void visitTypeApply(JCTypeApply tree) { 1505 result = translate(tree.clazz); 1506 } 1507 }; 1508 1509 /** Compute the type of a conditional expression, after 1510 * checking that it exists. See JLS 15.25. Does not take into 1511 * account the special case where condition and both arms 1512 * are constants. 1513 * 1514 * @param pos The source position to be used for error 1515 * diagnostics. 1516 * @param thentype The type of the expression's then-part. 1517 * @param elsetype The type of the expression's else-part. 1518 */ 1519 Type condType(DiagnosticPosition pos, 1520 Type thentype, Type elsetype) { 1521 // If same type, that is the result 1522 if (types.isSameType(thentype, elsetype)) 1523 return thentype.baseType(); 1524 1525 Type thenUnboxed = (thentype.isPrimitive()) 1526 ? thentype : types.unboxedType(thentype); 1527 Type elseUnboxed = (elsetype.isPrimitive()) 1528 ? elsetype : types.unboxedType(elsetype); 1529 1530 // Otherwise, if both arms can be converted to a numeric 1531 // type, return the least numeric type that fits both arms 1532 // (i.e. return larger of the two, or return int if one 1533 // arm is short, the other is char). 1534 if (thenUnboxed.isPrimitive() && elseUnboxed.isPrimitive()) { 1535 // If one arm has an integer subrange type (i.e., byte, 1536 // short, or char), and the other is an integer constant 1537 // that fits into the subrange, return the subrange type. 1538 if (thenUnboxed.getTag().isStrictSubRangeOf(INT) && 1539 elseUnboxed.hasTag(INT) && 1540 types.isAssignable(elseUnboxed, thenUnboxed)) { 1541 return thenUnboxed.baseType(); 1542 } 1543 if (elseUnboxed.getTag().isStrictSubRangeOf(INT) && 1544 thenUnboxed.hasTag(INT) && 1545 types.isAssignable(thenUnboxed, elseUnboxed)) { 1546 return elseUnboxed.baseType(); 1547 } 1548 1549 for (TypeTag tag : primitiveTags) { 1550 Type candidate = syms.typeOfTag[tag.ordinal()]; 1551 if (types.isSubtype(thenUnboxed, candidate) && 1552 types.isSubtype(elseUnboxed, candidate)) { 1553 return candidate; 1554 } 1555 } 1556 } 1557 1558 // Those were all the cases that could result in a primitive 1559 if (thentype.isPrimitive()) 1560 thentype = types.boxedClass(thentype).type; 1561 if (elsetype.isPrimitive()) 1562 elsetype = types.boxedClass(elsetype).type; 1563 1564 if (types.isSubtype(thentype, elsetype)) 1565 return elsetype.baseType(); 1566 if (types.isSubtype(elsetype, thentype)) 1567 return thentype.baseType(); 1568 1569 if (thentype.hasTag(VOID) || elsetype.hasTag(VOID)) { 1570 log.error(pos, "neither.conditional.subtype", 1571 thentype, elsetype); 1572 return thentype.baseType(); 1573 } 1574 1575 // both are known to be reference types. The result is 1576 // lub(thentype,elsetype). This cannot fail, as it will 1577 // always be possible to infer "Object" if nothing better. 1578 return types.lub(thentype.baseType(), elsetype.baseType()); 1579 } 1580 1581 final static TypeTag[] primitiveTags = new TypeTag[]{ 1582 BYTE, 1583 CHAR, 1584 SHORT, 1585 INT, 1586 LONG, 1587 FLOAT, 1588 DOUBLE, 1589 BOOLEAN, 1590 }; 1591 1592 public void visitIf(JCIf tree) { 1593 attribExpr(tree.cond, env, syms.booleanType); 1594 attribStat(tree.thenpart, env); 1595 if (tree.elsepart != null) 1596 attribStat(tree.elsepart, env); 1597 chk.checkEmptyIf(tree); 1598 result = null; 1599 } 1600 1601 public void visitExec(JCExpressionStatement tree) { 1602 //a fresh environment is required for 292 inference to work properly --- 1603 //see Infer.instantiatePolymorphicSignatureInstance() 1604 Env<AttrContext> localEnv = env.dup(tree); 1605 attribExpr(tree.expr, localEnv); 1606 result = null; 1607 } 1608 1609 public void visitBreak(JCBreak tree) { 1610 tree.target = findJumpTarget(tree.pos(), tree.getTag(), tree.label, env); 1611 result = null; 1612 } 1613 1614 public void visitContinue(JCContinue tree) { 1615 tree.target = findJumpTarget(tree.pos(), tree.getTag(), tree.label, env); 1616 result = null; 1617 } 1618 //where 1619 /** Return the target of a break or continue statement, if it exists, 1620 * report an error if not. 1621 * Note: The target of a labelled break or continue is the 1622 * (non-labelled) statement tree referred to by the label, 1623 * not the tree representing the labelled statement itself. 1624 * 1625 * @param pos The position to be used for error diagnostics 1626 * @param tag The tag of the jump statement. This is either 1627 * Tree.BREAK or Tree.CONTINUE. 1628 * @param label The label of the jump statement, or null if no 1629 * label is given. 1630 * @param env The environment current at the jump statement. 1631 */ 1632 private JCTree findJumpTarget(DiagnosticPosition pos, 1633 JCTree.Tag tag, 1634 Name label, 1635 Env<AttrContext> env) { 1636 // Search environments outwards from the point of jump. 1637 Env<AttrContext> env1 = env; 1638 LOOP: 1639 while (env1 != null) { 1640 switch (env1.tree.getTag()) { 1641 case LABELLED: 1642 JCLabeledStatement labelled = (JCLabeledStatement)env1.tree; 1643 if (label == labelled.label) { 1644 // If jump is a continue, check that target is a loop. 1645 if (tag == CONTINUE) { 1646 if (!labelled.body.hasTag(DOLOOP) && 1647 !labelled.body.hasTag(WHILELOOP) && 1648 !labelled.body.hasTag(FORLOOP) && 1649 !labelled.body.hasTag(FOREACHLOOP)) 1650 log.error(pos, "not.loop.label", label); 1651 // Found labelled statement target, now go inwards 1652 // to next non-labelled tree. 1653 return TreeInfo.referencedStatement(labelled); 1654 } else { 1655 return labelled; 1656 } 1657 } 1658 break; 1659 case DOLOOP: 1660 case WHILELOOP: 1661 case FORLOOP: 1662 case FOREACHLOOP: 1663 if (label == null) return env1.tree; 1664 break; 1665 case SWITCH: 1666 if (label == null && tag == BREAK) return env1.tree; 1667 break; 1668 case LAMBDA: 1669 case METHODDEF: 1670 case CLASSDEF: 1671 break LOOP; 1672 default: 1673 } 1674 env1 = env1.next; 1675 } 1676 if (label != null) 1677 log.error(pos, "undef.label", label); 1678 else if (tag == CONTINUE) 1679 log.error(pos, "cont.outside.loop"); 1680 else 1681 log.error(pos, "break.outside.switch.loop"); 1682 return null; 1683 } 1684 1685 public void visitReturn(JCReturn tree) { 1686 // Check that there is an enclosing method which is 1687 // nested within than the enclosing class. 1688 if (env.info.returnResult == null) { 1689 log.error(tree.pos(), "ret.outside.meth"); 1690 } else { 1691 // Attribute return expression, if it exists, and check that 1692 // it conforms to result type of enclosing method. 1693 if (tree.expr != null) { 1694 if (env.info.returnResult.pt.hasTag(VOID)) { 1695 env.info.returnResult.checkContext.report(tree.expr.pos(), 1696 diags.fragment("unexpected.ret.val")); 1697 } 1698 attribTree(tree.expr, env, env.info.returnResult); 1699 } else if (!env.info.returnResult.pt.hasTag(VOID) && 1700 !env.info.returnResult.pt.hasTag(NONE)) { 1701 env.info.returnResult.checkContext.report(tree.pos(), 1702 diags.fragment("missing.ret.val")); 1703 } 1704 } 1705 result = null; 1706 } 1707 1708 public void visitThrow(JCThrow tree) { 1709 Type owntype = attribExpr(tree.expr, env, allowPoly ? Type.noType : syms.throwableType); 1710 if (allowPoly) { 1711 chk.checkType(tree, owntype, syms.throwableType); 1712 } 1713 result = null; 1714 } 1715 1716 public void visitAssert(JCAssert tree) { 1717 attribExpr(tree.cond, env, syms.booleanType); 1718 if (tree.detail != null) { 1719 chk.checkNonVoid(tree.detail.pos(), attribExpr(tree.detail, env)); 1720 } 1721 result = null; 1722 } 1723 1724 /** Visitor method for method invocations. 1725 * NOTE: The method part of an application will have in its type field 1726 * the return type of the method, not the method's type itself! 1727 */ 1728 public void visitApply(JCMethodInvocation tree) { 1729 // The local environment of a method application is 1730 // a new environment nested in the current one. 1731 Env<AttrContext> localEnv = env.dup(tree, env.info.dup()); 1732 1733 // The types of the actual method arguments. 1734 List<Type> argtypes; 1735 1736 // The types of the actual method type arguments. 1737 List<Type> typeargtypes = null; 1738 1739 Name methName = TreeInfo.name(tree.meth); 1740 1741 boolean isConstructorCall = 1742 methName == names._this || methName == names._super; 1743 1744 ListBuffer<Type> argtypesBuf = new ListBuffer<>(); 1745 if (isConstructorCall) { 1746 // We are seeing a ...this(...) or ...super(...) call. 1747 // Check that this is the first statement in a constructor. 1748 if (checkFirstConstructorStat(tree, env)) { 1749 1750 // Record the fact 1751 // that this is a constructor call (using isSelfCall). 1752 localEnv.info.isSelfCall = true; 1753 1754 // Attribute arguments, yielding list of argument types. 1755 KindSelector kind = attribArgs(KindSelector.MTH, tree.args, localEnv, argtypesBuf); 1756 argtypes = argtypesBuf.toList(); 1757 typeargtypes = attribTypes(tree.typeargs, localEnv); 1758 1759 // Variable `site' points to the class in which the called 1760 // constructor is defined. 1761 Type site = env.enclClass.sym.type; 1762 if (methName == names._super) { 1763 if (site == syms.objectType) { 1764 log.error(tree.meth.pos(), "no.superclass", site); 1765 site = types.createErrorType(syms.objectType); 1766 } else { 1767 site = types.supertype(site); 1768 } 1769 } 1770 1771 if (site.hasTag(CLASS)) { 1772 Type encl = site.getEnclosingType(); 1773 while (encl != null && encl.hasTag(TYPEVAR)) 1774 encl = encl.getUpperBound(); 1775 if (encl.hasTag(CLASS)) { 1776 // we are calling a nested class 1777 1778 if (tree.meth.hasTag(SELECT)) { 1779 JCTree qualifier = ((JCFieldAccess) tree.meth).selected; 1780 1781 // We are seeing a prefixed call, of the form 1782 // <expr>.super(...). 1783 // Check that the prefix expression conforms 1784 // to the outer instance type of the class. 1785 chk.checkRefType(qualifier.pos(), 1786 attribExpr(qualifier, localEnv, 1787 encl)); 1788 } else if (methName == names._super) { 1789 // qualifier omitted; check for existence 1790 // of an appropriate implicit qualifier. 1791 rs.resolveImplicitThis(tree.meth.pos(), 1792 localEnv, site, true); 1793 } 1794 } else if (tree.meth.hasTag(SELECT)) { 1795 log.error(tree.meth.pos(), "illegal.qual.not.icls", 1796 site.tsym); 1797 } 1798 1799 // if we're calling a java.lang.Enum constructor, 1800 // prefix the implicit String and int parameters 1801 if (site.tsym == syms.enumSym) 1802 argtypes = argtypes.prepend(syms.intType).prepend(syms.stringType); 1803 1804 // Resolve the called constructor under the assumption 1805 // that we are referring to a superclass instance of the 1806 // current instance (JLS ???). 1807 boolean selectSuperPrev = localEnv.info.selectSuper; 1808 localEnv.info.selectSuper = true; 1809 localEnv.info.pendingResolutionPhase = null; 1810 Symbol sym = rs.resolveConstructor( 1811 tree.meth.pos(), localEnv, site, argtypes, typeargtypes); 1812 localEnv.info.selectSuper = selectSuperPrev; 1813 1814 // Set method symbol to resolved constructor... 1815 TreeInfo.setSymbol(tree.meth, sym); 1816 1817 // ...and check that it is legal in the current context. 1818 // (this will also set the tree's type) 1819 Type mpt = newMethodTemplate(resultInfo.pt, argtypes, typeargtypes); 1820 checkId(tree.meth, site, sym, localEnv, 1821 new ResultInfo(kind, mpt)); 1822 } 1823 // Otherwise, `site' is an error type and we do nothing 1824 } 1825 result = tree.type = syms.voidType; 1826 } else { 1827 // Otherwise, we are seeing a regular method call. 1828 // Attribute the arguments, yielding list of argument types, ... 1829 KindSelector kind = attribArgs(KindSelector.VAL, tree.args, localEnv, argtypesBuf); 1830 argtypes = argtypesBuf.toList(); 1831 typeargtypes = attribAnyTypes(tree.typeargs, localEnv); 1832 1833 // ... and attribute the method using as a prototype a methodtype 1834 // whose formal argument types is exactly the list of actual 1835 // arguments (this will also set the method symbol). 1836 Type mpt = newMethodTemplate(resultInfo.pt, argtypes, typeargtypes); 1837 localEnv.info.pendingResolutionPhase = null; 1838 Type mtype = attribTree(tree.meth, localEnv, new ResultInfo(kind, mpt, resultInfo.checkContext)); 1839 1840 // Compute the result type. 1841 Type restype = mtype.getReturnType(); 1842 if (restype.hasTag(WILDCARD)) 1843 throw new AssertionError(mtype); 1844 1845 Type qualifier = (tree.meth.hasTag(SELECT)) 1846 ? ((JCFieldAccess) tree.meth).selected.type 1847 : env.enclClass.sym.type; 1848 restype = adjustMethodReturnType(qualifier, methName, argtypes, restype); 1849 1850 chk.checkRefTypes(tree.typeargs, typeargtypes); 1851 1852 // Check that value of resulting type is admissible in the 1853 // current context. Also, capture the return type 1854 result = check(tree, capture(restype), KindSelector.VAL, resultInfo); 1855 } 1856 chk.validate(tree.typeargs, localEnv); 1857 } 1858 //where 1859 Type adjustMethodReturnType(Type qualifierType, Name methodName, List<Type> argtypes, Type restype) { 1860 if (methodName == names.clone && types.isArray(qualifierType)) { 1861 // as a special case, array.clone() has a result that is 1862 // the same as static type of the array being cloned 1863 return qualifierType; 1864 } else if (methodName == names.getClass && argtypes.isEmpty()) { 1865 // as a special case, x.getClass() has type Class<? extends |X|> 1866 return new ClassType(restype.getEnclosingType(), 1867 List.<Type>of(new WildcardType(types.erasure(qualifierType), 1868 BoundKind.EXTENDS, 1869 syms.boundClass)), 1870 restype.tsym, 1871 restype.getMetadata()); 1872 } else { 1873 return restype; 1874 } 1875 } 1876 1877 /** Check that given application node appears as first statement 1878 * in a constructor call. 1879 * @param tree The application node 1880 * @param env The environment current at the application. 1881 */ 1882 boolean checkFirstConstructorStat(JCMethodInvocation tree, Env<AttrContext> env) { 1883 JCMethodDecl enclMethod = env.enclMethod; 1884 if (enclMethod != null && enclMethod.name == names.init) { 1885 JCBlock body = enclMethod.body; 1886 if (body.stats.head.hasTag(EXEC) && 1887 ((JCExpressionStatement) body.stats.head).expr == tree) 1888 return true; 1889 } 1890 log.error(tree.pos(),"call.must.be.first.stmt.in.ctor", 1891 TreeInfo.name(tree.meth)); 1892 return false; 1893 } 1894 1895 /** Obtain a method type with given argument types. 1896 */ 1897 Type newMethodTemplate(Type restype, List<Type> argtypes, List<Type> typeargtypes) { 1898 MethodType mt = new MethodType(argtypes, restype, List.<Type>nil(), syms.methodClass); 1899 return (typeargtypes == null) ? mt : (Type)new ForAll(typeargtypes, mt); 1900 } 1901 1902 public void visitNewClass(final JCNewClass tree) { 1903 Type owntype = types.createErrorType(tree.type); 1904 1905 // The local environment of a class creation is 1906 // a new environment nested in the current one. 1907 Env<AttrContext> localEnv = env.dup(tree, env.info.dup()); 1908 1909 // The anonymous inner class definition of the new expression, 1910 // if one is defined by it. 1911 JCClassDecl cdef = tree.def; 1912 1913 // If enclosing class is given, attribute it, and 1914 // complete class name to be fully qualified 1915 JCExpression clazz = tree.clazz; // Class field following new 1916 JCExpression clazzid; // Identifier in class field 1917 JCAnnotatedType annoclazzid; // Annotated type enclosing clazzid 1918 annoclazzid = null; 1919 1920 if (clazz.hasTag(TYPEAPPLY)) { 1921 clazzid = ((JCTypeApply) clazz).clazz; 1922 if (clazzid.hasTag(ANNOTATED_TYPE)) { 1923 annoclazzid = (JCAnnotatedType) clazzid; 1924 clazzid = annoclazzid.underlyingType; 1925 } 1926 } else { 1927 if (clazz.hasTag(ANNOTATED_TYPE)) { 1928 annoclazzid = (JCAnnotatedType) clazz; 1929 clazzid = annoclazzid.underlyingType; 1930 } else { 1931 clazzid = clazz; 1932 } 1933 } 1934 1935 JCExpression clazzid1 = clazzid; // The same in fully qualified form 1936 1937 if (tree.encl != null) { 1938 // We are seeing a qualified new, of the form 1939 // <expr>.new C <...> (...) ... 1940 // In this case, we let clazz stand for the name of the 1941 // allocated class C prefixed with the type of the qualifier 1942 // expression, so that we can 1943 // resolve it with standard techniques later. I.e., if 1944 // <expr> has type T, then <expr>.new C <...> (...) 1945 // yields a clazz T.C. 1946 Type encltype = chk.checkRefType(tree.encl.pos(), 1947 attribExpr(tree.encl, env)); 1948 // TODO 308: in <expr>.new C, do we also want to add the type annotations 1949 // from expr to the combined type, or not? Yes, do this. 1950 clazzid1 = make.at(clazz.pos).Select(make.Type(encltype), 1951 ((JCIdent) clazzid).name); 1952 1953 EndPosTable endPosTable = this.env.toplevel.endPositions; 1954 endPosTable.storeEnd(clazzid1, tree.getEndPosition(endPosTable)); 1955 if (clazz.hasTag(ANNOTATED_TYPE)) { 1956 JCAnnotatedType annoType = (JCAnnotatedType) clazz; 1957 List<JCAnnotation> annos = annoType.annotations; 1958 1959 if (annoType.underlyingType.hasTag(TYPEAPPLY)) { 1960 clazzid1 = make.at(tree.pos). 1961 TypeApply(clazzid1, 1962 ((JCTypeApply) clazz).arguments); 1963 } 1964 1965 clazzid1 = make.at(tree.pos). 1966 AnnotatedType(annos, clazzid1); 1967 } else if (clazz.hasTag(TYPEAPPLY)) { 1968 clazzid1 = make.at(tree.pos). 1969 TypeApply(clazzid1, 1970 ((JCTypeApply) clazz).arguments); 1971 } 1972 1973 clazz = clazzid1; 1974 } 1975 1976 // Attribute clazz expression and store 1977 // symbol + type back into the attributed tree. 1978 Type clazztype; 1979 1980 try { 1981 env.info.isNewClass = true; 1982 clazztype = TreeInfo.isEnumInit(env.tree) ? 1983 attribIdentAsEnumType(env, (JCIdent)clazz) : 1984 attribType(clazz, env); 1985 } finally { 1986 env.info.isNewClass = false; 1987 } 1988 1989 clazztype = chk.checkDiamond(tree, clazztype); 1990 chk.validate(clazz, localEnv); 1991 if (tree.encl != null) { 1992 // We have to work in this case to store 1993 // symbol + type back into the attributed tree. 1994 tree.clazz.type = clazztype; 1995 TreeInfo.setSymbol(clazzid, TreeInfo.symbol(clazzid1)); 1996 clazzid.type = ((JCIdent) clazzid).sym.type; 1997 if (annoclazzid != null) { 1998 annoclazzid.type = clazzid.type; 1999 } 2000 if (!clazztype.isErroneous()) { 2001 if (cdef != null && clazztype.tsym.isInterface()) { 2002 log.error(tree.encl.pos(), "anon.class.impl.intf.no.qual.for.new"); 2003 } else if (clazztype.tsym.isStatic()) { 2004 log.error(tree.encl.pos(), "qualified.new.of.static.class", clazztype.tsym); 2005 } 2006 } 2007 } else if (!clazztype.tsym.isInterface() && 2008 clazztype.getEnclosingType().hasTag(CLASS)) { 2009 // Check for the existence of an apropos outer instance 2010 rs.resolveImplicitThis(tree.pos(), env, clazztype); 2011 } 2012 2013 // Attribute constructor arguments. 2014 ListBuffer<Type> argtypesBuf = new ListBuffer<>(); 2015 final KindSelector pkind = 2016 attribArgs(KindSelector.VAL, tree.args, localEnv, argtypesBuf); 2017 List<Type> argtypes = argtypesBuf.toList(); 2018 List<Type> typeargtypes = attribTypes(tree.typeargs, localEnv); 2019 2020 // If we have made no mistakes in the class type... 2021 if (clazztype.hasTag(CLASS)) { 2022 // Enums may not be instantiated except implicitly 2023 if ((clazztype.tsym.flags_field & Flags.ENUM) != 0 && 2024 (!env.tree.hasTag(VARDEF) || 2025 (((JCVariableDecl) env.tree).mods.flags & Flags.ENUM) == 0 || 2026 ((JCVariableDecl) env.tree).init != tree)) 2027 log.error(tree.pos(), "enum.cant.be.instantiated"); 2028 2029 boolean isSpeculativeDiamondInferenceRound = TreeInfo.isDiamond(tree) && 2030 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE; 2031 boolean skipNonDiamondPath = false; 2032 // Check that class is not abstract 2033 if (cdef == null && !isSpeculativeDiamondInferenceRound && // class body may be nulled out in speculative tree copy 2034 (clazztype.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) { 2035 log.error(tree.pos(), "abstract.cant.be.instantiated", 2036 clazztype.tsym); 2037 skipNonDiamondPath = true; 2038 } else if (cdef != null && clazztype.tsym.isInterface()) { 2039 // Check that no constructor arguments are given to 2040 // anonymous classes implementing an interface 2041 if (!argtypes.isEmpty()) 2042 log.error(tree.args.head.pos(), "anon.class.impl.intf.no.args"); 2043 2044 if (!typeargtypes.isEmpty()) 2045 log.error(tree.typeargs.head.pos(), "anon.class.impl.intf.no.typeargs"); 2046 2047 // Error recovery: pretend no arguments were supplied. 2048 argtypes = List.nil(); 2049 typeargtypes = List.nil(); 2050 skipNonDiamondPath = true; 2051 } 2052 if (TreeInfo.isDiamond(tree)) { 2053 ClassType site = new ClassType(clazztype.getEnclosingType(), 2054 clazztype.tsym.type.getTypeArguments(), 2055 clazztype.tsym, 2056 clazztype.getMetadata()); 2057 2058 Env<AttrContext> diamondEnv = localEnv.dup(tree); 2059 diamondEnv.info.selectSuper = cdef != null; 2060 diamondEnv.info.pendingResolutionPhase = null; 2061 2062 //if the type of the instance creation expression is a class type 2063 //apply method resolution inference (JLS 15.12.2.7). The return type 2064 //of the resolved constructor will be a partially instantiated type 2065 Symbol constructor = rs.resolveDiamond(tree.pos(), 2066 diamondEnv, 2067 site, 2068 argtypes, 2069 typeargtypes); 2070 tree.constructor = constructor.baseSymbol(); 2071 2072 final TypeSymbol csym = clazztype.tsym; 2073 ResultInfo diamondResult = new ResultInfo(pkind, newMethodTemplate(resultInfo.pt, argtypes, typeargtypes), new Check.NestedCheckContext(resultInfo.checkContext) { 2074 @Override 2075 public void report(DiagnosticPosition _unused, JCDiagnostic details) { 2076 enclosingContext.report(tree.clazz, 2077 diags.fragment("cant.apply.diamond.1", diags.fragment("diamond", csym), details)); 2078 } 2079 }, CheckMode.NO_TREE_UPDATE); 2080 Type constructorType = tree.constructorType = types.createErrorType(clazztype); 2081 constructorType = checkId(tree, site, 2082 constructor, 2083 diamondEnv, 2084 diamondResult); 2085 2086 tree.clazz.type = types.createErrorType(clazztype); 2087 if (!constructorType.isErroneous()) { 2088 tree.clazz.type = clazz.type = constructorType.getReturnType(); 2089 tree.constructorType = types.createMethodTypeWithReturn(constructorType, syms.voidType); 2090 } 2091 clazztype = chk.checkClassType(tree.clazz, tree.clazz.type, true); 2092 } 2093 2094 // Resolve the called constructor under the assumption 2095 // that we are referring to a superclass instance of the 2096 // current instance (JLS ???). 2097 else if (!skipNonDiamondPath) { 2098 //the following code alters some of the fields in the current 2099 //AttrContext - hence, the current context must be dup'ed in 2100 //order to avoid downstream failures 2101 Env<AttrContext> rsEnv = localEnv.dup(tree); 2102 rsEnv.info.selectSuper = cdef != null; 2103 rsEnv.info.pendingResolutionPhase = null; 2104 tree.constructor = rs.resolveConstructor( 2105 tree.pos(), rsEnv, clazztype, argtypes, typeargtypes); 2106 if (cdef == null) { //do not check twice! 2107 tree.constructorType = checkId(tree, 2108 clazztype, 2109 tree.constructor, 2110 rsEnv, 2111 new ResultInfo(pkind, newMethodTemplate(syms.voidType, argtypes, typeargtypes), CheckMode.NO_TREE_UPDATE)); 2112 if (rsEnv.info.lastResolveVarargs()) 2113 Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null); 2114 } 2115 } 2116 2117 if (cdef != null) { 2118 visitAnonymousClassDefinition(tree, clazz, clazztype, cdef, localEnv, argtypes, typeargtypes, pkind); 2119 return; 2120 } 2121 2122 if (tree.constructor != null && tree.constructor.kind == MTH) 2123 owntype = clazztype; 2124 } 2125 result = check(tree, owntype, KindSelector.VAL, resultInfo); 2126 InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext(); 2127 if (tree.constructorType != null && inferenceContext.free(tree.constructorType)) { 2128 //we need to wait for inference to finish and then replace inference vars in the constructor type 2129 inferenceContext.addFreeTypeListener(List.of(tree.constructorType), 2130 instantiatedContext -> { 2131 tree.constructorType = instantiatedContext.asInstType(tree.constructorType); 2132 }); 2133 } 2134 chk.validate(tree.typeargs, localEnv); 2135 } 2136 2137 // where 2138 private void visitAnonymousClassDefinition(JCNewClass tree, JCExpression clazz, Type clazztype, 2139 JCClassDecl cdef, Env<AttrContext> localEnv, 2140 List<Type> argtypes, List<Type> typeargtypes, 2141 KindSelector pkind) { 2142 // We are seeing an anonymous class instance creation. 2143 // In this case, the class instance creation 2144 // expression 2145 // 2146 // E.new <typeargs1>C<typargs2>(args) { ... } 2147 // 2148 // is represented internally as 2149 // 2150 // E . new <typeargs1>C<typargs2>(args) ( class <empty-name> { ... } ) . 2151 // 2152 // This expression is then *transformed* as follows: 2153 // 2154 // (1) add an extends or implements clause 2155 // (2) add a constructor. 2156 // 2157 // For instance, if C is a class, and ET is the type of E, 2158 // the expression 2159 // 2160 // E.new <typeargs1>C<typargs2>(args) { ... } 2161 // 2162 // is translated to (where X is a fresh name and typarams is the 2163 // parameter list of the super constructor): 2164 // 2165 // new <typeargs1>X(<*nullchk*>E, args) where 2166 // X extends C<typargs2> { 2167 // <typarams> X(ET e, args) { 2168 // e.<typeargs1>super(args) 2169 // } 2170 // ... 2171 // } 2172 InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext(); 2173 final boolean isDiamond = TreeInfo.isDiamond(tree); 2174 if (isDiamond 2175 && ((tree.constructorType != null && inferenceContext.free(tree.constructorType)) 2176 || (tree.clazz.type != null && inferenceContext.free(tree.clazz.type)))) { 2177 final ResultInfo resultInfoForClassDefinition = this.resultInfo; 2178 inferenceContext.addFreeTypeListener(List.of(tree.constructorType, tree.clazz.type), 2179 instantiatedContext -> { 2180 tree.constructorType = instantiatedContext.asInstType(tree.constructorType); 2181 clazz.type = instantiatedContext.asInstType(clazz.type); 2182 ResultInfo prevResult = this.resultInfo; 2183 try { 2184 this.resultInfo = resultInfoForClassDefinition; 2185 visitAnonymousClassDefinition(tree, clazz, clazz.type, cdef, 2186 localEnv, argtypes, typeargtypes, pkind); 2187 } finally { 2188 this.resultInfo = prevResult; 2189 } 2190 }); 2191 } else { 2192 if (isDiamond && clazztype.hasTag(CLASS)) { 2193 List<Type> invalidDiamondArgs = chk.checkDiamondDenotable((ClassType)clazztype); 2194 if (!clazztype.isErroneous() && invalidDiamondArgs.nonEmpty()) { 2195 // One or more types inferred in the previous steps is non-denotable. 2196 Fragment fragment = Diamond(clazztype.tsym); 2197 log.error(tree.clazz.pos(), 2198 Errors.CantApplyDiamond1( 2199 fragment, 2200 invalidDiamondArgs.size() > 1 ? 2201 DiamondInvalidArgs(invalidDiamondArgs, fragment) : 2202 DiamondInvalidArg(invalidDiamondArgs, fragment))); 2203 } 2204 // For <>(){}, inferred types must also be accessible. 2205 for (Type t : clazztype.getTypeArguments()) { 2206 rs.checkAccessibleType(env, t); 2207 } 2208 } 2209 2210 // If we already errored, be careful to avoid a further avalanche. ErrorType answers 2211 // false for isInterface call even when the original type is an interface. 2212 boolean implementing = clazztype.tsym.isInterface() || 2213 clazztype.isErroneous() && clazztype.getOriginalType().tsym.isInterface(); 2214 2215 if (implementing) { 2216 cdef.implementing = List.of(clazz); 2217 } else { 2218 cdef.extending = clazz; 2219 } 2220 2221 if (resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK && 2222 isSerializable(clazztype)) { 2223 localEnv.info.isSerializable = true; 2224 } 2225 2226 attribStat(cdef, localEnv); 2227 2228 List<Type> finalargtypes; 2229 // If an outer instance is given, 2230 // prefix it to the constructor arguments 2231 // and delete it from the new expression 2232 if (tree.encl != null && !clazztype.tsym.isInterface()) { 2233 tree.args = tree.args.prepend(makeNullCheck(tree.encl)); 2234 finalargtypes = argtypes.prepend(tree.encl.type); 2235 tree.encl = null; 2236 } else { 2237 finalargtypes = argtypes; 2238 } 2239 2240 // Reassign clazztype and recompute constructor. As this necessarily involves 2241 // another attribution pass for deferred types in the case of <>, replicate 2242 // them. Original arguments have right decorations already. 2243 if (isDiamond && pkind.contains(KindSelector.POLY)) { 2244 finalargtypes = finalargtypes.map(deferredAttr.deferredCopier); 2245 } 2246 2247 clazztype = cdef.sym.type; 2248 Symbol sym = tree.constructor = rs.resolveConstructor( 2249 tree.pos(), localEnv, clazztype, finalargtypes, typeargtypes); 2250 Assert.check(!sym.kind.isResolutionError()); 2251 tree.constructor = sym; 2252 tree.constructorType = checkId(tree, 2253 clazztype, 2254 tree.constructor, 2255 localEnv, 2256 new ResultInfo(pkind, newMethodTemplate(syms.voidType, finalargtypes, typeargtypes), CheckMode.NO_TREE_UPDATE)); 2257 } 2258 Type owntype = (tree.constructor != null && tree.constructor.kind == MTH) ? 2259 clazztype : types.createErrorType(tree.type); 2260 result = check(tree, owntype, KindSelector.VAL, resultInfo.dup(CheckMode.NO_INFERENCE_HOOK)); 2261 chk.validate(tree.typeargs, localEnv); 2262 } 2263 2264 /** Make an attributed null check tree. 2265 */ 2266 public JCExpression makeNullCheck(JCExpression arg) { 2267 // optimization: X.this is never null; skip null check 2268 Name name = TreeInfo.name(arg); 2269 if (name == names._this || name == names._super) return arg; 2270 2271 JCTree.Tag optag = NULLCHK; 2272 JCUnary tree = make.at(arg.pos).Unary(optag, arg); 2273 tree.operator = operators.resolveUnary(arg, optag, arg.type); 2274 tree.type = arg.type; 2275 return tree; 2276 } 2277 2278 public void visitNewArray(JCNewArray tree) { 2279 Type owntype = types.createErrorType(tree.type); 2280 Env<AttrContext> localEnv = env.dup(tree); 2281 Type elemtype; 2282 if (tree.elemtype != null) { 2283 elemtype = attribType(tree.elemtype, localEnv); 2284 chk.validate(tree.elemtype, localEnv); 2285 owntype = elemtype; 2286 for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) { 2287 attribExpr(l.head, localEnv, syms.intType); 2288 owntype = new ArrayType(owntype, syms.arrayClass); 2289 } 2290 } else { 2291 // we are seeing an untyped aggregate { ... } 2292 // this is allowed only if the prototype is an array 2293 if (pt().hasTag(ARRAY)) { 2294 elemtype = types.elemtype(pt()); 2295 } else { 2296 if (!pt().hasTag(ERROR)) { 2297 log.error(tree.pos(), "illegal.initializer.for.type", 2298 pt()); 2299 } 2300 elemtype = types.createErrorType(pt()); 2301 } 2302 } 2303 if (tree.elems != null) { 2304 attribExprs(tree.elems, localEnv, elemtype); 2305 owntype = new ArrayType(elemtype, syms.arrayClass); 2306 } 2307 if (!types.isReifiable(elemtype)) 2308 log.error(tree.pos(), "generic.array.creation"); 2309 result = check(tree, owntype, KindSelector.VAL, resultInfo); 2310 } 2311 2312 /* 2313 * A lambda expression can only be attributed when a target-type is available. 2314 * In addition, if the target-type is that of a functional interface whose 2315 * descriptor contains inference variables in argument position the lambda expression 2316 * is 'stuck' (see DeferredAttr). 2317 */ 2318 @Override 2319 public void visitLambda(final JCLambda that) { 2320 if (pt().isErroneous() || (pt().hasTag(NONE) && pt() != Type.recoveryType)) { 2321 if (pt().hasTag(NONE)) { 2322 //lambda only allowed in assignment or method invocation/cast context 2323 log.error(that.pos(), "unexpected.lambda"); 2324 } 2325 result = that.type = types.createErrorType(pt()); 2326 return; 2327 } 2328 //create an environment for attribution of the lambda expression 2329 final Env<AttrContext> localEnv = lambdaEnv(that, env); 2330 boolean needsRecovery = 2331 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK; 2332 try { 2333 Type currentTarget = pt(); 2334 if (needsRecovery && isSerializable(currentTarget)) { 2335 localEnv.info.isSerializable = true; 2336 } 2337 List<Type> explicitParamTypes = null; 2338 if (that.paramKind == JCLambda.ParameterKind.EXPLICIT) { 2339 //attribute lambda parameters 2340 attribStats(that.params, localEnv); 2341 explicitParamTypes = TreeInfo.types(that.params); 2342 } 2343 2344 Type lambdaType; 2345 if (pt() != Type.recoveryType) { 2346 /* We need to adjust the target. If the target is an 2347 * intersection type, for example: SAM & I1 & I2 ... 2348 * the target will be updated to SAM 2349 */ 2350 currentTarget = targetChecker.visit(currentTarget, that); 2351 if (explicitParamTypes != null) { 2352 currentTarget = infer.instantiateFunctionalInterface(that, 2353 currentTarget, explicitParamTypes, resultInfo.checkContext); 2354 } 2355 currentTarget = types.removeWildcards(currentTarget); 2356 lambdaType = types.findDescriptorType(currentTarget); 2357 } else { 2358 currentTarget = Type.recoveryType; 2359 lambdaType = fallbackDescriptorType(that); 2360 } 2361 2362 setFunctionalInfo(localEnv, that, pt(), lambdaType, currentTarget, resultInfo.checkContext); 2363 2364 if (lambdaType.hasTag(FORALL)) { 2365 //lambda expression target desc cannot be a generic method 2366 resultInfo.checkContext.report(that, diags.fragment("invalid.generic.lambda.target", 2367 lambdaType, kindName(currentTarget.tsym), currentTarget.tsym)); 2368 result = that.type = types.createErrorType(pt()); 2369 return; 2370 } 2371 2372 if (that.paramKind == JCLambda.ParameterKind.IMPLICIT) { 2373 //add param type info in the AST 2374 List<Type> actuals = lambdaType.getParameterTypes(); 2375 List<JCVariableDecl> params = that.params; 2376 2377 boolean arityMismatch = false; 2378 2379 while (params.nonEmpty()) { 2380 if (actuals.isEmpty()) { 2381 //not enough actuals to perform lambda parameter inference 2382 arityMismatch = true; 2383 } 2384 //reset previously set info 2385 Type argType = arityMismatch ? 2386 syms.errType : 2387 actuals.head; 2388 params.head.vartype = make.at(params.head).Type(argType); 2389 params.head.sym = null; 2390 actuals = actuals.isEmpty() ? 2391 actuals : 2392 actuals.tail; 2393 params = params.tail; 2394 } 2395 2396 //attribute lambda parameters 2397 attribStats(that.params, localEnv); 2398 2399 if (arityMismatch) { 2400 resultInfo.checkContext.report(that, diags.fragment("incompatible.arg.types.in.lambda")); 2401 result = that.type = types.createErrorType(currentTarget); 2402 return; 2403 } 2404 } 2405 2406 //from this point on, no recovery is needed; if we are in assignment context 2407 //we will be able to attribute the whole lambda body, regardless of errors; 2408 //if we are in a 'check' method context, and the lambda is not compatible 2409 //with the target-type, it will be recovered anyway in Attr.checkId 2410 needsRecovery = false; 2411 2412 FunctionalReturnContext funcContext = that.getBodyKind() == JCLambda.BodyKind.EXPRESSION ? 2413 new ExpressionLambdaReturnContext((JCExpression)that.getBody(), resultInfo.checkContext) : 2414 new FunctionalReturnContext(resultInfo.checkContext); 2415 2416 ResultInfo bodyResultInfo = lambdaType.getReturnType() == Type.recoveryType ? 2417 recoveryInfo : 2418 new ResultInfo(KindSelector.VAL, 2419 lambdaType.getReturnType(), funcContext); 2420 localEnv.info.returnResult = bodyResultInfo; 2421 2422 if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) { 2423 attribTree(that.getBody(), localEnv, bodyResultInfo); 2424 } else { 2425 JCBlock body = (JCBlock)that.body; 2426 attribStats(body.stats, localEnv); 2427 } 2428 2429 result = check(that, currentTarget, KindSelector.VAL, resultInfo); 2430 2431 boolean isSpeculativeRound = 2432 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE; 2433 2434 preFlow(that); 2435 flow.analyzeLambda(env, that, make, isSpeculativeRound); 2436 2437 that.type = currentTarget; //avoids recovery at this stage 2438 checkLambdaCompatible(that, lambdaType, resultInfo.checkContext); 2439 2440 if (!isSpeculativeRound) { 2441 //add thrown types as bounds to the thrown types free variables if needed: 2442 if (resultInfo.checkContext.inferenceContext().free(lambdaType.getThrownTypes())) { 2443 List<Type> inferredThrownTypes = flow.analyzeLambdaThrownTypes(env, that, make); 2444 List<Type> thrownTypes = resultInfo.checkContext.inferenceContext().asUndetVars(lambdaType.getThrownTypes()); 2445 2446 chk.unhandled(inferredThrownTypes, thrownTypes); 2447 } 2448 2449 checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), lambdaType, currentTarget); 2450 } 2451 result = check(that, currentTarget, KindSelector.VAL, resultInfo); 2452 } catch (Types.FunctionDescriptorLookupError ex) { 2453 JCDiagnostic cause = ex.getDiagnostic(); 2454 resultInfo.checkContext.report(that, cause); 2455 result = that.type = types.createErrorType(pt()); 2456 return; 2457 } catch (Throwable t) { 2458 //when an unexpected exception happens, avoid attempts to attribute the same tree again 2459 //as that would likely cause the same exception again. 2460 needsRecovery = false; 2461 throw t; 2462 } finally { 2463 localEnv.info.scope.leave(); 2464 if (needsRecovery) { 2465 attribTree(that, env, recoveryInfo); 2466 } 2467 } 2468 } 2469 //where 2470 void preFlow(JCLambda tree) { 2471 new PostAttrAnalyzer() { 2472 @Override 2473 public void scan(JCTree tree) { 2474 if (tree == null || 2475 (tree.type != null && 2476 tree.type == Type.stuckType)) { 2477 //don't touch stuck expressions! 2478 return; 2479 } 2480 super.scan(tree); 2481 } 2482 }.scan(tree); 2483 } 2484 2485 Types.MapVisitor<DiagnosticPosition> targetChecker = new Types.MapVisitor<DiagnosticPosition>() { 2486 2487 @Override 2488 public Type visitClassType(ClassType t, DiagnosticPosition pos) { 2489 return t.isIntersection() ? 2490 visitIntersectionClassType((IntersectionClassType)t, pos) : t; 2491 } 2492 2493 public Type visitIntersectionClassType(IntersectionClassType ict, DiagnosticPosition pos) { 2494 Symbol desc = types.findDescriptorSymbol(makeNotionalInterface(ict)); 2495 Type target = null; 2496 for (Type bound : ict.getExplicitComponents()) { 2497 TypeSymbol boundSym = bound.tsym; 2498 if (types.isFunctionalInterface(boundSym) && 2499 types.findDescriptorSymbol(boundSym) == desc) { 2500 target = bound; 2501 } else if (!boundSym.isInterface() || (boundSym.flags() & ANNOTATION) != 0) { 2502 //bound must be an interface 2503 reportIntersectionError(pos, "not.an.intf.component", boundSym); 2504 } 2505 } 2506 return target != null ? 2507 target : 2508 ict.getExplicitComponents().head; //error recovery 2509 } 2510 2511 private TypeSymbol makeNotionalInterface(IntersectionClassType ict) { 2512 ListBuffer<Type> targs = new ListBuffer<>(); 2513 ListBuffer<Type> supertypes = new ListBuffer<>(); 2514 for (Type i : ict.interfaces_field) { 2515 if (i.isParameterized()) { 2516 targs.appendList(i.tsym.type.allparams()); 2517 } 2518 supertypes.append(i.tsym.type); 2519 } 2520 IntersectionClassType notionalIntf = types.makeIntersectionType(supertypes.toList()); 2521 notionalIntf.allparams_field = targs.toList(); 2522 notionalIntf.tsym.flags_field |= INTERFACE; 2523 return notionalIntf.tsym; 2524 } 2525 2526 private void reportIntersectionError(DiagnosticPosition pos, String key, Object... args) { 2527 resultInfo.checkContext.report(pos, diags.fragment("bad.intersection.target.for.functional.expr", 2528 diags.fragment(key, args))); 2529 } 2530 }; 2531 2532 private Type fallbackDescriptorType(JCExpression tree) { 2533 switch (tree.getTag()) { 2534 case LAMBDA: 2535 JCLambda lambda = (JCLambda)tree; 2536 List<Type> argtypes = List.nil(); 2537 for (JCVariableDecl param : lambda.params) { 2538 argtypes = param.vartype != null ? 2539 argtypes.append(param.vartype.type) : 2540 argtypes.append(syms.errType); 2541 } 2542 return new MethodType(argtypes, Type.recoveryType, 2543 List.of(syms.throwableType), syms.methodClass); 2544 case REFERENCE: 2545 return new MethodType(List.<Type>nil(), Type.recoveryType, 2546 List.of(syms.throwableType), syms.methodClass); 2547 default: 2548 Assert.error("Cannot get here!"); 2549 } 2550 return null; 2551 } 2552 2553 private void checkAccessibleTypes(final DiagnosticPosition pos, final Env<AttrContext> env, 2554 final InferenceContext inferenceContext, final Type... ts) { 2555 checkAccessibleTypes(pos, env, inferenceContext, List.from(ts)); 2556 } 2557 2558 private void checkAccessibleTypes(final DiagnosticPosition pos, final Env<AttrContext> env, 2559 final InferenceContext inferenceContext, final List<Type> ts) { 2560 if (inferenceContext.free(ts)) { 2561 inferenceContext.addFreeTypeListener(ts, new FreeTypeListener() { 2562 @Override 2563 public void typesInferred(InferenceContext inferenceContext) { 2564 checkAccessibleTypes(pos, env, inferenceContext, inferenceContext.asInstTypes(ts)); 2565 } 2566 }); 2567 } else { 2568 for (Type t : ts) { 2569 rs.checkAccessibleType(env, t); 2570 } 2571 } 2572 } 2573 2574 /** 2575 * Lambda/method reference have a special check context that ensures 2576 * that i.e. a lambda return type is compatible with the expected 2577 * type according to both the inherited context and the assignment 2578 * context. 2579 */ 2580 class FunctionalReturnContext extends Check.NestedCheckContext { 2581 2582 FunctionalReturnContext(CheckContext enclosingContext) { 2583 super(enclosingContext); 2584 } 2585 2586 @Override 2587 public boolean compatible(Type found, Type req, Warner warn) { 2588 //return type must be compatible in both current context and assignment context 2589 return chk.basicHandler.compatible(found, inferenceContext().asUndetVar(req), warn); 2590 } 2591 2592 @Override 2593 public void report(DiagnosticPosition pos, JCDiagnostic details) { 2594 enclosingContext.report(pos, diags.fragment("incompatible.ret.type.in.lambda", details)); 2595 } 2596 } 2597 2598 class ExpressionLambdaReturnContext extends FunctionalReturnContext { 2599 2600 JCExpression expr; 2601 2602 ExpressionLambdaReturnContext(JCExpression expr, CheckContext enclosingContext) { 2603 super(enclosingContext); 2604 this.expr = expr; 2605 } 2606 2607 @Override 2608 public boolean compatible(Type found, Type req, Warner warn) { 2609 //a void return is compatible with an expression statement lambda 2610 return TreeInfo.isExpressionStatement(expr) && req.hasTag(VOID) || 2611 super.compatible(found, req, warn); 2612 } 2613 } 2614 2615 /** 2616 * Lambda compatibility. Check that given return types, thrown types, parameter types 2617 * are compatible with the expected functional interface descriptor. This means that: 2618 * (i) parameter types must be identical to those of the target descriptor; (ii) return 2619 * types must be compatible with the return type of the expected descriptor. 2620 */ 2621 private void checkLambdaCompatible(JCLambda tree, Type descriptor, CheckContext checkContext) { 2622 Type returnType = checkContext.inferenceContext().asUndetVar(descriptor.getReturnType()); 2623 2624 //return values have already been checked - but if lambda has no return 2625 //values, we must ensure that void/value compatibility is correct; 2626 //this amounts at checking that, if a lambda body can complete normally, 2627 //the descriptor's return type must be void 2628 if (tree.getBodyKind() == JCLambda.BodyKind.STATEMENT && tree.canCompleteNormally && 2629 !returnType.hasTag(VOID) && returnType != Type.recoveryType) { 2630 checkContext.report(tree, diags.fragment("incompatible.ret.type.in.lambda", 2631 diags.fragment("missing.ret.val", returnType))); 2632 } 2633 2634 List<Type> argTypes = checkContext.inferenceContext().asUndetVars(descriptor.getParameterTypes()); 2635 if (!types.isSameTypes(argTypes, TreeInfo.types(tree.params))) { 2636 checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda")); 2637 } 2638 } 2639 2640 /* Map to hold 'fake' clinit methods. If a lambda is used to initialize a 2641 * static field and that lambda has type annotations, these annotations will 2642 * also be stored at these fake clinit methods. 2643 * 2644 * LambdaToMethod also use fake clinit methods so they can be reused. 2645 * Also as LTM is a phase subsequent to attribution, the methods from 2646 * clinits can be safely removed by LTM to save memory. 2647 */ 2648 private Map<ClassSymbol, MethodSymbol> clinits = new HashMap<>(); 2649 2650 public MethodSymbol removeClinit(ClassSymbol sym) { 2651 return clinits.remove(sym); 2652 } 2653 2654 /* This method returns an environment to be used to attribute a lambda 2655 * expression. 2656 * 2657 * The owner of this environment is a method symbol. If the current owner 2658 * is not a method, for example if the lambda is used to initialize 2659 * a field, then if the field is: 2660 * 2661 * - an instance field, we use the first constructor. 2662 * - a static field, we create a fake clinit method. 2663 */ 2664 public Env<AttrContext> lambdaEnv(JCLambda that, Env<AttrContext> env) { 2665 Env<AttrContext> lambdaEnv; 2666 Symbol owner = env.info.scope.owner; 2667 if (owner.kind == VAR && owner.owner.kind == TYP) { 2668 //field initializer 2669 ClassSymbol enclClass = owner.enclClass(); 2670 Symbol newScopeOwner = env.info.scope.owner; 2671 /* if the field isn't static, then we can get the first constructor 2672 * and use it as the owner of the environment. This is what 2673 * LTM code is doing to look for type annotations so we are fine. 2674 */ 2675 if ((owner.flags() & STATIC) == 0) { 2676 for (Symbol s : enclClass.members_field.getSymbolsByName(names.init)) { 2677 newScopeOwner = s; 2678 break; 2679 } 2680 } else { 2681 /* if the field is static then we need to create a fake clinit 2682 * method, this method can later be reused by LTM. 2683 */ 2684 MethodSymbol clinit = clinits.get(enclClass); 2685 if (clinit == null) { 2686 Type clinitType = new MethodType(List.<Type>nil(), 2687 syms.voidType, List.<Type>nil(), syms.methodClass); 2688 clinit = new MethodSymbol(STATIC | SYNTHETIC | PRIVATE, 2689 names.clinit, clinitType, enclClass); 2690 clinit.params = List.<VarSymbol>nil(); 2691 clinits.put(enclClass, clinit); 2692 } 2693 newScopeOwner = clinit; 2694 } 2695 lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dupUnshared(newScopeOwner))); 2696 } else { 2697 lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup())); 2698 } 2699 return lambdaEnv; 2700 } 2701 2702 @Override 2703 public void visitReference(final JCMemberReference that) { 2704 if (pt().isErroneous() || (pt().hasTag(NONE) && pt() != Type.recoveryType)) { 2705 if (pt().hasTag(NONE)) { 2706 //method reference only allowed in assignment or method invocation/cast context 2707 log.error(that.pos(), "unexpected.mref"); 2708 } 2709 result = that.type = types.createErrorType(pt()); 2710 return; 2711 } 2712 final Env<AttrContext> localEnv = env.dup(that); 2713 try { 2714 //attribute member reference qualifier - if this is a constructor 2715 //reference, the expected kind must be a type 2716 Type exprType = attribTree(that.expr, env, memberReferenceQualifierResult(that)); 2717 2718 if (that.getMode() == JCMemberReference.ReferenceMode.NEW) { 2719 exprType = chk.checkConstructorRefType(that.expr, exprType); 2720 if (!exprType.isErroneous() && 2721 exprType.isRaw() && 2722 that.typeargs != null) { 2723 log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), 2724 diags.fragment("mref.infer.and.explicit.params")); 2725 exprType = types.createErrorType(exprType); 2726 } 2727 } 2728 2729 if (exprType.isErroneous()) { 2730 //if the qualifier expression contains problems, 2731 //give up attribution of method reference 2732 result = that.type = exprType; 2733 return; 2734 } 2735 2736 if (TreeInfo.isStaticSelector(that.expr, names)) { 2737 //if the qualifier is a type, validate it; raw warning check is 2738 //omitted as we don't know at this stage as to whether this is a 2739 //raw selector (because of inference) 2740 chk.validate(that.expr, env, false); 2741 } 2742 2743 //attrib type-arguments 2744 List<Type> typeargtypes = List.nil(); 2745 if (that.typeargs != null) { 2746 typeargtypes = attribTypes(that.typeargs, localEnv); 2747 } 2748 2749 Type desc; 2750 Type currentTarget = pt(); 2751 boolean isTargetSerializable = 2752 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK && 2753 isSerializable(currentTarget); 2754 if (currentTarget != Type.recoveryType) { 2755 currentTarget = types.removeWildcards(targetChecker.visit(currentTarget, that)); 2756 desc = types.findDescriptorType(currentTarget); 2757 } else { 2758 currentTarget = Type.recoveryType; 2759 desc = fallbackDescriptorType(that); 2760 } 2761 2762 setFunctionalInfo(localEnv, that, pt(), desc, currentTarget, resultInfo.checkContext); 2763 List<Type> argtypes = desc.getParameterTypes(); 2764 Resolve.MethodCheck referenceCheck = rs.resolveMethodCheck; 2765 2766 if (resultInfo.checkContext.inferenceContext().free(argtypes)) { 2767 referenceCheck = rs.new MethodReferenceCheck(resultInfo.checkContext.inferenceContext()); 2768 } 2769 2770 Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = null; 2771 List<Type> saved_undet = resultInfo.checkContext.inferenceContext().save(); 2772 try { 2773 refResult = rs.resolveMemberReference(localEnv, that, that.expr.type, 2774 that.name, argtypes, typeargtypes, referenceCheck, 2775 resultInfo.checkContext.inferenceContext(), rs.basicReferenceChooser); 2776 } finally { 2777 resultInfo.checkContext.inferenceContext().rollback(saved_undet); 2778 } 2779 2780 Symbol refSym = refResult.fst; 2781 Resolve.ReferenceLookupHelper lookupHelper = refResult.snd; 2782 2783 /** this switch will need to go away and be replaced by the new RESOLUTION_TARGET testing 2784 * JDK-8075541 2785 */ 2786 if (refSym.kind != MTH) { 2787 boolean targetError; 2788 switch (refSym.kind) { 2789 case ABSENT_MTH: 2790 case MISSING_ENCL: 2791 targetError = false; 2792 break; 2793 case WRONG_MTH: 2794 case WRONG_MTHS: 2795 case AMBIGUOUS: 2796 case HIDDEN: 2797 case STATICERR: 2798 targetError = true; 2799 break; 2800 default: 2801 Assert.error("unexpected result kind " + refSym.kind); 2802 targetError = false; 2803 } 2804 2805 JCDiagnostic detailsDiag = ((Resolve.ResolveError)refSym.baseSymbol()).getDiagnostic(JCDiagnostic.DiagnosticType.FRAGMENT, 2806 that, exprType.tsym, exprType, that.name, argtypes, typeargtypes); 2807 2808 JCDiagnostic.DiagnosticType diagKind = targetError ? 2809 JCDiagnostic.DiagnosticType.FRAGMENT : JCDiagnostic.DiagnosticType.ERROR; 2810 2811 JCDiagnostic diag = diags.create(diagKind, log.currentSource(), that, 2812 "invalid.mref", Kinds.kindName(that.getMode()), detailsDiag); 2813 2814 if (targetError && currentTarget == Type.recoveryType) { 2815 //a target error doesn't make sense during recovery stage 2816 //as we don't know what actual parameter types are 2817 result = that.type = currentTarget; 2818 return; 2819 } else { 2820 if (targetError) { 2821 resultInfo.checkContext.report(that, diag); 2822 } else { 2823 log.report(diag); 2824 } 2825 result = that.type = types.createErrorType(currentTarget); 2826 return; 2827 } 2828 } 2829 2830 that.sym = refSym.baseSymbol(); 2831 that.kind = lookupHelper.referenceKind(that.sym); 2832 that.ownerAccessible = rs.isAccessible(localEnv, that.sym.enclClass()); 2833 2834 if (desc.getReturnType() == Type.recoveryType) { 2835 // stop here 2836 result = that.type = currentTarget; 2837 return; 2838 } 2839 2840 if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) { 2841 2842 if (that.getMode() == ReferenceMode.INVOKE && 2843 TreeInfo.isStaticSelector(that.expr, names) && 2844 that.kind.isUnbound() && 2845 !desc.getParameterTypes().head.isParameterized()) { 2846 chk.checkRaw(that.expr, localEnv); 2847 } 2848 2849 if (that.sym.isStatic() && TreeInfo.isStaticSelector(that.expr, names) && 2850 exprType.getTypeArguments().nonEmpty()) { 2851 //static ref with class type-args 2852 log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), 2853 diags.fragment("static.mref.with.targs")); 2854 result = that.type = types.createErrorType(currentTarget); 2855 return; 2856 } 2857 2858 if (!refSym.isStatic() && that.kind == JCMemberReference.ReferenceKind.SUPER) { 2859 // Check that super-qualified symbols are not abstract (JLS) 2860 rs.checkNonAbstract(that.pos(), that.sym); 2861 } 2862 2863 if (isTargetSerializable) { 2864 chk.checkElemAccessFromSerializableLambda(that); 2865 } 2866 } 2867 2868 ResultInfo checkInfo = 2869 resultInfo.dup(newMethodTemplate( 2870 desc.getReturnType().hasTag(VOID) ? Type.noType : desc.getReturnType(), 2871 that.kind.isUnbound() ? argtypes.tail : argtypes, typeargtypes), 2872 new FunctionalReturnContext(resultInfo.checkContext), CheckMode.NO_TREE_UPDATE); 2873 2874 Type refType = checkId(that, lookupHelper.site, refSym, localEnv, checkInfo); 2875 2876 if (that.kind.isUnbound() && 2877 resultInfo.checkContext.inferenceContext().free(argtypes.head)) { 2878 //re-generate inference constraints for unbound receiver 2879 if (!types.isSubtype(resultInfo.checkContext.inferenceContext().asUndetVar(argtypes.head), exprType)) { 2880 //cannot happen as this has already been checked - we just need 2881 //to regenerate the inference constraints, as that has been lost 2882 //as a result of the call to inferenceContext.save() 2883 Assert.error("Can't get here"); 2884 } 2885 } 2886 2887 if (!refType.isErroneous()) { 2888 refType = types.createMethodTypeWithReturn(refType, 2889 adjustMethodReturnType(lookupHelper.site, that.name, checkInfo.pt.getParameterTypes(), refType.getReturnType())); 2890 } 2891 2892 //go ahead with standard method reference compatibility check - note that param check 2893 //is a no-op (as this has been taken care during method applicability) 2894 boolean isSpeculativeRound = 2895 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE; 2896 2897 that.type = currentTarget; //avoids recovery at this stage 2898 checkReferenceCompatible(that, desc, refType, resultInfo.checkContext, isSpeculativeRound); 2899 if (!isSpeculativeRound) { 2900 checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), desc, currentTarget); 2901 } 2902 result = check(that, currentTarget, KindSelector.VAL, resultInfo); 2903 } catch (Types.FunctionDescriptorLookupError ex) { 2904 JCDiagnostic cause = ex.getDiagnostic(); 2905 resultInfo.checkContext.report(that, cause); 2906 result = that.type = types.createErrorType(pt()); 2907 return; 2908 } 2909 } 2910 //where 2911 ResultInfo memberReferenceQualifierResult(JCMemberReference tree) { 2912 //if this is a constructor reference, the expected kind must be a type 2913 return new ResultInfo(tree.getMode() == ReferenceMode.INVOKE ? 2914 KindSelector.VAL_TYP : KindSelector.TYP, 2915 Type.noType); 2916 } 2917 2918 2919 @SuppressWarnings("fallthrough") 2920 void checkReferenceCompatible(JCMemberReference tree, Type descriptor, Type refType, CheckContext checkContext, boolean speculativeAttr) { 2921 InferenceContext inferenceContext = checkContext.inferenceContext(); 2922 Type returnType = inferenceContext.asUndetVar(descriptor.getReturnType()); 2923 2924 Type resType; 2925 switch (tree.getMode()) { 2926 case NEW: 2927 if (!tree.expr.type.isRaw()) { 2928 resType = tree.expr.type; 2929 break; 2930 } 2931 default: 2932 resType = refType.getReturnType(); 2933 } 2934 2935 Type incompatibleReturnType = resType; 2936 2937 if (returnType.hasTag(VOID)) { 2938 incompatibleReturnType = null; 2939 } 2940 2941 if (!returnType.hasTag(VOID) && !resType.hasTag(VOID)) { 2942 if (resType.isErroneous() || 2943 new FunctionalReturnContext(checkContext).compatible(resType, returnType, types.noWarnings)) { 2944 incompatibleReturnType = null; 2945 } 2946 } 2947 2948 if (incompatibleReturnType != null) { 2949 checkContext.report(tree, diags.fragment("incompatible.ret.type.in.mref", 2950 diags.fragment("inconvertible.types", resType, descriptor.getReturnType()))); 2951 } else { 2952 if (inferenceContext.free(refType)) { 2953 // we need to wait for inference to finish and then replace inference vars in the referent type 2954 inferenceContext.addFreeTypeListener(List.of(refType), 2955 instantiatedContext -> { 2956 tree.referentType = instantiatedContext.asInstType(refType); 2957 }); 2958 } else { 2959 tree.referentType = refType; 2960 } 2961 } 2962 2963 if (!speculativeAttr) { 2964 List<Type> thrownTypes = inferenceContext.asUndetVars(descriptor.getThrownTypes()); 2965 if (chk.unhandled(refType.getThrownTypes(), thrownTypes).nonEmpty()) { 2966 log.error(tree, "incompatible.thrown.types.in.mref", refType.getThrownTypes()); 2967 } 2968 } 2969 } 2970 2971 /** 2972 * Set functional type info on the underlying AST. Note: as the target descriptor 2973 * might contain inference variables, we might need to register an hook in the 2974 * current inference context. 2975 */ 2976 private void setFunctionalInfo(final Env<AttrContext> env, final JCFunctionalExpression fExpr, 2977 final Type pt, final Type descriptorType, final Type primaryTarget, final CheckContext checkContext) { 2978 if (checkContext.inferenceContext().free(descriptorType)) { 2979 checkContext.inferenceContext().addFreeTypeListener(List.of(pt, descriptorType), new FreeTypeListener() { 2980 public void typesInferred(InferenceContext inferenceContext) { 2981 setFunctionalInfo(env, fExpr, pt, inferenceContext.asInstType(descriptorType), 2982 inferenceContext.asInstType(primaryTarget), checkContext); 2983 } 2984 }); 2985 } else { 2986 ListBuffer<Type> targets = new ListBuffer<>(); 2987 if (pt.hasTag(CLASS)) { 2988 if (pt.isCompound()) { 2989 targets.append(types.removeWildcards(primaryTarget)); //this goes first 2990 for (Type t : ((IntersectionClassType)pt()).interfaces_field) { 2991 if (t != primaryTarget) { 2992 targets.append(types.removeWildcards(t)); 2993 } 2994 } 2995 } else { 2996 targets.append(types.removeWildcards(primaryTarget)); 2997 } 2998 } 2999 fExpr.targets = targets.toList(); 3000 if (checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK && 3001 pt != Type.recoveryType) { 3002 //check that functional interface class is well-formed 3003 try { 3004 /* Types.makeFunctionalInterfaceClass() may throw an exception 3005 * when it's executed post-inference. See the listener code 3006 * above. 3007 */ 3008 ClassSymbol csym = types.makeFunctionalInterfaceClass(env, 3009 names.empty, List.of(fExpr.targets.head), ABSTRACT); 3010 if (csym != null) { 3011 chk.checkImplementations(env.tree, csym, csym); 3012 try { 3013 //perform an additional functional interface check on the synthetic class, 3014 //as there may be spurious errors for raw targets - because of existing issues 3015 //with membership and inheritance (see JDK-8074570). 3016 csym.flags_field |= INTERFACE; 3017 types.findDescriptorType(csym.type); 3018 } catch (FunctionDescriptorLookupError err) { 3019 resultInfo.checkContext.report(fExpr, 3020 diags.fragment(Fragments.NoSuitableFunctionalIntfInst(fExpr.targets.head))); 3021 } 3022 } 3023 } catch (Types.FunctionDescriptorLookupError ex) { 3024 JCDiagnostic cause = ex.getDiagnostic(); 3025 resultInfo.checkContext.report(env.tree, cause); 3026 } 3027 } 3028 } 3029 } 3030 3031 public void visitParens(JCParens tree) { 3032 Type owntype = attribTree(tree.expr, env, resultInfo); 3033 result = check(tree, owntype, pkind(), resultInfo); 3034 Symbol sym = TreeInfo.symbol(tree); 3035 if (sym != null && sym.kind.matches(KindSelector.TYP_PCK)) 3036 log.error(tree.pos(), "illegal.start.of.type"); 3037 } 3038 3039 public void visitAssign(JCAssign tree) { 3040 Type owntype = attribTree(tree.lhs, env.dup(tree), varAssignmentInfo); 3041 Type capturedType = capture(owntype); 3042 attribExpr(tree.rhs, env, owntype); 3043 result = check(tree, capturedType, KindSelector.VAL, resultInfo); 3044 } 3045 3046 public void visitAssignop(JCAssignOp tree) { 3047 // Attribute arguments. 3048 Type owntype = attribTree(tree.lhs, env, varAssignmentInfo); 3049 Type operand = attribExpr(tree.rhs, env); 3050 // Find operator. 3051 Symbol operator = tree.operator = operators.resolveBinary(tree, tree.getTag().noAssignOp(), owntype, operand); 3052 if (operator.kind == MTH && 3053 !owntype.isErroneous() && 3054 !operand.isErroneous()) { 3055 chk.checkDivZero(tree.rhs.pos(), operator, operand); 3056 chk.checkCastable(tree.rhs.pos(), 3057 operator.type.getReturnType(), 3058 owntype); 3059 } 3060 result = check(tree, owntype, KindSelector.VAL, resultInfo); 3061 } 3062 3063 public void visitUnary(JCUnary tree) { 3064 // Attribute arguments. 3065 Type argtype = (tree.getTag().isIncOrDecUnaryOp()) 3066 ? attribTree(tree.arg, env, varAssignmentInfo) 3067 : chk.checkNonVoid(tree.arg.pos(), attribExpr(tree.arg, env)); 3068 3069 // Find operator. 3070 Symbol operator = tree.operator = operators.resolveUnary(tree, tree.getTag(), argtype); 3071 Type owntype = types.createErrorType(tree.type); 3072 if (operator.kind == MTH && 3073 !argtype.isErroneous()) { 3074 owntype = (tree.getTag().isIncOrDecUnaryOp()) 3075 ? tree.arg.type 3076 : operator.type.getReturnType(); 3077 int opc = ((OperatorSymbol)operator).opcode; 3078 3079 // If the argument is constant, fold it. 3080 if (argtype.constValue() != null) { 3081 Type ctype = cfolder.fold1(opc, argtype); 3082 if (ctype != null) { 3083 owntype = cfolder.coerce(ctype, owntype); 3084 } 3085 } 3086 } 3087 result = check(tree, owntype, KindSelector.VAL, resultInfo); 3088 } 3089 3090 public void visitBinary(JCBinary tree) { 3091 // Attribute arguments. 3092 Type left = chk.checkNonVoid(tree.lhs.pos(), attribExpr(tree.lhs, env)); 3093 Type right = chk.checkNonVoid(tree.rhs.pos(), attribExpr(tree.rhs, env)); 3094 // Find operator. 3095 Symbol operator = tree.operator = operators.resolveBinary(tree, tree.getTag(), left, right); 3096 Type owntype = types.createErrorType(tree.type); 3097 if (operator.kind == MTH && 3098 !left.isErroneous() && 3099 !right.isErroneous()) { 3100 owntype = operator.type.getReturnType(); 3101 int opc = ((OperatorSymbol)operator).opcode; 3102 // If both arguments are constants, fold them. 3103 if (left.constValue() != null && right.constValue() != null) { 3104 Type ctype = cfolder.fold2(opc, left, right); 3105 if (ctype != null) { 3106 owntype = cfolder.coerce(ctype, owntype); 3107 } 3108 } 3109 3110 // Check that argument types of a reference ==, != are 3111 // castable to each other, (JLS 15.21). Note: unboxing 3112 // comparisons will not have an acmp* opc at this point. 3113 if ((opc == ByteCodes.if_acmpeq || opc == ByteCodes.if_acmpne)) { 3114 if (!types.isCastable(left, right, new Warner(tree.pos()))) { 3115 log.error(tree.pos(), "incomparable.types", left, right); 3116 } 3117 } 3118 3119 chk.checkDivZero(tree.rhs.pos(), operator, right); 3120 } 3121 result = check(tree, owntype, KindSelector.VAL, resultInfo); 3122 } 3123 3124 public void visitTypeCast(final JCTypeCast tree) { 3125 Type clazztype = attribType(tree.clazz, env); 3126 chk.validate(tree.clazz, env, false); 3127 //a fresh environment is required for 292 inference to work properly --- 3128 //see Infer.instantiatePolymorphicSignatureInstance() 3129 Env<AttrContext> localEnv = env.dup(tree); 3130 //should we propagate the target type? 3131 final ResultInfo castInfo; 3132 JCExpression expr = TreeInfo.skipParens(tree.expr); 3133 boolean isPoly = allowPoly && (expr.hasTag(LAMBDA) || expr.hasTag(REFERENCE)); 3134 if (isPoly) { 3135 //expression is a poly - we need to propagate target type info 3136 castInfo = new ResultInfo(KindSelector.VAL, clazztype, 3137 new Check.NestedCheckContext(resultInfo.checkContext) { 3138 @Override 3139 public boolean compatible(Type found, Type req, Warner warn) { 3140 return types.isCastable(found, req, warn); 3141 } 3142 }); 3143 } else { 3144 //standalone cast - target-type info is not propagated 3145 castInfo = unknownExprInfo; 3146 } 3147 Type exprtype = attribTree(tree.expr, localEnv, castInfo); 3148 Type owntype = isPoly ? clazztype : chk.checkCastable(tree.expr.pos(), exprtype, clazztype); 3149 if (exprtype.constValue() != null) 3150 owntype = cfolder.coerce(exprtype, owntype); 3151 result = check(tree, capture(owntype), KindSelector.VAL, resultInfo); 3152 if (!isPoly) 3153 chk.checkRedundantCast(localEnv, tree); 3154 } 3155 3156 public void visitTypeTest(JCInstanceOf tree) { 3157 Type exprtype = chk.checkNullOrRefType( 3158 tree.expr.pos(), attribExpr(tree.expr, env)); 3159 Type clazztype = attribType(tree.clazz, env); 3160 if (!clazztype.hasTag(TYPEVAR)) { 3161 clazztype = chk.checkClassOrArrayType(tree.clazz.pos(), clazztype); 3162 } 3163 if (!clazztype.isErroneous() && !types.isReifiable(clazztype)) { 3164 log.error(tree.clazz.pos(), "illegal.generic.type.for.instof"); 3165 clazztype = types.createErrorType(clazztype); 3166 } 3167 chk.validate(tree.clazz, env, false); 3168 chk.checkCastable(tree.expr.pos(), exprtype, clazztype); 3169 result = check(tree, syms.booleanType, KindSelector.VAL, resultInfo); 3170 } 3171 3172 public void visitIndexed(JCArrayAccess tree) { 3173 Type owntype = types.createErrorType(tree.type); 3174 Type atype = attribExpr(tree.indexed, env); 3175 attribExpr(tree.index, env, syms.intType); 3176 if (types.isArray(atype)) 3177 owntype = types.elemtype(atype); 3178 else if (!atype.hasTag(ERROR)) 3179 log.error(tree.pos(), "array.req.but.found", atype); 3180 if (!pkind().contains(KindSelector.VAL)) 3181 owntype = capture(owntype); 3182 result = check(tree, owntype, KindSelector.VAR, resultInfo); 3183 } 3184 3185 public void visitIdent(JCIdent tree) { 3186 Symbol sym; 3187 3188 // Find symbol 3189 if (pt().hasTag(METHOD) || pt().hasTag(FORALL)) { 3190 // If we are looking for a method, the prototype `pt' will be a 3191 // method type with the type of the call's arguments as parameters. 3192 env.info.pendingResolutionPhase = null; 3193 sym = rs.resolveMethod(tree.pos(), env, tree.name, pt().getParameterTypes(), pt().getTypeArguments()); 3194 } else if (tree.sym != null && tree.sym.kind != VAR) { 3195 sym = tree.sym; 3196 } else { 3197 sym = rs.resolveIdent(tree.pos(), env, tree.name, pkind()); 3198 } 3199 tree.sym = sym; 3200 3201 // (1) Also find the environment current for the class where 3202 // sym is defined (`symEnv'). 3203 // Only for pre-tiger versions (1.4 and earlier): 3204 // (2) Also determine whether we access symbol out of an anonymous 3205 // class in a this or super call. This is illegal for instance 3206 // members since such classes don't carry a this$n link. 3207 // (`noOuterThisPath'). 3208 Env<AttrContext> symEnv = env; 3209 boolean noOuterThisPath = false; 3210 if (env.enclClass.sym.owner.kind != PCK && // we are in an inner class 3211 sym.kind.matches(KindSelector.VAL_MTH) && 3212 sym.owner.kind == TYP && 3213 tree.name != names._this && tree.name != names._super) { 3214 3215 // Find environment in which identifier is defined. 3216 while (symEnv.outer != null && 3217 !sym.isMemberOf(symEnv.enclClass.sym, types)) { 3218 if ((symEnv.enclClass.sym.flags() & NOOUTERTHIS) != 0) 3219 noOuterThisPath = false; 3220 symEnv = symEnv.outer; 3221 } 3222 } 3223 3224 // If symbol is a variable, ... 3225 if (sym.kind == VAR) { 3226 VarSymbol v = (VarSymbol)sym; 3227 3228 // ..., evaluate its initializer, if it has one, and check for 3229 // illegal forward reference. 3230 checkInit(tree, env, v, false); 3231 3232 // If we are expecting a variable (as opposed to a value), check 3233 // that the variable is assignable in the current environment. 3234 if (KindSelector.ASG.subset(pkind())) 3235 checkAssignable(tree.pos(), v, null, env); 3236 } 3237 3238 // In a constructor body, 3239 // if symbol is a field or instance method, check that it is 3240 // not accessed before the supertype constructor is called. 3241 if ((symEnv.info.isSelfCall || noOuterThisPath) && 3242 sym.kind.matches(KindSelector.VAL_MTH) && 3243 sym.owner.kind == TYP && 3244 (sym.flags() & STATIC) == 0) { 3245 chk.earlyRefError(tree.pos(), sym.kind == VAR ? 3246 sym : thisSym(tree.pos(), env)); 3247 } 3248 Env<AttrContext> env1 = env; 3249 if (sym.kind != ERR && sym.kind != TYP && 3250 sym.owner != null && sym.owner != env1.enclClass.sym) { 3251 // If the found symbol is inaccessible, then it is 3252 // accessed through an enclosing instance. Locate this 3253 // enclosing instance: 3254 while (env1.outer != null && !rs.isAccessible(env, env1.enclClass.sym.type, sym)) 3255 env1 = env1.outer; 3256 } 3257 3258 if (env.info.isSerializable) { 3259 chk.checkElemAccessFromSerializableLambda(tree); 3260 } 3261 3262 result = checkId(tree, env1.enclClass.sym.type, sym, env, resultInfo); 3263 } 3264 3265 public void visitSelect(JCFieldAccess tree) { 3266 // Determine the expected kind of the qualifier expression. 3267 KindSelector skind = KindSelector.NIL; 3268 if (tree.name == names._this || tree.name == names._super || 3269 tree.name == names._class) 3270 { 3271 skind = KindSelector.TYP; 3272 } else { 3273 if (pkind().contains(KindSelector.PCK)) 3274 skind = KindSelector.of(skind, KindSelector.PCK); 3275 if (pkind().contains(KindSelector.TYP)) 3276 skind = KindSelector.of(skind, KindSelector.TYP, KindSelector.PCK); 3277 if (pkind().contains(KindSelector.VAL_MTH)) 3278 skind = KindSelector.of(skind, KindSelector.VAL, KindSelector.TYP); 3279 } 3280 3281 // Attribute the qualifier expression, and determine its symbol (if any). 3282 Type site = attribTree(tree.selected, env, new ResultInfo(skind, Infer.anyPoly)); 3283 if (!pkind().contains(KindSelector.TYP_PCK)) 3284 site = capture(site); // Capture field access 3285 3286 // don't allow T.class T[].class, etc 3287 if (skind == KindSelector.TYP) { 3288 Type elt = site; 3289 while (elt.hasTag(ARRAY)) 3290 elt = ((ArrayType)elt).elemtype; 3291 if (elt.hasTag(TYPEVAR)) { 3292 log.error(tree.pos(), "type.var.cant.be.deref"); 3293 result = tree.type = types.createErrorType(tree.name, site.tsym, site); 3294 tree.sym = tree.type.tsym; 3295 return ; 3296 } 3297 } 3298 3299 // If qualifier symbol is a type or `super', assert `selectSuper' 3300 // for the selection. This is relevant for determining whether 3301 // protected symbols are accessible. 3302 Symbol sitesym = TreeInfo.symbol(tree.selected); 3303 boolean selectSuperPrev = env.info.selectSuper; 3304 env.info.selectSuper = 3305 sitesym != null && 3306 sitesym.name == names._super; 3307 3308 // Determine the symbol represented by the selection. 3309 env.info.pendingResolutionPhase = null; 3310 Symbol sym = selectSym(tree, sitesym, site, env, resultInfo); 3311 if (sym.kind == VAR && sym.name != names._super && env.info.defaultSuperCallSite != null) { 3312 log.error(tree.selected.pos(), "not.encl.class", site.tsym); 3313 sym = syms.errSymbol; 3314 } 3315 if (sym.exists() && !isType(sym) && pkind().contains(KindSelector.TYP_PCK)) { 3316 site = capture(site); 3317 sym = selectSym(tree, sitesym, site, env, resultInfo); 3318 } 3319 boolean varArgs = env.info.lastResolveVarargs(); 3320 tree.sym = sym; 3321 3322 if (site.hasTag(TYPEVAR) && !isType(sym) && sym.kind != ERR) { 3323 site = types.skipTypeVars(site, true); 3324 } 3325 3326 // If that symbol is a variable, ... 3327 if (sym.kind == VAR) { 3328 VarSymbol v = (VarSymbol)sym; 3329 3330 // ..., evaluate its initializer, if it has one, and check for 3331 // illegal forward reference. 3332 checkInit(tree, env, v, true); 3333 3334 // If we are expecting a variable (as opposed to a value), check 3335 // that the variable is assignable in the current environment. 3336 if (KindSelector.ASG.subset(pkind())) 3337 checkAssignable(tree.pos(), v, tree.selected, env); 3338 } 3339 3340 if (sitesym != null && 3341 sitesym.kind == VAR && 3342 ((VarSymbol)sitesym).isResourceVariable() && 3343 sym.kind == MTH && 3344 sym.name.equals(names.close) && 3345 sym.overrides(syms.autoCloseableClose, sitesym.type.tsym, types, true) && 3346 env.info.lint.isEnabled(LintCategory.TRY)) { 3347 log.warning(LintCategory.TRY, tree, "try.explicit.close.call"); 3348 } 3349 3350 // Disallow selecting a type from an expression 3351 if (isType(sym) && (sitesym == null || !sitesym.kind.matches(KindSelector.TYP_PCK))) { 3352 tree.type = check(tree.selected, pt(), 3353 sitesym == null ? 3354 KindSelector.VAL : sitesym.kind.toSelector(), 3355 new ResultInfo(KindSelector.TYP_PCK, pt())); 3356 } 3357 3358 if (isType(sitesym)) { 3359 if (sym.name == names._this) { 3360 // If `C' is the currently compiled class, check that 3361 // C.this' does not appear in a call to a super(...) 3362 if (env.info.isSelfCall && 3363 site.tsym == env.enclClass.sym) { 3364 chk.earlyRefError(tree.pos(), sym); 3365 } 3366 } else { 3367 // Check if type-qualified fields or methods are static (JLS) 3368 if ((sym.flags() & STATIC) == 0 && 3369 !env.next.tree.hasTag(REFERENCE) && 3370 sym.name != names._super && 3371 (sym.kind == VAR || sym.kind == MTH)) { 3372 rs.accessBase(rs.new StaticError(sym), 3373 tree.pos(), site, sym.name, true); 3374 } 3375 } 3376 if (!allowStaticInterfaceMethods && sitesym.isInterface() && 3377 sym.isStatic() && sym.kind == MTH) { 3378 log.error(tree.pos(), "static.intf.method.invoke.not.supported.in.source", sourceName); 3379 } 3380 } else if (sym.kind != ERR && 3381 (sym.flags() & STATIC) != 0 && 3382 sym.name != names._class) { 3383 // If the qualified item is not a type and the selected item is static, report 3384 // a warning. Make allowance for the class of an array type e.g. Object[].class) 3385 chk.warnStatic(tree, "static.not.qualified.by.type", 3386 sym.kind.kindName(), sym.owner); 3387 } 3388 3389 // If we are selecting an instance member via a `super', ... 3390 if (env.info.selectSuper && (sym.flags() & STATIC) == 0) { 3391 3392 // Check that super-qualified symbols are not abstract (JLS) 3393 rs.checkNonAbstract(tree.pos(), sym); 3394 3395 if (site.isRaw()) { 3396 // Determine argument types for site. 3397 Type site1 = types.asSuper(env.enclClass.sym.type, site.tsym); 3398 if (site1 != null) site = site1; 3399 } 3400 } 3401 3402 if (env.info.isSerializable) { 3403 chk.checkElemAccessFromSerializableLambda(tree); 3404 } 3405 3406 env.info.selectSuper = selectSuperPrev; 3407 result = checkId(tree, site, sym, env, resultInfo); 3408 } 3409 //where 3410 /** Determine symbol referenced by a Select expression, 3411 * 3412 * @param tree The select tree. 3413 * @param site The type of the selected expression, 3414 * @param env The current environment. 3415 * @param resultInfo The current result. 3416 */ 3417 private Symbol selectSym(JCFieldAccess tree, 3418 Symbol location, 3419 Type site, 3420 Env<AttrContext> env, 3421 ResultInfo resultInfo) { 3422 DiagnosticPosition pos = tree.pos(); 3423 Name name = tree.name; 3424 switch (site.getTag()) { 3425 case PACKAGE: 3426 return rs.accessBase( 3427 rs.findIdentInPackage(env, site.tsym, name, resultInfo.pkind), 3428 pos, location, site, name, true); 3429 case ARRAY: 3430 case CLASS: 3431 if (resultInfo.pt.hasTag(METHOD) || resultInfo.pt.hasTag(FORALL)) { 3432 return rs.resolveQualifiedMethod( 3433 pos, env, location, site, name, resultInfo.pt.getParameterTypes(), resultInfo.pt.getTypeArguments()); 3434 } else if (name == names._this || name == names._super) { 3435 return rs.resolveSelf(pos, env, site.tsym, name); 3436 } else if (name == names._class) { 3437 // In this case, we have already made sure in 3438 // visitSelect that qualifier expression is a type. 3439 Type t = syms.classType; 3440 List<Type> typeargs = List.of(types.erasure(site)); 3441 t = new ClassType(t.getEnclosingType(), typeargs, t.tsym); 3442 return new VarSymbol( 3443 STATIC | PUBLIC | FINAL, names._class, t, site.tsym); 3444 } else { 3445 // We are seeing a plain identifier as selector. 3446 Symbol sym = rs.findIdentInType(env, site, name, resultInfo.pkind); 3447 sym = rs.accessBase(sym, pos, location, site, name, true); 3448 return sym; 3449 } 3450 case WILDCARD: 3451 throw new AssertionError(tree); 3452 case TYPEVAR: 3453 // Normally, site.getUpperBound() shouldn't be null. 3454 // It should only happen during memberEnter/attribBase 3455 // when determining the super type which *must* beac 3456 // done before attributing the type variables. In 3457 // other words, we are seeing this illegal program: 3458 // class B<T> extends A<T.foo> {} 3459 Symbol sym = (site.getUpperBound() != null) 3460 ? selectSym(tree, location, capture(site.getUpperBound()), env, resultInfo) 3461 : null; 3462 if (sym == null) { 3463 log.error(pos, "type.var.cant.be.deref"); 3464 return syms.errSymbol; 3465 } else { 3466 Symbol sym2 = (sym.flags() & Flags.PRIVATE) != 0 ? 3467 rs.new AccessError(env, site, sym) : 3468 sym; 3469 rs.accessBase(sym2, pos, location, site, name, true); 3470 return sym; 3471 } 3472 case ERROR: 3473 // preserve identifier names through errors 3474 return types.createErrorType(name, site.tsym, site).tsym; 3475 default: 3476 // The qualifier expression is of a primitive type -- only 3477 // .class is allowed for these. 3478 if (name == names._class) { 3479 // In this case, we have already made sure in Select that 3480 // qualifier expression is a type. 3481 Type t = syms.classType; 3482 Type arg = types.boxedClass(site).type; 3483 t = new ClassType(t.getEnclosingType(), List.of(arg), t.tsym); 3484 return new VarSymbol( 3485 STATIC | PUBLIC | FINAL, names._class, t, site.tsym); 3486 } else { 3487 log.error(pos, "cant.deref", site); 3488 return syms.errSymbol; 3489 } 3490 } 3491 } 3492 3493 /** Determine type of identifier or select expression and check that 3494 * (1) the referenced symbol is not deprecated 3495 * (2) the symbol's type is safe (@see checkSafe) 3496 * (3) if symbol is a variable, check that its type and kind are 3497 * compatible with the prototype and protokind. 3498 * (4) if symbol is an instance field of a raw type, 3499 * which is being assigned to, issue an unchecked warning if its 3500 * type changes under erasure. 3501 * (5) if symbol is an instance method of a raw type, issue an 3502 * unchecked warning if its argument types change under erasure. 3503 * If checks succeed: 3504 * If symbol is a constant, return its constant type 3505 * else if symbol is a method, return its result type 3506 * otherwise return its type. 3507 * Otherwise return errType. 3508 * 3509 * @param tree The syntax tree representing the identifier 3510 * @param site If this is a select, the type of the selected 3511 * expression, otherwise the type of the current class. 3512 * @param sym The symbol representing the identifier. 3513 * @param env The current environment. 3514 * @param resultInfo The expected result 3515 */ 3516 Type checkId(JCTree tree, 3517 Type site, 3518 Symbol sym, 3519 Env<AttrContext> env, 3520 ResultInfo resultInfo) { 3521 return (resultInfo.pt.hasTag(FORALL) || resultInfo.pt.hasTag(METHOD)) ? 3522 checkMethodId(tree, site, sym, env, resultInfo) : 3523 checkIdInternal(tree, site, sym, resultInfo.pt, env, resultInfo); 3524 } 3525 3526 Type checkMethodId(JCTree tree, 3527 Type site, 3528 Symbol sym, 3529 Env<AttrContext> env, 3530 ResultInfo resultInfo) { 3531 boolean isPolymorhicSignature = 3532 (sym.baseSymbol().flags() & SIGNATURE_POLYMORPHIC) != 0; 3533 return isPolymorhicSignature ? 3534 checkSigPolyMethodId(tree, site, sym, env, resultInfo) : 3535 checkMethodIdInternal(tree, site, sym, env, resultInfo); 3536 } 3537 3538 Type checkSigPolyMethodId(JCTree tree, 3539 Type site, 3540 Symbol sym, 3541 Env<AttrContext> env, 3542 ResultInfo resultInfo) { 3543 //recover original symbol for signature polymorphic methods 3544 checkMethodIdInternal(tree, site, sym.baseSymbol(), env, resultInfo); 3545 env.info.pendingResolutionPhase = Resolve.MethodResolutionPhase.BASIC; 3546 return sym.type; 3547 } 3548 3549 Type checkMethodIdInternal(JCTree tree, 3550 Type site, 3551 Symbol sym, 3552 Env<AttrContext> env, 3553 ResultInfo resultInfo) { 3554 if (resultInfo.pkind.contains(KindSelector.POLY)) { 3555 Type pt = resultInfo.pt.map(deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, sym, env.info.pendingResolutionPhase)); 3556 Type owntype = checkIdInternal(tree, site, sym, pt, env, resultInfo); 3557 resultInfo.pt.map(deferredAttr.new RecoveryDeferredTypeMap(AttrMode.CHECK, sym, env.info.pendingResolutionPhase)); 3558 return owntype; 3559 } else { 3560 return checkIdInternal(tree, site, sym, resultInfo.pt, env, resultInfo); 3561 } 3562 } 3563 3564 Type checkIdInternal(JCTree tree, 3565 Type site, 3566 Symbol sym, 3567 Type pt, 3568 Env<AttrContext> env, 3569 ResultInfo resultInfo) { 3570 if (pt.isErroneous()) { 3571 return types.createErrorType(site); 3572 } 3573 Type owntype; // The computed type of this identifier occurrence. 3574 switch (sym.kind) { 3575 case TYP: 3576 // For types, the computed type equals the symbol's type, 3577 // except for two situations: 3578 owntype = sym.type; 3579 if (owntype.hasTag(CLASS)) { 3580 chk.checkForBadAuxiliaryClassAccess(tree.pos(), env, (ClassSymbol)sym); 3581 Type ownOuter = owntype.getEnclosingType(); 3582 3583 // (a) If the symbol's type is parameterized, erase it 3584 // because no type parameters were given. 3585 // We recover generic outer type later in visitTypeApply. 3586 if (owntype.tsym.type.getTypeArguments().nonEmpty()) { 3587 owntype = types.erasure(owntype); 3588 } 3589 3590 // (b) If the symbol's type is an inner class, then 3591 // we have to interpret its outer type as a superclass 3592 // of the site type. Example: 3593 // 3594 // class Tree<A> { class Visitor { ... } } 3595 // class PointTree extends Tree<Point> { ... } 3596 // ...PointTree.Visitor... 3597 // 3598 // Then the type of the last expression above is 3599 // Tree<Point>.Visitor. 3600 else if (ownOuter.hasTag(CLASS) && site != ownOuter) { 3601 Type normOuter = site; 3602 if (normOuter.hasTag(CLASS)) { 3603 normOuter = types.asEnclosingSuper(site, ownOuter.tsym); 3604 } 3605 if (normOuter == null) // perhaps from an import 3606 normOuter = types.erasure(ownOuter); 3607 if (normOuter != ownOuter) 3608 owntype = new ClassType( 3609 normOuter, List.<Type>nil(), owntype.tsym, 3610 owntype.getMetadata()); 3611 } 3612 } 3613 break; 3614 case VAR: 3615 VarSymbol v = (VarSymbol)sym; 3616 // Test (4): if symbol is an instance field of a raw type, 3617 // which is being assigned to, issue an unchecked warning if 3618 // its type changes under erasure. 3619 if (KindSelector.ASG.subset(pkind()) && 3620 v.owner.kind == TYP && 3621 (v.flags() & STATIC) == 0 && 3622 (site.hasTag(CLASS) || site.hasTag(TYPEVAR))) { 3623 Type s = types.asOuterSuper(site, v.owner); 3624 if (s != null && 3625 s.isRaw() && 3626 !types.isSameType(v.type, v.erasure(types))) { 3627 chk.warnUnchecked(tree.pos(), 3628 "unchecked.assign.to.var", 3629 v, s); 3630 } 3631 } 3632 // The computed type of a variable is the type of the 3633 // variable symbol, taken as a member of the site type. 3634 owntype = (sym.owner.kind == TYP && 3635 sym.name != names._this && sym.name != names._super) 3636 ? types.memberType(site, sym) 3637 : sym.type; 3638 3639 // If the variable is a constant, record constant value in 3640 // computed type. 3641 if (v.getConstValue() != null && isStaticReference(tree)) 3642 owntype = owntype.constType(v.getConstValue()); 3643 3644 if (resultInfo.pkind == KindSelector.VAL) { 3645 owntype = capture(owntype); // capture "names as expressions" 3646 } 3647 break; 3648 case MTH: { 3649 owntype = checkMethod(site, sym, 3650 new ResultInfo(resultInfo.pkind, resultInfo.pt.getReturnType(), resultInfo.checkContext), 3651 env, TreeInfo.args(env.tree), resultInfo.pt.getParameterTypes(), 3652 resultInfo.pt.getTypeArguments()); 3653 break; 3654 } 3655 case PCK: case ERR: 3656 owntype = sym.type; 3657 break; 3658 default: 3659 throw new AssertionError("unexpected kind: " + sym.kind + 3660 " in tree " + tree); 3661 } 3662 3663 // Test (1): emit a `deprecation' warning if symbol is deprecated. 3664 // (for constructors, the error was given when the constructor was 3665 // resolved) 3666 3667 if (sym.name != names.init) { 3668 chk.checkDeprecated(tree.pos(), env.info.scope.owner, sym); 3669 chk.checkSunAPI(tree.pos(), sym); 3670 chk.checkProfile(tree.pos(), sym); 3671 } 3672 3673 // Test (3): if symbol is a variable, check that its type and 3674 // kind are compatible with the prototype and protokind. 3675 return check(tree, owntype, sym.kind.toSelector(), resultInfo); 3676 } 3677 3678 /** Check that variable is initialized and evaluate the variable's 3679 * initializer, if not yet done. Also check that variable is not 3680 * referenced before it is defined. 3681 * @param tree The tree making up the variable reference. 3682 * @param env The current environment. 3683 * @param v The variable's symbol. 3684 */ 3685 private void checkInit(JCTree tree, 3686 Env<AttrContext> env, 3687 VarSymbol v, 3688 boolean onlyWarning) { 3689// System.err.println(v + " " + ((v.flags() & STATIC) != 0) + " " + 3690// tree.pos + " " + v.pos + " " + 3691// Resolve.isStatic(env));//DEBUG 3692 3693 // A forward reference is diagnosed if the declaration position 3694 // of the variable is greater than the current tree position 3695 // and the tree and variable definition occur in the same class 3696 // definition. Note that writes don't count as references. 3697 // This check applies only to class and instance 3698 // variables. Local variables follow different scope rules, 3699 // and are subject to definite assignment checking. 3700 if ((env.info.enclVar == v || v.pos > tree.pos) && 3701 v.owner.kind == TYP && 3702 enclosingInitEnv(env) != null && 3703 v.owner == env.info.scope.owner.enclClass() && 3704 ((v.flags() & STATIC) != 0) == Resolve.isStatic(env) && 3705 (!env.tree.hasTag(ASSIGN) || 3706 TreeInfo.skipParens(((JCAssign) env.tree).lhs) != tree)) { 3707 String suffix = (env.info.enclVar == v) ? 3708 "self.ref" : "forward.ref"; 3709 if (!onlyWarning || isStaticEnumField(v)) { 3710 log.error(tree.pos(), "illegal." + suffix); 3711 } else if (useBeforeDeclarationWarning) { 3712 log.warning(tree.pos(), suffix, v); 3713 } 3714 } 3715 3716 v.getConstValue(); // ensure initializer is evaluated 3717 3718 checkEnumInitializer(tree, env, v); 3719 } 3720 3721 /** 3722 * Returns the enclosing init environment associated with this env (if any). An init env 3723 * can be either a field declaration env or a static/instance initializer env. 3724 */ 3725 Env<AttrContext> enclosingInitEnv(Env<AttrContext> env) { 3726 while (true) { 3727 switch (env.tree.getTag()) { 3728 case VARDEF: 3729 JCVariableDecl vdecl = (JCVariableDecl)env.tree; 3730 if (vdecl.sym.owner.kind == TYP) { 3731 //field 3732 return env; 3733 } 3734 break; 3735 case BLOCK: 3736 if (env.next.tree.hasTag(CLASSDEF)) { 3737 //instance/static initializer 3738 return env; 3739 } 3740 break; 3741 case METHODDEF: 3742 case CLASSDEF: 3743 case TOPLEVEL: 3744 return null; 3745 } 3746 Assert.checkNonNull(env.next); 3747 env = env.next; 3748 } 3749 } 3750 3751 /** 3752 * Check for illegal references to static members of enum. In 3753 * an enum type, constructors and initializers may not 3754 * reference its static members unless they are constant. 3755 * 3756 * @param tree The tree making up the variable reference. 3757 * @param env The current environment. 3758 * @param v The variable's symbol. 3759 * @jls section 8.9 Enums 3760 */ 3761 private void checkEnumInitializer(JCTree tree, Env<AttrContext> env, VarSymbol v) { 3762 // JLS: 3763 // 3764 // "It is a compile-time error to reference a static field 3765 // of an enum type that is not a compile-time constant 3766 // (15.28) from constructors, instance initializer blocks, 3767 // or instance variable initializer expressions of that 3768 // type. It is a compile-time error for the constructors, 3769 // instance initializer blocks, or instance variable 3770 // initializer expressions of an enum constant e to refer 3771 // to itself or to an enum constant of the same type that 3772 // is declared to the right of e." 3773 if (isStaticEnumField(v)) { 3774 ClassSymbol enclClass = env.info.scope.owner.enclClass(); 3775 3776 if (enclClass == null || enclClass.owner == null) 3777 return; 3778 3779 // See if the enclosing class is the enum (or a 3780 // subclass thereof) declaring v. If not, this 3781 // reference is OK. 3782 if (v.owner != enclClass && !types.isSubtype(enclClass.type, v.owner.type)) 3783 return; 3784 3785 // If the reference isn't from an initializer, then 3786 // the reference is OK. 3787 if (!Resolve.isInitializer(env)) 3788 return; 3789 3790 log.error(tree.pos(), "illegal.enum.static.ref"); 3791 } 3792 } 3793 3794 /** Is the given symbol a static, non-constant field of an Enum? 3795 * Note: enum literals should not be regarded as such 3796 */ 3797 private boolean isStaticEnumField(VarSymbol v) { 3798 return Flags.isEnum(v.owner) && 3799 Flags.isStatic(v) && 3800 !Flags.isConstant(v) && 3801 v.name != names._class; 3802 } 3803 3804 Warner noteWarner = new Warner(); 3805 3806 /** 3807 * Check that method arguments conform to its instantiation. 3808 **/ 3809 public Type checkMethod(Type site, 3810 final Symbol sym, 3811 ResultInfo resultInfo, 3812 Env<AttrContext> env, 3813 final List<JCExpression> argtrees, 3814 List<Type> argtypes, 3815 List<Type> typeargtypes) { 3816 // Test (5): if symbol is an instance method of a raw type, issue 3817 // an unchecked warning if its argument types change under erasure. 3818 if ((sym.flags() & STATIC) == 0 && 3819 (site.hasTag(CLASS) || site.hasTag(TYPEVAR))) { 3820 Type s = types.asOuterSuper(site, sym.owner); 3821 if (s != null && s.isRaw() && 3822 !types.isSameTypes(sym.type.getParameterTypes(), 3823 sym.erasure(types).getParameterTypes())) { 3824 chk.warnUnchecked(env.tree.pos(), 3825 "unchecked.call.mbr.of.raw.type", 3826 sym, s); 3827 } 3828 } 3829 3830 if (env.info.defaultSuperCallSite != null) { 3831 for (Type sup : types.interfaces(env.enclClass.type).prepend(types.supertype((env.enclClass.type)))) { 3832 if (!sup.tsym.isSubClass(sym.enclClass(), types) || 3833 types.isSameType(sup, env.info.defaultSuperCallSite)) continue; 3834 List<MethodSymbol> icand_sup = 3835 types.interfaceCandidates(sup, (MethodSymbol)sym); 3836 if (icand_sup.nonEmpty() && 3837 icand_sup.head != sym && 3838 icand_sup.head.overrides(sym, icand_sup.head.enclClass(), types, true)) { 3839 log.error(env.tree.pos(), "illegal.default.super.call", env.info.defaultSuperCallSite, 3840 diags.fragment("overridden.default", sym, sup)); 3841 break; 3842 } 3843 } 3844 env.info.defaultSuperCallSite = null; 3845 } 3846 3847 if (sym.isStatic() && site.isInterface() && env.tree.hasTag(APPLY)) { 3848 JCMethodInvocation app = (JCMethodInvocation)env.tree; 3849 if (app.meth.hasTag(SELECT) && 3850 !TreeInfo.isStaticSelector(((JCFieldAccess)app.meth).selected, names)) { 3851 log.error(env.tree.pos(), "illegal.static.intf.meth.call", site); 3852 } 3853 } 3854 3855 // Compute the identifier's instantiated type. 3856 // For methods, we need to compute the instance type by 3857 // Resolve.instantiate from the symbol's type as well as 3858 // any type arguments and value arguments. 3859 noteWarner.clear(); 3860 try { 3861 Type owntype = rs.checkMethod( 3862 env, 3863 site, 3864 sym, 3865 resultInfo, 3866 argtypes, 3867 typeargtypes, 3868 noteWarner); 3869 3870 DeferredAttr.DeferredTypeMap checkDeferredMap = 3871 deferredAttr.new DeferredTypeMap(DeferredAttr.AttrMode.CHECK, sym, env.info.pendingResolutionPhase); 3872 3873 argtypes = argtypes.map(checkDeferredMap); 3874 3875 if (noteWarner.hasNonSilentLint(LintCategory.UNCHECKED)) { 3876 chk.warnUnchecked(env.tree.pos(), 3877 "unchecked.meth.invocation.applied", 3878 kindName(sym), 3879 sym.name, 3880 rs.methodArguments(sym.type.getParameterTypes()), 3881 rs.methodArguments(argtypes.map(checkDeferredMap)), 3882 kindName(sym.location()), 3883 sym.location()); 3884 owntype = new MethodType(owntype.getParameterTypes(), 3885 types.erasure(owntype.getReturnType()), 3886 types.erasure(owntype.getThrownTypes()), 3887 syms.methodClass); 3888 } 3889 3890 return chk.checkMethod(owntype, sym, env, argtrees, argtypes, env.info.lastResolveVarargs(), 3891 resultInfo.checkContext.inferenceContext()); 3892 } catch (Infer.InferenceException ex) { 3893 //invalid target type - propagate exception outwards or report error 3894 //depending on the current check context 3895 resultInfo.checkContext.report(env.tree.pos(), ex.getDiagnostic()); 3896 return types.createErrorType(site); 3897 } catch (Resolve.InapplicableMethodException ex) { 3898 final JCDiagnostic diag = ex.getDiagnostic(); 3899 Resolve.InapplicableSymbolError errSym = rs.new InapplicableSymbolError(null) { 3900 @Override 3901 protected Pair<Symbol, JCDiagnostic> errCandidate() { 3902 return new Pair<>(sym, diag); 3903 } 3904 }; 3905 List<Type> argtypes2 = argtypes.map( 3906 rs.new ResolveDeferredRecoveryMap(AttrMode.CHECK, sym, env.info.pendingResolutionPhase)); 3907 JCDiagnostic errDiag = errSym.getDiagnostic(JCDiagnostic.DiagnosticType.ERROR, 3908 env.tree, sym, site, sym.name, argtypes2, typeargtypes); 3909 log.report(errDiag); 3910 return types.createErrorType(site); 3911 } 3912 } 3913 3914 public void visitLiteral(JCLiteral tree) { 3915 result = check(tree, litType(tree.typetag).constType(tree.value), 3916 KindSelector.VAL, resultInfo); 3917 } 3918 //where 3919 /** Return the type of a literal with given type tag. 3920 */ 3921 Type litType(TypeTag tag) { 3922 return (tag == CLASS) ? syms.stringType : syms.typeOfTag[tag.ordinal()]; 3923 } 3924 3925 public void visitTypeIdent(JCPrimitiveTypeTree tree) { 3926 result = check(tree, syms.typeOfTag[tree.typetag.ordinal()], KindSelector.TYP, resultInfo); 3927 } 3928 3929 public void visitTypeArray(JCArrayTypeTree tree) { 3930 Type etype = attribType(tree.elemtype, env); 3931 Type type = new ArrayType(etype, syms.arrayClass); 3932 result = check(tree, type, KindSelector.TYP, resultInfo); 3933 } 3934 3935 /** Visitor method for parameterized types. 3936 * Bound checking is left until later, since types are attributed 3937 * before supertype structure is completely known 3938 */ 3939 public void visitTypeApply(JCTypeApply tree) { 3940 Type owntype = types.createErrorType(tree.type); 3941 3942 // Attribute functor part of application and make sure it's a class. 3943 Type clazztype = chk.checkClassType(tree.clazz.pos(), attribType(tree.clazz, env)); 3944 3945 // Attribute type parameters 3946 List<Type> actuals = attribTypes(tree.arguments, env); 3947 3948 if (clazztype.hasTag(CLASS)) { 3949 List<Type> formals = clazztype.tsym.type.getTypeArguments(); 3950 if (actuals.isEmpty()) //diamond 3951 actuals = formals; 3952 3953 if (actuals.length() == formals.length()) { 3954 List<Type> a = actuals; 3955 List<Type> f = formals; 3956 while (a.nonEmpty()) { 3957 a.head = a.head.withTypeVar(f.head); 3958 a = a.tail; 3959 f = f.tail; 3960 } 3961 // Compute the proper generic outer 3962 Type clazzOuter = clazztype.getEnclosingType(); 3963 if (clazzOuter.hasTag(CLASS)) { 3964 Type site; 3965 JCExpression clazz = TreeInfo.typeIn(tree.clazz); 3966 if (clazz.hasTag(IDENT)) { 3967 site = env.enclClass.sym.type; 3968 } else if (clazz.hasTag(SELECT)) { 3969 site = ((JCFieldAccess) clazz).selected.type; 3970 } else throw new AssertionError(""+tree); 3971 if (clazzOuter.hasTag(CLASS) && site != clazzOuter) { 3972 if (site.hasTag(CLASS)) 3973 site = types.asOuterSuper(site, clazzOuter.tsym); 3974 if (site == null) 3975 site = types.erasure(clazzOuter); 3976 clazzOuter = site; 3977 } 3978 } 3979 owntype = new ClassType(clazzOuter, actuals, clazztype.tsym, 3980 clazztype.getMetadata()); 3981 } else { 3982 if (formals.length() != 0) { 3983 log.error(tree.pos(), "wrong.number.type.args", 3984 Integer.toString(formals.length())); 3985 } else { 3986 log.error(tree.pos(), "type.doesnt.take.params", clazztype.tsym); 3987 } 3988 owntype = types.createErrorType(tree.type); 3989 } 3990 } 3991 result = check(tree, owntype, KindSelector.TYP, resultInfo); 3992 } 3993 3994 public void visitTypeUnion(JCTypeUnion tree) { 3995 ListBuffer<Type> multicatchTypes = new ListBuffer<>(); 3996 ListBuffer<Type> all_multicatchTypes = null; // lazy, only if needed 3997 for (JCExpression typeTree : tree.alternatives) { 3998 Type ctype = attribType(typeTree, env); 3999 ctype = chk.checkType(typeTree.pos(), 4000 chk.checkClassType(typeTree.pos(), ctype), 4001 syms.throwableType); 4002 if (!ctype.isErroneous()) { 4003 //check that alternatives of a union type are pairwise 4004 //unrelated w.r.t. subtyping 4005 if (chk.intersects(ctype, multicatchTypes.toList())) { 4006 for (Type t : multicatchTypes) { 4007 boolean sub = types.isSubtype(ctype, t); 4008 boolean sup = types.isSubtype(t, ctype); 4009 if (sub || sup) { 4010 //assume 'a' <: 'b' 4011 Type a = sub ? ctype : t; 4012 Type b = sub ? t : ctype; 4013 log.error(typeTree.pos(), "multicatch.types.must.be.disjoint", a, b); 4014 } 4015 } 4016 } 4017 multicatchTypes.append(ctype); 4018 if (all_multicatchTypes != null) 4019 all_multicatchTypes.append(ctype); 4020 } else { 4021 if (all_multicatchTypes == null) { 4022 all_multicatchTypes = new ListBuffer<>(); 4023 all_multicatchTypes.appendList(multicatchTypes); 4024 } 4025 all_multicatchTypes.append(ctype); 4026 } 4027 } 4028 Type t = check(tree, types.lub(multicatchTypes.toList()), 4029 KindSelector.TYP, resultInfo.dup(CheckMode.NO_TREE_UPDATE)); 4030 if (t.hasTag(CLASS)) { 4031 List<Type> alternatives = 4032 ((all_multicatchTypes == null) ? multicatchTypes : all_multicatchTypes).toList(); 4033 t = new UnionClassType((ClassType) t, alternatives); 4034 } 4035 tree.type = result = t; 4036 } 4037 4038 public void visitTypeIntersection(JCTypeIntersection tree) { 4039 attribTypes(tree.bounds, env); 4040 tree.type = result = checkIntersection(tree, tree.bounds); 4041 } 4042 4043 public void visitTypeParameter(JCTypeParameter tree) { 4044 TypeVar typeVar = (TypeVar) tree.type; 4045 4046 if (tree.annotations != null && tree.annotations.nonEmpty()) { 4047 annotate.annotateTypeParameterSecondStage(tree, tree.annotations); 4048 } 4049 4050 if (!typeVar.bound.isErroneous()) { 4051 //fixup type-parameter bound computed in 'attribTypeVariables' 4052 typeVar.bound = checkIntersection(tree, tree.bounds); 4053 } 4054 } 4055 4056 Type checkIntersection(JCTree tree, List<JCExpression> bounds) { 4057 Set<Type> boundSet = new HashSet<>(); 4058 if (bounds.nonEmpty()) { 4059 // accept class or interface or typevar as first bound. 4060 bounds.head.type = checkBase(bounds.head.type, bounds.head, env, false, false, false); 4061 boundSet.add(types.erasure(bounds.head.type)); 4062 if (bounds.head.type.isErroneous()) { 4063 return bounds.head.type; 4064 } 4065 else if (bounds.head.type.hasTag(TYPEVAR)) { 4066 // if first bound was a typevar, do not accept further bounds. 4067 if (bounds.tail.nonEmpty()) { 4068 log.error(bounds.tail.head.pos(), 4069 "type.var.may.not.be.followed.by.other.bounds"); 4070 return bounds.head.type; 4071 } 4072 } else { 4073 // if first bound was a class or interface, accept only interfaces 4074 // as further bounds. 4075 for (JCExpression bound : bounds.tail) { 4076 bound.type = checkBase(bound.type, bound, env, false, true, false); 4077 if (bound.type.isErroneous()) { 4078 bounds = List.of(bound); 4079 } 4080 else if (bound.type.hasTag(CLASS)) { 4081 chk.checkNotRepeated(bound.pos(), types.erasure(bound.type), boundSet); 4082 } 4083 } 4084 } 4085 } 4086 4087 if (bounds.length() == 0) { 4088 return syms.objectType; 4089 } else if (bounds.length() == 1) { 4090 return bounds.head.type; 4091 } else { 4092 Type owntype = types.makeIntersectionType(TreeInfo.types(bounds)); 4093 // ... the variable's bound is a class type flagged COMPOUND 4094 // (see comment for TypeVar.bound). 4095 // In this case, generate a class tree that represents the 4096 // bound class, ... 4097 JCExpression extending; 4098 List<JCExpression> implementing; 4099 if (!bounds.head.type.isInterface()) { 4100 extending = bounds.head; 4101 implementing = bounds.tail; 4102 } else { 4103 extending = null; 4104 implementing = bounds; 4105 } 4106 JCClassDecl cd = make.at(tree).ClassDef( 4107 make.Modifiers(PUBLIC | ABSTRACT), 4108 names.empty, List.<JCTypeParameter>nil(), 4109 extending, implementing, List.<JCTree>nil()); 4110 4111 ClassSymbol c = (ClassSymbol)owntype.tsym; 4112 Assert.check((c.flags() & COMPOUND) != 0); 4113 cd.sym = c; 4114 c.sourcefile = env.toplevel.sourcefile; 4115 4116 // ... and attribute the bound class 4117 c.flags_field |= UNATTRIBUTED; 4118 Env<AttrContext> cenv = enter.classEnv(cd, env); 4119 typeEnvs.put(c, cenv); 4120 attribClass(c); 4121 return owntype; 4122 } 4123 } 4124 4125 public void visitWildcard(JCWildcard tree) { 4126 //- System.err.println("visitWildcard("+tree+");");//DEBUG 4127 Type type = (tree.kind.kind == BoundKind.UNBOUND) 4128 ? syms.objectType 4129 : attribType(tree.inner, env); 4130 result = check(tree, new WildcardType(chk.checkRefType(tree.pos(), type), 4131 tree.kind.kind, 4132 syms.boundClass), 4133 KindSelector.TYP, resultInfo); 4134 } 4135 4136 public void visitAnnotation(JCAnnotation tree) { 4137 Assert.error("should be handled in annotate"); 4138 } 4139 4140 public void visitAnnotatedType(JCAnnotatedType tree) { 4141 attribAnnotationTypes(tree.annotations, env); 4142 Type underlyingType = attribType(tree.underlyingType, env); 4143 Type annotatedType = underlyingType.annotatedType(Annotations.TO_BE_SET); 4144 4145 if (!env.info.isNewClass) 4146 annotate.annotateTypeSecondStage(tree, tree.annotations, annotatedType); 4147 result = tree.type = annotatedType; 4148 } 4149 4150 public void visitErroneous(JCErroneous tree) { 4151 if (tree.errs != null) 4152 for (JCTree err : tree.errs) 4153 attribTree(err, env, new ResultInfo(KindSelector.ERR, pt())); 4154 result = tree.type = syms.errType; 4155 } 4156 4157 /** Default visitor method for all other trees. 4158 */ 4159 public void visitTree(JCTree tree) { 4160 throw new AssertionError(); 4161 } 4162 4163 /** 4164 * Attribute an env for either a top level tree or class declaration. 4165 */ 4166 public void attrib(Env<AttrContext> env) { 4167 if (env.tree.hasTag(TOPLEVEL)) 4168 attribTopLevel(env); 4169 else 4170 attribClass(env.tree.pos(), env.enclClass.sym); 4171 } 4172 4173 /** 4174 * Attribute a top level tree. These trees are encountered when the 4175 * package declaration has annotations. 4176 */ 4177 public void attribTopLevel(Env<AttrContext> env) { 4178 JCCompilationUnit toplevel = env.toplevel; 4179 try { 4180 annotate.flush(); 4181 } catch (CompletionFailure ex) { 4182 chk.completionError(toplevel.pos(), ex); 4183 } 4184 } 4185 4186 /** Main method: attribute class definition associated with given class symbol. 4187 * reporting completion failures at the given position. 4188 * @param pos The source position at which completion errors are to be 4189 * reported. 4190 * @param c The class symbol whose definition will be attributed. 4191 */ 4192 public void attribClass(DiagnosticPosition pos, ClassSymbol c) { 4193 try { 4194 annotate.flush(); 4195 attribClass(c); 4196 } catch (CompletionFailure ex) { 4197 chk.completionError(pos, ex); 4198 } 4199 } 4200 4201 /** Attribute class definition associated with given class symbol. 4202 * @param c The class symbol whose definition will be attributed. 4203 */ 4204 void attribClass(ClassSymbol c) throws CompletionFailure { 4205 if (c.type.hasTag(ERROR)) return; 4206 4207 // Check for cycles in the inheritance graph, which can arise from 4208 // ill-formed class files. 4209 chk.checkNonCyclic(null, c.type); 4210 4211 Type st = types.supertype(c.type); 4212 if ((c.flags_field & Flags.COMPOUND) == 0) { 4213 // First, attribute superclass. 4214 if (st.hasTag(CLASS)) 4215 attribClass((ClassSymbol)st.tsym); 4216 4217 // Next attribute owner, if it is a class. 4218 if (c.owner.kind == TYP && c.owner.type.hasTag(CLASS)) 4219 attribClass((ClassSymbol)c.owner); 4220 } 4221 4222 // The previous operations might have attributed the current class 4223 // if there was a cycle. So we test first whether the class is still 4224 // UNATTRIBUTED. 4225 if ((c.flags_field & UNATTRIBUTED) != 0) { 4226 c.flags_field &= ~UNATTRIBUTED; 4227 4228 // Get environment current at the point of class definition. 4229 Env<AttrContext> env = typeEnvs.get(c); 4230 4231 // The info.lint field in the envs stored in typeEnvs is deliberately uninitialized, 4232 // because the annotations were not available at the time the env was created. Therefore, 4233 // we look up the environment chain for the first enclosing environment for which the 4234 // lint value is set. Typically, this is the parent env, but might be further if there 4235 // are any envs created as a result of TypeParameter nodes. 4236 Env<AttrContext> lintEnv = env; 4237 while (lintEnv.info.lint == null) 4238 lintEnv = lintEnv.next; 4239 4240 // Having found the enclosing lint value, we can initialize the lint value for this class 4241 env.info.lint = lintEnv.info.lint.augment(c); 4242 4243 Lint prevLint = chk.setLint(env.info.lint); 4244 JavaFileObject prev = log.useSource(c.sourcefile); 4245 ResultInfo prevReturnRes = env.info.returnResult; 4246 4247 try { 4248 deferredLintHandler.flush(env.tree); 4249 env.info.returnResult = null; 4250 // java.lang.Enum may not be subclassed by a non-enum 4251 if (st.tsym == syms.enumSym && 4252 ((c.flags_field & (Flags.ENUM|Flags.COMPOUND)) == 0)) 4253 log.error(env.tree.pos(), "enum.no.subclassing"); 4254 4255 // Enums may not be extended by source-level classes 4256 if (st.tsym != null && 4257 ((st.tsym.flags_field & Flags.ENUM) != 0) && 4258 ((c.flags_field & (Flags.ENUM | Flags.COMPOUND)) == 0)) { 4259 log.error(env.tree.pos(), "enum.types.not.extensible"); 4260 } 4261 4262 if (isSerializable(c.type)) { 4263 env.info.isSerializable = true; 4264 } 4265 4266 attribClassBody(env, c); 4267 4268 chk.checkDeprecatedAnnotation(env.tree.pos(), c); 4269 chk.checkClassOverrideEqualsAndHashIfNeeded(env.tree.pos(), c); 4270 chk.checkFunctionalInterface((JCClassDecl) env.tree, c); 4271 } finally { 4272 env.info.returnResult = prevReturnRes; 4273 log.useSource(prev); 4274 chk.setLint(prevLint); 4275 } 4276 4277 } 4278 } 4279 4280 public void visitImport(JCImport tree) { 4281 // nothing to do 4282 } 4283 4284 /** Finish the attribution of a class. */ 4285 private void attribClassBody(Env<AttrContext> env, ClassSymbol c) { 4286 JCClassDecl tree = (JCClassDecl)env.tree; 4287 Assert.check(c == tree.sym); 4288 4289 // Validate type parameters, supertype and interfaces. 4290 attribStats(tree.typarams, env); 4291 if (!c.isAnonymous()) { 4292 //already checked if anonymous 4293 chk.validate(tree.typarams, env); 4294 chk.validate(tree.extending, env); 4295 chk.validate(tree.implementing, env); 4296 } 4297 4298 c.markAbstractIfNeeded(types); 4299 4300 // If this is a non-abstract class, check that it has no abstract 4301 // methods or unimplemented methods of an implemented interface. 4302 if ((c.flags() & (ABSTRACT | INTERFACE)) == 0) { 4303 if (!relax) 4304 chk.checkAllDefined(tree.pos(), c); 4305 } 4306 4307 if ((c.flags() & ANNOTATION) != 0) { 4308 if (tree.implementing.nonEmpty()) 4309 log.error(tree.implementing.head.pos(), 4310 "cant.extend.intf.annotation"); 4311 if (tree.typarams.nonEmpty()) 4312 log.error(tree.typarams.head.pos(), 4313 "intf.annotation.cant.have.type.params"); 4314 4315 // If this annotation type has a @Repeatable, validate 4316 Attribute.Compound repeatable = c.getAnnotationTypeMetadata().getRepeatable(); 4317 // If this annotation type has a @Repeatable, validate 4318 if (repeatable != null) { 4319 // get diagnostic position for error reporting 4320 DiagnosticPosition cbPos = getDiagnosticPosition(tree, repeatable.type); 4321 Assert.checkNonNull(cbPos); 4322 4323 chk.validateRepeatable(c, repeatable, cbPos); 4324 } 4325 } else { 4326 // Check that all extended classes and interfaces 4327 // are compatible (i.e. no two define methods with same arguments 4328 // yet different return types). (JLS 8.4.6.3) 4329 chk.checkCompatibleSupertypes(tree.pos(), c.type); 4330 if (allowDefaultMethods) { 4331 chk.checkDefaultMethodClashes(tree.pos(), c.type); 4332 } 4333 } 4334 4335 // Check that class does not import the same parameterized interface 4336 // with two different argument lists. 4337 chk.checkClassBounds(tree.pos(), c.type); 4338 4339 tree.type = c.type; 4340 4341 for (List<JCTypeParameter> l = tree.typarams; 4342 l.nonEmpty(); l = l.tail) { 4343 Assert.checkNonNull(env.info.scope.findFirst(l.head.name)); 4344 } 4345 4346 // Check that a generic class doesn't extend Throwable 4347 if (!c.type.allparams().isEmpty() && types.isSubtype(c.type, syms.throwableType)) 4348 log.error(tree.extending.pos(), "generic.throwable"); 4349 4350 // Check that all methods which implement some 4351 // method conform to the method they implement. 4352 chk.checkImplementations(tree); 4353 4354 //check that a resource implementing AutoCloseable cannot throw InterruptedException 4355 checkAutoCloseable(tree.pos(), env, c.type); 4356 4357 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { 4358 // Attribute declaration 4359 attribStat(l.head, env); 4360 // Check that declarations in inner classes are not static (JLS 8.1.2) 4361 // Make an exception for static constants. 4362 if (c.owner.kind != PCK && 4363 ((c.flags() & STATIC) == 0 || c.name == names.empty) && 4364 (TreeInfo.flags(l.head) & (STATIC | INTERFACE)) != 0) { 4365 Symbol sym = null; 4366 if (l.head.hasTag(VARDEF)) sym = ((JCVariableDecl) l.head).sym; 4367 if (sym == null || 4368 sym.kind != VAR || 4369 ((VarSymbol) sym).getConstValue() == null) 4370 log.error(l.head.pos(), "icls.cant.have.static.decl", c); 4371 } 4372 } 4373 4374 // Check for cycles among non-initial constructors. 4375 chk.checkCyclicConstructors(tree); 4376 4377 // Check for cycles among annotation elements. 4378 chk.checkNonCyclicElements(tree); 4379 4380 // Check for proper use of serialVersionUID 4381 if (env.info.lint.isEnabled(LintCategory.SERIAL) && 4382 isSerializable(c.type) && 4383 (c.flags() & Flags.ENUM) == 0 && 4384 checkForSerial(c)) { 4385 checkSerialVersionUID(tree, c); 4386 } 4387 if (allowTypeAnnos) { 4388 // Correctly organize the postions of the type annotations 4389 typeAnnotations.organizeTypeAnnotationsBodies(tree); 4390 4391 // Check type annotations applicability rules 4392 validateTypeAnnotations(tree, false); 4393 } 4394 } 4395 // where 4396 boolean checkForSerial(ClassSymbol c) { 4397 if ((c.flags() & ABSTRACT) == 0) { 4398 return true; 4399 } else { 4400 return c.members().anyMatch(anyNonAbstractOrDefaultMethod); 4401 } 4402 } 4403 4404 public static final Filter<Symbol> anyNonAbstractOrDefaultMethod = new Filter<Symbol>() { 4405 @Override 4406 public boolean accepts(Symbol s) { 4407 return s.kind == MTH && 4408 (s.flags() & (DEFAULT | ABSTRACT)) != ABSTRACT; 4409 } 4410 }; 4411 4412 /** get a diagnostic position for an attribute of Type t, or null if attribute missing */ 4413 private DiagnosticPosition getDiagnosticPosition(JCClassDecl tree, Type t) { 4414 for(List<JCAnnotation> al = tree.mods.annotations; !al.isEmpty(); al = al.tail) { 4415 if (types.isSameType(al.head.annotationType.type, t)) 4416 return al.head.pos(); 4417 } 4418 4419 return null; 4420 } 4421 4422 /** check if a type is a subtype of Serializable, if that is available. */ 4423 boolean isSerializable(Type t) { 4424 try { 4425 syms.serializableType.complete(); 4426 } 4427 catch (CompletionFailure e) { 4428 return false; 4429 } 4430 return types.isSubtype(t, syms.serializableType); 4431 } 4432 4433 /** Check that an appropriate serialVersionUID member is defined. */ 4434 private void checkSerialVersionUID(JCClassDecl tree, ClassSymbol c) { 4435 4436 // check for presence of serialVersionUID 4437 VarSymbol svuid = null; 4438 for (Symbol sym : c.members().getSymbolsByName(names.serialVersionUID)) { 4439 if (sym.kind == VAR) { 4440 svuid = (VarSymbol)sym; 4441 break; 4442 } 4443 } 4444 4445 if (svuid == null) { 4446 log.warning(LintCategory.SERIAL, 4447 tree.pos(), "missing.SVUID", c); 4448 return; 4449 } 4450 4451 // check that it is static final 4452 if ((svuid.flags() & (STATIC | FINAL)) != 4453 (STATIC | FINAL)) 4454 log.warning(LintCategory.SERIAL, 4455 TreeInfo.diagnosticPositionFor(svuid, tree), "improper.SVUID", c); 4456 4457 // check that it is long 4458 else if (!svuid.type.hasTag(LONG)) 4459 log.warning(LintCategory.SERIAL, 4460 TreeInfo.diagnosticPositionFor(svuid, tree), "long.SVUID", c); 4461 4462 // check constant 4463 else if (svuid.getConstValue() == null) 4464 log.warning(LintCategory.SERIAL, 4465 TreeInfo.diagnosticPositionFor(svuid, tree), "constant.SVUID", c); 4466 } 4467 4468 private Type capture(Type type) { 4469 return types.capture(type); 4470 } 4471 4472 public void validateTypeAnnotations(JCTree tree, boolean sigOnly) { 4473 tree.accept(new TypeAnnotationsValidator(sigOnly)); 4474 } 4475 //where 4476 private final class TypeAnnotationsValidator extends TreeScanner { 4477 4478 private final boolean sigOnly; 4479 public TypeAnnotationsValidator(boolean sigOnly) { 4480 this.sigOnly = sigOnly; 4481 } 4482 4483 public void visitAnnotation(JCAnnotation tree) { 4484 chk.validateTypeAnnotation(tree, false); 4485 super.visitAnnotation(tree); 4486 } 4487 public void visitAnnotatedType(JCAnnotatedType tree) { 4488 if (!tree.underlyingType.type.isErroneous()) { 4489 super.visitAnnotatedType(tree); 4490 } 4491 } 4492 public void visitTypeParameter(JCTypeParameter tree) { 4493 chk.validateTypeAnnotations(tree.annotations, true); 4494 scan(tree.bounds); 4495 // Don't call super. 4496 // This is needed because above we call validateTypeAnnotation with 4497 // false, which would forbid annotations on type parameters. 4498 // super.visitTypeParameter(tree); 4499 } 4500 public void visitMethodDef(JCMethodDecl tree) { 4501 if (tree.recvparam != null && 4502 !tree.recvparam.vartype.type.isErroneous()) { 4503 checkForDeclarationAnnotations(tree.recvparam.mods.annotations, 4504 tree.recvparam.vartype.type.tsym); 4505 } 4506 if (tree.restype != null && tree.restype.type != null) { 4507 validateAnnotatedType(tree.restype, tree.restype.type); 4508 } 4509 if (sigOnly) { 4510 scan(tree.mods); 4511 scan(tree.restype); 4512 scan(tree.typarams); 4513 scan(tree.recvparam); 4514 scan(tree.params); 4515 scan(tree.thrown); 4516 } else { 4517 scan(tree.defaultValue); 4518 scan(tree.body); 4519 } 4520 } 4521 public void visitVarDef(final JCVariableDecl tree) { 4522 //System.err.println("validateTypeAnnotations.visitVarDef " + tree); 4523 if (tree.sym != null && tree.sym.type != null) 4524 validateAnnotatedType(tree.vartype, tree.sym.type); 4525 scan(tree.mods); 4526 scan(tree.vartype); 4527 if (!sigOnly) { 4528 scan(tree.init); 4529 } 4530 } 4531 public void visitTypeCast(JCTypeCast tree) { 4532 if (tree.clazz != null && tree.clazz.type != null) 4533 validateAnnotatedType(tree.clazz, tree.clazz.type); 4534 super.visitTypeCast(tree); 4535 } 4536 public void visitTypeTest(JCInstanceOf tree) { 4537 if (tree.clazz != null && tree.clazz.type != null) 4538 validateAnnotatedType(tree.clazz, tree.clazz.type); 4539 super.visitTypeTest(tree); 4540 } 4541 public void visitNewClass(JCNewClass tree) { 4542 if (tree.clazz != null && tree.clazz.type != null) { 4543 if (tree.clazz.hasTag(ANNOTATED_TYPE)) { 4544 checkForDeclarationAnnotations(((JCAnnotatedType) tree.clazz).annotations, 4545 tree.clazz.type.tsym); 4546 } 4547 if (tree.def != null) { 4548 checkForDeclarationAnnotations(tree.def.mods.annotations, tree.clazz.type.tsym); 4549 } 4550 4551 validateAnnotatedType(tree.clazz, tree.clazz.type); 4552 } 4553 super.visitNewClass(tree); 4554 } 4555 public void visitNewArray(JCNewArray tree) { 4556 if (tree.elemtype != null && tree.elemtype.type != null) { 4557 if (tree.elemtype.hasTag(ANNOTATED_TYPE)) { 4558 checkForDeclarationAnnotations(((JCAnnotatedType) tree.elemtype).annotations, 4559 tree.elemtype.type.tsym); 4560 } 4561 validateAnnotatedType(tree.elemtype, tree.elemtype.type); 4562 } 4563 super.visitNewArray(tree); 4564 } 4565 public void visitClassDef(JCClassDecl tree) { 4566 //System.err.println("validateTypeAnnotations.visitClassDef " + tree); 4567 if (sigOnly) { 4568 scan(tree.mods); 4569 scan(tree.typarams); 4570 scan(tree.extending); 4571 scan(tree.implementing); 4572 } 4573 for (JCTree member : tree.defs) { 4574 if (member.hasTag(Tag.CLASSDEF)) { 4575 continue; 4576 } 4577 scan(member); 4578 } 4579 } 4580 public void visitBlock(JCBlock tree) { 4581 if (!sigOnly) { 4582 scan(tree.stats); 4583 } 4584 } 4585 4586 /* I would want to model this after 4587 * com.sun.tools.javac.comp.Check.Validator.visitSelectInternal(JCFieldAccess) 4588 * and override visitSelect and visitTypeApply. 4589 * However, we only set the annotated type in the top-level type 4590 * of the symbol. 4591 * Therefore, we need to override each individual location where a type 4592 * can occur. 4593 */ 4594 private void validateAnnotatedType(final JCTree errtree, final Type type) { 4595 //System.err.println("Attr.validateAnnotatedType: " + errtree + " type: " + type); 4596 4597 if (type.isPrimitiveOrVoid()) { 4598 return; 4599 } 4600 4601 JCTree enclTr = errtree; 4602 Type enclTy = type; 4603 4604 boolean repeat = true; 4605 while (repeat) { 4606 if (enclTr.hasTag(TYPEAPPLY)) { 4607 List<Type> tyargs = enclTy.getTypeArguments(); 4608 List<JCExpression> trargs = ((JCTypeApply)enclTr).getTypeArguments(); 4609 if (trargs.length() > 0) { 4610 // Nothing to do for diamonds 4611 if (tyargs.length() == trargs.length()) { 4612 for (int i = 0; i < tyargs.length(); ++i) { 4613 validateAnnotatedType(trargs.get(i), tyargs.get(i)); 4614 } 4615 } 4616 // If the lengths don't match, it's either a diamond 4617 // or some nested type that redundantly provides 4618 // type arguments in the tree. 4619 } 4620 4621 // Look at the clazz part of a generic type 4622 enclTr = ((JCTree.JCTypeApply)enclTr).clazz; 4623 } 4624 4625 if (enclTr.hasTag(SELECT)) { 4626 enclTr = ((JCTree.JCFieldAccess)enclTr).getExpression(); 4627 if (enclTy != null && 4628 !enclTy.hasTag(NONE)) { 4629 enclTy = enclTy.getEnclosingType(); 4630 } 4631 } else if (enclTr.hasTag(ANNOTATED_TYPE)) { 4632 JCAnnotatedType at = (JCTree.JCAnnotatedType) enclTr; 4633 if (enclTy == null || enclTy.hasTag(NONE)) { 4634 if (at.getAnnotations().size() == 1) { 4635 log.error(at.underlyingType.pos(), "cant.type.annotate.scoping.1", at.getAnnotations().head.attribute); 4636 } else { 4637 ListBuffer<Attribute.Compound> comps = new ListBuffer<>(); 4638 for (JCAnnotation an : at.getAnnotations()) { 4639 comps.add(an.attribute); 4640 } 4641 log.error(at.underlyingType.pos(), "cant.type.annotate.scoping", comps.toList()); 4642 } 4643 repeat = false; 4644 } 4645 enclTr = at.underlyingType; 4646 // enclTy doesn't need to be changed 4647 } else if (enclTr.hasTag(IDENT)) { 4648 repeat = false; 4649 } else if (enclTr.hasTag(JCTree.Tag.WILDCARD)) { 4650 JCWildcard wc = (JCWildcard) enclTr; 4651 if (wc.getKind() == JCTree.Kind.EXTENDS_WILDCARD) { 4652 validateAnnotatedType(wc.getBound(), ((WildcardType)enclTy).getExtendsBound()); 4653 } else if (wc.getKind() == JCTree.Kind.SUPER_WILDCARD) { 4654 validateAnnotatedType(wc.getBound(), ((WildcardType)enclTy).getSuperBound()); 4655 } else { 4656 // Nothing to do for UNBOUND 4657 } 4658 repeat = false; 4659 } else if (enclTr.hasTag(TYPEARRAY)) { 4660 JCArrayTypeTree art = (JCArrayTypeTree) enclTr; 4661 validateAnnotatedType(art.getType(), ((ArrayType)enclTy).getComponentType()); 4662 repeat = false; 4663 } else if (enclTr.hasTag(TYPEUNION)) { 4664 JCTypeUnion ut = (JCTypeUnion) enclTr; 4665 for (JCTree t : ut.getTypeAlternatives()) { 4666 validateAnnotatedType(t, t.type); 4667 } 4668 repeat = false; 4669 } else if (enclTr.hasTag(TYPEINTERSECTION)) { 4670 JCTypeIntersection it = (JCTypeIntersection) enclTr; 4671 for (JCTree t : it.getBounds()) { 4672 validateAnnotatedType(t, t.type); 4673 } 4674 repeat = false; 4675 } else if (enclTr.getKind() == JCTree.Kind.PRIMITIVE_TYPE || 4676 enclTr.getKind() == JCTree.Kind.ERRONEOUS) { 4677 repeat = false; 4678 } else { 4679 Assert.error("Unexpected tree: " + enclTr + " with kind: " + enclTr.getKind() + 4680 " within: "+ errtree + " with kind: " + errtree.getKind()); 4681 } 4682 } 4683 } 4684 4685 private void checkForDeclarationAnnotations(List<? extends JCAnnotation> annotations, 4686 Symbol sym) { 4687 // Ensure that no declaration annotations are present. 4688 // Note that a tree type might be an AnnotatedType with 4689 // empty annotations, if only declaration annotations were given. 4690 // This method will raise an error for such a type. 4691 for (JCAnnotation ai : annotations) { 4692 if (!ai.type.isErroneous() && 4693 typeAnnotations.annotationTargetType(ai.attribute, sym) == TypeAnnotations.AnnotationType.DECLARATION) { 4694 log.error(ai.pos(), Errors.AnnotationTypeNotApplicableToType(ai.type)); 4695 } 4696 } 4697 } 4698 } 4699 4700 // <editor-fold desc="post-attribution visitor"> 4701 4702 /** 4703 * Handle missing types/symbols in an AST. This routine is useful when 4704 * the compiler has encountered some errors (which might have ended up 4705 * terminating attribution abruptly); if the compiler is used in fail-over 4706 * mode (e.g. by an IDE) and the AST contains semantic errors, this routine 4707 * prevents NPE to be progagated during subsequent compilation steps. 4708 */ 4709 public void postAttr(JCTree tree) { 4710 new PostAttrAnalyzer().scan(tree); 4711 } 4712 4713 class PostAttrAnalyzer extends TreeScanner { 4714 4715 private void initTypeIfNeeded(JCTree that) { 4716 if (that.type == null) { 4717 if (that.hasTag(METHODDEF)) { 4718 that.type = dummyMethodType((JCMethodDecl)that); 4719 } else { 4720 that.type = syms.unknownType; 4721 } 4722 } 4723 } 4724 4725 /* Construct a dummy method type. If we have a method declaration, 4726 * and the declared return type is void, then use that return type 4727 * instead of UNKNOWN to avoid spurious error messages in lambda 4728 * bodies (see:JDK-8041704). 4729 */ 4730 private Type dummyMethodType(JCMethodDecl md) { 4731 Type restype = syms.unknownType; 4732 if (md != null && md.restype.hasTag(TYPEIDENT)) { 4733 JCPrimitiveTypeTree prim = (JCPrimitiveTypeTree)md.restype; 4734 if (prim.typetag == VOID) 4735 restype = syms.voidType; 4736 } 4737 return new MethodType(List.<Type>nil(), restype, 4738 List.<Type>nil(), syms.methodClass); 4739 } 4740 private Type dummyMethodType() { 4741 return dummyMethodType(null); 4742 } 4743 4744 @Override 4745 public void scan(JCTree tree) { 4746 if (tree == null) return; 4747 if (tree instanceof JCExpression) { 4748 initTypeIfNeeded(tree); 4749 } 4750 super.scan(tree); 4751 } 4752 4753 @Override 4754 public void visitIdent(JCIdent that) { 4755 if (that.sym == null) { 4756 that.sym = syms.unknownSymbol; 4757 } 4758 } 4759 4760 @Override 4761 public void visitSelect(JCFieldAccess that) { 4762 if (that.sym == null) { 4763 that.sym = syms.unknownSymbol; 4764 } 4765 super.visitSelect(that); 4766 } 4767 4768 @Override 4769 public void visitClassDef(JCClassDecl that) { 4770 initTypeIfNeeded(that); 4771 if (that.sym == null) { 4772 that.sym = new ClassSymbol(0, that.name, that.type, syms.noSymbol); 4773 } 4774 super.visitClassDef(that); 4775 } 4776 4777 @Override 4778 public void visitMethodDef(JCMethodDecl that) { 4779 initTypeIfNeeded(that); 4780 if (that.sym == null) { 4781 that.sym = new MethodSymbol(0, that.name, that.type, syms.noSymbol); 4782 } 4783 super.visitMethodDef(that); 4784 } 4785 4786 @Override 4787 public void visitVarDef(JCVariableDecl that) { 4788 initTypeIfNeeded(that); 4789 if (that.sym == null) { 4790 that.sym = new VarSymbol(0, that.name, that.type, syms.noSymbol); 4791 that.sym.adr = 0; 4792 } 4793 super.visitVarDef(that); 4794 } 4795 4796 @Override 4797 public void visitNewClass(JCNewClass that) { 4798 if (that.constructor == null) { 4799 that.constructor = new MethodSymbol(0, names.init, 4800 dummyMethodType(), syms.noSymbol); 4801 } 4802 if (that.constructorType == null) { 4803 that.constructorType = syms.unknownType; 4804 } 4805 super.visitNewClass(that); 4806 } 4807 4808 @Override 4809 public void visitAssignop(JCAssignOp that) { 4810 if (that.operator == null) { 4811 that.operator = new OperatorSymbol(names.empty, dummyMethodType(), 4812 -1, syms.noSymbol); 4813 } 4814 super.visitAssignop(that); 4815 } 4816 4817 @Override 4818 public void visitBinary(JCBinary that) { 4819 if (that.operator == null) { 4820 that.operator = new OperatorSymbol(names.empty, dummyMethodType(), 4821 -1, syms.noSymbol); 4822 } 4823 super.visitBinary(that); 4824 } 4825 4826 @Override 4827 public void visitUnary(JCUnary that) { 4828 if (that.operator == null) { 4829 that.operator = new OperatorSymbol(names.empty, dummyMethodType(), 4830 -1, syms.noSymbol); 4831 } 4832 super.visitUnary(that); 4833 } 4834 4835 @Override 4836 public void visitLambda(JCLambda that) { 4837 super.visitLambda(that); 4838 if (that.targets == null) { 4839 that.targets = List.nil(); 4840 } 4841 } 4842 4843 @Override 4844 public void visitReference(JCMemberReference that) { 4845 super.visitReference(that); 4846 if (that.sym == null) { 4847 that.sym = new MethodSymbol(0, names.empty, dummyMethodType(), 4848 syms.noSymbol); 4849 } 4850 if (that.targets == null) { 4851 that.targets = List.nil(); 4852 } 4853 } 4854 } 4855 // </editor-fold> 4856} 4857