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