< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java

Print this page
*** 122,10 ***
--- 122,11 ---
      final Dependencies dependencies;
      final Annotate annotate;
      final ArgumentAttr argumentAttr;
      final MatchBindingsComputer matchBindingsComputer;
      final AttrRecover attrRecover;
+     final LocalProxyVarsGen localProxyVarsGen;
  
      public static Attr instance(Context context) {
          Attr instance = context.get(attrKey);
          if (instance == null)
              instance = new Attr(context);

*** 161,10 ***
--- 162,11 ---
          typeEnvs = TypeEnvs.instance(context);
          dependencies = Dependencies.instance(context);
          argumentAttr = ArgumentAttr.instance(context);
          matchBindingsComputer = MatchBindingsComputer.instance(context);
          attrRecover = AttrRecover.instance(context);
+         localProxyVarsGen = LocalProxyVarsGen.instance(context);
  
          Options options = Options.instance(context);
  
          Source source = Source.instance(context);
          allowReifiableTypesInInstanceof = Feature.REIFIABLE_TYPES_INSTANCEOF.allowedInSource(source);

*** 182,10 ***
--- 184,12 ---
          methodAttrInfo = new MethodAttrInfo();
          unknownTypeInfo = new ResultInfo(KindSelector.TYP, Type.noType);
          unknownTypeExprInfo = new ResultInfo(KindSelector.VAL_TYP, Type.noType);
          recoveryInfo = new RecoveryInfo(deferredAttr.emptyDeferredAttrContext);
          initBlockType = new MethodType(List.nil(), syms.voidType, List.nil(), syms.methodClass);
+         allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
+                 Feature.VALUE_CLASSES.allowedInSource(source);
      }
  
      /** Switch: reifiable types in instanceof enabled?
       */
      boolean allowReifiableTypesInInstanceof;

*** 200,10 ***
--- 204,14 ---
  
      /** Are unconditional patterns in instanceof allowed
       */
      private final boolean allowUnconditionalPatternsInstanceOf;
  
+     /** Are value classes allowed
+      */
+     private final boolean allowValueClasses;
+ 
      /**
       * Switch: warn about use of variable before declaration?
       * RFE: 6425594
       */
      boolean useBeforeDeclarationWarning;

*** 293,40 ***
       *  @param env    The current environment.
       */
      void checkAssignable(DiagnosticPosition pos, VarSymbol v, JCTree base, Env<AttrContext> env) {
          if (v.name == names._this) {
              log.error(pos, Errors.CantAssignValToThis);
!             return;
-         }
-         if ((v.flags() & FINAL) != 0 &&
              ((v.flags() & HASINIT) != 0
               ||
               !((base == null ||
                 TreeInfo.isThisQualifier(base)) &&
                 isAssignableAsBlankFinal(v, env)))) {
              if (v.isResourceVariable()) { //TWR resource
                  log.error(pos, Errors.TryResourceMayNotBeAssigned(v));
              } else {
                  log.error(pos, Errors.CantAssignValToVar(Flags.toSource(v.flags() & (STATIC | FINAL)), v));
              }
-             return;
-         }
- 
-         // Check instance field assignments that appear in constructor prologues
-         if (rs.isEarlyReference(env, base, v)) {
- 
-             // Field may not be inherited from a superclass
-             if (v.owner != env.enclClass.sym) {
-                 log.error(pos, Errors.CantRefBeforeCtorCalled(v));
-                 return;
-             }
- 
-             // Field may not have an initializer
-             if ((v.flags() & HASINIT) != 0) {
-                 log.error(pos, Errors.CantAssignInitializedBeforeCtorCalled(v));
-                 return;
-             }
          }
      }
  
      /** Does tree represent a static reference to an identifier?
       *  It is assumed that tree is either a SELECT or an IDENT.
--- 301,21 ---
       *  @param env    The current environment.
       */
      void checkAssignable(DiagnosticPosition pos, VarSymbol v, JCTree base, Env<AttrContext> env) {
          if (v.name == names._this) {
              log.error(pos, Errors.CantAssignValToThis);
!         } else if ((v.flags() & FINAL) != 0 &&
              ((v.flags() & HASINIT) != 0
               ||
               !((base == null ||
                 TreeInfo.isThisQualifier(base)) &&
                 isAssignableAsBlankFinal(v, env)))) {
              if (v.isResourceVariable()) { //TWR resource
                  log.error(pos, Errors.TryResourceMayNotBeAssigned(v));
              } else {
                  log.error(pos, Errors.CantAssignValToVar(Flags.toSource(v.flags() & (STATIC | FINAL)), v));
              }
          }
      }
  
      /** Does tree represent a static reference to an identifier?
       *  It is assumed that tree is either a SELECT or an IDENT.

*** 1120,11 ***
                                                      Fragments.CanonicalMustNotHaveStrongerAccess(asFlagSet(env.enclClass.sym.flags() & AccessFlags))
                                              )
                                  );
                              }
  
!                             if (TreeInfo.hasAnyConstructorCall(tree)) {
                                  log.error(tree, Errors.InvalidCanonicalConstructorInRecord(
                                          Fragments.Canonical, env.enclClass.sym.name,
                                          Fragments.CanonicalMustNotContainExplicitConstructorInvocation));
                              }
                          }
--- 1109,11 ---
                                                      Fragments.CanonicalMustNotHaveStrongerAccess(asFlagSet(env.enclClass.sym.flags() & AccessFlags))
                                              )
                                  );
                              }
  
!                             if (!allowValueClasses && TreeInfo.hasAnyConstructorCall(tree)) {
                                  log.error(tree, Errors.InvalidCanonicalConstructorInRecord(
                                          Fragments.Canonical, env.enclClass.sym.name,
                                          Fragments.CanonicalMustNotContainExplicitConstructorInvocation));
                              }
                          }

*** 1202,11 ***
                  // or we are compiling class java.lang.Object.
                  if (isConstructor && owner.type != syms.objectType) {
                      if (!TreeInfo.hasAnyConstructorCall(tree)) {
                          JCStatement supCall = make.at(tree.body.pos).Exec(make.Apply(List.nil(),
                                  make.Ident(names._super), make.Idents(List.nil())));
!                         tree.body.stats = tree.body.stats.prepend(supCall);
                      } else if ((env.enclClass.sym.flags() & ENUM) != 0 &&
                              (tree.mods.flags & GENERATEDCONSTR) == 0 &&
                              TreeInfo.hasConstructorCall(tree, names._super)) {
                          // enum constructors are not allowed to call super
                          // directly, so make sure there aren't any super calls
--- 1191,15 ---
                  // or we are compiling class java.lang.Object.
                  if (isConstructor && owner.type != syms.objectType) {
                      if (!TreeInfo.hasAnyConstructorCall(tree)) {
                          JCStatement supCall = make.at(tree.body.pos).Exec(make.Apply(List.nil(),
                                  make.Ident(names._super), make.Idents(List.nil())));
!                         if (allowValueClasses && (owner.isValueClass() || owner.hasStrict() || ((owner.flags_field & RECORD) != 0))) {
+                             tree.body.stats = tree.body.stats.append(supCall);
+                         } else {
+                             tree.body.stats = tree.body.stats.prepend(supCall);
+                         }
                      } else if ((env.enclClass.sym.flags() & ENUM) != 0 &&
                              (tree.mods.flags & GENERATEDCONSTR) == 0 &&
                              TreeInfo.hasConstructorCall(tree, names._super)) {
                          // enum constructors are not allowed to call super
                          // directly, so make sure there aren't any super calls

*** 1240,10 ***
--- 1233,29 ---
                  // Start of constructor prologue
                  localEnv.info.ctorPrologue = isConstructor;
  
                  // Attribute method body.
                  attribStat(tree.body, localEnv);
+                 if (isConstructor) {
+                     ListBuffer<JCTree> prologueCode = new ListBuffer<>();
+                     for (JCTree stat : tree.body.stats) {
+                         prologueCode.add(stat);
+                         /* gather all the stats in the body until a `super` or `this` constructor invocation is found,
+                          * including the constructor invocation, that way we don't need to worry in the visitor below if
+                          * if we are dealing or not with prologue code
+                          */
+                         if (stat instanceof JCExpressionStatement expStmt &&
+                                 expStmt.expr instanceof JCMethodInvocation mi &&
+                                 TreeInfo.isConstructorCall(mi)) {
+                             break;
+                         }
+                     }
+                     if (!prologueCode.isEmpty()) {
+                         CtorPrologueVisitor ctorPrologueVisitor = new CtorPrologueVisitor(localEnv);
+                         ctorPrologueVisitor.scan(prologueCode.toList());
+                     }
+                 }
              }
  
              localEnv.info.scope.leave();
              result = tree.type = m.type;
          } finally {

*** 1251,10 ***
--- 1263,236 ---
              chk.setMethod(prevMethod);
              env.info.ctorPrologue = ctorProloguePrev;
          }
      }
  
+     class CtorPrologueVisitor extends TreeScanner {
+         Env<AttrContext> localEnv;
+         CtorPrologueVisitor(Env<AttrContext> localEnv) {
+             this.localEnv = localEnv;
+         }
+ 
+         boolean insideLambdaOrClassDef = false;
+ 
+         @Override
+         public void visitLambda(JCLambda lambda) {
+             boolean previousInsideLambdaOrClassDef = insideLambdaOrClassDef;
+             try {
+                 insideLambdaOrClassDef = true;
+                 super.visitLambda(lambda);
+             } finally {
+                 insideLambdaOrClassDef = previousInsideLambdaOrClassDef;
+             }
+         }
+ 
+         @Override
+         public void visitClassDef(JCClassDecl classDecl) {
+             boolean previousInsideLambdaOrClassDef = insideLambdaOrClassDef;
+             try {
+                 insideLambdaOrClassDef = true;
+                 super.visitClassDef(classDecl);
+             } finally {
+                 insideLambdaOrClassDef = previousInsideLambdaOrClassDef;
+             }
+         }
+ 
+         private void reportPrologueError(JCTree tree, Symbol sym) {
+             preview.checkSourceLevel(tree, Feature.FLEXIBLE_CONSTRUCTORS);
+             log.error(tree, Errors.CantRefBeforeCtorCalled(sym));
+         }
+ 
+         @Override
+         public void visitApply(JCMethodInvocation tree) {
+             super.visitApply(tree);
+             Name name = TreeInfo.name(tree.meth);
+             boolean isConstructorCall = name == names._this || name == names._super;
+             Symbol msym = TreeInfo.symbolFor(tree.meth);
+             // is this an instance method call or an illegal constructor invocation like: `this.super()`?
+             if (msym != null && // for erroneous invocations msym can be null, ignore those
+                 (!isConstructorCall ||
+                 isConstructorCall && tree.meth.hasTag(SELECT))) {
+                 if (isEarlyReference(localEnv, tree.meth, msym))
+                     reportPrologueError(tree.meth, msym);
+             }
+         }
+ 
+         @Override
+         public void visitIdent(JCIdent tree) {
+             analyzeSymbol(tree);
+         }
+ 
+         @Override
+         public void visitSelect(JCFieldAccess tree) {
+             SelectScanner ss = new SelectScanner();
+             ss.scan(tree);
+             if (ss.scanLater == null) {
+                 analyzeSymbol(tree);
+             } else {
+                 boolean prevLhs = isInLHS;
+                 try {
+                     isInLHS = false;
+                     scan(ss.scanLater);
+                 } finally {
+                     isInLHS = prevLhs;
+                 }
+             }
+         }
+ 
+         @Override
+         public void visitNewClass(JCNewClass tree) {
+             super.visitNewClass(tree);
+             checkNewClassAndMethRefs(tree, tree.type);
+         }
+ 
+         @Override
+         public void visitReference(JCMemberReference tree) {
+             super.visitReference(tree);
+             if (tree.getMode() == JCMemberReference.ReferenceMode.NEW) {
+                 checkNewClassAndMethRefs(tree, tree.expr.type);
+             }
+         }
+ 
+         void checkNewClassAndMethRefs(JCTree tree, Type t) {
+             if (t.tsym.isEnclosedBy(localEnv.enclClass.sym) &&
+                     !t.tsym.isStatic() &&
+                     !t.tsym.isDirectlyOrIndirectlyLocal()) {
+                 reportPrologueError(tree, t.getEnclosingType().tsym);
+             }
+         }
+ 
+         /* if a symbol is in the LHS of an assignment expression we won't consider it as a candidate
+          * for a proxy local variable later on
+          */
+         boolean isInLHS = false;
+ 
+         @Override
+         public void visitAssign(JCAssign tree) {
+             boolean previousIsInLHS = isInLHS;
+             try {
+                 isInLHS = true;
+                 scan(tree.lhs);
+             } finally {
+                 isInLHS = previousIsInLHS;
+             }
+             scan(tree.rhs);
+         }
+ 
+         @Override
+         public void visitMethodDef(JCMethodDecl tree) {
+             // ignore any declarative part, mainly to avoid scanning receiver parameters
+             scan(tree.body);
+         }
+ 
+         void analyzeSymbol(JCTree tree) {
+             Symbol sym = TreeInfo.symbolFor(tree);
+             if (isInLHS && !insideLambdaOrClassDef) {
+                 // Check instance field assignments that appear in constructor prologues
+                 if (isEarlyReference(localEnv, tree, sym)) {
+                     // Field may not be inherited from a superclass
+                     if (sym.owner != localEnv.enclClass.sym) {
+                         log.error(tree, Errors.CantRefBeforeCtorCalled(sym));
+                         return;
+                     }
+ 
+                     // Field may not have an initializer
+                     if ((sym.flags() & HASINIT) != 0) {
+                         log.error(tree, Errors.CantAssignInitializedBeforeCtorCalled(sym));
+                         return;
+                     }
+                 }
+                 return;
+             }
+             tree = TreeInfo.skipParens(tree);
+             if (sym != null) {
+                 if (!sym.isStatic() && sym.kind == VAR && sym.owner.kind == TYP) {
+                     if (sym.name == names._this || sym.name == names._super) {
+                         // are we seeing something like `this` or `CurrentClass.this` or `SuperClass.super::foo`?
+                         if (TreeInfo.isExplicitThisReference(
+                                 types,
+                                 (ClassType)localEnv.enclClass.sym.type,
+                                 tree)) {
+                             reportPrologueError(tree, sym);
+                         }
+                     } else if (sym.kind == VAR && sym.owner.kind == TYP) { // now fields only
+                         if (sym.owner != localEnv.enclClass.sym) {
+                             if (localEnv.enclClass.sym.isSubClass(sym.owner, types) &&
+                                     sym.isInheritedIn(localEnv.enclClass.sym, types)) {
+                                 /* if we are dealing with a field that doesn't belong to the current class, but the
+                                  * field is inherited, this is an error. Unless, the super class is also an outer
+                                  * class and the field's qualifier refers to the outer class
+                                  */
+                                 if (tree.hasTag(IDENT) ||
+                                     TreeInfo.isExplicitThisReference(
+                                             types,
+                                             (ClassType)localEnv.enclClass.sym.type,
+                                             ((JCFieldAccess)tree).selected)) {
+                                     reportPrologueError(tree, sym);
+                                 }
+                             }
+                         } else if (isEarlyReference(localEnv, tree, sym)) {
+                             /* now this is a `proper` instance field of the current class
+                              * references to fields of identity classes which happen to have initializers are
+                              * not allowed in the prologue
+                              */
+                             if (insideLambdaOrClassDef ||
+                                 (!localEnv.enclClass.sym.isValueClass() && (sym.flags_field & HASINIT) != 0))
+                                 reportPrologueError(tree, sym);
+                             // we will need to generate a proxy for this field later on
+                             if (!isInLHS) {
+                                 if (allowValueClasses) {
+                                     localProxyVarsGen.addFieldReadInPrologue(localEnv.enclMethod, sym);
+                                 } else {
+                                     reportPrologueError(tree, sym);
+                                 }
+                             }
+                         }
+                     }
+                 }
+             }
+         }
+ 
+         /**
+          * Determine if the symbol appearance constitutes an early reference to the current class.
+          *
+          * <p>
+          * This means the symbol is an instance field, or method, of the current class and it appears
+          * in an early initialization context of it (i.e., one of its constructor prologues).
+          *
+          * @param env    The current environment
+          * @param tree   the AST referencing the variable
+          * @param sym    The symbol
+          */
+         private boolean isEarlyReference(Env<AttrContext> env, JCTree tree, Symbol sym) {
+             if ((sym.flags() & STATIC) == 0 &&
+                     (sym.kind == VAR || sym.kind == MTH) &&
+                     sym.isMemberOf(env.enclClass.sym, types)) {
+                 // Allow "Foo.this.x" when "Foo" is (also) an outer class, as this refers to the outer instance
+                 if (tree instanceof JCFieldAccess fa) {
+                     return TreeInfo.isExplicitThisReference(types, (ClassType)env.enclClass.type, fa.selected);
+                 }
+                 return true;
+             }
+             return false;
+         }
+ 
+         /* scanner for a select expression, anything that is not a select or identifier
+          * will be stored for further analysis
+          */
+         class SelectScanner extends DeferredAttr.FilterScanner {
+             JCTree scanLater;
+ 
+             SelectScanner() {
+                 super(Set.of(IDENT, SELECT, PARENS));
+             }
+ 
+             @Override
+             void skip(JCTree tree) {
+                 scanLater = tree;
+             }
+         }
+     }
+ 
      public void visitVarDef(JCVariableDecl tree) {
          // Local variables have not been entered yet, so we need to do it now:
          if (env.info.scope.owner.kind == MTH || env.info.scope.owner.kind == VAR) {
              if (tree.sym != null) {
                  // parameters have already been entered

*** 1312,14 ***
                      initEnv.info.lint = lint;
                      // In order to catch self-references, we set the variable's
                      // declaration position to maximal possible value, effectively
                      // marking the variable as undefined.
                      initEnv.info.enclVar = v;
!                     attribExpr(tree.init, initEnv, v.type);
!                     if (tree.isImplicitlyTyped()) {
!                         //fixup local variable type
!                         v.type = chk.checkLocalVarType(tree, tree.init.type, tree.name);
                      }
                  }
                  if (tree.isImplicitlyTyped()) {
                      setSyntheticVariableType(tree, v.type);
                  }
--- 1550,28 ---
                      initEnv.info.lint = lint;
                      // In order to catch self-references, we set the variable's
                      // declaration position to maximal possible value, effectively
                      // marking the variable as undefined.
                      initEnv.info.enclVar = v;
!                     boolean previousCtorPrologue = initEnv.info.ctorPrologue;
!                     try {
!                         if (v.owner.kind == TYP && !v.isStatic() && v.isStrict()) {
!                             // strict instance initializer in a value class
+                             initEnv.info.ctorPrologue = true;
+                         }
+                         attribExpr(tree.init, initEnv, v.type);
+                         if (tree.isImplicitlyTyped()) {
+                             //fixup local variable type
+                             v.type = chk.checkLocalVarType(tree, tree.init.type, tree.name);
+                         }
+                         if (v.owner.kind == TYP && !v.isStatic() && v.isStrict()) {
+                             // strict field initializers are inlined in constructor's prologues
+                             CtorPrologueVisitor ctorPrologueVisitor = new CtorPrologueVisitor(initEnv);
+                             ctorPrologueVisitor.scan(tree.init);
+                         }
+                     } finally {
+                         initEnv.info.ctorPrologue = previousCtorPrologue;
                      }
                  }
                  if (tree.isImplicitlyTyped()) {
                      setSyntheticVariableType(tree, v.type);
                  }

*** 1436,11 ***
                      env.info.scope.owner.flags() & STRICTFP, names.empty, initBlockType,
                      env.info.scope.owner);
              final Env<AttrContext> localEnv =
                  env.dup(tree, env.info.dup(env.info.scope.dupUnshared(fakeOwner)));
  
!             if ((tree.flags & STATIC) != 0) localEnv.info.staticLevel++;
              // Attribute all type annotations in the block
              annotate.queueScanTreeAndTypeAnnotate(tree, localEnv, localEnv.info.scope.owner, null);
              annotate.flush();
              attribStats(tree.stats, localEnv);
  
--- 1688,15 ---
                      env.info.scope.owner.flags() & STRICTFP, names.empty, initBlockType,
                      env.info.scope.owner);
              final Env<AttrContext> localEnv =
                  env.dup(tree, env.info.dup(env.info.scope.dupUnshared(fakeOwner)));
  
!             if ((tree.flags & STATIC) != 0) {
+                 localEnv.info.staticLevel++;
+             } else {
+                 localEnv.info.instanceInitializerBlock = true;
+             }
              // Attribute all type annotations in the block
              annotate.queueScanTreeAndTypeAnnotate(tree, localEnv, localEnv.info.scope.owner, null);
              annotate.flush();
              attribStats(tree.stats, localEnv);
  

*** 1949,12 ***
          }
          return null;
      }
  
      public void visitSynchronized(JCSynchronized tree) {
!         chk.checkRefType(tree.pos(), attribExpr(tree.lock, env));
!         if (tree.lock.type != null && tree.lock.type.isValueBased()) {
              env.info.lint.logIfEnabled(tree.pos(), LintWarnings.AttemptToSynchronizeOnInstanceOfValueBasedClass);
          }
          attribStat(tree.body, env);
          result = null;
      }
--- 2205,12 ---
          }
          return null;
      }
  
      public void visitSynchronized(JCSynchronized tree) {
!         boolean identityType = chk.checkIdentityType(tree.pos(), attribExpr(tree.lock, env));
!         if (identityType && tree.lock.type != null && tree.lock.type.isValueBased()) {
              env.info.lint.logIfEnabled(tree.pos(), LintWarnings.AttemptToSynchronizeOnInstanceOfValueBasedClass);
          }
          attribStat(tree.body, env);
          result = null;
      }

*** 4404,10 ***
--- 4660,11 ---
                  skind = KindSelector.of(skind, KindSelector.VAL, KindSelector.TYP);
          }
  
          // Attribute the qualifier expression, and determine its symbol (if any).
          Type site = attribTree(tree.selected, env, new ResultInfo(skind, Type.noType));
+         Assert.check(site == tree.selected.type);
          if (!pkind().contains(KindSelector.TYP_PCK))
              site = capture(site); // Capture field access
  
          // don't allow T.class T[].class, etc
          if (skind == KindSelector.TYP) {

*** 5507,11 ***
  
                          if (!hasErrorSuper) {
                              log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.NonSealedWithNoSealedSupertype(c));
                          }
                      }
!                 } else {
                      if (c.isDirectlyOrIndirectlyLocal() && !c.isEnum()) {
                          log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.LocalClassesCantExtendSealed(c.isAnonymous() ? Fragments.Anonymous : Fragments.Local));
                      }
  
                      if (!c.type.isCompound()) {
--- 5764,11 ---
  
                          if (!hasErrorSuper) {
                              log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.NonSealedWithNoSealedSupertype(c));
                          }
                      }
!                 } else if ((c.flags_field & Flags.COMPOUND) == 0) {
                      if (c.isDirectlyOrIndirectlyLocal() && !c.isEnum()) {
                          log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.LocalClassesCantExtendSealed(c.isAnonymous() ? Fragments.Anonymous : Fragments.Local));
                      }
  
                      if (!c.type.isCompound()) {

*** 5545,10 ***
--- 5802,15 ---
  
                  if (rs.isSerializable(c.type)) {
                      env.info.isSerializable = true;
                  }
  
+                 if (c.isValueClass()) {
+                     Assert.check(env.tree.hasTag(CLASSDEF));
+                     chk.checkConstraintsOfValueClass((JCClassDecl) env.tree, c);
+                 }
+ 
                  attribClassBody(env, c);
  
                  chk.checkDeprecatedAnnotation(env.tree.pos(), c);
                  chk.checkClassOverrideEqualsAndHashIfNeeded(env.tree.pos(), c);
                  chk.checkFunctionalInterface((JCClassDecl) env.tree, c);

*** 5689,11 ***
          // Check for proper use of serialVersionUID and other
          // serialization-related fields and methods
          if (env.info.lint.isEnabled(LintCategory.SERIAL)
                  && rs.isSerializable(c.type)
                  && !c.isAnonymous()) {
!             chk.checkSerialStructure(tree, c);
          }
          // Correctly organize the positions of the type annotations
          typeAnnotations.organizeTypeAnnotationsBodies(tree);
  
          // Check type annotations applicability rules
--- 5951,11 ---
          // Check for proper use of serialVersionUID and other
          // serialization-related fields and methods
          if (env.info.lint.isEnabled(LintCategory.SERIAL)
                  && rs.isSerializable(c.type)
                  && !c.isAnonymous()) {
!             chk.checkSerialStructure(env, tree, c);
          }
          // Correctly organize the positions of the type annotations
          typeAnnotations.organizeTypeAnnotationsBodies(tree);
  
          // Check type annotations applicability rules
< prev index next >