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