1 /* 2 * Copyright (c) 1999, 2024, 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 26 package com.sun.tools.javac.comp; 27 28 import java.util.*; 29 import java.util.function.BiConsumer; 30 import java.util.function.Consumer; 31 import java.util.function.Function; 32 import java.util.stream.Stream; 33 34 import javax.lang.model.element.ElementKind; 35 import javax.tools.JavaFileObject; 36 37 import com.sun.source.tree.CaseTree; 38 import com.sun.source.tree.IdentifierTree; 39 import com.sun.source.tree.LambdaExpressionTree.BodyKind; 40 import com.sun.source.tree.MemberReferenceTree.ReferenceMode; 41 import com.sun.source.tree.MemberSelectTree; 42 import com.sun.source.tree.TreeVisitor; 43 import com.sun.source.util.SimpleTreeVisitor; 44 import com.sun.tools.javac.code.*; 45 import com.sun.tools.javac.code.Lint.LintCategory; 46 import com.sun.tools.javac.code.Scope.WriteableScope; 47 import com.sun.tools.javac.code.Source.Feature; 48 import com.sun.tools.javac.code.Symbol.*; 49 import com.sun.tools.javac.code.Type.*; 50 import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError; 51 import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext; 52 import com.sun.tools.javac.comp.Attr.ResultInfo; 53 import com.sun.tools.javac.comp.Check.CheckContext; 54 import com.sun.tools.javac.comp.Check.NestedCheckContext; 55 import com.sun.tools.javac.comp.DeferredAttr.AttrMode; 56 import com.sun.tools.javac.comp.DeferredAttr.LambdaReturnScanner; 57 import com.sun.tools.javac.comp.MatchBindingsComputer.MatchBindings; 58 import com.sun.tools.javac.jvm.*; 59 60 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.Diamond; 61 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArg; 62 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.DiamondInvalidArgs; 63 64 import com.sun.tools.javac.resources.CompilerProperties.Errors; 65 import com.sun.tools.javac.resources.CompilerProperties.Fragments; 66 import com.sun.tools.javac.resources.CompilerProperties.Warnings; 67 import com.sun.tools.javac.tree.*; 68 import com.sun.tools.javac.tree.JCTree.*; 69 import com.sun.tools.javac.tree.JCTree.JCLambda.ParameterKind; 70 import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*; 71 import com.sun.tools.javac.util.*; 72 import com.sun.tools.javac.util.DefinedBy.Api; 73 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 74 import com.sun.tools.javac.util.JCDiagnostic.Error; 75 import com.sun.tools.javac.util.JCDiagnostic.Fragment; 76 import com.sun.tools.javac.util.JCDiagnostic.Warning; 77 import com.sun.tools.javac.util.List; 78 79 import static com.sun.tools.javac.code.Flags.*; 80 import static com.sun.tools.javac.code.Flags.ANNOTATION; 81 import static com.sun.tools.javac.code.Flags.BLOCK; 82 import static com.sun.tools.javac.code.Kinds.*; 83 import static com.sun.tools.javac.code.Kinds.Kind.*; 84 import static com.sun.tools.javac.code.TypeTag.*; 85 import static com.sun.tools.javac.code.TypeTag.WILDCARD; 86 import static com.sun.tools.javac.tree.JCTree.Tag.*; 87 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; 88 89 /** This is the main context-dependent analysis phase in GJC. It 90 * encompasses name resolution, type checking and constant folding as 91 * subtasks. Some subtasks involve auxiliary classes. 92 * @see Check 93 * @see Resolve 94 * @see ConstFold 95 * @see Infer 96 * 97 * <p><b>This is NOT part of any supported API. 98 * If you write code that depends on this, you do so at your own risk. 99 * This code and its internal interfaces are subject to change or 100 * deletion without notice.</b> 101 */ 102 public class Attr extends JCTree.Visitor { 103 protected static final Context.Key<Attr> attrKey = new Context.Key<>(); 104 105 final Names names; 106 final Log log; 107 final Symtab syms; 108 final Resolve rs; 109 final Operators operators; 110 final Infer infer; 111 final Analyzer analyzer; 112 final DeferredAttr deferredAttr; 113 final Check chk; 114 final Flow flow; 115 final MemberEnter memberEnter; 116 final TypeEnter typeEnter; 117 final TreeMaker make; 118 final ConstFold cfolder; 119 final Enter enter; 120 final Target target; 121 final Types types; 122 final Preview preview; 123 final JCDiagnostic.Factory diags; 124 final TypeAnnotations typeAnnotations; 125 final DeferredLintHandler deferredLintHandler; 126 final TypeEnvs typeEnvs; 127 final Dependencies dependencies; 128 final Annotate annotate; 129 final ArgumentAttr argumentAttr; 130 final MatchBindingsComputer matchBindingsComputer; 131 final AttrRecover attrRecover; 132 133 public static Attr instance(Context context) { 134 Attr instance = context.get(attrKey); 135 if (instance == null) 136 instance = new Attr(context); 137 return instance; 138 } 139 140 @SuppressWarnings("this-escape") 141 protected Attr(Context context) { 142 context.put(attrKey, this); 143 144 names = Names.instance(context); 145 log = Log.instance(context); 146 syms = Symtab.instance(context); 147 rs = Resolve.instance(context); 148 operators = Operators.instance(context); 149 chk = Check.instance(context); 150 flow = Flow.instance(context); 151 memberEnter = MemberEnter.instance(context); 152 typeEnter = TypeEnter.instance(context); 153 make = TreeMaker.instance(context); 154 enter = Enter.instance(context); 155 infer = Infer.instance(context); 156 analyzer = Analyzer.instance(context); 157 deferredAttr = DeferredAttr.instance(context); 158 cfolder = ConstFold.instance(context); 159 target = Target.instance(context); 160 types = Types.instance(context); 161 preview = Preview.instance(context); 162 diags = JCDiagnostic.Factory.instance(context); 163 annotate = Annotate.instance(context); 164 typeAnnotations = TypeAnnotations.instance(context); 165 deferredLintHandler = DeferredLintHandler.instance(context); 166 typeEnvs = TypeEnvs.instance(context); 167 dependencies = Dependencies.instance(context); 168 argumentAttr = ArgumentAttr.instance(context); 169 matchBindingsComputer = MatchBindingsComputer.instance(context); 170 attrRecover = AttrRecover.instance(context); 171 172 Options options = Options.instance(context); 173 174 Source source = Source.instance(context); 175 allowReifiableTypesInInstanceof = Feature.REIFIABLE_TYPES_INSTANCEOF.allowedInSource(source); 176 allowRecords = Feature.RECORDS.allowedInSource(source); 177 allowPatternSwitch = (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH)) && 178 Feature.PATTERN_SWITCH.allowedInSource(source); 179 allowUnconditionalPatternsInstanceOf = 180 Feature.UNCONDITIONAL_PATTERN_IN_INSTANCEOF.allowedInSource(source); 181 sourceName = source.name; 182 useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning"); 183 184 statInfo = new ResultInfo(KindSelector.NIL, Type.noType); 185 varAssignmentInfo = new ResultInfo(KindSelector.ASG, Type.noType); 186 unknownExprInfo = new ResultInfo(KindSelector.VAL, Type.noType); 187 methodAttrInfo = new MethodAttrInfo(); 188 unknownTypeInfo = new ResultInfo(KindSelector.TYP, Type.noType); 189 unknownTypeExprInfo = new ResultInfo(KindSelector.VAL_TYP, Type.noType); 190 recoveryInfo = new RecoveryInfo(deferredAttr.emptyDeferredAttrContext); 191 } 192 193 /** Switch: reifiable types in instanceof enabled? 194 */ 195 boolean allowReifiableTypesInInstanceof; 196 197 /** Are records allowed 198 */ 199 private final boolean allowRecords; 200 201 /** Are patterns in switch allowed 202 */ 203 private final boolean allowPatternSwitch; 204 205 /** Are unconditional patterns in instanceof allowed 206 */ 207 private final boolean allowUnconditionalPatternsInstanceOf; 208 209 /** 210 * Switch: warn about use of variable before declaration? 211 * RFE: 6425594 212 */ 213 boolean useBeforeDeclarationWarning; 214 215 /** 216 * Switch: name of source level; used for error reporting. 217 */ 218 String sourceName; 219 220 /** Check kind and type of given tree against protokind and prototype. 221 * If check succeeds, store type in tree and return it. 222 * If check fails, store errType in tree and return it. 223 * No checks are performed if the prototype is a method type. 224 * It is not necessary in this case since we know that kind and type 225 * are correct. 226 * 227 * @param tree The tree whose kind and type is checked 228 * @param found The computed type of the tree 229 * @param ownkind The computed kind of the tree 230 * @param resultInfo The expected result of the tree 231 */ 232 Type check(final JCTree tree, 233 final Type found, 234 final KindSelector ownkind, 235 final ResultInfo resultInfo) { 236 InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext(); 237 Type owntype; 238 boolean shouldCheck = !found.hasTag(ERROR) && 239 !resultInfo.pt.hasTag(METHOD) && 240 !resultInfo.pt.hasTag(FORALL); 241 if (shouldCheck && !ownkind.subset(resultInfo.pkind)) { 242 log.error(tree.pos(), 243 Errors.UnexpectedType(resultInfo.pkind.kindNames(), 244 ownkind.kindNames())); 245 owntype = types.createErrorType(found); 246 } else if (inferenceContext.free(found)) { 247 //delay the check if there are inference variables in the found type 248 //this means we are dealing with a partially inferred poly expression 249 owntype = shouldCheck ? resultInfo.pt : found; 250 if (resultInfo.checkMode.installPostInferenceHook()) { 251 inferenceContext.addFreeTypeListener(List.of(found), 252 instantiatedContext -> { 253 ResultInfo pendingResult = 254 resultInfo.dup(inferenceContext.asInstType(resultInfo.pt)); 255 check(tree, inferenceContext.asInstType(found), ownkind, pendingResult); 256 }); 257 } 258 } else { 259 owntype = shouldCheck ? 260 resultInfo.check(tree, found) : 261 found; 262 } 263 if (resultInfo.checkMode.updateTreeType()) { 264 tree.type = owntype; 265 } 266 return owntype; 267 } 268 269 /** Is given blank final variable assignable, i.e. in a scope where it 270 * may be assigned to even though it is final? 271 * @param v The blank final variable. 272 * @param env The current environment. 273 */ 274 boolean isAssignableAsBlankFinal(VarSymbol v, Env<AttrContext> env) { 275 Symbol owner = env.info.scope.owner; 276 // owner refers to the innermost variable, method or 277 // initializer block declaration at this point. 278 boolean isAssignable = 279 v.owner == owner 280 || 281 ((owner.name == names.init || // i.e. we are in a constructor 282 owner.kind == VAR || // i.e. we are in a variable initializer 283 (owner.flags() & BLOCK) != 0) // i.e. we are in an initializer block 284 && 285 v.owner == owner.owner 286 && 287 ((v.flags() & STATIC) != 0) == Resolve.isStatic(env)); 288 boolean insideCompactConstructor = env.enclMethod != null && TreeInfo.isCompactConstructor(env.enclMethod); 289 return isAssignable & !insideCompactConstructor; 290 } 291 292 /** Check that variable can be assigned to. 293 * @param pos The current source code position. 294 * @param v The assigned variable 295 * @param base If the variable is referred to in a Select, the part 296 * to the left of the `.', null otherwise. 297 * @param env The current environment. 298 */ 299 void checkAssignable(DiagnosticPosition pos, VarSymbol v, JCTree base, Env<AttrContext> env) { 300 if (v.name == names._this) { 301 log.error(pos, Errors.CantAssignValToThis); 302 } else if ((v.flags() & FINAL) != 0 && 303 ((v.flags() & HASINIT) != 0 304 || 305 !((base == null || 306 TreeInfo.isThisQualifier(base)) && 307 isAssignableAsBlankFinal(v, env)))) { 308 if (v.isResourceVariable()) { //TWR resource 309 log.error(pos, Errors.TryResourceMayNotBeAssigned(v)); 310 } else { 311 log.error(pos, Errors.CantAssignValToVar(Flags.toSource(v.flags() & (STATIC | FINAL)), v)); 312 } 313 } 314 } 315 316 /** Does tree represent a static reference to an identifier? 317 * It is assumed that tree is either a SELECT or an IDENT. 318 * We have to weed out selects from non-type names here. 319 * @param tree The candidate tree. 320 */ 321 boolean isStaticReference(JCTree tree) { 322 if (tree.hasTag(SELECT)) { 323 Symbol lsym = TreeInfo.symbol(((JCFieldAccess) tree).selected); 324 if (lsym == null || lsym.kind != TYP) { 325 return false; 326 } 327 } 328 return true; 329 } 330 331 /** Is this symbol a type? 332 */ 333 static boolean isType(Symbol sym) { 334 return sym != null && sym.kind == TYP; 335 } 336 337 /** Attribute a parsed identifier. 338 * @param tree Parsed identifier name 339 * @param topLevel The toplevel to use 340 */ 341 public Symbol attribIdent(JCTree tree, JCCompilationUnit topLevel) { 342 Env<AttrContext> localEnv = enter.topLevelEnv(topLevel); 343 localEnv.enclClass = make.ClassDef(make.Modifiers(0), 344 syms.errSymbol.name, 345 null, null, null, null); 346 localEnv.enclClass.sym = syms.errSymbol; 347 return attribIdent(tree, localEnv); 348 } 349 350 /** Attribute a parsed identifier. 351 * @param tree Parsed identifier name 352 * @param env The env to use 353 */ 354 public Symbol attribIdent(JCTree tree, Env<AttrContext> env) { 355 return tree.accept(identAttributer, env); 356 } 357 // where 358 private TreeVisitor<Symbol,Env<AttrContext>> identAttributer = new IdentAttributer(); 359 private class IdentAttributer extends SimpleTreeVisitor<Symbol,Env<AttrContext>> { 360 @Override @DefinedBy(Api.COMPILER_TREE) 361 public Symbol visitMemberSelect(MemberSelectTree node, Env<AttrContext> env) { 362 Symbol site = visit(node.getExpression(), env); 363 if (site.kind == ERR || site.kind == ABSENT_TYP || site.kind == HIDDEN) 364 return site; 365 Name name = (Name)node.getIdentifier(); 366 if (site.kind == PCK) { 367 env.toplevel.packge = (PackageSymbol)site; 368 return rs.findIdentInPackage(null, env, (TypeSymbol)site, name, 369 KindSelector.TYP_PCK); 370 } else { 371 env.enclClass.sym = (ClassSymbol)site; 372 return rs.findMemberType(env, site.asType(), name, (TypeSymbol)site); 373 } 374 } 375 376 @Override @DefinedBy(Api.COMPILER_TREE) 377 public Symbol visitIdentifier(IdentifierTree node, Env<AttrContext> env) { 378 return rs.findIdent(null, env, (Name)node.getName(), KindSelector.TYP_PCK); 379 } 380 } 381 382 public Type coerce(Type etype, Type ttype) { 383 return cfolder.coerce(etype, ttype); 384 } 385 386 public Type attribType(JCTree node, TypeSymbol sym) { 387 Env<AttrContext> env = typeEnvs.get(sym); 388 Env<AttrContext> localEnv = env.dup(node, env.info.dup()); 389 return attribTree(node, localEnv, unknownTypeInfo); 390 } 391 392 public Type attribImportQualifier(JCImport tree, Env<AttrContext> env) { 393 // Attribute qualifying package or class. 394 JCFieldAccess s = tree.qualid; 395 return attribTree(s.selected, env, 396 new ResultInfo(tree.staticImport ? 397 KindSelector.TYP : KindSelector.TYP_PCK, 398 Type.noType)); 399 } 400 401 public Env<AttrContext> attribExprToTree(JCTree expr, Env<AttrContext> env, JCTree tree) { 402 return attribToTree(expr, env, tree, unknownExprInfo); 403 } 404 405 public Env<AttrContext> attribStatToTree(JCTree stmt, Env<AttrContext> env, JCTree tree) { 406 return attribToTree(stmt, env, tree, statInfo); 407 } 408 409 private Env<AttrContext> attribToTree(JCTree root, Env<AttrContext> env, JCTree tree, ResultInfo resultInfo) { 410 breakTree = tree; 411 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 412 try { 413 deferredAttr.attribSpeculative(root, env, resultInfo, 414 null, DeferredAttr.AttributionMode.ATTRIB_TO_TREE, 415 argumentAttr.withLocalCacheContext()); 416 attrRecover.doRecovery(); 417 } catch (BreakAttr b) { 418 return b.env; 419 } catch (AssertionError ae) { 420 if (ae.getCause() instanceof BreakAttr breakAttr) { 421 return breakAttr.env; 422 } else { 423 throw ae; 424 } 425 } finally { 426 breakTree = null; 427 log.useSource(prev); 428 } 429 return env; 430 } 431 432 public <R> R runWithAttributedMethod(Env<AttrContext> env, JCMethodDecl tree, Function<JCBlock, R> attributedAction) { 433 JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile); 434 try { 435 JCBlock dupTree = (JCBlock)deferredAttr.attribSpeculative(tree.body, env, statInfo, 436 null, DeferredAttr.AttributionMode.ATTRIB_TO_TREE, 437 argumentAttr.withLocalCacheContext()); 438 return attributedAction.apply(dupTree); 439 } finally { 440 attrRecover.doRecovery(); 441 log.useSource(prevSource); 442 } 443 } 444 445 private JCTree breakTree = null; 446 447 private static class BreakAttr extends RuntimeException { 448 static final long serialVersionUID = -6924771130405446405L; 449 private transient Env<AttrContext> env; 450 private BreakAttr(Env<AttrContext> env) { 451 this.env = env; 452 } 453 } 454 455 /** 456 * Mode controlling behavior of Attr.Check 457 */ 458 enum CheckMode { 459 460 NORMAL, 461 462 /** 463 * Mode signalling 'fake check' - skip tree update. A side-effect of this mode is 464 * that the captured var cache in {@code InferenceContext} will be used in read-only 465 * mode when performing inference checks. 466 */ 467 NO_TREE_UPDATE { 468 @Override 469 public boolean updateTreeType() { 470 return false; 471 } 472 }, 473 /** 474 * Mode signalling that caller will manage free types in tree decorations. 475 */ 476 NO_INFERENCE_HOOK { 477 @Override 478 public boolean installPostInferenceHook() { 479 return false; 480 } 481 }; 482 483 public boolean updateTreeType() { 484 return true; 485 } 486 public boolean installPostInferenceHook() { 487 return true; 488 } 489 } 490 491 492 class ResultInfo { 493 final KindSelector pkind; 494 final Type pt; 495 final CheckContext checkContext; 496 final CheckMode checkMode; 497 498 ResultInfo(KindSelector pkind, Type pt) { 499 this(pkind, pt, chk.basicHandler, CheckMode.NORMAL); 500 } 501 502 ResultInfo(KindSelector pkind, Type pt, CheckMode checkMode) { 503 this(pkind, pt, chk.basicHandler, checkMode); 504 } 505 506 protected ResultInfo(KindSelector pkind, 507 Type pt, CheckContext checkContext) { 508 this(pkind, pt, checkContext, CheckMode.NORMAL); 509 } 510 511 protected ResultInfo(KindSelector pkind, 512 Type pt, CheckContext checkContext, CheckMode checkMode) { 513 this.pkind = pkind; 514 this.pt = pt; 515 this.checkContext = checkContext; 516 this.checkMode = checkMode; 517 } 518 519 /** 520 * Should {@link Attr#attribTree} use the {@code ArgumentAttr} visitor instead of this one? 521 * @param tree The tree to be type-checked. 522 * @return true if {@code ArgumentAttr} should be used. 523 */ 524 protected boolean needsArgumentAttr(JCTree tree) { return false; } 525 526 protected Type check(final DiagnosticPosition pos, final Type found) { 527 return chk.checkType(pos, found, pt, checkContext); 528 } 529 530 protected ResultInfo dup(Type newPt) { 531 return new ResultInfo(pkind, newPt, checkContext, checkMode); 532 } 533 534 protected ResultInfo dup(CheckContext newContext) { 535 return new ResultInfo(pkind, pt, newContext, checkMode); 536 } 537 538 protected ResultInfo dup(Type newPt, CheckContext newContext) { 539 return new ResultInfo(pkind, newPt, newContext, checkMode); 540 } 541 542 protected ResultInfo dup(Type newPt, CheckContext newContext, CheckMode newMode) { 543 return new ResultInfo(pkind, newPt, newContext, newMode); 544 } 545 546 protected ResultInfo dup(CheckMode newMode) { 547 return new ResultInfo(pkind, pt, checkContext, newMode); 548 } 549 550 @Override 551 public String toString() { 552 if (pt != null) { 553 return pt.toString(); 554 } else { 555 return ""; 556 } 557 } 558 } 559 560 class MethodAttrInfo extends ResultInfo { 561 public MethodAttrInfo() { 562 this(chk.basicHandler); 563 } 564 565 public MethodAttrInfo(CheckContext checkContext) { 566 super(KindSelector.VAL, Infer.anyPoly, checkContext); 567 } 568 569 @Override 570 protected boolean needsArgumentAttr(JCTree tree) { 571 return true; 572 } 573 574 protected ResultInfo dup(Type newPt) { 575 throw new IllegalStateException(); 576 } 577 578 protected ResultInfo dup(CheckContext newContext) { 579 return new MethodAttrInfo(newContext); 580 } 581 582 protected ResultInfo dup(Type newPt, CheckContext newContext) { 583 throw new IllegalStateException(); 584 } 585 586 protected ResultInfo dup(Type newPt, CheckContext newContext, CheckMode newMode) { 587 throw new IllegalStateException(); 588 } 589 590 protected ResultInfo dup(CheckMode newMode) { 591 throw new IllegalStateException(); 592 } 593 } 594 595 class RecoveryInfo extends ResultInfo { 596 597 public RecoveryInfo(final DeferredAttr.DeferredAttrContext deferredAttrContext) { 598 this(deferredAttrContext, Type.recoveryType); 599 } 600 601 public RecoveryInfo(final DeferredAttr.DeferredAttrContext deferredAttrContext, Type pt) { 602 super(KindSelector.VAL, pt, new Check.NestedCheckContext(chk.basicHandler) { 603 @Override 604 public DeferredAttr.DeferredAttrContext deferredAttrContext() { 605 return deferredAttrContext; 606 } 607 @Override 608 public boolean compatible(Type found, Type req, Warner warn) { 609 return true; 610 } 611 @Override 612 public void report(DiagnosticPosition pos, JCDiagnostic details) { 613 boolean needsReport = pt == Type.recoveryType || 614 (details.getDiagnosticPosition() != null && 615 details.getDiagnosticPosition().getTree().hasTag(LAMBDA)); 616 if (needsReport) { 617 chk.basicHandler.report(pos, details); 618 } 619 } 620 }); 621 } 622 } 623 624 final ResultInfo statInfo; 625 final ResultInfo varAssignmentInfo; 626 final ResultInfo methodAttrInfo; 627 final ResultInfo unknownExprInfo; 628 final ResultInfo unknownTypeInfo; 629 final ResultInfo unknownTypeExprInfo; 630 final ResultInfo recoveryInfo; 631 632 Type pt() { 633 return resultInfo.pt; 634 } 635 636 KindSelector pkind() { 637 return resultInfo.pkind; 638 } 639 640 /* ************************************************************************ 641 * Visitor methods 642 *************************************************************************/ 643 644 /** Visitor argument: the current environment. 645 */ 646 Env<AttrContext> env; 647 648 /** Visitor argument: the currently expected attribution result. 649 */ 650 ResultInfo resultInfo; 651 652 /** Visitor result: the computed type. 653 */ 654 Type result; 655 656 MatchBindings matchBindings = MatchBindingsComputer.EMPTY; 657 658 /** Visitor method: attribute a tree, catching any completion failure 659 * exceptions. Return the tree's type. 660 * 661 * @param tree The tree to be visited. 662 * @param env The environment visitor argument. 663 * @param resultInfo The result info visitor argument. 664 */ 665 Type attribTree(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) { 666 Env<AttrContext> prevEnv = this.env; 667 ResultInfo prevResult = this.resultInfo; 668 try { 669 this.env = env; 670 this.resultInfo = resultInfo; 671 if (resultInfo.needsArgumentAttr(tree)) { 672 result = argumentAttr.attribArg(tree, env); 673 } else { 674 tree.accept(this); 675 } 676 matchBindings = matchBindingsComputer.finishBindings(tree, 677 matchBindings); 678 if (tree == breakTree && 679 resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) { 680 breakTreeFound(copyEnv(env)); 681 } 682 return result; 683 } catch (CompletionFailure ex) { 684 tree.type = syms.errType; 685 return chk.completionError(tree.pos(), ex); 686 } finally { 687 this.env = prevEnv; 688 this.resultInfo = prevResult; 689 } 690 } 691 692 protected void breakTreeFound(Env<AttrContext> env) { 693 throw new BreakAttr(env); 694 } 695 696 Env<AttrContext> copyEnv(Env<AttrContext> env) { 697 Env<AttrContext> newEnv = 698 env.dup(env.tree, env.info.dup(copyScope(env.info.scope))); 699 if (newEnv.outer != null) { 700 newEnv.outer = copyEnv(newEnv.outer); 701 } 702 return newEnv; 703 } 704 705 WriteableScope copyScope(WriteableScope sc) { 706 WriteableScope newScope = WriteableScope.create(sc.owner); 707 List<Symbol> elemsList = List.nil(); 708 for (Symbol sym : sc.getSymbols()) { 709 elemsList = elemsList.prepend(sym); 710 } 711 for (Symbol s : elemsList) { 712 newScope.enter(s); 713 } 714 return newScope; 715 } 716 717 /** Derived visitor method: attribute an expression tree. 718 */ 719 public Type attribExpr(JCTree tree, Env<AttrContext> env, Type pt) { 720 return attribTree(tree, env, new ResultInfo(KindSelector.VAL, !pt.hasTag(ERROR) ? pt : Type.noType)); 721 } 722 723 /** Derived visitor method: attribute an expression tree with 724 * no constraints on the computed type. 725 */ 726 public Type attribExpr(JCTree tree, Env<AttrContext> env) { 727 return attribTree(tree, env, unknownExprInfo); 728 } 729 730 /** Derived visitor method: attribute a type tree. 731 */ 732 public Type attribType(JCTree tree, Env<AttrContext> env) { 733 Type result = attribType(tree, env, Type.noType); 734 return result; 735 } 736 737 /** Derived visitor method: attribute a type tree. 738 */ 739 Type attribType(JCTree tree, Env<AttrContext> env, Type pt) { 740 Type result = attribTree(tree, env, new ResultInfo(KindSelector.TYP, pt)); 741 return result; 742 } 743 744 /** Derived visitor method: attribute a statement or definition tree. 745 */ 746 public Type attribStat(JCTree tree, Env<AttrContext> env) { 747 Env<AttrContext> analyzeEnv = analyzer.copyEnvIfNeeded(tree, env); 748 Type result = attribTree(tree, env, statInfo); 749 analyzer.analyzeIfNeeded(tree, analyzeEnv); 750 attrRecover.doRecovery(); 751 return result; 752 } 753 754 /** Attribute a list of expressions, returning a list of types. 755 */ 756 List<Type> attribExprs(List<JCExpression> trees, Env<AttrContext> env, Type pt) { 757 ListBuffer<Type> ts = new ListBuffer<>(); 758 for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail) 759 ts.append(attribExpr(l.head, env, pt)); 760 return ts.toList(); 761 } 762 763 /** Attribute a list of statements, returning nothing. 764 */ 765 <T extends JCTree> void attribStats(List<T> trees, Env<AttrContext> env) { 766 for (List<T> l = trees; l.nonEmpty(); l = l.tail) 767 attribStat(l.head, env); 768 } 769 770 /** Attribute the arguments in a method call, returning the method kind. 771 */ 772 KindSelector attribArgs(KindSelector initialKind, List<JCExpression> trees, Env<AttrContext> env, ListBuffer<Type> argtypes) { 773 KindSelector kind = initialKind; 774 for (JCExpression arg : trees) { 775 Type argtype = chk.checkNonVoid(arg, attribTree(arg, env, methodAttrInfo)); 776 if (argtype.hasTag(DEFERRED)) { 777 kind = KindSelector.of(KindSelector.POLY, kind); 778 } 779 argtypes.append(argtype); 780 } 781 return kind; 782 } 783 784 /** Attribute a type argument list, returning a list of types. 785 * Caller is responsible for calling checkRefTypes. 786 */ 787 List<Type> attribAnyTypes(List<JCExpression> trees, Env<AttrContext> env) { 788 ListBuffer<Type> argtypes = new ListBuffer<>(); 789 for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail) 790 argtypes.append(attribType(l.head, env)); 791 return argtypes.toList(); 792 } 793 794 /** Attribute a type argument list, returning a list of types. 795 * Check that all the types are references. 796 */ 797 List<Type> attribTypes(List<JCExpression> trees, Env<AttrContext> env) { 798 List<Type> types = attribAnyTypes(trees, env); 799 return chk.checkRefTypes(trees, types); 800 } 801 802 /** 803 * Attribute type variables (of generic classes or methods). 804 * Compound types are attributed later in attribBounds. 805 * @param typarams the type variables to enter 806 * @param env the current environment 807 */ 808 void attribTypeVariables(List<JCTypeParameter> typarams, Env<AttrContext> env, boolean checkCyclic) { 809 for (JCTypeParameter tvar : typarams) { 810 TypeVar a = (TypeVar)tvar.type; 811 a.tsym.flags_field |= UNATTRIBUTED; 812 a.setUpperBound(Type.noType); 813 if (!tvar.bounds.isEmpty()) { 814 List<Type> bounds = List.of(attribType(tvar.bounds.head, env)); 815 for (JCExpression bound : tvar.bounds.tail) 816 bounds = bounds.prepend(attribType(bound, env)); 817 types.setBounds(a, bounds.reverse()); 818 } else { 819 // if no bounds are given, assume a single bound of 820 // java.lang.Object. 821 types.setBounds(a, List.of(syms.objectType)); 822 } 823 a.tsym.flags_field &= ~UNATTRIBUTED; 824 } 825 if (checkCyclic) { 826 for (JCTypeParameter tvar : typarams) { 827 chk.checkNonCyclic(tvar.pos(), (TypeVar)tvar.type); 828 } 829 } 830 } 831 832 /** 833 * Attribute the type references in a list of annotations. 834 */ 835 void attribAnnotationTypes(List<JCAnnotation> annotations, 836 Env<AttrContext> env) { 837 for (List<JCAnnotation> al = annotations; al.nonEmpty(); al = al.tail) { 838 JCAnnotation a = al.head; 839 attribType(a.annotationType, env); 840 } 841 } 842 843 /** 844 * Attribute a "lazy constant value". 845 * @param env The env for the const value 846 * @param variable The initializer for the const value 847 * @param type The expected type, or null 848 * @see VarSymbol#setLazyConstValue 849 */ 850 public Object attribLazyConstantValue(Env<AttrContext> env, 851 JCVariableDecl variable, 852 Type type) { 853 854 DiagnosticPosition prevLintPos 855 = deferredLintHandler.setPos(variable.pos()); 856 857 final JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile); 858 try { 859 Type itype = attribExpr(variable.init, env, type); 860 if (variable.isImplicitlyTyped()) { 861 //fixup local variable type 862 type = variable.type = variable.sym.type = chk.checkLocalVarType(variable, itype, variable.name); 863 } 864 if (itype.constValue() != null) { 865 return coerce(itype, type).constValue(); 866 } else { 867 return null; 868 } 869 } finally { 870 log.useSource(prevSource); 871 deferredLintHandler.setPos(prevLintPos); 872 } 873 } 874 875 /** Attribute type reference in an `extends' or `implements' clause. 876 * Supertypes of anonymous inner classes are usually already attributed. 877 * 878 * @param tree The tree making up the type reference. 879 * @param env The environment current at the reference. 880 * @param classExpected true if only a class is expected here. 881 * @param interfaceExpected true if only an interface is expected here. 882 */ 883 Type attribBase(JCTree tree, 884 Env<AttrContext> env, 885 boolean classExpected, 886 boolean interfaceExpected, 887 boolean checkExtensible) { 888 Type t = tree.type != null ? 889 tree.type : 890 attribType(tree, env); 891 try { 892 return checkBase(t, tree, env, classExpected, interfaceExpected, checkExtensible); 893 } catch (CompletionFailure ex) { 894 chk.completionError(tree.pos(), ex); 895 return t; 896 } 897 } 898 Type checkBase(Type t, 899 JCTree tree, 900 Env<AttrContext> env, 901 boolean classExpected, 902 boolean interfaceExpected, 903 boolean checkExtensible) { 904 final DiagnosticPosition pos = tree.hasTag(TYPEAPPLY) ? 905 (((JCTypeApply) tree).clazz).pos() : tree.pos(); 906 if (t.tsym.isAnonymous()) { 907 log.error(pos, Errors.CantInheritFromAnon); 908 return types.createErrorType(t); 909 } 910 if (t.isErroneous()) 911 return t; 912 if (t.hasTag(TYPEVAR) && !classExpected && !interfaceExpected) { 913 // check that type variable is already visible 914 if (t.getUpperBound() == null) { 915 log.error(pos, Errors.IllegalForwardRef); 916 return types.createErrorType(t); 917 } 918 } else { 919 t = chk.checkClassType(pos, t, checkExtensible); 920 } 921 if (interfaceExpected && (t.tsym.flags() & INTERFACE) == 0) { 922 log.error(pos, Errors.IntfExpectedHere); 923 // return errType is necessary since otherwise there might 924 // be undetected cycles which cause attribution to loop 925 return types.createErrorType(t); 926 } else if (checkExtensible && 927 classExpected && 928 (t.tsym.flags() & INTERFACE) != 0) { 929 log.error(pos, Errors.NoIntfExpectedHere); 930 return types.createErrorType(t); 931 } 932 if (checkExtensible && 933 ((t.tsym.flags() & FINAL) != 0)) { 934 log.error(pos, 935 Errors.CantInheritFromFinal(t.tsym)); 936 } 937 chk.checkNonCyclic(pos, t); 938 return t; 939 } 940 941 Type attribIdentAsEnumType(Env<AttrContext> env, JCIdent id) { 942 Assert.check((env.enclClass.sym.flags() & ENUM) != 0); 943 id.type = env.info.scope.owner.enclClass().type; 944 id.sym = env.info.scope.owner.enclClass(); 945 return id.type; 946 } 947 948 public void visitClassDef(JCClassDecl tree) { 949 Optional<ArgumentAttr.LocalCacheContext> localCacheContext = 950 Optional.ofNullable(env.info.attributionMode.isSpeculative ? 951 argumentAttr.withLocalCacheContext() : null); 952 boolean ctorProloguePrev = env.info.ctorPrologue; 953 env.info.ctorPrologue = false; 954 try { 955 // Local and anonymous classes have not been entered yet, so we need to 956 // do it now. 957 if (env.info.scope.owner.kind.matches(KindSelector.VAL_MTH)) { 958 enter.classEnter(tree, env); 959 } else { 960 // If this class declaration is part of a class level annotation, 961 // as in @MyAnno(new Object() {}) class MyClass {}, enter it in 962 // order to simplify later steps and allow for sensible error 963 // messages. 964 if (env.tree.hasTag(NEWCLASS) && TreeInfo.isInAnnotation(env, tree)) 965 enter.classEnter(tree, env); 966 } 967 968 ClassSymbol c = tree.sym; 969 if (c == null) { 970 // exit in case something drastic went wrong during enter. 971 result = null; 972 } else { 973 // make sure class has been completed: 974 c.complete(); 975 976 // If a class declaration appears in a constructor prologue, 977 // that means it's either a local class or an anonymous class. 978 // Either way, there is no immediately enclosing instance. 979 if (ctorProloguePrev) { 980 c.flags_field |= NOOUTERTHIS; 981 } 982 attribClass(tree.pos(), c); 983 result = tree.type = c.type; 984 } 985 } finally { 986 localCacheContext.ifPresent(LocalCacheContext::leave); 987 env.info.ctorPrologue = ctorProloguePrev; 988 } 989 } 990 991 public void visitMethodDef(JCMethodDecl tree) { 992 MethodSymbol m = tree.sym; 993 boolean isDefaultMethod = (m.flags() & DEFAULT) != 0; 994 995 Lint lint = env.info.lint.augment(m); 996 Lint prevLint = chk.setLint(lint); 997 boolean ctorProloguePrev = env.info.ctorPrologue; 998 env.info.ctorPrologue = false; 999 MethodSymbol prevMethod = chk.setMethod(m); 1000 try { 1001 deferredLintHandler.flush(tree.pos(), lint); 1002 chk.checkDeprecatedAnnotation(tree.pos(), m); 1003 1004 1005 // Create a new environment with local scope 1006 // for attributing the method. 1007 Env<AttrContext> localEnv = memberEnter.methodEnv(tree, env); 1008 localEnv.info.lint = lint; 1009 1010 attribStats(tree.typarams, localEnv); 1011 1012 // If we override any other methods, check that we do so properly. 1013 // JLS ??? 1014 if (m.isStatic()) { 1015 chk.checkHideClashes(tree.pos(), env.enclClass.type, m); 1016 } else { 1017 chk.checkOverrideClashes(tree.pos(), env.enclClass.type, m); 1018 } 1019 chk.checkOverride(env, tree, m); 1020 1021 if (isDefaultMethod && types.overridesObjectMethod(m.enclClass(), m)) { 1022 log.error(tree, Errors.DefaultOverridesObjectMember(m.name, Kinds.kindName(m.location()), m.location())); 1023 } 1024 1025 // Enter all type parameters into the local method scope. 1026 for (List<JCTypeParameter> l = tree.typarams; l.nonEmpty(); l = l.tail) 1027 localEnv.info.scope.enterIfAbsent(l.head.type.tsym); 1028 1029 ClassSymbol owner = env.enclClass.sym; 1030 if ((owner.flags() & ANNOTATION) != 0 && 1031 (tree.params.nonEmpty() || 1032 tree.recvparam != null)) 1033 log.error(tree.params.nonEmpty() ? 1034 tree.params.head.pos() : 1035 tree.recvparam.pos(), 1036 Errors.IntfAnnotationMembersCantHaveParams); 1037 1038 // Attribute all value parameters. 1039 for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) { 1040 attribStat(l.head, localEnv); 1041 } 1042 1043 chk.checkVarargsMethodDecl(localEnv, tree); 1044 1045 // Check that type parameters are well-formed. 1046 chk.validate(tree.typarams, localEnv); 1047 1048 // Check that result type is well-formed. 1049 if (tree.restype != null && !tree.restype.type.hasTag(VOID)) 1050 chk.validate(tree.restype, localEnv); 1051 1052 // Check that receiver type is well-formed. 1053 if (tree.recvparam != null) { 1054 // Use a new environment to check the receiver parameter. 1055 // Otherwise I get "might not have been initialized" errors. 1056 // Is there a better way? 1057 Env<AttrContext> newEnv = memberEnter.methodEnv(tree, env); 1058 attribType(tree.recvparam, newEnv); 1059 chk.validate(tree.recvparam, newEnv); 1060 } 1061 1062 // Is this method a constructor? 1063 boolean isConstructor = TreeInfo.isConstructor(tree); 1064 1065 if (env.enclClass.sym.isRecord() && tree.sym.owner.kind == TYP) { 1066 // lets find if this method is an accessor 1067 Optional<? extends RecordComponent> recordComponent = env.enclClass.sym.getRecordComponents().stream() 1068 .filter(rc -> rc.accessor == tree.sym && (rc.accessor.flags_field & GENERATED_MEMBER) == 0).findFirst(); 1069 if (recordComponent.isPresent()) { 1070 // the method is a user defined accessor lets check that everything is fine 1071 if (!tree.sym.isPublic()) { 1072 log.error(tree, Errors.InvalidAccessorMethodInRecord(env.enclClass.sym, Fragments.MethodMustBePublic)); 1073 } 1074 if (!types.isSameType(tree.sym.type.getReturnType(), recordComponent.get().type)) { 1075 log.error(tree, Errors.InvalidAccessorMethodInRecord(env.enclClass.sym, 1076 Fragments.AccessorReturnTypeDoesntMatch(tree.sym, recordComponent.get()))); 1077 } 1078 if (tree.sym.type.asMethodType().thrown != null && !tree.sym.type.asMethodType().thrown.isEmpty()) { 1079 log.error(tree, 1080 Errors.InvalidAccessorMethodInRecord(env.enclClass.sym, Fragments.AccessorMethodCantThrowException)); 1081 } 1082 if (!tree.typarams.isEmpty()) { 1083 log.error(tree, 1084 Errors.InvalidAccessorMethodInRecord(env.enclClass.sym, Fragments.AccessorMethodMustNotBeGeneric)); 1085 } 1086 if (tree.sym.isStatic()) { 1087 log.error(tree, 1088 Errors.InvalidAccessorMethodInRecord(env.enclClass.sym, Fragments.AccessorMethodMustNotBeStatic)); 1089 } 1090 } 1091 1092 if (isConstructor) { 1093 // if this a constructor other than the canonical one 1094 if ((tree.sym.flags_field & RECORD) == 0) { 1095 if (!TreeInfo.hasConstructorCall(tree, names._this)) { 1096 log.error(tree, Errors.NonCanonicalConstructorInvokeAnotherConstructor(env.enclClass.sym)); 1097 } 1098 } else { 1099 // but if it is the canonical: 1100 1101 /* if user generated, then it shouldn't: 1102 * - have an accessibility stricter than that of the record type 1103 * - explicitly invoke any other constructor 1104 */ 1105 if ((tree.sym.flags_field & GENERATEDCONSTR) == 0) { 1106 if (Check.protection(m.flags()) > Check.protection(env.enclClass.sym.flags())) { 1107 log.error(tree, 1108 (env.enclClass.sym.flags() & AccessFlags) == 0 ? 1109 Errors.InvalidCanonicalConstructorInRecord( 1110 Fragments.Canonical, 1111 env.enclClass.sym.name, 1112 Fragments.CanonicalMustNotHaveStrongerAccess("package") 1113 ) : 1114 Errors.InvalidCanonicalConstructorInRecord( 1115 Fragments.Canonical, 1116 env.enclClass.sym.name, 1117 Fragments.CanonicalMustNotHaveStrongerAccess(asFlagSet(env.enclClass.sym.flags() & AccessFlags)) 1118 ) 1119 ); 1120 } 1121 1122 if (TreeInfo.hasAnyConstructorCall(tree)) { 1123 log.error(tree, Errors.InvalidCanonicalConstructorInRecord( 1124 Fragments.Canonical, env.enclClass.sym.name, 1125 Fragments.CanonicalMustNotContainExplicitConstructorInvocation)); 1126 } 1127 } 1128 1129 // also we want to check that no type variables have been defined 1130 if (!tree.typarams.isEmpty()) { 1131 log.error(tree, Errors.InvalidCanonicalConstructorInRecord( 1132 Fragments.Canonical, env.enclClass.sym.name, Fragments.CanonicalMustNotDeclareTypeVariables)); 1133 } 1134 1135 /* and now we need to check that the constructor's arguments are exactly the same as those of the 1136 * record components 1137 */ 1138 List<? extends RecordComponent> recordComponents = env.enclClass.sym.getRecordComponents(); 1139 List<Type> recordFieldTypes = TreeInfo.recordFields(env.enclClass).map(vd -> vd.sym.type); 1140 for (JCVariableDecl param: tree.params) { 1141 boolean paramIsVarArgs = (param.sym.flags_field & VARARGS) != 0; 1142 if (!types.isSameType(param.type, recordFieldTypes.head) || 1143 (recordComponents.head.isVarargs() != paramIsVarArgs)) { 1144 log.error(param, Errors.InvalidCanonicalConstructorInRecord( 1145 Fragments.Canonical, env.enclClass.sym.name, 1146 Fragments.TypeMustBeIdenticalToCorrespondingRecordComponentType)); 1147 } 1148 recordComponents = recordComponents.tail; 1149 recordFieldTypes = recordFieldTypes.tail; 1150 } 1151 } 1152 } 1153 } 1154 1155 // annotation method checks 1156 if ((owner.flags() & ANNOTATION) != 0) { 1157 // annotation method cannot have throws clause 1158 if (tree.thrown.nonEmpty()) { 1159 log.error(tree.thrown.head.pos(), 1160 Errors.ThrowsNotAllowedInIntfAnnotation); 1161 } 1162 // annotation method cannot declare type-parameters 1163 if (tree.typarams.nonEmpty()) { 1164 log.error(tree.typarams.head.pos(), 1165 Errors.IntfAnnotationMembersCantHaveTypeParams); 1166 } 1167 // validate annotation method's return type (could be an annotation type) 1168 chk.validateAnnotationType(tree.restype); 1169 // ensure that annotation method does not clash with members of Object/Annotation 1170 chk.validateAnnotationMethod(tree.pos(), m); 1171 } 1172 1173 for (List<JCExpression> l = tree.thrown; l.nonEmpty(); l = l.tail) 1174 chk.checkType(l.head.pos(), l.head.type, syms.throwableType); 1175 1176 if (tree.body == null) { 1177 // Empty bodies are only allowed for 1178 // abstract, native, or interface methods, or for methods 1179 // in a retrofit signature class. 1180 if (tree.defaultValue != null) { 1181 if ((owner.flags() & ANNOTATION) == 0) 1182 log.error(tree.pos(), 1183 Errors.DefaultAllowedInIntfAnnotationMember); 1184 } 1185 if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0) 1186 log.error(tree.pos(), Errors.MissingMethBodyOrDeclAbstract); 1187 } else { 1188 if ((tree.sym.flags() & (ABSTRACT|DEFAULT|PRIVATE)) == ABSTRACT) { 1189 if ((owner.flags() & INTERFACE) != 0) { 1190 log.error(tree.body.pos(), Errors.IntfMethCantHaveBody); 1191 } else { 1192 log.error(tree.pos(), Errors.AbstractMethCantHaveBody); 1193 } 1194 } else if ((tree.mods.flags & NATIVE) != 0) { 1195 log.error(tree.pos(), Errors.NativeMethCantHaveBody); 1196 } 1197 // Add an implicit super() call unless an explicit call to 1198 // super(...) or this(...) is given 1199 // or we are compiling class java.lang.Object. 1200 if (isConstructor && owner.type != syms.objectType) { 1201 if (!TreeInfo.hasAnyConstructorCall(tree)) { 1202 JCStatement supCall = make.at(tree.body.pos).Exec(make.Apply(List.nil(), 1203 make.Ident(names._super), make.Idents(List.nil()))); 1204 tree.body.stats = tree.body.stats.prepend(supCall); 1205 } else if ((env.enclClass.sym.flags() & ENUM) != 0 && 1206 (tree.mods.flags & GENERATEDCONSTR) == 0 && 1207 TreeInfo.hasConstructorCall(tree, names._super)) { 1208 // enum constructors are not allowed to call super 1209 // directly, so make sure there aren't any super calls 1210 // in enum constructors, except in the compiler 1211 // generated one. 1212 log.error(tree.body.stats.head.pos(), 1213 Errors.CallToSuperNotAllowedInEnumCtor(env.enclClass.sym)); 1214 } 1215 if (env.enclClass.sym.isRecord() && (tree.sym.flags_field & RECORD) != 0) { // we are seeing the canonical constructor 1216 List<Name> recordComponentNames = TreeInfo.recordFields(env.enclClass).map(vd -> vd.sym.name); 1217 List<Name> initParamNames = tree.sym.params.map(p -> p.name); 1218 if (!initParamNames.equals(recordComponentNames)) { 1219 log.error(tree, Errors.InvalidCanonicalConstructorInRecord( 1220 Fragments.Canonical, env.enclClass.sym.name, Fragments.CanonicalWithNameMismatch)); 1221 } 1222 if (tree.sym.type.asMethodType().thrown != null && !tree.sym.type.asMethodType().thrown.isEmpty()) { 1223 log.error(tree, 1224 Errors.InvalidCanonicalConstructorInRecord( 1225 TreeInfo.isCompactConstructor(tree) ? Fragments.Compact : Fragments.Canonical, 1226 env.enclClass.sym.name, 1227 Fragments.ThrowsClauseNotAllowedForCanonicalConstructor( 1228 TreeInfo.isCompactConstructor(tree) ? Fragments.Compact : Fragments.Canonical))); 1229 } 1230 } 1231 } 1232 1233 // Attribute all type annotations in the body 1234 annotate.queueScanTreeAndTypeAnnotate(tree.body, localEnv, m, null); 1235 annotate.flush(); 1236 1237 // Start of constructor prologue 1238 localEnv.info.ctorPrologue = isConstructor; 1239 1240 // Attribute method body. 1241 attribStat(tree.body, localEnv); 1242 } 1243 1244 localEnv.info.scope.leave(); 1245 result = tree.type = m.type; 1246 } finally { 1247 chk.setLint(prevLint); 1248 chk.setMethod(prevMethod); 1249 env.info.ctorPrologue = ctorProloguePrev; 1250 } 1251 } 1252 1253 public void visitVarDef(JCVariableDecl tree) { 1254 // Local variables have not been entered yet, so we need to do it now: 1255 if (env.info.scope.owner.kind == MTH || env.info.scope.owner.kind == VAR) { 1256 if (tree.sym != null) { 1257 // parameters have already been entered 1258 env.info.scope.enter(tree.sym); 1259 } else { 1260 if (tree.isImplicitlyTyped() && (tree.getModifiers().flags & PARAMETER) == 0) { 1261 if (tree.init == null) { 1262 //cannot use 'var' without initializer 1263 log.error(tree, Errors.CantInferLocalVarType(tree.name, Fragments.LocalMissingInit)); 1264 tree.vartype = make.Erroneous(); 1265 } else { 1266 Fragment msg = canInferLocalVarType(tree); 1267 if (msg != null) { 1268 //cannot use 'var' with initializer which require an explicit target 1269 //(e.g. lambda, method reference, array initializer). 1270 log.error(tree, Errors.CantInferLocalVarType(tree.name, msg)); 1271 tree.vartype = make.Erroneous(); 1272 } 1273 } 1274 } 1275 try { 1276 annotate.blockAnnotations(); 1277 memberEnter.memberEnter(tree, env); 1278 } finally { 1279 annotate.unblockAnnotations(); 1280 } 1281 } 1282 } else { 1283 if (tree.init != null) { 1284 // Field initializer expression need to be entered. 1285 annotate.queueScanTreeAndTypeAnnotate(tree.init, env, tree.sym, tree.pos()); 1286 annotate.flush(); 1287 } 1288 } 1289 1290 VarSymbol v = tree.sym; 1291 Lint lint = env.info.lint.augment(v); 1292 Lint prevLint = chk.setLint(lint); 1293 1294 // Check that the variable's declared type is well-formed. 1295 boolean isImplicitLambdaParameter = env.tree.hasTag(LAMBDA) && 1296 ((JCLambda)env.tree).paramKind == JCLambda.ParameterKind.IMPLICIT && 1297 (tree.sym.flags() & PARAMETER) != 0; 1298 chk.validate(tree.vartype, env, !isImplicitLambdaParameter && !tree.isImplicitlyTyped()); 1299 1300 try { 1301 v.getConstValue(); // ensure compile-time constant initializer is evaluated 1302 deferredLintHandler.flush(tree.pos(), lint); 1303 chk.checkDeprecatedAnnotation(tree.pos(), v); 1304 1305 if (tree.init != null) { 1306 if ((v.flags_field & FINAL) == 0 || 1307 !memberEnter.needsLazyConstValue(tree.init)) { 1308 // Not a compile-time constant 1309 // Attribute initializer in a new environment 1310 // with the declared variable as owner. 1311 // Check that initializer conforms to variable's declared type. 1312 Env<AttrContext> initEnv = memberEnter.initEnv(tree, env); 1313 initEnv.info.lint = lint; 1314 // In order to catch self-references, we set the variable's 1315 // declaration position to maximal possible value, effectively 1316 // marking the variable as undefined. 1317 initEnv.info.enclVar = v; 1318 attribExpr(tree.init, initEnv, v.type); 1319 if (tree.isImplicitlyTyped()) { 1320 //fixup local variable type 1321 v.type = chk.checkLocalVarType(tree, tree.init.type, tree.name); 1322 } 1323 } 1324 if (tree.isImplicitlyTyped()) { 1325 setSyntheticVariableType(tree, v.type); 1326 } 1327 } 1328 result = tree.type = v.type; 1329 if (env.enclClass.sym.isRecord() && tree.sym.owner.kind == TYP && !v.isStatic()) { 1330 if (isNonArgsMethodInObject(v.name)) { 1331 log.error(tree, Errors.IllegalRecordComponentName(v)); 1332 } 1333 } 1334 } 1335 finally { 1336 chk.setLint(prevLint); 1337 } 1338 } 1339 1340 private boolean isNonArgsMethodInObject(Name name) { 1341 for (Symbol s : syms.objectType.tsym.members().getSymbolsByName(name, s -> s.kind == MTH)) { 1342 if (s.type.getParameterTypes().isEmpty()) { 1343 return true; 1344 } 1345 } 1346 return false; 1347 } 1348 1349 Fragment canInferLocalVarType(JCVariableDecl tree) { 1350 LocalInitScanner lis = new LocalInitScanner(); 1351 lis.scan(tree.init); 1352 return lis.badInferenceMsg; 1353 } 1354 1355 static class LocalInitScanner extends TreeScanner { 1356 Fragment badInferenceMsg = null; 1357 boolean needsTarget = true; 1358 1359 @Override 1360 public void visitNewArray(JCNewArray tree) { 1361 if (tree.elemtype == null && needsTarget) { 1362 badInferenceMsg = Fragments.LocalArrayMissingTarget; 1363 } 1364 } 1365 1366 @Override 1367 public void visitLambda(JCLambda tree) { 1368 if (needsTarget) { 1369 badInferenceMsg = Fragments.LocalLambdaMissingTarget; 1370 } 1371 } 1372 1373 @Override 1374 public void visitTypeCast(JCTypeCast tree) { 1375 boolean prevNeedsTarget = needsTarget; 1376 try { 1377 needsTarget = false; 1378 super.visitTypeCast(tree); 1379 } finally { 1380 needsTarget = prevNeedsTarget; 1381 } 1382 } 1383 1384 @Override 1385 public void visitReference(JCMemberReference tree) { 1386 if (needsTarget) { 1387 badInferenceMsg = Fragments.LocalMrefMissingTarget; 1388 } 1389 } 1390 1391 @Override 1392 public void visitNewClass(JCNewClass tree) { 1393 boolean prevNeedsTarget = needsTarget; 1394 try { 1395 needsTarget = false; 1396 super.visitNewClass(tree); 1397 } finally { 1398 needsTarget = prevNeedsTarget; 1399 } 1400 } 1401 1402 @Override 1403 public void visitApply(JCMethodInvocation tree) { 1404 boolean prevNeedsTarget = needsTarget; 1405 try { 1406 needsTarget = false; 1407 super.visitApply(tree); 1408 } finally { 1409 needsTarget = prevNeedsTarget; 1410 } 1411 } 1412 } 1413 1414 public void visitSkip(JCSkip tree) { 1415 result = null; 1416 } 1417 1418 public void visitBlock(JCBlock tree) { 1419 if (env.info.scope.owner.kind == TYP || env.info.scope.owner.kind == ERR) { 1420 // Block is a static or instance initializer; 1421 // let the owner of the environment be a freshly 1422 // created BLOCK-method. 1423 Symbol fakeOwner = 1424 new MethodSymbol(tree.flags | BLOCK | 1425 env.info.scope.owner.flags() & STRICTFP, names.empty, null, 1426 env.info.scope.owner); 1427 final Env<AttrContext> localEnv = 1428 env.dup(tree, env.info.dup(env.info.scope.dupUnshared(fakeOwner))); 1429 1430 if ((tree.flags & STATIC) != 0) localEnv.info.staticLevel++; 1431 // Attribute all type annotations in the block 1432 annotate.queueScanTreeAndTypeAnnotate(tree, localEnv, localEnv.info.scope.owner, null); 1433 annotate.flush(); 1434 attribStats(tree.stats, localEnv); 1435 1436 { 1437 // Store init and clinit type annotations with the ClassSymbol 1438 // to allow output in Gen.normalizeDefs. 1439 ClassSymbol cs = (ClassSymbol)env.info.scope.owner; 1440 List<Attribute.TypeCompound> tas = localEnv.info.scope.owner.getRawTypeAttributes(); 1441 if ((tree.flags & STATIC) != 0) { 1442 cs.appendClassInitTypeAttributes(tas); 1443 } else { 1444 cs.appendInitTypeAttributes(tas); 1445 } 1446 } 1447 } else { 1448 // Create a new local environment with a local scope. 1449 Env<AttrContext> localEnv = 1450 env.dup(tree, env.info.dup(env.info.scope.dup())); 1451 try { 1452 attribStats(tree.stats, localEnv); 1453 } finally { 1454 localEnv.info.scope.leave(); 1455 } 1456 } 1457 result = null; 1458 } 1459 1460 public void visitDoLoop(JCDoWhileLoop tree) { 1461 attribStat(tree.body, env.dup(tree)); 1462 attribExpr(tree.cond, env, syms.booleanType); 1463 handleLoopConditionBindings(matchBindings, tree, tree.body); 1464 result = null; 1465 } 1466 1467 public void visitWhileLoop(JCWhileLoop tree) { 1468 attribExpr(tree.cond, env, syms.booleanType); 1469 MatchBindings condBindings = matchBindings; 1470 // include condition's bindings when true in the body: 1471 Env<AttrContext> whileEnv = bindingEnv(env, condBindings.bindingsWhenTrue); 1472 try { 1473 attribStat(tree.body, whileEnv.dup(tree)); 1474 } finally { 1475 whileEnv.info.scope.leave(); 1476 } 1477 handleLoopConditionBindings(condBindings, tree, tree.body); 1478 result = null; 1479 } 1480 1481 public void visitForLoop(JCForLoop tree) { 1482 Env<AttrContext> loopEnv = 1483 env.dup(env.tree, env.info.dup(env.info.scope.dup())); 1484 MatchBindings condBindings = MatchBindingsComputer.EMPTY; 1485 try { 1486 attribStats(tree.init, loopEnv); 1487 if (tree.cond != null) { 1488 attribExpr(tree.cond, loopEnv, syms.booleanType); 1489 // include condition's bindings when true in the body and step: 1490 condBindings = matchBindings; 1491 } 1492 Env<AttrContext> bodyEnv = bindingEnv(loopEnv, condBindings.bindingsWhenTrue); 1493 try { 1494 bodyEnv.tree = tree; // before, we were not in loop! 1495 attribStats(tree.step, bodyEnv); 1496 attribStat(tree.body, bodyEnv); 1497 } finally { 1498 bodyEnv.info.scope.leave(); 1499 } 1500 result = null; 1501 } 1502 finally { 1503 loopEnv.info.scope.leave(); 1504 } 1505 handleLoopConditionBindings(condBindings, tree, tree.body); 1506 } 1507 1508 /** 1509 * Include condition's bindings when false after the loop, if cannot get out of the loop 1510 */ 1511 private void handleLoopConditionBindings(MatchBindings condBindings, 1512 JCStatement loop, 1513 JCStatement loopBody) { 1514 if (condBindings.bindingsWhenFalse.nonEmpty() && 1515 !breaksTo(env, loop, loopBody)) { 1516 addBindings2Scope(loop, condBindings.bindingsWhenFalse); 1517 } 1518 } 1519 1520 private boolean breaksTo(Env<AttrContext> env, JCTree loop, JCTree body) { 1521 preFlow(body); 1522 return flow.breaksToTree(env, loop, body, make); 1523 } 1524 1525 /** 1526 * Add given bindings to the current scope, unless there's a break to 1527 * an immediately enclosing labeled statement. 1528 */ 1529 private void addBindings2Scope(JCStatement introducingStatement, 1530 List<BindingSymbol> bindings) { 1531 if (bindings.isEmpty()) { 1532 return ; 1533 } 1534 1535 var searchEnv = env; 1536 while (searchEnv.tree instanceof JCLabeledStatement labeled && 1537 labeled.body == introducingStatement) { 1538 if (breaksTo(env, labeled, labeled.body)) { 1539 //breaking to an immediately enclosing labeled statement 1540 return ; 1541 } 1542 searchEnv = searchEnv.next; 1543 introducingStatement = labeled; 1544 } 1545 1546 //include condition's body when false after the while, if cannot get out of the loop 1547 bindings.forEach(env.info.scope::enter); 1548 bindings.forEach(BindingSymbol::preserveBinding); 1549 } 1550 1551 public void visitForeachLoop(JCEnhancedForLoop tree) { 1552 Env<AttrContext> loopEnv = 1553 env.dup(env.tree, env.info.dup(env.info.scope.dup())); 1554 try { 1555 //the Formal Parameter of a for-each loop is not in the scope when 1556 //attributing the for-each expression; we mimic this by attributing 1557 //the for-each expression first (against original scope). 1558 Type exprType = types.cvarUpperBound(attribExpr(tree.expr, loopEnv)); 1559 chk.checkNonVoid(tree.pos(), exprType); 1560 Type elemtype = types.elemtype(exprType); // perhaps expr is an array? 1561 if (elemtype == null) { 1562 // or perhaps expr implements Iterable<T>? 1563 Type base = types.asSuper(exprType, syms.iterableType.tsym); 1564 if (base == null) { 1565 log.error(tree.expr.pos(), 1566 Errors.ForeachNotApplicableToType(exprType, 1567 Fragments.TypeReqArrayOrIterable)); 1568 elemtype = types.createErrorType(exprType); 1569 } else { 1570 List<Type> iterableParams = base.allparams(); 1571 elemtype = iterableParams.isEmpty() 1572 ? syms.objectType 1573 : types.wildUpperBound(iterableParams.head); 1574 1575 // Check the return type of the method iterator(). 1576 // This is the bare minimum we need to verify to make sure code generation doesn't crash. 1577 Symbol iterSymbol = rs.resolveInternalMethod(tree.pos(), 1578 loopEnv, types.skipTypeVars(exprType, false), names.iterator, List.nil(), List.nil()); 1579 if (types.asSuper(iterSymbol.type.getReturnType(), syms.iteratorType.tsym) == null) { 1580 log.error(tree.pos(), 1581 Errors.ForeachNotApplicableToType(exprType, Fragments.TypeReqArrayOrIterable)); 1582 } 1583 } 1584 } 1585 if (tree.var.isImplicitlyTyped()) { 1586 Type inferredType = chk.checkLocalVarType(tree.var, elemtype, tree.var.name); 1587 setSyntheticVariableType(tree.var, inferredType); 1588 } 1589 attribStat(tree.var, loopEnv); 1590 chk.checkType(tree.expr.pos(), elemtype, tree.var.sym.type); 1591 loopEnv.tree = tree; // before, we were not in loop! 1592 attribStat(tree.body, loopEnv); 1593 result = null; 1594 } 1595 finally { 1596 loopEnv.info.scope.leave(); 1597 } 1598 } 1599 1600 public void visitLabelled(JCLabeledStatement tree) { 1601 // Check that label is not used in an enclosing statement 1602 Env<AttrContext> env1 = env; 1603 while (env1 != null && !env1.tree.hasTag(CLASSDEF)) { 1604 if (env1.tree.hasTag(LABELLED) && 1605 ((JCLabeledStatement) env1.tree).label == tree.label) { 1606 log.error(tree.pos(), 1607 Errors.LabelAlreadyInUse(tree.label)); 1608 break; 1609 } 1610 env1 = env1.next; 1611 } 1612 1613 attribStat(tree.body, env.dup(tree)); 1614 result = null; 1615 } 1616 1617 public void visitSwitch(JCSwitch tree) { 1618 handleSwitch(tree, tree.selector, tree.cases, (c, caseEnv) -> { 1619 attribStats(c.stats, caseEnv); 1620 }); 1621 result = null; 1622 } 1623 1624 public void visitSwitchExpression(JCSwitchExpression tree) { 1625 boolean wrongContext = false; 1626 1627 tree.polyKind = (pt().hasTag(NONE) && pt() != Type.recoveryType && pt() != Infer.anyPoly) ? 1628 PolyKind.STANDALONE : PolyKind.POLY; 1629 1630 if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) { 1631 //this means we are returning a poly conditional from void-compatible lambda expression 1632 resultInfo.checkContext.report(tree, diags.fragment(Fragments.SwitchExpressionTargetCantBeVoid)); 1633 resultInfo = recoveryInfo; 1634 wrongContext = true; 1635 } 1636 1637 ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ? 1638 unknownExprInfo : 1639 resultInfo.dup(switchExpressionContext(resultInfo.checkContext)); 1640 1641 ListBuffer<DiagnosticPosition> caseTypePositions = new ListBuffer<>(); 1642 ListBuffer<Type> caseTypes = new ListBuffer<>(); 1643 1644 handleSwitch(tree, tree.selector, tree.cases, (c, caseEnv) -> { 1645 caseEnv.info.yieldResult = condInfo; 1646 attribStats(c.stats, caseEnv); 1647 new TreeScanner() { 1648 @Override 1649 public void visitYield(JCYield brk) { 1650 if (brk.target == tree) { 1651 caseTypePositions.append(brk.value != null ? brk.value.pos() : brk.pos()); 1652 caseTypes.append(brk.value != null ? brk.value.type : syms.errType); 1653 } 1654 super.visitYield(brk); 1655 } 1656 1657 @Override public void visitClassDef(JCClassDecl tree) {} 1658 @Override public void visitLambda(JCLambda tree) {} 1659 }.scan(c.stats); 1660 }); 1661 1662 if (tree.cases.isEmpty()) { 1663 log.error(tree.pos(), 1664 Errors.SwitchExpressionEmpty); 1665 } else if (caseTypes.isEmpty()) { 1666 log.error(tree.pos(), 1667 Errors.SwitchExpressionNoResultExpressions); 1668 } 1669 1670 Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(caseTypePositions.toList(), caseTypes.toList()) : pt(); 1671 1672 result = tree.type = wrongContext? types.createErrorType(pt()) : check(tree, owntype, KindSelector.VAL, resultInfo); 1673 } 1674 //where: 1675 CheckContext switchExpressionContext(CheckContext checkContext) { 1676 return new Check.NestedCheckContext(checkContext) { 1677 //this will use enclosing check context to check compatibility of 1678 //subexpression against target type; if we are in a method check context, 1679 //depending on whether boxing is allowed, we could have incompatibilities 1680 @Override 1681 public void report(DiagnosticPosition pos, JCDiagnostic details) { 1682 enclosingContext.report(pos, diags.fragment(Fragments.IncompatibleTypeInSwitchExpression(details))); 1683 } 1684 }; 1685 } 1686 1687 private void handleSwitch(JCTree switchTree, 1688 JCExpression selector, 1689 List<JCCase> cases, 1690 BiConsumer<JCCase, Env<AttrContext>> attribCase) { 1691 Type seltype = attribExpr(selector, env); 1692 1693 Env<AttrContext> switchEnv = 1694 env.dup(switchTree, env.info.dup(env.info.scope.dup())); 1695 1696 try { 1697 boolean enumSwitch = (seltype.tsym.flags() & Flags.ENUM) != 0; 1698 boolean stringSwitch = types.isSameType(seltype, syms.stringType); 1699 boolean booleanSwitch = types.isSameType(types.unboxedTypeOrType(seltype), syms.booleanType); 1700 boolean errorEnumSwitch = TreeInfo.isErrorEnumSwitch(selector, cases); 1701 boolean intSwitch = types.isAssignable(seltype, syms.intType); 1702 boolean patternSwitch; 1703 if (seltype.isPrimitive() && !intSwitch) { 1704 preview.checkSourceLevel(selector.pos(), Feature.PRIMITIVE_PATTERNS); 1705 patternSwitch = true; 1706 } 1707 if (!enumSwitch && !stringSwitch && !errorEnumSwitch && 1708 !intSwitch) { 1709 preview.checkSourceLevel(selector.pos(), Feature.PATTERN_SWITCH); 1710 patternSwitch = true; 1711 } else { 1712 patternSwitch = cases.stream() 1713 .flatMap(c -> c.labels.stream()) 1714 .anyMatch(l -> l.hasTag(PATTERNCASELABEL) || 1715 TreeInfo.isNullCaseLabel(l)); 1716 } 1717 1718 // Attribute all cases and 1719 // check that there are no duplicate case labels or default clauses. 1720 Set<Object> constants = new HashSet<>(); // The set of case constants. 1721 boolean hasDefault = false; // Is there a default label? 1722 boolean hasUnconditionalPattern = false; // Is there a unconditional pattern? 1723 boolean lastPatternErroneous = false; // Has the last pattern erroneous type? 1724 boolean hasNullPattern = false; // Is there a null pattern? 1725 CaseTree.CaseKind caseKind = null; 1726 boolean wasError = false; 1727 JCCaseLabel unconditionalCaseLabel = null; 1728 for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) { 1729 JCCase c = l.head; 1730 if (caseKind == null) { 1731 caseKind = c.caseKind; 1732 } else if (caseKind != c.caseKind && !wasError) { 1733 log.error(c.pos(), 1734 Errors.SwitchMixingCaseTypes); 1735 wasError = true; 1736 } 1737 MatchBindings currentBindings = null; 1738 MatchBindings guardBindings = null; 1739 for (List<JCCaseLabel> labels = c.labels; labels.nonEmpty(); labels = labels.tail) { 1740 JCCaseLabel label = labels.head; 1741 if (label instanceof JCConstantCaseLabel constLabel) { 1742 JCExpression expr = constLabel.expr; 1743 if (TreeInfo.isNull(expr)) { 1744 preview.checkSourceLevel(expr.pos(), Feature.CASE_NULL); 1745 if (hasNullPattern) { 1746 log.error(label.pos(), Errors.DuplicateCaseLabel); 1747 } 1748 hasNullPattern = true; 1749 attribExpr(expr, switchEnv, seltype); 1750 matchBindings = new MatchBindings(matchBindings.bindingsWhenTrue, matchBindings.bindingsWhenFalse, true); 1751 } else if (enumSwitch) { 1752 Symbol sym = enumConstant(expr, seltype); 1753 if (sym == null) { 1754 if (allowPatternSwitch) { 1755 attribTree(expr, switchEnv, caseLabelResultInfo(seltype)); 1756 Symbol enumSym = TreeInfo.symbol(expr); 1757 if (enumSym == null || !enumSym.isEnum() || enumSym.kind != VAR) { 1758 log.error(expr.pos(), Errors.EnumLabelMustBeEnumConstant); 1759 } else if (!constants.add(enumSym)) { 1760 log.error(label.pos(), Errors.DuplicateCaseLabel); 1761 } 1762 } else { 1763 log.error(expr.pos(), Errors.EnumLabelMustBeUnqualifiedEnum); 1764 } 1765 } else if (!constants.add(sym)) { 1766 log.error(label.pos(), Errors.DuplicateCaseLabel); 1767 } 1768 } else if (errorEnumSwitch) { 1769 //error recovery: the selector is erroneous, and all the case labels 1770 //are identifiers. This could be an enum switch - don't report resolve 1771 //error for the case label: 1772 var prevResolveHelper = rs.basicLogResolveHelper; 1773 try { 1774 rs.basicLogResolveHelper = rs.silentLogResolveHelper; 1775 attribExpr(expr, switchEnv, seltype); 1776 } finally { 1777 rs.basicLogResolveHelper = prevResolveHelper; 1778 } 1779 } else { 1780 Type pattype = attribTree(expr, switchEnv, caseLabelResultInfo(seltype)); 1781 if (!pattype.hasTag(ERROR)) { 1782 if (pattype.constValue() == null) { 1783 Symbol s = TreeInfo.symbol(expr); 1784 if (s != null && s.kind == TYP) { 1785 log.error(expr.pos(), 1786 Errors.PatternExpected); 1787 } else if (s == null || !s.isEnum()) { 1788 log.error(expr.pos(), 1789 (stringSwitch ? Errors.StringConstReq 1790 : intSwitch ? Errors.ConstExprReq 1791 : Errors.PatternOrEnumReq)); 1792 } else if (!constants.add(s)) { 1793 log.error(label.pos(), Errors.DuplicateCaseLabel); 1794 } 1795 } 1796 else { 1797 if (!stringSwitch && !intSwitch && 1798 !((pattype.getTag().isInSuperClassesOf(LONG) || pattype.getTag().equals(BOOLEAN)) && 1799 types.isSameType(types.unboxedTypeOrType(seltype), pattype))) { 1800 log.error(label.pos(), Errors.ConstantLabelNotCompatible(pattype, seltype)); 1801 } else if (!constants.add(pattype.constValue())) { 1802 log.error(c.pos(), Errors.DuplicateCaseLabel); 1803 } 1804 } 1805 } 1806 } 1807 } else if (label instanceof JCDefaultCaseLabel def) { 1808 if (hasDefault) { 1809 log.error(label.pos(), Errors.DuplicateDefaultLabel); 1810 } else if (hasUnconditionalPattern) { 1811 log.error(label.pos(), Errors.UnconditionalPatternAndDefault); 1812 } else if (booleanSwitch && constants.containsAll(Set.of(0, 1))) { 1813 log.error(label.pos(), Errors.DefaultAndBothBooleanValues); 1814 } 1815 hasDefault = true; 1816 matchBindings = MatchBindingsComputer.EMPTY; 1817 } else if (label instanceof JCPatternCaseLabel patternlabel) { 1818 //pattern 1819 JCPattern pat = patternlabel.pat; 1820 attribExpr(pat, switchEnv, seltype); 1821 Type primaryType = TreeInfo.primaryPatternType(pat); 1822 1823 if (primaryType.isPrimitive()) { 1824 preview.checkSourceLevel(pat.pos(), Feature.PRIMITIVE_PATTERNS); 1825 } else if (!primaryType.hasTag(TYPEVAR)) { 1826 primaryType = chk.checkClassOrArrayType(pat.pos(), primaryType); 1827 } 1828 checkCastablePattern(pat.pos(), seltype, primaryType); 1829 Type patternType = types.erasure(primaryType); 1830 JCExpression guard = c.guard; 1831 if (guardBindings == null && guard != null) { 1832 MatchBindings afterPattern = matchBindings; 1833 Env<AttrContext> bodyEnv = bindingEnv(switchEnv, matchBindings.bindingsWhenTrue); 1834 try { 1835 attribExpr(guard, bodyEnv, syms.booleanType); 1836 } finally { 1837 bodyEnv.info.scope.leave(); 1838 } 1839 1840 guardBindings = matchBindings; 1841 matchBindings = afterPattern; 1842 1843 if (TreeInfo.isBooleanWithValue(guard, 0)) { 1844 log.error(guard.pos(), Errors.GuardHasConstantExpressionFalse); 1845 } 1846 } 1847 boolean unguarded = TreeInfo.unguardedCase(c) && !pat.hasTag(RECORDPATTERN); 1848 boolean unconditional = 1849 unguarded && 1850 !patternType.isErroneous() && 1851 types.isUnconditionallyExact(seltype, patternType); 1852 if (unconditional) { 1853 if (hasUnconditionalPattern) { 1854 log.error(pat.pos(), Errors.DuplicateUnconditionalPattern); 1855 } else if (hasDefault) { 1856 log.error(pat.pos(), Errors.UnconditionalPatternAndDefault); 1857 } else if (booleanSwitch && constants.containsAll(Set.of(0, 1))) { 1858 log.error(pat.pos(), Errors.UnconditionalPatternAndBothBooleanValues); 1859 } 1860 hasUnconditionalPattern = true; 1861 unconditionalCaseLabel = label; 1862 } 1863 lastPatternErroneous = patternType.isErroneous(); 1864 } else { 1865 Assert.error(); 1866 } 1867 currentBindings = matchBindingsComputer.switchCase(label, currentBindings, matchBindings); 1868 } 1869 1870 if (guardBindings != null) { 1871 currentBindings = matchBindingsComputer.caseGuard(c, currentBindings, guardBindings); 1872 } 1873 1874 Env<AttrContext> caseEnv = 1875 bindingEnv(switchEnv, c, currentBindings.bindingsWhenTrue); 1876 try { 1877 attribCase.accept(c, caseEnv); 1878 } finally { 1879 caseEnv.info.scope.leave(); 1880 } 1881 addVars(c.stats, switchEnv.info.scope); 1882 1883 preFlow(c); 1884 c.completesNormally = flow.aliveAfter(caseEnv, c, make); 1885 } 1886 if (patternSwitch) { 1887 chk.checkSwitchCaseStructure(cases); 1888 chk.checkSwitchCaseLabelDominated(unconditionalCaseLabel, cases); 1889 } 1890 if (switchTree.hasTag(SWITCH)) { 1891 ((JCSwitch) switchTree).hasUnconditionalPattern = 1892 hasDefault || hasUnconditionalPattern || lastPatternErroneous; 1893 ((JCSwitch) switchTree).patternSwitch = patternSwitch; 1894 } else if (switchTree.hasTag(SWITCH_EXPRESSION)) { 1895 ((JCSwitchExpression) switchTree).hasUnconditionalPattern = 1896 hasDefault || hasUnconditionalPattern || lastPatternErroneous; 1897 ((JCSwitchExpression) switchTree).patternSwitch = patternSwitch; 1898 } else { 1899 Assert.error(switchTree.getTag().name()); 1900 } 1901 } finally { 1902 switchEnv.info.scope.leave(); 1903 } 1904 } 1905 // where 1906 private ResultInfo caseLabelResultInfo(Type seltype) { 1907 return new ResultInfo(KindSelector.VAL_TYP, 1908 !seltype.hasTag(ERROR) ? seltype 1909 : Type.noType); 1910 } 1911 /** Add any variables defined in stats to the switch scope. */ 1912 private static void addVars(List<JCStatement> stats, WriteableScope switchScope) { 1913 for (;stats.nonEmpty(); stats = stats.tail) { 1914 JCTree stat = stats.head; 1915 if (stat.hasTag(VARDEF)) 1916 switchScope.enter(((JCVariableDecl) stat).sym); 1917 } 1918 } 1919 // where 1920 /** Return the selected enumeration constant symbol, or null. */ 1921 private Symbol enumConstant(JCTree tree, Type enumType) { 1922 if (tree.hasTag(IDENT)) { 1923 JCIdent ident = (JCIdent)tree; 1924 Name name = ident.name; 1925 for (Symbol sym : enumType.tsym.members().getSymbolsByName(name)) { 1926 if (sym.kind == VAR) { 1927 Symbol s = ident.sym = sym; 1928 ((VarSymbol)s).getConstValue(); // ensure initializer is evaluated 1929 ident.type = s.type; 1930 return ((s.flags_field & Flags.ENUM) == 0) 1931 ? null : s; 1932 } 1933 } 1934 } 1935 return null; 1936 } 1937 1938 public void visitSynchronized(JCSynchronized tree) { 1939 chk.checkRefType(tree.pos(), attribExpr(tree.lock, env)); 1940 if (env.info.lint.isEnabled(LintCategory.SYNCHRONIZATION) && isValueBased(tree.lock.type)) { 1941 log.warning(LintCategory.SYNCHRONIZATION, tree.pos(), Warnings.AttemptToSynchronizeOnInstanceOfValueBasedClass); 1942 } 1943 attribStat(tree.body, env); 1944 result = null; 1945 } 1946 // where 1947 private boolean isValueBased(Type t) { 1948 return t != null && t.tsym != null && (t.tsym.flags() & VALUE_BASED) != 0; 1949 } 1950 1951 1952 public void visitTry(JCTry tree) { 1953 // Create a new local environment with a local 1954 Env<AttrContext> localEnv = env.dup(tree, env.info.dup(env.info.scope.dup())); 1955 try { 1956 boolean isTryWithResource = tree.resources.nonEmpty(); 1957 // Create a nested environment for attributing the try block if needed 1958 Env<AttrContext> tryEnv = isTryWithResource ? 1959 env.dup(tree, localEnv.info.dup(localEnv.info.scope.dup())) : 1960 localEnv; 1961 try { 1962 // Attribute resource declarations 1963 for (JCTree resource : tree.resources) { 1964 CheckContext twrContext = new Check.NestedCheckContext(resultInfo.checkContext) { 1965 @Override 1966 public void report(DiagnosticPosition pos, JCDiagnostic details) { 1967 chk.basicHandler.report(pos, diags.fragment(Fragments.TryNotApplicableToType(details))); 1968 } 1969 }; 1970 ResultInfo twrResult = 1971 new ResultInfo(KindSelector.VAR, 1972 syms.autoCloseableType, 1973 twrContext); 1974 if (resource.hasTag(VARDEF)) { 1975 attribStat(resource, tryEnv); 1976 twrResult.check(resource, resource.type); 1977 1978 //check that resource type cannot throw InterruptedException 1979 checkAutoCloseable(resource.pos(), localEnv, resource.type); 1980 1981 VarSymbol var = ((JCVariableDecl) resource).sym; 1982 1983 var.flags_field |= Flags.FINAL; 1984 var.setData(ElementKind.RESOURCE_VARIABLE); 1985 } else { 1986 attribTree(resource, tryEnv, twrResult); 1987 } 1988 } 1989 // Attribute body 1990 attribStat(tree.body, tryEnv); 1991 } finally { 1992 if (isTryWithResource) 1993 tryEnv.info.scope.leave(); 1994 } 1995 1996 // Attribute catch clauses 1997 for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { 1998 JCCatch c = l.head; 1999 Env<AttrContext> catchEnv = 2000 localEnv.dup(c, localEnv.info.dup(localEnv.info.scope.dup())); 2001 try { 2002 Type ctype = attribStat(c.param, catchEnv); 2003 if (TreeInfo.isMultiCatch(c)) { 2004 //multi-catch parameter is implicitly marked as final 2005 c.param.sym.flags_field |= FINAL | UNION; 2006 } 2007 if (c.param.sym.kind == VAR) { 2008 c.param.sym.setData(ElementKind.EXCEPTION_PARAMETER); 2009 } 2010 chk.checkType(c.param.vartype.pos(), 2011 chk.checkClassType(c.param.vartype.pos(), ctype), 2012 syms.throwableType); 2013 attribStat(c.body, catchEnv); 2014 } finally { 2015 catchEnv.info.scope.leave(); 2016 } 2017 } 2018 2019 // Attribute finalizer 2020 if (tree.finalizer != null) attribStat(tree.finalizer, localEnv); 2021 result = null; 2022 } 2023 finally { 2024 localEnv.info.scope.leave(); 2025 } 2026 } 2027 2028 void checkAutoCloseable(DiagnosticPosition pos, Env<AttrContext> env, Type resource) { 2029 if (!resource.isErroneous() && 2030 types.asSuper(resource, syms.autoCloseableType.tsym) != null && 2031 !types.isSameType(resource, syms.autoCloseableType)) { // Don't emit warning for AutoCloseable itself 2032 Symbol close = syms.noSymbol; 2033 Log.DiagnosticHandler discardHandler = new Log.DiscardDiagnosticHandler(log); 2034 try { 2035 close = rs.resolveQualifiedMethod(pos, 2036 env, 2037 types.skipTypeVars(resource, false), 2038 names.close, 2039 List.nil(), 2040 List.nil()); 2041 } 2042 finally { 2043 log.popDiagnosticHandler(discardHandler); 2044 } 2045 if (close.kind == MTH && 2046 close.overrides(syms.autoCloseableClose, resource.tsym, types, true) && 2047 chk.isHandled(syms.interruptedExceptionType, types.memberType(resource, close).getThrownTypes()) && 2048 env.info.lint.isEnabled(LintCategory.TRY)) { 2049 log.warning(LintCategory.TRY, pos, Warnings.TryResourceThrowsInterruptedExc(resource)); 2050 } 2051 } 2052 } 2053 2054 public void visitConditional(JCConditional tree) { 2055 Type condtype = attribExpr(tree.cond, env, syms.booleanType); 2056 MatchBindings condBindings = matchBindings; 2057 2058 tree.polyKind = (pt().hasTag(NONE) && pt() != Type.recoveryType && pt() != Infer.anyPoly || 2059 isBooleanOrNumeric(env, tree)) ? 2060 PolyKind.STANDALONE : PolyKind.POLY; 2061 2062 if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) { 2063 //this means we are returning a poly conditional from void-compatible lambda expression 2064 resultInfo.checkContext.report(tree, diags.fragment(Fragments.ConditionalTargetCantBeVoid)); 2065 result = tree.type = types.createErrorType(resultInfo.pt); 2066 return; 2067 } 2068 2069 ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ? 2070 unknownExprInfo : 2071 resultInfo.dup(conditionalContext(resultInfo.checkContext)); 2072 2073 2074 // x ? y : z 2075 // include x's bindings when true in y 2076 // include x's bindings when false in z 2077 2078 Type truetype; 2079 Env<AttrContext> trueEnv = bindingEnv(env, condBindings.bindingsWhenTrue); 2080 try { 2081 truetype = attribTree(tree.truepart, trueEnv, condInfo); 2082 } finally { 2083 trueEnv.info.scope.leave(); 2084 } 2085 2086 MatchBindings trueBindings = matchBindings; 2087 2088 Type falsetype; 2089 Env<AttrContext> falseEnv = bindingEnv(env, condBindings.bindingsWhenFalse); 2090 try { 2091 falsetype = attribTree(tree.falsepart, falseEnv, condInfo); 2092 } finally { 2093 falseEnv.info.scope.leave(); 2094 } 2095 2096 MatchBindings falseBindings = matchBindings; 2097 2098 Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? 2099 condType(List.of(tree.truepart.pos(), tree.falsepart.pos()), 2100 List.of(truetype, falsetype)) : pt(); 2101 if (condtype.constValue() != null && 2102 truetype.constValue() != null && 2103 falsetype.constValue() != null && 2104 !owntype.hasTag(NONE)) { 2105 //constant folding 2106 owntype = cfolder.coerce(condtype.isTrue() ? truetype : falsetype, owntype); 2107 } 2108 result = check(tree, owntype, KindSelector.VAL, resultInfo); 2109 matchBindings = matchBindingsComputer.conditional(tree, condBindings, trueBindings, falseBindings); 2110 } 2111 //where 2112 private boolean isBooleanOrNumeric(Env<AttrContext> env, JCExpression tree) { 2113 switch (tree.getTag()) { 2114 case LITERAL: return ((JCLiteral)tree).typetag.isSubRangeOf(DOUBLE) || 2115 ((JCLiteral)tree).typetag == BOOLEAN || 2116 ((JCLiteral)tree).typetag == BOT; 2117 case LAMBDA: case REFERENCE: return false; 2118 case PARENS: return isBooleanOrNumeric(env, ((JCParens)tree).expr); 2119 case CONDEXPR: 2120 JCConditional condTree = (JCConditional)tree; 2121 return isBooleanOrNumeric(env, condTree.truepart) && 2122 isBooleanOrNumeric(env, condTree.falsepart); 2123 case APPLY: 2124 JCMethodInvocation speculativeMethodTree = 2125 (JCMethodInvocation)deferredAttr.attribSpeculative( 2126 tree, env, unknownExprInfo, 2127 argumentAttr.withLocalCacheContext()); 2128 Symbol msym = TreeInfo.symbol(speculativeMethodTree.meth); 2129 Type receiverType = speculativeMethodTree.meth.hasTag(IDENT) ? 2130 env.enclClass.type : 2131 ((JCFieldAccess)speculativeMethodTree.meth).selected.type; 2132 Type owntype = types.memberType(receiverType, msym).getReturnType(); 2133 return primitiveOrBoxed(owntype); 2134 case NEWCLASS: 2135 JCExpression className = 2136 removeClassParams.translate(((JCNewClass)tree).clazz); 2137 JCExpression speculativeNewClassTree = 2138 (JCExpression)deferredAttr.attribSpeculative( 2139 className, env, unknownTypeInfo, 2140 argumentAttr.withLocalCacheContext()); 2141 return primitiveOrBoxed(speculativeNewClassTree.type); 2142 default: 2143 Type speculativeType = deferredAttr.attribSpeculative(tree, env, unknownExprInfo, 2144 argumentAttr.withLocalCacheContext()).type; 2145 return primitiveOrBoxed(speculativeType); 2146 } 2147 } 2148 //where 2149 boolean primitiveOrBoxed(Type t) { 2150 return (!t.hasTag(TYPEVAR) && !t.isErroneous() && types.unboxedTypeOrType(t).isPrimitive()); 2151 } 2152 2153 TreeTranslator removeClassParams = new TreeTranslator() { 2154 @Override 2155 public void visitTypeApply(JCTypeApply tree) { 2156 result = translate(tree.clazz); 2157 } 2158 }; 2159 2160 CheckContext conditionalContext(CheckContext checkContext) { 2161 return new Check.NestedCheckContext(checkContext) { 2162 //this will use enclosing check context to check compatibility of 2163 //subexpression against target type; if we are in a method check context, 2164 //depending on whether boxing is allowed, we could have incompatibilities 2165 @Override 2166 public void report(DiagnosticPosition pos, JCDiagnostic details) { 2167 enclosingContext.report(pos, diags.fragment(Fragments.IncompatibleTypeInConditional(details))); 2168 } 2169 }; 2170 } 2171 2172 /** Compute the type of a conditional expression, after 2173 * checking that it exists. See JLS 15.25. Does not take into 2174 * account the special case where condition and both arms 2175 * are constants. 2176 * 2177 * @param pos The source position to be used for error 2178 * diagnostics. 2179 * @param thentype The type of the expression's then-part. 2180 * @param elsetype The type of the expression's else-part. 2181 */ 2182 Type condType(List<DiagnosticPosition> positions, List<Type> condTypes) { 2183 if (condTypes.isEmpty()) { 2184 return syms.objectType; //TODO: how to handle? 2185 } 2186 Type first = condTypes.head; 2187 // If same type, that is the result 2188 if (condTypes.tail.stream().allMatch(t -> types.isSameType(first, t))) 2189 return first.baseType(); 2190 2191 List<Type> unboxedTypes = condTypes.stream() 2192 .map(t -> t.isPrimitive() ? t : types.unboxedType(t)) 2193 .collect(List.collector()); 2194 2195 // Otherwise, if both arms can be converted to a numeric 2196 // type, return the least numeric type that fits both arms 2197 // (i.e. return larger of the two, or return int if one 2198 // arm is short, the other is char). 2199 if (unboxedTypes.stream().allMatch(t -> t.isPrimitive())) { 2200 // If one arm has an integer subrange type (i.e., byte, 2201 // short, or char), and the other is an integer constant 2202 // that fits into the subrange, return the subrange type. 2203 for (Type type : unboxedTypes) { 2204 if (!type.getTag().isStrictSubRangeOf(INT)) { 2205 continue; 2206 } 2207 if (unboxedTypes.stream().filter(t -> t != type).allMatch(t -> t.hasTag(INT) && types.isAssignable(t, type))) 2208 return type.baseType(); 2209 } 2210 2211 for (TypeTag tag : primitiveTags) { 2212 Type candidate = syms.typeOfTag[tag.ordinal()]; 2213 if (unboxedTypes.stream().allMatch(t -> types.isSubtype(t, candidate))) { 2214 return candidate; 2215 } 2216 } 2217 } 2218 2219 // Those were all the cases that could result in a primitive 2220 condTypes = condTypes.stream() 2221 .map(t -> t.isPrimitive() ? types.boxedClass(t).type : t) 2222 .collect(List.collector()); 2223 2224 for (Type type : condTypes) { 2225 if (condTypes.stream().filter(t -> t != type).allMatch(t -> types.isAssignable(t, type))) 2226 return type.baseType(); 2227 } 2228 2229 Iterator<DiagnosticPosition> posIt = positions.iterator(); 2230 2231 condTypes = condTypes.stream() 2232 .map(t -> chk.checkNonVoid(posIt.next(), t)) 2233 .collect(List.collector()); 2234 2235 // both are known to be reference types. The result is 2236 // lub(thentype,elsetype). This cannot fail, as it will 2237 // always be possible to infer "Object" if nothing better. 2238 return types.lub(condTypes.stream() 2239 .map(t -> t.baseType()) 2240 .filter(t -> !t.hasTag(BOT)) 2241 .collect(List.collector())); 2242 } 2243 2244 static final TypeTag[] primitiveTags = new TypeTag[]{ 2245 BYTE, 2246 CHAR, 2247 SHORT, 2248 INT, 2249 LONG, 2250 FLOAT, 2251 DOUBLE, 2252 BOOLEAN, 2253 }; 2254 2255 Env<AttrContext> bindingEnv(Env<AttrContext> env, List<BindingSymbol> bindings) { 2256 return bindingEnv(env, env.tree, bindings); 2257 } 2258 2259 Env<AttrContext> bindingEnv(Env<AttrContext> env, JCTree newTree, List<BindingSymbol> bindings) { 2260 Env<AttrContext> env1 = env.dup(newTree, env.info.dup(env.info.scope.dup())); 2261 bindings.forEach(env1.info.scope::enter); 2262 return env1; 2263 } 2264 2265 public void visitIf(JCIf tree) { 2266 attribExpr(tree.cond, env, syms.booleanType); 2267 2268 // if (x) { y } [ else z ] 2269 // include x's bindings when true in y 2270 // include x's bindings when false in z 2271 2272 MatchBindings condBindings = matchBindings; 2273 Env<AttrContext> thenEnv = bindingEnv(env, condBindings.bindingsWhenTrue); 2274 2275 try { 2276 attribStat(tree.thenpart, thenEnv); 2277 } finally { 2278 thenEnv.info.scope.leave(); 2279 } 2280 2281 preFlow(tree.thenpart); 2282 boolean aliveAfterThen = flow.aliveAfter(env, tree.thenpart, make); 2283 boolean aliveAfterElse; 2284 2285 if (tree.elsepart != null) { 2286 Env<AttrContext> elseEnv = bindingEnv(env, condBindings.bindingsWhenFalse); 2287 try { 2288 attribStat(tree.elsepart, elseEnv); 2289 } finally { 2290 elseEnv.info.scope.leave(); 2291 } 2292 preFlow(tree.elsepart); 2293 aliveAfterElse = flow.aliveAfter(env, tree.elsepart, make); 2294 } else { 2295 aliveAfterElse = true; 2296 } 2297 2298 chk.checkEmptyIf(tree); 2299 2300 List<BindingSymbol> afterIfBindings = List.nil(); 2301 2302 if (aliveAfterThen && !aliveAfterElse) { 2303 afterIfBindings = condBindings.bindingsWhenTrue; 2304 } else if (aliveAfterElse && !aliveAfterThen) { 2305 afterIfBindings = condBindings.bindingsWhenFalse; 2306 } 2307 2308 addBindings2Scope(tree, afterIfBindings); 2309 2310 result = null; 2311 } 2312 2313 void preFlow(JCTree tree) { 2314 attrRecover.doRecovery(); 2315 new PostAttrAnalyzer() { 2316 @Override 2317 public void scan(JCTree tree) { 2318 if (tree == null || 2319 (tree.type != null && 2320 tree.type == Type.stuckType)) { 2321 //don't touch stuck expressions! 2322 return; 2323 } 2324 super.scan(tree); 2325 } 2326 2327 @Override 2328 public void visitClassDef(JCClassDecl that) { 2329 if (that.sym != null) { 2330 // Method preFlow shouldn't visit class definitions 2331 // that have not been entered and attributed. 2332 // See JDK-8254557 and JDK-8203277 for more details. 2333 super.visitClassDef(that); 2334 } 2335 } 2336 2337 @Override 2338 public void visitLambda(JCLambda that) { 2339 if (that.type != null) { 2340 // Method preFlow shouldn't visit lambda expressions 2341 // that have not been entered and attributed. 2342 // See JDK-8254557 and JDK-8203277 for more details. 2343 super.visitLambda(that); 2344 } 2345 } 2346 }.scan(tree); 2347 } 2348 2349 public void visitExec(JCExpressionStatement tree) { 2350 //a fresh environment is required for 292 inference to work properly --- 2351 //see Infer.instantiatePolymorphicSignatureInstance() 2352 Env<AttrContext> localEnv = env.dup(tree); 2353 attribExpr(tree.expr, localEnv); 2354 result = null; 2355 } 2356 2357 public void visitBreak(JCBreak tree) { 2358 tree.target = findJumpTarget(tree.pos(), tree.getTag(), tree.label, env); 2359 result = null; 2360 } 2361 2362 public void visitYield(JCYield tree) { 2363 if (env.info.yieldResult != null) { 2364 attribTree(tree.value, env, env.info.yieldResult); 2365 tree.target = findJumpTarget(tree.pos(), tree.getTag(), names.empty, env); 2366 } else { 2367 log.error(tree.pos(), tree.value.hasTag(PARENS) 2368 ? Errors.NoSwitchExpressionQualify 2369 : Errors.NoSwitchExpression); 2370 attribTree(tree.value, env, unknownExprInfo); 2371 } 2372 result = null; 2373 } 2374 2375 public void visitContinue(JCContinue tree) { 2376 tree.target = findJumpTarget(tree.pos(), tree.getTag(), tree.label, env); 2377 result = null; 2378 } 2379 //where 2380 /** Return the target of a break, continue or yield statement, 2381 * if it exists, report an error if not. 2382 * Note: The target of a labelled break or continue is the 2383 * (non-labelled) statement tree referred to by the label, 2384 * not the tree representing the labelled statement itself. 2385 * 2386 * @param pos The position to be used for error diagnostics 2387 * @param tag The tag of the jump statement. This is either 2388 * Tree.BREAK or Tree.CONTINUE. 2389 * @param label The label of the jump statement, or null if no 2390 * label is given. 2391 * @param env The environment current at the jump statement. 2392 */ 2393 private JCTree findJumpTarget(DiagnosticPosition pos, 2394 JCTree.Tag tag, 2395 Name label, 2396 Env<AttrContext> env) { 2397 Pair<JCTree, Error> jumpTarget = findJumpTargetNoError(tag, label, env); 2398 2399 if (jumpTarget.snd != null) { 2400 log.error(pos, jumpTarget.snd); 2401 } 2402 2403 return jumpTarget.fst; 2404 } 2405 /** Return the target of a break or continue statement, if it exists, 2406 * report an error if not. 2407 * Note: The target of a labelled break or continue is the 2408 * (non-labelled) statement tree referred to by the label, 2409 * not the tree representing the labelled statement itself. 2410 * 2411 * @param tag The tag of the jump statement. This is either 2412 * Tree.BREAK or Tree.CONTINUE. 2413 * @param label The label of the jump statement, or null if no 2414 * label is given. 2415 * @param env The environment current at the jump statement. 2416 */ 2417 private Pair<JCTree, JCDiagnostic.Error> findJumpTargetNoError(JCTree.Tag tag, 2418 Name label, 2419 Env<AttrContext> env) { 2420 // Search environments outwards from the point of jump. 2421 Env<AttrContext> env1 = env; 2422 JCDiagnostic.Error pendingError = null; 2423 LOOP: 2424 while (env1 != null) { 2425 switch (env1.tree.getTag()) { 2426 case LABELLED: 2427 JCLabeledStatement labelled = (JCLabeledStatement)env1.tree; 2428 if (label == labelled.label) { 2429 // If jump is a continue, check that target is a loop. 2430 if (tag == CONTINUE) { 2431 if (!labelled.body.hasTag(DOLOOP) && 2432 !labelled.body.hasTag(WHILELOOP) && 2433 !labelled.body.hasTag(FORLOOP) && 2434 !labelled.body.hasTag(FOREACHLOOP)) { 2435 pendingError = Errors.NotLoopLabel(label); 2436 } 2437 // Found labelled statement target, now go inwards 2438 // to next non-labelled tree. 2439 return Pair.of(TreeInfo.referencedStatement(labelled), pendingError); 2440 } else { 2441 return Pair.of(labelled, pendingError); 2442 } 2443 } 2444 break; 2445 case DOLOOP: 2446 case WHILELOOP: 2447 case FORLOOP: 2448 case FOREACHLOOP: 2449 if (label == null) return Pair.of(env1.tree, pendingError); 2450 break; 2451 case SWITCH: 2452 if (label == null && tag == BREAK) return Pair.of(env1.tree, null); 2453 break; 2454 case SWITCH_EXPRESSION: 2455 if (tag == YIELD) { 2456 return Pair.of(env1.tree, null); 2457 } else if (tag == BREAK) { 2458 pendingError = Errors.BreakOutsideSwitchExpression; 2459 } else { 2460 pendingError = Errors.ContinueOutsideSwitchExpression; 2461 } 2462 break; 2463 case LAMBDA: 2464 case METHODDEF: 2465 case CLASSDEF: 2466 break LOOP; 2467 default: 2468 } 2469 env1 = env1.next; 2470 } 2471 if (label != null) 2472 return Pair.of(null, Errors.UndefLabel(label)); 2473 else if (pendingError != null) 2474 return Pair.of(null, pendingError); 2475 else if (tag == CONTINUE) 2476 return Pair.of(null, Errors.ContOutsideLoop); 2477 else 2478 return Pair.of(null, Errors.BreakOutsideSwitchLoop); 2479 } 2480 2481 public void visitReturn(JCReturn tree) { 2482 // Check that there is an enclosing method which is 2483 // nested within than the enclosing class. 2484 if (env.info.returnResult == null) { 2485 log.error(tree.pos(), Errors.RetOutsideMeth); 2486 } else if (env.info.yieldResult != null) { 2487 log.error(tree.pos(), Errors.ReturnOutsideSwitchExpression); 2488 if (tree.expr != null) { 2489 attribExpr(tree.expr, env, env.info.yieldResult.pt); 2490 } 2491 } else if (!env.info.isLambda && 2492 !env.info.isNewClass && 2493 env.enclMethod != null && 2494 TreeInfo.isCompactConstructor(env.enclMethod)) { 2495 log.error(env.enclMethod, 2496 Errors.InvalidCanonicalConstructorInRecord(Fragments.Compact, env.enclMethod.sym.name, Fragments.CanonicalCantHaveReturnStatement)); 2497 } else { 2498 // Attribute return expression, if it exists, and check that 2499 // it conforms to result type of enclosing method. 2500 if (tree.expr != null) { 2501 if (env.info.returnResult.pt.hasTag(VOID)) { 2502 env.info.returnResult.checkContext.report(tree.expr.pos(), 2503 diags.fragment(Fragments.UnexpectedRetVal)); 2504 } 2505 attribTree(tree.expr, env, env.info.returnResult); 2506 } else if (!env.info.returnResult.pt.hasTag(VOID) && 2507 !env.info.returnResult.pt.hasTag(NONE)) { 2508 env.info.returnResult.checkContext.report(tree.pos(), 2509 diags.fragment(Fragments.MissingRetVal(env.info.returnResult.pt))); 2510 } 2511 } 2512 result = null; 2513 } 2514 2515 public void visitThrow(JCThrow tree) { 2516 Type owntype = attribExpr(tree.expr, env, Type.noType); 2517 chk.checkType(tree, owntype, syms.throwableType); 2518 result = null; 2519 } 2520 2521 public void visitAssert(JCAssert tree) { 2522 attribExpr(tree.cond, env, syms.booleanType); 2523 if (tree.detail != null) { 2524 chk.checkNonVoid(tree.detail.pos(), attribExpr(tree.detail, env)); 2525 } 2526 result = null; 2527 } 2528 2529 /** Visitor method for method invocations. 2530 * NOTE: The method part of an application will have in its type field 2531 * the return type of the method, not the method's type itself! 2532 */ 2533 public void visitApply(JCMethodInvocation tree) { 2534 // The local environment of a method application is 2535 // a new environment nested in the current one. 2536 Env<AttrContext> localEnv = env.dup(tree, env.info.dup()); 2537 2538 // The types of the actual method arguments. 2539 List<Type> argtypes; 2540 2541 // The types of the actual method type arguments. 2542 List<Type> typeargtypes = null; 2543 2544 Name methName = TreeInfo.name(tree.meth); 2545 2546 boolean isConstructorCall = 2547 methName == names._this || methName == names._super; 2548 2549 ListBuffer<Type> argtypesBuf = new ListBuffer<>(); 2550 if (isConstructorCall) { 2551 2552 // Attribute arguments, yielding list of argument types. 2553 KindSelector kind = attribArgs(KindSelector.MTH, tree.args, localEnv, argtypesBuf); 2554 argtypes = argtypesBuf.toList(); 2555 typeargtypes = attribTypes(tree.typeargs, localEnv); 2556 2557 // Done with this()/super() parameters. End of constructor prologue. 2558 env.info.ctorPrologue = false; 2559 2560 // Variable `site' points to the class in which the called 2561 // constructor is defined. 2562 Type site = env.enclClass.sym.type; 2563 if (methName == names._super) { 2564 if (site == syms.objectType) { 2565 log.error(tree.meth.pos(), Errors.NoSuperclass(site)); 2566 site = types.createErrorType(syms.objectType); 2567 } else { 2568 site = types.supertype(site); 2569 } 2570 } 2571 2572 if (site.hasTag(CLASS)) { 2573 Type encl = site.getEnclosingType(); 2574 while (encl != null && encl.hasTag(TYPEVAR)) 2575 encl = encl.getUpperBound(); 2576 if (encl.hasTag(CLASS)) { 2577 // we are calling a nested class 2578 2579 if (tree.meth.hasTag(SELECT)) { 2580 JCTree qualifier = ((JCFieldAccess) tree.meth).selected; 2581 2582 // We are seeing a prefixed call, of the form 2583 // <expr>.super(...). 2584 // Check that the prefix expression conforms 2585 // to the outer instance type of the class. 2586 chk.checkRefType(qualifier.pos(), 2587 attribExpr(qualifier, localEnv, 2588 encl)); 2589 } else if (methName == names._super) { 2590 // qualifier omitted; check for existence 2591 // of an appropriate implicit qualifier. 2592 rs.resolveImplicitThis(tree.meth.pos(), 2593 localEnv, site, true); 2594 } 2595 } else if (tree.meth.hasTag(SELECT)) { 2596 log.error(tree.meth.pos(), 2597 Errors.IllegalQualNotIcls(site.tsym)); 2598 attribExpr(((JCFieldAccess) tree.meth).selected, localEnv, site); 2599 } 2600 2601 // if we're calling a java.lang.Enum constructor, 2602 // prefix the implicit String and int parameters 2603 if (site.tsym == syms.enumSym) 2604 argtypes = argtypes.prepend(syms.intType).prepend(syms.stringType); 2605 2606 // Resolve the called constructor under the assumption 2607 // that we are referring to a superclass instance of the 2608 // current instance (JLS ???). 2609 boolean selectSuperPrev = localEnv.info.selectSuper; 2610 localEnv.info.selectSuper = true; 2611 localEnv.info.pendingResolutionPhase = null; 2612 Symbol sym = rs.resolveConstructor( 2613 tree.meth.pos(), localEnv, site, argtypes, typeargtypes); 2614 localEnv.info.selectSuper = selectSuperPrev; 2615 2616 // Set method symbol to resolved constructor... 2617 TreeInfo.setSymbol(tree.meth, sym); 2618 2619 // ...and check that it is legal in the current context. 2620 // (this will also set the tree's type) 2621 Type mpt = newMethodTemplate(resultInfo.pt, argtypes, typeargtypes); 2622 checkId(tree.meth, site, sym, localEnv, 2623 new ResultInfo(kind, mpt)); 2624 } else if (site.hasTag(ERROR) && tree.meth.hasTag(SELECT)) { 2625 attribExpr(((JCFieldAccess) tree.meth).selected, localEnv, site); 2626 } 2627 // Otherwise, `site' is an error type and we do nothing 2628 result = tree.type = syms.voidType; 2629 } else { 2630 // Otherwise, we are seeing a regular method call. 2631 // Attribute the arguments, yielding list of argument types, ... 2632 KindSelector kind = attribArgs(KindSelector.VAL, tree.args, localEnv, argtypesBuf); 2633 argtypes = argtypesBuf.toList(); 2634 typeargtypes = attribAnyTypes(tree.typeargs, localEnv); 2635 2636 // ... and attribute the method using as a prototype a methodtype 2637 // whose formal argument types is exactly the list of actual 2638 // arguments (this will also set the method symbol). 2639 Type mpt = newMethodTemplate(resultInfo.pt, argtypes, typeargtypes); 2640 localEnv.info.pendingResolutionPhase = null; 2641 Type mtype = attribTree(tree.meth, localEnv, new ResultInfo(kind, mpt, resultInfo.checkContext)); 2642 2643 // Compute the result type. 2644 Type restype = mtype.getReturnType(); 2645 if (restype.hasTag(WILDCARD)) 2646 throw new AssertionError(mtype); 2647 2648 Type qualifier = (tree.meth.hasTag(SELECT)) 2649 ? ((JCFieldAccess) tree.meth).selected.type 2650 : env.enclClass.sym.type; 2651 Symbol msym = TreeInfo.symbol(tree.meth); 2652 restype = adjustMethodReturnType(msym, qualifier, methName, argtypes, restype); 2653 2654 chk.checkRefTypes(tree.typeargs, typeargtypes); 2655 2656 // Check that value of resulting type is admissible in the 2657 // current context. Also, capture the return type 2658 Type capturedRes = resultInfo.checkContext.inferenceContext().cachedCapture(tree, restype, true); 2659 result = check(tree, capturedRes, KindSelector.VAL, resultInfo); 2660 } 2661 chk.validate(tree.typeargs, localEnv); 2662 } 2663 //where 2664 Type adjustMethodReturnType(Symbol msym, Type qualifierType, Name methodName, List<Type> argtypes, Type restype) { 2665 if (msym != null && 2666 (msym.owner == syms.objectType.tsym || msym.owner.isInterface()) && 2667 methodName == names.getClass && 2668 argtypes.isEmpty()) { 2669 // as a special case, x.getClass() has type Class<? extends |X|> 2670 return new ClassType(restype.getEnclosingType(), 2671 List.of(new WildcardType(types.erasure(qualifierType.baseType()), 2672 BoundKind.EXTENDS, 2673 syms.boundClass)), 2674 restype.tsym, 2675 restype.getMetadata()); 2676 } else if (msym != null && 2677 msym.owner == syms.arrayClass && 2678 methodName == names.clone && 2679 types.isArray(qualifierType)) { 2680 // as a special case, array.clone() has a result that is 2681 // the same as static type of the array being cloned 2682 return qualifierType; 2683 } else { 2684 return restype; 2685 } 2686 } 2687 2688 /** Obtain a method type with given argument types. 2689 */ 2690 Type newMethodTemplate(Type restype, List<Type> argtypes, List<Type> typeargtypes) { 2691 MethodType mt = new MethodType(argtypes, restype, List.nil(), syms.methodClass); 2692 return (typeargtypes == null) ? mt : (Type)new ForAll(typeargtypes, mt); 2693 } 2694 2695 public void visitNewClass(final JCNewClass tree) { 2696 Type owntype = types.createErrorType(tree.type); 2697 2698 // The local environment of a class creation is 2699 // a new environment nested in the current one. 2700 Env<AttrContext> localEnv = env.dup(tree, env.info.dup()); 2701 2702 // The anonymous inner class definition of the new expression, 2703 // if one is defined by it. 2704 JCClassDecl cdef = tree.def; 2705 2706 // If enclosing class is given, attribute it, and 2707 // complete class name to be fully qualified 2708 JCExpression clazz = tree.clazz; // Class field following new 2709 JCExpression clazzid; // Identifier in class field 2710 JCAnnotatedType annoclazzid; // Annotated type enclosing clazzid 2711 annoclazzid = null; 2712 2713 if (clazz.hasTag(TYPEAPPLY)) { 2714 clazzid = ((JCTypeApply) clazz).clazz; 2715 if (clazzid.hasTag(ANNOTATED_TYPE)) { 2716 annoclazzid = (JCAnnotatedType) clazzid; 2717 clazzid = annoclazzid.underlyingType; 2718 } 2719 } else { 2720 if (clazz.hasTag(ANNOTATED_TYPE)) { 2721 annoclazzid = (JCAnnotatedType) clazz; 2722 clazzid = annoclazzid.underlyingType; 2723 } else { 2724 clazzid = clazz; 2725 } 2726 } 2727 2728 JCExpression clazzid1 = clazzid; // The same in fully qualified form 2729 2730 if (tree.encl != null) { 2731 // We are seeing a qualified new, of the form 2732 // <expr>.new C <...> (...) ... 2733 // In this case, we let clazz stand for the name of the 2734 // allocated class C prefixed with the type of the qualifier 2735 // expression, so that we can 2736 // resolve it with standard techniques later. I.e., if 2737 // <expr> has type T, then <expr>.new C <...> (...) 2738 // yields a clazz T.C. 2739 Type encltype = chk.checkRefType(tree.encl.pos(), 2740 attribExpr(tree.encl, env)); 2741 // TODO 308: in <expr>.new C, do we also want to add the type annotations 2742 // from expr to the combined type, or not? Yes, do this. 2743 clazzid1 = make.at(clazz.pos).Select(make.Type(encltype), 2744 ((JCIdent) clazzid).name); 2745 2746 EndPosTable endPosTable = this.env.toplevel.endPositions; 2747 endPosTable.storeEnd(clazzid1, clazzid.getEndPosition(endPosTable)); 2748 if (clazz.hasTag(ANNOTATED_TYPE)) { 2749 JCAnnotatedType annoType = (JCAnnotatedType) clazz; 2750 List<JCAnnotation> annos = annoType.annotations; 2751 2752 if (annoType.underlyingType.hasTag(TYPEAPPLY)) { 2753 clazzid1 = make.at(tree.pos). 2754 TypeApply(clazzid1, 2755 ((JCTypeApply) clazz).arguments); 2756 } 2757 2758 clazzid1 = make.at(tree.pos). 2759 AnnotatedType(annos, clazzid1); 2760 } else if (clazz.hasTag(TYPEAPPLY)) { 2761 clazzid1 = make.at(tree.pos). 2762 TypeApply(clazzid1, 2763 ((JCTypeApply) clazz).arguments); 2764 } 2765 2766 clazz = clazzid1; 2767 } 2768 2769 // Attribute clazz expression and store 2770 // symbol + type back into the attributed tree. 2771 Type clazztype; 2772 2773 try { 2774 env.info.isNewClass = true; 2775 clazztype = TreeInfo.isEnumInit(env.tree) ? 2776 attribIdentAsEnumType(env, (JCIdent)clazz) : 2777 attribType(clazz, env); 2778 } finally { 2779 env.info.isNewClass = false; 2780 } 2781 2782 clazztype = chk.checkDiamond(tree, clazztype); 2783 chk.validate(clazz, localEnv); 2784 if (tree.encl != null) { 2785 // We have to work in this case to store 2786 // symbol + type back into the attributed tree. 2787 tree.clazz.type = clazztype; 2788 TreeInfo.setSymbol(clazzid, TreeInfo.symbol(clazzid1)); 2789 clazzid.type = ((JCIdent) clazzid).sym.type; 2790 if (annoclazzid != null) { 2791 annoclazzid.type = clazzid.type; 2792 } 2793 if (!clazztype.isErroneous()) { 2794 if (cdef != null && clazztype.tsym.isInterface()) { 2795 log.error(tree.encl.pos(), Errors.AnonClassImplIntfNoQualForNew); 2796 } else if (clazztype.tsym.isStatic()) { 2797 log.error(tree.encl.pos(), Errors.QualifiedNewOfStaticClass(clazztype.tsym)); 2798 } 2799 } 2800 } else if (!clazztype.tsym.isInterface() && 2801 clazztype.getEnclosingType().hasTag(CLASS)) { 2802 // Check for the existence of an apropos outer instance 2803 rs.resolveImplicitThis(tree.pos(), env, clazztype); 2804 } 2805 2806 // Attribute constructor arguments. 2807 ListBuffer<Type> argtypesBuf = new ListBuffer<>(); 2808 final KindSelector pkind = 2809 attribArgs(KindSelector.VAL, tree.args, localEnv, argtypesBuf); 2810 List<Type> argtypes = argtypesBuf.toList(); 2811 List<Type> typeargtypes = attribTypes(tree.typeargs, localEnv); 2812 2813 if (clazztype.hasTag(CLASS) || clazztype.hasTag(ERROR)) { 2814 // Enums may not be instantiated except implicitly 2815 if ((clazztype.tsym.flags_field & Flags.ENUM) != 0 && 2816 (!env.tree.hasTag(VARDEF) || 2817 (((JCVariableDecl) env.tree).mods.flags & Flags.ENUM) == 0 || 2818 ((JCVariableDecl) env.tree).init != tree)) 2819 log.error(tree.pos(), Errors.EnumCantBeInstantiated); 2820 2821 boolean isSpeculativeDiamondInferenceRound = TreeInfo.isDiamond(tree) && 2822 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE; 2823 boolean skipNonDiamondPath = false; 2824 // Check that class is not abstract 2825 if (cdef == null && !isSpeculativeDiamondInferenceRound && // class body may be nulled out in speculative tree copy 2826 (clazztype.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) { 2827 log.error(tree.pos(), 2828 Errors.AbstractCantBeInstantiated(clazztype.tsym)); 2829 skipNonDiamondPath = true; 2830 } else if (cdef != null && clazztype.tsym.isInterface()) { 2831 // Check that no constructor arguments are given to 2832 // anonymous classes implementing an interface 2833 if (!argtypes.isEmpty()) 2834 log.error(tree.args.head.pos(), Errors.AnonClassImplIntfNoArgs); 2835 2836 if (!typeargtypes.isEmpty()) 2837 log.error(tree.typeargs.head.pos(), Errors.AnonClassImplIntfNoTypeargs); 2838 2839 // Error recovery: pretend no arguments were supplied. 2840 argtypes = List.nil(); 2841 typeargtypes = List.nil(); 2842 skipNonDiamondPath = true; 2843 } 2844 if (TreeInfo.isDiamond(tree)) { 2845 ClassType site = new ClassType(clazztype.getEnclosingType(), 2846 clazztype.tsym.type.getTypeArguments(), 2847 clazztype.tsym, 2848 clazztype.getMetadata()); 2849 2850 Env<AttrContext> diamondEnv = localEnv.dup(tree); 2851 diamondEnv.info.selectSuper = cdef != null || tree.classDeclRemoved(); 2852 diamondEnv.info.pendingResolutionPhase = null; 2853 2854 //if the type of the instance creation expression is a class type 2855 //apply method resolution inference (JLS 15.12.2.7). The return type 2856 //of the resolved constructor will be a partially instantiated type 2857 Symbol constructor = rs.resolveDiamond(tree.pos(), 2858 diamondEnv, 2859 site, 2860 argtypes, 2861 typeargtypes); 2862 tree.constructor = constructor.baseSymbol(); 2863 2864 final TypeSymbol csym = clazztype.tsym; 2865 ResultInfo diamondResult = new ResultInfo(pkind, newMethodTemplate(resultInfo.pt, argtypes, typeargtypes), 2866 diamondContext(tree, csym, resultInfo.checkContext), CheckMode.NO_TREE_UPDATE); 2867 Type constructorType = tree.constructorType = types.createErrorType(clazztype); 2868 constructorType = checkId(tree, site, 2869 constructor, 2870 diamondEnv, 2871 diamondResult); 2872 2873 tree.clazz.type = types.createErrorType(clazztype); 2874 if (!constructorType.isErroneous()) { 2875 tree.clazz.type = clazz.type = constructorType.getReturnType(); 2876 tree.constructorType = types.createMethodTypeWithReturn(constructorType, syms.voidType); 2877 } 2878 clazztype = chk.checkClassType(tree.clazz, tree.clazz.type, true); 2879 } 2880 2881 // Resolve the called constructor under the assumption 2882 // that we are referring to a superclass instance of the 2883 // current instance (JLS ???). 2884 else if (!skipNonDiamondPath) { 2885 //the following code alters some of the fields in the current 2886 //AttrContext - hence, the current context must be dup'ed in 2887 //order to avoid downstream failures 2888 Env<AttrContext> rsEnv = localEnv.dup(tree); 2889 rsEnv.info.selectSuper = cdef != null; 2890 rsEnv.info.pendingResolutionPhase = null; 2891 tree.constructor = rs.resolveConstructor( 2892 tree.pos(), rsEnv, clazztype, argtypes, typeargtypes); 2893 if (cdef == null) { //do not check twice! 2894 tree.constructorType = checkId(tree, 2895 clazztype, 2896 tree.constructor, 2897 rsEnv, 2898 new ResultInfo(pkind, newMethodTemplate(syms.voidType, argtypes, typeargtypes), CheckMode.NO_TREE_UPDATE)); 2899 if (rsEnv.info.lastResolveVarargs()) 2900 Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null); 2901 } 2902 } 2903 2904 if (cdef != null) { 2905 visitAnonymousClassDefinition(tree, clazz, clazztype, cdef, localEnv, argtypes, typeargtypes, pkind); 2906 return; 2907 } 2908 2909 if (tree.constructor != null && tree.constructor.kind == MTH) 2910 owntype = clazztype; 2911 } 2912 result = check(tree, owntype, KindSelector.VAL, resultInfo); 2913 InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext(); 2914 if (tree.constructorType != null && inferenceContext.free(tree.constructorType)) { 2915 //we need to wait for inference to finish and then replace inference vars in the constructor type 2916 inferenceContext.addFreeTypeListener(List.of(tree.constructorType), 2917 instantiatedContext -> { 2918 tree.constructorType = instantiatedContext.asInstType(tree.constructorType); 2919 }); 2920 } 2921 chk.validate(tree.typeargs, localEnv); 2922 } 2923 2924 // where 2925 private void visitAnonymousClassDefinition(JCNewClass tree, JCExpression clazz, Type clazztype, 2926 JCClassDecl cdef, Env<AttrContext> localEnv, 2927 List<Type> argtypes, List<Type> typeargtypes, 2928 KindSelector pkind) { 2929 // We are seeing an anonymous class instance creation. 2930 // In this case, the class instance creation 2931 // expression 2932 // 2933 // E.new <typeargs1>C<typargs2>(args) { ... } 2934 // 2935 // is represented internally as 2936 // 2937 // E . new <typeargs1>C<typargs2>(args) ( class <empty-name> { ... } ) . 2938 // 2939 // This expression is then *transformed* as follows: 2940 // 2941 // (1) add an extends or implements clause 2942 // (2) add a constructor. 2943 // 2944 // For instance, if C is a class, and ET is the type of E, 2945 // the expression 2946 // 2947 // E.new <typeargs1>C<typargs2>(args) { ... } 2948 // 2949 // is translated to (where X is a fresh name and typarams is the 2950 // parameter list of the super constructor): 2951 // 2952 // new <typeargs1>X(<*nullchk*>E, args) where 2953 // X extends C<typargs2> { 2954 // <typarams> X(ET e, args) { 2955 // e.<typeargs1>super(args) 2956 // } 2957 // ... 2958 // } 2959 InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext(); 2960 Type enclType = clazztype.getEnclosingType(); 2961 if (enclType != null && 2962 enclType.hasTag(CLASS) && 2963 !chk.checkDenotable((ClassType)enclType)) { 2964 log.error(tree.encl, Errors.EnclosingClassTypeNonDenotable(enclType)); 2965 } 2966 final boolean isDiamond = TreeInfo.isDiamond(tree); 2967 if (isDiamond 2968 && ((tree.constructorType != null && inferenceContext.free(tree.constructorType)) 2969 || (tree.clazz.type != null && inferenceContext.free(tree.clazz.type)))) { 2970 final ResultInfo resultInfoForClassDefinition = this.resultInfo; 2971 Env<AttrContext> dupLocalEnv = copyEnv(localEnv); 2972 inferenceContext.addFreeTypeListener(List.of(tree.constructorType, tree.clazz.type), 2973 instantiatedContext -> { 2974 tree.constructorType = instantiatedContext.asInstType(tree.constructorType); 2975 tree.clazz.type = clazz.type = instantiatedContext.asInstType(clazz.type); 2976 ResultInfo prevResult = this.resultInfo; 2977 try { 2978 this.resultInfo = resultInfoForClassDefinition; 2979 visitAnonymousClassDefinition(tree, clazz, clazz.type, cdef, 2980 dupLocalEnv, argtypes, typeargtypes, pkind); 2981 } finally { 2982 this.resultInfo = prevResult; 2983 } 2984 }); 2985 } else { 2986 if (isDiamond && clazztype.hasTag(CLASS)) { 2987 List<Type> invalidDiamondArgs = chk.checkDiamondDenotable((ClassType)clazztype); 2988 if (!clazztype.isErroneous() && invalidDiamondArgs.nonEmpty()) { 2989 // One or more types inferred in the previous steps is non-denotable. 2990 Fragment fragment = Diamond(clazztype.tsym); 2991 log.error(tree.clazz.pos(), 2992 Errors.CantApplyDiamond1( 2993 fragment, 2994 invalidDiamondArgs.size() > 1 ? 2995 DiamondInvalidArgs(invalidDiamondArgs, fragment) : 2996 DiamondInvalidArg(invalidDiamondArgs, fragment))); 2997 } 2998 // For <>(){}, inferred types must also be accessible. 2999 for (Type t : clazztype.getTypeArguments()) { 3000 rs.checkAccessibleType(env, t); 3001 } 3002 } 3003 3004 // If we already errored, be careful to avoid a further avalanche. ErrorType answers 3005 // false for isInterface call even when the original type is an interface. 3006 boolean implementing = clazztype.tsym.isInterface() || 3007 clazztype.isErroneous() && !clazztype.getOriginalType().hasTag(NONE) && 3008 clazztype.getOriginalType().tsym.isInterface(); 3009 3010 if (implementing) { 3011 cdef.implementing = List.of(clazz); 3012 } else { 3013 cdef.extending = clazz; 3014 } 3015 3016 if (resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK && 3017 rs.isSerializable(clazztype)) { 3018 localEnv.info.isSerializable = true; 3019 } 3020 3021 attribStat(cdef, localEnv); 3022 3023 List<Type> finalargtypes; 3024 // If an outer instance is given, 3025 // prefix it to the constructor arguments 3026 // and delete it from the new expression 3027 if (tree.encl != null && !clazztype.tsym.isInterface()) { 3028 finalargtypes = argtypes.prepend(tree.encl.type); 3029 } else { 3030 finalargtypes = argtypes; 3031 } 3032 3033 // Reassign clazztype and recompute constructor. As this necessarily involves 3034 // another attribution pass for deferred types in the case of <>, replicate 3035 // them. Original arguments have right decorations already. 3036 if (isDiamond && pkind.contains(KindSelector.POLY)) { 3037 finalargtypes = finalargtypes.map(deferredAttr.deferredCopier); 3038 } 3039 3040 clazztype = clazztype.hasTag(ERROR) ? types.createErrorType(cdef.sym.type) 3041 : cdef.sym.type; 3042 Symbol sym = tree.constructor = rs.resolveConstructor( 3043 tree.pos(), localEnv, clazztype, finalargtypes, typeargtypes); 3044 Assert.check(!sym.kind.isResolutionError()); 3045 tree.constructor = sym; 3046 tree.constructorType = checkId(tree, 3047 clazztype, 3048 tree.constructor, 3049 localEnv, 3050 new ResultInfo(pkind, newMethodTemplate(syms.voidType, finalargtypes, typeargtypes), CheckMode.NO_TREE_UPDATE)); 3051 } 3052 Type owntype = (tree.constructor != null && tree.constructor.kind == MTH) ? 3053 clazztype : types.createErrorType(tree.type); 3054 result = check(tree, owntype, KindSelector.VAL, resultInfo.dup(CheckMode.NO_INFERENCE_HOOK)); 3055 chk.validate(tree.typeargs, localEnv); 3056 } 3057 3058 CheckContext diamondContext(JCNewClass clazz, TypeSymbol tsym, CheckContext checkContext) { 3059 return new Check.NestedCheckContext(checkContext) { 3060 @Override 3061 public void report(DiagnosticPosition _unused, JCDiagnostic details) { 3062 enclosingContext.report(clazz.clazz, 3063 diags.fragment(Fragments.CantApplyDiamond1(Fragments.Diamond(tsym), details))); 3064 } 3065 }; 3066 } 3067 3068 /** Make an attributed null check tree. 3069 */ 3070 public JCExpression makeNullCheck(JCExpression arg) { 3071 // optimization: new Outer() can never be null; skip null check 3072 if (arg.getTag() == NEWCLASS) 3073 return arg; 3074 // optimization: X.this is never null; skip null check 3075 Name name = TreeInfo.name(arg); 3076 if (name == names._this || name == names._super) return arg; 3077 3078 JCTree.Tag optag = NULLCHK; 3079 JCUnary tree = make.at(arg.pos).Unary(optag, arg); 3080 tree.operator = operators.resolveUnary(arg, optag, arg.type); 3081 tree.type = arg.type; 3082 return tree; 3083 } 3084 3085 public void visitNewArray(JCNewArray tree) { 3086 Type owntype = types.createErrorType(tree.type); 3087 Env<AttrContext> localEnv = env.dup(tree); 3088 Type elemtype; 3089 if (tree.elemtype != null) { 3090 elemtype = attribType(tree.elemtype, localEnv); 3091 chk.validate(tree.elemtype, localEnv); 3092 owntype = elemtype; 3093 for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) { 3094 attribExpr(l.head, localEnv, syms.intType); 3095 owntype = new ArrayType(owntype, syms.arrayClass); 3096 } 3097 } else { 3098 // we are seeing an untyped aggregate { ... } 3099 // this is allowed only if the prototype is an array 3100 if (pt().hasTag(ARRAY)) { 3101 elemtype = types.elemtype(pt()); 3102 } else { 3103 if (!pt().hasTag(ERROR) && 3104 (env.info.enclVar == null || !env.info.enclVar.type.isErroneous())) { 3105 log.error(tree.pos(), 3106 Errors.IllegalInitializerForType(pt())); 3107 } 3108 elemtype = types.createErrorType(pt()); 3109 } 3110 } 3111 if (tree.elems != null) { 3112 attribExprs(tree.elems, localEnv, elemtype); 3113 owntype = new ArrayType(elemtype, syms.arrayClass); 3114 } 3115 if (!types.isReifiable(elemtype)) 3116 log.error(tree.pos(), Errors.GenericArrayCreation); 3117 result = check(tree, owntype, KindSelector.VAL, resultInfo); 3118 } 3119 3120 /* 3121 * A lambda expression can only be attributed when a target-type is available. 3122 * In addition, if the target-type is that of a functional interface whose 3123 * descriptor contains inference variables in argument position the lambda expression 3124 * is 'stuck' (see DeferredAttr). 3125 */ 3126 @Override 3127 public void visitLambda(final JCLambda that) { 3128 boolean wrongContext = false; 3129 if (pt().isErroneous() || (pt().hasTag(NONE) && pt() != Type.recoveryType)) { 3130 if (pt().hasTag(NONE) && (env.info.enclVar == null || !env.info.enclVar.type.isErroneous())) { 3131 //lambda only allowed in assignment or method invocation/cast context 3132 log.error(that.pos(), Errors.UnexpectedLambda); 3133 } 3134 resultInfo = recoveryInfo; 3135 wrongContext = true; 3136 } 3137 if (types.isQuoted(pt())) { 3138 attribQuotedLambda(that); 3139 } else { 3140 attribFunctionalLambda(that, wrongContext); 3141 } 3142 } 3143 3144 void attribFunctionalLambda(JCLambda that, boolean wrongContext) { 3145 //create an environment for attribution of the lambda expression 3146 final Env<AttrContext> localEnv = lambdaEnv(that, env); 3147 boolean needsRecovery = 3148 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK; 3149 try { 3150 if (needsRecovery && rs.isSerializable(pt())) { 3151 localEnv.info.isSerializable = true; 3152 localEnv.info.isSerializableLambda = true; 3153 } 3154 List<Type> explicitParamTypes = null; 3155 if (that.paramKind == JCLambda.ParameterKind.EXPLICIT) { 3156 //attribute lambda parameters 3157 attribStats(that.params, localEnv); 3158 explicitParamTypes = TreeInfo.types(that.params); 3159 } 3160 3161 TargetInfo targetInfo = getTargetInfo(that, resultInfo, explicitParamTypes); 3162 Type currentTarget = targetInfo.target; 3163 Type lambdaType = targetInfo.descriptor; 3164 3165 if (currentTarget.isErroneous()) { 3166 result = that.type = currentTarget; 3167 return; 3168 } 3169 3170 setFunctionalInfo(localEnv, that, pt(), lambdaType, currentTarget, resultInfo.checkContext); 3171 3172 if (lambdaType.hasTag(FORALL)) { 3173 //lambda expression target desc cannot be a generic method 3174 Fragment msg = Fragments.InvalidGenericLambdaTarget(lambdaType, 3175 kindName(currentTarget.tsym), 3176 currentTarget.tsym); 3177 resultInfo.checkContext.report(that, diags.fragment(msg)); 3178 result = that.type = types.createErrorType(pt()); 3179 return; 3180 } 3181 3182 if (that.paramKind == JCLambda.ParameterKind.IMPLICIT) { 3183 //add param type info in the AST 3184 List<Type> actuals = lambdaType.getParameterTypes(); 3185 List<JCVariableDecl> params = that.params; 3186 3187 boolean arityMismatch = false; 3188 3189 while (params.nonEmpty()) { 3190 if (actuals.isEmpty()) { 3191 //not enough actuals to perform lambda parameter inference 3192 arityMismatch = true; 3193 } 3194 //reset previously set info 3195 Type argType = arityMismatch ? 3196 syms.errType : 3197 actuals.head; 3198 if (params.head.isImplicitlyTyped()) { 3199 setSyntheticVariableType(params.head, argType); 3200 } 3201 params.head.sym = null; 3202 actuals = actuals.isEmpty() ? 3203 actuals : 3204 actuals.tail; 3205 params = params.tail; 3206 } 3207 3208 //attribute lambda parameters 3209 attribStats(that.params, localEnv); 3210 3211 if (arityMismatch) { 3212 resultInfo.checkContext.report(that, diags.fragment(Fragments.IncompatibleArgTypesInLambda)); 3213 result = that.type = types.createErrorType(currentTarget); 3214 return; 3215 } 3216 } 3217 3218 //from this point on, no recovery is needed; if we are in assignment context 3219 //we will be able to attribute the whole lambda body, regardless of errors; 3220 //if we are in a 'check' method context, and the lambda is not compatible 3221 //with the target-type, it will be recovered anyway in Attr.checkId 3222 needsRecovery = false; 3223 3224 ResultInfo bodyResultInfo = localEnv.info.returnResult = 3225 lambdaBodyResult(that, lambdaType, resultInfo); 3226 3227 if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) { 3228 attribTree(that.getBody(), localEnv, bodyResultInfo); 3229 } else { 3230 JCBlock body = (JCBlock)that.body; 3231 if (body == breakTree && 3232 resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) { 3233 breakTreeFound(copyEnv(localEnv)); 3234 } 3235 attribStats(body.stats, localEnv); 3236 } 3237 3238 result = check(that, currentTarget, KindSelector.VAL, resultInfo); 3239 3240 boolean isSpeculativeRound = 3241 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE; 3242 3243 preFlow(that); 3244 flow.analyzeLambda(env, that, make, isSpeculativeRound); 3245 3246 that.type = currentTarget; //avoids recovery at this stage 3247 checkLambdaCompatible(that, lambdaType, resultInfo.checkContext); 3248 3249 if (!isSpeculativeRound) { 3250 //add thrown types as bounds to the thrown types free variables if needed: 3251 if (resultInfo.checkContext.inferenceContext().free(lambdaType.getThrownTypes())) { 3252 List<Type> inferredThrownTypes = flow.analyzeLambdaThrownTypes(env, that, make); 3253 if(!checkExConstraints(inferredThrownTypes, lambdaType.getThrownTypes(), resultInfo.checkContext.inferenceContext())) { 3254 log.error(that, Errors.IncompatibleThrownTypesInMref(lambdaType.getThrownTypes())); 3255 } 3256 } 3257 3258 checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), lambdaType, currentTarget); 3259 } 3260 result = wrongContext ? that.type = types.createErrorType(pt()) 3261 : check(that, currentTarget, KindSelector.VAL, resultInfo); 3262 } catch (Types.FunctionDescriptorLookupError ex) { 3263 JCDiagnostic cause = ex.getDiagnostic(); 3264 resultInfo.checkContext.report(that, cause); 3265 result = that.type = types.createErrorType(pt()); 3266 return; 3267 } catch (CompletionFailure cf) { 3268 chk.completionError(that.pos(), cf); 3269 } catch (Throwable t) { 3270 //when an unexpected exception happens, avoid attempts to attribute the same tree again 3271 //as that would likely cause the same exception again. 3272 needsRecovery = false; 3273 throw t; 3274 } finally { 3275 localEnv.info.scope.leave(); 3276 if (needsRecovery) { 3277 Type prevResult = result; 3278 try { 3279 attribTree(that, env, recoveryInfo); 3280 } finally { 3281 if (result == Type.recoveryType) { 3282 result = prevResult; 3283 } 3284 } 3285 } 3286 } 3287 } 3288 3289 void attribQuotedLambda(JCLambda that) { 3290 // create an environment for attribution of the lambda expression 3291 final Env<AttrContext> localEnv = lambdaEnv(that, env); 3292 try { 3293 // if quoted lambda is implicit, issue error, and recover 3294 if (that.paramKind == ParameterKind.IMPLICIT) { 3295 log.error(that, Errors.QuotedLambdaMustBeExplicit); 3296 // recovery 3297 List<JCVariableDecl> params = that.params; 3298 while (params.nonEmpty()) { 3299 Type argType = syms.errType; 3300 if (params.head.isImplicitlyTyped()) { 3301 setSyntheticVariableType(params.head, argType); 3302 } 3303 params = params.tail; 3304 } 3305 } 3306 // attribute lambda parameters 3307 attribStats(that.params, localEnv); 3308 List<Type> explicitParamTypes = TreeInfo.types(that.params); 3309 3310 ListBuffer<Type> restypes = new ListBuffer<>(); 3311 ListBuffer<DiagnosticPosition> resPositions = new ListBuffer<>(); 3312 ResultInfo bodyResultInfo = localEnv.info.returnResult = unknownExprInfo; 3313 3314 // type-check lambda body, and capture return types 3315 if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) { 3316 attribTree(that.getBody(), localEnv, bodyResultInfo); 3317 restypes.add(that.getBody().type); 3318 } else { 3319 JCBlock body = (JCBlock)that.body; 3320 if (body == breakTree && 3321 resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) { 3322 breakTreeFound(copyEnv(localEnv)); 3323 } 3324 attribStats(body.stats, localEnv); 3325 new LambdaReturnScanner() { 3326 @Override 3327 public void visitReturn(JCReturn tree) { 3328 if (tree.expr != null) { 3329 resPositions.add(tree); 3330 } 3331 restypes.add(tree.expr == null ? syms.voidType : tree.expr.type); 3332 } 3333 }.scan(body); 3334 } 3335 3336 // check if lambda body can complete normally 3337 preFlow(that); 3338 flow.analyzeLambda(localEnv, that, make, false); 3339 3340 final Type restype; 3341 if (that.getBodyKind() == BodyKind.STATEMENT) { 3342 if (that.canCompleteNormally) { 3343 // a lambda that completes normally has an implicit void return 3344 restypes.add(syms.voidType); 3345 } 3346 3347 boolean hasNonVoidReturn = restypes.toList() 3348 .stream().anyMatch(t -> t != syms.voidType); 3349 boolean hasVoidReturn = restypes.toList() 3350 .stream().anyMatch(t -> t == syms.voidType); 3351 3352 if (hasVoidReturn && hasNonVoidReturn) { 3353 // void vs. non-void mismatch 3354 log.error(that.body, Errors.CantInferQuotedLambdaReturnType(restypes.toList())); 3355 restype = syms.errorType; 3356 } else if (hasVoidReturn) { 3357 restype = syms.voidType; 3358 } else { 3359 restype = condType(resPositions.toList(), restypes.toList()); 3360 } 3361 } else { 3362 restype = restypes.first(); 3363 } 3364 3365 // infer lambda return type using lub 3366 if (restype.hasTag(ERROR)) { 3367 // some other error occurred 3368 log.error(that.body, Errors.CantInferQuotedLambdaReturnType(restypes.toList())); 3369 } 3370 3371 // infer thrown types 3372 List<Type> thrownTypes = flow.analyzeLambdaThrownTypes(localEnv, that, make); 3373 3374 // set up target descriptor with explicit parameter types, and inferred thrown/return types 3375 that.target = new MethodType(explicitParamTypes, restype, thrownTypes, syms.methodClass); 3376 result = that.type = pt(); 3377 } finally { 3378 localEnv.info.scope.leave(); 3379 } 3380 } 3381 //where 3382 class TargetInfo { 3383 Type target; 3384 Type descriptor; 3385 3386 public TargetInfo(Type target, Type descriptor) { 3387 this.target = target; 3388 this.descriptor = descriptor; 3389 } 3390 } 3391 3392 TargetInfo getTargetInfo(JCPolyExpression that, ResultInfo resultInfo, List<Type> explicitParamTypes) { 3393 Type lambdaType; 3394 Type currentTarget = resultInfo.pt; 3395 if (resultInfo.pt != Type.recoveryType) { 3396 /* We need to adjust the target. If the target is an 3397 * intersection type, for example: SAM & I1 & I2 ... 3398 * the target will be updated to SAM 3399 */ 3400 currentTarget = targetChecker.visit(currentTarget, that); 3401 if (!currentTarget.isIntersection()) { 3402 if (explicitParamTypes != null) { 3403 currentTarget = infer.instantiateFunctionalInterface(that, 3404 currentTarget, explicitParamTypes, resultInfo.checkContext); 3405 } 3406 currentTarget = types.removeWildcards(currentTarget); 3407 lambdaType = types.findDescriptorType(currentTarget); 3408 } else { 3409 IntersectionClassType ict = (IntersectionClassType)currentTarget; 3410 ListBuffer<Type> components = new ListBuffer<>(); 3411 for (Type bound : ict.getExplicitComponents()) { 3412 if (explicitParamTypes != null) { 3413 try { 3414 bound = infer.instantiateFunctionalInterface(that, 3415 bound, explicitParamTypes, resultInfo.checkContext); 3416 } catch (FunctionDescriptorLookupError t) { 3417 // do nothing 3418 } 3419 } 3420 bound = types.removeWildcards(bound); 3421 components.add(bound); 3422 } 3423 currentTarget = types.makeIntersectionType(components.toList()); 3424 currentTarget.tsym.flags_field |= INTERFACE; 3425 lambdaType = types.findDescriptorType(currentTarget); 3426 } 3427 3428 } else { 3429 currentTarget = Type.recoveryType; 3430 lambdaType = fallbackDescriptorType(that); 3431 } 3432 if (that.hasTag(LAMBDA) && lambdaType.hasTag(FORALL)) { 3433 //lambda expression target desc cannot be a generic method 3434 Fragment msg = Fragments.InvalidGenericLambdaTarget(lambdaType, 3435 kindName(currentTarget.tsym), 3436 currentTarget.tsym); 3437 resultInfo.checkContext.report(that, diags.fragment(msg)); 3438 currentTarget = types.createErrorType(pt()); 3439 } 3440 return new TargetInfo(currentTarget, lambdaType); 3441 } 3442 3443 void preFlow(JCLambda tree) { 3444 attrRecover.doRecovery(); 3445 new PostAttrAnalyzer() { 3446 @Override 3447 public void scan(JCTree tree) { 3448 if (tree == null || 3449 (tree.type != null && 3450 tree.type == Type.stuckType)) { 3451 //don't touch stuck expressions! 3452 return; 3453 } 3454 super.scan(tree); 3455 } 3456 3457 @Override 3458 public void visitClassDef(JCClassDecl that) { 3459 // or class declaration trees! 3460 } 3461 3462 public void visitLambda(JCLambda that) { 3463 // or lambda expressions! 3464 } 3465 }.scan(tree.body); 3466 } 3467 3468 Types.MapVisitor<DiagnosticPosition> targetChecker = new Types.MapVisitor<DiagnosticPosition>() { 3469 3470 @Override 3471 public Type visitClassType(ClassType t, DiagnosticPosition pos) { 3472 return t.isIntersection() ? 3473 visitIntersectionClassType((IntersectionClassType)t, pos) : t; 3474 } 3475 3476 public Type visitIntersectionClassType(IntersectionClassType ict, DiagnosticPosition pos) { 3477 types.findDescriptorSymbol(makeNotionalInterface(ict, pos)); 3478 return ict; 3479 } 3480 3481 private TypeSymbol makeNotionalInterface(IntersectionClassType ict, DiagnosticPosition pos) { 3482 ListBuffer<Type> targs = new ListBuffer<>(); 3483 ListBuffer<Type> supertypes = new ListBuffer<>(); 3484 for (Type i : ict.interfaces_field) { 3485 if (i.isParameterized()) { 3486 targs.appendList(i.tsym.type.allparams()); 3487 } 3488 supertypes.append(i.tsym.type); 3489 } 3490 IntersectionClassType notionalIntf = types.makeIntersectionType(supertypes.toList()); 3491 notionalIntf.allparams_field = targs.toList(); 3492 notionalIntf.tsym.flags_field |= INTERFACE; 3493 return notionalIntf.tsym; 3494 } 3495 }; 3496 3497 private Type fallbackDescriptorType(JCExpression tree) { 3498 switch (tree.getTag()) { 3499 case LAMBDA: 3500 JCLambda lambda = (JCLambda)tree; 3501 List<Type> argtypes = List.nil(); 3502 for (JCVariableDecl param : lambda.params) { 3503 argtypes = param.vartype != null && param.vartype.type != null ? 3504 argtypes.append(param.vartype.type) : 3505 argtypes.append(syms.errType); 3506 } 3507 return new MethodType(argtypes, Type.recoveryType, 3508 List.of(syms.throwableType), syms.methodClass); 3509 case REFERENCE: 3510 return new MethodType(List.nil(), Type.recoveryType, 3511 List.of(syms.throwableType), syms.methodClass); 3512 default: 3513 Assert.error("Cannot get here!"); 3514 } 3515 return null; 3516 } 3517 3518 private void checkAccessibleTypes(final DiagnosticPosition pos, final Env<AttrContext> env, 3519 final InferenceContext inferenceContext, final Type... ts) { 3520 checkAccessibleTypes(pos, env, inferenceContext, List.from(ts)); 3521 } 3522 3523 private void checkAccessibleTypes(final DiagnosticPosition pos, final Env<AttrContext> env, 3524 final InferenceContext inferenceContext, final List<Type> ts) { 3525 if (inferenceContext.free(ts)) { 3526 inferenceContext.addFreeTypeListener(ts, 3527 solvedContext -> checkAccessibleTypes(pos, env, solvedContext, solvedContext.asInstTypes(ts))); 3528 } else { 3529 for (Type t : ts) { 3530 rs.checkAccessibleType(env, t); 3531 } 3532 } 3533 } 3534 3535 /** 3536 * Lambda/method reference have a special check context that ensures 3537 * that i.e. a lambda return type is compatible with the expected 3538 * type according to both the inherited context and the assignment 3539 * context. 3540 */ 3541 class FunctionalReturnContext extends Check.NestedCheckContext { 3542 3543 FunctionalReturnContext(CheckContext enclosingContext) { 3544 super(enclosingContext); 3545 } 3546 3547 @Override 3548 public boolean compatible(Type found, Type req, Warner warn) { 3549 //return type must be compatible in both current context and assignment context 3550 return chk.basicHandler.compatible(inferenceContext().asUndetVar(found), inferenceContext().asUndetVar(req), warn); 3551 } 3552 3553 @Override 3554 public void report(DiagnosticPosition pos, JCDiagnostic details) { 3555 enclosingContext.report(pos, diags.fragment(Fragments.IncompatibleRetTypeInLambda(details))); 3556 } 3557 } 3558 3559 class ExpressionLambdaReturnContext extends FunctionalReturnContext { 3560 3561 JCExpression expr; 3562 boolean expStmtExpected; 3563 3564 ExpressionLambdaReturnContext(JCExpression expr, CheckContext enclosingContext) { 3565 super(enclosingContext); 3566 this.expr = expr; 3567 } 3568 3569 @Override 3570 public void report(DiagnosticPosition pos, JCDiagnostic details) { 3571 if (expStmtExpected) { 3572 enclosingContext.report(pos, diags.fragment(Fragments.StatExprExpected)); 3573 } else { 3574 super.report(pos, details); 3575 } 3576 } 3577 3578 @Override 3579 public boolean compatible(Type found, Type req, Warner warn) { 3580 //a void return is compatible with an expression statement lambda 3581 if (req.hasTag(VOID)) { 3582 expStmtExpected = true; 3583 return TreeInfo.isExpressionStatement(expr); 3584 } else { 3585 return super.compatible(found, req, warn); 3586 } 3587 } 3588 } 3589 3590 ResultInfo lambdaBodyResult(JCLambda that, Type descriptor, ResultInfo resultInfo) { 3591 FunctionalReturnContext funcContext = that.getBodyKind() == JCLambda.BodyKind.EXPRESSION ? 3592 new ExpressionLambdaReturnContext((JCExpression)that.getBody(), resultInfo.checkContext) : 3593 new FunctionalReturnContext(resultInfo.checkContext); 3594 3595 return descriptor.getReturnType() == Type.recoveryType ? 3596 recoveryInfo : 3597 new ResultInfo(KindSelector.VAL, 3598 descriptor.getReturnType(), funcContext); 3599 } 3600 3601 /** 3602 * Lambda compatibility. Check that given return types, thrown types, parameter types 3603 * are compatible with the expected functional interface descriptor. This means that: 3604 * (i) parameter types must be identical to those of the target descriptor; (ii) return 3605 * types must be compatible with the return type of the expected descriptor. 3606 */ 3607 void checkLambdaCompatible(JCLambda tree, Type descriptor, CheckContext checkContext) { 3608 Type returnType = checkContext.inferenceContext().asUndetVar(descriptor.getReturnType()); 3609 3610 //return values have already been checked - but if lambda has no return 3611 //values, we must ensure that void/value compatibility is correct; 3612 //this amounts at checking that, if a lambda body can complete normally, 3613 //the descriptor's return type must be void 3614 if (tree.getBodyKind() == JCLambda.BodyKind.STATEMENT && tree.canCompleteNormally && 3615 !returnType.hasTag(VOID) && returnType != Type.recoveryType) { 3616 Fragment msg = 3617 Fragments.IncompatibleRetTypeInLambda(Fragments.MissingRetVal(returnType)); 3618 checkContext.report(tree, 3619 diags.fragment(msg)); 3620 } 3621 3622 List<Type> argTypes = checkContext.inferenceContext().asUndetVars(descriptor.getParameterTypes()); 3623 if (!types.isSameTypes(argTypes, TreeInfo.types(tree.params))) { 3624 checkContext.report(tree, diags.fragment(Fragments.IncompatibleArgTypesInLambda)); 3625 } 3626 } 3627 3628 /* Map to hold 'fake' clinit methods. If a lambda is used to initialize a 3629 * static field and that lambda has type annotations, these annotations will 3630 * also be stored at these fake clinit methods. 3631 * 3632 * LambdaToMethod also use fake clinit methods so they can be reused. 3633 * Also as LTM is a phase subsequent to attribution, the methods from 3634 * clinits can be safely removed by LTM to save memory. 3635 */ 3636 private Map<ClassSymbol, MethodSymbol> clinits = new HashMap<>(); 3637 3638 public MethodSymbol removeClinit(ClassSymbol sym) { 3639 return clinits.remove(sym); 3640 } 3641 3642 /* This method returns an environment to be used to attribute a lambda 3643 * expression. 3644 * 3645 * The owner of this environment is a method symbol. If the current owner 3646 * is not a method, for example if the lambda is used to initialize 3647 * a field, then if the field is: 3648 * 3649 * - an instance field, we use the first constructor. 3650 * - a static field, we create a fake clinit method. 3651 */ 3652 public Env<AttrContext> lambdaEnv(JCLambda that, Env<AttrContext> env) { 3653 Env<AttrContext> lambdaEnv; 3654 Symbol owner = env.info.scope.owner; 3655 if (owner.kind == VAR && owner.owner.kind == TYP) { 3656 //field initializer 3657 ClassSymbol enclClass = owner.enclClass(); 3658 Symbol newScopeOwner = env.info.scope.owner; 3659 /* if the field isn't static, then we can get the first constructor 3660 * and use it as the owner of the environment. This is what 3661 * LTM code is doing to look for type annotations so we are fine. 3662 */ 3663 if ((owner.flags() & STATIC) == 0) { 3664 for (Symbol s : enclClass.members_field.getSymbolsByName(names.init)) { 3665 newScopeOwner = s; 3666 break; 3667 } 3668 } else { 3669 /* if the field is static then we need to create a fake clinit 3670 * method, this method can later be reused by LTM. 3671 */ 3672 MethodSymbol clinit = clinits.get(enclClass); 3673 if (clinit == null) { 3674 Type clinitType = new MethodType(List.nil(), 3675 syms.voidType, List.nil(), syms.methodClass); 3676 clinit = new MethodSymbol(STATIC | SYNTHETIC | PRIVATE, 3677 names.clinit, clinitType, enclClass); 3678 clinit.params = List.nil(); 3679 clinits.put(enclClass, clinit); 3680 } 3681 newScopeOwner = clinit; 3682 } 3683 lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dupUnshared(newScopeOwner))); 3684 } else { 3685 lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup())); 3686 } 3687 lambdaEnv.info.yieldResult = null; 3688 lambdaEnv.info.isLambda = true; 3689 return lambdaEnv; 3690 } 3691 3692 @Override 3693 public void visitReference(final JCMemberReference that) { 3694 if (pt().isErroneous() || (pt().hasTag(NONE) && pt() != Type.recoveryType)) { 3695 if (pt().hasTag(NONE) && (env.info.enclVar == null || !env.info.enclVar.type.isErroneous())) { 3696 //method reference only allowed in assignment or method invocation/cast context 3697 log.error(that.pos(), Errors.UnexpectedMref); 3698 } 3699 result = that.type = types.createErrorType(pt()); 3700 return; 3701 } 3702 final Env<AttrContext> localEnv = env.dup(that); 3703 try { 3704 //attribute member reference qualifier - if this is a constructor 3705 //reference, the expected kind must be a type 3706 Type exprType = attribTree(that.expr, env, memberReferenceQualifierResult(that)); 3707 3708 if (that.getMode() == JCMemberReference.ReferenceMode.NEW) { 3709 exprType = chk.checkConstructorRefType(that.expr, exprType); 3710 if (!exprType.isErroneous() && 3711 exprType.isRaw() && 3712 that.typeargs != null) { 3713 log.error(that.expr.pos(), 3714 Errors.InvalidMref(Kinds.kindName(that.getMode()), 3715 Fragments.MrefInferAndExplicitParams)); 3716 exprType = types.createErrorType(exprType); 3717 } 3718 } 3719 3720 if (exprType.isErroneous()) { 3721 //if the qualifier expression contains problems, 3722 //give up attribution of method reference 3723 result = that.type = exprType; 3724 return; 3725 } 3726 3727 if (TreeInfo.isStaticSelector(that.expr, names)) { 3728 //if the qualifier is a type, validate it; raw warning check is 3729 //omitted as we don't know at this stage as to whether this is a 3730 //raw selector (because of inference) 3731 chk.validate(that.expr, env, false); 3732 } else { 3733 Symbol lhsSym = TreeInfo.symbol(that.expr); 3734 localEnv.info.selectSuper = lhsSym != null && lhsSym.name == names._super; 3735 } 3736 //attrib type-arguments 3737 List<Type> typeargtypes = List.nil(); 3738 if (that.typeargs != null) { 3739 typeargtypes = attribTypes(that.typeargs, localEnv); 3740 } 3741 3742 boolean isTargetSerializable = 3743 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK && 3744 rs.isSerializable(pt()); 3745 TargetInfo targetInfo = getTargetInfo(that, resultInfo, null); 3746 Type currentTarget = targetInfo.target; 3747 Type desc = targetInfo.descriptor; 3748 3749 setFunctionalInfo(localEnv, that, pt(), desc, currentTarget, resultInfo.checkContext); 3750 List<Type> argtypes = desc.getParameterTypes(); 3751 Resolve.MethodCheck referenceCheck = rs.resolveMethodCheck; 3752 3753 if (resultInfo.checkContext.inferenceContext().free(argtypes)) { 3754 referenceCheck = rs.new MethodReferenceCheck(resultInfo.checkContext.inferenceContext()); 3755 } 3756 3757 Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = null; 3758 List<Type> saved_undet = resultInfo.checkContext.inferenceContext().save(); 3759 try { 3760 refResult = rs.resolveMemberReference(localEnv, that, that.expr.type, 3761 that.name, argtypes, typeargtypes, targetInfo.descriptor, referenceCheck, 3762 resultInfo.checkContext.inferenceContext(), rs.basicReferenceChooser); 3763 } finally { 3764 resultInfo.checkContext.inferenceContext().rollback(saved_undet); 3765 } 3766 3767 Symbol refSym = refResult.fst; 3768 Resolve.ReferenceLookupHelper lookupHelper = refResult.snd; 3769 3770 /** this switch will need to go away and be replaced by the new RESOLUTION_TARGET testing 3771 * JDK-8075541 3772 */ 3773 if (refSym.kind != MTH) { 3774 boolean targetError; 3775 switch (refSym.kind) { 3776 case ABSENT_MTH: 3777 case MISSING_ENCL: 3778 targetError = false; 3779 break; 3780 case WRONG_MTH: 3781 case WRONG_MTHS: 3782 case AMBIGUOUS: 3783 case HIDDEN: 3784 case STATICERR: 3785 targetError = true; 3786 break; 3787 default: 3788 Assert.error("unexpected result kind " + refSym.kind); 3789 targetError = false; 3790 } 3791 3792 JCDiagnostic detailsDiag = ((Resolve.ResolveError)refSym.baseSymbol()) 3793 .getDiagnostic(JCDiagnostic.DiagnosticType.FRAGMENT, 3794 that, exprType.tsym, exprType, that.name, argtypes, typeargtypes); 3795 3796 JCDiagnostic diag = diags.create(log.currentSource(), that, 3797 targetError ? 3798 Fragments.InvalidMref(Kinds.kindName(that.getMode()), detailsDiag) : 3799 Errors.InvalidMref(Kinds.kindName(that.getMode()), detailsDiag)); 3800 3801 if (targetError && currentTarget == Type.recoveryType) { 3802 //a target error doesn't make sense during recovery stage 3803 //as we don't know what actual parameter types are 3804 result = that.type = currentTarget; 3805 return; 3806 } else { 3807 if (targetError) { 3808 resultInfo.checkContext.report(that, diag); 3809 } else { 3810 log.report(diag); 3811 } 3812 result = that.type = types.createErrorType(currentTarget); 3813 return; 3814 } 3815 } 3816 3817 that.sym = refSym.isConstructor() ? refSym.baseSymbol() : refSym; 3818 that.kind = lookupHelper.referenceKind(that.sym); 3819 that.ownerAccessible = rs.isAccessible(localEnv, that.sym.enclClass()); 3820 3821 if (desc.getReturnType() == Type.recoveryType) { 3822 // stop here 3823 result = that.type = currentTarget; 3824 return; 3825 } 3826 3827 if (!env.info.attributionMode.isSpeculative && that.getMode() == JCMemberReference.ReferenceMode.NEW) { 3828 Type enclosingType = exprType.getEnclosingType(); 3829 if (enclosingType != null && enclosingType.hasTag(CLASS)) { 3830 // Check for the existence of an appropriate outer instance 3831 rs.resolveImplicitThis(that.pos(), env, exprType); 3832 } 3833 } 3834 3835 if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) { 3836 3837 if (that.getMode() == ReferenceMode.INVOKE && 3838 TreeInfo.isStaticSelector(that.expr, names) && 3839 that.kind.isUnbound() && 3840 lookupHelper.site.isRaw()) { 3841 chk.checkRaw(that.expr, localEnv); 3842 } 3843 3844 if (that.sym.isStatic() && TreeInfo.isStaticSelector(that.expr, names) && 3845 exprType.getTypeArguments().nonEmpty()) { 3846 //static ref with class type-args 3847 log.error(that.expr.pos(), 3848 Errors.InvalidMref(Kinds.kindName(that.getMode()), 3849 Fragments.StaticMrefWithTargs)); 3850 result = that.type = types.createErrorType(currentTarget); 3851 return; 3852 } 3853 3854 if (!refSym.isStatic() && that.kind == JCMemberReference.ReferenceKind.SUPER) { 3855 // Check that super-qualified symbols are not abstract (JLS) 3856 rs.checkNonAbstract(that.pos(), that.sym); 3857 } 3858 3859 if (isTargetSerializable) { 3860 chk.checkAccessFromSerializableElement(that, true); 3861 } 3862 } 3863 3864 ResultInfo checkInfo = 3865 resultInfo.dup(newMethodTemplate( 3866 desc.getReturnType().hasTag(VOID) ? Type.noType : desc.getReturnType(), 3867 that.kind.isUnbound() ? argtypes.tail : argtypes, typeargtypes), 3868 new FunctionalReturnContext(resultInfo.checkContext), CheckMode.NO_TREE_UPDATE); 3869 3870 Type refType = checkId(that, lookupHelper.site, refSym, localEnv, checkInfo); 3871 3872 if (that.kind.isUnbound() && 3873 resultInfo.checkContext.inferenceContext().free(argtypes.head)) { 3874 //re-generate inference constraints for unbound receiver 3875 if (!types.isSubtype(resultInfo.checkContext.inferenceContext().asUndetVar(argtypes.head), exprType)) { 3876 //cannot happen as this has already been checked - we just need 3877 //to regenerate the inference constraints, as that has been lost 3878 //as a result of the call to inferenceContext.save() 3879 Assert.error("Can't get here"); 3880 } 3881 } 3882 3883 if (!refType.isErroneous()) { 3884 refType = types.createMethodTypeWithReturn(refType, 3885 adjustMethodReturnType(refSym, lookupHelper.site, that.name, checkInfo.pt.getParameterTypes(), refType.getReturnType())); 3886 } 3887 3888 //go ahead with standard method reference compatibility check - note that param check 3889 //is a no-op (as this has been taken care during method applicability) 3890 boolean isSpeculativeRound = 3891 resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE; 3892 3893 that.type = currentTarget; //avoids recovery at this stage 3894 checkReferenceCompatible(that, desc, refType, resultInfo.checkContext, isSpeculativeRound); 3895 if (!isSpeculativeRound) { 3896 checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), desc, currentTarget); 3897 } 3898 result = check(that, currentTarget, KindSelector.VAL, resultInfo); 3899 } catch (Types.FunctionDescriptorLookupError ex) { 3900 JCDiagnostic cause = ex.getDiagnostic(); 3901 resultInfo.checkContext.report(that, cause); 3902 result = that.type = types.createErrorType(pt()); 3903 return; 3904 } 3905 } 3906 //where 3907 ResultInfo memberReferenceQualifierResult(JCMemberReference tree) { 3908 //if this is a constructor reference, the expected kind must be a type 3909 return new ResultInfo(tree.getMode() == ReferenceMode.INVOKE ? 3910 KindSelector.VAL_TYP : KindSelector.TYP, 3911 Type.noType); 3912 } 3913 3914 3915 @SuppressWarnings("fallthrough") 3916 void checkReferenceCompatible(JCMemberReference tree, Type descriptor, Type refType, CheckContext checkContext, boolean speculativeAttr) { 3917 InferenceContext inferenceContext = checkContext.inferenceContext(); 3918 Type returnType = inferenceContext.asUndetVar(descriptor.getReturnType()); 3919 3920 Type resType; 3921 switch (tree.getMode()) { 3922 case NEW: 3923 if (!tree.expr.type.isRaw()) { 3924 resType = tree.expr.type; 3925 break; 3926 } 3927 default: 3928 resType = refType.getReturnType(); 3929 } 3930 3931 Type incompatibleReturnType = resType; 3932 3933 if (returnType.hasTag(VOID)) { 3934 incompatibleReturnType = null; 3935 } 3936 3937 if (!returnType.hasTag(VOID) && !resType.hasTag(VOID)) { 3938 if (resType.isErroneous() || 3939 new FunctionalReturnContext(checkContext).compatible(resType, returnType, 3940 checkContext.checkWarner(tree, resType, returnType))) { 3941 incompatibleReturnType = null; 3942 } 3943 } 3944 3945 if (incompatibleReturnType != null) { 3946 Fragment msg = 3947 Fragments.IncompatibleRetTypeInMref(Fragments.InconvertibleTypes(resType, descriptor.getReturnType())); 3948 checkContext.report(tree, diags.fragment(msg)); 3949 } else { 3950 if (inferenceContext.free(refType)) { 3951 // we need to wait for inference to finish and then replace inference vars in the referent type 3952 inferenceContext.addFreeTypeListener(List.of(refType), 3953 instantiatedContext -> { 3954 tree.referentType = instantiatedContext.asInstType(refType); 3955 }); 3956 } else { 3957 tree.referentType = refType; 3958 } 3959 } 3960 3961 if (!speculativeAttr) { 3962 if (!checkExConstraints(refType.getThrownTypes(), descriptor.getThrownTypes(), inferenceContext)) { 3963 log.error(tree, Errors.IncompatibleThrownTypesInMref(refType.getThrownTypes())); 3964 } 3965 } 3966 } 3967 3968 boolean checkExConstraints( 3969 List<Type> thrownByFuncExpr, 3970 List<Type> thrownAtFuncType, 3971 InferenceContext inferenceContext) { 3972 /** 18.2.5: Otherwise, let E1, ..., En be the types in the function type's throws clause that 3973 * are not proper types 3974 */ 3975 List<Type> nonProperList = thrownAtFuncType.stream() 3976 .filter(e -> inferenceContext.free(e)).collect(List.collector()); 3977 List<Type> properList = thrownAtFuncType.diff(nonProperList); 3978 3979 /** Let X1,...,Xm be the checked exception types that the lambda body can throw or 3980 * in the throws clause of the invocation type of the method reference's compile-time 3981 * declaration 3982 */ 3983 List<Type> checkedList = thrownByFuncExpr.stream() 3984 .filter(e -> chk.isChecked(e)).collect(List.collector()); 3985 3986 /** If n = 0 (the function type's throws clause consists only of proper types), then 3987 * if there exists some i (1 <= i <= m) such that Xi is not a subtype of any proper type 3988 * in the throws clause, the constraint reduces to false; otherwise, the constraint 3989 * reduces to true 3990 */ 3991 ListBuffer<Type> uncaughtByProperTypes = new ListBuffer<>(); 3992 for (Type checked : checkedList) { 3993 boolean isSubtype = false; 3994 for (Type proper : properList) { 3995 if (types.isSubtype(checked, proper)) { 3996 isSubtype = true; 3997 break; 3998 } 3999 } 4000 if (!isSubtype) { 4001 uncaughtByProperTypes.add(checked); 4002 } 4003 } 4004 4005 if (nonProperList.isEmpty() && !uncaughtByProperTypes.isEmpty()) { 4006 return false; 4007 } 4008 4009 /** If n > 0, the constraint reduces to a set of subtyping constraints: 4010 * for all i (1 <= i <= m), if Xi is not a subtype of any proper type in the 4011 * throws clause, then the constraints include, for all j (1 <= j <= n), <Xi <: Ej> 4012 */ 4013 List<Type> nonProperAsUndet = inferenceContext.asUndetVars(nonProperList); 4014 uncaughtByProperTypes.forEach(checkedEx -> { 4015 nonProperAsUndet.forEach(nonProper -> { 4016 types.isSubtype(checkedEx, nonProper); 4017 }); 4018 }); 4019 4020 /** In addition, for all j (1 <= j <= n), the constraint reduces to the bound throws Ej 4021 */ 4022 nonProperAsUndet.stream() 4023 .filter(t -> t.hasTag(UNDETVAR)) 4024 .forEach(t -> ((UndetVar)t).setThrow()); 4025 return true; 4026 } 4027 4028 /** 4029 * Set functional type info on the underlying AST. Note: as the target descriptor 4030 * might contain inference variables, we might need to register an hook in the 4031 * current inference context. 4032 */ 4033 private void setFunctionalInfo(final Env<AttrContext> env, final JCFunctionalExpression fExpr, 4034 final Type pt, final Type descriptorType, final Type primaryTarget, final CheckContext checkContext) { 4035 if (checkContext.inferenceContext().free(descriptorType)) { 4036 checkContext.inferenceContext().addFreeTypeListener(List.of(pt, descriptorType), 4037 inferenceContext -> setFunctionalInfo(env, fExpr, pt, inferenceContext.asInstType(descriptorType), 4038 inferenceContext.asInstType(primaryTarget), checkContext)); 4039 } else { 4040 if (pt.hasTag(CLASS)) { 4041 fExpr.target = primaryTarget; 4042 } 4043 if (checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK && 4044 pt != Type.recoveryType) { 4045 //check that functional interface class is well-formed 4046 try { 4047 /* Types.makeFunctionalInterfaceClass() may throw an exception 4048 * when it's executed post-inference. See the listener code 4049 * above. 4050 */ 4051 ClassSymbol csym = types.makeFunctionalInterfaceClass(env, 4052 names.empty, fExpr.target, ABSTRACT); 4053 if (csym != null) { 4054 chk.checkImplementations(env.tree, csym, csym); 4055 try { 4056 //perform an additional functional interface check on the synthetic class, 4057 //as there may be spurious errors for raw targets - because of existing issues 4058 //with membership and inheritance (see JDK-8074570). 4059 csym.flags_field |= INTERFACE; 4060 types.findDescriptorType(csym.type); 4061 } catch (FunctionDescriptorLookupError err) { 4062 resultInfo.checkContext.report(fExpr, 4063 diags.fragment(Fragments.NoSuitableFunctionalIntfInst(fExpr.target))); 4064 } 4065 } 4066 } catch (Types.FunctionDescriptorLookupError ex) { 4067 JCDiagnostic cause = ex.getDiagnostic(); 4068 resultInfo.checkContext.report(env.tree, cause); 4069 } 4070 } 4071 } 4072 } 4073 4074 public void visitParens(JCParens tree) { 4075 Type owntype = attribTree(tree.expr, env, resultInfo); 4076 result = check(tree, owntype, pkind(), resultInfo); 4077 Symbol sym = TreeInfo.symbol(tree); 4078 if (sym != null && sym.kind.matches(KindSelector.TYP_PCK) && sym.kind != Kind.ERR) 4079 log.error(tree.pos(), Errors.IllegalParenthesizedExpression); 4080 } 4081 4082 public void visitAssign(JCAssign tree) { 4083 Type owntype = attribTree(tree.lhs, env.dup(tree), varAssignmentInfo); 4084 Type capturedType = capture(owntype); 4085 attribExpr(tree.rhs, env, owntype); 4086 result = check(tree, capturedType, KindSelector.VAL, resultInfo); 4087 } 4088 4089 public void visitAssignop(JCAssignOp tree) { 4090 // Attribute arguments. 4091 Type owntype = attribTree(tree.lhs, env, varAssignmentInfo); 4092 Type operand = attribExpr(tree.rhs, env); 4093 // Find operator. 4094 Symbol operator = tree.operator = operators.resolveBinary(tree, tree.getTag().noAssignOp(), owntype, operand); 4095 if (operator != operators.noOpSymbol && 4096 !owntype.isErroneous() && 4097 !operand.isErroneous()) { 4098 chk.checkDivZero(tree.rhs.pos(), operator, operand); 4099 chk.checkCastable(tree.rhs.pos(), 4100 operator.type.getReturnType(), 4101 owntype); 4102 chk.checkLossOfPrecision(tree.rhs.pos(), operand, owntype); 4103 } 4104 result = check(tree, owntype, KindSelector.VAL, resultInfo); 4105 } 4106 4107 public void visitUnary(JCUnary tree) { 4108 // Attribute arguments. 4109 Type argtype = (tree.getTag().isIncOrDecUnaryOp()) 4110 ? attribTree(tree.arg, env, varAssignmentInfo) 4111 : chk.checkNonVoid(tree.arg.pos(), attribExpr(tree.arg, env)); 4112 4113 // Find operator. 4114 OperatorSymbol operator = tree.operator = operators.resolveUnary(tree, tree.getTag(), argtype); 4115 Type owntype = types.createErrorType(tree.type); 4116 if (operator != operators.noOpSymbol && 4117 !argtype.isErroneous()) { 4118 owntype = (tree.getTag().isIncOrDecUnaryOp()) 4119 ? tree.arg.type 4120 : operator.type.getReturnType(); 4121 int opc = operator.opcode; 4122 4123 // If the argument is constant, fold it. 4124 if (argtype.constValue() != null) { 4125 Type ctype = cfolder.fold1(opc, argtype); 4126 if (ctype != null) { 4127 owntype = cfolder.coerce(ctype, owntype); 4128 } 4129 } 4130 } 4131 result = check(tree, owntype, KindSelector.VAL, resultInfo); 4132 matchBindings = matchBindingsComputer.unary(tree, matchBindings); 4133 } 4134 4135 public void visitBinary(JCBinary tree) { 4136 // Attribute arguments. 4137 Type left = chk.checkNonVoid(tree.lhs.pos(), attribExpr(tree.lhs, env)); 4138 // x && y 4139 // include x's bindings when true in y 4140 4141 // x || y 4142 // include x's bindings when false in y 4143 4144 MatchBindings lhsBindings = matchBindings; 4145 List<BindingSymbol> propagatedBindings; 4146 switch (tree.getTag()) { 4147 case AND: 4148 propagatedBindings = lhsBindings.bindingsWhenTrue; 4149 break; 4150 case OR: 4151 propagatedBindings = lhsBindings.bindingsWhenFalse; 4152 break; 4153 default: 4154 propagatedBindings = List.nil(); 4155 break; 4156 } 4157 Env<AttrContext> rhsEnv = bindingEnv(env, propagatedBindings); 4158 Type right; 4159 try { 4160 right = chk.checkNonVoid(tree.rhs.pos(), attribExpr(tree.rhs, rhsEnv)); 4161 } finally { 4162 rhsEnv.info.scope.leave(); 4163 } 4164 4165 matchBindings = matchBindingsComputer.binary(tree, lhsBindings, matchBindings); 4166 4167 // Find operator. 4168 OperatorSymbol operator = tree.operator = operators.resolveBinary(tree, tree.getTag(), left, right); 4169 Type owntype = types.createErrorType(tree.type); 4170 if (operator != operators.noOpSymbol && 4171 !left.isErroneous() && 4172 !right.isErroneous()) { 4173 owntype = operator.type.getReturnType(); 4174 int opc = operator.opcode; 4175 // If both arguments are constants, fold them. 4176 if (left.constValue() != null && right.constValue() != null) { 4177 Type ctype = cfolder.fold2(opc, left, right); 4178 if (ctype != null) { 4179 owntype = cfolder.coerce(ctype, owntype); 4180 } 4181 } 4182 4183 // Check that argument types of a reference ==, != are 4184 // castable to each other, (JLS 15.21). Note: unboxing 4185 // comparisons will not have an acmp* opc at this point. 4186 if ((opc == ByteCodes.if_acmpeq || opc == ByteCodes.if_acmpne)) { 4187 if (!types.isCastable(left, right, new Warner(tree.pos()))) { 4188 log.error(tree.pos(), Errors.IncomparableTypes(left, right)); 4189 } 4190 } 4191 4192 chk.checkDivZero(tree.rhs.pos(), operator, right); 4193 } 4194 result = check(tree, owntype, KindSelector.VAL, resultInfo); 4195 } 4196 4197 public void visitTypeCast(final JCTypeCast tree) { 4198 Type clazztype = attribType(tree.clazz, env); 4199 chk.validate(tree.clazz, env, false); 4200 //a fresh environment is required for 292 inference to work properly --- 4201 //see Infer.instantiatePolymorphicSignatureInstance() 4202 Env<AttrContext> localEnv = env.dup(tree); 4203 //should we propagate the target type? 4204 final ResultInfo castInfo; 4205 JCExpression expr = TreeInfo.skipParens(tree.expr); 4206 boolean isPoly = (expr.hasTag(LAMBDA) || expr.hasTag(REFERENCE)); 4207 if (isPoly) { 4208 //expression is a poly - we need to propagate target type info 4209 castInfo = new ResultInfo(KindSelector.VAL, clazztype, 4210 new Check.NestedCheckContext(resultInfo.checkContext) { 4211 @Override 4212 public boolean compatible(Type found, Type req, Warner warn) { 4213 return types.isCastable(found, req, warn); 4214 } 4215 }); 4216 } else { 4217 //standalone cast - target-type info is not propagated 4218 castInfo = unknownExprInfo; 4219 } 4220 Type exprtype = attribTree(tree.expr, localEnv, castInfo); 4221 Type owntype = isPoly ? clazztype : chk.checkCastable(tree.expr.pos(), exprtype, clazztype); 4222 if (exprtype.constValue() != null) 4223 owntype = cfolder.coerce(exprtype, owntype); 4224 result = check(tree, capture(owntype), KindSelector.VAL, resultInfo); 4225 if (!isPoly) 4226 chk.checkRedundantCast(localEnv, tree); 4227 } 4228 4229 public void visitTypeTest(JCInstanceOf tree) { 4230 Type exprtype = attribExpr(tree.expr, env); 4231 if (exprtype.isPrimitive()) { 4232 preview.checkSourceLevel(tree.expr.pos(), Feature.PRIMITIVE_PATTERNS); 4233 } else { 4234 exprtype = chk.checkNullOrRefType( 4235 tree.expr.pos(), exprtype); 4236 } 4237 Type clazztype; 4238 JCTree typeTree; 4239 if (tree.pattern.getTag() == BINDINGPATTERN || 4240 tree.pattern.getTag() == RECORDPATTERN) { 4241 attribExpr(tree.pattern, env, exprtype); 4242 clazztype = tree.pattern.type; 4243 if (types.isSubtype(exprtype, clazztype) && 4244 !exprtype.isErroneous() && !clazztype.isErroneous() && 4245 tree.pattern.getTag() != RECORDPATTERN) { 4246 if (!allowUnconditionalPatternsInstanceOf) { 4247 log.error(DiagnosticFlag.SOURCE_LEVEL, tree.pos(), 4248 Feature.UNCONDITIONAL_PATTERN_IN_INSTANCEOF.error(this.sourceName)); 4249 } 4250 } 4251 typeTree = TreeInfo.primaryPatternTypeTree((JCPattern) tree.pattern); 4252 } else { 4253 clazztype = attribType(tree.pattern, env); 4254 typeTree = tree.pattern; 4255 chk.validate(typeTree, env, false); 4256 } 4257 if (clazztype.isPrimitive()) { 4258 preview.checkSourceLevel(tree.pattern.pos(), Feature.PRIMITIVE_PATTERNS); 4259 } else { 4260 if (!clazztype.hasTag(TYPEVAR)) { 4261 clazztype = chk.checkClassOrArrayType(typeTree.pos(), clazztype); 4262 } 4263 if (!clazztype.isErroneous() && !types.isReifiable(clazztype)) { 4264 boolean valid = false; 4265 if (allowReifiableTypesInInstanceof) { 4266 valid = checkCastablePattern(tree.expr.pos(), exprtype, clazztype); 4267 } else { 4268 log.error(DiagnosticFlag.SOURCE_LEVEL, tree.pos(), 4269 Feature.REIFIABLE_TYPES_INSTANCEOF.error(this.sourceName)); 4270 allowReifiableTypesInInstanceof = true; 4271 } 4272 if (!valid) { 4273 clazztype = types.createErrorType(clazztype); 4274 } 4275 } 4276 } 4277 chk.checkCastable(tree.expr.pos(), exprtype, clazztype); 4278 result = check(tree, syms.booleanType, KindSelector.VAL, resultInfo); 4279 } 4280 4281 private boolean checkCastablePattern(DiagnosticPosition pos, 4282 Type exprType, 4283 Type pattType) { 4284 Warner warner = new Warner(); 4285 // if any type is erroneous, the problem is reported elsewhere 4286 if (exprType.isErroneous() || pattType.isErroneous()) { 4287 return false; 4288 } 4289 if (!types.isCastable(exprType, pattType, warner)) { 4290 chk.basicHandler.report(pos, 4291 diags.fragment(Fragments.InconvertibleTypes(exprType, pattType))); 4292 return false; 4293 } else if ((exprType.isPrimitive() || pattType.isPrimitive()) && 4294 (!exprType.isPrimitive() || !pattType.isPrimitive() || !types.isSameType(exprType, pattType))) { 4295 preview.checkSourceLevel(pos, Feature.PRIMITIVE_PATTERNS); 4296 return true; 4297 } else if (warner.hasLint(LintCategory.UNCHECKED)) { 4298 log.error(pos, 4299 Errors.InstanceofReifiableNotSafe(exprType, pattType)); 4300 return false; 4301 } else { 4302 return true; 4303 } 4304 } 4305 4306 @Override 4307 public void visitAnyPattern(JCAnyPattern tree) { 4308 result = tree.type = resultInfo.pt; 4309 } 4310 4311 public void visitBindingPattern(JCBindingPattern tree) { 4312 Type type; 4313 if (tree.var.vartype != null) { 4314 type = attribType(tree.var.vartype, env); 4315 } else { 4316 type = resultInfo.pt; 4317 } 4318 tree.type = tree.var.type = type; 4319 BindingSymbol v = new BindingSymbol(tree.var.mods.flags, tree.var.name, type, env.info.scope.owner); 4320 v.pos = tree.pos; 4321 tree.var.sym = v; 4322 if (chk.checkUnique(tree.var.pos(), v, env.info.scope)) { 4323 chk.checkTransparentVar(tree.var.pos(), v, env.info.scope); 4324 } 4325 annotate.annotateLater(tree.var.mods.annotations, env, v, tree.pos()); 4326 if (!tree.var.isImplicitlyTyped()) { 4327 annotate.queueScanTreeAndTypeAnnotate(tree.var.vartype, env, v, tree.var.pos()); 4328 } 4329 annotate.flush(); 4330 chk.validate(tree.var.vartype, env, true); 4331 result = tree.type; 4332 if (v.isUnnamedVariable()) { 4333 matchBindings = MatchBindingsComputer.EMPTY; 4334 } else { 4335 matchBindings = new MatchBindings(List.of(v), List.nil()); 4336 } 4337 } 4338 4339 @Override 4340 public void visitRecordPattern(JCRecordPattern tree) { 4341 Type site; 4342 4343 if (tree.deconstructor == null) { 4344 log.error(tree.pos(), Errors.DeconstructionPatternVarNotAllowed); 4345 tree.record = syms.errSymbol; 4346 site = tree.type = types.createErrorType(tree.record.type); 4347 } else { 4348 Type type = attribType(tree.deconstructor, env); 4349 if (type.isRaw() && type.tsym.getTypeParameters().nonEmpty()) { 4350 Type inferred = infer.instantiatePatternType(resultInfo.pt, type.tsym); 4351 if (inferred == null) { 4352 log.error(tree.pos(), Errors.PatternTypeCannotInfer); 4353 } else { 4354 type = inferred; 4355 } 4356 } 4357 tree.type = tree.deconstructor.type = type; 4358 site = types.capture(tree.type); 4359 } 4360 4361 List<Type> expectedRecordTypes; 4362 if (site.tsym.kind == Kind.TYP && ((ClassSymbol) site.tsym).isRecord()) { 4363 ClassSymbol record = (ClassSymbol) site.tsym; 4364 expectedRecordTypes = record.getRecordComponents() 4365 .stream() 4366 .map(rc -> types.memberType(site, rc)) 4367 .map(t -> types.upward(t, types.captures(t)).baseType()) 4368 .collect(List.collector()); 4369 tree.record = record; 4370 } else { 4371 log.error(tree.pos(), Errors.DeconstructionPatternOnlyRecords(site.tsym)); 4372 expectedRecordTypes = Stream.generate(() -> types.createErrorType(tree.type)) 4373 .limit(tree.nested.size()) 4374 .collect(List.collector()); 4375 tree.record = syms.errSymbol; 4376 } 4377 ListBuffer<BindingSymbol> outBindings = new ListBuffer<>(); 4378 List<Type> recordTypes = expectedRecordTypes; 4379 List<JCPattern> nestedPatterns = tree.nested; 4380 Env<AttrContext> localEnv = env.dup(tree, env.info.dup(env.info.scope.dup())); 4381 try { 4382 while (recordTypes.nonEmpty() && nestedPatterns.nonEmpty()) { 4383 attribExpr(nestedPatterns.head, localEnv, recordTypes.head); 4384 checkCastablePattern(nestedPatterns.head.pos(), recordTypes.head, nestedPatterns.head.type); 4385 outBindings.addAll(matchBindings.bindingsWhenTrue); 4386 matchBindings.bindingsWhenTrue.forEach(localEnv.info.scope::enter); 4387 nestedPatterns = nestedPatterns.tail; 4388 recordTypes = recordTypes.tail; 4389 } 4390 if (recordTypes.nonEmpty() || nestedPatterns.nonEmpty()) { 4391 while (nestedPatterns.nonEmpty()) { 4392 attribExpr(nestedPatterns.head, localEnv, Type.noType); 4393 nestedPatterns = nestedPatterns.tail; 4394 } 4395 List<Type> nestedTypes = 4396 tree.nested.stream().map(p -> p.type).collect(List.collector()); 4397 log.error(tree.pos(), 4398 Errors.IncorrectNumberOfNestedPatterns(expectedRecordTypes, 4399 nestedTypes)); 4400 } 4401 } finally { 4402 localEnv.info.scope.leave(); 4403 } 4404 chk.validate(tree.deconstructor, env, true); 4405 result = tree.type; 4406 matchBindings = new MatchBindings(outBindings.toList(), List.nil()); 4407 } 4408 4409 public void visitIndexed(JCArrayAccess tree) { 4410 Type owntype = types.createErrorType(tree.type); 4411 Type atype = attribExpr(tree.indexed, env); 4412 attribExpr(tree.index, env, syms.intType); 4413 if (types.isArray(atype)) 4414 owntype = types.elemtype(atype); 4415 else if (!atype.hasTag(ERROR)) 4416 log.error(tree.pos(), Errors.ArrayReqButFound(atype)); 4417 if (!pkind().contains(KindSelector.VAL)) 4418 owntype = capture(owntype); 4419 result = check(tree, owntype, KindSelector.VAR, resultInfo); 4420 } 4421 4422 public void visitIdent(JCIdent tree) { 4423 Symbol sym; 4424 4425 // Find symbol 4426 if (pt().hasTag(METHOD) || pt().hasTag(FORALL)) { 4427 // If we are looking for a method, the prototype `pt' will be a 4428 // method type with the type of the call's arguments as parameters. 4429 env.info.pendingResolutionPhase = null; 4430 sym = rs.resolveMethod(tree.pos(), env, tree.name, pt().getParameterTypes(), pt().getTypeArguments()); 4431 } else if (tree.sym != null && tree.sym.kind != VAR) { 4432 sym = tree.sym; 4433 } else { 4434 sym = rs.resolveIdent(tree.pos(), env, tree.name, pkind()); 4435 } 4436 tree.sym = sym; 4437 4438 // Also find the environment current for the class where 4439 // sym is defined (`symEnv'). 4440 Env<AttrContext> symEnv = env; 4441 if (env.enclClass.sym.owner.kind != PCK && // we are in an inner class 4442 sym.kind.matches(KindSelector.VAL_MTH) && 4443 sym.owner.kind == TYP && 4444 tree.name != names._this && tree.name != names._super) { 4445 4446 // Find environment in which identifier is defined. 4447 while (symEnv.outer != null && 4448 !sym.isMemberOf(symEnv.enclClass.sym, types)) { 4449 symEnv = symEnv.outer; 4450 } 4451 } 4452 4453 // If symbol is a variable, ... 4454 if (sym.kind == VAR) { 4455 VarSymbol v = (VarSymbol)sym; 4456 4457 // ..., evaluate its initializer, if it has one, and check for 4458 // illegal forward reference. 4459 checkInit(tree, env, v, false); 4460 4461 // If we are expecting a variable (as opposed to a value), check 4462 // that the variable is assignable in the current environment. 4463 if (KindSelector.ASG.subset(pkind())) 4464 checkAssignable(tree.pos(), v, null, env); 4465 } 4466 4467 Env<AttrContext> env1 = env; 4468 if (sym.kind != ERR && sym.kind != TYP && 4469 sym.owner != null && sym.owner != env1.enclClass.sym) { 4470 // If the found symbol is inaccessible, then it is 4471 // accessed through an enclosing instance. Locate this 4472 // enclosing instance: 4473 while (env1.outer != null && !rs.isAccessible(env, env1.enclClass.sym.type, sym)) 4474 env1 = env1.outer; 4475 } 4476 4477 if (env.info.isSerializable) { 4478 chk.checkAccessFromSerializableElement(tree, env.info.isSerializableLambda); 4479 } 4480 4481 result = checkId(tree, env1.enclClass.sym.type, sym, env, resultInfo); 4482 } 4483 4484 public void visitSelect(JCFieldAccess tree) { 4485 // Determine the expected kind of the qualifier expression. 4486 KindSelector skind = KindSelector.NIL; 4487 if (tree.name == names._this || tree.name == names._super || 4488 tree.name == names._class) 4489 { 4490 skind = KindSelector.TYP; 4491 } else { 4492 if (pkind().contains(KindSelector.PCK)) 4493 skind = KindSelector.of(skind, KindSelector.PCK); 4494 if (pkind().contains(KindSelector.TYP)) 4495 skind = KindSelector.of(skind, KindSelector.TYP, KindSelector.PCK); 4496 if (pkind().contains(KindSelector.VAL_MTH)) 4497 skind = KindSelector.of(skind, KindSelector.VAL, KindSelector.TYP); 4498 } 4499 4500 // Attribute the qualifier expression, and determine its symbol (if any). 4501 Type site = attribTree(tree.selected, env, new ResultInfo(skind, Type.noType)); 4502 if (!pkind().contains(KindSelector.TYP_PCK)) 4503 site = capture(site); // Capture field access 4504 4505 // don't allow T.class T[].class, etc 4506 if (skind == KindSelector.TYP) { 4507 Type elt = site; 4508 while (elt.hasTag(ARRAY)) 4509 elt = ((ArrayType)elt).elemtype; 4510 if (elt.hasTag(TYPEVAR)) { 4511 log.error(tree.pos(), Errors.TypeVarCantBeDeref); 4512 result = tree.type = types.createErrorType(tree.name, site.tsym, site); 4513 tree.sym = tree.type.tsym; 4514 return ; 4515 } 4516 } 4517 4518 // If qualifier symbol is a type or `super', assert `selectSuper' 4519 // for the selection. This is relevant for determining whether 4520 // protected symbols are accessible. 4521 Symbol sitesym = TreeInfo.symbol(tree.selected); 4522 boolean selectSuperPrev = env.info.selectSuper; 4523 env.info.selectSuper = 4524 sitesym != null && 4525 sitesym.name == names._super; 4526 4527 // Determine the symbol represented by the selection. 4528 env.info.pendingResolutionPhase = null; 4529 Symbol sym = selectSym(tree, sitesym, site, env, resultInfo); 4530 if (sym.kind == VAR && sym.name != names._super && env.info.defaultSuperCallSite != null) { 4531 log.error(tree.selected.pos(), Errors.NotEnclClass(site.tsym)); 4532 sym = syms.errSymbol; 4533 } 4534 if (sym.exists() && !isType(sym) && pkind().contains(KindSelector.TYP_PCK)) { 4535 site = capture(site); 4536 sym = selectSym(tree, sitesym, site, env, resultInfo); 4537 } 4538 boolean varArgs = env.info.lastResolveVarargs(); 4539 tree.sym = sym; 4540 4541 if (site.hasTag(TYPEVAR) && !isType(sym) && sym.kind != ERR) { 4542 site = types.skipTypeVars(site, true); 4543 } 4544 4545 // If that symbol is a variable, ... 4546 if (sym.kind == VAR) { 4547 VarSymbol v = (VarSymbol)sym; 4548 4549 // ..., evaluate its initializer, if it has one, and check for 4550 // illegal forward reference. 4551 checkInit(tree, env, v, true); 4552 4553 // If we are expecting a variable (as opposed to a value), check 4554 // that the variable is assignable in the current environment. 4555 if (KindSelector.ASG.subset(pkind())) 4556 checkAssignable(tree.pos(), v, tree.selected, env); 4557 } 4558 4559 if (sitesym != null && 4560 sitesym.kind == VAR && 4561 ((VarSymbol)sitesym).isResourceVariable() && 4562 sym.kind == MTH && 4563 sym.name.equals(names.close) && 4564 sym.overrides(syms.autoCloseableClose, sitesym.type.tsym, types, true) && 4565 env.info.lint.isEnabled(LintCategory.TRY)) { 4566 log.warning(LintCategory.TRY, tree, Warnings.TryExplicitCloseCall); 4567 } 4568 4569 // Disallow selecting a type from an expression 4570 if (isType(sym) && (sitesym == null || !sitesym.kind.matches(KindSelector.TYP_PCK))) { 4571 tree.type = check(tree.selected, pt(), 4572 sitesym == null ? 4573 KindSelector.VAL : sitesym.kind.toSelector(), 4574 new ResultInfo(KindSelector.TYP_PCK, pt())); 4575 } 4576 4577 if (isType(sitesym)) { 4578 if (sym.name != names._this && sym.name != names._super) { 4579 // Check if type-qualified fields or methods are static (JLS) 4580 if ((sym.flags() & STATIC) == 0 && 4581 sym.name != names._super && 4582 (sym.kind == VAR || sym.kind == MTH)) { 4583 rs.accessBase(rs.new StaticError(sym), 4584 tree.pos(), site, sym.name, true); 4585 } 4586 } 4587 } else if (sym.kind != ERR && 4588 (sym.flags() & STATIC) != 0 && 4589 sym.name != names._class) { 4590 // If the qualified item is not a type and the selected item is static, report 4591 // a warning. Make allowance for the class of an array type e.g. Object[].class) 4592 if (!sym.owner.isAnonymous()) { 4593 chk.warnStatic(tree, Warnings.StaticNotQualifiedByType(sym.kind.kindName(), sym.owner)); 4594 } else { 4595 chk.warnStatic(tree, Warnings.StaticNotQualifiedByType2(sym.kind.kindName())); 4596 } 4597 } 4598 4599 // If we are selecting an instance member via a `super', ... 4600 if (env.info.selectSuper && (sym.flags() & STATIC) == 0) { 4601 4602 // Check that super-qualified symbols are not abstract (JLS) 4603 rs.checkNonAbstract(tree.pos(), sym); 4604 4605 if (site.isRaw()) { 4606 // Determine argument types for site. 4607 Type site1 = types.asSuper(env.enclClass.sym.type, site.tsym); 4608 if (site1 != null) site = site1; 4609 } 4610 } 4611 4612 if (env.info.isSerializable) { 4613 chk.checkAccessFromSerializableElement(tree, env.info.isSerializableLambda); 4614 } 4615 4616 env.info.selectSuper = selectSuperPrev; 4617 result = checkId(tree, site, sym, env, resultInfo); 4618 } 4619 //where 4620 /** Determine symbol referenced by a Select expression, 4621 * 4622 * @param tree The select tree. 4623 * @param site The type of the selected expression, 4624 * @param env The current environment. 4625 * @param resultInfo The current result. 4626 */ 4627 private Symbol selectSym(JCFieldAccess tree, 4628 Symbol location, 4629 Type site, 4630 Env<AttrContext> env, 4631 ResultInfo resultInfo) { 4632 DiagnosticPosition pos = tree.pos(); 4633 Name name = tree.name; 4634 switch (site.getTag()) { 4635 case PACKAGE: 4636 return rs.accessBase( 4637 rs.findIdentInPackage(pos, env, site.tsym, name, resultInfo.pkind), 4638 pos, location, site, name, true); 4639 case ARRAY: 4640 case CLASS: 4641 if (resultInfo.pt.hasTag(METHOD) || resultInfo.pt.hasTag(FORALL)) { 4642 return rs.resolveQualifiedMethod( 4643 pos, env, location, site, name, resultInfo.pt.getParameterTypes(), resultInfo.pt.getTypeArguments()); 4644 } else if (name == names._this || name == names._super) { 4645 return rs.resolveSelf(pos, env, site.tsym, name); 4646 } else if (name == names._class) { 4647 // In this case, we have already made sure in 4648 // visitSelect that qualifier expression is a type. 4649 return syms.getClassField(site, types); 4650 } else { 4651 // We are seeing a plain identifier as selector. 4652 Symbol sym = rs.findIdentInType(pos, env, site, name, resultInfo.pkind); 4653 sym = rs.accessBase(sym, pos, location, site, name, true); 4654 return sym; 4655 } 4656 case WILDCARD: 4657 throw new AssertionError(tree); 4658 case TYPEVAR: 4659 // Normally, site.getUpperBound() shouldn't be null. 4660 // It should only happen during memberEnter/attribBase 4661 // when determining the supertype which *must* be 4662 // done before attributing the type variables. In 4663 // other words, we are seeing this illegal program: 4664 // class B<T> extends A<T.foo> {} 4665 Symbol sym = (site.getUpperBound() != null) 4666 ? selectSym(tree, location, capture(site.getUpperBound()), env, resultInfo) 4667 : null; 4668 if (sym == null) { 4669 log.error(pos, Errors.TypeVarCantBeDeref); 4670 return syms.errSymbol; 4671 } else { 4672 Symbol sym2 = (sym.flags() & Flags.PRIVATE) != 0 ? 4673 rs.new AccessError(env, site, sym) : 4674 sym; 4675 rs.accessBase(sym2, pos, location, site, name, true); 4676 return sym; 4677 } 4678 case ERROR: 4679 // preserve identifier names through errors 4680 return types.createErrorType(name, site.tsym, site).tsym; 4681 default: 4682 // The qualifier expression is of a primitive type -- only 4683 // .class is allowed for these. 4684 if (name == names._class) { 4685 // In this case, we have already made sure in Select that 4686 // qualifier expression is a type. 4687 return syms.getClassField(site, types); 4688 } else { 4689 log.error(pos, Errors.CantDeref(site)); 4690 return syms.errSymbol; 4691 } 4692 } 4693 } 4694 4695 /** Determine type of identifier or select expression and check that 4696 * (1) the referenced symbol is not deprecated 4697 * (2) the symbol's type is safe (@see checkSafe) 4698 * (3) if symbol is a variable, check that its type and kind are 4699 * compatible with the prototype and protokind. 4700 * (4) if symbol is an instance field of a raw type, 4701 * which is being assigned to, issue an unchecked warning if its 4702 * type changes under erasure. 4703 * (5) if symbol is an instance method of a raw type, issue an 4704 * unchecked warning if its argument types change under erasure. 4705 * If checks succeed: 4706 * If symbol is a constant, return its constant type 4707 * else if symbol is a method, return its result type 4708 * otherwise return its type. 4709 * Otherwise return errType. 4710 * 4711 * @param tree The syntax tree representing the identifier 4712 * @param site If this is a select, the type of the selected 4713 * expression, otherwise the type of the current class. 4714 * @param sym The symbol representing the identifier. 4715 * @param env The current environment. 4716 * @param resultInfo The expected result 4717 */ 4718 Type checkId(JCTree tree, 4719 Type site, 4720 Symbol sym, 4721 Env<AttrContext> env, 4722 ResultInfo resultInfo) { 4723 return (resultInfo.pt.hasTag(FORALL) || resultInfo.pt.hasTag(METHOD)) ? 4724 checkMethodIdInternal(tree, site, sym, env, resultInfo) : 4725 checkIdInternal(tree, site, sym, resultInfo.pt, env, resultInfo); 4726 } 4727 4728 Type checkMethodIdInternal(JCTree tree, 4729 Type site, 4730 Symbol sym, 4731 Env<AttrContext> env, 4732 ResultInfo resultInfo) { 4733 if (resultInfo.pkind.contains(KindSelector.POLY)) { 4734 return attrRecover.recoverMethodInvocation(tree, site, sym, env, resultInfo); 4735 } else { 4736 return checkIdInternal(tree, site, sym, resultInfo.pt, env, resultInfo); 4737 } 4738 } 4739 4740 Type checkIdInternal(JCTree tree, 4741 Type site, 4742 Symbol sym, 4743 Type pt, 4744 Env<AttrContext> env, 4745 ResultInfo resultInfo) { 4746 if (pt.isErroneous()) { 4747 return types.createErrorType(site); 4748 } 4749 Type owntype; // The computed type of this identifier occurrence. 4750 switch (sym.kind) { 4751 case TYP: 4752 // For types, the computed type equals the symbol's type, 4753 // except for two situations: 4754 owntype = sym.type; 4755 if (owntype.hasTag(CLASS)) { 4756 chk.checkForBadAuxiliaryClassAccess(tree.pos(), env, (ClassSymbol)sym); 4757 Type ownOuter = owntype.getEnclosingType(); 4758 4759 // (a) If the symbol's type is parameterized, erase it 4760 // because no type parameters were given. 4761 // We recover generic outer type later in visitTypeApply. 4762 if (owntype.tsym.type.getTypeArguments().nonEmpty()) { 4763 owntype = types.erasure(owntype); 4764 } 4765 4766 // (b) If the symbol's type is an inner class, then 4767 // we have to interpret its outer type as a superclass 4768 // of the site type. Example: 4769 // 4770 // class Tree<A> { class Visitor { ... } } 4771 // class PointTree extends Tree<Point> { ... } 4772 // ...PointTree.Visitor... 4773 // 4774 // Then the type of the last expression above is 4775 // Tree<Point>.Visitor. 4776 else if (ownOuter.hasTag(CLASS) && site != ownOuter) { 4777 Type normOuter = site; 4778 if (normOuter.hasTag(CLASS)) { 4779 normOuter = types.asEnclosingSuper(site, ownOuter.tsym); 4780 } 4781 if (normOuter == null) // perhaps from an import 4782 normOuter = types.erasure(ownOuter); 4783 if (normOuter != ownOuter) 4784 owntype = new ClassType( 4785 normOuter, List.nil(), owntype.tsym, 4786 owntype.getMetadata()); 4787 } 4788 } 4789 break; 4790 case VAR: 4791 VarSymbol v = (VarSymbol)sym; 4792 4793 if (env.info.enclVar != null 4794 && v.type.hasTag(NONE)) { 4795 //self reference to implicitly typed variable declaration 4796 log.error(TreeInfo.positionFor(v, env.enclClass), Errors.CantInferLocalVarType(v.name, Fragments.LocalSelfRef)); 4797 return tree.type = v.type = types.createErrorType(v.type); 4798 } 4799 4800 // Test (4): if symbol is an instance field of a raw type, 4801 // which is being assigned to, issue an unchecked warning if 4802 // its type changes under erasure. 4803 if (KindSelector.ASG.subset(pkind()) && 4804 v.owner.kind == TYP && 4805 (v.flags() & STATIC) == 0 && 4806 (site.hasTag(CLASS) || site.hasTag(TYPEVAR))) { 4807 Type s = types.asOuterSuper(site, v.owner); 4808 if (s != null && 4809 s.isRaw() && 4810 !types.isSameType(v.type, v.erasure(types))) { 4811 chk.warnUnchecked(tree.pos(), Warnings.UncheckedAssignToVar(v, s)); 4812 } 4813 } 4814 // The computed type of a variable is the type of the 4815 // variable symbol, taken as a member of the site type. 4816 owntype = (sym.owner.kind == TYP && 4817 sym.name != names._this && sym.name != names._super) 4818 ? types.memberType(site, sym) 4819 : sym.type; 4820 4821 // If the variable is a constant, record constant value in 4822 // computed type. 4823 if (v.getConstValue() != null && isStaticReference(tree)) 4824 owntype = owntype.constType(v.getConstValue()); 4825 4826 if (resultInfo.pkind == KindSelector.VAL) { 4827 owntype = capture(owntype); // capture "names as expressions" 4828 } 4829 break; 4830 case MTH: { 4831 owntype = checkMethod(site, sym, 4832 new ResultInfo(resultInfo.pkind, resultInfo.pt.getReturnType(), resultInfo.checkContext, resultInfo.checkMode), 4833 env, TreeInfo.args(env.tree), resultInfo.pt.getParameterTypes(), 4834 resultInfo.pt.getTypeArguments()); 4835 chk.checkRestricted(tree.pos(), sym); 4836 break; 4837 } 4838 case PCK: case ERR: 4839 owntype = sym.type; 4840 break; 4841 default: 4842 throw new AssertionError("unexpected kind: " + sym.kind + 4843 " in tree " + tree); 4844 } 4845 4846 // Emit a `deprecation' warning if symbol is deprecated. 4847 // (for constructors (but not for constructor references), the error 4848 // was given when the constructor was resolved) 4849 4850 if (sym.name != names.init || tree.hasTag(REFERENCE)) { 4851 chk.checkDeprecated(tree.pos(), env.info.scope.owner, sym); 4852 chk.checkSunAPI(tree.pos(), sym); 4853 chk.checkProfile(tree.pos(), sym); 4854 chk.checkPreview(tree.pos(), env.info.scope.owner, sym); 4855 } 4856 4857 // If symbol is a variable, check that its type and 4858 // kind are compatible with the prototype and protokind. 4859 return check(tree, owntype, sym.kind.toSelector(), resultInfo); 4860 } 4861 4862 /** Check that variable is initialized and evaluate the variable's 4863 * initializer, if not yet done. Also check that variable is not 4864 * referenced before it is defined. 4865 * @param tree The tree making up the variable reference. 4866 * @param env The current environment. 4867 * @param v The variable's symbol. 4868 */ 4869 private void checkInit(JCTree tree, 4870 Env<AttrContext> env, 4871 VarSymbol v, 4872 boolean onlyWarning) { 4873 // A forward reference is diagnosed if the declaration position 4874 // of the variable is greater than the current tree position 4875 // and the tree and variable definition occur in the same class 4876 // definition. Note that writes don't count as references. 4877 // This check applies only to class and instance 4878 // variables. Local variables follow different scope rules, 4879 // and are subject to definite assignment checking. 4880 Env<AttrContext> initEnv = enclosingInitEnv(env); 4881 if (initEnv != null && 4882 (initEnv.info.enclVar == v || v.pos > tree.pos) && 4883 v.owner.kind == TYP && 4884 v.owner == env.info.scope.owner.enclClass() && 4885 ((v.flags() & STATIC) != 0) == Resolve.isStatic(env) && 4886 (!env.tree.hasTag(ASSIGN) || 4887 TreeInfo.skipParens(((JCAssign) env.tree).lhs) != tree)) { 4888 if (!onlyWarning || isStaticEnumField(v)) { 4889 Error errkey = (initEnv.info.enclVar == v) ? 4890 Errors.IllegalSelfRef : Errors.IllegalForwardRef; 4891 log.error(tree.pos(), errkey); 4892 } else if (useBeforeDeclarationWarning) { 4893 Warning warnkey = (initEnv.info.enclVar == v) ? 4894 Warnings.SelfRef(v) : Warnings.ForwardRef(v); 4895 log.warning(tree.pos(), warnkey); 4896 } 4897 } 4898 4899 v.getConstValue(); // ensure initializer is evaluated 4900 4901 checkEnumInitializer(tree, env, v); 4902 } 4903 4904 /** 4905 * Returns the enclosing init environment associated with this env (if any). An init env 4906 * can be either a field declaration env or a static/instance initializer env. 4907 */ 4908 Env<AttrContext> enclosingInitEnv(Env<AttrContext> env) { 4909 while (true) { 4910 switch (env.tree.getTag()) { 4911 case VARDEF: 4912 JCVariableDecl vdecl = (JCVariableDecl)env.tree; 4913 if (vdecl.sym.owner.kind == TYP) { 4914 //field 4915 return env; 4916 } 4917 break; 4918 case BLOCK: 4919 if (env.next.tree.hasTag(CLASSDEF)) { 4920 //instance/static initializer 4921 return env; 4922 } 4923 break; 4924 case METHODDEF: 4925 case CLASSDEF: 4926 case TOPLEVEL: 4927 return null; 4928 } 4929 Assert.checkNonNull(env.next); 4930 env = env.next; 4931 } 4932 } 4933 4934 /** 4935 * Check for illegal references to static members of enum. In 4936 * an enum type, constructors and initializers may not 4937 * reference its static members unless they are constant. 4938 * 4939 * @param tree The tree making up the variable reference. 4940 * @param env The current environment. 4941 * @param v The variable's symbol. 4942 * @jls 8.9 Enum Types 4943 */ 4944 private void checkEnumInitializer(JCTree tree, Env<AttrContext> env, VarSymbol v) { 4945 // JLS: 4946 // 4947 // "It is a compile-time error to reference a static field 4948 // of an enum type that is not a compile-time constant 4949 // (15.28) from constructors, instance initializer blocks, 4950 // or instance variable initializer expressions of that 4951 // type. It is a compile-time error for the constructors, 4952 // instance initializer blocks, or instance variable 4953 // initializer expressions of an enum constant e to refer 4954 // to itself or to an enum constant of the same type that 4955 // is declared to the right of e." 4956 if (isStaticEnumField(v)) { 4957 ClassSymbol enclClass = env.info.scope.owner.enclClass(); 4958 4959 if (enclClass == null || enclClass.owner == null) 4960 return; 4961 4962 // See if the enclosing class is the enum (or a 4963 // subclass thereof) declaring v. If not, this 4964 // reference is OK. 4965 if (v.owner != enclClass && !types.isSubtype(enclClass.type, v.owner.type)) 4966 return; 4967 4968 // If the reference isn't from an initializer, then 4969 // the reference is OK. 4970 if (!Resolve.isInitializer(env)) 4971 return; 4972 4973 log.error(tree.pos(), Errors.IllegalEnumStaticRef); 4974 } 4975 } 4976 4977 /** Is the given symbol a static, non-constant field of an Enum? 4978 * Note: enum literals should not be regarded as such 4979 */ 4980 private boolean isStaticEnumField(VarSymbol v) { 4981 return Flags.isEnum(v.owner) && 4982 Flags.isStatic(v) && 4983 !Flags.isConstant(v) && 4984 v.name != names._class; 4985 } 4986 4987 /** 4988 * Check that method arguments conform to its instantiation. 4989 **/ 4990 public Type checkMethod(Type site, 4991 final Symbol sym, 4992 ResultInfo resultInfo, 4993 Env<AttrContext> env, 4994 final List<JCExpression> argtrees, 4995 List<Type> argtypes, 4996 List<Type> typeargtypes) { 4997 // Test (5): if symbol is an instance method of a raw type, issue 4998 // an unchecked warning if its argument types change under erasure. 4999 if ((sym.flags() & STATIC) == 0 && 5000 (site.hasTag(CLASS) || site.hasTag(TYPEVAR))) { 5001 Type s = types.asOuterSuper(site, sym.owner); 5002 if (s != null && s.isRaw() && 5003 !types.isSameTypes(sym.type.getParameterTypes(), 5004 sym.erasure(types).getParameterTypes())) { 5005 chk.warnUnchecked(env.tree.pos(), Warnings.UncheckedCallMbrOfRawType(sym, s)); 5006 } 5007 } 5008 5009 if (env.info.defaultSuperCallSite != null) { 5010 for (Type sup : types.interfaces(env.enclClass.type).prepend(types.supertype((env.enclClass.type)))) { 5011 if (!sup.tsym.isSubClass(sym.enclClass(), types) || 5012 types.isSameType(sup, env.info.defaultSuperCallSite)) continue; 5013 List<MethodSymbol> icand_sup = 5014 types.interfaceCandidates(sup, (MethodSymbol)sym); 5015 if (icand_sup.nonEmpty() && 5016 icand_sup.head != sym && 5017 icand_sup.head.overrides(sym, icand_sup.head.enclClass(), types, true)) { 5018 log.error(env.tree.pos(), 5019 Errors.IllegalDefaultSuperCall(env.info.defaultSuperCallSite, Fragments.OverriddenDefault(sym, sup))); 5020 break; 5021 } 5022 } 5023 env.info.defaultSuperCallSite = null; 5024 } 5025 5026 if (sym.isStatic() && site.isInterface() && env.tree.hasTag(APPLY)) { 5027 JCMethodInvocation app = (JCMethodInvocation)env.tree; 5028 if (app.meth.hasTag(SELECT) && 5029 !TreeInfo.isStaticSelector(((JCFieldAccess)app.meth).selected, names)) { 5030 log.error(env.tree.pos(), Errors.IllegalStaticIntfMethCall(site)); 5031 } 5032 } 5033 5034 // Compute the identifier's instantiated type. 5035 // For methods, we need to compute the instance type by 5036 // Resolve.instantiate from the symbol's type as well as 5037 // any type arguments and value arguments. 5038 Warner noteWarner = new Warner(); 5039 try { 5040 Type owntype = rs.checkMethod( 5041 env, 5042 site, 5043 sym, 5044 resultInfo, 5045 argtypes, 5046 typeargtypes, 5047 noteWarner); 5048 5049 DeferredAttr.DeferredTypeMap<Void> checkDeferredMap = 5050 deferredAttr.new DeferredTypeMap<>(DeferredAttr.AttrMode.CHECK, sym, env.info.pendingResolutionPhase); 5051 5052 argtypes = argtypes.map(checkDeferredMap); 5053 5054 if (noteWarner.hasNonSilentLint(LintCategory.UNCHECKED)) { 5055 chk.warnUnchecked(env.tree.pos(), Warnings.UncheckedMethInvocationApplied(kindName(sym), 5056 sym.name, 5057 rs.methodArguments(sym.type.getParameterTypes()), 5058 rs.methodArguments(argtypes.map(checkDeferredMap)), 5059 kindName(sym.location()), 5060 sym.location())); 5061 if (resultInfo.pt != Infer.anyPoly || 5062 !owntype.hasTag(METHOD) || 5063 !owntype.isPartial()) { 5064 //if this is not a partially inferred method type, erase return type. Otherwise, 5065 //erasure is carried out in PartiallyInferredMethodType.check(). 5066 owntype = new MethodType(owntype.getParameterTypes(), 5067 types.erasure(owntype.getReturnType()), 5068 types.erasure(owntype.getThrownTypes()), 5069 syms.methodClass); 5070 } 5071 } 5072 5073 PolyKind pkind = (sym.type.hasTag(FORALL) && 5074 sym.type.getReturnType().containsAny(((ForAll)sym.type).tvars)) ? 5075 PolyKind.POLY : PolyKind.STANDALONE; 5076 TreeInfo.setPolyKind(env.tree, pkind); 5077 5078 return (resultInfo.pt == Infer.anyPoly) ? 5079 owntype : 5080 chk.checkMethod(owntype, sym, env, argtrees, argtypes, env.info.lastResolveVarargs(), 5081 resultInfo.checkContext.inferenceContext()); 5082 } catch (Infer.InferenceException ex) { 5083 //invalid target type - propagate exception outwards or report error 5084 //depending on the current check context 5085 resultInfo.checkContext.report(env.tree.pos(), ex.getDiagnostic()); 5086 return types.createErrorType(site); 5087 } catch (Resolve.InapplicableMethodException ex) { 5088 final JCDiagnostic diag = ex.getDiagnostic(); 5089 Resolve.InapplicableSymbolError errSym = rs.new InapplicableSymbolError(null) { 5090 @Override 5091 protected Pair<Symbol, JCDiagnostic> errCandidate() { 5092 return new Pair<>(sym, diag); 5093 } 5094 }; 5095 List<Type> argtypes2 = argtypes.map( 5096 rs.new ResolveDeferredRecoveryMap(AttrMode.CHECK, sym, env.info.pendingResolutionPhase)); 5097 JCDiagnostic errDiag = errSym.getDiagnostic(JCDiagnostic.DiagnosticType.ERROR, 5098 env.tree, sym, site, sym.name, argtypes2, typeargtypes); 5099 log.report(errDiag); 5100 return types.createErrorType(site); 5101 } 5102 } 5103 5104 public void visitLiteral(JCLiteral tree) { 5105 result = check(tree, litType(tree.typetag).constType(tree.value), 5106 KindSelector.VAL, resultInfo); 5107 } 5108 //where 5109 /** Return the type of a literal with given type tag. 5110 */ 5111 Type litType(TypeTag tag) { 5112 return (tag == CLASS) ? syms.stringType : syms.typeOfTag[tag.ordinal()]; 5113 } 5114 5115 public void visitTypeIdent(JCPrimitiveTypeTree tree) { 5116 result = check(tree, syms.typeOfTag[tree.typetag.ordinal()], KindSelector.TYP, resultInfo); 5117 } 5118 5119 public void visitTypeArray(JCArrayTypeTree tree) { 5120 Type etype = attribType(tree.elemtype, env); 5121 Type type = new ArrayType(etype, syms.arrayClass); 5122 result = check(tree, type, KindSelector.TYP, resultInfo); 5123 } 5124 5125 /** Visitor method for parameterized types. 5126 * Bound checking is left until later, since types are attributed 5127 * before supertype structure is completely known 5128 */ 5129 public void visitTypeApply(JCTypeApply tree) { 5130 Type owntype = types.createErrorType(tree.type); 5131 5132 // Attribute functor part of application and make sure it's a class. 5133 Type clazztype = chk.checkClassType(tree.clazz.pos(), attribType(tree.clazz, env)); 5134 5135 // Attribute type parameters 5136 List<Type> actuals = attribTypes(tree.arguments, env); 5137 5138 if (clazztype.hasTag(CLASS)) { 5139 List<Type> formals = clazztype.tsym.type.getTypeArguments(); 5140 if (actuals.isEmpty()) //diamond 5141 actuals = formals; 5142 5143 if (actuals.length() == formals.length()) { 5144 List<Type> a = actuals; 5145 List<Type> f = formals; 5146 while (a.nonEmpty()) { 5147 a.head = a.head.withTypeVar(f.head); 5148 a = a.tail; 5149 f = f.tail; 5150 } 5151 // Compute the proper generic outer 5152 Type clazzOuter = clazztype.getEnclosingType(); 5153 if (clazzOuter.hasTag(CLASS)) { 5154 Type site; 5155 JCExpression clazz = TreeInfo.typeIn(tree.clazz); 5156 if (clazz.hasTag(IDENT)) { 5157 site = env.enclClass.sym.type; 5158 } else if (clazz.hasTag(SELECT)) { 5159 site = ((JCFieldAccess) clazz).selected.type; 5160 } else throw new AssertionError(""+tree); 5161 if (clazzOuter.hasTag(CLASS) && site != clazzOuter) { 5162 if (site.hasTag(CLASS)) 5163 site = types.asOuterSuper(site, clazzOuter.tsym); 5164 if (site == null) 5165 site = types.erasure(clazzOuter); 5166 clazzOuter = site; 5167 } 5168 } 5169 owntype = new ClassType(clazzOuter, actuals, clazztype.tsym, 5170 clazztype.getMetadata()); 5171 } else { 5172 if (formals.length() != 0) { 5173 log.error(tree.pos(), 5174 Errors.WrongNumberTypeArgs(Integer.toString(formals.length()))); 5175 } else { 5176 log.error(tree.pos(), Errors.TypeDoesntTakeParams(clazztype.tsym)); 5177 } 5178 owntype = types.createErrorType(tree.type); 5179 } 5180 } 5181 result = check(tree, owntype, KindSelector.TYP, resultInfo); 5182 } 5183 5184 public void visitTypeUnion(JCTypeUnion tree) { 5185 ListBuffer<Type> multicatchTypes = new ListBuffer<>(); 5186 ListBuffer<Type> all_multicatchTypes = null; // lazy, only if needed 5187 for (JCExpression typeTree : tree.alternatives) { 5188 Type ctype = attribType(typeTree, env); 5189 ctype = chk.checkType(typeTree.pos(), 5190 chk.checkClassType(typeTree.pos(), ctype), 5191 syms.throwableType); 5192 if (!ctype.isErroneous()) { 5193 //check that alternatives of a union type are pairwise 5194 //unrelated w.r.t. subtyping 5195 if (chk.intersects(ctype, multicatchTypes.toList())) { 5196 for (Type t : multicatchTypes) { 5197 boolean sub = types.isSubtype(ctype, t); 5198 boolean sup = types.isSubtype(t, ctype); 5199 if (sub || sup) { 5200 //assume 'a' <: 'b' 5201 Type a = sub ? ctype : t; 5202 Type b = sub ? t : ctype; 5203 log.error(typeTree.pos(), Errors.MulticatchTypesMustBeDisjoint(a, b)); 5204 } 5205 } 5206 } 5207 multicatchTypes.append(ctype); 5208 if (all_multicatchTypes != null) 5209 all_multicatchTypes.append(ctype); 5210 } else { 5211 if (all_multicatchTypes == null) { 5212 all_multicatchTypes = new ListBuffer<>(); 5213 all_multicatchTypes.appendList(multicatchTypes); 5214 } 5215 all_multicatchTypes.append(ctype); 5216 } 5217 } 5218 Type t = check(tree, types.lub(multicatchTypes.toList()), 5219 KindSelector.TYP, resultInfo.dup(CheckMode.NO_TREE_UPDATE)); 5220 if (t.hasTag(CLASS)) { 5221 List<Type> alternatives = 5222 ((all_multicatchTypes == null) ? multicatchTypes : all_multicatchTypes).toList(); 5223 t = new UnionClassType((ClassType) t, alternatives); 5224 } 5225 tree.type = result = t; 5226 } 5227 5228 public void visitTypeIntersection(JCTypeIntersection tree) { 5229 attribTypes(tree.bounds, env); 5230 tree.type = result = checkIntersection(tree, tree.bounds); 5231 } 5232 5233 public void visitTypeParameter(JCTypeParameter tree) { 5234 TypeVar typeVar = (TypeVar) tree.type; 5235 5236 if (tree.annotations != null && tree.annotations.nonEmpty()) { 5237 annotate.annotateTypeParameterSecondStage(tree, tree.annotations); 5238 } 5239 5240 if (!typeVar.getUpperBound().isErroneous()) { 5241 //fixup type-parameter bound computed in 'attribTypeVariables' 5242 typeVar.setUpperBound(checkIntersection(tree, tree.bounds)); 5243 } 5244 } 5245 5246 Type checkIntersection(JCTree tree, List<JCExpression> bounds) { 5247 Set<Symbol> boundSet = new HashSet<>(); 5248 if (bounds.nonEmpty()) { 5249 // accept class or interface or typevar as first bound. 5250 bounds.head.type = checkBase(bounds.head.type, bounds.head, env, false, false, false); 5251 boundSet.add(types.erasure(bounds.head.type).tsym); 5252 if (bounds.head.type.isErroneous()) { 5253 return bounds.head.type; 5254 } 5255 else if (bounds.head.type.hasTag(TYPEVAR)) { 5256 // if first bound was a typevar, do not accept further bounds. 5257 if (bounds.tail.nonEmpty()) { 5258 log.error(bounds.tail.head.pos(), 5259 Errors.TypeVarMayNotBeFollowedByOtherBounds); 5260 return bounds.head.type; 5261 } 5262 } else { 5263 // if first bound was a class or interface, accept only interfaces 5264 // as further bounds. 5265 for (JCExpression bound : bounds.tail) { 5266 bound.type = checkBase(bound.type, bound, env, false, true, false); 5267 if (bound.type.isErroneous()) { 5268 bounds = List.of(bound); 5269 } 5270 else if (bound.type.hasTag(CLASS)) { 5271 chk.checkNotRepeated(bound.pos(), types.erasure(bound.type), boundSet); 5272 } 5273 } 5274 } 5275 } 5276 5277 if (bounds.length() == 0) { 5278 return syms.objectType; 5279 } else if (bounds.length() == 1) { 5280 return bounds.head.type; 5281 } else { 5282 Type owntype = types.makeIntersectionType(TreeInfo.types(bounds)); 5283 // ... the variable's bound is a class type flagged COMPOUND 5284 // (see comment for TypeVar.bound). 5285 // In this case, generate a class tree that represents the 5286 // bound class, ... 5287 JCExpression extending; 5288 List<JCExpression> implementing; 5289 if (!bounds.head.type.isInterface()) { 5290 extending = bounds.head; 5291 implementing = bounds.tail; 5292 } else { 5293 extending = null; 5294 implementing = bounds; 5295 } 5296 JCClassDecl cd = make.at(tree).ClassDef( 5297 make.Modifiers(PUBLIC | ABSTRACT), 5298 names.empty, List.nil(), 5299 extending, implementing, List.nil()); 5300 5301 ClassSymbol c = (ClassSymbol)owntype.tsym; 5302 Assert.check((c.flags() & COMPOUND) != 0); 5303 cd.sym = c; 5304 c.sourcefile = env.toplevel.sourcefile; 5305 5306 // ... and attribute the bound class 5307 c.flags_field |= UNATTRIBUTED; 5308 Env<AttrContext> cenv = enter.classEnv(cd, env); 5309 typeEnvs.put(c, cenv); 5310 attribClass(c); 5311 return owntype; 5312 } 5313 } 5314 5315 public void visitWildcard(JCWildcard tree) { 5316 //- System.err.println("visitWildcard("+tree+");");//DEBUG 5317 Type type = (tree.kind.kind == BoundKind.UNBOUND) 5318 ? syms.objectType 5319 : attribType(tree.inner, env); 5320 result = check(tree, new WildcardType(chk.checkRefType(tree.pos(), type), 5321 tree.kind.kind, 5322 syms.boundClass), 5323 KindSelector.TYP, resultInfo); 5324 } 5325 5326 public void visitAnnotation(JCAnnotation tree) { 5327 Assert.error("should be handled in annotate"); 5328 } 5329 5330 @Override 5331 public void visitModifiers(JCModifiers tree) { 5332 //error recovery only: 5333 Assert.check(resultInfo.pkind == KindSelector.ERR); 5334 5335 attribAnnotationTypes(tree.annotations, env); 5336 } 5337 5338 public void visitAnnotatedType(JCAnnotatedType tree) { 5339 attribAnnotationTypes(tree.annotations, env); 5340 Type underlyingType = attribType(tree.underlyingType, env); 5341 Type annotatedType = underlyingType.preannotatedType(); 5342 5343 if (!env.info.isNewClass) 5344 annotate.annotateTypeSecondStage(tree, tree.annotations, annotatedType); 5345 result = tree.type = annotatedType; 5346 } 5347 5348 public void visitErroneous(JCErroneous tree) { 5349 if (tree.errs != null) { 5350 Env<AttrContext> errEnv = env.dup(env.tree, env.info.dup()); 5351 errEnv.info.returnResult = unknownExprInfo; 5352 for (JCTree err : tree.errs) 5353 attribTree(err, errEnv, new ResultInfo(KindSelector.ERR, pt())); 5354 } 5355 result = tree.type = syms.errType; 5356 } 5357 5358 /** Default visitor method for all other trees. 5359 */ 5360 public void visitTree(JCTree tree) { 5361 throw new AssertionError(); 5362 } 5363 5364 /** 5365 * Attribute an env for either a top level tree or class or module declaration. 5366 */ 5367 public void attrib(Env<AttrContext> env) { 5368 switch (env.tree.getTag()) { 5369 case MODULEDEF: 5370 attribModule(env.tree.pos(), ((JCModuleDecl)env.tree).sym); 5371 break; 5372 case PACKAGEDEF: 5373 attribPackage(env.tree.pos(), ((JCPackageDecl) env.tree).packge); 5374 break; 5375 default: 5376 attribClass(env.tree.pos(), env.enclClass.sym); 5377 } 5378 } 5379 5380 public void attribPackage(DiagnosticPosition pos, PackageSymbol p) { 5381 try { 5382 annotate.flush(); 5383 attribPackage(p); 5384 } catch (CompletionFailure ex) { 5385 chk.completionError(pos, ex); 5386 } 5387 } 5388 5389 void attribPackage(PackageSymbol p) { 5390 attribWithLint(p, 5391 env -> chk.checkDeprecatedAnnotation(((JCPackageDecl) env.tree).pid.pos(), p)); 5392 } 5393 5394 public void attribModule(DiagnosticPosition pos, ModuleSymbol m) { 5395 try { 5396 annotate.flush(); 5397 attribModule(m); 5398 } catch (CompletionFailure ex) { 5399 chk.completionError(pos, ex); 5400 } 5401 } 5402 5403 void attribModule(ModuleSymbol m) { 5404 attribWithLint(m, env -> attribStat(env.tree, env)); 5405 } 5406 5407 private void attribWithLint(TypeSymbol sym, Consumer<Env<AttrContext>> attrib) { 5408 Env<AttrContext> env = typeEnvs.get(sym); 5409 5410 Env<AttrContext> lintEnv = env; 5411 while (lintEnv.info.lint == null) 5412 lintEnv = lintEnv.next; 5413 5414 Lint lint = lintEnv.info.lint.augment(sym); 5415 5416 Lint prevLint = chk.setLint(lint); 5417 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 5418 5419 try { 5420 deferredLintHandler.flush(env.tree.pos(), lint); 5421 attrib.accept(env); 5422 } finally { 5423 log.useSource(prev); 5424 chk.setLint(prevLint); 5425 } 5426 } 5427 5428 /** Main method: attribute class definition associated with given class symbol. 5429 * reporting completion failures at the given position. 5430 * @param pos The source position at which completion errors are to be 5431 * reported. 5432 * @param c The class symbol whose definition will be attributed. 5433 */ 5434 public void attribClass(DiagnosticPosition pos, ClassSymbol c) { 5435 try { 5436 annotate.flush(); 5437 attribClass(c); 5438 } catch (CompletionFailure ex) { 5439 chk.completionError(pos, ex); 5440 } 5441 } 5442 5443 /** Attribute class definition associated with given class symbol. 5444 * @param c The class symbol whose definition will be attributed. 5445 */ 5446 void attribClass(ClassSymbol c) throws CompletionFailure { 5447 if (c.type.hasTag(ERROR)) return; 5448 5449 // Check for cycles in the inheritance graph, which can arise from 5450 // ill-formed class files. 5451 chk.checkNonCyclic(null, c.type); 5452 5453 Type st = types.supertype(c.type); 5454 if ((c.flags_field & Flags.COMPOUND) == 0 && 5455 (c.flags_field & Flags.SUPER_OWNER_ATTRIBUTED) == 0) { 5456 // First, attribute superclass. 5457 if (st.hasTag(CLASS)) 5458 attribClass((ClassSymbol)st.tsym); 5459 5460 // Next attribute owner, if it is a class. 5461 if (c.owner.kind == TYP && c.owner.type.hasTag(CLASS)) 5462 attribClass((ClassSymbol)c.owner); 5463 5464 c.flags_field |= Flags.SUPER_OWNER_ATTRIBUTED; 5465 } 5466 5467 // The previous operations might have attributed the current class 5468 // if there was a cycle. So we test first whether the class is still 5469 // UNATTRIBUTED. 5470 if ((c.flags_field & UNATTRIBUTED) != 0) { 5471 c.flags_field &= ~UNATTRIBUTED; 5472 5473 // Get environment current at the point of class definition. 5474 Env<AttrContext> env = typeEnvs.get(c); 5475 5476 // The info.lint field in the envs stored in typeEnvs is deliberately uninitialized, 5477 // because the annotations were not available at the time the env was created. Therefore, 5478 // we look up the environment chain for the first enclosing environment for which the 5479 // lint value is set. Typically, this is the parent env, but might be further if there 5480 // are any envs created as a result of TypeParameter nodes. 5481 Env<AttrContext> lintEnv = env; 5482 while (lintEnv.info.lint == null) 5483 lintEnv = lintEnv.next; 5484 5485 // Having found the enclosing lint value, we can initialize the lint value for this class 5486 env.info.lint = lintEnv.info.lint.augment(c); 5487 5488 Lint prevLint = chk.setLint(env.info.lint); 5489 JavaFileObject prev = log.useSource(c.sourcefile); 5490 ResultInfo prevReturnRes = env.info.returnResult; 5491 5492 try { 5493 if (c.isSealed() && 5494 !c.isEnum() && 5495 !c.isPermittedExplicit && 5496 c.getPermittedSubclasses().isEmpty()) { 5497 log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.SealedClassMustHaveSubclasses); 5498 } 5499 5500 if (c.isSealed()) { 5501 Set<Symbol> permittedTypes = new HashSet<>(); 5502 boolean sealedInUnnamed = c.packge().modle == syms.unnamedModule || c.packge().modle == syms.noModule; 5503 for (Type subType : c.getPermittedSubclasses()) { 5504 boolean isTypeVar = false; 5505 if (subType.getTag() == TYPEVAR) { 5506 isTypeVar = true; //error recovery 5507 log.error(TreeInfo.diagnosticPositionFor(subType.tsym, env.tree), 5508 Errors.InvalidPermitsClause(Fragments.IsATypeVariable(subType))); 5509 } 5510 if (subType.tsym.isAnonymous() && !c.isEnum()) { 5511 log.error(TreeInfo.diagnosticPositionFor(subType.tsym, env.tree), Errors.LocalClassesCantExtendSealed(Fragments.Anonymous)); 5512 } 5513 if (permittedTypes.contains(subType.tsym)) { 5514 DiagnosticPosition pos = 5515 env.enclClass.permitting.stream() 5516 .filter(permittedExpr -> TreeInfo.diagnosticPositionFor(subType.tsym, permittedExpr, true) != null) 5517 .limit(2).collect(List.collector()).get(1); 5518 log.error(pos, Errors.InvalidPermitsClause(Fragments.IsDuplicated(subType))); 5519 } else { 5520 permittedTypes.add(subType.tsym); 5521 } 5522 if (sealedInUnnamed) { 5523 if (subType.tsym.packge() != c.packge()) { 5524 log.error(TreeInfo.diagnosticPositionFor(subType.tsym, env.tree), 5525 Errors.ClassInUnnamedModuleCantExtendSealedInDiffPackage(c) 5526 ); 5527 } 5528 } else if (subType.tsym.packge().modle != c.packge().modle) { 5529 log.error(TreeInfo.diagnosticPositionFor(subType.tsym, env.tree), 5530 Errors.ClassInModuleCantExtendSealedInDiffModule(c, c.packge().modle) 5531 ); 5532 } 5533 if (subType.tsym == c.type.tsym || types.isSuperType(subType, c.type)) { 5534 log.error(TreeInfo.diagnosticPositionFor(subType.tsym, ((JCClassDecl)env.tree).permitting), 5535 Errors.InvalidPermitsClause( 5536 subType.tsym == c.type.tsym ? 5537 Fragments.MustNotBeSameClass : 5538 Fragments.MustNotBeSupertype(subType) 5539 ) 5540 ); 5541 } else if (!isTypeVar) { 5542 boolean thisIsASuper = types.directSupertypes(subType) 5543 .stream() 5544 .anyMatch(d -> d.tsym == c); 5545 if (!thisIsASuper) { 5546 log.error(TreeInfo.diagnosticPositionFor(subType.tsym, env.tree), 5547 Errors.InvalidPermitsClause(Fragments.DoesntExtendSealed(subType))); 5548 } 5549 } 5550 } 5551 } 5552 5553 List<ClassSymbol> sealedSupers = types.directSupertypes(c.type) 5554 .stream() 5555 .filter(s -> s.tsym.isSealed()) 5556 .map(s -> (ClassSymbol) s.tsym) 5557 .collect(List.collector()); 5558 5559 if (sealedSupers.isEmpty()) { 5560 if ((c.flags_field & Flags.NON_SEALED) != 0) { 5561 boolean hasErrorSuper = false; 5562 5563 hasErrorSuper |= types.directSupertypes(c.type) 5564 .stream() 5565 .anyMatch(s -> s.tsym.kind == Kind.ERR); 5566 5567 ClassType ct = (ClassType) c.type; 5568 5569 hasErrorSuper |= !ct.isCompound() && ct.interfaces_field != ct.all_interfaces_field; 5570 5571 if (!hasErrorSuper) { 5572 log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.NonSealedWithNoSealedSupertype(c)); 5573 } 5574 } 5575 } else { 5576 if (c.isDirectlyOrIndirectlyLocal() && !c.isEnum()) { 5577 log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.LocalClassesCantExtendSealed(c.isAnonymous() ? Fragments.Anonymous : Fragments.Local)); 5578 } 5579 5580 if (!c.type.isCompound()) { 5581 for (ClassSymbol supertypeSym : sealedSupers) { 5582 if (!supertypeSym.isPermittedSubclass(c.type.tsym)) { 5583 log.error(TreeInfo.diagnosticPositionFor(c.type.tsym, env.tree), Errors.CantInheritFromSealed(supertypeSym)); 5584 } 5585 } 5586 if (!c.isNonSealed() && !c.isFinal() && !c.isSealed()) { 5587 log.error(TreeInfo.diagnosticPositionFor(c, env.tree), 5588 c.isInterface() ? 5589 Errors.NonSealedOrSealedExpected : 5590 Errors.NonSealedSealedOrFinalExpected); 5591 } 5592 } 5593 } 5594 5595 deferredLintHandler.flush(env.tree, env.info.lint); 5596 env.info.returnResult = null; 5597 // java.lang.Enum may not be subclassed by a non-enum 5598 if (st.tsym == syms.enumSym && 5599 ((c.flags_field & (Flags.ENUM|Flags.COMPOUND)) == 0)) 5600 log.error(env.tree.pos(), Errors.EnumNoSubclassing); 5601 5602 // Enums may not be extended by source-level classes 5603 if (st.tsym != null && 5604 ((st.tsym.flags_field & Flags.ENUM) != 0) && 5605 ((c.flags_field & (Flags.ENUM | Flags.COMPOUND)) == 0)) { 5606 log.error(env.tree.pos(), Errors.EnumTypesNotExtensible); 5607 } 5608 5609 if (rs.isSerializable(c.type)) { 5610 env.info.isSerializable = true; 5611 } 5612 5613 attribClassBody(env, c); 5614 5615 chk.checkDeprecatedAnnotation(env.tree.pos(), c); 5616 chk.checkClassOverrideEqualsAndHashIfNeeded(env.tree.pos(), c); 5617 chk.checkFunctionalInterface((JCClassDecl) env.tree, c); 5618 chk.checkLeaksNotAccessible(env, (JCClassDecl) env.tree); 5619 5620 if (c.isImplicit()) { 5621 chk.checkHasMain(env.tree.pos(), c); 5622 } 5623 } finally { 5624 env.info.returnResult = prevReturnRes; 5625 log.useSource(prev); 5626 chk.setLint(prevLint); 5627 } 5628 5629 } 5630 } 5631 5632 public void visitImport(JCImport tree) { 5633 // nothing to do 5634 } 5635 5636 public void visitModuleDef(JCModuleDecl tree) { 5637 tree.sym.completeUsesProvides(); 5638 ModuleSymbol msym = tree.sym; 5639 Lint lint = env.outer.info.lint = env.outer.info.lint.augment(msym); 5640 Lint prevLint = chk.setLint(lint); 5641 chk.checkModuleName(tree); 5642 chk.checkDeprecatedAnnotation(tree, msym); 5643 5644 try { 5645 deferredLintHandler.flush(tree.pos(), lint); 5646 } finally { 5647 chk.setLint(prevLint); 5648 } 5649 } 5650 5651 /** Finish the attribution of a class. */ 5652 private void attribClassBody(Env<AttrContext> env, ClassSymbol c) { 5653 JCClassDecl tree = (JCClassDecl)env.tree; 5654 Assert.check(c == tree.sym); 5655 5656 // Validate type parameters, supertype and interfaces. 5657 attribStats(tree.typarams, env); 5658 if (!c.isAnonymous()) { 5659 //already checked if anonymous 5660 chk.validate(tree.typarams, env); 5661 chk.validate(tree.extending, env); 5662 chk.validate(tree.implementing, env); 5663 } 5664 5665 c.markAbstractIfNeeded(types); 5666 5667 // If this is a non-abstract class, check that it has no abstract 5668 // methods or unimplemented methods of an implemented interface. 5669 if ((c.flags() & (ABSTRACT | INTERFACE)) == 0) { 5670 chk.checkAllDefined(tree.pos(), c); 5671 } 5672 5673 if ((c.flags() & ANNOTATION) != 0) { 5674 if (tree.implementing.nonEmpty()) 5675 log.error(tree.implementing.head.pos(), 5676 Errors.CantExtendIntfAnnotation); 5677 if (tree.typarams.nonEmpty()) { 5678 log.error(tree.typarams.head.pos(), 5679 Errors.IntfAnnotationCantHaveTypeParams(c)); 5680 } 5681 5682 // If this annotation type has a @Repeatable, validate 5683 Attribute.Compound repeatable = c.getAnnotationTypeMetadata().getRepeatable(); 5684 // If this annotation type has a @Repeatable, validate 5685 if (repeatable != null) { 5686 // get diagnostic position for error reporting 5687 DiagnosticPosition cbPos = getDiagnosticPosition(tree, repeatable.type); 5688 Assert.checkNonNull(cbPos); 5689 5690 chk.validateRepeatable(c, repeatable, cbPos); 5691 } 5692 } else { 5693 // Check that all extended classes and interfaces 5694 // are compatible (i.e. no two define methods with same arguments 5695 // yet different return types). (JLS 8.4.8.3) 5696 chk.checkCompatibleSupertypes(tree.pos(), c.type); 5697 chk.checkDefaultMethodClashes(tree.pos(), c.type); 5698 chk.checkPotentiallyAmbiguousOverloads(tree, c.type); 5699 } 5700 5701 // Check that class does not import the same parameterized interface 5702 // with two different argument lists. 5703 chk.checkClassBounds(tree.pos(), c.type); 5704 5705 tree.type = c.type; 5706 5707 for (List<JCTypeParameter> l = tree.typarams; 5708 l.nonEmpty(); l = l.tail) { 5709 Assert.checkNonNull(env.info.scope.findFirst(l.head.name)); 5710 } 5711 5712 // Check that a generic class doesn't extend Throwable 5713 if (!c.type.allparams().isEmpty() && types.isSubtype(c.type, syms.throwableType)) 5714 log.error(tree.extending.pos(), Errors.GenericThrowable); 5715 5716 // Check that all methods which implement some 5717 // method conform to the method they implement. 5718 chk.checkImplementations(tree); 5719 5720 //check that a resource implementing AutoCloseable cannot throw InterruptedException 5721 checkAutoCloseable(tree.pos(), env, c.type); 5722 5723 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) { 5724 // Attribute declaration 5725 attribStat(l.head, env); 5726 // Check that declarations in inner classes are not static (JLS 8.1.2) 5727 // Make an exception for static constants. 5728 if (!allowRecords && 5729 c.owner.kind != PCK && 5730 ((c.flags() & STATIC) == 0 || c.name == names.empty) && 5731 (TreeInfo.flags(l.head) & (STATIC | INTERFACE)) != 0) { 5732 VarSymbol sym = null; 5733 if (l.head.hasTag(VARDEF)) sym = ((JCVariableDecl) l.head).sym; 5734 if (sym == null || 5735 sym.kind != VAR || 5736 sym.getConstValue() == null) 5737 log.error(l.head.pos(), Errors.IclsCantHaveStaticDecl(c)); 5738 } 5739 } 5740 5741 // Check for proper placement of super()/this() calls. 5742 chk.checkSuperInitCalls(tree); 5743 5744 // Check for cycles among non-initial constructors. 5745 chk.checkCyclicConstructors(tree); 5746 5747 // Check for cycles among annotation elements. 5748 chk.checkNonCyclicElements(tree); 5749 5750 // Check for proper use of serialVersionUID and other 5751 // serialization-related fields and methods 5752 if (env.info.lint.isEnabled(LintCategory.SERIAL) 5753 && rs.isSerializable(c.type) 5754 && !c.isAnonymous()) { 5755 chk.checkSerialStructure(tree, c); 5756 } 5757 // Correctly organize the positions of the type annotations 5758 typeAnnotations.organizeTypeAnnotationsBodies(tree); 5759 5760 // Check type annotations applicability rules 5761 validateTypeAnnotations(tree, false); 5762 } 5763 // where 5764 /** get a diagnostic position for an attribute of Type t, or null if attribute missing */ 5765 private DiagnosticPosition getDiagnosticPosition(JCClassDecl tree, Type t) { 5766 for(List<JCAnnotation> al = tree.mods.annotations; !al.isEmpty(); al = al.tail) { 5767 if (types.isSameType(al.head.annotationType.type, t)) 5768 return al.head.pos(); 5769 } 5770 5771 return null; 5772 } 5773 5774 private Type capture(Type type) { 5775 return types.capture(type); 5776 } 5777 5778 private void setSyntheticVariableType(JCVariableDecl tree, Type type) { 5779 if (type.isErroneous()) { 5780 tree.vartype = make.at(Position.NOPOS).Erroneous(); 5781 } else { 5782 tree.vartype = make.at(Position.NOPOS).Type(type); 5783 } 5784 } 5785 5786 public void validateTypeAnnotations(JCTree tree, boolean sigOnly) { 5787 tree.accept(new TypeAnnotationsValidator(sigOnly)); 5788 } 5789 //where 5790 private final class TypeAnnotationsValidator extends TreeScanner { 5791 5792 private final boolean sigOnly; 5793 public TypeAnnotationsValidator(boolean sigOnly) { 5794 this.sigOnly = sigOnly; 5795 } 5796 5797 public void visitAnnotation(JCAnnotation tree) { 5798 chk.validateTypeAnnotation(tree, null, false); 5799 super.visitAnnotation(tree); 5800 } 5801 public void visitAnnotatedType(JCAnnotatedType tree) { 5802 if (!tree.underlyingType.type.isErroneous()) { 5803 super.visitAnnotatedType(tree); 5804 } 5805 } 5806 public void visitTypeParameter(JCTypeParameter tree) { 5807 chk.validateTypeAnnotations(tree.annotations, tree.type.tsym, true); 5808 scan(tree.bounds); 5809 // Don't call super. 5810 // This is needed because above we call validateTypeAnnotation with 5811 // false, which would forbid annotations on type parameters. 5812 // super.visitTypeParameter(tree); 5813 } 5814 public void visitMethodDef(JCMethodDecl tree) { 5815 if (tree.recvparam != null && 5816 !tree.recvparam.vartype.type.isErroneous()) { 5817 checkForDeclarationAnnotations(tree.recvparam.mods.annotations, tree.recvparam.sym); 5818 } 5819 if (tree.restype != null && tree.restype.type != null) { 5820 validateAnnotatedType(tree.restype, tree.restype.type); 5821 } 5822 if (sigOnly) { 5823 scan(tree.mods); 5824 scan(tree.restype); 5825 scan(tree.typarams); 5826 scan(tree.recvparam); 5827 scan(tree.params); 5828 scan(tree.thrown); 5829 } else { 5830 scan(tree.defaultValue); 5831 scan(tree.body); 5832 } 5833 } 5834 public void visitVarDef(final JCVariableDecl tree) { 5835 //System.err.println("validateTypeAnnotations.visitVarDef " + tree); 5836 if (tree.sym != null && tree.sym.type != null && !tree.isImplicitlyTyped()) 5837 validateAnnotatedType(tree.vartype, tree.sym.type); 5838 scan(tree.mods); 5839 scan(tree.vartype); 5840 if (!sigOnly) { 5841 scan(tree.init); 5842 } 5843 } 5844 public void visitTypeCast(JCTypeCast tree) { 5845 if (tree.clazz != null && tree.clazz.type != null) 5846 validateAnnotatedType(tree.clazz, tree.clazz.type); 5847 super.visitTypeCast(tree); 5848 } 5849 public void visitTypeTest(JCInstanceOf tree) { 5850 if (tree.pattern != null && !(tree.pattern instanceof JCPattern) && tree.pattern.type != null) 5851 validateAnnotatedType(tree.pattern, tree.pattern.type); 5852 super.visitTypeTest(tree); 5853 } 5854 public void visitNewClass(JCNewClass tree) { 5855 if (tree.clazz != null && tree.clazz.type != null) { 5856 if (tree.clazz.hasTag(ANNOTATED_TYPE)) { 5857 checkForDeclarationAnnotations(((JCAnnotatedType) tree.clazz).annotations, 5858 tree.clazz.type.tsym); 5859 } 5860 if (tree.def != null) { 5861 checkForDeclarationAnnotations(tree.def.mods.annotations, tree.clazz.type.tsym); 5862 } 5863 5864 validateAnnotatedType(tree.clazz, tree.clazz.type); 5865 } 5866 super.visitNewClass(tree); 5867 } 5868 public void visitNewArray(JCNewArray tree) { 5869 if (tree.elemtype != null && tree.elemtype.type != null) { 5870 if (tree.elemtype.hasTag(ANNOTATED_TYPE)) { 5871 checkForDeclarationAnnotations(((JCAnnotatedType) tree.elemtype).annotations, 5872 tree.elemtype.type.tsym); 5873 } 5874 validateAnnotatedType(tree.elemtype, tree.elemtype.type); 5875 } 5876 super.visitNewArray(tree); 5877 } 5878 public void visitClassDef(JCClassDecl tree) { 5879 //System.err.println("validateTypeAnnotations.visitClassDef " + tree); 5880 if (sigOnly) { 5881 scan(tree.mods); 5882 scan(tree.typarams); 5883 scan(tree.extending); 5884 scan(tree.implementing); 5885 } 5886 for (JCTree member : tree.defs) { 5887 if (member.hasTag(Tag.CLASSDEF)) { 5888 continue; 5889 } 5890 scan(member); 5891 } 5892 } 5893 public void visitBlock(JCBlock tree) { 5894 if (!sigOnly) { 5895 scan(tree.stats); 5896 } 5897 } 5898 5899 /* I would want to model this after 5900 * com.sun.tools.javac.comp.Check.Validator.visitSelectInternal(JCFieldAccess) 5901 * and override visitSelect and visitTypeApply. 5902 * However, we only set the annotated type in the top-level type 5903 * of the symbol. 5904 * Therefore, we need to override each individual location where a type 5905 * can occur. 5906 */ 5907 private void validateAnnotatedType(final JCTree errtree, final Type type) { 5908 //System.err.println("Attr.validateAnnotatedType: " + errtree + " type: " + type); 5909 5910 if (type.isPrimitiveOrVoid()) { 5911 return; 5912 } 5913 5914 JCTree enclTr = errtree; 5915 Type enclTy = type; 5916 5917 boolean repeat = true; 5918 while (repeat) { 5919 if (enclTr.hasTag(TYPEAPPLY)) { 5920 List<Type> tyargs = enclTy.getTypeArguments(); 5921 List<JCExpression> trargs = ((JCTypeApply)enclTr).getTypeArguments(); 5922 if (trargs.length() > 0) { 5923 // Nothing to do for diamonds 5924 if (tyargs.length() == trargs.length()) { 5925 for (int i = 0; i < tyargs.length(); ++i) { 5926 validateAnnotatedType(trargs.get(i), tyargs.get(i)); 5927 } 5928 } 5929 // If the lengths don't match, it's either a diamond 5930 // or some nested type that redundantly provides 5931 // type arguments in the tree. 5932 } 5933 5934 // Look at the clazz part of a generic type 5935 enclTr = ((JCTree.JCTypeApply)enclTr).clazz; 5936 } 5937 5938 if (enclTr.hasTag(SELECT)) { 5939 enclTr = ((JCTree.JCFieldAccess)enclTr).getExpression(); 5940 if (enclTy != null && 5941 !enclTy.hasTag(NONE)) { 5942 enclTy = enclTy.getEnclosingType(); 5943 } 5944 } else if (enclTr.hasTag(ANNOTATED_TYPE)) { 5945 JCAnnotatedType at = (JCTree.JCAnnotatedType) enclTr; 5946 if (enclTy == null || enclTy.hasTag(NONE)) { 5947 if (at.getAnnotations().size() == 1) { 5948 log.error(at.underlyingType.pos(), Errors.CantTypeAnnotateScoping1(at.getAnnotations().head.attribute)); 5949 } else { 5950 ListBuffer<Attribute.Compound> comps = new ListBuffer<>(); 5951 for (JCAnnotation an : at.getAnnotations()) { 5952 comps.add(an.attribute); 5953 } 5954 log.error(at.underlyingType.pos(), Errors.CantTypeAnnotateScoping(comps.toList())); 5955 } 5956 repeat = false; 5957 } 5958 enclTr = at.underlyingType; 5959 // enclTy doesn't need to be changed 5960 } else if (enclTr.hasTag(IDENT)) { 5961 repeat = false; 5962 } else if (enclTr.hasTag(JCTree.Tag.WILDCARD)) { 5963 JCWildcard wc = (JCWildcard) enclTr; 5964 if (wc.getKind() == JCTree.Kind.EXTENDS_WILDCARD || 5965 wc.getKind() == JCTree.Kind.SUPER_WILDCARD) { 5966 validateAnnotatedType(wc.getBound(), wc.getBound().type); 5967 } else { 5968 // Nothing to do for UNBOUND 5969 } 5970 repeat = false; 5971 } else if (enclTr.hasTag(TYPEARRAY)) { 5972 JCArrayTypeTree art = (JCArrayTypeTree) enclTr; 5973 validateAnnotatedType(art.getType(), art.elemtype.type); 5974 repeat = false; 5975 } else if (enclTr.hasTag(TYPEUNION)) { 5976 JCTypeUnion ut = (JCTypeUnion) enclTr; 5977 for (JCTree t : ut.getTypeAlternatives()) { 5978 validateAnnotatedType(t, t.type); 5979 } 5980 repeat = false; 5981 } else if (enclTr.hasTag(TYPEINTERSECTION)) { 5982 JCTypeIntersection it = (JCTypeIntersection) enclTr; 5983 for (JCTree t : it.getBounds()) { 5984 validateAnnotatedType(t, t.type); 5985 } 5986 repeat = false; 5987 } else if (enclTr.getKind() == JCTree.Kind.PRIMITIVE_TYPE || 5988 enclTr.getKind() == JCTree.Kind.ERRONEOUS) { 5989 repeat = false; 5990 } else { 5991 Assert.error("Unexpected tree: " + enclTr + " with kind: " + enclTr.getKind() + 5992 " within: "+ errtree + " with kind: " + errtree.getKind()); 5993 } 5994 } 5995 } 5996 5997 private void checkForDeclarationAnnotations(List<? extends JCAnnotation> annotations, 5998 Symbol sym) { 5999 // Ensure that no declaration annotations are present. 6000 // Note that a tree type might be an AnnotatedType with 6001 // empty annotations, if only declaration annotations were given. 6002 // This method will raise an error for such a type. 6003 for (JCAnnotation ai : annotations) { 6004 if (!ai.type.isErroneous() && 6005 typeAnnotations.annotationTargetType(ai, ai.attribute, sym) == TypeAnnotations.AnnotationType.DECLARATION) { 6006 log.error(ai.pos(), Errors.AnnotationTypeNotApplicableToType(ai.type)); 6007 } 6008 } 6009 } 6010 } 6011 6012 // <editor-fold desc="post-attribution visitor"> 6013 6014 /** 6015 * Handle missing types/symbols in an AST. This routine is useful when 6016 * the compiler has encountered some errors (which might have ended up 6017 * terminating attribution abruptly); if the compiler is used in fail-over 6018 * mode (e.g. by an IDE) and the AST contains semantic errors, this routine 6019 * prevents NPE to be propagated during subsequent compilation steps. 6020 */ 6021 public void postAttr(JCTree tree) { 6022 new PostAttrAnalyzer().scan(tree); 6023 } 6024 6025 class PostAttrAnalyzer extends TreeScanner { 6026 6027 private void initTypeIfNeeded(JCTree that) { 6028 if (that.type == null) { 6029 if (that.hasTag(METHODDEF)) { 6030 that.type = dummyMethodType((JCMethodDecl)that); 6031 } else { 6032 that.type = syms.unknownType; 6033 } 6034 } 6035 } 6036 6037 /* Construct a dummy method type. If we have a method declaration, 6038 * and the declared return type is void, then use that return type 6039 * instead of UNKNOWN to avoid spurious error messages in lambda 6040 * bodies (see:JDK-8041704). 6041 */ 6042 private Type dummyMethodType(JCMethodDecl md) { 6043 Type restype = syms.unknownType; 6044 if (md != null && md.restype != null && md.restype.hasTag(TYPEIDENT)) { 6045 JCPrimitiveTypeTree prim = (JCPrimitiveTypeTree)md.restype; 6046 if (prim.typetag == VOID) 6047 restype = syms.voidType; 6048 } 6049 return new MethodType(List.nil(), restype, 6050 List.nil(), syms.methodClass); 6051 } 6052 private Type dummyMethodType() { 6053 return dummyMethodType(null); 6054 } 6055 6056 @Override 6057 public void scan(JCTree tree) { 6058 if (tree == null) return; 6059 if (tree instanceof JCExpression) { 6060 initTypeIfNeeded(tree); 6061 } 6062 super.scan(tree); 6063 } 6064 6065 @Override 6066 public void visitIdent(JCIdent that) { 6067 if (that.sym == null) { 6068 that.sym = syms.unknownSymbol; 6069 } 6070 } 6071 6072 @Override 6073 public void visitSelect(JCFieldAccess that) { 6074 if (that.sym == null) { 6075 that.sym = syms.unknownSymbol; 6076 } 6077 super.visitSelect(that); 6078 } 6079 6080 @Override 6081 public void visitClassDef(JCClassDecl that) { 6082 initTypeIfNeeded(that); 6083 if (that.sym == null) { 6084 that.sym = new ClassSymbol(0, that.name, that.type, syms.noSymbol); 6085 } 6086 super.visitClassDef(that); 6087 } 6088 6089 @Override 6090 public void visitMethodDef(JCMethodDecl that) { 6091 initTypeIfNeeded(that); 6092 if (that.sym == null) { 6093 that.sym = new MethodSymbol(0, that.name, that.type, syms.noSymbol); 6094 } 6095 super.visitMethodDef(that); 6096 } 6097 6098 @Override 6099 public void visitVarDef(JCVariableDecl that) { 6100 initTypeIfNeeded(that); 6101 if (that.sym == null) { 6102 that.sym = new VarSymbol(0, that.name, that.type, syms.noSymbol); 6103 that.sym.adr = 0; 6104 } 6105 if (that.vartype == null) { 6106 that.vartype = make.at(Position.NOPOS).Erroneous(); 6107 } 6108 super.visitVarDef(that); 6109 } 6110 6111 @Override 6112 public void visitBindingPattern(JCBindingPattern that) { 6113 initTypeIfNeeded(that); 6114 initTypeIfNeeded(that.var); 6115 if (that.var.sym == null) { 6116 that.var.sym = new BindingSymbol(0, that.var.name, that.var.type, syms.noSymbol); 6117 that.var.sym.adr = 0; 6118 } 6119 super.visitBindingPattern(that); 6120 } 6121 6122 @Override 6123 public void visitNewClass(JCNewClass that) { 6124 if (that.constructor == null) { 6125 that.constructor = new MethodSymbol(0, names.init, 6126 dummyMethodType(), syms.noSymbol); 6127 } 6128 if (that.constructorType == null) { 6129 that.constructorType = syms.unknownType; 6130 } 6131 super.visitNewClass(that); 6132 } 6133 6134 @Override 6135 public void visitAssignop(JCAssignOp that) { 6136 if (that.operator == null) { 6137 that.operator = new OperatorSymbol(names.empty, dummyMethodType(), 6138 -1, syms.noSymbol); 6139 } 6140 super.visitAssignop(that); 6141 } 6142 6143 @Override 6144 public void visitBinary(JCBinary that) { 6145 if (that.operator == null) { 6146 that.operator = new OperatorSymbol(names.empty, dummyMethodType(), 6147 -1, syms.noSymbol); 6148 } 6149 super.visitBinary(that); 6150 } 6151 6152 @Override 6153 public void visitUnary(JCUnary that) { 6154 if (that.operator == null) { 6155 that.operator = new OperatorSymbol(names.empty, dummyMethodType(), 6156 -1, syms.noSymbol); 6157 } 6158 super.visitUnary(that); 6159 } 6160 6161 @Override 6162 public void visitReference(JCMemberReference that) { 6163 super.visitReference(that); 6164 if (that.sym == null) { 6165 that.sym = new MethodSymbol(0, names.empty, dummyMethodType(), 6166 syms.noSymbol); 6167 } 6168 } 6169 } 6170 // </editor-fold> 6171 6172 public void setPackageSymbols(JCExpression pid, Symbol pkg) { 6173 new TreeScanner() { 6174 Symbol packge = pkg; 6175 @Override 6176 public void visitIdent(JCIdent that) { 6177 that.sym = packge; 6178 } 6179 6180 @Override 6181 public void visitSelect(JCFieldAccess that) { 6182 that.sym = packge; 6183 packge = packge.owner; 6184 super.visitSelect(that); 6185 } 6186 }.scan(pid); 6187 } 6188 6189 }