1 /*
   2  * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.comp;
  27 
  28 import java.util.*;
  29 import java.util.function.BiConsumer;
  30 import java.util.function.BiPredicate;
  31 import java.util.function.Predicate;
  32 import java.util.function.Supplier;
  33 import java.util.function.ToIntBiFunction;
  34 import java.util.stream.Collectors;
  35 import java.util.stream.StreamSupport;
  36 
  37 import javax.lang.model.element.ElementKind;
  38 import javax.lang.model.element.NestingKind;
  39 import javax.tools.JavaFileManager;
  40 
  41 import com.sun.source.tree.CaseTree;
  42 import com.sun.tools.javac.code.*;
  43 import com.sun.tools.javac.code.Attribute.Compound;
  44 import com.sun.tools.javac.code.Directive.ExportsDirective;
  45 import com.sun.tools.javac.code.Directive.RequiresDirective;
  46 import com.sun.tools.javac.code.Source.Feature;
  47 import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
  48 import com.sun.tools.javac.jvm.*;
  49 import com.sun.tools.javac.resources.CompilerProperties.Errors;
  50 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  51 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  52 import com.sun.tools.javac.resources.CompilerProperties.LintWarnings;
  53 import com.sun.tools.javac.tree.*;
  54 import com.sun.tools.javac.util.*;
  55 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
  56 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  57 import com.sun.tools.javac.util.JCDiagnostic.Error;
  58 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
  59 import com.sun.tools.javac.util.JCDiagnostic.LintWarning;
  60 import com.sun.tools.javac.util.List;
  61 
  62 import com.sun.tools.javac.code.Lint;
  63 import com.sun.tools.javac.code.Lint.LintCategory;
  64 import com.sun.tools.javac.code.Scope.WriteableScope;
  65 import com.sun.tools.javac.code.Type.*;
  66 import com.sun.tools.javac.code.Symbol.*;
  67 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
  68 import com.sun.tools.javac.tree.JCTree.*;
  69 
  70 import static com.sun.tools.javac.code.Flags.*;
  71 import static com.sun.tools.javac.code.Flags.ANNOTATION;
  72 import static com.sun.tools.javac.code.Flags.SYNCHRONIZED;
  73 import static com.sun.tools.javac.code.Kinds.*;
  74 import static com.sun.tools.javac.code.Kinds.Kind.*;
  75 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
  76 import static com.sun.tools.javac.code.Scope.LookupKind.RECURSIVE;
  77 import static com.sun.tools.javac.code.TypeTag.*;
  78 import static com.sun.tools.javac.code.TypeTag.WILDCARD;
  79 
  80 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  81 import javax.lang.model.element.Element;
  82 import javax.lang.model.element.TypeElement;
  83 import javax.lang.model.type.DeclaredType;
  84 import javax.lang.model.util.ElementKindVisitor14;
  85 
  86 /** Type checking helper class for the attribution phase.
  87  *
  88  *  <p><b>This is NOT part of any supported API.
  89  *  If you write code that depends on this, you do so at your own risk.
  90  *  This code and its internal interfaces are subject to change or
  91  *  deletion without notice.</b>
  92  */
  93 public class Check {
  94     protected static final Context.Key<Check> checkKey = new Context.Key<>();
  95 
  96     // Flag bits indicating which item(s) chosen from a pair of items
  97     private static final int FIRST = 0x01;
  98     private static final int SECOND = 0x02;
  99 
 100     private final Names names;
 101     private final Log log;
 102     private final Resolve rs;
 103     private final Symtab syms;
 104     private final Enter enter;
 105     private final DeferredAttr deferredAttr;
 106     private final Infer infer;
 107     private final Types types;
 108     private final TypeAnnotations typeAnnotations;
 109     private final JCDiagnostic.Factory diags;
 110     private final JavaFileManager fileManager;
 111     private final Source source;
 112     private final Target target;
 113     private final Profile profile;
 114     private final Preview preview;
 115     private final boolean warnOnAnyAccessToMembers;
 116 
 117     public boolean disablePreviewCheck;
 118 
 119     // The set of lint options currently in effect. It is initialized
 120     // from the context, and then is set/reset as needed by Attr as it
 121     // visits all the various parts of the trees during attribution.
 122     Lint lint;
 123 
 124     // The method being analyzed in Attr - it is set/reset as needed by
 125     // Attr as it visits new method declarations.
 126     private MethodSymbol method;
 127 
 128     public static Check instance(Context context) {
 129         Check instance = context.get(checkKey);
 130         if (instance == null)
 131             instance = new Check(context);
 132         return instance;
 133     }
 134 
 135     @SuppressWarnings("this-escape")
 136     protected Check(Context context) {
 137         context.put(checkKey, this);
 138 
 139         names = Names.instance(context);
 140         log = Log.instance(context);
 141         rs = Resolve.instance(context);
 142         syms = Symtab.instance(context);
 143         enter = Enter.instance(context);
 144         deferredAttr = DeferredAttr.instance(context);
 145         infer = Infer.instance(context);
 146         types = Types.instance(context);
 147         typeAnnotations = TypeAnnotations.instance(context);
 148         diags = JCDiagnostic.Factory.instance(context);
 149         Options options = Options.instance(context);
 150         lint = Lint.instance(context);
 151         fileManager = context.get(JavaFileManager.class);
 152 
 153         source = Source.instance(context);
 154         target = Target.instance(context);
 155         warnOnAnyAccessToMembers = options.isSet("warnOnAccessToMembers");
 156 
 157         disablePreviewCheck = false;
 158 
 159         Target target = Target.instance(context);
 160         syntheticNameChar = target.syntheticNameChar();
 161 
 162         profile = Profile.instance(context);
 163         preview = Preview.instance(context);
 164 
 165         boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION);
 166         boolean verboseRemoval = lint.isEnabled(LintCategory.REMOVAL);
 167         boolean verboseUnchecked = lint.isEnabled(LintCategory.UNCHECKED);
 168         boolean enforceMandatoryWarnings = true;
 169 
 170         deprecationHandler = new MandatoryWarningHandler(log, null, verboseDeprecated,
 171                 enforceMandatoryWarnings, LintCategory.DEPRECATION, "deprecated");
 172         removalHandler = new MandatoryWarningHandler(log, null, verboseRemoval,
 173                 enforceMandatoryWarnings, LintCategory.REMOVAL);
 174         uncheckedHandler = new MandatoryWarningHandler(log, null, verboseUnchecked,
 175                 enforceMandatoryWarnings, LintCategory.UNCHECKED);
 176 
 177         deferredLintHandler = DeferredLintHandler.instance(context);
 178 
 179         allowModules = Feature.MODULES.allowedInSource(source);
 180         allowRecords = Feature.RECORDS.allowedInSource(source);
 181         allowSealed = Feature.SEALED_CLASSES.allowedInSource(source);
 182         allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
 183                 Feature.VALUE_CLASSES.allowedInSource(source);
 184     }
 185 
 186     /** Character for synthetic names
 187      */
 188     char syntheticNameChar;
 189 
 190     /** A table mapping flat names of all compiled classes for each module in this run
 191      *  to their symbols; maintained from outside.
 192      */
 193     private Map<Pair<ModuleSymbol, Name>,ClassSymbol> compiled = new HashMap<>();
 194 
 195     /** A handler for messages about deprecated usage.
 196      */
 197     private MandatoryWarningHandler deprecationHandler;
 198 
 199     /** A handler for messages about deprecated-for-removal usage.
 200      */
 201     private MandatoryWarningHandler removalHandler;
 202 
 203     /** A handler for messages about unchecked or unsafe usage.
 204      */
 205     private MandatoryWarningHandler uncheckedHandler;
 206 
 207     /** A handler for deferred lint warnings.
 208      */
 209     private DeferredLintHandler deferredLintHandler;
 210 
 211     /** Are modules allowed
 212      */
 213     private final boolean allowModules;
 214 
 215     /** Are records allowed
 216      */
 217     private final boolean allowRecords;
 218 
 219     /** Are sealed classes allowed
 220      */
 221     private final boolean allowSealed;
 222 
 223     /** Are value classes allowed
 224      */
 225     private final boolean allowValueClasses;
 226 
 227     /** Whether to force suppression of deprecation and preview warnings.
 228      *  This happens when attributing import statements for JDK 9+.
 229      *  @see Feature#DEPRECATION_ON_IMPORT
 230      */
 231     private boolean importSuppression;
 232 
 233 /* *************************************************************************
 234  * Errors and Warnings
 235  **************************************************************************/
 236 
 237     Lint setLint(Lint newLint) {
 238         Lint prev = lint;
 239         lint = newLint;
 240         return prev;
 241     }
 242 
 243     boolean setImportSuppression(boolean newImportSuppression) {
 244         boolean prev = importSuppression;
 245         importSuppression = newImportSuppression;
 246         return prev;
 247     }
 248 
 249     MethodSymbol setMethod(MethodSymbol newMethod) {
 250         MethodSymbol prev = method;
 251         method = newMethod;
 252         return prev;
 253     }
 254 
 255     /** Warn about deprecated symbol.
 256      *  @param pos        Position to be used for error reporting.
 257      *  @param sym        The deprecated symbol.
 258      */
 259     void warnDeprecated(DiagnosticPosition pos, Symbol sym) {
 260         if (sym.isDeprecatedForRemoval()) {
 261             if (!lint.isSuppressed(LintCategory.REMOVAL)) {
 262                 if (sym.kind == MDL) {
 263                     removalHandler.report(pos, LintWarnings.HasBeenDeprecatedForRemovalModule(sym));
 264                 } else {
 265                     removalHandler.report(pos, LintWarnings.HasBeenDeprecatedForRemoval(sym, sym.location()));
 266                 }
 267             }
 268         } else if (!lint.isSuppressed(LintCategory.DEPRECATION)) {
 269             if (sym.kind == MDL) {
 270                 deprecationHandler.report(pos, LintWarnings.HasBeenDeprecatedModule(sym));
 271             } else {
 272                 deprecationHandler.report(pos, LintWarnings.HasBeenDeprecated(sym, sym.location()));
 273             }
 274         }
 275     }
 276 
 277     /** Log a preview warning.
 278      *  @param pos        Position to be used for error reporting.
 279      *  @param msg        A Warning describing the problem.
 280      */
 281     public void warnPreviewAPI(DiagnosticPosition pos, LintWarning warnKey) {
 282         if (!importSuppression && !lint.isSuppressed(LintCategory.PREVIEW))
 283             preview.reportPreviewWarning(pos, warnKey);
 284     }
 285 
 286     /** Log a preview warning.
 287      *  @param pos        Position to be used for error reporting.
 288      *  @param msg        A Warning describing the problem.
 289      */
 290     public void warnRestrictedAPI(DiagnosticPosition pos, Symbol sym) {
 291         lint.logIfEnabled(pos, LintWarnings.RestrictedMethod(sym.enclClass(), sym));
 292     }
 293 
 294     /** Warn about unchecked operation.
 295      *  @param pos        Position to be used for error reporting.
 296      *  @param msg        A string describing the problem.
 297      */
 298     public void warnUnchecked(DiagnosticPosition pos, LintWarning warnKey) {
 299         if (!lint.isSuppressed(LintCategory.UNCHECKED))
 300             uncheckedHandler.report(pos, warnKey);
 301     }
 302 
 303     /**
 304      * Report any deferred diagnostics.
 305      */
 306     public void reportDeferredDiagnostics() {
 307         deprecationHandler.reportDeferredDiagnostic();
 308         removalHandler.reportDeferredDiagnostic();
 309         uncheckedHandler.reportDeferredDiagnostic();
 310     }
 311 
 312 
 313     /** Report a failure to complete a class.
 314      *  @param pos        Position to be used for error reporting.
 315      *  @param ex         The failure to report.
 316      */
 317     public Type completionError(DiagnosticPosition pos, CompletionFailure ex) {
 318         log.error(JCDiagnostic.DiagnosticFlag.NON_DEFERRABLE, pos, Errors.CantAccess(ex.sym, ex.getDetailValue()));
 319         return syms.errType;
 320     }
 321 
 322     /** Report an error that wrong type tag was found.
 323      *  @param pos        Position to be used for error reporting.
 324      *  @param required   An internationalized string describing the type tag
 325      *                    required.
 326      *  @param found      The type that was found.
 327      */
 328     Type typeTagError(DiagnosticPosition pos, JCDiagnostic required, Object found) {
 329         // this error used to be raised by the parser,
 330         // but has been delayed to this point:
 331         if (found instanceof Type type && type.hasTag(VOID)) {
 332             log.error(pos, Errors.IllegalStartOfType);
 333             return syms.errType;
 334         }
 335         log.error(pos, Errors.TypeFoundReq(found, required));
 336         return types.createErrorType(found instanceof Type type ? type : syms.errType);
 337     }
 338 
 339     /** Report duplicate declaration error.
 340      */
 341     void duplicateError(DiagnosticPosition pos, Symbol sym) {
 342         if (!sym.type.isErroneous()) {
 343             Symbol location = sym.location();
 344             if (location.kind == MTH &&
 345                     ((MethodSymbol)location).isStaticOrInstanceInit()) {
 346                 log.error(pos,
 347                           Errors.AlreadyDefinedInClinit(kindName(sym),
 348                                                         sym,
 349                                                         kindName(sym.location()),
 350                                                         kindName(sym.location().enclClass()),
 351                                                         sym.location().enclClass()));
 352             } else {
 353                 /* dont error if this is a duplicated parameter of a generated canonical constructor
 354                  * as we should have issued an error for the duplicated fields
 355                  */
 356                 if (location.kind != MTH ||
 357                         ((sym.owner.flags_field & GENERATEDCONSTR) == 0) ||
 358                         ((sym.owner.flags_field & RECORD) == 0)) {
 359                     log.error(pos,
 360                             Errors.AlreadyDefined(kindName(sym),
 361                                     sym,
 362                                     kindName(sym.location()),
 363                                     sym.location()));
 364                 }
 365             }
 366         }
 367     }
 368 
 369     /** Report array/varargs duplicate declaration
 370      */
 371     void varargsDuplicateError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) {
 372         if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) {
 373             log.error(pos, Errors.ArrayAndVarargs(sym1, sym2, sym2.location()));
 374         }
 375     }
 376 
 377 /* ************************************************************************
 378  * duplicate declaration checking
 379  *************************************************************************/
 380 
 381     /** Check that variable does not hide variable with same name in
 382      *  immediately enclosing local scope.
 383      *  @param pos           Position for error reporting.
 384      *  @param v             The symbol.
 385      *  @param s             The scope.
 386      */
 387     void checkTransparentVar(DiagnosticPosition pos, VarSymbol v, Scope s) {
 388         for (Symbol sym : s.getSymbolsByName(v.name)) {
 389             if (sym.owner != v.owner) break;
 390             if (sym.kind == VAR &&
 391                 sym.owner.kind.matches(KindSelector.VAL_MTH) &&
 392                 v.name != names.error) {
 393                 duplicateError(pos, sym);
 394                 return;
 395             }
 396         }
 397     }
 398 
 399     /** Check that a class or interface does not hide a class or
 400      *  interface with same name in immediately enclosing local scope.
 401      *  @param pos           Position for error reporting.
 402      *  @param c             The symbol.
 403      *  @param s             The scope.
 404      */
 405     void checkTransparentClass(DiagnosticPosition pos, ClassSymbol c, Scope s) {
 406         for (Symbol sym : s.getSymbolsByName(c.name)) {
 407             if (sym.owner != c.owner) break;
 408             if (sym.kind == TYP && !sym.type.hasTag(TYPEVAR) &&
 409                 sym.owner.kind.matches(KindSelector.VAL_MTH) &&
 410                 c.name != names.error) {
 411                 duplicateError(pos, sym);
 412                 return;
 413             }
 414         }
 415     }
 416 
 417     /** Check that class does not have the same name as one of
 418      *  its enclosing classes, or as a class defined in its enclosing scope.
 419      *  return true if class is unique in its enclosing scope.
 420      *  @param pos           Position for error reporting.
 421      *  @param name          The class name.
 422      *  @param s             The enclosing scope.
 423      */
 424     boolean checkUniqueClassName(DiagnosticPosition pos, Name name, Scope s) {
 425         for (Symbol sym : s.getSymbolsByName(name, NON_RECURSIVE)) {
 426             if (sym.kind == TYP && sym.name != names.error) {
 427                 duplicateError(pos, sym);
 428                 return false;
 429             }
 430         }
 431         for (Symbol sym = s.owner; sym != null; sym = sym.owner) {
 432             if (sym.kind == TYP && sym.name == name && sym.name != names.error &&
 433                     !sym.isImplicit()) {
 434                 duplicateError(pos, sym);
 435                 return true;
 436             }
 437         }
 438         return true;
 439     }
 440 
 441 /* *************************************************************************
 442  * Class name generation
 443  **************************************************************************/
 444 
 445 
 446     private Map<Pair<Name, Name>, Integer> localClassNameIndexes = new HashMap<>();
 447 
 448     /** Return name of local class.
 449      *  This is of the form   {@code <enclClass> $ n <classname> }
 450      *  where
 451      *    enclClass is the flat name of the enclosing class,
 452      *    classname is the simple name of the local class
 453      */
 454     public Name localClassName(ClassSymbol c) {
 455         Name enclFlatname = c.owner.enclClass().flatname;
 456         String enclFlatnameStr = enclFlatname.toString();
 457         Pair<Name, Name> key = new Pair<>(enclFlatname, c.name);
 458         Integer index = localClassNameIndexes.get(key);
 459         for (int i = (index == null) ? 1 : index; ; i++) {
 460             Name flatname = names.fromString(enclFlatnameStr
 461                     + syntheticNameChar + i + c.name);
 462             if (getCompiled(c.packge().modle, flatname) == null) {
 463                 localClassNameIndexes.put(key, i + 1);
 464                 return flatname;
 465             }
 466         }
 467     }
 468 
 469     public void clearLocalClassNameIndexes(ClassSymbol c) {
 470         if (c.owner != null && c.owner.kind != NIL) {
 471             localClassNameIndexes.remove(new Pair<>(
 472                     c.owner.enclClass().flatname, c.name));
 473         }
 474     }
 475 
 476     public void newRound() {
 477         compiled.clear();
 478         localClassNameIndexes.clear();
 479     }
 480 
 481     public void clear() {
 482         deprecationHandler.clear();
 483         removalHandler.clear();
 484         uncheckedHandler.clear();
 485     }
 486 
 487     public void putCompiled(ClassSymbol csym) {
 488         compiled.put(Pair.of(csym.packge().modle, csym.flatname), csym);
 489     }
 490 
 491     public ClassSymbol getCompiled(ClassSymbol csym) {
 492         return compiled.get(Pair.of(csym.packge().modle, csym.flatname));
 493     }
 494 
 495     public ClassSymbol getCompiled(ModuleSymbol msym, Name flatname) {
 496         return compiled.get(Pair.of(msym, flatname));
 497     }
 498 
 499     public void removeCompiled(ClassSymbol csym) {
 500         compiled.remove(Pair.of(csym.packge().modle, csym.flatname));
 501     }
 502 
 503 /* *************************************************************************
 504  * Type Checking
 505  **************************************************************************/
 506 
 507     /**
 508      * A check context is an object that can be used to perform compatibility
 509      * checks - depending on the check context, meaning of 'compatibility' might
 510      * vary significantly.
 511      */
 512     public interface CheckContext {
 513         /**
 514          * Is type 'found' compatible with type 'req' in given context
 515          */
 516         boolean compatible(Type found, Type req, Warner warn);
 517         /**
 518          * Report a check error
 519          */
 520         void report(DiagnosticPosition pos, JCDiagnostic details);
 521         /**
 522          * Obtain a warner for this check context
 523          */
 524         public Warner checkWarner(DiagnosticPosition pos, Type found, Type req);
 525 
 526         public InferenceContext inferenceContext();
 527 
 528         public DeferredAttr.DeferredAttrContext deferredAttrContext();
 529     }
 530 
 531     /**
 532      * This class represent a check context that is nested within another check
 533      * context - useful to check sub-expressions. The default behavior simply
 534      * redirects all method calls to the enclosing check context leveraging
 535      * the forwarding pattern.
 536      */
 537     static class NestedCheckContext implements CheckContext {
 538         CheckContext enclosingContext;
 539 
 540         NestedCheckContext(CheckContext enclosingContext) {
 541             this.enclosingContext = enclosingContext;
 542         }
 543 
 544         public boolean compatible(Type found, Type req, Warner warn) {
 545             return enclosingContext.compatible(found, req, warn);
 546         }
 547 
 548         public void report(DiagnosticPosition pos, JCDiagnostic details) {
 549             enclosingContext.report(pos, details);
 550         }
 551 
 552         public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
 553             return enclosingContext.checkWarner(pos, found, req);
 554         }
 555 
 556         public InferenceContext inferenceContext() {
 557             return enclosingContext.inferenceContext();
 558         }
 559 
 560         public DeferredAttrContext deferredAttrContext() {
 561             return enclosingContext.deferredAttrContext();
 562         }
 563     }
 564 
 565     /**
 566      * Check context to be used when evaluating assignment/return statements
 567      */
 568     CheckContext basicHandler = new CheckContext() {
 569         public void report(DiagnosticPosition pos, JCDiagnostic details) {
 570             log.error(pos, Errors.ProbFoundReq(details));
 571         }
 572         public boolean compatible(Type found, Type req, Warner warn) {
 573             return types.isAssignable(found, req, warn);
 574         }
 575 
 576         public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
 577             return convertWarner(pos, found, req);
 578         }
 579 
 580         public InferenceContext inferenceContext() {
 581             return infer.emptyContext;
 582         }
 583 
 584         public DeferredAttrContext deferredAttrContext() {
 585             return deferredAttr.emptyDeferredAttrContext;
 586         }
 587 
 588         @Override
 589         public String toString() {
 590             return "CheckContext: basicHandler";
 591         }
 592     };
 593 
 594     /** Check that a given type is assignable to a given proto-type.
 595      *  If it is, return the type, otherwise return errType.
 596      *  @param pos        Position to be used for error reporting.
 597      *  @param found      The type that was found.
 598      *  @param req        The type that was required.
 599      */
 600     public Type checkType(DiagnosticPosition pos, Type found, Type req) {
 601         return checkType(pos, found, req, basicHandler);
 602     }
 603 
 604     Type checkType(final DiagnosticPosition pos, final Type found, final Type req, final CheckContext checkContext) {
 605         final InferenceContext inferenceContext = checkContext.inferenceContext();
 606         if (inferenceContext.free(req) || inferenceContext.free(found)) {
 607             inferenceContext.addFreeTypeListener(List.of(req, found),
 608                     solvedContext -> checkType(pos, solvedContext.asInstType(found), solvedContext.asInstType(req), checkContext));
 609         }
 610         if (req.hasTag(ERROR))
 611             return req;
 612         if (req.hasTag(NONE))
 613             return found;
 614         if (checkContext.compatible(found, req, checkContext.checkWarner(pos, found, req))) {
 615             return found;
 616         } else {
 617             if (found.isNumeric() && req.isNumeric()) {
 618                 checkContext.report(pos, diags.fragment(Fragments.PossibleLossOfPrecision(found, req)));
 619                 return types.createErrorType(found);
 620             }
 621             checkContext.report(pos, diags.fragment(Fragments.InconvertibleTypes(found, req)));
 622             return types.createErrorType(found);
 623         }
 624     }
 625 
 626     /** Check that a given type can be cast to a given target type.
 627      *  Return the result of the cast.
 628      *  @param pos        Position to be used for error reporting.
 629      *  @param found      The type that is being cast.
 630      *  @param req        The target type of the cast.
 631      */
 632     Type checkCastable(DiagnosticPosition pos, Type found, Type req) {
 633         return checkCastable(pos, found, req, basicHandler);
 634     }
 635     Type checkCastable(DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) {
 636         if (types.isCastable(found, req, castWarner(pos, found, req))) {
 637             return req;
 638         } else {
 639             checkContext.report(pos, diags.fragment(Fragments.InconvertibleTypes(found, req)));
 640             return types.createErrorType(found);
 641         }
 642     }
 643 
 644     /** Check for redundant casts (i.e. where source type is a subtype of target type)
 645      * The problem should only be reported for non-292 cast
 646      */
 647     public void checkRedundantCast(Env<AttrContext> env, final JCTypeCast tree) {
 648         if (!tree.type.isErroneous()
 649                 && types.isSameType(tree.expr.type, tree.clazz.type)
 650                 && !(ignoreAnnotatedCasts && TreeInfo.containsTypeAnnotation(tree.clazz))
 651                 && !is292targetTypeCast(tree)) {
 652             deferredLintHandler.report(_l -> {
 653                 lint.logIfEnabled(tree.pos(), LintWarnings.RedundantCast(tree.clazz.type));
 654             });
 655         }
 656     }
 657     //where
 658         private boolean is292targetTypeCast(JCTypeCast tree) {
 659             boolean is292targetTypeCast = false;
 660             JCExpression expr = TreeInfo.skipParens(tree.expr);
 661             if (expr.hasTag(APPLY)) {
 662                 JCMethodInvocation apply = (JCMethodInvocation)expr;
 663                 Symbol sym = TreeInfo.symbol(apply.meth);
 664                 is292targetTypeCast = sym != null &&
 665                     sym.kind == MTH &&
 666                     (sym.flags() & HYPOTHETICAL) != 0;
 667             }
 668             return is292targetTypeCast;
 669         }
 670 
 671         private static final boolean ignoreAnnotatedCasts = true;
 672 
 673     /** Check that a type is within some bounds.
 674      *
 675      *  Used in TypeApply to verify that, e.g., X in {@code V<X>} is a valid
 676      *  type argument.
 677      *  @param a             The type that should be bounded by bs.
 678      *  @param bound         The bound.
 679      */
 680     private boolean checkExtends(Type a, Type bound) {
 681          if (a.isUnbound()) {
 682              return true;
 683          } else if (!a.hasTag(WILDCARD)) {
 684              a = types.cvarUpperBound(a);
 685              return types.isSubtype(a, bound);
 686          } else if (a.isExtendsBound()) {
 687              return types.isCastable(bound, types.wildUpperBound(a), types.noWarnings);
 688          } else if (a.isSuperBound()) {
 689              return !types.notSoftSubtype(types.wildLowerBound(a), bound);
 690          }
 691          return true;
 692      }
 693 
 694     /** Check that type is different from 'void'.
 695      *  @param pos           Position to be used for error reporting.
 696      *  @param t             The type to be checked.
 697      */
 698     Type checkNonVoid(DiagnosticPosition pos, Type t) {
 699         if (t.hasTag(VOID)) {
 700             log.error(pos, Errors.VoidNotAllowedHere);
 701             return types.createErrorType(t);
 702         } else {
 703             return t;
 704         }
 705     }
 706 
 707     Type checkClassOrArrayType(DiagnosticPosition pos, Type t) {
 708         if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) {
 709             return typeTagError(pos,
 710                                 diags.fragment(Fragments.TypeReqClassArray),
 711                                 asTypeParam(t));
 712         } else {
 713             return t;
 714         }
 715     }
 716 
 717     /** Check that type is a class or interface type.
 718      *  @param pos           Position to be used for error reporting.
 719      *  @param t             The type to be checked.
 720      */
 721     Type checkClassType(DiagnosticPosition pos, Type t) {
 722         if (!t.hasTag(CLASS) && !t.hasTag(ERROR)) {
 723             return typeTagError(pos,
 724                                 diags.fragment(Fragments.TypeReqClass),
 725                                 asTypeParam(t));
 726         } else {
 727             return t;
 728         }
 729     }
 730     //where
 731         private Object asTypeParam(Type t) {
 732             return (t.hasTag(TYPEVAR))
 733                                     ? diags.fragment(Fragments.TypeParameter(t))
 734                                     : t;
 735         }
 736 
 737     void checkConstraintsOfValueClass(JCClassDecl tree, ClassSymbol c) {
 738         DiagnosticPosition pos = tree.pos();
 739         for (Type st : types.closure(c.type)) {
 740             if (st == null || st.tsym == null || st.tsym.kind == ERR)
 741                 continue;
 742             if  (st.tsym == syms.objectType.tsym || st.tsym == syms.recordType.tsym || st.isInterface())
 743                 continue;
 744             if (!st.tsym.isAbstract()) {
 745                 if (c != st.tsym) {
 746                     log.error(pos, Errors.ConcreteSupertypeForValueClass(c, st));
 747                 }
 748                 continue;
 749             }
 750             // dealing with an abstract value or value super class below.
 751             for (Symbol s : st.tsym.members().getSymbols(NON_RECURSIVE)) {
 752                 if (s.kind == MTH) {
 753                     if ((s.flags() & (SYNCHRONIZED | STATIC)) == SYNCHRONIZED) {
 754                         log.error(pos, Errors.SuperClassMethodCannotBeSynchronized(s, c, st));
 755                     }
 756                     break;
 757                 }
 758             }
 759         }
 760     }
 761 
 762     /** Check that type is a valid qualifier for a constructor reference expression
 763      */
 764     Type checkConstructorRefType(DiagnosticPosition pos, Type t) {
 765         t = checkClassOrArrayType(pos, t);
 766         if (t.hasTag(CLASS)) {
 767             if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) {
 768                 log.error(pos, Errors.AbstractCantBeInstantiated(t.tsym));
 769                 t = types.createErrorType(t);
 770             } else if ((t.tsym.flags() & ENUM) != 0) {
 771                 log.error(pos, Errors.EnumCantBeInstantiated);
 772                 t = types.createErrorType(t);
 773             } else {
 774                 t = checkClassType(pos, t, true);
 775             }
 776         } else if (t.hasTag(ARRAY)) {
 777             if (!types.isReifiable(((ArrayType)t).elemtype)) {
 778                 log.error(pos, Errors.GenericArrayCreation);
 779                 t = types.createErrorType(t);
 780             }
 781         }
 782         return t;
 783     }
 784 
 785     /** Check that type is a class or interface type.
 786      *  @param pos           Position to be used for error reporting.
 787      *  @param t             The type to be checked.
 788      *  @param noBounds    True if type bounds are illegal here.
 789      */
 790     Type checkClassType(DiagnosticPosition pos, Type t, boolean noBounds) {
 791         t = checkClassType(pos, t);
 792         if (noBounds && t.isParameterized()) {
 793             List<Type> args = t.getTypeArguments();
 794             while (args.nonEmpty()) {
 795                 if (args.head.hasTag(WILDCARD))
 796                     return typeTagError(pos,
 797                                         diags.fragment(Fragments.TypeReqExact),
 798                                         args.head);
 799                 args = args.tail;
 800             }
 801         }
 802         return t;
 803     }
 804 
 805     /** Check that type is a reference type, i.e. a class, interface or array type
 806      *  or a type variable.
 807      *  @param pos           Position to be used for error reporting.
 808      *  @param t             The type to be checked.
 809      */
 810     Type checkRefType(DiagnosticPosition pos, Type t) {
 811         if (t.isReference())
 812             return t;
 813         else
 814             return typeTagError(pos,
 815                                 diags.fragment(Fragments.TypeReqRef),
 816                                 t);
 817     }
 818 
 819     /** Check that type is an identity type, i.e. not a value type.
 820      *  When not discernible statically, give it the benefit of doubt
 821      *  and defer to runtime.
 822      *
 823      *  @param pos           Position to be used for error reporting.
 824      *  @param t             The type to be checked.
 825      */
 826     boolean checkIdentityType(DiagnosticPosition pos, Type t) {
 827         if (t.hasTag(TYPEVAR)) {
 828             t = types.skipTypeVars(t, false);
 829         }
 830         if (t.isIntersection()) {
 831             IntersectionClassType ict = (IntersectionClassType)t;
 832             boolean result = true;
 833             for (Type component : ict.getExplicitComponents()) {
 834                 result &= checkIdentityType(pos, component);
 835             }
 836             return result;
 837         }
 838         if (t.isPrimitive() || (t.isValueClass() && !t.tsym.isAbstract())) {
 839             typeTagError(pos, diags.fragment(Fragments.TypeReqIdentity), t);
 840             return false;
 841         }
 842         return true;
 843     }
 844 
 845     /** Check that each type is a reference type, i.e. a class, interface or array type
 846      *  or a type variable.
 847      *  @param trees         Original trees, used for error reporting.
 848      *  @param types         The types to be checked.
 849      */
 850     List<Type> checkRefTypes(List<JCExpression> trees, List<Type> types) {
 851         List<JCExpression> tl = trees;
 852         for (List<Type> l = types; l.nonEmpty(); l = l.tail) {
 853             l.head = checkRefType(tl.head.pos(), l.head);
 854             tl = tl.tail;
 855         }
 856         return types;
 857     }
 858 
 859     /** Check that type is a null or reference type.
 860      *  @param pos           Position to be used for error reporting.
 861      *  @param t             The type to be checked.
 862      */
 863     Type checkNullOrRefType(DiagnosticPosition pos, Type t) {
 864         if (t.isReference() || t.hasTag(BOT))
 865             return t;
 866         else
 867             return typeTagError(pos,
 868                                 diags.fragment(Fragments.TypeReqRef),
 869                                 t);
 870     }
 871 
 872     /** Check that flag set does not contain elements of two conflicting sets. s
 873      *  Return true if it doesn't.
 874      *  @param pos           Position to be used for error reporting.
 875      *  @param flags         The set of flags to be checked.
 876      *  @param set1          Conflicting flags set #1.
 877      *  @param set2          Conflicting flags set #2.
 878      */
 879     boolean checkDisjoint(DiagnosticPosition pos, long flags, long set1, long set2) {
 880         if ((flags & set1) != 0 && (flags & set2) != 0) {
 881             log.error(pos,
 882                       Errors.IllegalCombinationOfModifiers(asFlagSet(TreeInfo.firstFlag(flags & set1)),
 883                                                            asFlagSet(TreeInfo.firstFlag(flags & set2))));
 884             return false;
 885         } else
 886             return true;
 887     }
 888 
 889     /** Check that usage of diamond operator is correct (i.e. diamond should not
 890      * be used with non-generic classes or in anonymous class creation expressions)
 891      */
 892     Type checkDiamond(JCNewClass tree, Type t) {
 893         if (!TreeInfo.isDiamond(tree) ||
 894                 t.isErroneous()) {
 895             return checkClassType(tree.clazz.pos(), t, true);
 896         } else {
 897             if (tree.def != null && !Feature.DIAMOND_WITH_ANONYMOUS_CLASS_CREATION.allowedInSource(source)) {
 898                 log.error(DiagnosticFlag.SOURCE_LEVEL, tree.clazz.pos(),
 899                         Errors.CantApplyDiamond1(t, Feature.DIAMOND_WITH_ANONYMOUS_CLASS_CREATION.fragment(source.name)));
 900             }
 901             if (t.tsym.type.getTypeArguments().isEmpty()) {
 902                 log.error(tree.clazz.pos(),
 903                           Errors.CantApplyDiamond1(t,
 904                                                    Fragments.DiamondNonGeneric(t)));
 905                 return types.createErrorType(t);
 906             } else if (tree.typeargs != null &&
 907                     tree.typeargs.nonEmpty()) {
 908                 log.error(tree.clazz.pos(),
 909                           Errors.CantApplyDiamond1(t,
 910                                                    Fragments.DiamondAndExplicitParams(t)));
 911                 return types.createErrorType(t);
 912             } else {
 913                 return t;
 914             }
 915         }
 916     }
 917 
 918     /** Check that the type inferred using the diamond operator does not contain
 919      *  non-denotable types such as captured types or intersection types.
 920      *  @param t the type inferred using the diamond operator
 921      *  @return  the (possibly empty) list of non-denotable types.
 922      */
 923     List<Type> checkDiamondDenotable(ClassType t) {
 924         ListBuffer<Type> buf = new ListBuffer<>();
 925         for (Type arg : t.allparams()) {
 926             if (!checkDenotable(arg)) {
 927                 buf.append(arg);
 928             }
 929         }
 930         return buf.toList();
 931     }
 932 
 933     public boolean checkDenotable(Type t) {
 934         return denotableChecker.visit(t, null);
 935     }
 936         // where
 937 
 938         /** diamondTypeChecker: A type visitor that descends down the given type looking for non-denotable
 939          *  types. The visit methods return false as soon as a non-denotable type is encountered and true
 940          *  otherwise.
 941          */
 942         private static final Types.SimpleVisitor<Boolean, Void> denotableChecker = new Types.SimpleVisitor<Boolean, Void>() {
 943             @Override
 944             public Boolean visitType(Type t, Void s) {
 945                 return true;
 946             }
 947             @Override
 948             public Boolean visitClassType(ClassType t, Void s) {
 949                 if (t.isUnion() || t.isIntersection()) {
 950                     return false;
 951                 }
 952                 for (Type targ : t.allparams()) {
 953                     if (!visit(targ, s)) {
 954                         return false;
 955                     }
 956                 }
 957                 return true;
 958             }
 959 
 960             @Override
 961             public Boolean visitTypeVar(TypeVar t, Void s) {
 962                 /* Any type variable mentioned in the inferred type must have been declared as a type parameter
 963                   (i.e cannot have been produced by inference (18.4))
 964                 */
 965                 return (t.tsym.flags() & SYNTHETIC) == 0;
 966             }
 967 
 968             @Override
 969             public Boolean visitCapturedType(CapturedType t, Void s) {
 970                 /* Any type variable mentioned in the inferred type must have been declared as a type parameter
 971                   (i.e cannot have been produced by capture conversion (5.1.10))
 972                 */
 973                 return false;
 974             }
 975 
 976             @Override
 977             public Boolean visitArrayType(ArrayType t, Void s) {
 978                 return visit(t.elemtype, s);
 979             }
 980 
 981             @Override
 982             public Boolean visitWildcardType(WildcardType t, Void s) {
 983                 return visit(t.type, s);
 984             }
 985         };
 986 
 987     void checkVarargsMethodDecl(Env<AttrContext> env, JCMethodDecl tree) {
 988         MethodSymbol m = tree.sym;
 989         boolean hasTrustMeAnno = m.attribute(syms.trustMeType.tsym) != null;
 990         Type varargElemType = null;
 991         if (m.isVarArgs()) {
 992             varargElemType = types.elemtype(tree.params.last().type);
 993         }
 994         if (hasTrustMeAnno && !isTrustMeAllowedOnMethod(m)) {
 995             if (varargElemType != null) {
 996                 JCDiagnostic msg = Feature.PRIVATE_SAFE_VARARGS.allowedInSource(source) ?
 997                         diags.fragment(Fragments.VarargsTrustmeOnVirtualVarargs(m)) :
 998                         diags.fragment(Fragments.VarargsTrustmeOnVirtualVarargsFinalOnly(m));
 999                 log.error(tree,
1000                           Errors.VarargsInvalidTrustmeAnno(syms.trustMeType.tsym,
1001                                                            msg));
1002             } else {
1003                 log.error(tree,
1004                           Errors.VarargsInvalidTrustmeAnno(syms.trustMeType.tsym,
1005                                                            Fragments.VarargsTrustmeOnNonVarargsMeth(m)));
1006             }
1007         } else if (hasTrustMeAnno && varargElemType != null &&
1008                             types.isReifiable(varargElemType)) {
1009             lint.logIfEnabled(tree, LintWarnings.VarargsRedundantTrustmeAnno(
1010                                 syms.trustMeType.tsym,
1011                                 diags.fragment(Fragments.VarargsTrustmeOnReifiableVarargs(varargElemType))));
1012         }
1013         else if (!hasTrustMeAnno && varargElemType != null &&
1014                 !types.isReifiable(varargElemType)) {
1015             warnUnchecked(tree.params.head.pos(), LintWarnings.UncheckedVarargsNonReifiableType(varargElemType));
1016         }
1017     }
1018     //where
1019         private boolean isTrustMeAllowedOnMethod(Symbol s) {
1020             return (s.flags() & VARARGS) != 0 &&
1021                 (s.isConstructor() ||
1022                     (s.flags() & (STATIC | FINAL |
1023                                   (Feature.PRIVATE_SAFE_VARARGS.allowedInSource(source) ? PRIVATE : 0) )) != 0);
1024         }
1025 
1026     Type checkLocalVarType(DiagnosticPosition pos, Type t, Name name) {
1027         //check that resulting type is not the null type
1028         if (t.hasTag(BOT)) {
1029             log.error(pos, Errors.CantInferLocalVarType(name, Fragments.LocalCantInferNull));
1030             return types.createErrorType(t);
1031         } else if (t.hasTag(VOID)) {
1032             log.error(pos, Errors.CantInferLocalVarType(name, Fragments.LocalCantInferVoid));
1033             return types.createErrorType(t);
1034         }
1035 
1036         //upward project the initializer type
1037         return types.upward(t, types.captures(t)).baseType();
1038     }
1039 
1040     Type checkMethod(final Type mtype,
1041             final Symbol sym,
1042             final Env<AttrContext> env,
1043             final List<JCExpression> argtrees,
1044             final List<Type> argtypes,
1045             final boolean useVarargs,
1046             InferenceContext inferenceContext) {
1047         // System.out.println("call   : " + env.tree);
1048         // System.out.println("method : " + owntype);
1049         // System.out.println("actuals: " + argtypes);
1050         if (inferenceContext.free(mtype)) {
1051             inferenceContext.addFreeTypeListener(List.of(mtype),
1052                     solvedContext -> checkMethod(solvedContext.asInstType(mtype), sym, env, argtrees, argtypes, useVarargs, solvedContext));
1053             return mtype;
1054         }
1055         Type owntype = mtype;
1056         List<Type> formals = owntype.getParameterTypes();
1057         List<Type> nonInferred = sym.type.getParameterTypes();
1058         if (nonInferred.length() != formals.length()) nonInferred = formals;
1059         Type last = useVarargs ? formals.last() : null;
1060         if (sym.name == names.init && sym.owner == syms.enumSym) {
1061             formals = formals.tail.tail;
1062             nonInferred = nonInferred.tail.tail;
1063         }
1064         if ((sym.flags() & ANONCONSTR_BASED) != 0) {
1065             formals = formals.tail;
1066             nonInferred = nonInferred.tail;
1067         }
1068         List<JCExpression> args = argtrees;
1069         if (args != null) {
1070             //this is null when type-checking a method reference
1071             while (formals.head != last) {
1072                 JCTree arg = args.head;
1073                 Warner warn = convertWarner(arg.pos(), arg.type, nonInferred.head);
1074                 assertConvertible(arg, arg.type, formals.head, warn);
1075                 args = args.tail;
1076                 formals = formals.tail;
1077                 nonInferred = nonInferred.tail;
1078             }
1079             if (useVarargs) {
1080                 Type varArg = types.elemtype(last);
1081                 while (args.tail != null) {
1082                     JCTree arg = args.head;
1083                     Warner warn = convertWarner(arg.pos(), arg.type, varArg);
1084                     assertConvertible(arg, arg.type, varArg, warn);
1085                     args = args.tail;
1086                 }
1087             } else if ((sym.flags() & (VARARGS | SIGNATURE_POLYMORPHIC)) == VARARGS) {
1088                 // non-varargs call to varargs method
1089                 Type varParam = owntype.getParameterTypes().last();
1090                 Type lastArg = argtypes.last();
1091                 if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) &&
1092                     !types.isSameType(types.erasure(varParam), types.erasure(lastArg)))
1093                     log.warning(argtrees.last().pos(),
1094                                 Warnings.InexactNonVarargsCall(types.elemtype(varParam),varParam));
1095             }
1096         }
1097         if (useVarargs) {
1098             Type argtype = owntype.getParameterTypes().last();
1099             if (!types.isReifiable(argtype) &&
1100                 (sym.baseSymbol().attribute(syms.trustMeType.tsym) == null ||
1101                  !isTrustMeAllowedOnMethod(sym))) {
1102                 warnUnchecked(env.tree.pos(), LintWarnings.UncheckedGenericArrayCreation(argtype));
1103             }
1104             TreeInfo.setVarargsElement(env.tree, types.elemtype(argtype));
1105          }
1106          return owntype;
1107     }
1108     //where
1109     private void assertConvertible(JCTree tree, Type actual, Type formal, Warner warn) {
1110         if (types.isConvertible(actual, formal, warn))
1111             return;
1112 
1113         if (formal.isCompound()
1114             && types.isSubtype(actual, types.supertype(formal))
1115             && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn))
1116             return;
1117     }
1118 
1119     /**
1120      * Check that type 't' is a valid instantiation of a generic class
1121      * (see JLS 4.5)
1122      *
1123      * @param t class type to be checked
1124      * @return true if 't' is well-formed
1125      */
1126     public boolean checkValidGenericType(Type t) {
1127         return firstIncompatibleTypeArg(t) == null;
1128     }
1129     //WHERE
1130         private Type firstIncompatibleTypeArg(Type type) {
1131             List<Type> formals = type.tsym.type.allparams();
1132             List<Type> actuals = type.allparams();
1133             List<Type> args = type.getTypeArguments();
1134             List<Type> forms = type.tsym.type.getTypeArguments();
1135             ListBuffer<Type> bounds_buf = new ListBuffer<>();
1136 
1137             // For matching pairs of actual argument types `a' and
1138             // formal type parameters with declared bound `b' ...
1139             while (args.nonEmpty() && forms.nonEmpty()) {
1140                 // exact type arguments needs to know their
1141                 // bounds (for upper and lower bound
1142                 // calculations).  So we create new bounds where
1143                 // type-parameters are replaced with actuals argument types.
1144                 bounds_buf.append(types.subst(forms.head.getUpperBound(), formals, actuals));
1145                 args = args.tail;
1146                 forms = forms.tail;
1147             }
1148 
1149             args = type.getTypeArguments();
1150             List<Type> tvars_cap = types.substBounds(formals,
1151                                       formals,
1152                                       types.capture(type).allparams());
1153             while (args.nonEmpty() && tvars_cap.nonEmpty()) {
1154                 // Let the actual arguments know their bound
1155                 args.head.withTypeVar((TypeVar)tvars_cap.head);
1156                 args = args.tail;
1157                 tvars_cap = tvars_cap.tail;
1158             }
1159 
1160             args = type.getTypeArguments();
1161             List<Type> bounds = bounds_buf.toList();
1162 
1163             while (args.nonEmpty() && bounds.nonEmpty()) {
1164                 Type actual = args.head;
1165                 if (!isTypeArgErroneous(actual) &&
1166                         !bounds.head.isErroneous() &&
1167                         !checkExtends(actual, bounds.head)) {
1168                     return args.head;
1169                 }
1170                 args = args.tail;
1171                 bounds = bounds.tail;
1172             }
1173 
1174             args = type.getTypeArguments();
1175             bounds = bounds_buf.toList();
1176 
1177             for (Type arg : types.capture(type).getTypeArguments()) {
1178                 if (arg.hasTag(TYPEVAR) &&
1179                         arg.getUpperBound().isErroneous() &&
1180                         !bounds.head.isErroneous() &&
1181                         !isTypeArgErroneous(args.head)) {
1182                     return args.head;
1183                 }
1184                 bounds = bounds.tail;
1185                 args = args.tail;
1186             }
1187 
1188             return null;
1189         }
1190         //where
1191         boolean isTypeArgErroneous(Type t) {
1192             return isTypeArgErroneous.visit(t);
1193         }
1194 
1195         Types.UnaryVisitor<Boolean> isTypeArgErroneous = new Types.UnaryVisitor<Boolean>() {
1196             public Boolean visitType(Type t, Void s) {
1197                 return t.isErroneous();
1198             }
1199             @Override
1200             public Boolean visitTypeVar(TypeVar t, Void s) {
1201                 return visit(t.getUpperBound());
1202             }
1203             @Override
1204             public Boolean visitCapturedType(CapturedType t, Void s) {
1205                 return visit(t.getUpperBound()) ||
1206                         visit(t.getLowerBound());
1207             }
1208             @Override
1209             public Boolean visitWildcardType(WildcardType t, Void s) {
1210                 return visit(t.type);
1211             }
1212         };
1213 
1214     /** Check that given modifiers are legal for given symbol and
1215      *  return modifiers together with any implicit modifiers for that symbol.
1216      *  Warning: we can't use flags() here since this method
1217      *  is called during class enter, when flags() would cause a premature
1218      *  completion.
1219      *  @param flags         The set of modifiers given in a definition.
1220      *  @param sym           The defined symbol.
1221      *  @param tree          The declaration
1222      */
1223     long checkFlags(long flags, Symbol sym, JCTree tree) {
1224         final DiagnosticPosition pos = tree.pos();
1225         long mask;
1226         long implicit = 0;
1227 
1228         switch (sym.kind) {
1229         case VAR:
1230             if (TreeInfo.isReceiverParam(tree))
1231                 mask = ReceiverParamFlags;
1232             else if (sym.owner.kind != TYP)
1233                 mask = LocalVarFlags;
1234             else if ((sym.owner.flags_field & INTERFACE) != 0)
1235                 mask = implicit = InterfaceVarFlags;
1236             else {
1237                 boolean isInstanceFieldOfValueClass = sym.owner.type.isValueClass() && (flags & STATIC) == 0;
1238                 mask = !isInstanceFieldOfValueClass ? VarFlags : ValueFieldFlags;
1239                 if (isInstanceFieldOfValueClass) {
1240                     implicit |= FINAL | STRICT;
1241                 }
1242             }
1243             break;
1244         case MTH:
1245             if (sym.name == names.init) {
1246                 if ((sym.owner.flags_field & ENUM) != 0) {
1247                     // enum constructors cannot be declared public or
1248                     // protected and must be implicitly or explicitly
1249                     // private
1250                     implicit = PRIVATE;
1251                     mask = PRIVATE;
1252                 } else
1253                     mask = ConstructorFlags;
1254             }  else if ((sym.owner.flags_field & INTERFACE) != 0) {
1255                 if ((sym.owner.flags_field & ANNOTATION) != 0) {
1256                     mask = AnnotationTypeElementMask;
1257                     implicit = PUBLIC | ABSTRACT;
1258                 } else if ((flags & (DEFAULT | STATIC | PRIVATE)) != 0) {
1259                     mask = InterfaceMethodMask;
1260                     implicit = (flags & PRIVATE) != 0 ? 0 : PUBLIC;
1261                     if ((flags & DEFAULT) != 0) {
1262                         implicit |= ABSTRACT;
1263                     }
1264                 } else {
1265                     mask = implicit = InterfaceMethodFlags;
1266                 }
1267             } else if ((sym.owner.flags_field & RECORD) != 0) {
1268                 mask = ((sym.owner.flags_field & VALUE_CLASS) != 0 && (flags & Flags.STATIC) == 0) ?
1269                         RecordMethodFlags & ~SYNCHRONIZED : RecordMethodFlags;
1270             } else {
1271                 // value objects do not have an associated monitor/lock
1272                 mask = ((sym.owner.flags_field & VALUE_CLASS) != 0 && (flags & Flags.STATIC) == 0) ?
1273                         MethodFlags & ~SYNCHRONIZED : MethodFlags;
1274             }
1275             if ((flags & STRICTFP) != 0) {
1276                 warnOnExplicitStrictfp(tree);
1277             }
1278             // Imply STRICTFP if owner has STRICTFP set.
1279             if (((flags|implicit) & Flags.ABSTRACT) == 0 ||
1280                 ((flags) & Flags.DEFAULT) != 0)
1281                 implicit |= sym.owner.flags_field & STRICTFP;
1282             break;
1283         case TYP:
1284             if (sym.owner.kind.matches(KindSelector.VAL_MTH) ||
1285                     (sym.isDirectlyOrIndirectlyLocal() && (flags & ANNOTATION) != 0)) {
1286                 boolean implicitlyStatic = !sym.isAnonymous() &&
1287                         ((flags & RECORD) != 0 || (flags & ENUM) != 0 || (flags & INTERFACE) != 0);
1288                 boolean staticOrImplicitlyStatic = (flags & STATIC) != 0 || implicitlyStatic;
1289                 // local statics are allowed only if records are allowed too
1290                 mask = staticOrImplicitlyStatic && allowRecords && (flags & ANNOTATION) == 0 ? ExtendedStaticLocalClassFlags : ExtendedLocalClassFlags;
1291                 implicit = implicitlyStatic ? STATIC : implicit;
1292             } else if (sym.owner.kind == TYP) {
1293                 // statics in inner classes are allowed only if records are allowed too
1294                 mask = ((flags & STATIC) != 0) && allowRecords && (flags & ANNOTATION) == 0 ? ExtendedMemberStaticClassFlags : ExtendedMemberClassFlags;
1295                 if (sym.owner.owner.kind == PCK ||
1296                     (sym.owner.flags_field & STATIC) != 0) {
1297                     mask |= STATIC;
1298                 } else if (!allowRecords && ((flags & ENUM) != 0 || (flags & RECORD) != 0)) {
1299                     log.error(pos, Errors.StaticDeclarationNotAllowedInInnerClasses);
1300                 }
1301                 // Nested interfaces and enums are always STATIC (Spec ???)
1302                 if ((flags & (INTERFACE | ENUM | RECORD)) != 0 ) implicit = STATIC;
1303             } else {
1304                 mask = ExtendedClassFlags;
1305             }
1306             if ((flags & (VALUE_CLASS | SEALED | ABSTRACT)) == (VALUE_CLASS | SEALED) ||
1307                 (flags & (VALUE_CLASS | NON_SEALED | ABSTRACT)) == (VALUE_CLASS | NON_SEALED)) {
1308                 log.error(pos, Errors.NonAbstractValueClassCantBeSealedOrNonSealed);
1309             }
1310             // Interfaces are always ABSTRACT
1311             if ((flags & INTERFACE) != 0) implicit |= ABSTRACT;
1312 
1313             if ((flags & (INTERFACE | VALUE_CLASS)) == 0) {
1314                 implicit |= IDENTITY_TYPE;
1315             }
1316 
1317             if ((flags & ENUM) != 0) {
1318                 // enums can't be declared abstract, final, sealed or non-sealed or value
1319                 mask &= ~(ABSTRACT | FINAL | SEALED | NON_SEALED | VALUE_CLASS);
1320                 implicit |= implicitEnumFinalFlag(tree);
1321             }
1322             if ((flags & RECORD) != 0) {
1323                 // records can't be declared abstract
1324                 mask &= ~ABSTRACT;
1325                 implicit |= FINAL;
1326             }
1327             if ((flags & STRICTFP) != 0) {
1328                 warnOnExplicitStrictfp(tree);
1329             }
1330             // Imply STRICTFP if owner has STRICTFP set.
1331             implicit |= sym.owner.flags_field & STRICTFP;
1332 
1333             // concrete value classes are implicitly final
1334             if ((flags & (ABSTRACT | INTERFACE | VALUE_CLASS)) == VALUE_CLASS) {
1335                 implicit |= FINAL;
1336             }
1337             break;
1338         default:
1339             throw new AssertionError();
1340         }
1341         long illegal = flags & ExtendedStandardFlags & ~mask;
1342         if (illegal != 0) {
1343             if ((illegal & INTERFACE) != 0) {
1344                 log.error(pos, ((flags & ANNOTATION) != 0) ? Errors.AnnotationDeclNotAllowedHere : Errors.IntfNotAllowedHere);
1345                 mask |= INTERFACE;
1346             }
1347             else {
1348                 log.error(pos,
1349                         Errors.ModNotAllowedHere(asFlagSet(illegal)));
1350             }
1351         } else if ((sym.kind == TYP ||
1352                   // ISSUE: Disallowing abstract&private is no longer appropriate
1353                   // in the presence of inner classes. Should it be deleted here?
1354                   checkDisjoint(pos, flags,
1355                                 ABSTRACT,
1356                                 PRIVATE | STATIC | DEFAULT))
1357                  &&
1358                  checkDisjoint(pos, flags,
1359                                 STATIC | PRIVATE,
1360                                 DEFAULT)
1361                  &&
1362                  checkDisjoint(pos, flags,
1363                                ABSTRACT | INTERFACE,
1364                                FINAL | NATIVE | SYNCHRONIZED)
1365                  &&
1366                  checkDisjoint(pos, flags,
1367                                PUBLIC,
1368                                PRIVATE | PROTECTED)
1369                  &&
1370                  checkDisjoint(pos, flags,
1371                                PRIVATE,
1372                                PUBLIC | PROTECTED)
1373                  &&
1374                  // we are using `implicit` here as instance fields of value classes are implicitly final
1375                  checkDisjoint(pos, flags | implicit,
1376                                FINAL,
1377                                VOLATILE)
1378                  &&
1379                  (sym.kind == TYP ||
1380                   checkDisjoint(pos, flags,
1381                                 ABSTRACT | NATIVE,
1382                                 STRICTFP))
1383                  && checkDisjoint(pos, flags,
1384                                 FINAL,
1385                            SEALED | NON_SEALED)
1386                  && checkDisjoint(pos, flags,
1387                                 SEALED,
1388                            FINAL | NON_SEALED)
1389                  && checkDisjoint(pos, flags,
1390                                 SEALED,
1391                                 ANNOTATION)
1392                 && checkDisjoint(pos, flags,
1393                                 VALUE_CLASS,
1394                                 ANNOTATION)
1395                 && checkDisjoint(pos, flags,
1396                                 VALUE_CLASS,
1397                                 INTERFACE) ) {
1398             // skip
1399         }
1400         return flags & (mask | ~ExtendedStandardFlags) | implicit;
1401     }
1402 
1403     private void warnOnExplicitStrictfp(JCTree tree) {
1404         deferredLintHandler.push(tree);
1405         try {
1406             deferredLintHandler.report(_ -> lint.logIfEnabled(tree.pos(), LintWarnings.Strictfp));
1407         } finally {
1408             deferredLintHandler.pop();
1409         }
1410     }
1411 
1412 
1413     /** Determine if this enum should be implicitly final.
1414      *
1415      *  If the enum has no specialized enum constants, it is final.
1416      *
1417      *  If the enum does have specialized enum constants, it is
1418      *  <i>not</i> final.
1419      */
1420     private long implicitEnumFinalFlag(JCTree tree) {
1421         if (!tree.hasTag(CLASSDEF)) return 0;
1422         class SpecialTreeVisitor extends JCTree.Visitor {
1423             boolean specialized;
1424             SpecialTreeVisitor() {
1425                 this.specialized = false;
1426             }
1427 
1428             @Override
1429             public void visitTree(JCTree tree) { /* no-op */ }
1430 
1431             @Override
1432             public void visitVarDef(JCVariableDecl tree) {
1433                 if ((tree.mods.flags & ENUM) != 0) {
1434                     if (tree.init instanceof JCNewClass newClass && newClass.def != null) {
1435                         specialized = true;
1436                     }
1437                 }
1438             }
1439         }
1440 
1441         SpecialTreeVisitor sts = new SpecialTreeVisitor();
1442         JCClassDecl cdef = (JCClassDecl) tree;
1443         for (JCTree defs: cdef.defs) {
1444             defs.accept(sts);
1445             if (sts.specialized) return allowSealed ? SEALED : 0;
1446         }
1447         return FINAL;
1448     }
1449 
1450 /* *************************************************************************
1451  * Type Validation
1452  **************************************************************************/
1453 
1454     /** Validate a type expression. That is,
1455      *  check that all type arguments of a parametric type are within
1456      *  their bounds. This must be done in a second phase after type attribution
1457      *  since a class might have a subclass as type parameter bound. E.g:
1458      *
1459      *  <pre>{@code
1460      *  class B<A extends C> { ... }
1461      *  class C extends B<C> { ... }
1462      *  }</pre>
1463      *
1464      *  and we can't make sure that the bound is already attributed because
1465      *  of possible cycles.
1466      *
1467      * Visitor method: Validate a type expression, if it is not null, catching
1468      *  and reporting any completion failures.
1469      */
1470     void validate(JCTree tree, Env<AttrContext> env) {
1471         validate(tree, env, true);
1472     }
1473     void validate(JCTree tree, Env<AttrContext> env, boolean checkRaw) {
1474         new Validator(env).validateTree(tree, checkRaw, true);
1475     }
1476 
1477     /** Visitor method: Validate a list of type expressions.
1478      */
1479     void validate(List<? extends JCTree> trees, Env<AttrContext> env) {
1480         for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
1481             validate(l.head, env);
1482     }
1483 
1484     /** A visitor class for type validation.
1485      */
1486     class Validator extends JCTree.Visitor {
1487 
1488         boolean checkRaw;
1489         boolean isOuter;
1490         Env<AttrContext> env;
1491 
1492         Validator(Env<AttrContext> env) {
1493             this.env = env;
1494         }
1495 
1496         @Override
1497         public void visitTypeArray(JCArrayTypeTree tree) {
1498             validateTree(tree.elemtype, checkRaw, isOuter);
1499         }
1500 
1501         @Override
1502         public void visitTypeApply(JCTypeApply tree) {
1503             if (tree.type.hasTag(CLASS)) {
1504                 List<JCExpression> args = tree.arguments;
1505                 List<Type> forms = tree.type.tsym.type.getTypeArguments();
1506 
1507                 Type incompatibleArg = firstIncompatibleTypeArg(tree.type);
1508                 if (incompatibleArg != null) {
1509                     for (JCTree arg : tree.arguments) {
1510                         if (arg.type == incompatibleArg) {
1511                             log.error(arg, Errors.NotWithinBounds(incompatibleArg, forms.head));
1512                         }
1513                         forms = forms.tail;
1514                      }
1515                  }
1516 
1517                 forms = tree.type.tsym.type.getTypeArguments();
1518 
1519                 boolean is_java_lang_Class = tree.type.tsym.flatName() == names.java_lang_Class;
1520 
1521                 // For matching pairs of actual argument types `a' and
1522                 // formal type parameters with declared bound `b' ...
1523                 while (args.nonEmpty() && forms.nonEmpty()) {
1524                     validateTree(args.head,
1525                             !(isOuter && is_java_lang_Class),
1526                             false);
1527                     args = args.tail;
1528                     forms = forms.tail;
1529                 }
1530 
1531                 // Check that this type is either fully parameterized, or
1532                 // not parameterized at all.
1533                 if (tree.type.getEnclosingType().isRaw())
1534                     log.error(tree.pos(), Errors.ImproperlyFormedTypeInnerRawParam);
1535                 if (tree.clazz.hasTag(SELECT))
1536                     visitSelectInternal((JCFieldAccess)tree.clazz);
1537             }
1538         }
1539 
1540         @Override
1541         public void visitTypeParameter(JCTypeParameter tree) {
1542             validateTrees(tree.bounds, true, isOuter);
1543             checkClassBounds(tree.pos(), tree.type);
1544         }
1545 
1546         @Override
1547         public void visitWildcard(JCWildcard tree) {
1548             if (tree.inner != null)
1549                 validateTree(tree.inner, true, isOuter);
1550         }
1551 
1552         @Override
1553         public void visitSelect(JCFieldAccess tree) {
1554             if (tree.type.hasTag(CLASS)) {
1555                 visitSelectInternal(tree);
1556 
1557                 // Check that this type is either fully parameterized, or
1558                 // not parameterized at all.
1559                 if (tree.selected.type.isParameterized() && tree.type.tsym.type.getTypeArguments().nonEmpty())
1560                     log.error(tree.pos(), Errors.ImproperlyFormedTypeParamMissing);
1561             }
1562         }
1563 
1564         public void visitSelectInternal(JCFieldAccess tree) {
1565             if (tree.type.tsym.isStatic() &&
1566                 tree.selected.type.isParameterized()) {
1567                 // The enclosing type is not a class, so we are
1568                 // looking at a static member type.  However, the
1569                 // qualifying expression is parameterized.
1570                 log.error(tree.pos(), Errors.CantSelectStaticClassFromParamType);
1571             } else {
1572                 // otherwise validate the rest of the expression
1573                 tree.selected.accept(this);
1574             }
1575         }
1576 
1577         @Override
1578         public void visitAnnotatedType(JCAnnotatedType tree) {
1579             tree.underlyingType.accept(this);
1580         }
1581 
1582         @Override
1583         public void visitTypeIdent(JCPrimitiveTypeTree that) {
1584             if (that.type.hasTag(TypeTag.VOID)) {
1585                 log.error(that.pos(), Errors.VoidNotAllowedHere);
1586             }
1587             super.visitTypeIdent(that);
1588         }
1589 
1590         /** Default visitor method: do nothing.
1591          */
1592         @Override
1593         public void visitTree(JCTree tree) {
1594         }
1595 
1596         public void validateTree(JCTree tree, boolean checkRaw, boolean isOuter) {
1597             if (tree != null) {
1598                 boolean prevCheckRaw = this.checkRaw;
1599                 this.checkRaw = checkRaw;
1600                 this.isOuter = isOuter;
1601 
1602                 try {
1603                     tree.accept(this);
1604                     if (checkRaw)
1605                         checkRaw(tree, env);
1606                 } catch (CompletionFailure ex) {
1607                     completionError(tree.pos(), ex);
1608                 } finally {
1609                     this.checkRaw = prevCheckRaw;
1610                 }
1611             }
1612         }
1613 
1614         public void validateTrees(List<? extends JCTree> trees, boolean checkRaw, boolean isOuter) {
1615             for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
1616                 validateTree(l.head, checkRaw, isOuter);
1617         }
1618     }
1619 
1620     void checkRaw(JCTree tree, Env<AttrContext> env) {
1621         if (tree.type.hasTag(CLASS) &&
1622             !TreeInfo.isDiamond(tree) &&
1623             !withinAnonConstr(env) &&
1624             tree.type.isRaw()) {
1625             lint.logIfEnabled(tree.pos(), LintWarnings.RawClassUse(tree.type, tree.type.tsym.type));
1626         }
1627     }
1628     //where
1629         private boolean withinAnonConstr(Env<AttrContext> env) {
1630             return env.enclClass.name.isEmpty() &&
1631                     env.enclMethod != null && env.enclMethod.name == names.init;
1632         }
1633 
1634 /* *************************************************************************
1635  * Exception checking
1636  **************************************************************************/
1637 
1638     /* The following methods treat classes as sets that contain
1639      * the class itself and all their subclasses
1640      */
1641 
1642     /** Is given type a subtype of some of the types in given list?
1643      */
1644     boolean subset(Type t, List<Type> ts) {
1645         for (List<Type> l = ts; l.nonEmpty(); l = l.tail)
1646             if (types.isSubtype(t, l.head)) return true;
1647         return false;
1648     }
1649 
1650     /** Is given type a subtype or supertype of
1651      *  some of the types in given list?
1652      */
1653     boolean intersects(Type t, List<Type> ts) {
1654         for (List<Type> l = ts; l.nonEmpty(); l = l.tail)
1655             if (types.isSubtype(t, l.head) || types.isSubtype(l.head, t)) return true;
1656         return false;
1657     }
1658 
1659     /** Add type set to given type list, unless it is a subclass of some class
1660      *  in the list.
1661      */
1662     List<Type> incl(Type t, List<Type> ts) {
1663         return subset(t, ts) ? ts : excl(t, ts).prepend(t);
1664     }
1665 
1666     /** Remove type set from type set list.
1667      */
1668     List<Type> excl(Type t, List<Type> ts) {
1669         if (ts.isEmpty()) {
1670             return ts;
1671         } else {
1672             List<Type> ts1 = excl(t, ts.tail);
1673             if (types.isSubtype(ts.head, t)) return ts1;
1674             else if (ts1 == ts.tail) return ts;
1675             else return ts1.prepend(ts.head);
1676         }
1677     }
1678 
1679     /** Form the union of two type set lists.
1680      */
1681     List<Type> union(List<Type> ts1, List<Type> ts2) {
1682         List<Type> ts = ts1;
1683         for (List<Type> l = ts2; l.nonEmpty(); l = l.tail)
1684             ts = incl(l.head, ts);
1685         return ts;
1686     }
1687 
1688     /** Form the difference of two type lists.
1689      */
1690     List<Type> diff(List<Type> ts1, List<Type> ts2) {
1691         List<Type> ts = ts1;
1692         for (List<Type> l = ts2; l.nonEmpty(); l = l.tail)
1693             ts = excl(l.head, ts);
1694         return ts;
1695     }
1696 
1697     /** Form the intersection of two type lists.
1698      */
1699     public List<Type> intersect(List<Type> ts1, List<Type> ts2) {
1700         List<Type> ts = List.nil();
1701         for (List<Type> l = ts1; l.nonEmpty(); l = l.tail)
1702             if (subset(l.head, ts2)) ts = incl(l.head, ts);
1703         for (List<Type> l = ts2; l.nonEmpty(); l = l.tail)
1704             if (subset(l.head, ts1)) ts = incl(l.head, ts);
1705         return ts;
1706     }
1707 
1708     /** Is exc an exception symbol that need not be declared?
1709      */
1710     boolean isUnchecked(ClassSymbol exc) {
1711         return
1712             exc.kind == ERR ||
1713             exc.isSubClass(syms.errorType.tsym, types) ||
1714             exc.isSubClass(syms.runtimeExceptionType.tsym, types);
1715     }
1716 
1717     /** Is exc an exception type that need not be declared?
1718      */
1719     boolean isUnchecked(Type exc) {
1720         return
1721             (exc.hasTag(TYPEVAR)) ? isUnchecked(types.supertype(exc)) :
1722             (exc.hasTag(CLASS)) ? isUnchecked((ClassSymbol)exc.tsym) :
1723             exc.hasTag(BOT);
1724     }
1725 
1726     boolean isChecked(Type exc) {
1727         return !isUnchecked(exc);
1728     }
1729 
1730     /** Same, but handling completion failures.
1731      */
1732     boolean isUnchecked(DiagnosticPosition pos, Type exc) {
1733         try {
1734             return isUnchecked(exc);
1735         } catch (CompletionFailure ex) {
1736             completionError(pos, ex);
1737             return true;
1738         }
1739     }
1740 
1741     /** Is exc handled by given exception list?
1742      */
1743     boolean isHandled(Type exc, List<Type> handled) {
1744         return isUnchecked(exc) || subset(exc, handled);
1745     }
1746 
1747     /** Return all exceptions in thrown list that are not in handled list.
1748      *  @param thrown     The list of thrown exceptions.
1749      *  @param handled    The list of handled exceptions.
1750      */
1751     List<Type> unhandled(List<Type> thrown, List<Type> handled) {
1752         List<Type> unhandled = List.nil();
1753         for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
1754             if (!isHandled(l.head, handled)) unhandled = unhandled.prepend(l.head);
1755         return unhandled;
1756     }
1757 
1758 /* *************************************************************************
1759  * Overriding/Implementation checking
1760  **************************************************************************/
1761 
1762     /** The level of access protection given by a flag set,
1763      *  where PRIVATE is highest and PUBLIC is lowest.
1764      */
1765     static int protection(long flags) {
1766         switch ((short)(flags & AccessFlags)) {
1767         case PRIVATE: return 3;
1768         case PROTECTED: return 1;
1769         default:
1770         case PUBLIC: return 0;
1771         case 0: return 2;
1772         }
1773     }
1774 
1775     /** A customized "cannot override" error message.
1776      *  @param m      The overriding method.
1777      *  @param other  The overridden method.
1778      *  @return       An internationalized string.
1779      */
1780     Fragment cannotOverride(MethodSymbol m, MethodSymbol other) {
1781         Symbol mloc = m.location();
1782         Symbol oloc = other.location();
1783 
1784         if ((other.owner.flags() & INTERFACE) == 0)
1785             return Fragments.CantOverride(m, mloc, other, oloc);
1786         else if ((m.owner.flags() & INTERFACE) == 0)
1787             return Fragments.CantImplement(m, mloc, other, oloc);
1788         else
1789             return Fragments.ClashesWith(m, mloc, other, oloc);
1790     }
1791 
1792     /** A customized "override" warning message.
1793      *  @param m      The overriding method.
1794      *  @param other  The overridden method.
1795      *  @return       An internationalized string.
1796      */
1797     Fragment uncheckedOverrides(MethodSymbol m, MethodSymbol other) {
1798         Symbol mloc = m.location();
1799         Symbol oloc = other.location();
1800 
1801         if ((other.owner.flags() & INTERFACE) == 0)
1802             return Fragments.UncheckedOverride(m, mloc, other, oloc);
1803         else if ((m.owner.flags() & INTERFACE) == 0)
1804             return Fragments.UncheckedImplement(m, mloc, other, oloc);
1805         else
1806             return Fragments.UncheckedClashWith(m, mloc, other, oloc);
1807     }
1808 
1809     /** A customized "override" warning message.
1810      *  @param m      The overriding method.
1811      *  @param other  The overridden method.
1812      *  @return       An internationalized string.
1813      */
1814     Fragment varargsOverrides(MethodSymbol m, MethodSymbol other) {
1815         Symbol mloc = m.location();
1816         Symbol oloc = other.location();
1817 
1818         if ((other.owner.flags() & INTERFACE) == 0)
1819             return Fragments.VarargsOverride(m, mloc, other, oloc);
1820         else  if ((m.owner.flags() & INTERFACE) == 0)
1821             return Fragments.VarargsImplement(m, mloc, other, oloc);
1822         else
1823             return Fragments.VarargsClashWith(m, mloc, other, oloc);
1824     }
1825 
1826     /** Check that this method conforms with overridden method 'other'.
1827      *  where `origin' is the class where checking started.
1828      *  Complications:
1829      *  (1) Do not check overriding of synthetic methods
1830      *      (reason: they might be final).
1831      *      todo: check whether this is still necessary.
1832      *  (2) Admit the case where an interface proxy throws fewer exceptions
1833      *      than the method it implements. Augment the proxy methods with the
1834      *      undeclared exceptions in this case.
1835      *  (3) When generics are enabled, admit the case where an interface proxy
1836      *      has a result type
1837      *      extended by the result type of the method it implements.
1838      *      Change the proxies result type to the smaller type in this case.
1839      *
1840      *  @param tree         The tree from which positions
1841      *                      are extracted for errors.
1842      *  @param m            The overriding method.
1843      *  @param other        The overridden method.
1844      *  @param origin       The class of which the overriding method
1845      *                      is a member.
1846      */
1847     void checkOverride(JCTree tree,
1848                        MethodSymbol m,
1849                        MethodSymbol other,
1850                        ClassSymbol origin) {
1851         // Don't check overriding of synthetic methods or by bridge methods.
1852         if ((m.flags() & (SYNTHETIC|BRIDGE)) != 0 || (other.flags() & SYNTHETIC) != 0) {
1853             return;
1854         }
1855 
1856         // Error if static method overrides instance method (JLS 8.4.8.2).
1857         if ((m.flags() & STATIC) != 0 &&
1858                    (other.flags() & STATIC) == 0) {
1859             log.error(TreeInfo.diagnosticPositionFor(m, tree),
1860                       Errors.OverrideStatic(cannotOverride(m, other)));
1861             m.flags_field |= BAD_OVERRIDE;
1862             return;
1863         }
1864 
1865         // Error if instance method overrides static or final
1866         // method (JLS 8.4.8.1).
1867         if ((other.flags() & FINAL) != 0 ||
1868                  (m.flags() & STATIC) == 0 &&
1869                  (other.flags() & STATIC) != 0) {
1870             log.error(TreeInfo.diagnosticPositionFor(m, tree),
1871                       Errors.OverrideMeth(cannotOverride(m, other),
1872                                           asFlagSet(other.flags() & (FINAL | STATIC))));
1873             m.flags_field |= BAD_OVERRIDE;
1874             return;
1875         }
1876 
1877         if ((m.owner.flags() & ANNOTATION) != 0) {
1878             // handled in validateAnnotationMethod
1879             return;
1880         }
1881 
1882         // Error if overriding method has weaker access (JLS 8.4.8.3).
1883         if (protection(m.flags()) > protection(other.flags())) {
1884             log.error(TreeInfo.diagnosticPositionFor(m, tree),
1885                       (other.flags() & AccessFlags) == 0 ?
1886                               Errors.OverrideWeakerAccess(cannotOverride(m, other),
1887                                                           "package") :
1888                               Errors.OverrideWeakerAccess(cannotOverride(m, other),
1889                                                           asFlagSet(other.flags() & AccessFlags)));
1890             m.flags_field |= BAD_OVERRIDE;
1891             return;
1892         }
1893 
1894         if (shouldCheckPreview(m, other, origin)) {
1895             checkPreview(TreeInfo.diagnosticPositionFor(m, tree),
1896                          m, origin.type, other);
1897         }
1898 
1899         Type mt = types.memberType(origin.type, m);
1900         Type ot = types.memberType(origin.type, other);
1901         // Error if overriding result type is different
1902         // (or, in the case of generics mode, not a subtype) of
1903         // overridden result type. We have to rename any type parameters
1904         // before comparing types.
1905         List<Type> mtvars = mt.getTypeArguments();
1906         List<Type> otvars = ot.getTypeArguments();
1907         Type mtres = mt.getReturnType();
1908         Type otres = types.subst(ot.getReturnType(), otvars, mtvars);
1909 
1910         overrideWarner.clear();
1911         boolean resultTypesOK =
1912             types.returnTypeSubstitutable(mt, ot, otres, overrideWarner);
1913         if (!resultTypesOK) {
1914             if ((m.flags() & STATIC) != 0 && (other.flags() & STATIC) != 0) {
1915                 log.error(TreeInfo.diagnosticPositionFor(m, tree),
1916                           Errors.OverrideIncompatibleRet(Fragments.CantHide(m, m.location(), other,
1917                                         other.location()), mtres, otres));
1918                 m.flags_field |= BAD_OVERRIDE;
1919             } else {
1920                 log.error(TreeInfo.diagnosticPositionFor(m, tree),
1921                           Errors.OverrideIncompatibleRet(cannotOverride(m, other), mtres, otres));
1922                 m.flags_field |= BAD_OVERRIDE;
1923             }
1924             return;
1925         } else if (overrideWarner.hasNonSilentLint(LintCategory.UNCHECKED)) {
1926             warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree),
1927                     LintWarnings.OverrideUncheckedRet(uncheckedOverrides(m, other), mtres, otres));
1928         }
1929 
1930         // Error if overriding method throws an exception not reported
1931         // by overridden method.
1932         List<Type> otthrown = types.subst(ot.getThrownTypes(), otvars, mtvars);
1933         List<Type> unhandledErased = unhandled(mt.getThrownTypes(), types.erasure(otthrown));
1934         List<Type> unhandledUnerased = unhandled(mt.getThrownTypes(), otthrown);
1935         if (unhandledErased.nonEmpty()) {
1936             log.error(TreeInfo.diagnosticPositionFor(m, tree),
1937                       Errors.OverrideMethDoesntThrow(cannotOverride(m, other), unhandledUnerased.head));
1938             m.flags_field |= BAD_OVERRIDE;
1939             return;
1940         }
1941         else if (unhandledUnerased.nonEmpty()) {
1942             warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree),
1943                           LintWarnings.OverrideUncheckedThrown(cannotOverride(m, other), unhandledUnerased.head));
1944             return;
1945         }
1946 
1947         // Optional warning if varargs don't agree
1948         if ((((m.flags() ^ other.flags()) & Flags.VARARGS) != 0)) {
1949             lint.logIfEnabled(TreeInfo.diagnosticPositionFor(m, tree),
1950                         ((m.flags() & Flags.VARARGS) != 0)
1951                         ? LintWarnings.OverrideVarargsMissing(varargsOverrides(m, other))
1952                         : LintWarnings.OverrideVarargsExtra(varargsOverrides(m, other)));
1953         }
1954 
1955         // Warn if instance method overrides bridge method (compiler spec ??)
1956         if ((other.flags() & BRIDGE) != 0) {
1957             log.warning(TreeInfo.diagnosticPositionFor(m, tree),
1958                         Warnings.OverrideBridge(uncheckedOverrides(m, other)));
1959         }
1960 
1961         // Warn if a deprecated method overridden by a non-deprecated one.
1962         if (!isDeprecatedOverrideIgnorable(other, origin)) {
1963             Lint prevLint = setLint(lint.augment(m));
1964             try {
1965                 checkDeprecated(() -> TreeInfo.diagnosticPositionFor(m, tree), m, other);
1966             } finally {
1967                 setLint(prevLint);
1968             }
1969         }
1970     }
1971     // where
1972         private boolean shouldCheckPreview(MethodSymbol m, MethodSymbol other, ClassSymbol origin) {
1973             if (m.owner != origin ||
1974                 //performance - only do the expensive checks when the overridden method is a Preview API:
1975                 ((other.flags() & PREVIEW_API) == 0 &&
1976                  (other.owner.flags() & PREVIEW_API) == 0)) {
1977                 return false;
1978             }
1979 
1980             for (Symbol s : types.membersClosure(origin.type, false).getSymbolsByName(m.name)) {
1981                 if (m != s && m.overrides(s, origin, types, false)) {
1982                     //only produce preview warnings or errors if "m" immediatelly overrides "other"
1983                     //without intermediate overriding methods:
1984                     return s == other;
1985                 }
1986             }
1987 
1988             return false;
1989         }
1990         private boolean isDeprecatedOverrideIgnorable(MethodSymbol m, ClassSymbol origin) {
1991             // If the method, m, is defined in an interface, then ignore the issue if the method
1992             // is only inherited via a supertype and also implemented in the supertype,
1993             // because in that case, we will rediscover the issue when examining the method
1994             // in the supertype.
1995             // If the method, m, is not defined in an interface, then the only time we need to
1996             // address the issue is when the method is the supertype implementation: any other
1997             // case, we will have dealt with when examining the supertype classes
1998             ClassSymbol mc = m.enclClass();
1999             Type st = types.supertype(origin.type);
2000             if (!st.hasTag(CLASS))
2001                 return true;
2002             MethodSymbol stimpl = m.implementation((ClassSymbol)st.tsym, types, false);
2003 
2004             if (mc != null && ((mc.flags() & INTERFACE) != 0)) {
2005                 List<Type> intfs = types.interfaces(origin.type);
2006                 return (intfs.contains(mc.type) ? false : (stimpl != null));
2007             }
2008             else
2009                 return (stimpl != m);
2010         }
2011 
2012 
2013     // used to check if there were any unchecked conversions
2014     Warner overrideWarner = new Warner();
2015 
2016     /** Check that a class does not inherit two concrete methods
2017      *  with the same signature.
2018      *  @param pos          Position to be used for error reporting.
2019      *  @param site         The class type to be checked.
2020      */
2021     public void checkCompatibleConcretes(DiagnosticPosition pos, Type site) {
2022         Type sup = types.supertype(site);
2023         if (!sup.hasTag(CLASS)) return;
2024 
2025         for (Type t1 = sup;
2026              t1.hasTag(CLASS) && t1.tsym.type.isParameterized();
2027              t1 = types.supertype(t1)) {
2028             for (Symbol s1 : t1.tsym.members().getSymbols(NON_RECURSIVE)) {
2029                 if (s1.kind != MTH ||
2030                     (s1.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 ||
2031                     !s1.isInheritedIn(site.tsym, types) ||
2032                     ((MethodSymbol)s1).implementation(site.tsym,
2033                                                       types,
2034                                                       true) != s1)
2035                     continue;
2036                 Type st1 = types.memberType(t1, s1);
2037                 int s1ArgsLength = st1.getParameterTypes().length();
2038                 if (st1 == s1.type) continue;
2039 
2040                 for (Type t2 = sup;
2041                      t2.hasTag(CLASS);
2042                      t2 = types.supertype(t2)) {
2043                     for (Symbol s2 : t2.tsym.members().getSymbolsByName(s1.name)) {
2044                         if (s2 == s1 ||
2045                             s2.kind != MTH ||
2046                             (s2.flags() & (STATIC|SYNTHETIC|BRIDGE)) != 0 ||
2047                             s2.type.getParameterTypes().length() != s1ArgsLength ||
2048                             !s2.isInheritedIn(site.tsym, types) ||
2049                             ((MethodSymbol)s2).implementation(site.tsym,
2050                                                               types,
2051                                                               true) != s2)
2052                             continue;
2053                         Type st2 = types.memberType(t2, s2);
2054                         if (types.overrideEquivalent(st1, st2))
2055                             log.error(pos,
2056                                       Errors.ConcreteInheritanceConflict(s1, t1, s2, t2, sup));
2057                     }
2058                 }
2059             }
2060         }
2061     }
2062 
2063     /** Check that classes (or interfaces) do not each define an abstract
2064      *  method with same name and arguments but incompatible return types.
2065      *  @param pos          Position to be used for error reporting.
2066      *  @param t1           The first argument type.
2067      *  @param t2           The second argument type.
2068      */
2069     public boolean checkCompatibleAbstracts(DiagnosticPosition pos,
2070                                             Type t1,
2071                                             Type t2,
2072                                             Type site) {
2073         if ((site.tsym.flags() & COMPOUND) != 0) {
2074             // special case for intersections: need to eliminate wildcards in supertypes
2075             t1 = types.capture(t1);
2076             t2 = types.capture(t2);
2077         }
2078         return firstIncompatibility(pos, t1, t2, site) == null;
2079     }
2080 
2081     /** Return the first method which is defined with same args
2082      *  but different return types in two given interfaces, or null if none
2083      *  exists.
2084      *  @param t1     The first type.
2085      *  @param t2     The second type.
2086      *  @param site   The most derived type.
2087      *  @return symbol from t2 that conflicts with one in t1.
2088      */
2089     private Symbol firstIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site) {
2090         Map<TypeSymbol,Type> interfaces1 = new HashMap<>();
2091         closure(t1, interfaces1);
2092         Map<TypeSymbol,Type> interfaces2;
2093         if (t1 == t2)
2094             interfaces2 = interfaces1;
2095         else
2096             closure(t2, interfaces1, interfaces2 = new HashMap<>());
2097 
2098         for (Type t3 : interfaces1.values()) {
2099             for (Type t4 : interfaces2.values()) {
2100                 Symbol s = firstDirectIncompatibility(pos, t3, t4, site);
2101                 if (s != null) return s;
2102             }
2103         }
2104         return null;
2105     }
2106 
2107     /** Compute all the supertypes of t, indexed by type symbol. */
2108     private void closure(Type t, Map<TypeSymbol,Type> typeMap) {
2109         if (!t.hasTag(CLASS)) return;
2110         if (typeMap.put(t.tsym, t) == null) {
2111             closure(types.supertype(t), typeMap);
2112             for (Type i : types.interfaces(t))
2113                 closure(i, typeMap);
2114         }
2115     }
2116 
2117     /** Compute all the supertypes of t, indexed by type symbol (except those in typesSkip). */
2118     private void closure(Type t, Map<TypeSymbol,Type> typesSkip, Map<TypeSymbol,Type> typeMap) {
2119         if (!t.hasTag(CLASS)) return;
2120         if (typesSkip.get(t.tsym) != null) return;
2121         if (typeMap.put(t.tsym, t) == null) {
2122             closure(types.supertype(t), typesSkip, typeMap);
2123             for (Type i : types.interfaces(t))
2124                 closure(i, typesSkip, typeMap);
2125         }
2126     }
2127 
2128     /** Return the first method in t2 that conflicts with a method from t1. */
2129     private Symbol firstDirectIncompatibility(DiagnosticPosition pos, Type t1, Type t2, Type site) {
2130         for (Symbol s1 : t1.tsym.members().getSymbols(NON_RECURSIVE)) {
2131             Type st1 = null;
2132             if (s1.kind != MTH || !s1.isInheritedIn(site.tsym, types) ||
2133                     (s1.flags() & SYNTHETIC) != 0) continue;
2134             Symbol impl = ((MethodSymbol)s1).implementation(site.tsym, types, false);
2135             if (impl != null && (impl.flags() & ABSTRACT) == 0) continue;
2136             for (Symbol s2 : t2.tsym.members().getSymbolsByName(s1.name)) {
2137                 if (s1 == s2) continue;
2138                 if (s2.kind != MTH || !s2.isInheritedIn(site.tsym, types) ||
2139                         (s2.flags() & SYNTHETIC) != 0) continue;
2140                 if (st1 == null) st1 = types.memberType(t1, s1);
2141                 Type st2 = types.memberType(t2, s2);
2142                 if (types.overrideEquivalent(st1, st2)) {
2143                     List<Type> tvars1 = st1.getTypeArguments();
2144                     List<Type> tvars2 = st2.getTypeArguments();
2145                     Type rt1 = st1.getReturnType();
2146                     Type rt2 = types.subst(st2.getReturnType(), tvars2, tvars1);
2147                     boolean compat =
2148                         types.isSameType(rt1, rt2) ||
2149                         !rt1.isPrimitiveOrVoid() &&
2150                         !rt2.isPrimitiveOrVoid() &&
2151                         (types.covariantReturnType(rt1, rt2, types.noWarnings) ||
2152                          types.covariantReturnType(rt2, rt1, types.noWarnings)) ||
2153                          checkCommonOverriderIn(s1,s2,site);
2154                     if (!compat) {
2155                         if (types.isSameType(t1, t2)) {
2156                             log.error(pos, Errors.IncompatibleDiffRetSameType(t1,
2157                                     s2.name, types.memberType(t2, s2).getParameterTypes()));
2158                         } else {
2159                             log.error(pos, Errors.TypesIncompatible(t1, t2,
2160                                     Fragments.IncompatibleDiffRet(s2.name, types.memberType(t2, s2).getParameterTypes())));
2161                         }
2162                         return s2;
2163                     }
2164                 } else if (checkNameClash((ClassSymbol)site.tsym, s1, s2) &&
2165                         !checkCommonOverriderIn(s1, s2, site)) {
2166                     log.error(pos, Errors.NameClashSameErasureNoOverride(
2167                             s1.name, types.memberType(site, s1).asMethodType().getParameterTypes(), s1.location(),
2168                             s2.name, types.memberType(site, s2).asMethodType().getParameterTypes(), s2.location()));
2169                     return s2;
2170                 }
2171             }
2172         }
2173         return null;
2174     }
2175     //WHERE
2176     boolean checkCommonOverriderIn(Symbol s1, Symbol s2, Type site) {
2177         Map<TypeSymbol,Type> supertypes = new HashMap<>();
2178         Type st1 = types.memberType(site, s1);
2179         Type st2 = types.memberType(site, s2);
2180         closure(site, supertypes);
2181         for (Type t : supertypes.values()) {
2182             for (Symbol s3 : t.tsym.members().getSymbolsByName(s1.name)) {
2183                 if (s3 == s1 || s3 == s2 || s3.kind != MTH || (s3.flags() & (BRIDGE|SYNTHETIC)) != 0) continue;
2184                 Type st3 = types.memberType(site,s3);
2185                 if (types.overrideEquivalent(st3, st1) &&
2186                         types.overrideEquivalent(st3, st2) &&
2187                         types.returnTypeSubstitutable(st3, st1) &&
2188                         types.returnTypeSubstitutable(st3, st2)) {
2189                     return true;
2190                 }
2191             }
2192         }
2193         return false;
2194     }
2195 
2196     /** Check that a given method conforms with any method it overrides.
2197      *  @param tree         The tree from which positions are extracted
2198      *                      for errors.
2199      *  @param m            The overriding method.
2200      */
2201     void checkOverride(Env<AttrContext> env, JCMethodDecl tree, MethodSymbol m) {
2202         ClassSymbol origin = (ClassSymbol)m.owner;
2203         if ((origin.flags() & ENUM) != 0 && names.finalize.equals(m.name)) {
2204             if (m.overrides(syms.enumFinalFinalize, origin, types, false)) {
2205                 log.error(tree.pos(), Errors.EnumNoFinalize);
2206                 return;
2207             }
2208         }
2209         if (allowValueClasses && origin.isValueClass() && names.finalize.equals(m.name)) {
2210             if (m.overrides(syms.objectFinalize, origin, types, false)) {
2211                 log.warning(tree.pos(), Warnings.ValueFinalize);
2212             }
2213         }
2214         if (allowRecords && origin.isRecord()) {
2215             // let's find out if this is a user defined accessor in which case the @Override annotation is acceptable
2216             Optional<? extends RecordComponent> recordComponent = origin.getRecordComponents().stream()
2217                     .filter(rc -> rc.accessor == tree.sym && (rc.accessor.flags_field & GENERATED_MEMBER) == 0).findFirst();
2218             if (recordComponent.isPresent()) {
2219                 return;
2220             }
2221         }
2222 
2223         for (Type t = origin.type; t.hasTag(CLASS);
2224              t = types.supertype(t)) {
2225             if (t != origin.type) {
2226                 checkOverride(tree, t, origin, m);
2227             }
2228             for (Type t2 : types.interfaces(t)) {
2229                 checkOverride(tree, t2, origin, m);
2230             }
2231         }
2232 
2233         final boolean explicitOverride = m.attribute(syms.overrideType.tsym) != null;
2234         // Check if this method must override a super method due to being annotated with @Override
2235         // or by virtue of being a member of a diamond inferred anonymous class. Latter case is to
2236         // be treated "as if as they were annotated" with @Override.
2237         boolean mustOverride = explicitOverride ||
2238                 (env.info.isAnonymousDiamond && !m.isConstructor() && !m.isPrivate());
2239         if (mustOverride && !isOverrider(m)) {
2240             DiagnosticPosition pos = tree.pos();
2241             for (JCAnnotation a : tree.getModifiers().annotations) {
2242                 if (a.annotationType.type.tsym == syms.overrideType.tsym) {
2243                     pos = a.pos();
2244                     break;
2245                 }
2246             }
2247             log.error(pos,
2248                       explicitOverride ? (m.isStatic() ? Errors.StaticMethodsCannotBeAnnotatedWithOverride : Errors.MethodDoesNotOverrideSuperclass) :
2249                                 Errors.AnonymousDiamondMethodDoesNotOverrideSuperclass(Fragments.DiamondAnonymousMethodsImplicitlyOverride));
2250         }
2251     }
2252 
2253     void checkOverride(JCTree tree, Type site, ClassSymbol origin, MethodSymbol m) {
2254         TypeSymbol c = site.tsym;
2255         for (Symbol sym : c.members().getSymbolsByName(m.name)) {
2256             if (m.overrides(sym, origin, types, false)) {
2257                 if ((sym.flags() & ABSTRACT) == 0) {
2258                     checkOverride(tree, m, (MethodSymbol)sym, origin);
2259                 }
2260             }
2261         }
2262     }
2263 
2264     private Predicate<Symbol> equalsHasCodeFilter = s -> MethodSymbol.implementation_filter.test(s) &&
2265             (s.flags() & BAD_OVERRIDE) == 0;
2266 
2267     public void checkClassOverrideEqualsAndHashIfNeeded(DiagnosticPosition pos,
2268             ClassSymbol someClass) {
2269         /* At present, annotations cannot possibly have a method that is override
2270          * equivalent with Object.equals(Object) but in any case the condition is
2271          * fine for completeness.
2272          */
2273         if (someClass == (ClassSymbol)syms.objectType.tsym ||
2274             someClass.isInterface() || someClass.isEnum() ||
2275             (someClass.flags() & ANNOTATION) != 0 ||
2276             (someClass.flags() & ABSTRACT) != 0) return;
2277         //anonymous inner classes implementing interfaces need especial treatment
2278         if (someClass.isAnonymous()) {
2279             List<Type> interfaces =  types.interfaces(someClass.type);
2280             if (interfaces != null && !interfaces.isEmpty() &&
2281                 interfaces.head.tsym == syms.comparatorType.tsym) return;
2282         }
2283         checkClassOverrideEqualsAndHash(pos, someClass);
2284     }
2285 
2286     private void checkClassOverrideEqualsAndHash(DiagnosticPosition pos,
2287             ClassSymbol someClass) {
2288         if (lint.isEnabled(LintCategory.OVERRIDES)) {
2289             MethodSymbol equalsAtObject = (MethodSymbol)syms.objectType
2290                     .tsym.members().findFirst(names.equals);
2291             MethodSymbol hashCodeAtObject = (MethodSymbol)syms.objectType
2292                     .tsym.members().findFirst(names.hashCode);
2293             MethodSymbol equalsImpl = types.implementation(equalsAtObject,
2294                     someClass, false, equalsHasCodeFilter);
2295             boolean overridesEquals = equalsImpl != null &&
2296                                       equalsImpl.owner == someClass;
2297             boolean overridesHashCode = types.implementation(hashCodeAtObject,
2298                 someClass, false, equalsHasCodeFilter) != hashCodeAtObject;
2299 
2300             if (overridesEquals && !overridesHashCode) {
2301                 log.warning(pos,
2302                             LintWarnings.OverrideEqualsButNotHashcode(someClass));
2303             }
2304         }
2305     }
2306 
2307     public void checkHasMain(DiagnosticPosition pos, ClassSymbol c) {
2308         boolean found = false;
2309 
2310         for (Symbol sym : c.members().getSymbolsByName(names.main)) {
2311             if (sym.kind == MTH && (sym.flags() & PRIVATE) == 0) {
2312                 MethodSymbol meth = (MethodSymbol)sym;
2313                 if (!types.isSameType(meth.getReturnType(), syms.voidType)) {
2314                     continue;
2315                 }
2316                 if (meth.params.isEmpty()) {
2317                     found = true;
2318                     break;
2319                 }
2320                 if (meth.params.size() != 1) {
2321                     continue;
2322                 }
2323                 if (!types.isSameType(meth.params.head.type, types.makeArrayType(syms.stringType))) {
2324                     continue;
2325                 }
2326 
2327                 found = true;
2328                 break;
2329             }
2330         }
2331 
2332         if (!found) {
2333             log.error(pos, Errors.ImplicitClassDoesNotHaveMainMethod);
2334         }
2335     }
2336 
2337     public void checkModuleName (JCModuleDecl tree) {
2338         Name moduleName = tree.sym.name;
2339         Assert.checkNonNull(moduleName);
2340         if (lint.isEnabled(LintCategory.MODULE)) {
2341             JCExpression qualId = tree.qualId;
2342             while (qualId != null) {
2343                 Name componentName;
2344                 DiagnosticPosition pos;
2345                 switch (qualId.getTag()) {
2346                     case SELECT:
2347                         JCFieldAccess selectNode = ((JCFieldAccess) qualId);
2348                         componentName = selectNode.name;
2349                         pos = selectNode.pos();
2350                         qualId = selectNode.selected;
2351                         break;
2352                     case IDENT:
2353                         componentName = ((JCIdent) qualId).name;
2354                         pos = qualId.pos();
2355                         qualId = null;
2356                         break;
2357                     default:
2358                         throw new AssertionError("Unexpected qualified identifier: " + qualId.toString());
2359                 }
2360                 if (componentName != null) {
2361                     String moduleNameComponentString = componentName.toString();
2362                     int nameLength = moduleNameComponentString.length();
2363                     if (nameLength > 0 && Character.isDigit(moduleNameComponentString.charAt(nameLength - 1))) {
2364                         log.warning(pos, LintWarnings.PoorChoiceForModuleName(componentName));
2365                     }
2366                 }
2367             }
2368         }
2369     }
2370 
2371     private boolean checkNameClash(ClassSymbol origin, Symbol s1, Symbol s2) {
2372         ClashFilter cf = new ClashFilter(origin.type);
2373         return (cf.test(s1) &&
2374                 cf.test(s2) &&
2375                 types.hasSameArgs(s1.erasure(types), s2.erasure(types)));
2376     }
2377 
2378 
2379     /** Check that all abstract members of given class have definitions.
2380      *  @param pos          Position to be used for error reporting.
2381      *  @param c            The class.
2382      */
2383     void checkAllDefined(DiagnosticPosition pos, ClassSymbol c) {
2384         MethodSymbol undef = types.firstUnimplementedAbstract(c);
2385         if (undef != null) {
2386             MethodSymbol undef1 =
2387                 new MethodSymbol(undef.flags(), undef.name,
2388                                  types.memberType(c.type, undef), undef.owner);
2389             log.error(pos,
2390                       Errors.DoesNotOverrideAbstract(c, undef1, undef1.location()));
2391         }
2392     }
2393 
2394     void checkNonCyclicDecl(JCClassDecl tree) {
2395         CycleChecker cc = new CycleChecker();
2396         cc.scan(tree);
2397         if (!cc.errorFound && !cc.partialCheck) {
2398             tree.sym.flags_field |= ACYCLIC;
2399         }
2400     }
2401 
2402     class CycleChecker extends TreeScanner {
2403 
2404         Set<Symbol> seenClasses = new HashSet<>();
2405         boolean errorFound = false;
2406         boolean partialCheck = false;
2407 
2408         private void checkSymbol(DiagnosticPosition pos, Symbol sym) {
2409             if (sym != null && sym.kind == TYP) {
2410                 Env<AttrContext> classEnv = enter.getEnv((TypeSymbol)sym);
2411                 if (classEnv != null) {
2412                     DiagnosticSource prevSource = log.currentSource();
2413                     try {
2414                         log.useSource(classEnv.toplevel.sourcefile);
2415                         scan(classEnv.tree);
2416                     }
2417                     finally {
2418                         log.useSource(prevSource.getFile());
2419                     }
2420                 } else if (sym.kind == TYP) {
2421                     checkClass(pos, sym, List.nil());
2422                 }
2423             } else if (sym == null || sym.kind != PCK) {
2424                 //not completed yet
2425                 partialCheck = true;
2426             }
2427         }
2428 
2429         @Override
2430         public void visitSelect(JCFieldAccess tree) {
2431             super.visitSelect(tree);
2432             checkSymbol(tree.pos(), tree.sym);
2433         }
2434 
2435         @Override
2436         public void visitIdent(JCIdent tree) {
2437             checkSymbol(tree.pos(), tree.sym);
2438         }
2439 
2440         @Override
2441         public void visitTypeApply(JCTypeApply tree) {
2442             scan(tree.clazz);
2443         }
2444 
2445         @Override
2446         public void visitTypeArray(JCArrayTypeTree tree) {
2447             scan(tree.elemtype);
2448         }
2449 
2450         @Override
2451         public void visitClassDef(JCClassDecl tree) {
2452             List<JCTree> supertypes = List.nil();
2453             if (tree.getExtendsClause() != null) {
2454                 supertypes = supertypes.prepend(tree.getExtendsClause());
2455             }
2456             if (tree.getImplementsClause() != null) {
2457                 for (JCTree intf : tree.getImplementsClause()) {
2458                     supertypes = supertypes.prepend(intf);
2459                 }
2460             }
2461             checkClass(tree.pos(), tree.sym, supertypes);
2462         }
2463 
2464         void checkClass(DiagnosticPosition pos, Symbol c, List<JCTree> supertypes) {
2465             if ((c.flags_field & ACYCLIC) != 0)
2466                 return;
2467             if (seenClasses.contains(c)) {
2468                 errorFound = true;
2469                 log.error(pos, Errors.CyclicInheritance(c));
2470                 seenClasses.stream()
2471                   .filter(s -> !s.type.isErroneous())
2472                   .filter(ClassSymbol.class::isInstance)
2473                   .map(ClassSymbol.class::cast)
2474                   .forEach(Check.this::handleCyclic);
2475             } else if (!c.type.isErroneous()) {
2476                 try {
2477                     seenClasses.add(c);
2478                     if (c.type.hasTag(CLASS)) {
2479                         if (supertypes.nonEmpty()) {
2480                             scan(supertypes);
2481                         }
2482                         else {
2483                             ClassType ct = (ClassType)c.type;
2484                             if (ct.supertype_field == null ||
2485                                     ct.interfaces_field == null) {
2486                                 //not completed yet
2487                                 partialCheck = true;
2488                                 return;
2489                             }
2490                             checkSymbol(pos, ct.supertype_field.tsym);
2491                             for (Type intf : ct.interfaces_field) {
2492                                 checkSymbol(pos, intf.tsym);
2493                             }
2494                         }
2495                         if (c.owner.kind == TYP) {
2496                             checkSymbol(pos, c.owner);
2497                         }
2498                     }
2499                 } finally {
2500                     seenClasses.remove(c);
2501                 }
2502             }
2503         }
2504     }
2505 
2506     /** Check for cyclic references. Issue an error if the
2507      *  symbol of the type referred to has a LOCKED flag set.
2508      *
2509      *  @param pos      Position to be used for error reporting.
2510      *  @param t        The type referred to.
2511      */
2512     void checkNonCyclic(DiagnosticPosition pos, Type t) {
2513         checkNonCyclicInternal(pos, t);
2514     }
2515 
2516 
2517     void checkNonCyclic(DiagnosticPosition pos, TypeVar t) {
2518         checkNonCyclic1(pos, t, List.nil());
2519     }
2520 
2521     private void checkNonCyclic1(DiagnosticPosition pos, Type t, List<TypeVar> seen) {
2522         final TypeVar tv;
2523         if  (t.hasTag(TYPEVAR) && (t.tsym.flags() & UNATTRIBUTED) != 0)
2524             return;
2525         if (seen.contains(t)) {
2526             tv = (TypeVar)t;
2527             tv.setUpperBound(types.createErrorType(t));
2528             log.error(pos, Errors.CyclicInheritance(t));
2529         } else if (t.hasTag(TYPEVAR)) {
2530             tv = (TypeVar)t;
2531             seen = seen.prepend(tv);
2532             for (Type b : types.getBounds(tv))
2533                 checkNonCyclic1(pos, b, seen);
2534         }
2535     }
2536 
2537     /** Check for cyclic references. Issue an error if the
2538      *  symbol of the type referred to has a LOCKED flag set.
2539      *
2540      *  @param pos      Position to be used for error reporting.
2541      *  @param t        The type referred to.
2542      *  @return        True if the check completed on all attributed classes
2543      */
2544     private boolean checkNonCyclicInternal(DiagnosticPosition pos, Type t) {
2545         boolean complete = true; // was the check complete?
2546         //- System.err.println("checkNonCyclicInternal("+t+");");//DEBUG
2547         Symbol c = t.tsym;
2548         if ((c.flags_field & ACYCLIC) != 0) return true;
2549 
2550         if ((c.flags_field & LOCKED) != 0) {
2551             log.error(pos, Errors.CyclicInheritance(c));
2552             handleCyclic((ClassSymbol)c);
2553         } else if (!c.type.isErroneous()) {
2554             try {
2555                 c.flags_field |= LOCKED;
2556                 if (c.type.hasTag(CLASS)) {
2557                     ClassType clazz = (ClassType)c.type;
2558                     if (clazz.interfaces_field != null)
2559                         for (List<Type> l=clazz.interfaces_field; l.nonEmpty(); l=l.tail)
2560                             complete &= checkNonCyclicInternal(pos, l.head);
2561                     if (clazz.supertype_field != null) {
2562                         Type st = clazz.supertype_field;
2563                         if (st != null && st.hasTag(CLASS))
2564                             complete &= checkNonCyclicInternal(pos, st);
2565                     }
2566                     if (c.owner.kind == TYP)
2567                         complete &= checkNonCyclicInternal(pos, c.owner.type);
2568                 }
2569             } finally {
2570                 c.flags_field &= ~LOCKED;
2571             }
2572         }
2573         if (complete)
2574             complete = ((c.flags_field & UNATTRIBUTED) == 0) && c.isCompleted();
2575         if (complete) c.flags_field |= ACYCLIC;
2576         return complete;
2577     }
2578 
2579     /** Handle finding an inheritance cycle on a class by setting
2580      *  the class' and its supertypes' types to the error type.
2581      **/
2582     private void handleCyclic(ClassSymbol c) {
2583         for (List<Type> l=types.interfaces(c.type); l.nonEmpty(); l=l.tail)
2584             l.head = types.createErrorType((ClassSymbol)l.head.tsym, Type.noType);
2585         Type st = types.supertype(c.type);
2586         if (st.hasTag(CLASS))
2587             ((ClassType)c.type).supertype_field = types.createErrorType((ClassSymbol)st.tsym, Type.noType);
2588         c.type = types.createErrorType(c, c.type);
2589         c.flags_field |= ACYCLIC;
2590     }
2591 
2592     /** Check that all methods which implement some
2593      *  method conform to the method they implement.
2594      *  @param tree         The class definition whose members are checked.
2595      */
2596     void checkImplementations(JCClassDecl tree) {
2597         checkImplementations(tree, tree.sym, tree.sym);
2598     }
2599     //where
2600         /** Check that all methods which implement some
2601          *  method in `ic' conform to the method they implement.
2602          */
2603         void checkImplementations(JCTree tree, ClassSymbol origin, ClassSymbol ic) {
2604             for (List<Type> l = types.closure(ic.type); l.nonEmpty(); l = l.tail) {
2605                 ClassSymbol lc = (ClassSymbol)l.head.tsym;
2606                 if ((lc.flags() & ABSTRACT) != 0) {
2607                     for (Symbol sym : lc.members().getSymbols(NON_RECURSIVE)) {
2608                         if (sym.kind == MTH &&
2609                             (sym.flags() & (STATIC|ABSTRACT)) == ABSTRACT) {
2610                             MethodSymbol absmeth = (MethodSymbol)sym;
2611                             MethodSymbol implmeth = absmeth.implementation(origin, types, false);
2612                             if (implmeth != null && implmeth != absmeth &&
2613                                 (implmeth.owner.flags() & INTERFACE) ==
2614                                 (origin.flags() & INTERFACE)) {
2615                                 // don't check if implmeth is in a class, yet
2616                                 // origin is an interface. This case arises only
2617                                 // if implmeth is declared in Object. The reason is
2618                                 // that interfaces really don't inherit from
2619                                 // Object it's just that the compiler represents
2620                                 // things that way.
2621                                 checkOverride(tree, implmeth, absmeth, origin);
2622                             }
2623                         }
2624                     }
2625                 }
2626             }
2627         }
2628 
2629     /** Check that all abstract methods implemented by a class are
2630      *  mutually compatible.
2631      *  @param pos          Position to be used for error reporting.
2632      *  @param c            The class whose interfaces are checked.
2633      */
2634     void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) {
2635         List<Type> supertypes = types.interfaces(c);
2636         Type supertype = types.supertype(c);
2637         if (supertype.hasTag(CLASS) &&
2638             (supertype.tsym.flags() & ABSTRACT) != 0)
2639             supertypes = supertypes.prepend(supertype);
2640         for (List<Type> l = supertypes; l.nonEmpty(); l = l.tail) {
2641             if (!l.head.getTypeArguments().isEmpty() &&
2642                 !checkCompatibleAbstracts(pos, l.head, l.head, c))
2643                 return;
2644             for (List<Type> m = supertypes; m != l; m = m.tail)
2645                 if (!checkCompatibleAbstracts(pos, l.head, m.head, c))
2646                     return;
2647         }
2648         checkCompatibleConcretes(pos, c);
2649 
2650         Type identitySuper = null;
2651         for (Type t : types.closure(c)) {
2652             if (t != c) {
2653                 if (t.isIdentityClass() && (t.tsym.flags() & VALUE_BASED) == 0)
2654                     identitySuper = t;
2655                 if (c.isValueClass() && identitySuper != null && identitySuper.tsym != syms.objectType.tsym) { // Object is special
2656                     log.error(pos, Errors.ValueTypeHasIdentitySuperType(c, identitySuper));
2657                     break;
2658                 }
2659             }
2660         }
2661     }
2662 
2663     /** Check that all non-override equivalent methods accessible from 'site'
2664      *  are mutually compatible (JLS 8.4.8/9.4.1).
2665      *
2666      *  @param pos  Position to be used for error reporting.
2667      *  @param site The class whose methods are checked.
2668      *  @param sym  The method symbol to be checked.
2669      */
2670     void checkOverrideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) {
2671          ClashFilter cf = new ClashFilter(site);
2672         //for each method m1 that is overridden (directly or indirectly)
2673         //by method 'sym' in 'site'...
2674 
2675         ArrayList<Symbol> symbolsByName = new ArrayList<>();
2676         types.membersClosure(site, false).getSymbolsByName(sym.name, cf).forEach(symbolsByName::add);
2677         for (Symbol m1 : symbolsByName) {
2678             if (!sym.overrides(m1, site.tsym, types, false)) {
2679                 continue;
2680             }
2681 
2682             //...check each method m2 that is a member of 'site'
2683             for (Symbol m2 : symbolsByName) {
2684                 if (m2 == m1) continue;
2685                 //if (i) the signature of 'sym' is not a subsignature of m1 (seen as
2686                 //a member of 'site') and (ii) m1 has the same erasure as m2, issue an error
2687                 if (!types.isSubSignature(sym.type, types.memberType(site, m2)) &&
2688                         types.hasSameArgs(m2.erasure(types), m1.erasure(types))) {
2689                     sym.flags_field |= CLASH;
2690                     if (m1 == sym) {
2691                         log.error(pos, Errors.NameClashSameErasureNoOverride(
2692                             m1.name, types.memberType(site, m1).asMethodType().getParameterTypes(), m1.location(),
2693                             m2.name, types.memberType(site, m2).asMethodType().getParameterTypes(), m2.location()));
2694                     } else {
2695                         ClassType ct = (ClassType)site;
2696                         String kind = ct.isInterface() ? "interface" : "class";
2697                         log.error(pos, Errors.NameClashSameErasureNoOverride1(
2698                             kind,
2699                             ct.tsym.name,
2700                             m1.name,
2701                             types.memberType(site, m1).asMethodType().getParameterTypes(),
2702                             m1.location(),
2703                             m2.name,
2704                             types.memberType(site, m2).asMethodType().getParameterTypes(),
2705                             m2.location()));
2706                     }
2707                     return;
2708                 }
2709             }
2710         }
2711     }
2712 
2713     /** Check that all static methods accessible from 'site' are
2714      *  mutually compatible (JLS 8.4.8).
2715      *
2716      *  @param pos  Position to be used for error reporting.
2717      *  @param site The class whose methods are checked.
2718      *  @param sym  The method symbol to be checked.
2719      */
2720     void checkHideClashes(DiagnosticPosition pos, Type site, MethodSymbol sym) {
2721         ClashFilter cf = new ClashFilter(site);
2722         //for each method m1 that is a member of 'site'...
2723         for (Symbol s : types.membersClosure(site, true).getSymbolsByName(sym.name, cf)) {
2724             //if (i) the signature of 'sym' is not a subsignature of m1 (seen as
2725             //a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error
2726             if (!types.isSubSignature(sym.type, types.memberType(site, s))) {
2727                 if (types.hasSameArgs(s.erasure(types), sym.erasure(types))) {
2728                     log.error(pos,
2729                               Errors.NameClashSameErasureNoHide(sym, sym.location(), s, s.location()));
2730                     return;
2731                 }
2732             }
2733          }
2734      }
2735 
2736      //where
2737      private class ClashFilter implements Predicate<Symbol> {
2738 
2739          Type site;
2740 
2741          ClashFilter(Type site) {
2742              this.site = site;
2743          }
2744 
2745          boolean shouldSkip(Symbol s) {
2746              return (s.flags() & CLASH) != 0 &&
2747                 s.owner == site.tsym;
2748          }
2749 
2750          @Override
2751          public boolean test(Symbol s) {
2752              return s.kind == MTH &&
2753                      (s.flags() & SYNTHETIC) == 0 &&
2754                      !shouldSkip(s) &&
2755                      s.isInheritedIn(site.tsym, types) &&
2756                      !s.isConstructor();
2757          }
2758      }
2759 
2760     void checkDefaultMethodClashes(DiagnosticPosition pos, Type site) {
2761         DefaultMethodClashFilter dcf = new DefaultMethodClashFilter(site);
2762         for (Symbol m : types.membersClosure(site, false).getSymbols(dcf)) {
2763             Assert.check(m.kind == MTH);
2764             List<MethodSymbol> prov = types.interfaceCandidates(site, (MethodSymbol)m);
2765             if (prov.size() > 1) {
2766                 ListBuffer<Symbol> abstracts = new ListBuffer<>();
2767                 ListBuffer<Symbol> defaults = new ListBuffer<>();
2768                 for (MethodSymbol provSym : prov) {
2769                     if ((provSym.flags() & DEFAULT) != 0) {
2770                         defaults = defaults.append(provSym);
2771                     } else if ((provSym.flags() & ABSTRACT) != 0) {
2772                         abstracts = abstracts.append(provSym);
2773                     }
2774                     if (defaults.nonEmpty() && defaults.size() + abstracts.size() >= 2) {
2775                         //strong semantics - issue an error if two sibling interfaces
2776                         //have two override-equivalent defaults - or if one is abstract
2777                         //and the other is default
2778                         Fragment diagKey;
2779                         Symbol s1 = defaults.first();
2780                         Symbol s2;
2781                         if (defaults.size() > 1) {
2782                             s2 = defaults.toList().tail.head;
2783                             diagKey = Fragments.IncompatibleUnrelatedDefaults(Kinds.kindName(site.tsym), site,
2784                                     m.name, types.memberType(site, m).getParameterTypes(),
2785                                     s1.location(), s2.location());
2786 
2787                         } else {
2788                             s2 = abstracts.first();
2789                             diagKey = Fragments.IncompatibleAbstractDefault(Kinds.kindName(site.tsym), site,
2790                                     m.name, types.memberType(site, m).getParameterTypes(),
2791                                     s1.location(), s2.location());
2792                         }
2793                         log.error(pos, Errors.TypesIncompatible(s1.location().type, s2.location().type, diagKey));
2794                         break;
2795                     }
2796                 }
2797             }
2798         }
2799     }
2800 
2801     //where
2802      private class DefaultMethodClashFilter implements Predicate<Symbol> {
2803 
2804          Type site;
2805 
2806          DefaultMethodClashFilter(Type site) {
2807              this.site = site;
2808          }
2809 
2810          @Override
2811          public boolean test(Symbol s) {
2812              return s.kind == MTH &&
2813                      (s.flags() & DEFAULT) != 0 &&
2814                      s.isInheritedIn(site.tsym, types) &&
2815                      !s.isConstructor();
2816          }
2817      }
2818 
2819     /** Report warnings for potentially ambiguous method declarations in the given site. */
2820     void checkPotentiallyAmbiguousOverloads(JCClassDecl tree, Type site) {
2821 
2822         // Skip if warning not enabled
2823         if (!lint.isEnabled(LintCategory.OVERLOADS))
2824             return;
2825 
2826         // Gather all of site's methods, including overridden methods, grouped by name (except Object methods)
2827         List<java.util.List<MethodSymbol>> methodGroups = methodsGroupedByName(site,
2828             new PotentiallyAmbiguousFilter(site), ArrayList::new);
2829 
2830         // Build the predicate that determines if site is responsible for an ambiguity
2831         BiPredicate<MethodSymbol, MethodSymbol> responsible = buildResponsiblePredicate(site, methodGroups);
2832 
2833         // Now remove overridden methods from each group, leaving only site's actual members
2834         methodGroups.forEach(list -> removePreempted(list, (m1, m2) -> m1.overrides(m2, site.tsym, types, false)));
2835 
2836         // Allow site's own declared methods (only) to apply @SuppressWarnings("overloads")
2837         methodGroups.forEach(list -> list.removeIf(
2838             m -> m.owner == site.tsym && !lint.augment(m).isEnabled(LintCategory.OVERLOADS)));
2839 
2840         // Warn about ambiguous overload method pairs for which site is responsible
2841         methodGroups.forEach(list -> compareAndRemove(list, (m1, m2) -> {
2842 
2843             // See if this is an ambiguous overload for which "site" is responsible
2844             if (!potentiallyAmbiguousOverload(site, m1, m2) || !responsible.test(m1, m2))
2845                 return 0;
2846 
2847             // Locate the warning at one of the methods, if possible
2848             DiagnosticPosition pos =
2849                 m1.owner == site.tsym ? TreeInfo.diagnosticPositionFor(m1, tree) :
2850                 m2.owner == site.tsym ? TreeInfo.diagnosticPositionFor(m2, tree) :
2851                 tree.pos();
2852 
2853             // Log the warning
2854             log.warning(pos,
2855                 LintWarnings.PotentiallyAmbiguousOverload(
2856                     m1.asMemberOf(site, types), m1.location(),
2857                     m2.asMemberOf(site, types), m2.location()));
2858 
2859             // Don't warn again for either of these two methods
2860             return FIRST | SECOND;
2861         }));
2862     }
2863 
2864     /** Build a predicate that determines, given two methods that are members of the given class,
2865      *  whether the class should be held "responsible" if the methods are potentially ambiguous.
2866      *
2867      *  Sometimes ambiguous methods are unavoidable because they're inherited from a supertype.
2868      *  For example, any subtype of Spliterator.OfInt will have ambiguities for both
2869      *  forEachRemaining() and tryAdvance() (in both cases the overloads are IntConsumer and
2870      *  Consumer&lt;? super Integer&gt;). So we only want to "blame" a class when that class is
2871      *  itself responsible for creating the ambiguity. We declare that a class C is "responsible"
2872      *  for the ambiguity between two methods m1 and m2 if there is no direct supertype T of C
2873      *  such that m1 and m2, or some overrides thereof, both exist in T and are ambiguous in T.
2874      *  As an optimization, we first check if either method is declared in C and does not override
2875      *  any other methods; in this case the class is definitely responsible.
2876      */
2877     BiPredicate<MethodSymbol, MethodSymbol> buildResponsiblePredicate(Type site,
2878         List<? extends Collection<MethodSymbol>> methodGroups) {
2879 
2880         // Define the "overrides" predicate
2881         BiPredicate<MethodSymbol, MethodSymbol> overrides = (m1, m2) -> m1.overrides(m2, site.tsym, types, false);
2882 
2883         // Map each method declared in site to a list of the supertype method(s) it directly overrides
2884         HashMap<MethodSymbol, ArrayList<MethodSymbol>> overriddenMethodsMap = new HashMap<>();
2885         methodGroups.forEach(list -> {
2886             for (MethodSymbol m : list) {
2887 
2888                 // Skip methods not declared in site
2889                 if (m.owner != site.tsym)
2890                     continue;
2891 
2892                 // Gather all supertype methods overridden by m, directly or indirectly
2893                 ArrayList<MethodSymbol> overriddenMethods = list.stream()
2894                   .filter(m2 -> m2 != m && overrides.test(m, m2))
2895                   .collect(Collectors.toCollection(ArrayList::new));
2896 
2897                 // Eliminate non-direct overrides
2898                 removePreempted(overriddenMethods, overrides);
2899 
2900                 // Add to map
2901                 overriddenMethodsMap.put(m, overriddenMethods);
2902             }
2903         });
2904 
2905         // Build the predicate
2906         return (m1, m2) -> {
2907 
2908             // Get corresponding supertype methods (if declared in site)
2909             java.util.List<MethodSymbol> overriddenMethods1 = overriddenMethodsMap.get(m1);
2910             java.util.List<MethodSymbol> overriddenMethods2 = overriddenMethodsMap.get(m2);
2911 
2912             // Quick check for the case where a method was added by site itself
2913             if (overriddenMethods1 != null && overriddenMethods1.isEmpty())
2914                 return true;
2915             if (overriddenMethods2 != null && overriddenMethods2.isEmpty())
2916                 return true;
2917 
2918             // Get each method's corresponding method(s) from supertypes of site
2919             java.util.List<MethodSymbol> supertypeMethods1 = overriddenMethods1 != null ?
2920               overriddenMethods1 : Collections.singletonList(m1);
2921             java.util.List<MethodSymbol> supertypeMethods2 = overriddenMethods2 != null ?
2922               overriddenMethods2 : Collections.singletonList(m2);
2923 
2924             // See if we can blame some direct supertype instead
2925             return types.directSupertypes(site).stream()
2926               .filter(stype -> stype != syms.objectType)
2927               .map(stype -> stype.tsym.type)                // view supertype in its original form
2928               .noneMatch(stype -> {
2929                 for (MethodSymbol sm1 : supertypeMethods1) {
2930                     if (!types.isSubtype(types.erasure(stype), types.erasure(sm1.owner.type)))
2931                         continue;
2932                     for (MethodSymbol sm2 : supertypeMethods2) {
2933                         if (!types.isSubtype(types.erasure(stype), types.erasure(sm2.owner.type)))
2934                             continue;
2935                         if (potentiallyAmbiguousOverload(stype, sm1, sm2))
2936                             return true;
2937                     }
2938                 }
2939                 return false;
2940             });
2941         };
2942     }
2943 
2944     /** Gather all of site's methods, including overridden methods, grouped and sorted by name,
2945      *  after applying the given filter.
2946      */
2947     <C extends Collection<MethodSymbol>> List<C> methodsGroupedByName(Type site,
2948             Predicate<Symbol> filter, Supplier<? extends C> groupMaker) {
2949         Iterable<Symbol> symbols = types.membersClosure(site, false).getSymbols(filter, RECURSIVE);
2950         return StreamSupport.stream(symbols.spliterator(), false)
2951           .map(MethodSymbol.class::cast)
2952           .collect(Collectors.groupingBy(m -> m.name, Collectors.toCollection(groupMaker)))
2953           .entrySet()
2954           .stream()
2955           .sorted(Comparator.comparing(e -> e.getKey().toString()))
2956           .map(Map.Entry::getValue)
2957           .collect(List.collector());
2958     }
2959 
2960     /** Compare elements in a list pair-wise in order to remove some of them.
2961      *  @param list mutable list of items
2962      *  @param comparer returns flag bit(s) to remove FIRST and/or SECOND
2963      */
2964     <T> void compareAndRemove(java.util.List<T> list, ToIntBiFunction<? super T, ? super T> comparer) {
2965         for (int index1 = 0; index1 < list.size() - 1; index1++) {
2966             T item1 = list.get(index1);
2967             for (int index2 = index1 + 1; index2 < list.size(); index2++) {
2968                 T item2 = list.get(index2);
2969                 int flags = comparer.applyAsInt(item1, item2);
2970                 if ((flags & SECOND) != 0)
2971                     list.remove(index2--);          // remove item2
2972                 if ((flags & FIRST) != 0) {
2973                     list.remove(index1--);          // remove item1
2974                     break;
2975                 }
2976             }
2977         }
2978     }
2979 
2980     /** Remove elements in a list that are preempted by some other element in the list.
2981      *  @param list mutable list of items
2982      *  @param preempts decides if one item preempts another, causing the second one to be removed
2983      */
2984     <T> void removePreempted(java.util.List<T> list, BiPredicate<? super T, ? super T> preempts) {
2985         compareAndRemove(list, (item1, item2) -> {
2986             int flags = 0;
2987             if (preempts.test(item1, item2))
2988                 flags |= SECOND;
2989             if (preempts.test(item2, item1))
2990                 flags |= FIRST;
2991             return flags;
2992         });
2993     }
2994 
2995     /** Filters method candidates for the "potentially ambiguous method" check */
2996     class PotentiallyAmbiguousFilter extends ClashFilter {
2997 
2998         PotentiallyAmbiguousFilter(Type site) {
2999             super(site);
3000         }
3001 
3002         @Override
3003         boolean shouldSkip(Symbol s) {
3004             return s.owner.type.tsym == syms.objectType.tsym || super.shouldSkip(s);
3005         }
3006     }
3007 
3008     /**
3009       * Report warnings for potentially ambiguous method declarations. Two declarations
3010       * are potentially ambiguous if they feature two unrelated functional interface
3011       * in same argument position (in which case, a call site passing an implicit
3012       * lambda would be ambiguous). This assumes they already have the same name.
3013       */
3014     boolean potentiallyAmbiguousOverload(Type site, MethodSymbol msym1, MethodSymbol msym2) {
3015         Assert.check(msym1.name == msym2.name);
3016         if (msym1 == msym2)
3017             return false;
3018         Type mt1 = types.memberType(site, msym1);
3019         Type mt2 = types.memberType(site, msym2);
3020         //if both generic methods, adjust type variables
3021         if (mt1.hasTag(FORALL) && mt2.hasTag(FORALL) &&
3022                 types.hasSameBounds((ForAll)mt1, (ForAll)mt2)) {
3023             mt2 = types.subst(mt2, ((ForAll)mt2).tvars, ((ForAll)mt1).tvars);
3024         }
3025         //expand varargs methods if needed
3026         int maxLength = Math.max(mt1.getParameterTypes().length(), mt2.getParameterTypes().length());
3027         List<Type> args1 = rs.adjustArgs(mt1.getParameterTypes(), msym1, maxLength, true);
3028         List<Type> args2 = rs.adjustArgs(mt2.getParameterTypes(), msym2, maxLength, true);
3029         //if arities don't match, exit
3030         if (args1.length() != args2.length())
3031             return false;
3032         boolean potentiallyAmbiguous = false;
3033         while (args1.nonEmpty() && args2.nonEmpty()) {
3034             Type s = args1.head;
3035             Type t = args2.head;
3036             if (!types.isSubtype(t, s) && !types.isSubtype(s, t)) {
3037                 if (types.isFunctionalInterface(s) && types.isFunctionalInterface(t) &&
3038                         types.findDescriptorType(s).getParameterTypes().length() > 0 &&
3039                         types.findDescriptorType(s).getParameterTypes().length() ==
3040                         types.findDescriptorType(t).getParameterTypes().length()) {
3041                     potentiallyAmbiguous = true;
3042                 } else {
3043                     return false;
3044                 }
3045             }
3046             args1 = args1.tail;
3047             args2 = args2.tail;
3048         }
3049         return potentiallyAmbiguous;
3050     }
3051 
3052     // Apply special flag "-XDwarnOnAccessToMembers" which turns on just this particular warning for all types of access
3053     void checkAccessFromSerializableElement(final JCTree tree, boolean isLambda) {
3054         final Lint prevLint = setLint(warnOnAnyAccessToMembers ? lint.enable(LintCategory.SERIAL) : lint);
3055         try {
3056             if (warnOnAnyAccessToMembers || isLambda)
3057                 checkAccessFromSerializableElementInner(tree, isLambda);
3058         } finally {
3059             setLint(prevLint);
3060         }
3061     }
3062 
3063     private void checkAccessFromSerializableElementInner(final JCTree tree, boolean isLambda) {
3064         if (lint.isEnabled(LintCategory.SERIAL)) {
3065             Symbol sym = TreeInfo.symbol(tree);
3066             if (!sym.kind.matches(KindSelector.VAL_MTH)) {
3067                 return;
3068             }
3069 
3070             if (sym.kind == VAR) {
3071                 if ((sym.flags() & PARAMETER) != 0 ||
3072                     sym.isDirectlyOrIndirectlyLocal() ||
3073                     sym.name == names._this ||
3074                     sym.name == names._super) {
3075                     return;
3076                 }
3077             }
3078 
3079             if (!types.isSubtype(sym.owner.type, syms.serializableType) &&
3080                 isEffectivelyNonPublic(sym)) {
3081                 if (isLambda) {
3082                     if (belongsToRestrictedPackage(sym)) {
3083                         log.warning(tree.pos(),
3084                                     LintWarnings.AccessToMemberFromSerializableLambda(sym));
3085                     }
3086                 } else {
3087                     log.warning(tree.pos(),
3088                                 LintWarnings.AccessToMemberFromSerializableElement(sym));
3089                 }
3090             }
3091         }
3092     }
3093 
3094     private boolean isEffectivelyNonPublic(Symbol sym) {
3095         if (sym.packge() == syms.rootPackage) {
3096             return false;
3097         }
3098 
3099         while (sym.kind != PCK) {
3100             if ((sym.flags() & PUBLIC) == 0) {
3101                 return true;
3102             }
3103             sym = sym.owner;
3104         }
3105         return false;
3106     }
3107 
3108     private boolean belongsToRestrictedPackage(Symbol sym) {
3109         String fullName = sym.packge().fullname.toString();
3110         return fullName.startsWith("java.") ||
3111                 fullName.startsWith("javax.") ||
3112                 fullName.startsWith("sun.") ||
3113                 fullName.contains(".internal.");
3114     }
3115 
3116     /** Check that class c does not implement directly or indirectly
3117      *  the same parameterized interface with two different argument lists.
3118      *  @param pos          Position to be used for error reporting.
3119      *  @param type         The type whose interfaces are checked.
3120      */
3121     void checkClassBounds(DiagnosticPosition pos, Type type) {
3122         checkClassBounds(pos, new HashMap<TypeSymbol,Type>(), type);
3123     }
3124 //where
3125         /** Enter all interfaces of type `type' into the hash table `seensofar'
3126          *  with their class symbol as key and their type as value. Make
3127          *  sure no class is entered with two different types.
3128          */
3129         void checkClassBounds(DiagnosticPosition pos,
3130                               Map<TypeSymbol,Type> seensofar,
3131                               Type type) {
3132             if (type.isErroneous()) return;
3133             for (List<Type> l = types.interfaces(type); l.nonEmpty(); l = l.tail) {
3134                 Type it = l.head;
3135                 if (type.hasTag(CLASS) && !it.hasTag(CLASS)) continue; // JLS 8.1.5
3136 
3137                 Type oldit = seensofar.put(it.tsym, it);
3138                 if (oldit != null) {
3139                     List<Type> oldparams = oldit.allparams();
3140                     List<Type> newparams = it.allparams();
3141                     if (!types.containsTypeEquivalent(oldparams, newparams))
3142                         log.error(pos,
3143                                   Errors.CantInheritDiffArg(it.tsym,
3144                                                             Type.toString(oldparams),
3145                                                             Type.toString(newparams)));
3146                 }
3147                 checkClassBounds(pos, seensofar, it);
3148             }
3149             Type st = types.supertype(type);
3150             if (type.hasTag(CLASS) && !st.hasTag(CLASS)) return; // JLS 8.1.4
3151             if (st != Type.noType) checkClassBounds(pos, seensofar, st);
3152         }
3153 
3154     /** Enter interface into into set.
3155      *  If it existed already, issue a "repeated interface" error.
3156      */
3157     void checkNotRepeated(DiagnosticPosition pos, Type it, Set<Symbol> its) {
3158         if (its.contains(it.tsym))
3159             log.error(pos, Errors.RepeatedInterface);
3160         else {
3161             its.add(it.tsym);
3162         }
3163     }
3164 
3165 /* *************************************************************************
3166  * Check annotations
3167  **************************************************************************/
3168 
3169     /**
3170      * Recursively validate annotations values
3171      */
3172     void validateAnnotationTree(JCTree tree) {
3173         class AnnotationValidator extends TreeScanner {
3174             @Override
3175             public void visitAnnotation(JCAnnotation tree) {
3176                 if (!tree.type.isErroneous() && tree.type.tsym.isAnnotationType()) {
3177                     super.visitAnnotation(tree);
3178                     validateAnnotation(tree);
3179                 }
3180             }
3181         }
3182         tree.accept(new AnnotationValidator());
3183     }
3184 
3185     /**
3186      *  {@literal
3187      *  Annotation types are restricted to primitives, String, an
3188      *  enum, an annotation, Class, Class<?>, Class<? extends
3189      *  Anything>, arrays of the preceding.
3190      *  }
3191      */
3192     void validateAnnotationType(JCTree restype) {
3193         // restype may be null if an error occurred, so don't bother validating it
3194         if (restype != null) {
3195             validateAnnotationType(restype.pos(), restype.type);
3196         }
3197     }
3198 
3199     void validateAnnotationType(DiagnosticPosition pos, Type type) {
3200         if (type.isPrimitive()) return;
3201         if (types.isSameType(type, syms.stringType)) return;
3202         if ((type.tsym.flags() & Flags.ENUM) != 0) return;
3203         if ((type.tsym.flags() & Flags.ANNOTATION) != 0) return;
3204         if (types.cvarLowerBound(type).tsym == syms.classType.tsym) return;
3205         if (types.isArray(type) && !types.isArray(types.elemtype(type))) {
3206             validateAnnotationType(pos, types.elemtype(type));
3207             return;
3208         }
3209         log.error(pos, Errors.InvalidAnnotationMemberType);
3210     }
3211 
3212     /**
3213      * "It is also a compile-time error if any method declared in an
3214      * annotation type has a signature that is override-equivalent to
3215      * that of any public or protected method declared in class Object
3216      * or in the interface annotation.Annotation."
3217      *
3218      * @jls 9.6 Annotation Types
3219      */
3220     void validateAnnotationMethod(DiagnosticPosition pos, MethodSymbol m) {
3221         for (Type sup = syms.annotationType; sup.hasTag(CLASS); sup = types.supertype(sup)) {
3222             Scope s = sup.tsym.members();
3223             for (Symbol sym : s.getSymbolsByName(m.name)) {
3224                 if (sym.kind == MTH &&
3225                     (sym.flags() & (PUBLIC | PROTECTED)) != 0 &&
3226                     types.overrideEquivalent(m.type, sym.type))
3227                     log.error(pos, Errors.IntfAnnotationMemberClash(sym, sup));
3228             }
3229         }
3230     }
3231 
3232     /** Check the annotations of a symbol.
3233      */
3234     public void validateAnnotations(List<JCAnnotation> annotations, JCTree declarationTree, Symbol s) {
3235         for (JCAnnotation a : annotations)
3236             validateAnnotation(a, declarationTree, s);
3237     }
3238 
3239     /** Check the type annotations.
3240      */
3241     public void validateTypeAnnotations(List<JCAnnotation> annotations, Symbol s, boolean isTypeParameter) {
3242         for (JCAnnotation a : annotations)
3243             validateTypeAnnotation(a, s, isTypeParameter);
3244     }
3245 
3246     /** Check an annotation of a symbol.
3247      */
3248     private void validateAnnotation(JCAnnotation a, JCTree declarationTree, Symbol s) {
3249         /** NOTE: if annotation processors are present, annotation processing rounds can happen after this method,
3250          *  this can impact in particular records for which annotations are forcibly propagated.
3251          */
3252         validateAnnotationTree(a);
3253         boolean isRecordMember = ((s.flags_field & RECORD) != 0 || s.enclClass() != null && s.enclClass().isRecord());
3254 
3255         boolean isRecordField = (s.flags_field & RECORD) != 0 &&
3256                 declarationTree.hasTag(VARDEF) &&
3257                 s.owner.kind == TYP;
3258 
3259         if (isRecordField) {
3260             // first we need to check if the annotation is applicable to records
3261             Name[] targets = getTargetNames(a);
3262             boolean appliesToRecords = false;
3263             for (Name target : targets) {
3264                 appliesToRecords =
3265                                 target == names.FIELD ||
3266                                 target == names.PARAMETER ||
3267                                 target == names.METHOD ||
3268                                 target == names.TYPE_USE ||
3269                                 target == names.RECORD_COMPONENT;
3270                 if (appliesToRecords) {
3271                     break;
3272                 }
3273             }
3274             if (!appliesToRecords) {
3275                 log.error(a.pos(), Errors.AnnotationTypeNotApplicable);
3276             } else {
3277                 /* lets now find the annotations in the field that are targeted to record components and append them to
3278                  * the corresponding record component
3279                  */
3280                 ClassSymbol recordClass = (ClassSymbol) s.owner;
3281                 RecordComponent rc = recordClass.getRecordComponent((VarSymbol)s);
3282                 SymbolMetadata metadata = rc.getMetadata();
3283                 if (metadata == null || metadata.isEmpty()) {
3284                     /* if not is empty then we have already been here, which is the case if multiple annotations are applied
3285                      * to the record component declaration
3286                      */
3287                     rc.appendAttributes(s.getRawAttributes().stream().filter(anno ->
3288                             Arrays.stream(getTargetNames(anno.type.tsym)).anyMatch(name -> name == names.RECORD_COMPONENT)
3289                     ).collect(List.collector()));
3290 
3291                     JCVariableDecl fieldAST = (JCVariableDecl) declarationTree;
3292                     for (JCAnnotation fieldAnnot : fieldAST.mods.annotations) {
3293                         for (JCAnnotation rcAnnot : rc.declarationFor().mods.annotations) {
3294                             if (rcAnnot.pos == fieldAnnot.pos) {
3295                                 rcAnnot.setType(fieldAnnot.type);
3296                                 break;
3297                             }
3298                         }
3299                     }
3300 
3301                     /* At this point, we used to carry over any type annotations from the VARDEF to the record component, but
3302                      * that is problematic, since we get here only when *some* annotation is applied to the SE5 (declaration)
3303                      * annotation location, inadvertently failing to carry over the type annotations when the VarDef has no
3304                      * annotations in the SE5 annotation location.
3305                      *
3306                      * Now type annotations are assigned to record components in a method that would execute irrespective of
3307                      * whether there are SE5 annotations on a VarDef viz com.sun.tools.javac.code.TypeAnnotations.TypeAnnotationPositions.visitVarDef
3308                      */
3309                 }
3310             }
3311         }
3312 
3313         /* the section below is tricky. Annotations applied to record components are propagated to the corresponding
3314          * record member so if an annotation has target: FIELD, it is propagated to the corresponding FIELD, if it has
3315          * target METHOD, it is propagated to the accessor and so on. But at the moment when method members are generated
3316          * there is no enough information to propagate only the right annotations. So all the annotations are propagated
3317          * to all the possible locations.
3318          *
3319          * At this point we need to remove all the annotations that are not in place before going on with the annotation
3320          * party. On top of the above there is the issue that there is no AST representing record components, just symbols
3321          * so the corresponding field has been holding all the annotations and it's metadata has been modified as if it
3322          * was both a field and a record component.
3323          *
3324          * So there are two places where we need to trim annotations from: the metadata of the symbol and / or the modifiers
3325          * in the AST. Whatever is in the metadata will be written to the class file, whatever is in the modifiers could
3326          * be see by annotation processors.
3327          *
3328          * The metadata contains both type annotations and declaration annotations. At this point of the game we don't
3329          * need to care about type annotations, they are all in the right place. But we could need to remove declaration
3330          * annotations. So for declaration annotations if they are not applicable to the record member, excluding type
3331          * annotations which are already correct, then we will remove it. For the AST modifiers if the annotation is not
3332          * applicable either as type annotation and or declaration annotation, only in that case it will be removed.
3333          *
3334          * So it could be that annotation is removed as a declaration annotation but it is kept in the AST modifier for
3335          * further inspection by annotation processors.
3336          *
3337          * For example:
3338          *
3339          *     import java.lang.annotation.*;
3340          *
3341          *     @Target({ElementType.TYPE_USE, ElementType.RECORD_COMPONENT})
3342          *     @Retention(RetentionPolicy.RUNTIME)
3343          *     @interface Anno { }
3344          *
3345          *     record R(@Anno String s) {}
3346          *
3347          * at this point we will have for the case of the generated field:
3348          *   - @Anno in the modifier
3349          *   - @Anno as a type annotation
3350          *   - @Anno as a declaration annotation
3351          *
3352          * the last one should be removed because the annotation has not FIELD as target but it was applied as a
3353          * declaration annotation because the field was being treated both as a field and as a record component
3354          * as we have already copied the annotations to the record component, now the field doesn't need to hold
3355          * annotations that are not intended for it anymore. Still @Anno has to be kept in the AST's modifiers as it
3356          * is applicable as a type annotation to the type of the field.
3357          */
3358 
3359         if (a.type.tsym.isAnnotationType()) {
3360             Optional<Set<Name>> applicableTargetsOp = getApplicableTargets(a, s);
3361             if (!applicableTargetsOp.isEmpty()) {
3362                 Set<Name> applicableTargets = applicableTargetsOp.get();
3363                 boolean notApplicableOrIsTypeUseOnly = applicableTargets.isEmpty() ||
3364                         applicableTargets.size() == 1 && applicableTargets.contains(names.TYPE_USE);
3365                 boolean isCompGeneratedRecordElement = isRecordMember && (s.flags_field & Flags.GENERATED_MEMBER) != 0;
3366                 boolean isCompRecordElementWithNonApplicableDeclAnno = isCompGeneratedRecordElement && notApplicableOrIsTypeUseOnly;
3367 
3368                 if (applicableTargets.isEmpty() || isCompRecordElementWithNonApplicableDeclAnno) {
3369                     if (isCompRecordElementWithNonApplicableDeclAnno) {
3370                             /* so we have found an annotation that is not applicable to a record member that was generated by the
3371                              * compiler. This was intentionally done at TypeEnter, now is the moment strip away the annotations
3372                              * that are not applicable to the given record member
3373                              */
3374                         JCModifiers modifiers = TreeInfo.getModifiers(declarationTree);
3375                             /* lets first remove the annotation from the modifier if it is not applicable, we have to check again as
3376                              * it could be a type annotation
3377                              */
3378                         if (modifiers != null && applicableTargets.isEmpty()) {
3379                             ListBuffer<JCAnnotation> newAnnotations = new ListBuffer<>();
3380                             for (JCAnnotation anno : modifiers.annotations) {
3381                                 if (anno != a) {
3382                                     newAnnotations.add(anno);
3383                                 }
3384                             }
3385                             modifiers.annotations = newAnnotations.toList();
3386                         }
3387                         // now lets remove it from the symbol
3388                         s.getMetadata().removeDeclarationMetadata(a.attribute);
3389                     } else {
3390                         log.error(a.pos(), Errors.AnnotationTypeNotApplicable);
3391                     }
3392                 }
3393                 /* if we are seeing the @SafeVarargs annotation applied to a compiler generated accessor,
3394                  * then this is an error as we know that no compiler generated accessor will be a varargs
3395                  * method, better to fail asap
3396                  */
3397                 if (isCompGeneratedRecordElement && !isRecordField && a.type.tsym == syms.trustMeType.tsym && declarationTree.hasTag(METHODDEF)) {
3398                     log.error(a.pos(), Errors.VarargsInvalidTrustmeAnno(syms.trustMeType.tsym, Fragments.VarargsTrustmeOnNonVarargsAccessor(s)));
3399                 }
3400             }
3401         }
3402 
3403         if (a.annotationType.type.tsym == syms.functionalInterfaceType.tsym) {
3404             if (s.kind != TYP) {
3405                 log.error(a.pos(), Errors.BadFunctionalIntfAnno);
3406             } else if (!s.isInterface() || (s.flags() & ANNOTATION) != 0) {
3407                 log.error(a.pos(), Errors.BadFunctionalIntfAnno1(Fragments.NotAFunctionalIntf(s)));
3408             }
3409         }
3410     }
3411 
3412     public void validateTypeAnnotation(JCAnnotation a, Symbol s, boolean isTypeParameter) {
3413         Assert.checkNonNull(a.type);
3414         // we just want to validate that the anotation doesn't have any wrong target
3415         if (s != null) getApplicableTargets(a, s);
3416         validateAnnotationTree(a);
3417 
3418         if (a.hasTag(TYPE_ANNOTATION) &&
3419                 !a.annotationType.type.isErroneous() &&
3420                 !isTypeAnnotation(a, isTypeParameter)) {
3421             log.error(a.pos(), Errors.AnnotationTypeNotApplicableToType(a.type));
3422         }
3423     }
3424 
3425     /**
3426      * Validate the proposed container 'repeatable' on the
3427      * annotation type symbol 's'. Report errors at position
3428      * 'pos'.
3429      *
3430      * @param s The (annotation)type declaration annotated with a @Repeatable
3431      * @param repeatable the @Repeatable on 's'
3432      * @param pos where to report errors
3433      */
3434     public void validateRepeatable(TypeSymbol s, Attribute.Compound repeatable, DiagnosticPosition pos) {
3435         Assert.check(types.isSameType(repeatable.type, syms.repeatableType));
3436 
3437         Type t = null;
3438         List<Pair<MethodSymbol,Attribute>> l = repeatable.values;
3439         if (!l.isEmpty()) {
3440             Assert.check(l.head.fst.name == names.value);
3441             if (l.head.snd instanceof Attribute.Class) {
3442                 t = ((Attribute.Class)l.head.snd).getValue();
3443             }
3444         }
3445 
3446         if (t == null) {
3447             // errors should already have been reported during Annotate
3448             return;
3449         }
3450 
3451         validateValue(t.tsym, s, pos);
3452         validateRetention(t.tsym, s, pos);
3453         validateDocumented(t.tsym, s, pos);
3454         validateInherited(t.tsym, s, pos);
3455         validateTarget(t.tsym, s, pos);
3456         validateDefault(t.tsym, pos);
3457     }
3458 
3459     private void validateValue(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
3460         Symbol sym = container.members().findFirst(names.value);
3461         if (sym != null && sym.kind == MTH) {
3462             MethodSymbol m = (MethodSymbol) sym;
3463             Type ret = m.getReturnType();
3464             if (!(ret.hasTag(ARRAY) && types.isSameType(((ArrayType)ret).elemtype, contained.type))) {
3465                 log.error(pos,
3466                           Errors.InvalidRepeatableAnnotationValueReturn(container,
3467                                                                         ret,
3468                                                                         types.makeArrayType(contained.type)));
3469             }
3470         } else {
3471             log.error(pos, Errors.InvalidRepeatableAnnotationNoValue(container));
3472         }
3473     }
3474 
3475     private void validateRetention(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
3476         Attribute.RetentionPolicy containerRetention = types.getRetention(container);
3477         Attribute.RetentionPolicy containedRetention = types.getRetention(contained);
3478 
3479         boolean error = false;
3480         switch (containedRetention) {
3481         case RUNTIME:
3482             if (containerRetention != Attribute.RetentionPolicy.RUNTIME) {
3483                 error = true;
3484             }
3485             break;
3486         case CLASS:
3487             if (containerRetention == Attribute.RetentionPolicy.SOURCE)  {
3488                 error = true;
3489             }
3490         }
3491         if (error ) {
3492             log.error(pos,
3493                       Errors.InvalidRepeatableAnnotationRetention(container,
3494                                                                   containerRetention.name(),
3495                                                                   contained,
3496                                                                   containedRetention.name()));
3497         }
3498     }
3499 
3500     private void validateDocumented(Symbol container, Symbol contained, DiagnosticPosition pos) {
3501         if (contained.attribute(syms.documentedType.tsym) != null) {
3502             if (container.attribute(syms.documentedType.tsym) == null) {
3503                 log.error(pos, Errors.InvalidRepeatableAnnotationNotDocumented(container, contained));
3504             }
3505         }
3506     }
3507 
3508     private void validateInherited(Symbol container, Symbol contained, DiagnosticPosition pos) {
3509         if (contained.attribute(syms.inheritedType.tsym) != null) {
3510             if (container.attribute(syms.inheritedType.tsym) == null) {
3511                 log.error(pos, Errors.InvalidRepeatableAnnotationNotInherited(container, contained));
3512             }
3513         }
3514     }
3515 
3516     private void validateTarget(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
3517         // The set of targets the container is applicable to must be a subset
3518         // (with respect to annotation target semantics) of the set of targets
3519         // the contained is applicable to. The target sets may be implicit or
3520         // explicit.
3521 
3522         Set<Name> containerTargets;
3523         Attribute.Array containerTarget = getAttributeTargetAttribute(container);
3524         if (containerTarget == null) {
3525             containerTargets = getDefaultTargetSet();
3526         } else {
3527             containerTargets = new HashSet<>();
3528             for (Attribute app : containerTarget.values) {
3529                 if (!(app instanceof Attribute.Enum attributeEnum)) {
3530                     continue; // recovery
3531                 }
3532                 containerTargets.add(attributeEnum.value.name);
3533             }
3534         }
3535 
3536         Set<Name> containedTargets;
3537         Attribute.Array containedTarget = getAttributeTargetAttribute(contained);
3538         if (containedTarget == null) {
3539             containedTargets = getDefaultTargetSet();
3540         } else {
3541             containedTargets = new HashSet<>();
3542             for (Attribute app : containedTarget.values) {
3543                 if (!(app instanceof Attribute.Enum attributeEnum)) {
3544                     continue; // recovery
3545                 }
3546                 containedTargets.add(attributeEnum.value.name);
3547             }
3548         }
3549 
3550         if (!isTargetSubsetOf(containerTargets, containedTargets)) {
3551             log.error(pos, Errors.InvalidRepeatableAnnotationIncompatibleTarget(container, contained));
3552         }
3553     }
3554 
3555     /* get a set of names for the default target */
3556     private Set<Name> getDefaultTargetSet() {
3557         if (defaultTargets == null) {
3558             defaultTargets = Set.of(defaultTargetMetaInfo());
3559         }
3560 
3561         return defaultTargets;
3562     }
3563     private Set<Name> defaultTargets;
3564 
3565 
3566     /** Checks that s is a subset of t, with respect to ElementType
3567      * semantics, specifically {ANNOTATION_TYPE} is a subset of {TYPE},
3568      * and {TYPE_USE} covers the set {ANNOTATION_TYPE, TYPE, TYPE_USE,
3569      * TYPE_PARAMETER}.
3570      */
3571     private boolean isTargetSubsetOf(Set<Name> s, Set<Name> t) {
3572         // Check that all elements in s are present in t
3573         for (Name n2 : s) {
3574             boolean currentElementOk = false;
3575             for (Name n1 : t) {
3576                 if (n1 == n2) {
3577                     currentElementOk = true;
3578                     break;
3579                 } else if (n1 == names.TYPE && n2 == names.ANNOTATION_TYPE) {
3580                     currentElementOk = true;
3581                     break;
3582                 } else if (n1 == names.TYPE_USE &&
3583                         (n2 == names.TYPE ||
3584                          n2 == names.ANNOTATION_TYPE ||
3585                          n2 == names.TYPE_PARAMETER)) {
3586                     currentElementOk = true;
3587                     break;
3588                 }
3589             }
3590             if (!currentElementOk)
3591                 return false;
3592         }
3593         return true;
3594     }
3595 
3596     private void validateDefault(Symbol container, DiagnosticPosition pos) {
3597         // validate that all other elements of containing type has defaults
3598         Scope scope = container.members();
3599         for(Symbol elm : scope.getSymbols()) {
3600             if (elm.name != names.value &&
3601                 elm.kind == MTH &&
3602                 ((MethodSymbol)elm).defaultValue == null) {
3603                 log.error(pos,
3604                           Errors.InvalidRepeatableAnnotationElemNondefault(container, elm));
3605             }
3606         }
3607     }
3608 
3609     /** Is s a method symbol that overrides a method in a superclass? */
3610     boolean isOverrider(Symbol s) {
3611         if (s.kind != MTH || s.isStatic())
3612             return false;
3613         MethodSymbol m = (MethodSymbol)s;
3614         TypeSymbol owner = (TypeSymbol)m.owner;
3615         for (Type sup : types.closure(owner.type)) {
3616             if (sup == owner.type)
3617                 continue; // skip "this"
3618             Scope scope = sup.tsym.members();
3619             for (Symbol sym : scope.getSymbolsByName(m.name)) {
3620                 if (!sym.isStatic() && m.overrides(sym, owner, types, true))
3621                     return true;
3622             }
3623         }
3624         return false;
3625     }
3626 
3627     /** Is the annotation applicable to types? */
3628     protected boolean isTypeAnnotation(JCAnnotation a, boolean isTypeParameter) {
3629         List<Attribute> targets = typeAnnotations.annotationTargets(a.annotationType.type.tsym);
3630         return (targets == null) ?
3631                 (Feature.NO_TARGET_ANNOTATION_APPLICABILITY.allowedInSource(source) && isTypeParameter) :
3632                 targets.stream()
3633                         .anyMatch(attr -> isTypeAnnotation(attr, isTypeParameter));
3634     }
3635     //where
3636         boolean isTypeAnnotation(Attribute a, boolean isTypeParameter) {
3637             Attribute.Enum e = (Attribute.Enum)a;
3638             return (e.value.name == names.TYPE_USE ||
3639                     (isTypeParameter && e.value.name == names.TYPE_PARAMETER));
3640         }
3641 
3642     /** Is the annotation applicable to the symbol? */
3643     Name[] getTargetNames(JCAnnotation a) {
3644         return getTargetNames(a.annotationType.type.tsym);
3645     }
3646 
3647     public Name[] getTargetNames(TypeSymbol annoSym) {
3648         Attribute.Array arr = getAttributeTargetAttribute(annoSym);
3649         Name[] targets;
3650         if (arr == null) {
3651             targets = defaultTargetMetaInfo();
3652         } else {
3653             // TODO: can we optimize this?
3654             targets = new Name[arr.values.length];
3655             for (int i=0; i<arr.values.length; ++i) {
3656                 Attribute app = arr.values[i];
3657                 if (!(app instanceof Attribute.Enum attributeEnum)) {
3658                     return new Name[0];
3659                 }
3660                 targets[i] = attributeEnum.value.name;
3661             }
3662         }
3663         return targets;
3664     }
3665 
3666     boolean annotationApplicable(JCAnnotation a, Symbol s) {
3667         Optional<Set<Name>> targets = getApplicableTargets(a, s);
3668         /* the optional could be empty if the annotation is unknown in that case
3669          * we return that it is applicable and if it is erroneous that should imply
3670          * an error at the declaration site
3671          */
3672         return targets.isEmpty() || targets.isPresent() && !targets.get().isEmpty();
3673     }
3674 
3675     Optional<Set<Name>> getApplicableTargets(JCAnnotation a, Symbol s) {
3676         Attribute.Array arr = getAttributeTargetAttribute(a.annotationType.type.tsym);
3677         Name[] targets;
3678         Set<Name> applicableTargets = new HashSet<>();
3679 
3680         if (arr == null) {
3681             targets = defaultTargetMetaInfo();
3682         } else {
3683             // TODO: can we optimize this?
3684             targets = new Name[arr.values.length];
3685             for (int i=0; i<arr.values.length; ++i) {
3686                 Attribute app = arr.values[i];
3687                 if (!(app instanceof Attribute.Enum attributeEnum)) {
3688                     // recovery
3689                     return Optional.empty();
3690                 }
3691                 targets[i] = attributeEnum.value.name;
3692             }
3693         }
3694         for (Name target : targets) {
3695             if (target == names.TYPE) {
3696                 if (s.kind == TYP)
3697                     applicableTargets.add(names.TYPE);
3698             } else if (target == names.FIELD) {
3699                 if (s.kind == VAR && s.owner.kind != MTH)
3700                     applicableTargets.add(names.FIELD);
3701             } else if (target == names.RECORD_COMPONENT) {
3702                 if (s.getKind() == ElementKind.RECORD_COMPONENT) {
3703                     applicableTargets.add(names.RECORD_COMPONENT);
3704                 }
3705             } else if (target == names.METHOD) {
3706                 if (s.kind == MTH && !s.isConstructor())
3707                     applicableTargets.add(names.METHOD);
3708             } else if (target == names.PARAMETER) {
3709                 if (s.kind == VAR &&
3710                     (s.owner.kind == MTH && (s.flags() & PARAMETER) != 0)) {
3711                     applicableTargets.add(names.PARAMETER);
3712                 }
3713             } else if (target == names.CONSTRUCTOR) {
3714                 if (s.kind == MTH && s.isConstructor())
3715                     applicableTargets.add(names.CONSTRUCTOR);
3716             } else if (target == names.LOCAL_VARIABLE) {
3717                 if (s.kind == VAR && s.owner.kind == MTH &&
3718                       (s.flags() & PARAMETER) == 0) {
3719                     applicableTargets.add(names.LOCAL_VARIABLE);
3720                 }
3721             } else if (target == names.ANNOTATION_TYPE) {
3722                 if (s.kind == TYP && (s.flags() & ANNOTATION) != 0) {
3723                     applicableTargets.add(names.ANNOTATION_TYPE);
3724                 }
3725             } else if (target == names.PACKAGE) {
3726                 if (s.kind == PCK)
3727                     applicableTargets.add(names.PACKAGE);
3728             } else if (target == names.TYPE_USE) {
3729                 if (s.kind == VAR && s.owner.kind == MTH && s.type.hasTag(NONE)) {
3730                     //cannot type annotate implicitly typed locals
3731                     continue;
3732                 } else if (s.kind == TYP || s.kind == VAR ||
3733                         (s.kind == MTH && !s.isConstructor() &&
3734                                 !s.type.getReturnType().hasTag(VOID)) ||
3735                         (s.kind == MTH && s.isConstructor())) {
3736                     applicableTargets.add(names.TYPE_USE);
3737                 }
3738             } else if (target == names.TYPE_PARAMETER) {
3739                 if (s.kind == TYP && s.type.hasTag(TYPEVAR))
3740                     applicableTargets.add(names.TYPE_PARAMETER);
3741             } else if (target == names.MODULE) {
3742                 if (s.kind == MDL)
3743                     applicableTargets.add(names.MODULE);
3744             } else {
3745                 log.error(a, Errors.AnnotationUnrecognizedAttributeName(a.type, target));
3746                 return Optional.empty(); // Unknown ElementType
3747             }
3748         }
3749         return Optional.of(applicableTargets);
3750     }
3751 
3752     Attribute.Array getAttributeTargetAttribute(TypeSymbol s) {
3753         Attribute.Compound atTarget = s.getAnnotationTypeMetadata().getTarget();
3754         if (atTarget == null) return null; // ok, is applicable
3755         Attribute atValue = atTarget.member(names.value);
3756         return (atValue instanceof Attribute.Array attributeArray) ? attributeArray : null;
3757     }
3758 
3759     private Name[] dfltTargetMeta;
3760     private Name[] defaultTargetMetaInfo() {
3761         if (dfltTargetMeta == null) {
3762             ArrayList<Name> defaultTargets = new ArrayList<>();
3763             defaultTargets.add(names.PACKAGE);
3764             defaultTargets.add(names.TYPE);
3765             defaultTargets.add(names.FIELD);
3766             defaultTargets.add(names.METHOD);
3767             defaultTargets.add(names.CONSTRUCTOR);
3768             defaultTargets.add(names.ANNOTATION_TYPE);
3769             defaultTargets.add(names.LOCAL_VARIABLE);
3770             defaultTargets.add(names.PARAMETER);
3771             if (allowRecords) {
3772               defaultTargets.add(names.RECORD_COMPONENT);
3773             }
3774             if (allowModules) {
3775               defaultTargets.add(names.MODULE);
3776             }
3777             dfltTargetMeta = defaultTargets.toArray(new Name[0]);
3778         }
3779         return dfltTargetMeta;
3780     }
3781 
3782     /** Check an annotation value.
3783      *
3784      * @param a The annotation tree to check
3785      * @return true if this annotation tree is valid, otherwise false
3786      */
3787     public boolean validateAnnotationDeferErrors(JCAnnotation a) {
3788         boolean res = false;
3789         final Log.DiagnosticHandler diagHandler = log.new DiscardDiagnosticHandler();
3790         try {
3791             res = validateAnnotation(a);
3792         } finally {
3793             log.popDiagnosticHandler(diagHandler);
3794         }
3795         return res;
3796     }
3797 
3798     private boolean validateAnnotation(JCAnnotation a) {
3799         boolean isValid = true;
3800         AnnotationTypeMetadata metadata = a.annotationType.type.tsym.getAnnotationTypeMetadata();
3801 
3802         // collect an inventory of the annotation elements
3803         Set<MethodSymbol> elements = metadata.getAnnotationElements();
3804 
3805         // remove the ones that are assigned values
3806         for (JCTree arg : a.args) {
3807             if (!arg.hasTag(ASSIGN)) continue; // recovery
3808             JCAssign assign = (JCAssign)arg;
3809             Symbol m = TreeInfo.symbol(assign.lhs);
3810             if (m == null || m.type.isErroneous()) continue;
3811             if (!elements.remove(m)) {
3812                 isValid = false;
3813                 log.error(assign.lhs.pos(),
3814                           Errors.DuplicateAnnotationMemberValue(m.name, a.type));
3815             }
3816         }
3817 
3818         // all the remaining ones better have default values
3819         List<Name> missingDefaults = List.nil();
3820         Set<MethodSymbol> membersWithDefault = metadata.getAnnotationElementsWithDefault();
3821         for (MethodSymbol m : elements) {
3822             if (m.type.isErroneous())
3823                 continue;
3824 
3825             if (!membersWithDefault.contains(m))
3826                 missingDefaults = missingDefaults.append(m.name);
3827         }
3828         missingDefaults = missingDefaults.reverse();
3829         if (missingDefaults.nonEmpty()) {
3830             isValid = false;
3831             Error errorKey = (missingDefaults.size() > 1)
3832                     ? Errors.AnnotationMissingDefaultValue1(a.type, missingDefaults)
3833                     : Errors.AnnotationMissingDefaultValue(a.type, missingDefaults);
3834             log.error(a.pos(), errorKey);
3835         }
3836 
3837         return isValid && validateTargetAnnotationValue(a);
3838     }
3839 
3840     /* Validate the special java.lang.annotation.Target annotation */
3841     boolean validateTargetAnnotationValue(JCAnnotation a) {
3842         // special case: java.lang.annotation.Target must not have
3843         // repeated values in its value member
3844         if (a.annotationType.type.tsym != syms.annotationTargetType.tsym ||
3845                 a.args.tail == null)
3846             return true;
3847 
3848         boolean isValid = true;
3849         if (!a.args.head.hasTag(ASSIGN)) return false; // error recovery
3850         JCAssign assign = (JCAssign) a.args.head;
3851         Symbol m = TreeInfo.symbol(assign.lhs);
3852         if (m.name != names.value) return false;
3853         JCTree rhs = assign.rhs;
3854         if (!rhs.hasTag(NEWARRAY)) return false;
3855         JCNewArray na = (JCNewArray) rhs;
3856         Set<Symbol> targets = new HashSet<>();
3857         for (JCTree elem : na.elems) {
3858             if (!targets.add(TreeInfo.symbol(elem))) {
3859                 isValid = false;
3860                 log.error(elem.pos(), Errors.RepeatedAnnotationTarget);
3861             }
3862         }
3863         return isValid;
3864     }
3865 
3866     void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) {
3867         if (lint.isEnabled(LintCategory.DEP_ANN) && s.isDeprecatableViaAnnotation() &&
3868             (s.flags() & DEPRECATED) != 0 &&
3869             !syms.deprecatedType.isErroneous() &&
3870             s.attribute(syms.deprecatedType.tsym) == null) {
3871             log.warning(pos, LintWarnings.MissingDeprecatedAnnotation);
3872         }
3873         // Note: @Deprecated has no effect on local variables, parameters and package decls.
3874         if (lint.isEnabled(LintCategory.DEPRECATION) && !s.isDeprecatableViaAnnotation()) {
3875             if (!syms.deprecatedType.isErroneous() && s.attribute(syms.deprecatedType.tsym) != null) {
3876                 log.warning(pos,
3877                             LintWarnings.DeprecatedAnnotationHasNoEffect(Kinds.kindName(s)));
3878             }
3879         }
3880     }
3881 
3882     void checkDeprecated(final DiagnosticPosition pos, final Symbol other, final Symbol s) {
3883         checkDeprecated(() -> pos, other, s);
3884     }
3885 
3886     void checkDeprecated(Supplier<DiagnosticPosition> pos, final Symbol other, final Symbol s) {
3887         if (!importSuppression
3888                 && (s.isDeprecatedForRemoval() || s.isDeprecated() && !other.isDeprecated())
3889                 && (s.outermostClass() != other.outermostClass() || s.outermostClass() == null)
3890                 && s.kind != Kind.PCK) {
3891             deferredLintHandler.report(_l -> warnDeprecated(pos.get(), s));
3892         }
3893     }
3894 
3895     void checkSunAPI(final DiagnosticPosition pos, final Symbol s) {
3896         if ((s.flags() & PROPRIETARY) != 0) {
3897             deferredLintHandler.report(_l -> {
3898                 log.mandatoryWarning(pos, Warnings.SunProprietary(s));
3899             });
3900         }
3901     }
3902 
3903     void checkProfile(final DiagnosticPosition pos, final Symbol s) {
3904         if (profile != Profile.DEFAULT && (s.flags() & NOT_IN_PROFILE) != 0) {
3905             log.error(pos, Errors.NotInProfile(s, profile));
3906         }
3907     }
3908 
3909     void checkPreview(DiagnosticPosition pos, Symbol other, Symbol s) {
3910         checkPreview(pos, other, Type.noType, s);
3911     }
3912 
3913     void checkPreview(DiagnosticPosition pos, Symbol other, Type site, Symbol s) {
3914         boolean sIsPreview;
3915         Symbol previewSymbol;
3916         if ((s.flags() & PREVIEW_API) != 0) {
3917             sIsPreview = true;
3918             previewSymbol=  s;
3919         } else if ((s.kind == Kind.MTH || s.kind == Kind.VAR) &&
3920                    site.tsym != null &&
3921                    (site.tsym.flags() & PREVIEW_API) == 0 &&
3922                    (s.owner.flags() & PREVIEW_API) != 0) {
3923             //calling a method, or using a field, whose owner is a preview, but
3924             //using a site that is not a preview. Also produce an error or warning:
3925             sIsPreview = true;
3926             previewSymbol = s.owner;
3927         } else {
3928             sIsPreview = false;
3929             previewSymbol = null;
3930         }
3931         if (sIsPreview && !preview.participatesInPreview(syms, other, s) && !disablePreviewCheck) {
3932             if ((previewSymbol.flags() & PREVIEW_REFLECTIVE) == 0) {
3933                 if (!preview.isEnabled()) {
3934                     log.error(pos, Errors.IsPreview(s));
3935                 } else {
3936                     preview.markUsesPreview(pos);
3937                     warnPreviewAPI(pos, LintWarnings.IsPreview(s));
3938                 }
3939             } else {
3940                 warnPreviewAPI(pos, LintWarnings.IsPreviewReflective(s));
3941             }
3942         }
3943         if (preview.declaredUsingPreviewFeature(s)) {
3944             if (preview.isEnabled()) {
3945                 //for preview disabled do presumably so not need to do anything?
3946                 //If "s" is compiled from source, then there was an error for it already;
3947                 //if "s" is from classfile, there already was an error for the classfile.
3948                 preview.markUsesPreview(pos);
3949                 warnPreviewAPI(pos, LintWarnings.DeclaredUsingPreview(kindName(s), s));
3950             }
3951         }
3952     }
3953 
3954     void checkRestricted(DiagnosticPosition pos, Symbol s) {
3955         if (s.kind == MTH && (s.flags() & RESTRICTED) != 0) {
3956             deferredLintHandler.report(_l -> warnRestrictedAPI(pos, s));
3957         }
3958     }
3959 
3960 /* *************************************************************************
3961  * Check for recursive annotation elements.
3962  **************************************************************************/
3963 
3964     /** Check for cycles in the graph of annotation elements.
3965      */
3966     void checkNonCyclicElements(JCClassDecl tree) {
3967         if ((tree.sym.flags_field & ANNOTATION) == 0) return;
3968         Assert.check((tree.sym.flags_field & LOCKED) == 0);
3969         try {
3970             tree.sym.flags_field |= LOCKED;
3971             for (JCTree def : tree.defs) {
3972                 if (!def.hasTag(METHODDEF)) continue;
3973                 JCMethodDecl meth = (JCMethodDecl)def;
3974                 checkAnnotationResType(meth.pos(), meth.restype.type);
3975             }
3976         } finally {
3977             tree.sym.flags_field &= ~LOCKED;
3978             tree.sym.flags_field |= ACYCLIC_ANN;
3979         }
3980     }
3981 
3982     void checkNonCyclicElementsInternal(DiagnosticPosition pos, TypeSymbol tsym) {
3983         if ((tsym.flags_field & ACYCLIC_ANN) != 0)
3984             return;
3985         if ((tsym.flags_field & LOCKED) != 0) {
3986             log.error(pos, Errors.CyclicAnnotationElement(tsym));
3987             return;
3988         }
3989         try {
3990             tsym.flags_field |= LOCKED;
3991             for (Symbol s : tsym.members().getSymbols(NON_RECURSIVE)) {
3992                 if (s.kind != MTH)
3993                     continue;
3994                 checkAnnotationResType(pos, ((MethodSymbol)s).type.getReturnType());
3995             }
3996         } finally {
3997             tsym.flags_field &= ~LOCKED;
3998             tsym.flags_field |= ACYCLIC_ANN;
3999         }
4000     }
4001 
4002     void checkAnnotationResType(DiagnosticPosition pos, Type type) {
4003         switch (type.getTag()) {
4004         case CLASS:
4005             if ((type.tsym.flags() & ANNOTATION) != 0)
4006                 checkNonCyclicElementsInternal(pos, type.tsym);
4007             break;
4008         case ARRAY:
4009             checkAnnotationResType(pos, types.elemtype(type));
4010             break;
4011         default:
4012             break; // int etc
4013         }
4014     }
4015 
4016 /* *************************************************************************
4017  * Check for cycles in the constructor call graph.
4018  **************************************************************************/
4019 
4020     /** Check for cycles in the graph of constructors calling other
4021      *  constructors.
4022      */
4023     void checkCyclicConstructors(JCClassDecl tree) {
4024         // use LinkedHashMap so we generate errors deterministically
4025         Map<Symbol,Symbol> callMap = new LinkedHashMap<>();
4026 
4027         // enter each constructor this-call into the map
4028         for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
4029             if (!TreeInfo.isConstructor(l.head))
4030                 continue;
4031             JCMethodDecl meth = (JCMethodDecl)l.head;
4032             JCMethodInvocation app = TreeInfo.findConstructorCall(meth);
4033             if (app != null && TreeInfo.name(app.meth) == names._this) {
4034                 callMap.put(meth.sym, TreeInfo.symbol(app.meth));
4035             } else {
4036                 meth.sym.flags_field |= ACYCLIC;
4037             }
4038         }
4039 
4040         // Check for cycles in the map
4041         Symbol[] ctors = new Symbol[0];
4042         ctors = callMap.keySet().toArray(ctors);
4043         for (Symbol caller : ctors) {
4044             checkCyclicConstructor(tree, caller, callMap);
4045         }
4046     }
4047 
4048     /** Look in the map to see if the given constructor is part of a
4049      *  call cycle.
4050      */
4051     private void checkCyclicConstructor(JCClassDecl tree, Symbol ctor,
4052                                         Map<Symbol,Symbol> callMap) {
4053         if (ctor != null && (ctor.flags_field & ACYCLIC) == 0) {
4054             if ((ctor.flags_field & LOCKED) != 0) {
4055                 log.error(TreeInfo.diagnosticPositionFor(ctor, tree, false, t -> t.hasTag(IDENT)),
4056                           Errors.RecursiveCtorInvocation);
4057             } else {
4058                 ctor.flags_field |= LOCKED;
4059                 checkCyclicConstructor(tree, callMap.remove(ctor), callMap);
4060                 ctor.flags_field &= ~LOCKED;
4061             }
4062             ctor.flags_field |= ACYCLIC;
4063         }
4064     }
4065 
4066 /* *************************************************************************
4067  * Verify the proper placement of super()/this() calls.
4068  *
4069  *    - super()/this() may only appear in constructors
4070  *    - There must be at most one super()/this() call per constructor
4071  *    - The super()/this() call, if any, must be a top-level statement in the
4072  *      constructor, i.e., not nested inside any other statement or block
4073  *    - There must be no return statements prior to the super()/this() call
4074  **************************************************************************/
4075 
4076     void checkSuperInitCalls(JCClassDecl tree) {
4077         new SuperThisChecker().check(tree);
4078     }
4079 
4080     private class SuperThisChecker extends TreeScanner {
4081 
4082         // Match this scan stack: 1=JCMethodDecl, 2=JCExpressionStatement, 3=JCMethodInvocation
4083         private static final int MATCH_SCAN_DEPTH = 3;
4084 
4085         private boolean constructor;        // is this method a constructor?
4086         private boolean firstStatement;     // at the first statement in method?
4087         private JCReturn earlyReturn;       // first return prior to the super()/init(), if any
4088         private Name initCall;              // whichever of "super" or "init" we've seen already
4089         private int scanDepth;              // current scan recursion depth in method body
4090 
4091         public void check(JCClassDecl classDef) {
4092             scan(classDef.defs);
4093         }
4094 
4095         @Override
4096         public void visitMethodDef(JCMethodDecl tree) {
4097             Assert.check(!constructor);
4098             Assert.check(earlyReturn == null);
4099             Assert.check(initCall == null);
4100             Assert.check(scanDepth == 1);
4101 
4102             // Initialize state for this method
4103             constructor = TreeInfo.isConstructor(tree);
4104             try {
4105 
4106                 // Scan method body
4107                 if (tree.body != null) {
4108                     firstStatement = true;
4109                     for (List<JCStatement> l = tree.body.stats; l.nonEmpty(); l = l.tail) {
4110                         scan(l.head);
4111                         firstStatement = false;
4112                     }
4113                 }
4114 
4115                 // Verify no 'return' seen prior to an explicit super()/this() call
4116                 if (constructor && earlyReturn != null && initCall != null)
4117                     log.error(earlyReturn.pos(), Errors.ReturnBeforeSuperclassInitialized);
4118             } finally {
4119                 firstStatement = false;
4120                 constructor = false;
4121                 earlyReturn = null;
4122                 initCall = null;
4123             }
4124         }
4125 
4126         @Override
4127         public void scan(JCTree tree) {
4128             scanDepth++;
4129             try {
4130                 super.scan(tree);
4131             } finally {
4132                 scanDepth--;
4133             }
4134         }
4135 
4136         @Override
4137         public void visitApply(JCMethodInvocation apply) {
4138             do {
4139 
4140                 // Is this a super() or this() call?
4141                 Name methodName = TreeInfo.name(apply.meth);
4142                 if (methodName != names._super && methodName != names._this)
4143                     break;
4144 
4145                 // super()/this() calls must only appear in a constructor
4146                 if (!constructor) {
4147                     log.error(apply.pos(), Errors.CallMustOnlyAppearInCtor);
4148                     break;
4149                 }
4150 
4151                 // super()/this() calls must be a top level statement
4152                 if (scanDepth != MATCH_SCAN_DEPTH) {
4153                     log.error(apply.pos(), Errors.CtorCallsNotAllowedHere);
4154                     break;
4155                 }
4156 
4157                 // super()/this() calls must not appear more than once
4158                 if (initCall != null) {
4159                     log.error(apply.pos(), Errors.RedundantSuperclassInit);
4160                     break;
4161                 }
4162 
4163                 // If super()/this() isn't first, require flexible constructors feature
4164                 if (!firstStatement)
4165                     preview.checkSourceLevel(apply.pos(), Feature.FLEXIBLE_CONSTRUCTORS);
4166 
4167                 // We found a legitimate super()/this() call; remember it
4168                 initCall = methodName;
4169             } while (false);
4170 
4171             // Proceed
4172             super.visitApply(apply);
4173         }
4174 
4175         @Override
4176         public void visitReturn(JCReturn tree) {
4177             if (constructor && initCall == null && earlyReturn == null)
4178                 earlyReturn = tree;             // we have seen a return but not (yet) a super()/this()
4179             super.visitReturn(tree);
4180         }
4181 
4182         @Override
4183         public void visitClassDef(JCClassDecl tree) {
4184             // don't descend any further
4185         }
4186 
4187         @Override
4188         public void visitLambda(JCLambda tree) {
4189             final boolean constructorPrev = constructor;
4190             final boolean firstStatementPrev = firstStatement;
4191             final JCReturn earlyReturnPrev = earlyReturn;
4192             final Name initCallPrev = initCall;
4193             final int scanDepthPrev = scanDepth;
4194             constructor = false;
4195             firstStatement = false;
4196             earlyReturn = null;
4197             initCall = null;
4198             scanDepth = 0;
4199             try {
4200                 super.visitLambda(tree);
4201             } finally {
4202                 constructor = constructorPrev;
4203                 firstStatement = firstStatementPrev;
4204                 earlyReturn = earlyReturnPrev;
4205                 initCall = initCallPrev;
4206                 scanDepth = scanDepthPrev;
4207             }
4208         }
4209     }
4210 
4211 /* *************************************************************************
4212  * Miscellaneous
4213  **************************************************************************/
4214 
4215     /**
4216      *  Check for division by integer constant zero
4217      *  @param pos           Position for error reporting.
4218      *  @param operator      The operator for the expression
4219      *  @param operand       The right hand operand for the expression
4220      */
4221     void checkDivZero(final DiagnosticPosition pos, Symbol operator, Type operand) {
4222         if (operand.constValue() != null
4223             && operand.getTag().isSubRangeOf(LONG)
4224             && ((Number) (operand.constValue())).longValue() == 0) {
4225             int opc = ((OperatorSymbol)operator).opcode;
4226             if (opc == ByteCodes.idiv || opc == ByteCodes.imod
4227                 || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) {
4228                 deferredLintHandler.report(_ -> lint.logIfEnabled(pos, LintWarnings.DivZero));
4229             }
4230         }
4231     }
4232 
4233     /**
4234      *  Check for possible loss of precission
4235      *  @param pos           Position for error reporting.
4236      *  @param found    The computed type of the tree
4237      *  @param req  The computed type of the tree
4238      */
4239     void checkLossOfPrecision(final DiagnosticPosition pos, Type found, Type req) {
4240         if (found.isNumeric() && req.isNumeric() && !types.isAssignable(found, req)) {
4241             deferredLintHandler.report(_ ->
4242                 lint.logIfEnabled(pos, LintWarnings.PossibleLossOfPrecision(found, req)));
4243         }
4244     }
4245 
4246     /**
4247      * Check for empty statements after if
4248      */
4249     void checkEmptyIf(JCIf tree) {
4250         if (tree.thenpart.hasTag(SKIP) && tree.elsepart == null) {
4251             lint.logIfEnabled(tree.thenpart.pos(), LintWarnings.EmptyIf);
4252         }
4253     }
4254 
4255     /** Check that symbol is unique in given scope.
4256      *  @param pos           Position for error reporting.
4257      *  @param sym           The symbol.
4258      *  @param s             The scope.
4259      */
4260     boolean checkUnique(DiagnosticPosition pos, Symbol sym, Scope s) {
4261         if (sym.type.isErroneous())
4262             return true;
4263         if (sym.owner.name == names.any) return false;
4264         for (Symbol byName : s.getSymbolsByName(sym.name, NON_RECURSIVE)) {
4265             if (sym != byName &&
4266                     (byName.flags() & CLASH) == 0 &&
4267                     sym.kind == byName.kind &&
4268                     sym.name != names.error &&
4269                     (sym.kind != MTH ||
4270                      types.hasSameArgs(sym.type, byName.type) ||
4271                      types.hasSameArgs(types.erasure(sym.type), types.erasure(byName.type)))) {
4272                 if ((sym.flags() & VARARGS) != (byName.flags() & VARARGS)) {
4273                     sym.flags_field |= CLASH;
4274                     varargsDuplicateError(pos, sym, byName);
4275                     return true;
4276                 } else if (sym.kind == MTH && !types.hasSameArgs(sym.type, byName.type, false)) {
4277                     duplicateErasureError(pos, sym, byName);
4278                     sym.flags_field |= CLASH;
4279                     return true;
4280                 } else if ((sym.flags() & MATCH_BINDING) != 0 &&
4281                            (byName.flags() & MATCH_BINDING) != 0 &&
4282                            (byName.flags() & MATCH_BINDING_TO_OUTER) == 0) {
4283                     if (!sym.type.isErroneous()) {
4284                         log.error(pos, Errors.MatchBindingExists);
4285                         sym.flags_field |= CLASH;
4286                     }
4287                     return false;
4288                 } else {
4289                     duplicateError(pos, byName);
4290                     return false;
4291                 }
4292             }
4293         }
4294         return true;
4295     }
4296 
4297     /** Report duplicate declaration error.
4298      */
4299     void duplicateErasureError(DiagnosticPosition pos, Symbol sym1, Symbol sym2) {
4300         if (!sym1.type.isErroneous() && !sym2.type.isErroneous()) {
4301             log.error(pos, Errors.NameClashSameErasure(sym1, sym2));
4302         }
4303     }
4304 
4305     /**Check that types imported through the ordinary imports don't clash with types imported
4306      * by other (static or ordinary) imports. Note that two static imports may import two clashing
4307      * types without an error on the imports.
4308      * @param toplevel       The toplevel tree for which the test should be performed.
4309      */
4310     void checkImportsUnique(JCCompilationUnit toplevel) {
4311         WriteableScope ordinallyImportedSoFar = WriteableScope.create(toplevel.packge);
4312         WriteableScope staticallyImportedSoFar = WriteableScope.create(toplevel.packge);
4313         WriteableScope topLevelScope = toplevel.toplevelScope;
4314 
4315         for (JCTree def : toplevel.defs) {
4316             if (!def.hasTag(IMPORT))
4317                 continue;
4318 
4319             JCImport imp = (JCImport) def;
4320 
4321             if (imp.importScope == null)
4322                 continue;
4323 
4324             for (Symbol sym : imp.importScope.getSymbols(sym -> sym.kind == TYP)) {
4325                 if (imp.isStatic()) {
4326                     checkUniqueImport(imp.pos(), ordinallyImportedSoFar, staticallyImportedSoFar, topLevelScope, sym, true);
4327                     staticallyImportedSoFar.enter(sym);
4328                 } else {
4329                     checkUniqueImport(imp.pos(), ordinallyImportedSoFar, staticallyImportedSoFar, topLevelScope, sym, false);
4330                     ordinallyImportedSoFar.enter(sym);
4331                 }
4332             }
4333 
4334             imp.importScope = null;
4335         }
4336     }
4337 
4338     /** Check that single-type import is not already imported or top-level defined,
4339      *  but make an exception for two single-type imports which denote the same type.
4340      *  @param pos                     Position for error reporting.
4341      *  @param ordinallyImportedSoFar  A Scope containing types imported so far through
4342      *                                 ordinary imports.
4343      *  @param staticallyImportedSoFar A Scope containing types imported so far through
4344      *                                 static imports.
4345      *  @param topLevelScope           The current file's top-level Scope
4346      *  @param sym                     The symbol.
4347      *  @param staticImport            Whether or not this was a static import
4348      */
4349     private boolean checkUniqueImport(DiagnosticPosition pos, Scope ordinallyImportedSoFar,
4350                                       Scope staticallyImportedSoFar, Scope topLevelScope,
4351                                       Symbol sym, boolean staticImport) {
4352         Predicate<Symbol> duplicates = candidate -> candidate != sym && !candidate.type.isErroneous();
4353         Symbol ordinaryClashing = ordinallyImportedSoFar.findFirst(sym.name, duplicates);
4354         Symbol staticClashing = null;
4355         if (ordinaryClashing == null && !staticImport) {
4356             staticClashing = staticallyImportedSoFar.findFirst(sym.name, duplicates);
4357         }
4358         if (ordinaryClashing != null || staticClashing != null) {
4359             if (ordinaryClashing != null)
4360                 log.error(pos, Errors.AlreadyDefinedSingleImport(ordinaryClashing));
4361             else
4362                 log.error(pos, Errors.AlreadyDefinedStaticSingleImport(staticClashing));
4363             return false;
4364         }
4365         Symbol clashing = topLevelScope.findFirst(sym.name, duplicates);
4366         if (clashing != null) {
4367             log.error(pos, Errors.AlreadyDefinedThisUnit(clashing));
4368             return false;
4369         }
4370         return true;
4371     }
4372 
4373     /** Check that a qualified name is in canonical form (for import decls).
4374      */
4375     public void checkCanonical(JCTree tree) {
4376         if (!isCanonical(tree))
4377             log.error(tree.pos(),
4378                       Errors.ImportRequiresCanonical(TreeInfo.symbol(tree)));
4379     }
4380         // where
4381         private boolean isCanonical(JCTree tree) {
4382             while (tree.hasTag(SELECT)) {
4383                 JCFieldAccess s = (JCFieldAccess) tree;
4384                 if (s.sym.owner.getQualifiedName() != TreeInfo.symbol(s.selected).getQualifiedName())
4385                     return false;
4386                 tree = s.selected;
4387             }
4388             return true;
4389         }
4390 
4391     /** Check that an auxiliary class is not accessed from any other file than its own.
4392      */
4393     void checkForBadAuxiliaryClassAccess(DiagnosticPosition pos, Env<AttrContext> env, ClassSymbol c) {
4394         if ((c.flags() & AUXILIARY) != 0 &&
4395             rs.isAccessible(env, c) &&
4396             !fileManager.isSameFile(c.sourcefile, env.toplevel.sourcefile))
4397         {
4398             lint.logIfEnabled(pos,
4399                         LintWarnings.AuxiliaryClassAccessedFromOutsideOfItsSourceFile(c, c.sourcefile));
4400         }
4401     }
4402 
4403     /**
4404      * Check for a default constructor in an exported package.
4405      */
4406     void checkDefaultConstructor(ClassSymbol c, DiagnosticPosition pos) {
4407         if (lint.isEnabled(LintCategory.MISSING_EXPLICIT_CTOR) &&
4408             ((c.flags() & (ENUM | RECORD)) == 0) &&
4409             !c.isAnonymous() &&
4410             ((c.flags() & (PUBLIC | PROTECTED)) != 0) &&
4411             Feature.MODULES.allowedInSource(source)) {
4412             NestingKind nestingKind = c.getNestingKind();
4413             switch (nestingKind) {
4414                 case ANONYMOUS,
4415                      LOCAL -> {return;}
4416                 case TOP_LEVEL -> {;} // No additional checks needed
4417                 case MEMBER -> {
4418                     // For nested member classes, all the enclosing
4419                     // classes must be public or protected.
4420                     Symbol owner = c.owner;
4421                     while (owner != null && owner.kind == TYP) {
4422                         if ((owner.flags() & (PUBLIC | PROTECTED)) == 0)
4423                             return;
4424                         owner = owner.owner;
4425                     }
4426                 }
4427             }
4428 
4429             // Only check classes in named packages exported by its module
4430             PackageSymbol pkg = c.packge();
4431             if (!pkg.isUnnamed()) {
4432                 ModuleSymbol modle = pkg.modle;
4433                 for (ExportsDirective exportDir : modle.exports) {
4434                     // Report warning only if the containing
4435                     // package is unconditionally exported
4436                     if (exportDir.packge.equals(pkg)) {
4437                         if (exportDir.modules == null || exportDir.modules.isEmpty()) {
4438                             // Warning may be suppressed by
4439                             // annotations; check again for being
4440                             // enabled in the deferred context.
4441                             deferredLintHandler.report(_ ->
4442                                 lint.logIfEnabled(pos, LintWarnings.MissingExplicitCtor(c, pkg, modle)));
4443                         } else {
4444                             return;
4445                         }
4446                     }
4447                 }
4448             }
4449         }
4450         return;
4451     }
4452 
4453     private class ConversionWarner extends Warner {
4454         final String uncheckedKey;
4455         final Type found;
4456         final Type expected;
4457         public ConversionWarner(DiagnosticPosition pos, String uncheckedKey, Type found, Type expected) {
4458             super(pos);
4459             this.uncheckedKey = uncheckedKey;
4460             this.found = found;
4461             this.expected = expected;
4462         }
4463 
4464         @Override
4465         public void warn(LintCategory lint) {
4466             boolean warned = this.warned;
4467             super.warn(lint);
4468             if (warned) return; // suppress redundant diagnostics
4469             switch (lint) {
4470                 case UNCHECKED:
4471                     Check.this.warnUnchecked(pos(), LintWarnings.ProbFoundReq(diags.fragment(uncheckedKey), found, expected));
4472                     break;
4473                 case VARARGS:
4474                     if (method != null &&
4475                             method.attribute(syms.trustMeType.tsym) != null &&
4476                             isTrustMeAllowedOnMethod(method) &&
4477                             !types.isReifiable(method.type.getParameterTypes().last())) {
4478                         Check.this.lint.logIfEnabled(pos(), LintWarnings.VarargsUnsafeUseVarargsParam(method.params.last()));
4479                     }
4480                     break;
4481                 default:
4482                     throw new AssertionError("Unexpected lint: " + lint);
4483             }
4484         }
4485     }
4486 
4487     public Warner castWarner(DiagnosticPosition pos, Type found, Type expected) {
4488         return new ConversionWarner(pos, "unchecked.cast.to.type", found, expected);
4489     }
4490 
4491     public Warner convertWarner(DiagnosticPosition pos, Type found, Type expected) {
4492         return new ConversionWarner(pos, "unchecked.assign", found, expected);
4493     }
4494 
4495     public void checkFunctionalInterface(JCClassDecl tree, ClassSymbol cs) {
4496         Compound functionalType = cs.attribute(syms.functionalInterfaceType.tsym);
4497 
4498         if (functionalType != null) {
4499             try {
4500                 types.findDescriptorSymbol((TypeSymbol)cs);
4501             } catch (Types.FunctionDescriptorLookupError ex) {
4502                 DiagnosticPosition pos = tree.pos();
4503                 for (JCAnnotation a : tree.getModifiers().annotations) {
4504                     if (a.annotationType.type.tsym == syms.functionalInterfaceType.tsym) {
4505                         pos = a.pos();
4506                         break;
4507                     }
4508                 }
4509                 log.error(pos, Errors.BadFunctionalIntfAnno1(ex.getDiagnostic()));
4510             }
4511         }
4512     }
4513 
4514     public void checkImportsResolvable(final JCCompilationUnit toplevel) {
4515         for (final JCImportBase impBase : toplevel.getImports()) {
4516             if (!(impBase instanceof JCImport imp))
4517                 continue;
4518             if (!imp.staticImport || !imp.qualid.hasTag(SELECT))
4519                 continue;
4520             final JCFieldAccess select = imp.qualid;
4521             final Symbol origin;
4522             if (select.name == names.asterisk || (origin = TreeInfo.symbol(select.selected)) == null || origin.kind != TYP)
4523                 continue;
4524 
4525             TypeSymbol site = (TypeSymbol) TreeInfo.symbol(select.selected);
4526             if (!checkTypeContainsImportableElement(site, site, toplevel.packge, select.name, new HashSet<Symbol>())) {
4527                 log.error(imp.pos(),
4528                           Errors.CantResolveLocation(KindName.STATIC,
4529                                                      select.name,
4530                                                      null,
4531                                                      null,
4532                                                      Fragments.Location(kindName(site),
4533                                                                         site,
4534                                                                         null)));
4535             }
4536         }
4537     }
4538 
4539     // Check that packages imported are in scope (JLS 7.4.3, 6.3, 6.5.3.1, 6.5.3.2)
4540     public void checkImportedPackagesObservable(final JCCompilationUnit toplevel) {
4541         OUTER: for (JCImportBase impBase : toplevel.getImports()) {
4542             if (impBase instanceof JCImport imp && !imp.staticImport &&
4543                 TreeInfo.name(imp.qualid) == names.asterisk) {
4544                 TypeSymbol tsym = imp.qualid.selected.type.tsym;
4545                 if (tsym.kind == PCK && tsym.members().isEmpty() &&
4546                     !(Feature.IMPORT_ON_DEMAND_OBSERVABLE_PACKAGES.allowedInSource(source) && tsym.exists())) {
4547                     log.error(DiagnosticFlag.RESOLVE_ERROR, imp.qualid.selected.pos(), Errors.DoesntExist(tsym));
4548                 }
4549             }
4550         }
4551     }
4552 
4553     private boolean checkTypeContainsImportableElement(TypeSymbol tsym, TypeSymbol origin, PackageSymbol packge, Name name, Set<Symbol> processed) {
4554         if (tsym == null || !processed.add(tsym))
4555             return false;
4556 
4557             // also search through inherited names
4558         if (checkTypeContainsImportableElement(types.supertype(tsym.type).tsym, origin, packge, name, processed))
4559             return true;
4560 
4561         for (Type t : types.interfaces(tsym.type))
4562             if (checkTypeContainsImportableElement(t.tsym, origin, packge, name, processed))
4563                 return true;
4564 
4565         for (Symbol sym : tsym.members().getSymbolsByName(name)) {
4566             if (sym.isStatic() &&
4567                 importAccessible(sym, packge) &&
4568                 sym.isMemberOf(origin, types)) {
4569                 return true;
4570             }
4571         }
4572 
4573         return false;
4574     }
4575 
4576     // is the sym accessible everywhere in packge?
4577     public boolean importAccessible(Symbol sym, PackageSymbol packge) {
4578         try {
4579             int flags = (int)(sym.flags() & AccessFlags);
4580             switch (flags) {
4581             default:
4582             case PUBLIC:
4583                 return true;
4584             case PRIVATE:
4585                 return false;
4586             case 0:
4587             case PROTECTED:
4588                 return sym.packge() == packge;
4589             }
4590         } catch (ClassFinder.BadClassFile err) {
4591             throw err;
4592         } catch (CompletionFailure ex) {
4593             return false;
4594         }
4595     }
4596 
4597     public void checkLeaksNotAccessible(Env<AttrContext> env, JCClassDecl check) {
4598         JCCompilationUnit toplevel = env.toplevel;
4599 
4600         if (   toplevel.modle == syms.unnamedModule
4601             || toplevel.modle == syms.noModule
4602             || (check.sym.flags() & COMPOUND) != 0) {
4603             return ;
4604         }
4605 
4606         ExportsDirective currentExport = findExport(toplevel.packge);
4607 
4608         if (   currentExport == null //not exported
4609             || currentExport.modules != null) //don't check classes in qualified export
4610             return ;
4611 
4612         new TreeScanner() {
4613             Lint lint = env.info.lint;
4614             boolean inSuperType;
4615 
4616             @Override
4617             public void visitBlock(JCBlock tree) {
4618             }
4619             @Override
4620             public void visitMethodDef(JCMethodDecl tree) {
4621                 if (!isAPISymbol(tree.sym))
4622                     return;
4623                 Lint prevLint = lint;
4624                 try {
4625                     lint = lint.augment(tree.sym);
4626                     if (lint.isEnabled(LintCategory.EXPORTS)) {
4627                         super.visitMethodDef(tree);
4628                     }
4629                 } finally {
4630                     lint = prevLint;
4631                 }
4632             }
4633             @Override
4634             public void visitVarDef(JCVariableDecl tree) {
4635                 if (!isAPISymbol(tree.sym) && tree.sym.owner.kind != MTH)
4636                     return;
4637                 Lint prevLint = lint;
4638                 try {
4639                     lint = lint.augment(tree.sym);
4640                     if (lint.isEnabled(LintCategory.EXPORTS)) {
4641                         scan(tree.mods);
4642                         scan(tree.vartype);
4643                     }
4644                 } finally {
4645                     lint = prevLint;
4646                 }
4647             }
4648             @Override
4649             public void visitClassDef(JCClassDecl tree) {
4650                 if (tree != check)
4651                     return ;
4652 
4653                 if (!isAPISymbol(tree.sym))
4654                     return ;
4655 
4656                 Lint prevLint = lint;
4657                 try {
4658                     lint = lint.augment(tree.sym);
4659                     if (lint.isEnabled(LintCategory.EXPORTS)) {
4660                         scan(tree.mods);
4661                         scan(tree.typarams);
4662                         try {
4663                             inSuperType = true;
4664                             scan(tree.extending);
4665                             scan(tree.implementing);
4666                         } finally {
4667                             inSuperType = false;
4668                         }
4669                         scan(tree.defs);
4670                     }
4671                 } finally {
4672                     lint = prevLint;
4673                 }
4674             }
4675             @Override
4676             public void visitTypeApply(JCTypeApply tree) {
4677                 scan(tree.clazz);
4678                 boolean oldInSuperType = inSuperType;
4679                 try {
4680                     inSuperType = false;
4681                     scan(tree.arguments);
4682                 } finally {
4683                     inSuperType = oldInSuperType;
4684                 }
4685             }
4686             @Override
4687             public void visitIdent(JCIdent tree) {
4688                 Symbol sym = TreeInfo.symbol(tree);
4689                 if (sym.kind == TYP && !sym.type.hasTag(TYPEVAR)) {
4690                     checkVisible(tree.pos(), sym, toplevel.packge, inSuperType);
4691                 }
4692             }
4693 
4694             @Override
4695             public void visitSelect(JCFieldAccess tree) {
4696                 Symbol sym = TreeInfo.symbol(tree);
4697                 Symbol sitesym = TreeInfo.symbol(tree.selected);
4698                 if (sym.kind == TYP && sitesym.kind == PCK) {
4699                     checkVisible(tree.pos(), sym, toplevel.packge, inSuperType);
4700                 } else {
4701                     super.visitSelect(tree);
4702                 }
4703             }
4704 
4705             @Override
4706             public void visitAnnotation(JCAnnotation tree) {
4707                 if (tree.attribute.type.tsym.getAnnotation(java.lang.annotation.Documented.class) != null)
4708                     super.visitAnnotation(tree);
4709             }
4710 
4711         }.scan(check);
4712     }
4713         //where:
4714         private ExportsDirective findExport(PackageSymbol pack) {
4715             for (ExportsDirective d : pack.modle.exports) {
4716                 if (d.packge == pack)
4717                     return d;
4718             }
4719 
4720             return null;
4721         }
4722         private boolean isAPISymbol(Symbol sym) {
4723             while (sym.kind != PCK) {
4724                 if ((sym.flags() & Flags.PUBLIC) == 0 && (sym.flags() & Flags.PROTECTED) == 0) {
4725                     return false;
4726                 }
4727                 sym = sym.owner;
4728             }
4729             return true;
4730         }
4731         private void checkVisible(DiagnosticPosition pos, Symbol what, PackageSymbol inPackage, boolean inSuperType) {
4732             if (!isAPISymbol(what) && !inSuperType) { //package private/private element
4733                 log.warning(pos, LintWarnings.LeaksNotAccessible(kindName(what), what, what.packge().modle));
4734                 return ;
4735             }
4736 
4737             PackageSymbol whatPackage = what.packge();
4738             ExportsDirective whatExport = findExport(whatPackage);
4739             ExportsDirective inExport = findExport(inPackage);
4740 
4741             if (whatExport == null) { //package not exported:
4742                 log.warning(pos, LintWarnings.LeaksNotAccessibleUnexported(kindName(what), what, what.packge().modle));
4743                 return ;
4744             }
4745 
4746             if (whatExport.modules != null) {
4747                 if (inExport.modules == null || !whatExport.modules.containsAll(inExport.modules)) {
4748                     log.warning(pos, LintWarnings.LeaksNotAccessibleUnexportedQualified(kindName(what), what, what.packge().modle));
4749                 }
4750             }
4751 
4752             if (whatPackage.modle != inPackage.modle && whatPackage.modle != syms.java_base) {
4753                 //check that relativeTo.modle requires transitive what.modle, somehow:
4754                 List<ModuleSymbol> todo = List.of(inPackage.modle);
4755 
4756                 while (todo.nonEmpty()) {
4757                     ModuleSymbol current = todo.head;
4758                     todo = todo.tail;
4759                     if (current == whatPackage.modle)
4760                         return ; //OK
4761                     if ((current.flags() & Flags.AUTOMATIC_MODULE) != 0)
4762                         continue; //for automatic modules, don't look into their dependencies
4763                     for (RequiresDirective req : current.requires) {
4764                         if (req.isTransitive()) {
4765                             todo = todo.prepend(req.module);
4766                         }
4767                     }
4768                 }
4769 
4770                 log.warning(pos, LintWarnings.LeaksNotAccessibleNotRequiredTransitive(kindName(what), what, what.packge().modle));
4771             }
4772         }
4773 
4774     void checkModuleExists(final DiagnosticPosition pos, ModuleSymbol msym) {
4775         if (msym.kind != MDL) {
4776             deferredLintHandler.report(_ ->
4777                 lint.logIfEnabled(pos, LintWarnings.ModuleNotFound(msym)));
4778         }
4779     }
4780 
4781     void checkPackageExistsForOpens(final DiagnosticPosition pos, PackageSymbol packge) {
4782         if (packge.members().isEmpty() &&
4783             ((packge.flags() & Flags.HAS_RESOURCE) == 0)) {
4784             deferredLintHandler.report(_ ->
4785                 lint.logIfEnabled(pos, LintWarnings.PackageEmptyOrNotFound(packge)));
4786         }
4787     }
4788 
4789     void checkModuleRequires(final DiagnosticPosition pos, final RequiresDirective rd) {
4790         if ((rd.module.flags() & Flags.AUTOMATIC_MODULE) != 0) {
4791             deferredLintHandler.report(_ -> {
4792                 if (rd.isTransitive() && lint.isEnabled(LintCategory.REQUIRES_TRANSITIVE_AUTOMATIC)) {
4793                     log.warning(pos, LintWarnings.RequiresTransitiveAutomatic);
4794                 } else {
4795                     lint.logIfEnabled(pos, LintWarnings.RequiresAutomatic);
4796                 }
4797             });
4798         }
4799     }
4800 
4801     /**
4802      * Verify the case labels conform to the constraints. Checks constraints related
4803      * combinations of patterns and other labels.
4804      *
4805      * @param cases the cases that should be checked.
4806      */
4807     void checkSwitchCaseStructure(List<JCCase> cases) {
4808         for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
4809             JCCase c = l.head;
4810             if (c.labels.head instanceof JCConstantCaseLabel constLabel) {
4811                 if (TreeInfo.isNull(constLabel.expr)) {
4812                     if (c.labels.tail.nonEmpty()) {
4813                         if (c.labels.tail.head instanceof JCDefaultCaseLabel defLabel) {
4814                             if (c.labels.tail.tail.nonEmpty()) {
4815                                 log.error(c.labels.tail.tail.head.pos(), Errors.InvalidCaseLabelCombination);
4816                             }
4817                         } else {
4818                             log.error(c.labels.tail.head.pos(), Errors.InvalidCaseLabelCombination);
4819                         }
4820                     }
4821                 } else {
4822                     for (JCCaseLabel label : c.labels.tail) {
4823                         if (!(label instanceof JCConstantCaseLabel) || TreeInfo.isNullCaseLabel(label)) {
4824                             log.error(label.pos(), Errors.InvalidCaseLabelCombination);
4825                             break;
4826                         }
4827                     }
4828                 }
4829             } else if (c.labels.tail.nonEmpty()) {
4830                 var patterCaseLabels = c.labels.stream().filter(ll -> ll instanceof JCPatternCaseLabel).map(cl -> (JCPatternCaseLabel)cl);
4831                 var allUnderscore = patterCaseLabels.allMatch(pcl -> !hasBindings(pcl.getPattern()));
4832 
4833                 if (!allUnderscore) {
4834                     log.error(c.labels.tail.head.pos(), Errors.FlowsThroughFromPattern);
4835                 }
4836 
4837                 boolean allPatternCaseLabels = c.labels.stream().allMatch(p -> p instanceof JCPatternCaseLabel);
4838 
4839                 if (allPatternCaseLabels) {
4840                     preview.checkSourceLevel(c.labels.tail.head.pos(), Feature.UNNAMED_VARIABLES);
4841                 }
4842 
4843                 for (JCCaseLabel label : c.labels.tail) {
4844                     if (label instanceof JCConstantCaseLabel) {
4845                         log.error(label.pos(), Errors.InvalidCaseLabelCombination);
4846                         break;
4847                     }
4848                 }
4849             }
4850         }
4851 
4852         boolean isCaseStatementGroup = cases.nonEmpty() &&
4853                                        cases.head.caseKind == CaseTree.CaseKind.STATEMENT;
4854 
4855         if (isCaseStatementGroup) {
4856             boolean previousCompletessNormally = false;
4857             for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
4858                 JCCase c = l.head;
4859                 if (previousCompletessNormally &&
4860                     c.stats.nonEmpty() &&
4861                     c.labels.head instanceof JCPatternCaseLabel patternLabel &&
4862                     (hasBindings(patternLabel.pat) || hasBindings(c.guard))) {
4863                     log.error(c.labels.head.pos(), Errors.FlowsThroughToPattern);
4864                 } else if (c.stats.isEmpty() &&
4865                            c.labels.head instanceof JCPatternCaseLabel patternLabel &&
4866                            (hasBindings(patternLabel.pat) || hasBindings(c.guard)) &&
4867                            hasStatements(l.tail)) {
4868                     log.error(c.labels.head.pos(), Errors.FlowsThroughFromPattern);
4869                 }
4870                 previousCompletessNormally = c.completesNormally;
4871             }
4872         }
4873     }
4874 
4875     boolean hasBindings(JCTree p) {
4876         boolean[] bindings = new boolean[1];
4877 
4878         new TreeScanner() {
4879             @Override
4880             public void visitBindingPattern(JCBindingPattern tree) {
4881                 bindings[0] |= !tree.var.sym.isUnnamedVariable();
4882                 super.visitBindingPattern(tree);
4883             }
4884         }.scan(p);
4885 
4886         return bindings[0];
4887     }
4888 
4889     boolean hasStatements(List<JCCase> cases) {
4890         for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
4891             if (l.head.stats.nonEmpty()) {
4892                 return true;
4893             }
4894         }
4895 
4896         return false;
4897     }
4898     void checkSwitchCaseLabelDominated(JCCaseLabel unconditionalCaseLabel, List<JCCase> cases) {
4899         List<Pair<JCCase, JCCaseLabel>> caseLabels = List.nil();
4900         boolean seenDefault = false;
4901         boolean seenDefaultLabel = false;
4902         boolean warnDominatedByDefault = false;
4903         boolean unconditionalFound = false;
4904 
4905         for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
4906             JCCase c = l.head;
4907             for (JCCaseLabel label : c.labels) {
4908                 if (label.hasTag(DEFAULTCASELABEL)) {
4909                     seenDefault = true;
4910                     seenDefaultLabel |=
4911                             TreeInfo.isNullCaseLabel(c.labels.head);
4912                     continue;
4913                 }
4914                 if (TreeInfo.isNullCaseLabel(label)) {
4915                     if (seenDefault) {
4916                         log.error(label.pos(), Errors.PatternDominated);
4917                     }
4918                     continue;
4919                 }
4920                 if (seenDefault && !warnDominatedByDefault) {
4921                     if (label.hasTag(PATTERNCASELABEL) ||
4922                         (label instanceof JCConstantCaseLabel && seenDefaultLabel)) {
4923                         log.error(label.pos(), Errors.PatternDominated);
4924                         warnDominatedByDefault = true;
4925                     }
4926                 }
4927                 Type currentType = labelType(label);
4928                 for (Pair<JCCase, JCCaseLabel> caseAndLabel : caseLabels) {
4929                     JCCase testCase = caseAndLabel.fst;
4930                     JCCaseLabel testCaseLabel = caseAndLabel.snd;
4931                     Type testType = labelType(testCaseLabel);
4932                     boolean dominated = false;
4933                     if (types.isUnconditionallyExact(currentType, testType) &&
4934                         !currentType.hasTag(ERROR) && !testType.hasTag(ERROR)) {
4935                         //the current label is potentially dominated by the existing (test) label, check:
4936                         if (label instanceof JCConstantCaseLabel) {
4937                             dominated |= !(testCaseLabel instanceof JCConstantCaseLabel) &&
4938                                          TreeInfo.unguardedCase(testCase);
4939                         } else if (label instanceof JCPatternCaseLabel patternCL &&
4940                                    testCaseLabel instanceof JCPatternCaseLabel testPatternCaseLabel &&
4941                                    (testCase.equals(c) || TreeInfo.unguardedCase(testCase))) {
4942                             dominated = patternDominated(testPatternCaseLabel.pat,
4943                                                          patternCL.pat);
4944                         }
4945                     }
4946 
4947                     if (dominated) {
4948                         log.error(label.pos(), Errors.PatternDominated);
4949                     }
4950                 }
4951                 caseLabels = caseLabels.prepend(Pair.of(c, label));
4952             }
4953         }
4954     }
4955         //where:
4956         private Type labelType(JCCaseLabel label) {
4957             return types.erasure(switch (label.getTag()) {
4958                 case PATTERNCASELABEL -> ((JCPatternCaseLabel) label).pat.type;
4959                 case CONSTANTCASELABEL -> ((JCConstantCaseLabel) label).expr.type;
4960                 default -> throw Assert.error("Unexpected tree kind: " + label.getTag());
4961             });
4962         }
4963         private boolean patternDominated(JCPattern existingPattern, JCPattern currentPattern) {
4964             Type existingPatternType = types.erasure(existingPattern.type);
4965             Type currentPatternType = types.erasure(currentPattern.type);
4966             if (!types.isUnconditionallyExact(currentPatternType, existingPatternType)) {
4967                 return false;
4968             }
4969             if (currentPattern instanceof JCBindingPattern ||
4970                 currentPattern instanceof JCAnyPattern) {
4971                 return existingPattern instanceof JCBindingPattern ||
4972                        existingPattern instanceof JCAnyPattern;
4973             } else if (currentPattern instanceof JCRecordPattern currentRecordPattern) {
4974                 if (existingPattern instanceof JCBindingPattern ||
4975                     existingPattern instanceof JCAnyPattern) {
4976                     return true;
4977                 } else if (existingPattern instanceof JCRecordPattern existingRecordPattern) {
4978                     List<JCPattern> existingNested = existingRecordPattern.nested;
4979                     List<JCPattern> currentNested = currentRecordPattern.nested;
4980                     if (existingNested.size() != currentNested.size()) {
4981                         return false;
4982                     }
4983                     while (existingNested.nonEmpty()) {
4984                         if (!patternDominated(existingNested.head, currentNested.head)) {
4985                             return false;
4986                         }
4987                         existingNested = existingNested.tail;
4988                         currentNested = currentNested.tail;
4989                     }
4990                     return true;
4991                 } else {
4992                     Assert.error("Unknown pattern: " + existingPattern.getTag());
4993                 }
4994             } else {
4995                 Assert.error("Unknown pattern: " + currentPattern.getTag());
4996             }
4997             return false;
4998         }
4999 
5000     /** check if a type is a subtype of Externalizable, if that is available. */
5001     boolean isExternalizable(Type t) {
5002         try {
5003             syms.externalizableType.complete();
5004         } catch (CompletionFailure e) {
5005             return false;
5006         }
5007         return types.isSubtype(t, syms.externalizableType);
5008     }
5009 
5010     /**
5011      * Check structure of serialization declarations.
5012      */
5013     public void checkSerialStructure(Env<AttrContext> env, JCClassDecl tree, ClassSymbol c) {
5014         (new SerialTypeVisitor(env)).visit(c, tree);
5015     }
5016 
5017     /**
5018      * This visitor will warn if a serialization-related field or
5019      * method is declared in a suspicious or incorrect way. In
5020      * particular, it will warn for cases where the runtime
5021      * serialization mechanism will silently ignore a mis-declared
5022      * entity.
5023      *
5024      * Distinguished serialization-related fields and methods:
5025      *
5026      * Methods:
5027      *
5028      * private void writeObject(ObjectOutputStream stream) throws IOException
5029      * ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException
5030      *
5031      * private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException
5032      * private void readObjectNoData() throws ObjectStreamException
5033      * ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException
5034      *
5035      * Fields:
5036      *
5037      * private static final long serialVersionUID
5038      * private static final ObjectStreamField[] serialPersistentFields
5039      *
5040      * Externalizable: methods defined on the interface
5041      * public void writeExternal(ObjectOutput) throws IOException
5042      * public void readExternal(ObjectInput) throws IOException
5043      */
5044     private class SerialTypeVisitor extends ElementKindVisitor14<Void, JCClassDecl> {
5045         Env<AttrContext> env;
5046         SerialTypeVisitor(Env<AttrContext> env) {
5047             this.lint = Check.this.lint;
5048             this.env = env;
5049         }
5050 
5051         private static final Set<String> serialMethodNames =
5052             Set.of("writeObject", "writeReplace",
5053                    "readObject",  "readObjectNoData",
5054                    "readResolve");
5055 
5056         private static final Set<String> serialFieldNames =
5057             Set.of("serialVersionUID", "serialPersistentFields");
5058 
5059         // Type of serialPersistentFields
5060         private final Type OSF_TYPE = new Type.ArrayType(syms.objectStreamFieldType, syms.arrayClass);
5061 
5062         Lint lint;
5063 
5064         @Override
5065         public Void defaultAction(Element e, JCClassDecl p) {
5066             throw new IllegalArgumentException(Objects.requireNonNullElse(e.toString(), ""));
5067         }
5068 
5069         @Override
5070         public Void visitType(TypeElement e, JCClassDecl p) {
5071             runUnderLint(e, p, (symbol, param) -> super.visitType(symbol, param));
5072             return null;
5073         }
5074 
5075         @Override
5076         public Void visitTypeAsClass(TypeElement e,
5077                                      JCClassDecl p) {
5078             // Anonymous classes filtered out by caller.
5079 
5080             ClassSymbol c = (ClassSymbol)e;
5081 
5082             checkCtorAccess(p, c);
5083 
5084             // Check for missing serialVersionUID; check *not* done
5085             // for enums or records.
5086             VarSymbol svuidSym = null;
5087             for (Symbol sym : c.members().getSymbolsByName(names.serialVersionUID)) {
5088                 if (sym.kind == VAR) {
5089                     svuidSym = (VarSymbol)sym;
5090                     break;
5091                 }
5092             }
5093 
5094             if (svuidSym == null) {
5095                 log.warning(p.pos(), LintWarnings.MissingSVUID(c));
5096             }
5097 
5098             // Check for serialPersistentFields to gate checks for
5099             // non-serializable non-transient instance fields
5100             boolean serialPersistentFieldsPresent =
5101                     c.members()
5102                      .getSymbolsByName(names.serialPersistentFields, sym -> sym.kind == VAR)
5103                      .iterator()
5104                      .hasNext();
5105 
5106             // Check declarations of serialization-related methods and
5107             // fields
5108             final boolean[] hasWriteReplace = {false};
5109             for(Symbol el : c.getEnclosedElements()) {
5110                 runUnderLint(el, p, (enclosed, tree) -> {
5111                     String name = null;
5112                     switch(enclosed.getKind()) {
5113                     case FIELD -> {
5114                         if (!serialPersistentFieldsPresent) {
5115                             var flags = enclosed.flags();
5116                             if ( ((flags & TRANSIENT) == 0) &&
5117                                  ((flags & STATIC) == 0)) {
5118                                 Type varType = enclosed.asType();
5119                                 if (!canBeSerialized(varType)) {
5120                                     // Note per JLS arrays are
5121                                     // serializable even if the
5122                                     // component type is not.
5123                                     log.warning(
5124                                             TreeInfo.diagnosticPositionFor(enclosed, tree),
5125                                                 LintWarnings.NonSerializableInstanceField);
5126                                 } else if (varType.hasTag(ARRAY)) {
5127                                     ArrayType arrayType = (ArrayType)varType;
5128                                     Type elementType = arrayType.elemtype;
5129                                     while (elementType.hasTag(ARRAY)) {
5130                                         arrayType = (ArrayType)elementType;
5131                                         elementType = arrayType.elemtype;
5132                                     }
5133                                     if (!canBeSerialized(elementType)) {
5134                                         log.warning(
5135                                                 TreeInfo.diagnosticPositionFor(enclosed, tree),
5136                                                     LintWarnings.NonSerializableInstanceFieldArray(elementType));
5137                                     }
5138                                 }
5139                             }
5140                         }
5141 
5142                         name = enclosed.getSimpleName().toString();
5143                         if (serialFieldNames.contains(name)) {
5144                             VarSymbol field = (VarSymbol)enclosed;
5145                             switch (name) {
5146                             case "serialVersionUID"       ->  checkSerialVersionUID(tree, e, field);
5147                             case "serialPersistentFields" ->  checkSerialPersistentFields(tree, e, field);
5148                             default -> throw new AssertionError();
5149                             }
5150                         }
5151                     }
5152 
5153                     // Correctly checking the serialization-related
5154                     // methods is subtle. For the methods declared to be
5155                     // private or directly declared in the class, the
5156                     // enclosed elements of the class can be checked in
5157                     // turn. However, writeReplace and readResolve can be
5158                     // declared in a superclass and inherited. Note that
5159                     // the runtime lookup walks the superclass chain
5160                     // looking for writeReplace/readResolve via
5161                     // Class.getDeclaredMethod. This differs from calling
5162                     // Elements.getAllMembers(TypeElement) as the latter
5163                     // will also pull in default methods from
5164                     // superinterfaces. In other words, the runtime checks
5165                     // (which long predate default methods on interfaces)
5166                     // do not admit the possibility of inheriting methods
5167                     // this way, a difference from general inheritance.
5168 
5169                     // The current implementation just checks the enclosed
5170                     // elements and does not directly check the inherited
5171                     // methods. If all the types are being checked this is
5172                     // less of a concern; however, there are cases that
5173                     // could be missed. In particular, readResolve and
5174                     // writeReplace could, in principle, by inherited from
5175                     // a non-serializable superclass and thus not checked
5176                     // even if compiled with a serializable child class.
5177                     case METHOD -> {
5178                         var method = (MethodSymbol)enclosed;
5179                         name = method.getSimpleName().toString();
5180                         if (serialMethodNames.contains(name)) {
5181                             switch (name) {
5182                             case "writeObject"      -> checkWriteObject(tree, e, method);
5183                             case "writeReplace"     -> {hasWriteReplace[0] = true; hasAppropriateWriteReplace(tree, method, true);}
5184                             case "readObject"       -> checkReadObject(tree,e, method);
5185                             case "readObjectNoData" -> checkReadObjectNoData(tree, e, method);
5186                             case "readResolve"      -> checkReadResolve(tree, e, method);
5187                             default ->  throw new AssertionError();
5188                             }
5189                         }
5190                     }
5191                     }
5192                 });
5193             }
5194             if (!hasWriteReplace[0] &&
5195                     (c.isValueClass() || hasAbstractValueSuperClass(c, Set.of(syms.numberType.tsym))) &&
5196                     !c.isAbstract() && !c.isRecord() &&
5197                     types.unboxedType(c.type) == Type.noType) {
5198                 // we need to check if the class is inheriting an appropriate writeReplace method
5199                 MethodSymbol ms = null;
5200                 Log.DiagnosticHandler discardHandler = log.new DiscardDiagnosticHandler();
5201                 try {
5202                     ms = rs.resolveInternalMethod(env.tree, env, c.type, names.writeReplace, List.nil(), List.nil());
5203                 } catch (FatalError fe) {
5204                     // ignore no method was found
5205                 } finally {
5206                     log.popDiagnosticHandler(discardHandler);
5207                 }
5208                 if (ms == null || !hasAppropriateWriteReplace(p, ms, false)) {
5209                     log.warning(p.pos(),
5210                             c.isValueClass() ? LintWarnings.SerializableValueClassWithoutWriteReplace1 :
5211                                     LintWarnings.SerializableValueClassWithoutWriteReplace2);
5212                 }
5213             }
5214             return null;
5215         }
5216 
5217         boolean canBeSerialized(Type type) {
5218             return type.isPrimitive() || rs.isSerializable(type);
5219         }
5220 
5221         private boolean hasAbstractValueSuperClass(Symbol c, Set<Symbol> excluding) {
5222             while (c.getKind() == ElementKind.CLASS) {
5223                 Type sup = ((ClassSymbol)c).getSuperclass();
5224                 if (!sup.hasTag(CLASS) || sup.isErroneous() ||
5225                         sup.tsym == syms.objectType.tsym) {
5226                     return false;
5227                 }
5228                 // if it is a value super class it has to be abstract
5229                 if (sup.isValueClass() && !excluding.contains(sup.tsym)) {
5230                     return true;
5231                 }
5232                 c = sup.tsym;
5233             }
5234             return false;
5235         }
5236 
5237         /**
5238          * Check that Externalizable class needs a public no-arg
5239          * constructor.
5240          *
5241          * Check that a Serializable class has access to the no-arg
5242          * constructor of its first nonserializable superclass.
5243          */
5244         private void checkCtorAccess(JCClassDecl tree, ClassSymbol c) {
5245             if (isExternalizable(c.type)) {
5246                 for(var sym : c.getEnclosedElements()) {
5247                     if (sym.isConstructor() &&
5248                         ((sym.flags() & PUBLIC) == PUBLIC)) {
5249                         if (((MethodSymbol)sym).getParameters().isEmpty()) {
5250                             return;
5251                         }
5252                     }
5253                 }
5254                 log.warning(tree.pos(),
5255                             LintWarnings.ExternalizableMissingPublicNoArgCtor);
5256             } else {
5257                 // Approximate access to the no-arg constructor up in
5258                 // the superclass chain by checking that the
5259                 // constructor is not private. This may not handle
5260                 // some cross-package situations correctly.
5261                 Type superClass = c.getSuperclass();
5262                 // java.lang.Object is *not* Serializable so this loop
5263                 // should terminate.
5264                 while (rs.isSerializable(superClass) ) {
5265                     try {
5266                         superClass = (Type)((TypeElement)(((DeclaredType)superClass)).asElement()).getSuperclass();
5267                     } catch(ClassCastException cce) {
5268                         return ; // Don't try to recover
5269                     }
5270                 }
5271                 // Non-Serializable superclass
5272                 try {
5273                     ClassSymbol supertype = ((ClassSymbol)(((DeclaredType)superClass).asElement()));
5274                     for(var sym : supertype.getEnclosedElements()) {
5275                         if (sym.isConstructor()) {
5276                             MethodSymbol ctor = (MethodSymbol)sym;
5277                             if (ctor.getParameters().isEmpty()) {
5278                                 if (((ctor.flags() & PRIVATE) == PRIVATE) ||
5279                                     // Handle nested classes and implicit this$0
5280                                     (supertype.getNestingKind() == NestingKind.MEMBER &&
5281                                      ((supertype.flags() & STATIC) == 0)))
5282                                     log.warning(tree.pos(),
5283                                                 LintWarnings.SerializableMissingAccessNoArgCtor(supertype.getQualifiedName()));
5284                             }
5285                         }
5286                     }
5287                 } catch (ClassCastException cce) {
5288                     return ; // Don't try to recover
5289                 }
5290                 return;
5291             }
5292         }
5293 
5294         private void checkSerialVersionUID(JCClassDecl tree, Element e, VarSymbol svuid) {
5295             // To be effective, serialVersionUID must be marked static
5296             // and final, but private is recommended. But alas, in
5297             // practice there are many non-private serialVersionUID
5298             // fields.
5299              if ((svuid.flags() & (STATIC | FINAL)) !=
5300                  (STATIC | FINAL)) {
5301                  log.warning(
5302                          TreeInfo.diagnosticPositionFor(svuid, tree),
5303                              LintWarnings.ImproperSVUID((Symbol)e));
5304              }
5305 
5306              // check svuid has type long
5307              if (!svuid.type.hasTag(LONG)) {
5308                  log.warning(
5309                          TreeInfo.diagnosticPositionFor(svuid, tree),
5310                              LintWarnings.LongSVUID((Symbol)e));
5311              }
5312 
5313              if (svuid.getConstValue() == null)
5314                  log.warning(
5315                          TreeInfo.diagnosticPositionFor(svuid, tree),
5316                              LintWarnings.ConstantSVUID((Symbol)e));
5317         }
5318 
5319         private void checkSerialPersistentFields(JCClassDecl tree, Element e, VarSymbol spf) {
5320             // To be effective, serialPersisentFields must be private, static, and final.
5321              if ((spf.flags() & (PRIVATE | STATIC | FINAL)) !=
5322                  (PRIVATE | STATIC | FINAL)) {
5323                  log.warning(
5324                          TreeInfo.diagnosticPositionFor(spf, tree),
5325                              LintWarnings.ImproperSPF);
5326              }
5327 
5328              if (!types.isSameType(spf.type, OSF_TYPE)) {
5329                  log.warning(
5330                          TreeInfo.diagnosticPositionFor(spf, tree),
5331                              LintWarnings.OSFArraySPF);
5332              }
5333 
5334             if (isExternalizable((Type)(e.asType()))) {
5335                 log.warning(
5336                         TreeInfo.diagnosticPositionFor(spf, tree),
5337                             LintWarnings.IneffectualSerialFieldExternalizable);
5338             }
5339 
5340             // Warn if serialPersistentFields is initialized to a
5341             // literal null.
5342             JCTree spfDecl = TreeInfo.declarationFor(spf, tree);
5343             if (spfDecl != null && spfDecl.getTag() == VARDEF) {
5344                 JCVariableDecl variableDef = (JCVariableDecl) spfDecl;
5345                 JCExpression initExpr = variableDef.init;
5346                  if (initExpr != null && TreeInfo.isNull(initExpr)) {
5347                      log.warning(initExpr.pos(),
5348                                  LintWarnings.SPFNullInit);
5349                  }
5350             }
5351         }
5352 
5353         private void checkWriteObject(JCClassDecl tree, Element e, MethodSymbol method) {
5354             // The "synchronized" modifier is seen in the wild on
5355             // readObject and writeObject methods and is generally
5356             // innocuous.
5357 
5358             // private void writeObject(ObjectOutputStream stream) throws IOException
5359             checkPrivateNonStaticMethod(tree, method);
5360             isExpectedReturnType(tree, method, syms.voidType, true);
5361             checkOneArg(tree, e, method, syms.objectOutputStreamType);
5362             hasExpectedExceptions(tree, method, true, syms.ioExceptionType);
5363             checkExternalizable(tree, e, method);
5364         }
5365 
5366         private boolean hasAppropriateWriteReplace(JCClassDecl tree, MethodSymbol method, boolean warn) {
5367             // ANY-ACCESS-MODIFIER Object writeReplace() throws
5368             // ObjectStreamException
5369 
5370             // Excluding abstract, could have a more complicated
5371             // rule based on abstract-ness of the class
5372             return isConcreteInstanceMethod(tree, method, warn) &&
5373                     isExpectedReturnType(tree, method, syms.objectType, warn) &&
5374                     hasNoArgs(tree, method, warn) &&
5375                     hasExpectedExceptions(tree, method, warn, syms.objectStreamExceptionType);
5376         }
5377 
5378         private void checkReadObject(JCClassDecl tree, Element e, MethodSymbol method) {
5379             // The "synchronized" modifier is seen in the wild on
5380             // readObject and writeObject methods and is generally
5381             // innocuous.
5382 
5383             // private void readObject(ObjectInputStream stream)
5384             //   throws IOException, ClassNotFoundException
5385             checkPrivateNonStaticMethod(tree, method);
5386             isExpectedReturnType(tree, method, syms.voidType, true);
5387             checkOneArg(tree, e, method, syms.objectInputStreamType);
5388             hasExpectedExceptions(tree, method, true, syms.ioExceptionType, syms.classNotFoundExceptionType);
5389             checkExternalizable(tree, e, method);
5390         }
5391 
5392         private void checkReadObjectNoData(JCClassDecl tree, Element e, MethodSymbol method) {
5393             // private void readObjectNoData() throws ObjectStreamException
5394             checkPrivateNonStaticMethod(tree, method);
5395             isExpectedReturnType(tree, method, syms.voidType, true);
5396             hasNoArgs(tree, method, true);
5397             hasExpectedExceptions(tree, method, true, syms.objectStreamExceptionType);
5398             checkExternalizable(tree, e, method);
5399         }
5400 
5401         private void checkReadResolve(JCClassDecl tree, Element e, MethodSymbol method) {
5402             // ANY-ACCESS-MODIFIER Object readResolve()
5403             // throws ObjectStreamException
5404 
5405             // Excluding abstract, could have a more complicated
5406             // rule based on abstract-ness of the class
5407             isConcreteInstanceMethod(tree, method, true);
5408             isExpectedReturnType(tree, method, syms.objectType, true);
5409             hasNoArgs(tree, method, true);
5410             hasExpectedExceptions(tree, method, true, syms.objectStreamExceptionType);
5411         }
5412 
5413         private void checkWriteExternalRecord(JCClassDecl tree, Element e, MethodSymbol method, boolean isExtern) {
5414             //public void writeExternal(ObjectOutput) throws IOException
5415             checkExternMethodRecord(tree, e, method, syms.objectOutputType, isExtern);
5416         }
5417 
5418         private void checkReadExternalRecord(JCClassDecl tree, Element e, MethodSymbol method, boolean isExtern) {
5419             // public void readExternal(ObjectInput) throws IOException
5420             checkExternMethodRecord(tree, e, method, syms.objectInputType, isExtern);
5421          }
5422 
5423         private void checkExternMethodRecord(JCClassDecl tree, Element e, MethodSymbol method, Type argType,
5424                                              boolean isExtern) {
5425             if (isExtern && isExternMethod(tree, e, method, argType)) {
5426                 log.warning(
5427                         TreeInfo.diagnosticPositionFor(method, tree),
5428                             LintWarnings.IneffectualExternalizableMethodRecord(method.getSimpleName().toString()));
5429             }
5430         }
5431 
5432         void checkPrivateNonStaticMethod(JCClassDecl tree, MethodSymbol method) {
5433             var flags = method.flags();
5434             if ((flags & PRIVATE) == 0) {
5435                 log.warning(
5436                         TreeInfo.diagnosticPositionFor(method, tree),
5437                             LintWarnings.SerialMethodNotPrivate(method.getSimpleName()));
5438             }
5439 
5440             if ((flags & STATIC) != 0) {
5441                 log.warning(
5442                         TreeInfo.diagnosticPositionFor(method, tree),
5443                             LintWarnings.SerialMethodStatic(method.getSimpleName()));
5444             }
5445         }
5446 
5447         /**
5448          * Per section 1.12 "Serialization of Enum Constants" of
5449          * the serialization specification, due to the special
5450          * serialization handling of enums, any writeObject,
5451          * readObject, writeReplace, and readResolve methods are
5452          * ignored as are serialPersistentFields and
5453          * serialVersionUID fields.
5454          */
5455         @Override
5456         public Void visitTypeAsEnum(TypeElement e,
5457                                     JCClassDecl p) {
5458             boolean isExtern = isExternalizable((Type)e.asType());
5459             for(Element el : e.getEnclosedElements()) {
5460                 runUnderLint(el, p, (enclosed, tree) -> {
5461                     String name = enclosed.getSimpleName().toString();
5462                     switch(enclosed.getKind()) {
5463                     case FIELD -> {
5464                         var field = (VarSymbol)enclosed;
5465                         if (serialFieldNames.contains(name)) {
5466                             log.warning(
5467                                     TreeInfo.diagnosticPositionFor(field, tree),
5468                                         LintWarnings.IneffectualSerialFieldEnum(name));
5469                         }
5470                     }
5471 
5472                     case METHOD -> {
5473                         var method = (MethodSymbol)enclosed;
5474                         if (serialMethodNames.contains(name)) {
5475                             log.warning(
5476                                     TreeInfo.diagnosticPositionFor(method, tree),
5477                                         LintWarnings.IneffectualSerialMethodEnum(name));
5478                         }
5479 
5480                         if (isExtern) {
5481                             switch(name) {
5482                             case "writeExternal" -> checkWriteExternalEnum(tree, e, method);
5483                             case "readExternal"  -> checkReadExternalEnum(tree, e, method);
5484                             }
5485                         }
5486                     }
5487 
5488                     // Also perform checks on any class bodies of enum constants, see JLS 8.9.1.
5489                     case ENUM_CONSTANT -> {
5490                         var field = (VarSymbol)enclosed;
5491                         JCVariableDecl decl = (JCVariableDecl) TreeInfo.declarationFor(field, p);
5492                         if (decl.init instanceof JCNewClass nc && nc.def != null) {
5493                             ClassSymbol enumConstantType = nc.def.sym;
5494                             visitTypeAsEnum(enumConstantType, p);
5495                         }
5496                     }
5497 
5498                     }});
5499             }
5500             return null;
5501         }
5502 
5503         private void checkWriteExternalEnum(JCClassDecl tree, Element e, MethodSymbol method) {
5504             //public void writeExternal(ObjectOutput) throws IOException
5505             checkExternMethodEnum(tree, e, method, syms.objectOutputType);
5506         }
5507 
5508         private void checkReadExternalEnum(JCClassDecl tree, Element e, MethodSymbol method) {
5509              // public void readExternal(ObjectInput) throws IOException
5510             checkExternMethodEnum(tree, e, method, syms.objectInputType);
5511          }
5512 
5513         private void checkExternMethodEnum(JCClassDecl tree, Element e, MethodSymbol method, Type argType) {
5514             if (isExternMethod(tree, e, method, argType)) {
5515                 log.warning(
5516                         TreeInfo.diagnosticPositionFor(method, tree),
5517                             LintWarnings.IneffectualExternMethodEnum(method.getSimpleName().toString()));
5518             }
5519         }
5520 
5521         private boolean isExternMethod(JCClassDecl tree, Element e, MethodSymbol method, Type argType) {
5522             long flags = method.flags();
5523             Type rtype = method.getReturnType();
5524 
5525             // Not necessary to check throws clause in this context
5526             return (flags & PUBLIC) != 0 && (flags & STATIC) == 0 &&
5527                 types.isSameType(syms.voidType, rtype) &&
5528                 hasExactlyOneArgWithType(tree, e, method, argType);
5529         }
5530 
5531         /**
5532          * Most serialization-related fields and methods on interfaces
5533          * are ineffectual or problematic.
5534          */
5535         @Override
5536         public Void visitTypeAsInterface(TypeElement e,
5537                                          JCClassDecl p) {
5538             for(Element el : e.getEnclosedElements()) {
5539                 runUnderLint(el, p, (enclosed, tree) -> {
5540                     String name = null;
5541                     switch(enclosed.getKind()) {
5542                     case FIELD -> {
5543                         var field = (VarSymbol)enclosed;
5544                         name = field.getSimpleName().toString();
5545                         switch(name) {
5546                         case "serialPersistentFields" -> {
5547                             log.warning(
5548                                     TreeInfo.diagnosticPositionFor(field, tree),
5549                                         LintWarnings.IneffectualSerialFieldInterface);
5550                         }
5551 
5552                         case "serialVersionUID" -> {
5553                             checkSerialVersionUID(tree, e, field);
5554                         }
5555                         }
5556                     }
5557 
5558                     case METHOD -> {
5559                         var method = (MethodSymbol)enclosed;
5560                         name = enclosed.getSimpleName().toString();
5561                         if (serialMethodNames.contains(name)) {
5562                             switch (name) {
5563                             case
5564                                 "readObject",
5565                                 "readObjectNoData",
5566                                 "writeObject"      -> checkPrivateMethod(tree, e, method);
5567 
5568                             case
5569                                 "writeReplace",
5570                                 "readResolve"      -> checkDefaultIneffective(tree, e, method);
5571 
5572                             default ->  throw new AssertionError();
5573                             }
5574 
5575                         }
5576                     }}
5577                 });
5578             }
5579 
5580             return null;
5581         }
5582 
5583         private void checkPrivateMethod(JCClassDecl tree,
5584                                         Element e,
5585                                         MethodSymbol method) {
5586             if ((method.flags() & PRIVATE) == 0) {
5587                 log.warning(
5588                         TreeInfo.diagnosticPositionFor(method, tree),
5589                             LintWarnings.NonPrivateMethodWeakerAccess);
5590             }
5591         }
5592 
5593         private void checkDefaultIneffective(JCClassDecl tree,
5594                                              Element e,
5595                                              MethodSymbol method) {
5596             if ((method.flags() & DEFAULT) == DEFAULT) {
5597                 log.warning(
5598                         TreeInfo.diagnosticPositionFor(method, tree),
5599                             LintWarnings.DefaultIneffective);
5600 
5601             }
5602         }
5603 
5604         @Override
5605         public Void visitTypeAsAnnotationType(TypeElement e,
5606                                               JCClassDecl p) {
5607             // Per the JLS, annotation types are not serializeable
5608             return null;
5609         }
5610 
5611         /**
5612          * From the Java Object Serialization Specification, 1.13
5613          * Serialization of Records:
5614          *
5615          * "The process by which record objects are serialized or
5616          * externalized cannot be customized; any class-specific
5617          * writeObject, readObject, readObjectNoData, writeExternal,
5618          * and readExternal methods defined by record classes are
5619          * ignored during serialization and deserialization. However,
5620          * a substitute object to be serialized or a designate
5621          * replacement may be specified, by the writeReplace and
5622          * readResolve methods, respectively. Any
5623          * serialPersistentFields field declaration is
5624          * ignored. Documenting serializable fields and data for
5625          * record classes is unnecessary, since there is no variation
5626          * in the serial form, other than whether a substitute or
5627          * replacement object is used. The serialVersionUID of a
5628          * record class is 0L unless explicitly declared. The
5629          * requirement for matching serialVersionUID values is waived
5630          * for record classes."
5631          */
5632         @Override
5633         public Void visitTypeAsRecord(TypeElement e,
5634                                       JCClassDecl p) {
5635             boolean isExtern = isExternalizable((Type)e.asType());
5636             for(Element el : e.getEnclosedElements()) {
5637                 runUnderLint(el, p, (enclosed, tree) -> {
5638                     String name = enclosed.getSimpleName().toString();
5639                     switch(enclosed.getKind()) {
5640                     case FIELD -> {
5641                         var field = (VarSymbol)enclosed;
5642                         switch(name) {
5643                         case "serialPersistentFields" -> {
5644                             log.warning(
5645                                     TreeInfo.diagnosticPositionFor(field, tree),
5646                                         LintWarnings.IneffectualSerialFieldRecord);
5647                         }
5648 
5649                         case "serialVersionUID" -> {
5650                             // Could generate additional warning that
5651                             // svuid value is not checked to match for
5652                             // records.
5653                             checkSerialVersionUID(tree, e, field);
5654                         }}
5655                     }
5656 
5657                     case METHOD -> {
5658                         var method = (MethodSymbol)enclosed;
5659                         switch(name) {
5660                         case "writeReplace" -> hasAppropriateWriteReplace(tree, method, true);
5661                         case "readResolve"  -> checkReadResolve(tree, e, method);
5662 
5663                         case "writeExternal" -> checkWriteExternalRecord(tree, e, method, isExtern);
5664                         case "readExternal"  -> checkReadExternalRecord(tree, e, method, isExtern);
5665 
5666                         default -> {
5667                             if (serialMethodNames.contains(name)) {
5668                                 log.warning(
5669                                         TreeInfo.diagnosticPositionFor(method, tree),
5670                                             LintWarnings.IneffectualSerialMethodRecord(name));
5671                             }
5672                         }}
5673                     }}});
5674             }
5675             return null;
5676         }
5677 
5678         boolean isConcreteInstanceMethod(JCClassDecl tree,
5679                                          MethodSymbol method,
5680                                          boolean warn) {
5681             if ((method.flags() & (STATIC | ABSTRACT)) != 0) {
5682                 if (warn) {
5683                     log.warning(
5684                             TreeInfo.diagnosticPositionFor(method, tree),
5685                                 LintWarnings.SerialConcreteInstanceMethod(method.getSimpleName()));
5686                 }
5687                 return false;
5688             }
5689             return true;
5690         }
5691 
5692         private boolean isExpectedReturnType(JCClassDecl tree,
5693                                           MethodSymbol method,
5694                                           Type expectedReturnType,
5695                                           boolean warn) {
5696             // Note: there may be complications checking writeReplace
5697             // and readResolve since they return Object and could, in
5698             // principle, have covariant overrides and any synthetic
5699             // bridge method would not be represented here for
5700             // checking.
5701             Type rtype = method.getReturnType();
5702             if (!types.isSameType(expectedReturnType, rtype)) {
5703                 if (warn) {
5704                     log.warning(
5705                             TreeInfo.diagnosticPositionFor(method, tree),
5706                             LintWarnings.SerialMethodUnexpectedReturnType(method.getSimpleName(),
5707                                                                       rtype, expectedReturnType));
5708                 }
5709                 return false;
5710             }
5711             return true;
5712         }
5713 
5714         private void checkOneArg(JCClassDecl tree,
5715                                  Element enclosing,
5716                                  MethodSymbol method,
5717                                  Type expectedType) {
5718             String name = method.getSimpleName().toString();
5719 
5720             var parameters= method.getParameters();
5721 
5722             if (parameters.size() != 1) {
5723                 log.warning(
5724                         TreeInfo.diagnosticPositionFor(method, tree),
5725                             LintWarnings.SerialMethodOneArg(method.getSimpleName(), parameters.size()));
5726                 return;
5727             }
5728 
5729             Type parameterType = parameters.get(0).asType();
5730             if (!types.isSameType(parameterType, expectedType)) {
5731                 log.warning(
5732                         TreeInfo.diagnosticPositionFor(method, tree),
5733                             LintWarnings.SerialMethodParameterType(method.getSimpleName(),
5734                                                                expectedType,
5735                                                                parameterType));
5736             }
5737         }
5738 
5739         private boolean hasExactlyOneArgWithType(JCClassDecl tree,
5740                                                  Element enclosing,
5741                                                  MethodSymbol method,
5742                                                  Type expectedType) {
5743             var parameters = method.getParameters();
5744             return (parameters.size() == 1) &&
5745                 types.isSameType(parameters.get(0).asType(), expectedType);
5746         }
5747 
5748 
5749         boolean hasNoArgs(JCClassDecl tree, MethodSymbol method, boolean warn) {
5750             var parameters = method.getParameters();
5751             if (!parameters.isEmpty()) {
5752                 if (warn) {
5753                     log.warning(
5754                             TreeInfo.diagnosticPositionFor(parameters.get(0), tree),
5755                             LintWarnings.SerialMethodNoArgs(method.getSimpleName()));
5756                 }
5757                 return false;
5758             }
5759             return true;
5760         }
5761 
5762         private void checkExternalizable(JCClassDecl tree, Element enclosing, MethodSymbol method) {
5763             // If the enclosing class is externalizable, warn for the method
5764             if (isExternalizable((Type)enclosing.asType())) {
5765                 log.warning(
5766                         TreeInfo.diagnosticPositionFor(method, tree),
5767                             LintWarnings.IneffectualSerialMethodExternalizable(method.getSimpleName()));
5768             }
5769             return;
5770         }
5771 
5772         private boolean hasExpectedExceptions(JCClassDecl tree,
5773                                               MethodSymbol method,
5774                                               boolean warn,
5775                                               Type... declaredExceptions) {
5776             for (Type thrownType: method.getThrownTypes()) {
5777                 // For each exception in the throws clause of the
5778                 // method, if not an Error and not a RuntimeException,
5779                 // check if the exception is a subtype of a declared
5780                 // exception from the throws clause of the
5781                 // serialization method in question.
5782                 if (types.isSubtype(thrownType, syms.runtimeExceptionType) ||
5783                     types.isSubtype(thrownType, syms.errorType) ) {
5784                     continue;
5785                 } else {
5786                     boolean declared = false;
5787                     for (Type declaredException : declaredExceptions) {
5788                         if (types.isSubtype(thrownType, declaredException)) {
5789                             declared = true;
5790                             continue;
5791                         }
5792                     }
5793                     if (!declared) {
5794                         if (warn) {
5795                             log.warning(
5796                                     TreeInfo.diagnosticPositionFor(method, tree),
5797                                     LintWarnings.SerialMethodUnexpectedException(method.getSimpleName(),
5798                                                                              thrownType));
5799                         }
5800                         return false;
5801                     }
5802                 }
5803             }
5804             return true;
5805         }
5806 
5807         private <E extends Element> Void runUnderLint(E symbol, JCClassDecl p, BiConsumer<E, JCClassDecl> task) {
5808             Lint prevLint = lint;
5809             try {
5810                 lint = lint.augment((Symbol) symbol);
5811 
5812                 if (lint.isEnabled(LintCategory.SERIAL)) {
5813                     task.accept(symbol, p);
5814                 }
5815 
5816                 return null;
5817             } finally {
5818                 lint = prevLint;
5819             }
5820         }
5821 
5822     }
5823 
5824 }