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