package org.checkerframework.common.basetype;

import com.github.javaparser.ParseProblemException;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.printer.DefaultPrettyPrinter;
import com.sun.source.tree.AnnotatedTypeTree;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.ArrayAccessTree;
import com.sun.source.tree.ArrayTypeTree;
import com.sun.source.tree.AssignmentTree;
import com.sun.source.tree.CatchTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.CompoundAssignmentTree;
import com.sun.source.tree.ConditionalExpressionTree;
import com.sun.source.tree.EnhancedForLoopTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.IdentifierTree;
import com.sun.source.tree.InstanceOfTree;
import com.sun.source.tree.IntersectionTypeTree;
import com.sun.source.tree.LambdaExpressionTree;
import com.sun.source.tree.MemberReferenceTree;
import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.ModifiersTree;
import com.sun.source.tree.NewArrayTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.ParameterizedTypeTree;
import com.sun.source.tree.ReturnTree;
import com.sun.source.tree.ThrowTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.TypeCastTree;
import com.sun.source.tree.TypeParameterTree;
import com.sun.source.tree.UnaryTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.SourcePositions;
import com.sun.source.util.TreePath;
import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCIdent;
import com.sun.tools.javac.tree.JCTree.JCMemberReference;
import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
import com.sun.tools.javac.tree.TreeInfo;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.Vector;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.tools.Diagnostic.Kind;
import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey;
import org.checkerframework.checker.interning.qual.FindDistinct;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.dataflow.analysis.Analysis;
import org.checkerframework.dataflow.analysis.TransferResult;
import org.checkerframework.dataflow.cfg.node.BooleanLiteralNode;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.dataflow.cfg.node.ReturnNode;
import org.checkerframework.dataflow.expression.JavaExpression;
import org.checkerframework.dataflow.expression.JavaExpressionScanner;
import org.checkerframework.dataflow.expression.LocalVariable;
import org.checkerframework.dataflow.qual.Pure;
import org.checkerframework.dataflow.util.PurityChecker;
import org.checkerframework.dataflow.util.PurityChecker.PurityResult;
import org.checkerframework.dataflow.util.PurityUtils;
import org.checkerframework.framework.ajava.AnnotationEqualityVisitor;
import org.checkerframework.framework.ajava.ExpectedTreesVisitor;
import org.checkerframework.framework.ajava.InsertAjavaAnnotations;
import org.checkerframework.framework.ajava.JointVisitorWithDefaultAction;
import org.checkerframework.framework.flow.CFAbstractStore;
import org.checkerframework.framework.flow.CFAbstractValue;
import org.checkerframework.framework.qual.DefaultQualifier;
import org.checkerframework.framework.qual.Unused;
import org.checkerframework.framework.source.DiagMessage;
import org.checkerframework.framework.source.SourceVisitor;
import org.checkerframework.framework.type.AnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeFactory.ParameterizedExecutableType;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedIntersectionType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedPrimitiveType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedUnionType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedWildcardType;
import org.checkerframework.framework.type.AnnotatedTypeParameterBounds;
import org.checkerframework.framework.type.GenericAnnotatedTypeFactory;
import org.checkerframework.framework.type.QualifierHierarchy;
import org.checkerframework.framework.type.TypeHierarchy;
import org.checkerframework.framework.type.VisitorState;
import org.checkerframework.framework.type.poly.QualifierPolymorphism;
import org.checkerframework.framework.type.visitor.SimpleAnnotatedTypeScanner;
import org.checkerframework.framework.util.AnnotatedTypes;
import org.checkerframework.framework.util.Contract;
import org.checkerframework.framework.util.Contract.ConditionalPostcondition;
import org.checkerframework.framework.util.Contract.Postcondition;
import org.checkerframework.framework.util.Contract.Precondition;
import org.checkerframework.framework.util.ContractsFromMethod;
import org.checkerframework.framework.util.FieldInvariants;
import org.checkerframework.framework.util.JavaExpressionParseUtil.JavaExpressionParseException;
import org.checkerframework.framework.util.JavaParserUtil;
import org.checkerframework.framework.util.StringToJavaExpression;
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.Pair;
import org.checkerframework.javacutil.TreePathUtil;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypesUtils;
import org.plumelib.util.ArraysPlume;
import org.plumelib.util.CollectionsPlume;

/**
 * A {@link SourceVisitor} that performs assignment and pseudo-assignment checking, method
 * invocation checking, and assignability checking.
 *
 * <p>This implementation uses the {@link AnnotatedTypeFactory} implementation provided by an
 * associated {@link BaseTypeChecker}; its visitor methods will invoke this factory on parts of the
 * AST to determine the "annotated type" of an expression. Then, the visitor methods will check the
 * types in assignments and pseudo-assignments using {@link #commonAssignmentCheck}, which
 * ultimately calls the {@link TypeHierarchy#isSubtype} method and reports errors that violate
 * Java's rules of assignment.
 *
 * <p>Note that since this implementation only performs assignment and pseudo-assignment checking,
 * other rules for custom type systems must be added in subclasses (e.g., dereference checking in
 * the {@link org.checkerframework.checker.nullness.NullnessChecker} is implemented in the {@link
 * org.checkerframework.checker.nullness.NullnessChecker}'s {@link TreeScanner#visitMemberSelect}
 * method).
 *
 * <p>This implementation does the following checks:
 *
 * <ol>
 *   <li><b>Assignment and Pseudo-Assignment Check</b>: It verifies that any assignment type-checks,
 *       using {@code TypeHierarchy.isSubtype} method. This includes method invocation and method
 *       overriding checks.
 *   <li><b>Type Validity Check</b>: It verifies that any user-supplied type is a valid type, using
 *       one of the {@code isValidUse} methods.
 *   <li><b>(Re-)Assignability Check</b>: It verifies that any assignment is valid, using {@code
 *       Checker.isAssignable} method.
 * </ol>
 *
 * @see "JLS $4"
 * @see TypeHierarchy#isSubtype(AnnotatedTypeMirror, AnnotatedTypeMirror)
 * @see AnnotatedTypeFactory
 */
/*
 * Note how the handling of VisitorState is duplicated in AbstractFlow. In
 * particular, the handling of the assignment context has to be done correctly
 * in both classes. This is a pain and we should see how to handle this in the
 * DFF version.
 *
 * TODO: missing assignment context: array initializer
 * expressions should have the component type as context
 */
public class BaseTypeVisitor<Factory extends GenericAnnotatedTypeFactory<?, ?, ?, ?>>
    extends SourceVisitor<Void, Void> {

  /** The {@link BaseTypeChecker} for error reporting. */
  protected final BaseTypeChecker checker;

  /** The factory to use for obtaining "parsed" version of annotations. */
  protected final Factory atypeFactory;

  /** For obtaining line numbers in -Ashowchecks debugging output. */
  protected final SourcePositions positions;

  /** For storing visitor state. */
  protected final VisitorState visitorState;

  /** The element for java.util.Vector#copyInto. */
  private final ExecutableElement vectorCopyInto;

  /** The element for java.util.function.Function#apply. */
  private final ExecutableElement functionApply;

  /** The type of java.util.Vector. */
  private final AnnotatedDeclaredType vectorType;

  /** The @java.lang.annotation.Target annotation. */
  protected final AnnotationMirror TARGET =
      AnnotationBuilder.fromClass(
          elements,
          java.lang.annotation.Target.class,
          AnnotationBuilder.elementNamesValues("value", new ElementType[0]));

  /** The {@code value} element/field of the @java.lang.annotation.Target annotation. */
  protected final ExecutableElement targetValueElement;
  /** The {@code when} element/field of the @Unused annotation. */
  protected final ExecutableElement unusedWhenElement;

  /** True if "-Ashowchecks" was passed on the command line. */
  private final boolean showchecks;

  /**
   * @param checker the type-checker associated with this visitor (for callbacks to {@link
   *     TypeHierarchy#isSubtype})
   */
  public BaseTypeVisitor(BaseTypeChecker checker) {
    this(checker, null);
  }

  /**
   * @param checker the type-checker associated with this visitor
   * @param typeFactory the type factory, or null. If null, this calls {@link #createTypeFactory}.
   */
  protected BaseTypeVisitor(BaseTypeChecker checker, Factory typeFactory) {
    super(checker);

    this.checker = checker;
    this.atypeFactory = typeFactory == null ? createTypeFactory() : typeFactory;
    this.positions = trees.getSourcePositions();
    this.visitorState = atypeFactory.getVisitorState();
    this.typeValidator = createTypeValidator();
    ProcessingEnvironment env = checker.getProcessingEnvironment();
    this.vectorCopyInto = TreeUtils.getMethod("java.util.Vector", "copyInto", 1, env);
    this.functionApply = TreeUtils.getMethod("java.util.function.Function", "apply", 1, env);
    this.vectorType =
        atypeFactory.fromElement(elements.getTypeElement(Vector.class.getCanonicalName()));
    targetValueElement = TreeUtils.getMethod(Target.class, "value", 0, env);
    unusedWhenElement = TreeUtils.getMethod(Unused.class, "when", 0, env);
    showchecks = checker.hasOption("showchecks");
  }

  /**
   * Constructs an instance of the appropriate type factory for the implemented type system.
   *
   * <p>The default implementation uses the checker naming convention to create the appropriate type
   * factory. If no factory is found, it returns {@link BaseAnnotatedTypeFactory}. It reflectively
   * invokes the constructor that accepts this checker and compilation unit tree (in that order) as
   * arguments.
   *
   * <p>Subclasses have to override this method to create the appropriate visitor if they do not
   * follow the checker naming convention.
   *
   * @return the appropriate type factory
   */
  @SuppressWarnings("unchecked") // unchecked cast to type variable
  protected Factory createTypeFactory() {
    // Try to reflectively load the type factory.
    Class<?> checkerClass = checker.getClass();
    while (checkerClass != BaseTypeChecker.class) {
      AnnotatedTypeFactory result =
          BaseTypeChecker.invokeConstructorFor(
              BaseTypeChecker.getRelatedClassName(checkerClass, "AnnotatedTypeFactory"),
              new Class<?>[] {BaseTypeChecker.class},
              new Object[] {checker});
      if (result != null) {
        return (Factory) result;
      }
      checkerClass = checkerClass.getSuperclass();
    }
    try {
      return (Factory) new BaseAnnotatedTypeFactory(checker);
    } catch (Throwable t) {
      throw new BugInCF(
          "Unexpected "
              + t.getClass().getSimpleName()
              + " when invoking BaseAnnotatedTypeFactory for checker "
              + checker.getClass().getSimpleName(),
          t);
    }
  }

  public final Factory getTypeFactory() {
    return atypeFactory;
  }

  /**
   * A public variant of {@link #createTypeFactory}. Only use this if you know what you are doing.
   *
   * @return the appropriate type factory
   */
  public Factory createTypeFactoryPublic() {
    return createTypeFactory();
  }

  // **********************************************************************
  // Responsible for updating the factory for the location (for performance)
  // **********************************************************************

  @Override
  public void setRoot(CompilationUnitTree root) {
    atypeFactory.setRoot(root);
    super.setRoot(root);
    testJointJavacJavaParserVisitor();
    testAnnotationInsertion();
  }

  @Override
  public Void scan(@Nullable Tree tree, Void p) {
    if (tree != null && getCurrentPath() != null) {
      this.visitorState.setPath(new TreePath(getCurrentPath(), tree));
    }
    return super.scan(tree, p);
  }

  /**
   * Test {@link org.checkerframework.framework.ajava.JointJavacJavaParserVisitor} if the checker
   * has the "ajavaChecks" option.
   *
   * <p>Parse the current source file with JavaParser and check that the AST can be matched with the
   * Tree prodoced by javac. Crash if not.
   *
   * <p>Subclasses may override this method to disable the test if even the option is provided.
   */
  protected void testJointJavacJavaParserVisitor() {
    if (root == null || !checker.hasOption("ajavaChecks")) {
      return;
    }

    Map<Tree, com.github.javaparser.ast.Node> treePairs = new HashMap<>();
    try (InputStream reader = root.getSourceFile().openInputStream()) {
      CompilationUnit javaParserRoot = JavaParserUtil.parseCompilationUnit(reader);
      JavaParserUtil.concatenateAddedStringLiterals(javaParserRoot);
      new JointVisitorWithDefaultAction() {
        @Override
        public void defaultAction(Tree javacTree, com.github.javaparser.ast.Node javaParserNode) {
          treePairs.put(javacTree, javaParserNode);
        }
      }.visitCompilationUnit(root, javaParserRoot);
      ExpectedTreesVisitor expectedTreesVisitor = new ExpectedTreesVisitor();
      expectedTreesVisitor.visitCompilationUnit(root, null);
      for (Tree expected : expectedTreesVisitor.getTrees()) {
        if (!treePairs.containsKey(expected)) {
          throw new BugInCF(
              "Javac tree not matched to JavaParser node: %s, in file: %s",
              expected, root.getSourceFile().getName());
        }
      }
    } catch (IOException e) {
      throw new BugInCF("Error reading Java source file", e);
    }
  }

  /**
   * Tests {@link org.checkerframework.framework.ajava.InsertAjavaAnnotations} if the checker has
   * the "ajavaChecks" option.
   *
   * <ol>
   *   <li>Parses the current file with JavaParser.
   *   <li>Removes all annotations.
   *   <li>Reinserts the annotations.
   *   <li>Throws an exception if the ASTs are not the same.
   * </ol>
   *
   * <p>Subclasses may override this method to disable the test even if the option is provided.
   */
  protected void testAnnotationInsertion() {
    if (root == null || !checker.hasOption("ajavaChecks")) {
      return;
    }

    CompilationUnit originalAst;
    try (InputStream originalInputStream = root.getSourceFile().openInputStream()) {
      originalAst = JavaParserUtil.parseCompilationUnit(originalInputStream);
    } catch (IOException e) {
      throw new BugInCF("Error while reading Java file: " + root.getSourceFile().toUri(), e);
    }

    CompilationUnit astWithoutAnnotations = originalAst.clone();
    JavaParserUtil.clearAnnotations(astWithoutAnnotations);
    String withoutAnnotations = new DefaultPrettyPrinter().print(astWithoutAnnotations);

    String withAnnotations;
    try (InputStream annotationInputStream = root.getSourceFile().openInputStream()) {
      // This check only runs on files from the Checker Framework test suite, which should all use
      // UNIX line separators. Using System.lineSeparator instead of "\n" could cause the test to
      // fail on Mac or Windows.
      withAnnotations =
          new InsertAjavaAnnotations(elements)
              .insertAnnotations(annotationInputStream, withoutAnnotations, "\n");
    } catch (IOException e) {
      throw new BugInCF("Error while reading Java file: " + root.getSourceFile().toUri(), e);
    }

    CompilationUnit modifiedAst = null;
    try {
      modifiedAst = JavaParserUtil.parseCompilationUnit(withAnnotations);
    } catch (ParseProblemException e) {
      throw new BugInCF("Failed to parse annotation insertion:\n" + withAnnotations, e);
    }

    AnnotationEqualityVisitor visitor = new AnnotationEqualityVisitor();
    originalAst.accept(visitor, modifiedAst);
    if (!visitor.getAnnotationsMatch()) {
      throw new BugInCF(
          "Reinserting annotations produced different AST.\n"
              + "Original node: "
              + visitor.getMismatchedNode1()
              + "\n"
              + "Node with annotations re-inserted: "
              + visitor.getMismatchedNode2()
              + "\n"
              + "Original annotations: "
              + visitor.getMismatchedNode1().getAnnotations()
              + "\n"
              + "Re-inserted annotations: "
              + visitor.getMismatchedNode2().getAnnotations()
              + "\n"
              + "Original AST:\n"
              + originalAst
              + "\n"
              + "Ast with annotations re-inserted: "
              + modifiedAst);
    }
  }

  /**
   * Type-check classTree and skips classes specified by the skipDef option. Subclasses should
   * override {@link #processClassTree(ClassTree)} instead of this method.
   *
   * @param classTree class to check
   * @param p null
   * @return null
   */
  @Override
  public final Void visitClass(ClassTree classTree, Void p) {
    if (checker.shouldSkipDefs(classTree)) {
      // Not "return super.visitClass(classTree, p);" because that would recursively call visitors
      // on subtrees; we want to skip the class entirely.
      return null;
    }
    atypeFactory.preProcessClassTree(classTree);

    TreePath preTreePath = visitorState.getPath();
    AnnotatedDeclaredType preACT = visitorState.getClassType();
    ClassTree preCT = visitorState.getClassTree();
    AnnotatedDeclaredType preAMT = visitorState.getMethodReceiver();
    MethodTree preMT = visitorState.getMethodTree();
    Pair<Tree, AnnotatedTypeMirror> preAssignmentContext = visitorState.getAssignmentContext();

    // Don't use atypeFactory.getPath, because that depends on the visitorState path.
    visitorState.setPath(TreePath.getPath(root, classTree));
    visitorState.setClassType(
        atypeFactory.getAnnotatedType(TreeUtils.elementFromDeclaration(classTree)));
    visitorState.setClassTree(classTree);
    visitorState.setMethodReceiver(null);
    visitorState.setMethodTree(null);
    visitorState.setAssignmentContext(null);

    try {
      processClassTree(classTree);
      atypeFactory.postProcessClassTree(classTree);
    } finally {
      visitorState.setPath(preTreePath);
      visitorState.setClassType(preACT);
      visitorState.setClassTree(preCT);
      visitorState.setMethodReceiver(preAMT);
      visitorState.setMethodTree(preMT);
      visitorState.setAssignmentContext(preAssignmentContext);
    }
    return null;
  }

  /**
   * Type-check classTree. Subclasses should override this method instead of {@link
   * #visitClass(ClassTree, Void)}.
   *
   * @param classTree class to check
   */
  public void processClassTree(ClassTree classTree) {
    checkFieldInvariantDeclarations(classTree);
    if (!TreeUtils.hasExplicitConstructor(classTree)) {
      checkDefaultConstructor(classTree);
    }

    AnnotatedDeclaredType classType = atypeFactory.getAnnotatedType(classTree);
    atypeFactory.getDependentTypesHelper().checkClassForErrorExpressions(classTree, classType);
    validateType(classTree, classType);

    Tree ext = classTree.getExtendsClause();
    if (ext != null) {
      validateTypeOf(ext);
    }

    List<? extends Tree> impls = classTree.getImplementsClause();
    if (impls != null) {
      for (Tree im : impls) {
        validateTypeOf(im);
      }
    }

    checkForPolymorphicQualifiers(classTree);

    checkExtendsImplements(classTree);

    checkQualifierParameter(classTree);

    super.visitClass(classTree, null);
  }

  /**
   * A TreeScanner that issues an "invalid.polymorphic.qualifier" error for each {@link
   * AnnotationTree} that is a polymorphic qualifier. The second parameter is added to the error
   * message and should explain the location.
   */
  private final TreeScanner<Void, String> polyTreeScanner =
      new TreeScanner<Void, String>() {
        @Override
        public Void visitAnnotation(AnnotationTree annoTree, String location) {
          QualifierHierarchy qualifierHierarchy = atypeFactory.getQualifierHierarchy();
          AnnotationMirror anno = TreeUtils.annotationFromAnnotationTree(annoTree);
          if (atypeFactory.isSupportedQualifier(anno)
              && qualifierHierarchy.isPolymorphicQualifier(anno)) {
            checker.reportError(annoTree, "invalid.polymorphic.qualifier", anno, location);
          }
          return super.visitAnnotation(annoTree, location);
        }
      };

  /**
   * Issues an "invalid.polymorphic.qualifier" error for all polymorphic annotations written on the
   * class declaration.
   *
   * @param classTree the class to check
   */
  protected void checkForPolymorphicQualifiers(ClassTree classTree) {
    if (TypesUtils.isAnonymous(TreeUtils.typeOf(classTree))) {
      // Anonymous class can have polymorphic annotations, so don't check them.
      return;
    }
    classTree.getModifiers().accept(polyTreeScanner, "in a class declaration");
    if (classTree.getExtendsClause() != null) {
      classTree.getExtendsClause().accept(polyTreeScanner, "in a class declaration");
    }
    for (Tree tree : classTree.getImplementsClause()) {
      tree.accept(polyTreeScanner, "in a class declaration");
    }
    for (Tree tree : classTree.getTypeParameters()) {
      tree.accept(polyTreeScanner, "in a class declaration");
    }
  }

  /**
   * Issues an "invalid.polymorphic.qualifier" error for all polymorphic annotations written on the
   * type parameters declaration.
   *
   * @param typeParameterTrees the type parameters to check
   */
  protected void checkForPolymorphicQualifiers(
      List<? extends TypeParameterTree> typeParameterTrees) {
    for (Tree tree : typeParameterTrees) {
      tree.accept(polyTreeScanner, "in a type parameter");
    }
  }

  /**
   * Issues an error if {@code classTree} has polymorphic fields but is not annotated with
   * {@code @HasQualifierParameter}. Always issue a warning if the type of a static field is
   * annotated with a polymorphic qualifier.
   *
   * <p>Issues an error if {@code classTree} extends or implements a class/interface that has a
   * qualifier parameter, but this class does not.
   *
   * @param classTree the ClassTree to check for polymorphic fields
   */
  protected void checkQualifierParameter(ClassTree classTree) {
    // Set of polymorphic qualifiers for hierarchies that do not have a qualifier parameter and
    // therefor cannot appear on a field.
    Set<AnnotationMirror> illegalOnFieldsPolyQual = AnnotationUtils.createAnnotationSet();
    // Set of polymorphic annotations for all hierarchies
    Set<AnnotationMirror> polys = AnnotationUtils.createAnnotationSet();
    TypeElement classElement = TreeUtils.elementFromDeclaration(classTree);
    for (AnnotationMirror top : atypeFactory.getQualifierHierarchy().getTopAnnotations()) {
      AnnotationMirror poly = atypeFactory.getQualifierHierarchy().getPolymorphicAnnotation(top);
      if (poly != null) {
        polys.add(poly);
      }
      // else {
      // If there is no polymorphic qualifier in the hierarchy, it could still have a
      // @HasQualifierParameter that must be checked.
      // }

      if (atypeFactory.hasExplicitQualifierParameterInHierarchy(classElement, top)
          && atypeFactory.hasExplicitNoQualifierParameterInHierarchy(classElement, top)) {
        checker.reportError(classTree, "conflicting.qual.param", top);
      }

      if (atypeFactory.hasQualifierParameterInHierarchy(classElement, top)) {
        continue;
      }

      if (poly != null) {
        illegalOnFieldsPolyQual.add(poly);
      }
      Element extendsEle = TypesUtils.getTypeElement(classElement.getSuperclass());
      if (extendsEle != null && atypeFactory.hasQualifierParameterInHierarchy(extendsEle, top)) {
        checker.reportError(classTree, "missing.has.qual.param", top);
      } else {
        for (TypeMirror interfaceType : classElement.getInterfaces()) {
          Element interfaceEle = TypesUtils.getTypeElement(interfaceType);
          if (atypeFactory.hasQualifierParameterInHierarchy(interfaceEle, top)) {
            checker.reportError(classTree, "missing.has.qual.param", top);
            break; // only issue error once
          }
        }
      }
    }

    for (Tree mem : classTree.getMembers()) {
      if (mem.getKind() == Tree.Kind.VARIABLE) {
        AnnotatedTypeMirror fieldType = atypeFactory.getAnnotatedType(mem);
        List<DiagMessage> hasIllegalPoly;
        if (ElementUtils.isStatic(TreeUtils.elementFromDeclaration((VariableTree) mem))) {
          // A polymorphic qualifier is not allowed on a static field even if the class
          // has a qualifier parameter.
          hasIllegalPoly = polyScanner.visit(fieldType, polys);
        } else {
          hasIllegalPoly = polyScanner.visit(fieldType, illegalOnFieldsPolyQual);
        }
        for (DiagMessage dm : hasIllegalPoly) {
          checker.report(mem, dm);
        }
      }
    }
  }

  /**
   * A scanner that given a set of polymorphic qualifiers, returns a list of errors reporting a use
   * of one of the polymorphic qualifiers.
   */
  private final PolyTypeScanner polyScanner = new PolyTypeScanner();

  /**
   * A scanner that given a set of polymorphic qualifiers, returns a list of errors reporting a use
   * of one of the polymorphic qualifiers.
   */
  static class PolyTypeScanner
      extends SimpleAnnotatedTypeScanner<List<DiagMessage>, Set<AnnotationMirror>> {

    /** Create PolyTypeScanner. */
    private PolyTypeScanner() {
      super(DiagMessage::mergeLists, Collections.emptyList());
    }

    @Override
    protected List<DiagMessage> defaultAction(
        AnnotatedTypeMirror type, Set<AnnotationMirror> polys) {
      if (type == null) {
        return Collections.emptyList();
      }

      for (AnnotationMirror poly : polys) {
        if (type.hasAnnotationRelaxed(poly)) {
          return Collections.singletonList(
              new DiagMessage(Kind.ERROR, "invalid.polymorphic.qualifier.use", poly));
        }
      }
      return Collections.emptyList();
    }
  }

  /**
   * If "@B class Y extends @A X {}", then enforce that @B must be a subtype of @A.
   *
   * <p>Also validate the types of the extends and implements clauses.
   *
   * @param classTree class tree to check
   */
  protected void checkExtendsImplements(ClassTree classTree) {
    if (TypesUtils.isAnonymous(TreeUtils.typeOf(classTree))) {
      // Don't check extends clause on anonymous classes.
      return;
    }
    Set<AnnotationMirror> classBounds =
        atypeFactory.getTypeDeclarationBounds(TreeUtils.typeOf(classTree));
    QualifierHierarchy qualifierHierarchy = atypeFactory.getQualifierHierarchy();
    // If "@B class Y extends @A X {}", then enforce that @B must be a subtype of @A.
    // classTree.getExtendsClause() is null when there is no explicitly-written extends clause,
    // as in "class X {}". This is equivalent to writing "class X extends @Top Object {}", so
    // there is no need to do any subtype checking.
    if (classTree.getExtendsClause() != null) {
      Set<AnnotationMirror> extendsAnnos =
          atypeFactory.getTypeOfExtendsImplements(classTree.getExtendsClause()).getAnnotations();
      for (AnnotationMirror classAnno : classBounds) {
        AnnotationMirror extendsAnno =
            qualifierHierarchy.findAnnotationInSameHierarchy(extendsAnnos, classAnno);
        if (!qualifierHierarchy.isSubtype(classAnno, extendsAnno)) {
          checker.reportError(
              classTree.getExtendsClause(),
              "declaration.inconsistent.with.extends.clause",
              classAnno,
              extendsAnno);
        }
      }
    }
    // Do the same check as above for implements clauses.
    for (Tree implementsClause : classTree.getImplementsClause()) {
      Set<AnnotationMirror> implementsClauseAnnos =
          atypeFactory.getTypeOfExtendsImplements(implementsClause).getAnnotations();

      for (AnnotationMirror classAnno : classBounds) {
        AnnotationMirror implementsAnno =
            qualifierHierarchy.findAnnotationInSameHierarchy(implementsClauseAnnos, classAnno);
        if (!qualifierHierarchy.isSubtype(classAnno, implementsAnno)) {
          checker.reportError(
              implementsClause,
              "declaration.inconsistent.with.implements.clause",
              classAnno,
              implementsAnno);
        }
      }
    }
  }

  /**
   * Check that the field invariant declaration annotations meet the following requirements:
   *
   * <ol>
   *   <!-- The item numbering is referred to in the body of the method.-->
   *   <li value="1">If the superclass of {@code classTree} has a field invariant, then the field
   *       invariant for {@code classTree} must include all the fields in the superclass invariant
   *       and those fields' annotations must be a subtype (or equal) to the annotations for those
   *       fields in the superclass.
   *   <li value="2">The fields in the invariant must be a.) final and b.) declared in a superclass
   *       of {@code classTree}.
   *   <li value="3">The qualifier for each field must be a subtype of the annotation on the
   *       declaration of that field.
   *   <li value="4">The field invariant has an equal number of fields and qualifiers, or it has one
   *       qualifier and at least one field.
   * </ol>
   *
   * @param classTree class that might have a field invariant
   * @checker_framework.manual #field-invariants Field invariants
   */
  protected void checkFieldInvariantDeclarations(ClassTree classTree) {
    TypeElement elt = TreeUtils.elementFromDeclaration(classTree);
    FieldInvariants invariants = atypeFactory.getFieldInvariants(elt);
    if (invariants == null) {
      // No invariants to check
      return;
    }

    // Where to issue an error, if any.
    Tree errorTree =
        atypeFactory.getFieldInvariantAnnotationTree(classTree.getModifiers().getAnnotations());
    if (errorTree == null) {
      // If the annotation was inherited, then there is no annotation tree, so issue the
      // error on the class.
      errorTree = classTree;
    }

    // Checks #4 (see method Javadoc)
    if (!invariants.isWellFormed()) {
      checker.reportError(errorTree, "field.invariant.not.wellformed");
      return;
    }

    TypeMirror superClass = elt.getSuperclass();
    List<String> fieldsNotFound = new ArrayList<>(invariants.getFields());
    Set<VariableElement> fieldElts =
        ElementUtils.findFieldsInTypeOrSuperType(superClass, fieldsNotFound);

    // Checks that fields are declared in super class. (#2b)
    if (!fieldsNotFound.isEmpty()) {
      String notFoundString = String.join(", ", fieldsNotFound);
      checker.reportError(errorTree, "field.invariant.not.found", notFoundString);
    }

    FieldInvariants superInvar =
        atypeFactory.getFieldInvariants(TypesUtils.getTypeElement(superClass));
    if (superInvar != null) {
      // Checks #3 (see method Javadoc)
      DiagMessage superError = invariants.isSuperInvariant(superInvar, atypeFactory);
      if (superError != null) {
        checker.report(errorTree, superError);
      }
    }

    List<String> notFinal = new ArrayList<>();
    for (VariableElement field : fieldElts) {
      String fieldName = field.getSimpleName().toString();
      if (!ElementUtils.isFinal(field)) {
        notFinal.add(fieldName);
      }
      AnnotatedTypeMirror type = atypeFactory.getAnnotatedType(field);

      List<AnnotationMirror> annos = invariants.getQualifiersFor(field.getSimpleName());
      for (AnnotationMirror invariantAnno : annos) {
        AnnotationMirror declaredAnno = type.getEffectiveAnnotationInHierarchy(invariantAnno);
        if (declaredAnno == null) {
          // invariant anno isn't in this hierarchy
          continue;
        }

        if (!atypeFactory.getQualifierHierarchy().isSubtype(invariantAnno, declaredAnno)) {
          // Checks #3
          checker.reportError(
              errorTree, "field.invariant.not.subtype", fieldName, invariantAnno, declaredAnno);
        }
      }
    }

    // Checks #2a
    if (!notFinal.isEmpty()) {
      String notFinalString = String.join(", ", notFinal);
      checker.reportError(errorTree, "field.invariant.not.final", notFinalString);
    }
  }

  protected void checkDefaultConstructor(ClassTree node) {}

  /**
   * Performs pseudo-assignment check: checks that the method obeys override and subtype rules to
   * all overridden methods.
   *
   * <p>The override rule specifies that a method, m1, may override a method m2 only if:
   *
   * <ul>
   *   <li>m1 return type is a subtype of m2
   *   <li>m1 receiver type is a supertype of m2
   *   <li>m1 parameters are supertypes of corresponding m2 parameters
   * </ul>
   *
   * Also, it issues a "missing.this" error for static method annotated receivers.
   */
  @Override
  public Void visitMethod(MethodTree node, Void p) {
    // We copy the result from getAnnotatedType to ensure that circular types (e.g. K extends
    // Comparable<K>) are represented by circular AnnotatedTypeMirrors, which avoids problems with
    // later checks.
    // TODO: Find a cleaner way to ensure circular AnnotatedTypeMirrors.
    AnnotatedExecutableType methodType = atypeFactory.getAnnotatedType(node).deepCopy();
    AnnotatedDeclaredType preMRT = visitorState.getMethodReceiver();
    MethodTree preMT = visitorState.getMethodTree();
    visitorState.setMethodReceiver(methodType.getReceiverType());
    visitorState.setMethodTree(node);
    ExecutableElement methodElement = TreeUtils.elementFromDeclaration(node);

    warnAboutTypeAnnotationsTooEarly(node, node.getModifiers());

    if (node.getReturnType() != null) {
      visitAnnotatedType(node.getModifiers().getAnnotations(), node.getReturnType());
    }

    try {
      if (TreeUtils.isAnonymousConstructor(node)) {
        // We shouldn't dig deeper
        return null;
      }

      if (TreeUtils.isConstructor(node)) {
        checkConstructorResult(methodType, methodElement);
      }

      checkPurity(node);

      // Passing the whole method/constructor validates the return type
      validateTypeOf(node);

      // Validate types in throws clauses
      for (ExpressionTree thr : node.getThrows()) {
        validateTypeOf(thr);
      }

      atypeFactory.getDependentTypesHelper().checkMethodForErrorExpressions(node, methodType);

      // Check method overrides
      AnnotatedDeclaredType enclosingType =
          (AnnotatedDeclaredType)
              atypeFactory.getAnnotatedType(methodElement.getEnclosingElement());

      // Find which methods this method overrides
      Map<AnnotatedDeclaredType, ExecutableElement> overriddenMethods =
          AnnotatedTypes.overriddenMethods(elements, atypeFactory, methodElement);
      for (Map.Entry<AnnotatedDeclaredType, ExecutableElement> pair :
          overriddenMethods.entrySet()) {
        AnnotatedDeclaredType overriddenType = pair.getKey();
        ExecutableElement overriddenMethodElt = pair.getValue();
        AnnotatedExecutableType overriddenMethodType =
            AnnotatedTypes.asMemberOf(types, atypeFactory, overriddenType, overriddenMethodElt);
        if (!checkOverride(node, enclosingType, overriddenMethodType, overriddenType)) {
          // Stop at the first mismatch; this makes a difference only if
          // -Awarns is passed, in which case multiple warnings might be raised on
          // the same method, not adding any value. See Issue 373.
          break;
        }
      }

      // Check well-formedness of pre/postcondition
      boolean abstractMethod =
          methodElement.getModifiers().contains(Modifier.ABSTRACT)
              || methodElement.getModifiers().contains(Modifier.NATIVE);

      List<String> formalParamNames =
          CollectionsPlume.mapList(
              (VariableTree param) -> param.getName().toString(), node.getParameters());
      checkContractsAtMethodDeclaration(node, methodElement, formalParamNames, abstractMethod);

      // Infer postconditions
      if (atypeFactory.getWholeProgramInference() != null) {
        assert ElementUtils.isElementFromSourceCode(methodElement);

        // TODO: Infer conditional postconditions too.
        CFAbstractStore<?, ?> store = atypeFactory.getRegularExitStore(node);
        // The store is null if the method has no normal exit, for example if its body is a
        // throw statement.
        if (store != null) {
          atypeFactory
              .getWholeProgramInference()
              .updateContracts(Analysis.BeforeOrAfter.AFTER, methodElement, store);
        }
      }

      checkForPolymorphicQualifiers(node.getTypeParameters());

      return super.visitMethod(node, p);
    } finally {
      visitorState.setMethodReceiver(preMRT);
      visitorState.setMethodTree(preMT);
    }
  }

  /**
   * Check method purity if needed. Note that overriding rules are checked as part of {@link
   * #checkOverride(MethodTree, AnnotatedTypeMirror.AnnotatedExecutableType,
   * AnnotatedTypeMirror.AnnotatedDeclaredType, AnnotatedTypeMirror.AnnotatedExecutableType,
   * AnnotatedTypeMirror.AnnotatedDeclaredType)}.
   *
   * @param node the method tree to check
   */
  protected void checkPurity(MethodTree node) {
    if (!checker.hasOption("checkPurityAnnotations")) {
      return;
    }

    boolean anyPurityAnnotation = PurityUtils.hasPurityAnnotation(atypeFactory, node);
    boolean suggestPureMethods = checker.hasOption("suggestPureMethods");
    if (!anyPurityAnnotation && !suggestPureMethods) {
      return;
    }

    // check "no" purity
    EnumSet<Pure.Kind> kinds = PurityUtils.getPurityKinds(atypeFactory, node);
    // @Deterministic makes no sense for a void method or constructor
    boolean isDeterministic = kinds.contains(Pure.Kind.DETERMINISTIC);
    if (isDeterministic) {
      if (TreeUtils.isConstructor(node)) {
        checker.reportWarning(node, "purity.deterministic.constructor");
      } else if (TreeUtils.typeOf(node.getReturnType()).getKind() == TypeKind.VOID) {
        checker.reportWarning(node, "purity.deterministic.void.method");
      }
    }

    TreePath body = atypeFactory.getPath(node.getBody());
    PurityResult r;
    if (body == null) {
      r = new PurityResult();
    } else {
      r =
          PurityChecker.checkPurity(
              body,
              atypeFactory,
              checker.hasOption("assumeSideEffectFree") || checker.hasOption("assumePure"),
              checker.hasOption("assumeDeterministic") || checker.hasOption("assumePure"));
    }
    if (!r.isPure(kinds)) {
      reportPurityErrors(r, node, kinds);
    }

    if (suggestPureMethods && !TreeUtils.isSynthetic(node)) {
      // Issue a warning if the method is pure, but not annotated as such.
      EnumSet<Pure.Kind> additionalKinds = r.getKinds().clone();
      additionalKinds.removeAll(kinds);
      if (TreeUtils.isConstructor(node)) {
        additionalKinds.remove(Pure.Kind.DETERMINISTIC);
      }
      if (!additionalKinds.isEmpty()) {
        if (additionalKinds.size() == 2) {
          checker.reportWarning(node, "purity.more.pure", node.getName());
        } else if (additionalKinds.contains(Pure.Kind.SIDE_EFFECT_FREE)) {
          checker.reportWarning(node, "purity.more.sideeffectfree", node.getName());
        } else if (additionalKinds.contains(Pure.Kind.DETERMINISTIC)) {
          checker.reportWarning(node, "purity.more.deterministic", node.getName());
        } else {
          assert false : "BaseTypeVisitor reached undesirable state";
        }
      }
    }
  }

  /**
   * Issue a warning if the result type of the constructor is not top. If it is a supertype of the
   * class, then a conflicting.annos error will also be issued by {@link
   * #isValidUse(AnnotatedTypeMirror.AnnotatedDeclaredType,AnnotatedTypeMirror.AnnotatedDeclaredType,Tree)}.
   *
   * @param constructorType AnnotatedExecutableType for the constructor
   * @param constructorElement element that declares the constructor
   */
  protected void checkConstructorResult(
      AnnotatedExecutableType constructorType, ExecutableElement constructorElement) {
    QualifierHierarchy qualifierHierarchy = atypeFactory.getQualifierHierarchy();
    Set<AnnotationMirror> constructorAnnotations = constructorType.getReturnType().getAnnotations();
    Set<? extends AnnotationMirror> tops = qualifierHierarchy.getTopAnnotations();

    for (AnnotationMirror top : tops) {
      AnnotationMirror constructorAnno =
          qualifierHierarchy.findAnnotationInHierarchy(constructorAnnotations, top);
      if (!qualifierHierarchy.isSubtype(top, constructorAnno)) {
        checker.reportWarning(
            constructorElement, "inconsistent.constructor.type", constructorAnno, top);
      }
    }
  }

  /**
   * Reports errors found during purity checking.
   *
   * @param result whether the method is deterministic and/or side-effect-free
   * @param node the method
   * @param expectedKinds the expected purity for the method
   */
  protected void reportPurityErrors(
      PurityResult result, MethodTree node, EnumSet<Pure.Kind> expectedKinds) {
    assert !result.isPure(expectedKinds);
    EnumSet<Pure.Kind> violations = EnumSet.copyOf(expectedKinds);
    violations.removeAll(result.getKinds());
    if (violations.contains(Pure.Kind.DETERMINISTIC)
        || violations.contains(Pure.Kind.SIDE_EFFECT_FREE)) {
      String msgKeyPrefix;
      if (!violations.contains(Pure.Kind.SIDE_EFFECT_FREE)) {
        msgKeyPrefix = "purity.not.deterministic.";
      } else if (!violations.contains(Pure.Kind.DETERMINISTIC)) {
        msgKeyPrefix = "purity.not.sideeffectfree.";
      } else {
        msgKeyPrefix = "purity.not.deterministic.not.sideeffectfree.";
      }
      for (Pair<Tree, String> r : result.getNotBothReasons()) {
        reportPurityError(msgKeyPrefix, r);
      }
      if (violations.contains(Pure.Kind.SIDE_EFFECT_FREE)) {
        for (Pair<Tree, String> r : result.getNotSEFreeReasons()) {
          reportPurityError("purity.not.sideeffectfree.", r);
        }
      }
      if (violations.contains(Pure.Kind.DETERMINISTIC)) {
        for (Pair<Tree, String> r : result.getNotDetReasons()) {
          reportPurityError("purity.not.deterministic.", r);
        }
      }
    }
  }

  /**
   * Reports a single purity error.
   *
   * @param msgKeyPrefix the prefix of the message key to use when reporting
   * @param r the result to report
   */
  private void reportPurityError(String msgKeyPrefix, Pair<Tree, String> r) {
    String reason = r.second;
    @SuppressWarnings("compilermessages")
    @CompilerMessageKey String msgKey = msgKeyPrefix + reason;
    if (reason.equals("call")) {
      if (r.first.getKind() == Tree.Kind.METHOD_INVOCATION) {
        MethodInvocationTree mitree = (MethodInvocationTree) r.first;
        checker.reportError(r.first, msgKey, mitree.getMethodSelect());
      } else {
        NewClassTree nctree = (NewClassTree) r.first;
        checker.reportError(r.first, msgKey, nctree.getIdentifier());
      }
    } else {
      checker.reportError(r.first, msgKey);
    }
  }

  /**
   * Check the contracts written on a method declaration. Ensures that the postconditions hold on
   * exit, and that the contracts are well-formed.
   *
   * @param methodTree the method declaration
   * @param methodElement the method element
   * @param formalParamNames the formal parameter names
   * @param abstractMethod whether the method is abstract
   */
  private void checkContractsAtMethodDeclaration(
      MethodTree methodTree,
      ExecutableElement methodElement,
      List<String> formalParamNames,
      boolean abstractMethod) {
    Set<Contract> contracts = atypeFactory.getContractsFromMethod().getContracts(methodElement);

    if (contracts.isEmpty()) {
      return;
    }
    StringToJavaExpression stringToJavaExpr =
        stringExpr -> StringToJavaExpression.atMethodBody(stringExpr, methodTree, checker);
    for (Contract contract : contracts) {
      String expressionString = contract.expressionString;
      AnnotationMirror annotation =
          contract.viewpointAdaptDependentTypeAnnotation(
              atypeFactory, stringToJavaExpr, methodTree);

      JavaExpression exprJe;
      try {
        exprJe = StringToJavaExpression.atMethodBody(expressionString, methodTree, checker);
      } catch (JavaExpressionParseException e) {
        DiagMessage diagMessage = e.getDiagMessage();
        if (diagMessage.getMessageKey().equals("flowexpr.parse.error")) {
          String s =
              String.format(
                  "'%s' in the %s %s on the declaration of method '%s': ",
                  expressionString,
                  contract.kind.errorKey,
                  contract.contractAnnotation.getAnnotationType().asElement().getSimpleName(),
                  methodTree.getName().toString());
          checker.reportError(methodTree, "flowexpr.parse.error", s + diagMessage.getArgs()[0]);
        } else {
          checker.report(methodTree, e.getDiagMessage());
        }
        continue;
      }
      if (!CFAbstractStore.canInsertJavaExpression(exprJe)) {
        checker.reportError(methodTree, "flowexpr.parse.error", expressionString);
        continue;
      }
      if (!abstractMethod && contract.kind != Contract.Kind.PRECONDITION) {
        // Check the contract, which is a postcondition.
        // Preconditions are checked at method invocations, not declarations.

        switch (contract.kind) {
          case POSTCONDITION:
            checkPostcondition(methodTree, annotation, exprJe);
            break;
          case CONDITIONALPOSTCONDITION:
            checkConditionalPostcondition(
                methodTree, annotation, exprJe, ((ConditionalPostcondition) contract).resultValue);
            break;
          default:
            throw new BugInCF("Impossible: " + contract.kind);
        }
      }

      if (formalParamNames != null && formalParamNames.contains(expressionString)) {
        String locationOfExpression =
            contract.kind.errorKey
                + " "
                + contract.contractAnnotation.getAnnotationType().asElement().getSimpleName()
                + " on the declaration";
        checker.reportWarning(
            methodTree,
            "expression.parameter.name.shadows.field",
            locationOfExpression,
            methodTree.getName().toString(),
            expressionString,
            expressionString,
            formalParamNames.indexOf(expressionString) + 1);
      }

      checkParametersAreEffectivelyFinal(methodTree, exprJe);
    }
  }

  /**
   * Scans a {@link JavaExpression} and adds all the parameters in the {@code JavaExpression} to the
   * passed set.
   */
  private final JavaExpressionScanner<Set<Element>> findParameters =
      new JavaExpressionScanner<Set<Element>>() {
        @Override
        protected Void visitLocalVariable(LocalVariable localVarExpr, Set<Element> parameters) {
          if (localVarExpr.getElement().getKind() == ElementKind.PARAMETER) {
            parameters.add(localVarExpr.getElement());
          }
          return super.visitLocalVariable(localVarExpr, parameters);
        }
      };
  /**
   * Check that the parameters used in {@code javaExpression} are effectively final for method
   * {@code method}.
   *
   * @param methodDeclTree a method declaration
   * @param javaExpression a Java expression
   */
  private void checkParametersAreEffectivelyFinal(
      MethodTree methodDeclTree, JavaExpression javaExpression) {
    // check that all parameters used in the expression are
    // effectively final, so that they cannot be modified
    Set<Element> parameters = new HashSet<>(1);
    findParameters.scan(javaExpression, parameters);
    for (Element parameter : parameters) {
      if (!ElementUtils.isEffectivelyFinal(parameter)) {
        checker.reportError(
            methodDeclTree,
            "flowexpr.parameter.not.final",
            parameter.getSimpleName(),
            javaExpression);
      }
    }
  }

  /**
   * Check that the expression's type is annotated with {@code annotation} at the regular exit
   * store.
   *
   * @param methodTree declaration of the method
   * @param annotation expression's type must have this annotation
   * @param expression the expression that must have an annotation
   */
  protected void checkPostcondition(
      MethodTree methodTree, AnnotationMirror annotation, JavaExpression expression) {
    CFAbstractStore<?, ?> exitStore = atypeFactory.getRegularExitStore(methodTree);
    if (exitStore == null) {
      // If there is no regular exitStore, then the method cannot reach the regular exit and there
      // is no need to check anything.
    } else {
      CFAbstractValue<?> value = exitStore.getValue(expression);
      AnnotationMirror inferredAnno = null;
      if (value != null) {
        QualifierHierarchy hierarchy = atypeFactory.getQualifierHierarchy();
        Set<AnnotationMirror> annos = value.getAnnotations();
        inferredAnno = hierarchy.findAnnotationInSameHierarchy(annos, annotation);
      }
      if (!checkContract(expression, annotation, inferredAnno, exitStore)) {
        checker.reportError(
            methodTree,
            "contracts.postcondition",
            methodTree.getName(),
            contractExpressionAndType(expression.toString(), inferredAnno),
            contractExpressionAndType(expression.toString(), annotation));
      }
    }
  }

  /**
   * Returns a string representation of an expression and type qualifier.
   *
   * @param expression a Java expression
   * @param qualifier the expression's type, or null if no information is available
   * @return a string representation of the expression and type qualifier
   */
  private String contractExpressionAndType(
      String expression, @Nullable AnnotationMirror qualifier) {
    if (qualifier == null) {
      return "no information about " + expression;
    } else {
      return expression
          + " is "
          + atypeFactory.getAnnotationFormatter().formatAnnotationMirror(qualifier);
    }
  }

  /**
   * Check that the expression's type is annotated with {@code annotation} at every regular exit
   * that returns {@code result}.
   *
   * @param methodTree tree of method with the postcondition
   * @param annotation expression's type must have this annotation
   * @param expression the expression that the postcondition concerns
   * @param result result for which the postcondition is valid
   */
  protected void checkConditionalPostcondition(
      MethodTree methodTree,
      AnnotationMirror annotation,
      JavaExpression expression,
      boolean result) {
    boolean booleanReturnType =
        TypesUtils.isBooleanType(TreeUtils.typeOf(methodTree.getReturnType()));
    if (!booleanReturnType) {
      checker.reportError(methodTree, "contracts.conditional.postcondition.returntype");
      // No reason to go ahead with further checking. The
      // annotation is invalid.
      return;
    }

    for (Pair<ReturnNode, ?> pair : atypeFactory.getReturnStatementStores(methodTree)) {
      ReturnNode returnStmt = pair.first;

      Node retValNode = returnStmt.getResult();
      Boolean retVal =
          retValNode instanceof BooleanLiteralNode
              ? ((BooleanLiteralNode) retValNode).getValue()
              : null;

      TransferResult<?, ?> transferResult = (TransferResult<?, ?>) pair.second;
      if (transferResult == null) {
        // Unreachable return statements have no stores, but there is no need to check them.
        continue;
      }
      CFAbstractStore<?, ?> exitStore =
          (CFAbstractStore<?, ?>)
              (result ? transferResult.getThenStore() : transferResult.getElseStore());
      CFAbstractValue<?> value = exitStore.getValue(expression);

      // don't check if return statement certainly does not match 'result'. at the moment,
      // this means the result is a boolean literal
      if (!(retVal == null || retVal == result)) {
        continue;
      }
      AnnotationMirror inferredAnno = null;
      if (value != null) {
        QualifierHierarchy hierarchy = atypeFactory.getQualifierHierarchy();
        Set<AnnotationMirror> annos = value.getAnnotations();
        inferredAnno = hierarchy.findAnnotationInSameHierarchy(annos, annotation);
      }

      if (!checkContract(expression, annotation, inferredAnno, exitStore)) {
        checker.reportError(
            returnStmt.getTree(),
            "contracts.conditional.postcondition",
            methodTree.getName(),
            result,
            contractExpressionAndType(expression.toString(), inferredAnno),
            contractExpressionAndType(expression.toString(), annotation));
      }
    }
  }

  @Override
  public Void visitTypeParameter(TypeParameterTree node, Void p) {
    validateTypeOf(node);
    // Check the bounds here and not with every TypeParameterTree.
    // For the latter, we only need to check annotations on the type variable itself.
    // Why isn't this covered by the super call?
    for (Tree tpb : node.getBounds()) {
      validateTypeOf(tpb);
    }

    if (node.getBounds().size() > 1) {
      // The upper bound of the type parameter is an intersection
      AnnotatedTypeVariable type =
          (AnnotatedTypeVariable) atypeFactory.getAnnotatedTypeFromTypeTree(node);
      AnnotatedIntersectionType intersection = (AnnotatedIntersectionType) type.getUpperBound();
      checkExplicitAnnotationsOnIntersectionBounds(intersection, node.getBounds());
    }

    return super.visitTypeParameter(node, p);
  }

  /**
   * Issues "explicit.annotation.ignored" warning if any explicit annotation on an intersection
   * bound is not the same as the primary annotation of the given intersection type.
   *
   * @param intersection type to use
   * @param boundTrees trees of {@code intersection} bounds
   */
  protected void checkExplicitAnnotationsOnIntersectionBounds(
      AnnotatedIntersectionType intersection, List<? extends Tree> boundTrees) {
    for (Tree boundTree : boundTrees) {
      if (boundTree.getKind() != Tree.Kind.ANNOTATED_TYPE) {
        continue;
      }
      List<? extends AnnotationMirror> explictAnnos =
          TreeUtils.annotationsFromTree((AnnotatedTypeTree) boundTree);
      for (AnnotationMirror explictAnno : explictAnnos) {
        if (atypeFactory.isSupportedQualifier(explictAnno)) {
          AnnotationMirror anno = intersection.getAnnotationInHierarchy(explictAnno);
          if (!AnnotationUtils.areSame(anno, explictAnno)) {
            checker.reportWarning(
                boundTree, "explicit.annotation.ignored", explictAnno, anno, explictAnno, anno);
          }
        }
      }
    }
  }

  // **********************************************************************
  // Assignment checkers and pseudo-assignments
  // **********************************************************************

  @Override
  public Void visitVariable(VariableTree node, Void p) {
    warnAboutTypeAnnotationsTooEarly(node, node.getModifiers());

    visitAnnotatedType(node.getModifiers().getAnnotations(), node.getType());

    Pair<Tree, AnnotatedTypeMirror> preAssignmentContext = visitorState.getAssignmentContext();
    AnnotatedTypeMirror variableType;
    if (getCurrentPath().getParentPath() != null
        && getCurrentPath().getParentPath().getLeaf().getKind() == Tree.Kind.LAMBDA_EXPRESSION) {
      // Calling getAnnotatedTypeLhs on a lambda parameter node is possibly expensive
      // because caching is turned off.  This should be fixed by #979.
      // See https://github.com/typetools/checker-framework/issues/2853 for an example.
      variableType = atypeFactory.getAnnotatedType(node);
    } else {
      variableType = atypeFactory.getAnnotatedTypeLhs(node);
    }
    visitorState.setAssignmentContext(Pair.of(node, variableType));

    try {
      atypeFactory.getDependentTypesHelper().checkTypeForErrorExpressions(variableType, node);
      // If there's no assignment in this variable declaration, skip it.
      if (node.getInitializer() != null) {
        commonAssignmentCheck(node, node.getInitializer(), "assignment");
      } else {
        // commonAssignmentCheck validates the type of node,
        // so only validate if commonAssignmentCheck wasn't called
        validateTypeOf(node);
      }
      return super.visitVariable(node, p);
    } finally {
      visitorState.setAssignmentContext(preAssignmentContext);
    }
  }

  /**
   * Warn if a type annotation is written before a modifier such as "public" or before a declaration
   * annotation.
   *
   * @param node a VariableTree or a MethodTree
   * @param modifiersTree the modifiers sub-tree of node
   */
  private void warnAboutTypeAnnotationsTooEarly(Tree node, ModifiersTree modifiersTree) {

    // Don't issue warnings about compiler-inserted modifiers.
    // This simple code completely igonores enum constants and try-with-resources declarations.
    // It could be made to catch some user errors in those locations, but it doesn't seem worth
    // the effort to do so.
    if (node.getKind() == Tree.Kind.VARIABLE) {
      ElementKind varKind = TreeUtils.elementFromDeclaration((VariableTree) node).getKind();
      switch (varKind) {
        case ENUM_CONSTANT:
          // Enum constants are "public static final" by default, so the annotation always
          // appears to be before "public".
          return;
        case RESOURCE_VARIABLE:
          // Try-with-resources variables are "final" by default, so the annotation always
          // appears to be before "final".
          return;
        default:
          // Nothing to do
      }
    }

    Set<Modifier> modifierSet = modifiersTree.getFlags();
    List<? extends AnnotationTree> annotations = modifiersTree.getAnnotations();

    if (annotations.isEmpty()) {
      return;
    }

    // Warn about type annotations written before modifiers such as "public".  javac retains no
    // information about modifier locations.  So, this is a very partial check:  Issue a warning if
    // a type annotation is at the very beginning of the VariableTree, and a modifier follows it.

    // Check if a type annotation precedes a declaration annotation.
    int lastDeclAnnoIndex = -1;
    for (int i = annotations.size() - 1; i > 0; i--) { // no need to check index 0
      if (!isTypeAnnotation(annotations.get(i))) {
        lastDeclAnnoIndex = i;
        break;
      }
    }
    if (lastDeclAnnoIndex != -1) {
      List<AnnotationTree> badTypeAnnos = new ArrayList<>();
      for (int i = 0; i < lastDeclAnnoIndex; i++) {
        AnnotationTree anno = annotations.get(i);
        if (isTypeAnnotation(anno)) {
          badTypeAnnos.add(anno);
        }
      }
      if (!badTypeAnnos.isEmpty()) {
        checker.reportWarning(
            node, "type.anno.before.decl.anno", badTypeAnnos, annotations.get(lastDeclAnnoIndex));
      }
    }

    // Determine the length of the text that ought to precede the first type annotation.
    // If the type annotation appears before that text could appear, then warn that a
    // modifier appears after the type annotation.
    // TODO: in the future, account for the lengths of declaration annotations.  Length of toString
    // of the annotation isn't useful, as it might be different length than original input.  Can use
    // JCTree.getEndPosition(EndPosTable) and com.sun.tools.javac.tree.EndPosTable, but it requires
    // -Xjcov.
    AnnotationTree firstAnno = annotations.get(0);
    if (!modifierSet.isEmpty() && isTypeAnnotation(firstAnno)) {
      int precedingTextLength = 0;
      for (Modifier m : modifierSet) {
        precedingTextLength += m.toString().length() + 1; // +1 for the space
      }
      int annoStartPos = ((JCTree) firstAnno).getStartPosition();
      int varStartPos = ((JCTree) node).getStartPosition();
      if (annoStartPos < varStartPos + precedingTextLength) {
        checker.reportWarning(node, "type.anno.before.modifier", firstAnno, modifierSet);
      }
    }
  }

  /**
   * Return true if the given annotation is a type annotation: that is, its definition is
   * meta-annotated with {@code @Target({TYPE_USE,....})}.
   */
  private boolean isTypeAnnotation(AnnotationTree anno) {
    Tree annoType = anno.getAnnotationType();
    ClassSymbol annoSymbol;
    switch (annoType.getKind()) {
      case IDENTIFIER:
        annoSymbol = (ClassSymbol) ((JCIdent) annoType).sym;
        break;
      case MEMBER_SELECT:
        annoSymbol = (ClassSymbol) ((JCFieldAccess) annoType).sym;
        break;
      default:
        throw new Error("Unhandled kind: " + annoType.getKind() + " for " + anno);
    }
    for (AnnotationMirror metaAnno : annoSymbol.getAnnotationMirrors()) {
      if (AnnotationUtils.areSameByName(metaAnno, TARGET)) {
        AnnotationValue av = metaAnno.getElementValues().get(targetValueElement);
        return AnnotationUtils.annotationValueContainsToString(av, "TYPE_USE");
      }
    }

    return false;
  }

  /**
   * Performs two checks: subtyping and assignability checks, using {@link
   * #commonAssignmentCheck(Tree, ExpressionTree, String, Object[])}.
   *
   * <p>If the subtype check fails, it issues a "assignment" error.
   */
  @Override
  public Void visitAssignment(AssignmentTree node, Void p) {
    Pair<Tree, AnnotatedTypeMirror> preAssignmentContext = visitorState.getAssignmentContext();
    visitorState.setAssignmentContext(
        Pair.of((Tree) node.getVariable(), atypeFactory.getAnnotatedType(node.getVariable())));
    try {
      commonAssignmentCheck(node.getVariable(), node.getExpression(), "assignment");
      return super.visitAssignment(node, p);
    } finally {
      visitorState.setAssignmentContext(preAssignmentContext);
    }
  }

  /**
   * Performs a subtype check, to test whether the node expression iterable type is a subtype of the
   * variable type in the enhanced for loop.
   *
   * <p>If the subtype check fails, it issues a "enhancedfor" error.
   */
  @Override
  public Void visitEnhancedForLoop(EnhancedForLoopTree node, Void p) {
    AnnotatedTypeMirror var = atypeFactory.getAnnotatedTypeLhs(node.getVariable());
    AnnotatedTypeMirror iteratedType = atypeFactory.getIterableElementType(node.getExpression());
    boolean valid = validateTypeOf(node.getVariable());
    if (valid) {
      commonAssignmentCheck(var, iteratedType, node.getExpression(), "enhancedfor");
    }
    return super.visitEnhancedForLoop(node, p);
  }

  /**
   * Performs a method invocation check.
   *
   * <p>An invocation of a method, m, on the receiver, r is valid only if:
   *
   * <ul>
   *   <li>passed arguments are subtypes of corresponding m parameters
   *   <li>r is a subtype of m receiver type
   *   <li>if m is generic, passed type arguments are subtypes of m type variables
   * </ul>
   */
  @Override
  public Void visitMethodInvocation(MethodInvocationTree node, Void p) {

    // Skip calls to the Enum constructor (they're generated by javac and
    // hard to check), also see CFGBuilder.visitMethodInvocation.
    if (TreeUtils.elementFromUse(node) == null || TreeUtils.isEnumSuper(node)) {
      return super.visitMethodInvocation(node, p);
    }

    if (shouldSkipUses(node)) {
      return super.visitMethodInvocation(node, p);
    }

    ParameterizedExecutableType mType = atypeFactory.methodFromUse(node);
    AnnotatedExecutableType invokedMethod = mType.executableType;
    List<AnnotatedTypeMirror> typeargs = mType.typeArgs;

    if (!atypeFactory.ignoreUninferredTypeArguments) {
      for (AnnotatedTypeMirror typearg : typeargs) {
        if (typearg.getKind() == TypeKind.WILDCARD
            && ((AnnotatedWildcardType) typearg).isUninferredTypeArgument()) {
          checker.reportError(
              node, "type.arguments.not.inferred", invokedMethod.getElement().getSimpleName());
          break; // only issue error once per method
        }
      }
    }

    List<AnnotatedTypeParameterBounds> paramBounds =
        CollectionsPlume.mapList(
            AnnotatedTypeVariable::getBounds, invokedMethod.getTypeVariables());

    ExecutableElement method = invokedMethod.getElement();
    CharSequence methodName = ElementUtils.getSimpleNameOrDescription(method);
    try {
      checkTypeArguments(
          node,
          paramBounds,
          typeargs,
          node.getTypeArguments(),
          methodName,
          invokedMethod.getTypeVariables());
      List<AnnotatedTypeMirror> params =
          AnnotatedTypes.expandVarArgs(atypeFactory, invokedMethod, node.getArguments());
      checkArguments(params, node.getArguments(), methodName, method.getParameters());
      checkVarargs(invokedMethod, node);

      if (ElementUtils.isMethod(
          invokedMethod.getElement(), vectorCopyInto, atypeFactory.getProcessingEnv())) {
        typeCheckVectorCopyIntoArgument(node, params);
      }

      ExecutableElement invokedMethodElement = invokedMethod.getElement();
      if (!ElementUtils.isStatic(invokedMethodElement) && !TreeUtils.isSuperConstructorCall(node)) {
        checkMethodInvocability(invokedMethod, node);
      }

      // check precondition annotations
      checkPreconditions(
          node, atypeFactory.getContractsFromMethod().getPreconditions(invokedMethodElement));

      if (TreeUtils.isSuperConstructorCall(node)) {
        checkSuperConstructorCall(node);
      } else if (TreeUtils.isThisConstructorCall(node)) {
        checkThisConstructorCall(node);
      }
    } catch (RuntimeException t) {
      // Sometimes the type arguments are inferred incorrect which causes crashes. Once #979
      // is fixed this should be removed and crashes should be reported normally.
      if (node.getTypeArguments().size() == typeargs.size()) {
        // They type arguments were explicitly written.
        throw t;
      }
      if (!atypeFactory.ignoreUninferredTypeArguments) {
        checker.reportError(
            node, "type.arguments.not.inferred", invokedMethod.getElement().getSimpleName());
      } // else ignore the crash.
    }

    // Do not call super, as that would observe the arguments without
    // a set assignment context.
    scan(node.getMethodSelect(), p);
    return null; // super.visitMethodInvocation(node, p);
  }

  /**
   * Checks that the following rule is satisfied: The type on a constructor declaration must be a
   * supertype of the return type of "this()" invocation within that constructor.
   *
   * <p>Subclasses can override this method to change the behavior for just "this" constructor
   * class. Or override {@link #checkThisOrSuperConstructorCall(MethodInvocationTree, String)} to
   * change the behavior for "this" and "super" constructor calls.
   *
   * @param thisCall the AST node for the constructor call
   */
  protected void checkThisConstructorCall(MethodInvocationTree thisCall) {
    checkThisOrSuperConstructorCall(thisCall, "this.invocation");
  }

  /**
   * Checks that the following rule is satisfied: The type on a constructor declaration must be a
   * supertype of the return type of "super()" invocation within that constructor.
   *
   * <p>Subclasses can override this method to change the behavior for just "super" constructor
   * class. Or override {@link #checkThisOrSuperConstructorCall(MethodInvocationTree, String)} to
   * change the behavior for "this" and "super" constructor calls.
   *
   * @param superCall the AST node for the super constructor call
   */
  protected void checkSuperConstructorCall(MethodInvocationTree superCall) {
    checkThisOrSuperConstructorCall(superCall, "super.invocation");
  }

  /**
   * Checks that the following rule is satisfied: The type on a constructor declaration must be a
   * supertype of the return type of "this()" or "super()" invocation within that constructor.
   *
   * @param call the AST node for the constructor call
   * @param errorKey the error message key to use if the check fails
   */
  protected void checkThisOrSuperConstructorCall(
      MethodInvocationTree call, @CompilerMessageKey String errorKey) {
    TreePath path = atypeFactory.getPath(call);
    MethodTree enclosingMethod = TreePathUtil.enclosingMethod(path);
    AnnotatedTypeMirror superType = atypeFactory.getAnnotatedType(call);
    AnnotatedExecutableType constructorType = atypeFactory.getAnnotatedType(enclosingMethod);
    Set<? extends AnnotationMirror> topAnnotations =
        atypeFactory.getQualifierHierarchy().getTopAnnotations();
    for (AnnotationMirror topAnno : topAnnotations) {
      AnnotationMirror superTypeMirror = superType.getAnnotationInHierarchy(topAnno);
      AnnotationMirror constructorTypeMirror =
          constructorType.getReturnType().getAnnotationInHierarchy(topAnno);

      if (!atypeFactory.getQualifierHierarchy().isSubtype(superTypeMirror, constructorTypeMirror)) {
        checker.reportError(call, errorKey, constructorTypeMirror, call, superTypeMirror);
      }
    }
  }

  /**
   * A helper method to check that the array type of actual varargs is a subtype of the
   * corresponding required varargs, and issues "argument" error if it's not a subtype of the
   * required one.
   *
   * <p>Note it's required that type checking for each element in varargs is executed by the caller
   * before or after calling this method.
   *
   * @see #checkArguments
   * @param invokedMethod the method type to be invoked
   * @param tree method or constructor invocation tree
   */
  protected void checkVarargs(AnnotatedExecutableType invokedMethod, Tree tree) {
    if (!invokedMethod.isVarArgs()) {
      return;
    }

    List<AnnotatedTypeMirror> formals = invokedMethod.getParameterTypes();
    int numFormals = formals.size();
    int lastArgIndex = numFormals - 1;
    AnnotatedArrayType lastParamAnnotatedType = (AnnotatedArrayType) formals.get(lastArgIndex);

    // We will skip type checking so that we avoid duplicating error message if the last argument is
    // same depth with the depth of formal varargs because type checking is already done in
    // checkArguments.
    List<? extends ExpressionTree> args;
    switch (tree.getKind()) {
      case METHOD_INVOCATION:
        args = ((MethodInvocationTree) tree).getArguments();
        break;
      case NEW_CLASS:
        args = ((NewClassTree) tree).getArguments();
        break;
      default:
        throw new BugInCF("Unexpected kind of tree: " + tree);
    }
    if (numFormals == args.size()) {
      AnnotatedTypeMirror lastArgType = atypeFactory.getAnnotatedType(args.get(args.size() - 1));
      if (lastArgType.getKind() == TypeKind.ARRAY
          && AnnotatedTypes.getArrayDepth(lastParamAnnotatedType)
              == AnnotatedTypes.getArrayDepth((AnnotatedArrayType) lastArgType)) {
        return;
      }
    }

    AnnotatedTypeMirror wrappedVarargsType = atypeFactory.getAnnotatedTypeVarargsArray(tree);

    // When dataflow analysis is not enabled, it will be null and we can suppose there is no
    // annotation to be checked for generated varargs array.
    if (wrappedVarargsType == null) {
      return;
    }

    // The component type of wrappedVarargsType might not be a subtype of the component type of
    // lastParamAnnotatedType due to the difference of type inference between for an expression
    // and an invoked method element. We can consider that the component type of actual is same
    // with formal one because type checking for elements will be done in checkArguments. This
    // is also needed to avoid duplicating error message caused by elements in varargs.
    if (wrappedVarargsType.getKind() == TypeKind.ARRAY) {
      ((AnnotatedArrayType) wrappedVarargsType)
          .setComponentType(lastParamAnnotatedType.getComponentType());
    }

    commonAssignmentCheck(lastParamAnnotatedType, wrappedVarargsType, tree, "varargs");
  }

  /**
   * Checks that all the given {@code preconditions} hold true immediately prior to the method
   * invocation or variable access at {@code tree}.
   *
   * @param tree the method invocation; immediately prior to it, the preconditions must hold true
   * @param preconditions the preconditions to be checked
   */
  protected void checkPreconditions(MethodInvocationTree tree, Set<Precondition> preconditions) {
    // This check is needed for the GUI effects and Units Checkers tests to pass.
    // TODO: Remove this check and investigate the root cause.
    if (preconditions.isEmpty()) {
      return;
    }

    StringToJavaExpression stringToJavaExpr =
        stringExpr -> StringToJavaExpression.atMethodInvocation(stringExpr, tree, checker);
    for (Contract c : preconditions) {
      Precondition p = (Precondition) c;
      String expressionString = p.expressionString;
      AnnotationMirror anno =
          c.viewpointAdaptDependentTypeAnnotation(atypeFactory, stringToJavaExpr, tree);
      JavaExpression exprJe;
      try {
        exprJe = StringToJavaExpression.atMethodInvocation(expressionString, tree, checker);
      } catch (JavaExpressionParseException e) {
        // report errors here
        checker.report(tree, e.getDiagMessage());
        return;
      }

      CFAbstractStore<?, ?> store = atypeFactory.getStoreBefore(tree);
      CFAbstractValue<?> value = null;
      if (CFAbstractStore.canInsertJavaExpression(exprJe)) {
        value = store.getValue(exprJe);
      }
      AnnotationMirror inferredAnno = null;
      if (value != null) {
        QualifierHierarchy hierarchy = atypeFactory.getQualifierHierarchy();
        Set<AnnotationMirror> annos = value.getAnnotations();
        inferredAnno = hierarchy.findAnnotationInSameHierarchy(annos, anno);
      }
      if (!checkContract(exprJe, anno, inferredAnno, store)) {
        if (exprJe != null) {
          expressionString = exprJe.toString();
        }
        checker.reportError(
            tree,
            "contracts.precondition",
            tree.getMethodSelect().toString(),
            contractExpressionAndType(expressionString, inferredAnno),
            contractExpressionAndType(expressionString, anno));
      }
    }
  }

  /**
   * Returns true if and only if {@code inferredAnnotation} is valid for a given expression to match
   * the {@code necessaryAnnotation}.
   *
   * <p>By default, {@code inferredAnnotation} must be a subtype of {@code necessaryAnnotation}, but
   * subclasses might override this behavior.
   */
  protected boolean checkContract(
      JavaExpression expr,
      AnnotationMirror necessaryAnnotation,
      AnnotationMirror inferredAnnotation,
      CFAbstractStore<?, ?> store) {
    return inferredAnnotation != null
        && atypeFactory.getQualifierHierarchy().isSubtype(inferredAnnotation, necessaryAnnotation);
  }

  /**
   * Type checks the method arguments of {@code Vector.copyInto()}.
   *
   * <p>The Checker Framework special-cases the method invocation, as its type safety cannot be
   * expressed by Java's type system.
   *
   * <p>For a Vector {@code v} of type {@code Vector<E>}, the method invocation {@code
   * v.copyInto(arr)} is type-safe iff {@code arr} is an array of type {@code T[]}, where {@code T}
   * is a subtype of {@code E}.
   *
   * <p>In other words, this method checks that the type argument of the receiver method is a
   * subtype of the component type of the passed array argument.
   *
   * @param node a method invocation of {@code Vector.copyInto()}
   * @param params the types of the parameters of {@code Vectory.copyInto()}
   */
  protected void typeCheckVectorCopyIntoArgument(
      MethodInvocationTree node, List<? extends AnnotatedTypeMirror> params) {
    assert params.size() == 1
        : "invalid no. of parameters " + params + " found for method invocation " + node;
    assert node.getArguments().size() == 1
        : "invalid no. of arguments in method invocation " + node;

    AnnotatedTypeMirror passed = atypeFactory.getAnnotatedType(node.getArguments().get(0));
    AnnotatedArrayType passedAsArray = (AnnotatedArrayType) passed;

    AnnotatedTypeMirror receiver = atypeFactory.getReceiverType(node);
    AnnotatedDeclaredType receiverAsVector =
        AnnotatedTypes.asSuper(atypeFactory, receiver, vectorType);
    if (receiverAsVector.getTypeArguments().isEmpty()) {
      return;
    }

    AnnotatedTypeMirror argComponent = passedAsArray.getComponentType();
    AnnotatedTypeMirror vectorTypeArg = receiverAsVector.getTypeArguments().get(0);
    Tree errorLocation = node.getArguments().get(0);
    if (TypesUtils.isErasedSubtype(
        vectorTypeArg.getUnderlyingType(), argComponent.getUnderlyingType(), types)) {
      commonAssignmentCheck(argComponent, vectorTypeArg, errorLocation, "vector.copyinto");
    } else {
      checker.reportError(errorLocation, "vector.copyinto", vectorTypeArg, argComponent);
    }
  }

  /**
   * Performs a new class invocation check.
   *
   * <p>An invocation of a constructor, c, is valid only if:
   *
   * <ul>
   *   <li>passed arguments are subtypes of corresponding c parameters
   *   <li>if c is generic, passed type arguments are subtypes of c type variables
   * </ul>
   */
  @Override
  public Void visitNewClass(NewClassTree node, Void p) {
    if (checker.shouldSkipUses(TreeUtils.constructor(node))) {
      return super.visitNewClass(node, p);
    }

    ParameterizedExecutableType fromUse = atypeFactory.constructorFromUse(node);
    AnnotatedExecutableType constructorType = fromUse.executableType;
    List<AnnotatedTypeMirror> typeargs = fromUse.typeArgs;

    List<? extends ExpressionTree> passedArguments = node.getArguments();
    List<AnnotatedTypeMirror> params =
        AnnotatedTypes.expandVarArgs(atypeFactory, constructorType, passedArguments);

    ExecutableElement constructor = constructorType.getElement();
    CharSequence constructorName = ElementUtils.getSimpleNameOrDescription(constructor);

    checkArguments(params, passedArguments, constructorName, constructor.getParameters());
    checkVarargs(constructorType, node);

    List<AnnotatedTypeParameterBounds> paramBounds =
        CollectionsPlume.mapList(
            AnnotatedTypeVariable::getBounds, constructorType.getTypeVariables());

    checkTypeArguments(
        node,
        paramBounds,
        typeargs,
        node.getTypeArguments(),
        constructorName,
        constructor.getTypeParameters());

    boolean valid = validateTypeOf(node);

    if (valid) {
      AnnotatedDeclaredType dt = atypeFactory.getAnnotatedType(node);
      atypeFactory.getDependentTypesHelper().checkTypeForErrorExpressions(dt, node);
      checkConstructorInvocation(dt, constructorType, node);
    }
    // Do not call super, as that would observe the arguments without
    // a set assignment context.
    scan(node.getEnclosingExpression(), p);
    scan(node.getIdentifier(), p);
    scan(node.getClassBody(), p);

    return null;
  }

  @Override
  public Void visitLambdaExpression(LambdaExpressionTree node, Void p) {

    AnnotatedExecutableType functionType = atypeFactory.getFunctionTypeFromTree(node);

    if (node.getBody().getKind() != Tree.Kind.BLOCK) {
      // Check return type for single statement returns here.
      AnnotatedTypeMirror ret = functionType.getReturnType();
      if (ret.getKind() != TypeKind.VOID) {
        visitorState.setAssignmentContext(Pair.of((Tree) node, ret));
        commonAssignmentCheck(ret, (ExpressionTree) node.getBody(), "return");
      }
    }

    // Check parameters
    for (int i = 0; i < functionType.getParameterTypes().size(); ++i) {
      AnnotatedTypeMirror lambdaParameter =
          atypeFactory.getAnnotatedType(node.getParameters().get(i));
      commonAssignmentCheck(
          lambdaParameter,
          functionType.getParameterTypes().get(i),
          node.getParameters().get(i),
          "lambda.param",
          i);
    }

    // TODO: Postconditions?
    // https://github.com/typetools/checker-framework/issues/801

    return super.visitLambdaExpression(node, p);
  }

  @Override
  public Void visitMemberReference(MemberReferenceTree node, Void p) {
    this.checkMethodReferenceAsOverride(node, p);
    return super.visitMemberReference(node, p);
  }

  /**
   * Checks that the type of the return expression is a subtype of the enclosing method required
   * return type. If not, it issues a "return" error.
   */
  @Override
  public Void visitReturn(ReturnTree node, Void p) {
    // Don't try to check return expressions for void methods.
    if (node.getExpression() == null) {
      return super.visitReturn(node, p);
    }

    Pair<Tree, AnnotatedTypeMirror> preAssignmentContext = visitorState.getAssignmentContext();
    try {

      Tree enclosing =
          TreePathUtil.enclosingOfKind(
              getCurrentPath(),
              new HashSet<>(Arrays.asList(Tree.Kind.METHOD, Tree.Kind.LAMBDA_EXPRESSION)));

      AnnotatedTypeMirror ret = null;
      if (enclosing.getKind() == Tree.Kind.METHOD) {

        MethodTree enclosingMethod = TreePathUtil.enclosingMethod(getCurrentPath());
        boolean valid = validateTypeOf(enclosing);
        if (valid) {
          ret = atypeFactory.getMethodReturnType(enclosingMethod, node);
        }
      } else {
        AnnotatedExecutableType result =
            atypeFactory.getFunctionTypeFromTree((LambdaExpressionTree) enclosing);
        ret = result.getReturnType();
      }

      if (ret != null) {
        visitorState.setAssignmentContext(Pair.of((Tree) node, ret));

        commonAssignmentCheck(ret, node.getExpression(), "return");
      }
      return super.visitReturn(node, p);
    } finally {
      visitorState.setAssignmentContext(preAssignmentContext);
    }
  }

  /**
   * Ensure that the annotation arguments comply to their declarations. This needs some special
   * casing, as annotation arguments form special trees.
   */
  @Override
  public Void visitAnnotation(AnnotationTree node, Void p) {
    List<? extends ExpressionTree> args = node.getArguments();
    if (args.isEmpty()) {
      // Nothing to do if there are no annotation arguments.
      return null;
    }

    TypeElement anno = (TypeElement) TreeInfo.symbol((JCTree) node.getAnnotationType());

    Name annoName = anno.getQualifiedName();
    if (annoName.contentEquals(DefaultQualifier.class.getName())
        || annoName.contentEquals(SuppressWarnings.class.getName())) {
      // Skip these two annotations, as we don't care about the arguments to them.
      return null;
    }

    List<ExecutableElement> methods = ElementFilter.methodsIn(anno.getEnclosedElements());
    // Mapping from argument simple name to its annotated type.
    Map<String, AnnotatedTypeMirror> annoTypes = new HashMap<>(methods.size());
    for (ExecutableElement meth : methods) {
      AnnotatedExecutableType exeatm = atypeFactory.getAnnotatedType(meth);
      AnnotatedTypeMirror retty = exeatm.getReturnType();
      annoTypes.put(meth.getSimpleName().toString(), retty);
    }

    for (ExpressionTree arg : args) {
      if (!(arg instanceof AssignmentTree)) {
        // TODO: when can this happen?
        continue;
      }

      AssignmentTree at = (AssignmentTree) arg;
      // Ensure that we never ask for the annotated type of an annotation, because
      // we don't have a type for annotations.
      if (at.getExpression().getKind() == Tree.Kind.ANNOTATION) {
        visitAnnotation((AnnotationTree) at.getExpression(), p);
        continue;
      }
      if (at.getExpression().getKind() == Tree.Kind.NEW_ARRAY) {
        NewArrayTree nat = (NewArrayTree) at.getExpression();
        boolean isAnno = false;
        for (ExpressionTree init : nat.getInitializers()) {
          if (init.getKind() == Tree.Kind.ANNOTATION) {
            visitAnnotation((AnnotationTree) init, p);
            isAnno = true;
          }
        }
        if (isAnno) {
          continue;
        }
      }

      AnnotatedTypeMirror expected = annoTypes.get(at.getVariable().toString());
      Pair<Tree, AnnotatedTypeMirror> preAssignmentContext = visitorState.getAssignmentContext();

      {
        // Determine and set the new assignment context.
        ExpressionTree var = at.getVariable();
        assert var instanceof IdentifierTree : "Expected IdentifierTree as context. Found: " + var;
        AnnotatedTypeMirror meth = atypeFactory.getAnnotatedType(var);
        assert meth instanceof AnnotatedExecutableType
            : "Expected AnnotatedExecutableType as context. Found: " + meth;
        AnnotatedTypeMirror newctx = ((AnnotatedExecutableType) meth).getReturnType();
        visitorState.setAssignmentContext(Pair.of((Tree) null, newctx));
      }

      try {
        AnnotatedTypeMirror actual = atypeFactory.getAnnotatedType(at.getExpression());
        if (expected.getKind() != TypeKind.ARRAY) {
          // Expected is not an array -> direct comparison.
          commonAssignmentCheck(expected, actual, at.getExpression(), "annotation");
        } else {
          if (actual.getKind() == TypeKind.ARRAY) {
            // Both actual and expected are arrays.
            commonAssignmentCheck(expected, actual, at.getExpression(), "annotation");
          } else {
            // The declaration is an array type, but just a single
            // element is given.
            commonAssignmentCheck(
                ((AnnotatedArrayType) expected).getComponentType(),
                actual,
                at.getExpression(),
                "annotation");
          }
        }
      } finally {
        visitorState.setAssignmentContext(preAssignmentContext);
      }
    }
    return null;
  }

  /**
   * If the computation of the type of the ConditionalExpressionTree in
   * org.checkerframework.framework.type.TypeFromTree.TypeFromExpression.visitConditionalExpression(ConditionalExpressionTree,
   * AnnotatedTypeFactory) is correct, the following checks are redundant. However, let's add
   * another failsafe guard and do the checks.
   */
  @Override
  public Void visitConditionalExpression(ConditionalExpressionTree node, Void p) {
    AnnotatedTypeMirror cond = atypeFactory.getAnnotatedType(node);
    this.commonAssignmentCheck(cond, node.getTrueExpression(), "conditional");
    this.commonAssignmentCheck(cond, node.getFalseExpression(), "conditional");
    return super.visitConditionalExpression(node, p);
  }

  // **********************************************************************
  // Check for illegal re-assignment
  // **********************************************************************

  /** Performs assignability check. */
  @Override
  public Void visitUnary(UnaryTree node, Void p) {
    Tree.Kind nodeKind = node.getKind();
    if ((nodeKind == Tree.Kind.PREFIX_DECREMENT)
        || (nodeKind == Tree.Kind.PREFIX_INCREMENT)
        || (nodeKind == Tree.Kind.POSTFIX_DECREMENT)
        || (nodeKind == Tree.Kind.POSTFIX_INCREMENT)) {
      AnnotatedTypeMirror varType = atypeFactory.getAnnotatedTypeLhs(node.getExpression());
      AnnotatedTypeMirror valueType = atypeFactory.getAnnotatedTypeRhsUnaryAssign(node);
      String errorKey =
          (nodeKind == Tree.Kind.PREFIX_INCREMENT || nodeKind == Tree.Kind.POSTFIX_INCREMENT)
              ? "unary.increment"
              : "unary.decrement";
      commonAssignmentCheck(varType, valueType, node, errorKey);
    }
    return super.visitUnary(node, p);
  }

  /** Performs assignability check. */
  @Override
  public Void visitCompoundAssignment(CompoundAssignmentTree node, Void p) {
    // If node is the tree representing the compounds assignment s += expr,
    // Then this method should check whether s + expr can be assigned to s,
    // but the "s + expr" tree does not exist.  So instead, check that
    // s += expr can be assigned to s.
    commonAssignmentCheck(node.getVariable(), node, "compound.assignment");
    return super.visitCompoundAssignment(node, p);
  }

  // **********************************************************************
  // Check for invalid types inserted by the user
  // **********************************************************************

  @Override
  public Void visitNewArray(NewArrayTree node, Void p) {
    boolean valid = validateTypeOf(node);

    if (valid && node.getType() != null) {
      AnnotatedArrayType arrayType = atypeFactory.getAnnotatedType(node);
      atypeFactory.getDependentTypesHelper().checkTypeForErrorExpressions(arrayType, node);
      if (node.getInitializers() != null) {
        checkArrayInitialization(arrayType.getComponentType(), node.getInitializers());
      }
    }

    return super.visitNewArray(node, p);
  }

  /**
   * If the lint option "cast:redundant" is set, this methods issues a warning if the cast is
   * redundant.
   */
  protected void checkTypecastRedundancy(TypeCastTree typeCastTree) {
    if (!checker.getLintOption("cast:redundant", false)) {
      return;
    }

    AnnotatedTypeMirror castType = atypeFactory.getAnnotatedType(typeCastTree);
    AnnotatedTypeMirror exprType = atypeFactory.getAnnotatedType(typeCastTree.getExpression());

    if (castType.equals(exprType)) {
      checker.reportWarning(typeCastTree, "cast.redundant", castType);
    }
  }

  /**
   * Issues a warning if the given explicitly-written typecast is unsafe. Does nothing if the lint
   * option "cast:unsafe" is not set. Only primary qualifiers are checked unless the command line
   * option "checkCastElementType" is supplied.
   *
   * @param typeCastTree an explicitly-written typecast
   */
  protected void checkTypecastSafety(TypeCastTree typeCastTree) {
    if (!checker.getLintOption("cast:unsafe", true)) {
      return;
    }
    AnnotatedTypeMirror castType = atypeFactory.getAnnotatedType(typeCastTree);
    AnnotatedTypeMirror exprType = atypeFactory.getAnnotatedType(typeCastTree.getExpression());
    boolean calledOnce = false;
    for (AnnotationMirror top : atypeFactory.getQualifierParameterHierarchies(castType)) {
      if (!isInvariantTypeCastSafe(castType, exprType, top)) {
        checker.reportError(
            typeCastTree,
            "invariant.cast.unsafe",
            exprType.toString(true),
            castType.toString(true));
      }
      calledOnce = true; // don't issue cast unsafe warning.
    }
    // We cannot do a simple test of casting, as isSubtypeOf requires
    // the input types to be subtypes according to Java.
    if (!calledOnce && !isTypeCastSafe(castType, exprType)) {
      checker.reportWarning(
          typeCastTree, "cast.unsafe", exprType.toString(true), castType.toString(true));
    }
  }

  /**
   * Returns true if the cast is safe.
   *
   * <p>Only primary qualifiers are checked unless the command line option "checkCastElementType" is
   * supplied.
   *
   * @param castType annotated type of the cast
   * @param exprType annotated type of the casted expression
   * @return true if the type cast is safe, false otherwise
   */
  protected boolean isTypeCastSafe(AnnotatedTypeMirror castType, AnnotatedTypeMirror exprType) {

    final TypeKind castTypeKind = castType.getKind();
    if (castTypeKind == TypeKind.DECLARED) {
      // Don't issue an error if the annotations are equivalent to the qualifier upper bound of the
      // type.
      AnnotatedDeclaredType castDeclared = (AnnotatedDeclaredType) castType;
      Set<AnnotationMirror> bounds =
          atypeFactory.getTypeDeclarationBounds(castDeclared.getUnderlyingType());

      if (AnnotationUtils.areSame(castDeclared.getAnnotations(), bounds)) {
        return true;
      }
    }

    QualifierHierarchy qualifierHierarchy = atypeFactory.getQualifierHierarchy();

    Set<AnnotationMirror> castAnnos;
    if (!checker.hasOption("checkCastElementType")) {
      // checkCastElementType option wasn't specified, so only check effective annotations.
      castAnnos = castType.getEffectiveAnnotations();
    } else {
      AnnotatedTypeMirror newCastType;
      if (castTypeKind == TypeKind.TYPEVAR) {
        newCastType = ((AnnotatedTypeVariable) castType).getUpperBound();
      } else {
        newCastType = castType;
      }
      AnnotatedTypeMirror newExprType;
      if (exprType.getKind() == TypeKind.TYPEVAR) {
        newExprType = ((AnnotatedTypeVariable) exprType).getUpperBound();
      } else {
        newExprType = exprType;
      }

      if (!atypeFactory.getTypeHierarchy().isSubtype(newExprType, newCastType)) {
        return false;
      }
      if (newCastType.getKind() == TypeKind.ARRAY && newExprType.getKind() != TypeKind.ARRAY) {
        // Always warn if the cast contains an array, but the expression
        // doesn't, as in "(Object[]) o" where o is of type Object
        return false;
      } else if (newCastType.getKind() == TypeKind.DECLARED
          && newExprType.getKind() == TypeKind.DECLARED) {
        int castSize = ((AnnotatedDeclaredType) newCastType).getTypeArguments().size();
        int exprSize = ((AnnotatedDeclaredType) newExprType).getTypeArguments().size();

        if (castSize != exprSize) {
          // Always warn if the cast and expression contain a different number of type arguments,
          // e.g. to catch a cast from "Object" to "List<@NonNull Object>".
          // TODO: the same number of arguments actually doesn't guarantee anything.
          return false;
        }
      } else if (castTypeKind == TypeKind.TYPEVAR && exprType.getKind() == TypeKind.TYPEVAR) {
        // If both the cast type and the casted expression are type variables, then check the
        // bounds.
        Set<AnnotationMirror> lowerBoundAnnotationsCast =
            AnnotatedTypes.findEffectiveLowerBoundAnnotations(qualifierHierarchy, castType);
        Set<AnnotationMirror> lowerBoundAnnotationsExpr =
            AnnotatedTypes.findEffectiveLowerBoundAnnotations(qualifierHierarchy, exprType);
        return qualifierHierarchy.isSubtype(lowerBoundAnnotationsExpr, lowerBoundAnnotationsCast)
            && qualifierHierarchy.isSubtype(
                exprType.getEffectiveAnnotations(), castType.getEffectiveAnnotations());
      }
      if (castTypeKind == TypeKind.TYPEVAR) {
        // If the cast type is a type var, but the expression is not, then check that the
        // type of the expression is a subtype of the lower bound.
        castAnnos = AnnotatedTypes.findEffectiveLowerBoundAnnotations(qualifierHierarchy, castType);
      } else {
        castAnnos = castType.getAnnotations();
      }
    }

    AnnotatedTypeMirror exprTypeWidened = atypeFactory.getWidenedType(exprType, castType);
    return qualifierHierarchy.isSubtype(exprTypeWidened.getEffectiveAnnotations(), castAnnos);
  }

  /**
   * Return whether or not casting the exprType to castType is legal.
   *
   * @param castType an invariant type
   * @param exprType type of the expressions that is cast which may or may not be invariant
   * @param top the top qualifier of the hierarchy to check
   * @return whether or not casting the exprType to castType is legal
   */
  private boolean isInvariantTypeCastSafe(
      AnnotatedTypeMirror castType, AnnotatedTypeMirror exprType, AnnotationMirror top) {
    if (!isTypeCastSafe(castType, exprType)) {
      return false;
    }
    AnnotationMirror castTypeAnno = castType.getEffectiveAnnotationInHierarchy(top);
    AnnotationMirror exprTypeAnno = exprType.getEffectiveAnnotationInHierarchy(top);

    if (atypeFactory.hasQualifierParameterInHierarchy(exprType, top)) {
      // The isTypeCastSafe call above checked that the exprType is a subtype of castType,
      // so just check the reverse to check that the qualifiers are equivalent.
      return atypeFactory.getQualifierHierarchy().isSubtype(castTypeAnno, exprTypeAnno);
    }
    // Otherwise the cast is unsafe, unless the qualifiers on both cast and expr are bottom.
    AnnotationMirror bottom = atypeFactory.getQualifierHierarchy().getBottomAnnotation(top);
    return AnnotationUtils.areSame(castTypeAnno, bottom)
        && AnnotationUtils.areSame(exprTypeAnno, bottom);
  }

  @Override
  public Void visitTypeCast(TypeCastTree node, Void p) {
    // validate "node" instead of "node.getType()" to prevent duplicate errors.
    boolean valid = validateTypeOf(node) && validateTypeOf(node.getExpression());
    if (valid) {
      checkTypecastSafety(node);
      checkTypecastRedundancy(node);
    }
    if (atypeFactory.getDependentTypesHelper().hasDependentAnnotations()) {
      AnnotatedTypeMirror type = atypeFactory.getAnnotatedType(node);
      atypeFactory.getDependentTypesHelper().checkTypeForErrorExpressions(type, node.getType());
    }

    if (node.getType().getKind() == Tree.Kind.INTERSECTION_TYPE) {
      AnnotatedIntersectionType intersection =
          (AnnotatedIntersectionType) atypeFactory.getAnnotatedType(node);
      checkExplicitAnnotationsOnIntersectionBounds(
          intersection, ((IntersectionTypeTree) node.getType()).getBounds());
    }
    return super.visitTypeCast(node, p);
    // return scan(node.getExpression(), p);
  }

  @Override
  public Void visitInstanceOf(InstanceOfTree node, Void p) {
    // The "reference type" is the type after "instanceof".
    Tree refTypeTree = node.getType();
    validateTypeOf(refTypeTree);
    if (refTypeTree.getKind() == Tree.Kind.ANNOTATED_TYPE) {
      AnnotatedTypeMirror refType = atypeFactory.getAnnotatedType(refTypeTree);
      AnnotatedTypeMirror expType = atypeFactory.getAnnotatedType(node.getExpression());
      if (!refType.hasAnnotation(NonNull.class)
          && atypeFactory.getTypeHierarchy().isSubtype(refType, expType)
          && !refType.getAnnotations().equals(expType.getAnnotations())) {
        checker.reportWarning(node, "instanceof.unsafe", expType, refType);
      }
    }
    return super.visitInstanceOf(node, p);
  }

  @Override
  public Void visitArrayAccess(ArrayAccessTree node, Void p) {
    Pair<Tree, AnnotatedTypeMirror> preAssignmentContext = visitorState.getAssignmentContext();
    try {
      visitorState.setAssignmentContext(null);
      scan(node.getExpression(), p);
      scan(node.getIndex(), p);
    } finally {
      visitorState.setAssignmentContext(preAssignmentContext);
    }
    return null;
  }

  /**
   * Checks the type of the exception parameter. Subclasses should override {@link
   * #checkExceptionParameter} rather than this method to change the behavior of this check.
   */
  @Override
  public Void visitCatch(CatchTree node, Void p) {
    checkExceptionParameter(node);
    return super.visitCatch(node, p);
  }

  /**
   * Checks the type of a thrown exception. Subclasses should override
   * checkThrownExpression(ThrowTree node) rather than this method to change the behavior of this
   * check.
   */
  @Override
  public Void visitThrow(ThrowTree node, Void p) {
    checkThrownExpression(node);
    return super.visitThrow(node, p);
  }

  /**
   * Rather than overriding this method, clients should often override {@link
   * #visitAnnotatedType(List,Tree)}. That method also handles the case of annotations at the
   * beginning of a variable or method declaration. javac parses all those annotations as being on
   * the variable or method declaration, even though the ones that are type annotations logically
   * belong to the variable type or method return type.
   */
  @Override
  public Void visitAnnotatedType(AnnotatedTypeTree node, Void p) {
    visitAnnotatedType(null, node);
    return super.visitAnnotatedType(node, p);
  }

  /**
   * Checks an annotated type. Invoked by {@link #visitAnnotatedType(AnnotatedTypeTree, Void)},
   * {@link #visitVariable}, and {@link #visitMethod}. Exists to prevent code duplication among the
   * three. Checking in {@code visitVariable} and {@code visitMethod} is needed because there isn't
   * an AnnotatedTypeTree within a variable declaration or for a method return type -- all the
   * annotations are attached to the VariableTree or MethodTree, respectively.
   *
   * @param annoTrees annotations written before a variable/method declaration, if this type is from
   *     one; null otherwise. This might contain type annotations that the Java parser attached to
   *     the declaration rather than to the type.
   * @param typeTree the type that any type annotations in annoTrees apply to
   */
  public void visitAnnotatedType(
      @Nullable List<? extends AnnotationTree> annoTrees, Tree typeTree) {
    warnAboutIrrelevantJavaTypes(annoTrees, typeTree);
  }

  /**
   * Warns if a type annotation is written on a Java type that is not listed in
   * the @RelevantJavaTypes annotation.
   *
   * @param annoTrees annotations written before a variable/method declaration, if this type is from
   *     one; null otherwise. This might contain type annotations that the Java parser attached to
   *     the declaration rather than to the type.
   * @param typeTree the type that any type annotations in annoTrees apply to
   */
  public void warnAboutIrrelevantJavaTypes(
      @Nullable List<? extends AnnotationTree> annoTrees, Tree typeTree) {
    if (atypeFactory.relevantJavaTypes == null) {
      return;
    }

    Tree t = typeTree;
    while (true) {
      switch (t.getKind()) {

          // Recurse for compound types whose top level is not at the far left.
        case ARRAY_TYPE:
          t = ((ArrayTypeTree) t).getType();
          continue;
        case MEMBER_SELECT:
          t = ((MemberSelectTree) t).getExpression();
          continue;
        case PARAMETERIZED_TYPE:
          t = ((ParameterizedTypeTree) t).getType();
          continue;

          // Base cases
        case PRIMITIVE_TYPE:
        case IDENTIFIER:
          List<AnnotationTree> supportedAnnoTrees = supportedAnnoTrees(annoTrees);
          if (!supportedAnnoTrees.isEmpty() && !atypeFactory.isRelevant(TreeUtils.typeOf(t))) {
            checker.reportError(t, "anno.on.irrelevant", supportedAnnoTrees, t);
          }
          return;
        case ANNOTATED_TYPE:
          AnnotatedTypeTree at = (AnnotatedTypeTree) t;
          ExpressionTree underlying = at.getUnderlyingType();
          List<AnnotationTree> annos = supportedAnnoTrees(at.getAnnotations());
          if (!annos.isEmpty() && !atypeFactory.isRelevant(TreeUtils.typeOf(underlying))) {
            checker.reportError(t, "anno.on.irrelevant", annos, underlying);
          }
          return;

        default:
          return;
      }
    }
  }

  /**
   * Returns a new list containing only the supported annotations from its argument -- that is,
   * those that are part of the current type system.
   *
   * <p>This method ignores aliases of supported annotations that are declaration annotations,
   * because they may apply to inner types.
   *
   * @param annoTrees annotation trees
   * @return a new list containing only the supported annotations from its argument
   */
  private List<AnnotationTree> supportedAnnoTrees(List<? extends AnnotationTree> annoTrees) {
    List<AnnotationTree> result = new ArrayList<>(1);
    for (AnnotationTree at : annoTrees) {
      AnnotationMirror anno = TreeUtils.annotationFromAnnotationTree(at);
      if (!AnnotationUtils.isDeclarationAnnotation(anno)
          && atypeFactory.isSupportedQualifier(anno)) {
        result.add(at);
      }
    }
    return result;
  }

  // **********************************************************************
  // Helper methods to provide a single overriding point
  // **********************************************************************

  /** Cache to avoid calling {@link #getExceptionParameterLowerBoundAnnotations} more than once. */
  private Set<? extends AnnotationMirror> getExceptionParameterLowerBoundAnnotationsCache = null;
  /** The same as {@link #getExceptionParameterLowerBoundAnnotations}, but uses a cache. */
  private Set<? extends AnnotationMirror> getExceptionParameterLowerBoundAnnotationsCached() {
    if (getExceptionParameterLowerBoundAnnotationsCache == null) {
      getExceptionParameterLowerBoundAnnotationsCache =
          getExceptionParameterLowerBoundAnnotations();
    }
    return getExceptionParameterLowerBoundAnnotationsCache;
  }

  /**
   * Issue error if the exception parameter is not a supertype of the annotation specified by {@link
   * #getExceptionParameterLowerBoundAnnotations()}, which is top by default.
   *
   * <p>Subclasses may override this method to change the behavior of this check. Subclasses wishing
   * to enforce that exception parameter be annotated with other annotations can just override
   * {@link #getExceptionParameterLowerBoundAnnotations()}.
   *
   * @param node CatchTree to check
   */
  protected void checkExceptionParameter(CatchTree node) {

    Set<? extends AnnotationMirror> requiredAnnotations =
        getExceptionParameterLowerBoundAnnotationsCached();
    AnnotatedTypeMirror exPar = atypeFactory.getAnnotatedType(node.getParameter());

    for (AnnotationMirror required : requiredAnnotations) {
      AnnotationMirror found = exPar.getAnnotationInHierarchy(required);
      assert found != null;
      if (!atypeFactory.getQualifierHierarchy().isSubtype(required, found)) {
        checker.reportError(node.getParameter(), "exception.parameter", found, required);
      }

      if (exPar.getKind() == TypeKind.UNION) {
        AnnotatedUnionType aut = (AnnotatedUnionType) exPar;
        for (AnnotatedTypeMirror alterntive : aut.getAlternatives()) {
          AnnotationMirror foundAltern = alterntive.getAnnotationInHierarchy(required);
          if (!atypeFactory.getQualifierHierarchy().isSubtype(required, foundAltern)) {
            checker.reportError(node.getParameter(), "exception.parameter", foundAltern, required);
          }
        }
      }
    }
  }

  /**
   * Returns a set of AnnotationMirrors that is a lower bound for exception parameters.
   *
   * <p>This implementation returns top; subclasses can change this behavior.
   *
   * <p>Note: by default this method is called by {@link #getThrowUpperBoundAnnotations()}, so that
   * this annotation is enforced.
   *
   * @return set of annotation mirrors, one per hierarchy, that form a lower bound of annotations
   *     that can be written on an exception parameter
   */
  protected Set<? extends AnnotationMirror> getExceptionParameterLowerBoundAnnotations() {
    return atypeFactory.getQualifierHierarchy().getTopAnnotations();
  }

  /**
   * Checks the type of the thrown expression.
   *
   * <p>By default, this method checks that the thrown expression is a subtype of top.
   *
   * <p>Issue error if the thrown expression is not a sub type of the annotation given by {@link
   * #getThrowUpperBoundAnnotations()}, the same as {@link
   * #getExceptionParameterLowerBoundAnnotations()} by default.
   *
   * <p>Subclasses may override this method to change the behavior of this check. Subclasses wishing
   * to enforce that the thrown expression be a subtype of a type besides {@link
   * #getExceptionParameterLowerBoundAnnotations}, should override {@link
   * #getThrowUpperBoundAnnotations()}.
   *
   * @param node ThrowTree to check
   */
  protected void checkThrownExpression(ThrowTree node) {
    AnnotatedTypeMirror throwType = atypeFactory.getAnnotatedType(node.getExpression());
    Set<? extends AnnotationMirror> required = getThrowUpperBoundAnnotations();
    switch (throwType.getKind()) {
      case NULL:
      case DECLARED:
        Set<AnnotationMirror> found = throwType.getAnnotations();
        if (!atypeFactory.getQualifierHierarchy().isSubtype(found, required)) {
          checker.reportError(node.getExpression(), "throw", found, required);
        }
        break;
      case TYPEVAR:
      case WILDCARD:
        // TODO: this code might change after the type var changes.
        Set<AnnotationMirror> foundEffective = throwType.getEffectiveAnnotations();
        if (!atypeFactory.getQualifierHierarchy().isSubtype(foundEffective, required)) {
          checker.reportError(node.getExpression(), "throw", foundEffective, required);
        }
        break;
      case UNION:
        AnnotatedUnionType unionType = (AnnotatedUnionType) throwType;
        Set<AnnotationMirror> foundPrimary = unionType.getAnnotations();
        if (!atypeFactory.getQualifierHierarchy().isSubtype(foundPrimary, required)) {
          checker.reportError(node.getExpression(), "throw", foundPrimary, required);
        }
        for (AnnotatedTypeMirror altern : unionType.getAlternatives()) {
          if (!atypeFactory.getQualifierHierarchy().isSubtype(altern.getAnnotations(), required)) {
            checker.reportError(node.getExpression(), "throw", altern.getAnnotations(), required);
          }
        }
        break;
      default:
        throw new BugInCF("Unexpected throw expression type: " + throwType.getKind());
    }
  }

  /**
   * Returns a set of AnnotationMirrors that is a upper bound for thrown exceptions.
   *
   * <p>Note: by default this method is returns by getExceptionParameterLowerBoundAnnotations(), so
   * that this annotation is enforced.
   *
   * <p>(Default is top)
   *
   * @return set of annotation mirrors, one per hierarchy, that form an upper bound of thrown
   *     expressions
   */
  protected Set<? extends AnnotationMirror> getThrowUpperBoundAnnotations() {
    return getExceptionParameterLowerBoundAnnotations();
  }

  /**
   * Checks the validity of an assignment (or pseudo-assignment) from a value to a variable and
   * emits an error message (through the compiler's messaging interface) if it is not valid.
   *
   * @param varTree the AST node for the lvalue (usually a variable)
   * @param valueExp the AST node for the rvalue (the new value)
   * @param errorKey the error message key to use if the check fails
   * @param extraArgs arguments to the error message key, before "found" and "expected" types
   */
  protected void commonAssignmentCheck(
      Tree varTree,
      ExpressionTree valueExp,
      @CompilerMessageKey String errorKey,
      Object... extraArgs) {
    AnnotatedTypeMirror varType = atypeFactory.getAnnotatedTypeLhs(varTree);
    assert varType != null : "no variable found for tree: " + varTree;

    if (!validateType(varTree, varType)) {
      return;
    }

    commonAssignmentCheck(varType, valueExp, errorKey, extraArgs);
  }

  /**
   * Checks the validity of an assignment (or pseudo-assignment) from a value to a variable and
   * emits an error message (through the compiler's messaging interface) if it is not valid.
   *
   * @param varType the annotated type for the lvalue (usually a variable)
   * @param valueExp the AST node for the rvalue (the new value)
   * @param errorKey the error message key to use if the check fails
   * @param extraArgs arguments to the error message key, before "found" and "expected" types
   */
  protected void commonAssignmentCheck(
      AnnotatedTypeMirror varType,
      ExpressionTree valueExp,
      @CompilerMessageKey String errorKey,
      Object... extraArgs) {
    if (shouldSkipUses(valueExp)) {
      return;
    }
    if (valueExp.getKind() == Tree.Kind.MEMBER_REFERENCE
        || valueExp.getKind() == Tree.Kind.LAMBDA_EXPRESSION) {
      // Member references and lambda expressions are type checked separately
      // and do not need to be checked again as arguments.
      return;
    }
    if (varType.getKind() == TypeKind.ARRAY
        && valueExp instanceof NewArrayTree
        && ((NewArrayTree) valueExp).getType() == null) {
      AnnotatedTypeMirror compType = ((AnnotatedArrayType) varType).getComponentType();
      NewArrayTree arrayTree = (NewArrayTree) valueExp;
      assert arrayTree.getInitializers() != null
          : "array initializers are not expected to be null in: " + valueExp;
      checkArrayInitialization(compType, arrayTree.getInitializers());
    }
    if (!validateTypeOf(valueExp)) {
      return;
    }
    AnnotatedTypeMirror valueType = atypeFactory.getAnnotatedType(valueExp);
    assert valueType != null : "null type for expression: " + valueExp;
    commonAssignmentCheck(varType, valueType, valueExp, errorKey, extraArgs);
  }

  /**
   * Checks the validity of an assignment (or pseudo-assignment) from a value to a variable and
   * emits an error message (through the compiler's messaging interface) if it is not valid.
   *
   * @param varType the annotated type of the variable
   * @param valueType the annotated type of the value
   * @param valueTree the location to use when reporting the error message
   * @param errorKey the error message key to use if the check fails
   * @param extraArgs arguments to the error message key, before "found" and "expected" types
   */
  protected void commonAssignmentCheck(
      AnnotatedTypeMirror varType,
      AnnotatedTypeMirror valueType,
      Tree valueTree,
      @CompilerMessageKey String errorKey,
      Object... extraArgs) {

    commonAssignmentCheckStartDiagnostic(varType, valueType, valueTree);

    AnnotatedTypeMirror widenedValueType = atypeFactory.getWidenedType(valueType, varType);
    boolean success = atypeFactory.getTypeHierarchy().isSubtype(widenedValueType, varType);

    // TODO: integrate with subtype test.
    if (success) {
      for (Class<? extends Annotation> mono : atypeFactory.getSupportedMonotonicTypeQualifiers()) {
        if (valueType.hasAnnotation(mono) && varType.hasAnnotation(mono)) {
          checker.reportError(
              valueTree,
              "monotonic",
              mono.getSimpleName(),
              mono.getSimpleName(),
              valueType.toString());
          return;
        }
      }
    }

    commonAssignmentCheckEndDiagnostic(success, null, varType, valueType, valueTree);

    // Use an error key only if it's overridden by a checker.
    if (!success) {
      FoundRequired pair = FoundRequired.of(valueType, varType);
      String valueTypeString = pair.found;
      String varTypeString = pair.required;
      checker.reportError(
          valueTree, errorKey, ArraysPlume.concatenate(extraArgs, valueTypeString, varTypeString));
    }
  }

  /**
   * Prints a diagnostic about entering commonAssignmentCheck, if the showchecks option was set.
   *
   * @param varType the annotated type of the variable
   * @param valueType the annotated type of the value
   * @param valueTree the location to use when reporting the error message
   */
  protected final void commonAssignmentCheckStartDiagnostic(
      AnnotatedTypeMirror varType, AnnotatedTypeMirror valueType, Tree valueTree) {
    if (showchecks) {
      long valuePos = positions.getStartPosition(root, valueTree);
      System.out.printf(
          "%s %s (line %3d): actual tree = %s %s%n     actual: %s %s%n   expected: %s %s%n",
          this.getClass().getSimpleName(),
          "about to test whether actual is a subtype of expected",
          (root.getLineMap() != null ? root.getLineMap().getLineNumber(valuePos) : -1),
          valueTree.getKind(),
          valueTree,
          valueType.getKind(),
          valueType.toString(),
          varType.getKind(),
          varType.toString());
    }
  }

  /**
   * Prints a diagnostic about exiting commonAssignmentCheck, if the showchecks option was set.
   *
   * @param success whether the check succeeded or failed
   * @param extraMessage information about why the result is what it is; may be null
   * @param varType the annotated type of the variable
   * @param valueType the annotated type of the value
   * @param valueTree the location to use when reporting the error message
   */
  protected final void commonAssignmentCheckEndDiagnostic(
      boolean success,
      String extraMessage,
      AnnotatedTypeMirror varType,
      AnnotatedTypeMirror valueType,
      Tree valueTree) {
    if (showchecks) {
      commonAssignmentCheckEndDiagnostic(
          (success
                  ? "success: actual is subtype of expected"
                  : "FAILURE: actual is not subtype of expected")
              + (extraMessage == null ? "" : " because " + extraMessage),
          varType,
          valueType,
          valueTree);
    }
  }

  /**
   * Prints a diagnostic about exiting commonAssignmentCheck, if the showchecks option was set.
   *
   * <p>Most clients should call {@link #commonAssignmentCheckEndDiagnostic(boolean, String,
   * AnnotatedTypeMirror, AnnotatedTypeMirror, Tree)}. The purpose of this method is to permit
   * customizing the message that is printed.
   *
   * @param message the result, plus information about why the result is what it is; may be null
   * @param varType the annotated type of the variable
   * @param valueType the annotated type of the value
   * @param valueTree the location to use when reporting the error message
   */
  protected final void commonAssignmentCheckEndDiagnostic(
      String message, AnnotatedTypeMirror varType, AnnotatedTypeMirror valueType, Tree valueTree) {
    if (showchecks) {
      long valuePos = positions.getStartPosition(root, valueTree);
      System.out.printf(
          " %s (line %3d): actual tree = %s %s%n     actual: %s %s%n   expected: %s %s%n",
          message,
          (root.getLineMap() != null ? root.getLineMap().getLineNumber(valuePos) : -1),
          valueTree.getKind(),
          valueTree,
          valueType.getKind(),
          valueType.toString(),
          varType.getKind(),
          varType.toString());
    }
  }

  /**
   * Class that creates string representations of {@link AnnotatedTypeMirror}s which are only
   * verbose if required to differentiate the two types.
   */
  private static class FoundRequired {
    public final String found;
    public final String required;

    private FoundRequired(AnnotatedTypeMirror found, AnnotatedTypeMirror required) {
      if (shouldPrintVerbose(found, required)) {
        this.found = found.toString(true);
        this.required = required.toString(true);
      } else {
        this.found = found.toString();
        this.required = required.toString();
      }
    }

    /** Create a FoundRequired for a type and bounds. */
    private FoundRequired(AnnotatedTypeMirror found, AnnotatedTypeParameterBounds required) {
      if (shouldPrintVerbose(found, required)) {
        this.found = found.toString(true);
        this.required = required.toString(true);
      } else {
        this.found = found.toString();
        this.required = required.toString();
      }
    }

    /**
     * Creates string representations of {@link AnnotatedTypeMirror}s which are only verbose if
     * required to differentiate the two types.
     */
    static FoundRequired of(AnnotatedTypeMirror found, AnnotatedTypeMirror required) {
      return new FoundRequired(found, required);
    }

    /**
     * Creates string representations of {@link AnnotatedTypeMirror} and {@link
     * AnnotatedTypeParameterBounds}s which are only verbose if required to differentiate the two
     * types.
     */
    static FoundRequired of(AnnotatedTypeMirror found, AnnotatedTypeParameterBounds required) {
      return new FoundRequired(found, required);
    }
  }

  /**
   * Return whether or not the verbose toString should be used when printing the two annotated
   * types.
   *
   * @param atm1 the first AnnotatedTypeMirror
   * @param atm2 the second AnnotatedTypeMirror
   * @return true iff neither argumentc contains "@", or there are two annotated types (in either
   *     ATM) such that their toStrings are the same but their verbose toStrings differ
   */
  private static boolean shouldPrintVerbose(AnnotatedTypeMirror atm1, AnnotatedTypeMirror atm2) {
    if (!atm1.toString().contains("@") && !atm2.toString().contains("@")) {
      return true;
    }
    return containsSameToString(atm1, atm2);
  }

  /**
   * Return whether or not the verbose toString should be used when printing the annotated type and
   * the bounds it is not within.
   *
   * @param atm the type
   * @param bounds the bounds
   * @return true iff bounds does not contain "@", or there are two annotated types (in either
   *     argument) such that their toStrings are the same but their verbose toStrings differ
   */
  private static boolean shouldPrintVerbose(
      AnnotatedTypeMirror atm, AnnotatedTypeParameterBounds bounds) {
    if (!atm.toString().contains("@") && !bounds.toString().contains("@")) {
      return true;
    }
    return containsSameToString(atm, bounds.getUpperBound(), bounds.getLowerBound());
  }

  /**
   * A scanner that indicates whether any (sub-)types have the same toString but different verbose
   * toString. If so, the Checker Framework prints types verbosely.
   */
  private static SimpleAnnotatedTypeScanner<Boolean, Map<String, String>>
      checkContainsSameToString =
          new SimpleAnnotatedTypeScanner<>(
              (AnnotatedTypeMirror type, Map<String, String> map) -> {
                if (type == null) {
                  return false;
                }
                String simple = type.toString();
                String verbose = map.get(simple);
                if (verbose == null) {
                  map.put(simple, type.toString(true));
                  return false;
                } else {
                  return !verbose.equals(type.toString(true));
                }
              },
              Boolean::logicalOr,
              false);

  /**
   * Return true iff there are two annotated types (anywhere in any ATM) such that their toStrings
   * are the same but their verbose toStrings differ. If so, the Checker Framework prints types
   * verbosely.
   *
   * @param atms annotated type mirrors to compare
   * @return true iff there are two annotated types (anywhere in any ATM) such that their toStrings
   *     are the same but their verbose toStrings differ
   */
  private static boolean containsSameToString(AnnotatedTypeMirror... atms) {
    Map<String, String> simpleToVerbose = new HashMap<>();
    for (AnnotatedTypeMirror atm : atms) {
      if (checkContainsSameToString.visit(atm, simpleToVerbose)) {
        return true;
      }
    }

    return false;
  }

  protected void checkArrayInitialization(
      AnnotatedTypeMirror type, List<? extends ExpressionTree> initializers) {
    // TODO: set assignment context like for method arguments?
    // Also in AbstractFlow.
    for (ExpressionTree init : initializers) {
      commonAssignmentCheck(type, init, "array.initializer");
    }
  }

  /**
   * Checks that the annotations on the type arguments supplied to a type or a method invocation are
   * within the bounds of the type variables as declared, and issues the "type.argument" error if
   * they are not.
   *
   * @param toptree the tree for error reporting, only used for inferred type arguments
   * @param paramBounds the bounds of the type parameters from a class or method declaration
   * @param typeargs the type arguments from the type or method invocation
   * @param typeargTrees the type arguments as trees, used for error reporting
   */
  protected void checkTypeArguments(
      Tree toptree,
      List<? extends AnnotatedTypeParameterBounds> paramBounds,
      List<? extends AnnotatedTypeMirror> typeargs,
      List<? extends Tree> typeargTrees,
      CharSequence typeOrMethodName,
      List<?> paramNames) {

    // System.out.printf("BaseTypeVisitor.checkTypeArguments: %s, TVs: %s, TAs: %s, TATs: %s%n",
    //         toptree, paramBounds, typeargs, typeargTrees);

    // If there are no type variables, do nothing.
    if (paramBounds.isEmpty()) {
      return;
    }

    int size = paramBounds.size();
    assert size == typeargs.size()
        : "BaseTypeVisitor.checkTypeArguments: mismatch between type arguments: "
            + typeargs
            + " and type parameter bounds"
            + paramBounds;

    for (int i = 0; i < size; i++) {

      AnnotatedTypeParameterBounds bounds = paramBounds.get(i);
      AnnotatedTypeMirror typeArg = typeargs.get(i);

      if (isIgnoredUninferredWildcard(bounds.getUpperBound())
          || isIgnoredUninferredWildcard(typeArg)) {
        continue;
      }

      if (shouldBeCaptureConverted(typeArg, bounds)) {
        continue;
      }

      AnnotatedTypeMirror paramUpperBound = bounds.getUpperBound();
      if (typeArg.getKind() == TypeKind.WILDCARD) {
        paramUpperBound =
            atypeFactory.widenToUpperBound(paramUpperBound, (AnnotatedWildcardType) typeArg);
      }

      Tree reportErrorToTree;
      if (typeargTrees == null || typeargTrees.isEmpty()) {
        // The type arguments were inferred, report the error on the method invocation.
        reportErrorToTree = toptree;
      } else {
        reportErrorToTree = typeargTrees.get(i);
      }

      checkHasQualifierParameterAsTypeArgument(typeArg, paramUpperBound, toptree);
      commonAssignmentCheck(
          paramUpperBound,
          typeArg,
          reportErrorToTree,
          "type.argument",
          paramNames.get(i),
          typeOrMethodName);

      if (!atypeFactory.getTypeHierarchy().isSubtype(bounds.getLowerBound(), typeArg)) {
        FoundRequired fr = FoundRequired.of(typeArg, bounds);
        checker.reportError(
            reportErrorToTree,
            "type.argument",
            paramNames.get(i),
            typeOrMethodName,
            fr.found,
            fr.required);
      }
    }
  }

  /**
   * Reports an error if the type argument has a qualifier parameter and the type parameter upper
   * bound does not have a qualifier parameter.
   *
   * @param typeArgument type argument
   * @param typeParameterUpperBound upper bound of the type parameter
   * @param reportError where to report the error
   */
  private void checkHasQualifierParameterAsTypeArgument(
      AnnotatedTypeMirror typeArgument,
      AnnotatedTypeMirror typeParameterUpperBound,
      Tree reportError) {
    for (AnnotationMirror top : atypeFactory.getQualifierHierarchy().getTopAnnotations()) {
      if (atypeFactory.hasQualifierParameterInHierarchy(typeArgument, top)
          && !getTypeFactory().hasQualifierParameterInHierarchy(typeParameterUpperBound, top)) {
        checker.reportError(reportError, "type.argument.hasqualparam", top);
      }
    }
  }

  private boolean isIgnoredUninferredWildcard(AnnotatedTypeMirror type) {
    return atypeFactory.ignoreUninferredTypeArguments
        && type.getKind() == TypeKind.WILDCARD
        && ((AnnotatedWildcardType) type).isUninferredTypeArgument();
  }

  // TODO: REMOVE WHEN CAPTURE CONVERSION IS IMPLEMENTED
  // TODO: This may not occur only in places where capture conversion occurs but in those cases
  // TODO: The containment check provided by this method should be enough
  /**
   * Identifies cases that would not happen if capture conversion were implemented. These special
   * cases should be removed when capture conversion is implemented.
   */
  private boolean shouldBeCaptureConverted(
      final AnnotatedTypeMirror typeArg, final AnnotatedTypeParameterBounds bounds) {
    return typeArg.getKind() == TypeKind.WILDCARD
        && bounds.getUpperBound().getKind() == TypeKind.WILDCARD;
  }

  /**
   * Indicates whether to skip subtype checks on the receiver when checking method invocability. A
   * visitor may, for example, allow a method to be invoked even if the receivers are siblings in a
   * hierarchy, provided that some other condition (implemented by the visitor) is satisfied.
   *
   * @param node the method invocation node
   * @param methodDefinitionReceiver the ATM of the receiver of the method definition
   * @param methodCallReceiver the ATM of the receiver of the method call
   * @return whether to skip subtype checks on the receiver
   */
  protected boolean skipReceiverSubtypeCheck(
      MethodInvocationTree node,
      AnnotatedTypeMirror methodDefinitionReceiver,
      AnnotatedTypeMirror methodCallReceiver) {
    return false;
  }

  /**
   * Tests whether the method can be invoked using the receiver of the 'node' method invocation, and
   * issues a "method.invocation" if the invocation is invalid.
   *
   * <p>This implementation tests whether the receiver in the method invocation is a subtype of the
   * method receiver type. This behavior can be specialized by overriding skipReceiverSubtypeCheck.
   *
   * @param method the type of the invoked method
   * @param node the method invocation node
   */
  protected void checkMethodInvocability(
      AnnotatedExecutableType method, MethodInvocationTree node) {
    if (method.getReceiverType() == null) {
      // Static methods don't have a receiver.
      return;
    }
    if (method.getElement().getKind() == ElementKind.CONSTRUCTOR) {
      // TODO: Explicit "this()" calls of constructors have an implicit passed
      // from the enclosing constructor. We must not use the self type, but
      // instead should find a way to determine the receiver of the enclosing constructor.
      // rcv =
      // ((AnnotatedExecutableType)atypeFactory.getAnnotatedType(atypeFactory.getEnclosingMethod(node))).getReceiverType();
      return;
    }

    AnnotatedTypeMirror methodReceiver = method.getReceiverType().getErased();
    AnnotatedTypeMirror treeReceiver = methodReceiver.shallowCopy(false);
    AnnotatedTypeMirror rcv = atypeFactory.getReceiverType(node);

    treeReceiver.addAnnotations(rcv.getEffectiveAnnotations());

    if (!skipReceiverSubtypeCheck(node, methodReceiver, rcv)) {
      commonAssignmentCheckStartDiagnostic(methodReceiver, treeReceiver, node);
      boolean success = atypeFactory.getTypeHierarchy().isSubtype(treeReceiver, methodReceiver);
      commonAssignmentCheckEndDiagnostic(success, null, methodReceiver, treeReceiver, node);
      if (!success) {
        reportMethodInvocabilityError(node, treeReceiver, methodReceiver);
      }
    }
  }

  /**
   * Report a method invocability error. Allows checkers to change how the message is output.
   *
   * @param node the AST node at which to report the error
   * @param found the actual type of the receiver
   * @param expected the expected type of the receiver
   */
  protected void reportMethodInvocabilityError(
      MethodInvocationTree node, AnnotatedTypeMirror found, AnnotatedTypeMirror expected) {
    checker.reportError(
        node,
        "method.invocation",
        TreeUtils.elementFromUse(node),
        found.toString(),
        expected.toString());
  }

  /**
   * Check that the (explicit) annotations on a new class tree are comparable to the result type of
   * the constructor. Issue an error if not.
   *
   * <p>Issue a warning if the annotations on the constructor invocation is a subtype of the
   * constructor result type. This is equivalent to down-casting.
   */
  protected void checkConstructorInvocation(
      AnnotatedDeclaredType invocation,
      AnnotatedExecutableType constructor,
      NewClassTree newClassTree) {
    // Only check the primary annotations, the type arguments are checked elsewhere.
    Set<AnnotationMirror> explicitAnnos = atypeFactory.fromNewClass(newClassTree).getAnnotations();
    if (explicitAnnos.isEmpty()) {
      return;
    }
    Set<AnnotationMirror> resultAnnos = constructor.getReturnType().getAnnotations();
    for (AnnotationMirror explicit : explicitAnnos) {
      AnnotationMirror resultAnno =
          atypeFactory.getQualifierHierarchy().findAnnotationInSameHierarchy(resultAnnos, explicit);
      // The return type of the constructor (resultAnnos) must be comparable to the
      // annotations on the constructor invocation (explicitAnnos).
      if (!(atypeFactory.getQualifierHierarchy().isSubtype(explicit, resultAnno)
          || atypeFactory.getQualifierHierarchy().isSubtype(resultAnno, explicit))) {
        checker.reportError(
            newClassTree, "constructor.invocation", constructor.toString(), explicit, resultAnno);
        return;
      } else if (!atypeFactory.getQualifierHierarchy().isSubtype(resultAnno, explicit)) {
        // Issue a warning if the annotations on the constructor invocation is a subtype of
        // the constructor result type. This is equivalent to down-casting.
        checker.reportWarning(
            newClassTree, "cast.unsafe.constructor.invocation", resultAnno, explicit);
        return;
      }
    }

    // TODO: what properties should hold for constructor receivers for
    // inner type instantiations?
  }

  /**
   * A helper method to check that each passed argument is a subtype of the corresponding required
   * argument, and issues "argument" error for each passed argument that not a subtype of the
   * required one.
   *
   * <p>Note this method requires the lists to have the same length, as it does not handle cases
   * like var args.
   *
   * @see #checkVarargs(AnnotatedTypeMirror.AnnotatedExecutableType, Tree)
   * @param requiredArgs the required types. This may differ from the formal parameter types,
   *     because it replaces a varargs parameter by multiple parameters with the vararg's element
   *     type.
   * @param passedArgs the expressions passed to the corresponding types
   * @param executableName the name of the method or constructor being called
   * @param paramNames the names of the callee's formal parameters
   */
  protected void checkArguments(
      List<? extends AnnotatedTypeMirror> requiredArgs,
      List<? extends ExpressionTree> passedArgs,
      CharSequence executableName,
      List<?> paramNames) {
    int size = requiredArgs.size();
    assert size == passedArgs.size()
        : "mismatch between required args ("
            + requiredArgs
            + ") and passed args ("
            + passedArgs
            + ")";
    int maxParamNamesIndex = paramNames.size() - 1;
    // Rather weak assertion, due to how varargs parameters are treated.
    assert size >= maxParamNamesIndex
        : String.format(
            "mismatched lengths %d %d %d checkArguments(%s, %s, %s, %s)",
            size,
            passedArgs.size(),
            paramNames.size(),
            listToString(requiredArgs),
            listToString(passedArgs),
            executableName,
            listToString(paramNames));

    Pair<Tree, AnnotatedTypeMirror> preAssignmentContext = visitorState.getAssignmentContext();
    try {
      for (int i = 0; i < size; ++i) {
        visitorState.setAssignmentContext(
            Pair.of((Tree) null, (AnnotatedTypeMirror) requiredArgs.get(i)));
        commonAssignmentCheck(
            requiredArgs.get(i),
            passedArgs.get(i),
            "argument",
            // TODO: for expanded varargs parameters, maybe adjust the name
            paramNames.get(Math.min(i, maxParamNamesIndex)),
            executableName);
        // Also descend into the argument within the correct assignment context.
        scan(passedArgs.get(i), null);
      }
    } finally {
      visitorState.setAssignmentContext(preAssignmentContext);
    }
  }

  // com.sun.tools.javac.util.List has a toString that does not include surrounding "[...]",
  // making it hard to interpret in messages.
  /**
   * Produce a printed representation of a list, in the standard format with surrounding "[...]".
   *
   * @param lst a list to format
   * @return the printed representation of the list
   */
  private String listToString(List<?> lst) {
    StringJoiner result = new StringJoiner(",", "[", "]");
    for (Object elt : lst) {
      result.add(elt.toString());
    }
    return result.toString();
  }

  /**
   * Returns true if both types are type variables and outer contains inner. Outer contains inner
   * implies: {@literal inner.upperBound <: outer.upperBound outer.lowerBound <: inner.lowerBound}.
   *
   * @return true if both types are type variables and outer contains inner
   */
  protected boolean testTypevarContainment(
      final AnnotatedTypeMirror inner, final AnnotatedTypeMirror outer) {
    if (inner.getKind() == TypeKind.TYPEVAR && outer.getKind() == TypeKind.TYPEVAR) {

      final AnnotatedTypeVariable innerAtv = (AnnotatedTypeVariable) inner;
      final AnnotatedTypeVariable outerAtv = (AnnotatedTypeVariable) outer;

      if (AnnotatedTypes.areCorrespondingTypeVariables(elements, innerAtv, outerAtv)) {
        final TypeHierarchy typeHierarchy = atypeFactory.getTypeHierarchy();
        return typeHierarchy.isSubtype(innerAtv.getUpperBound(), outerAtv.getUpperBound())
            && typeHierarchy.isSubtype(outerAtv.getLowerBound(), innerAtv.getLowerBound());
      }
    }

    return false;
  }

  /**
   * Create an OverrideChecker.
   *
   * <p>This exists so that subclasses can subclass OverrideChecker and use their subclass instead
   * of using OverrideChecker itself.
   *
   * @param overriderTree the AST node of the overriding method or method reference
   * @param overriderMethodType the type of the overriding method
   * @param overriderType the type enclosing the overrider method, usually an AnnotatedDeclaredType;
   *     for Method References may be something else
   * @param overriderReturnType the return type of the overriding method
   * @param overriddenMethodType the type of the overridden method
   * @param overriddenType the declared type enclosing the overridden method
   * @param overriddenReturnType the return type of the overridden method
   * @return an OverrideChecker
   */
  protected OverrideChecker createOverrideChecker(
      Tree overriderTree,
      AnnotatedExecutableType overriderMethodType,
      AnnotatedTypeMirror overriderType,
      AnnotatedTypeMirror overriderReturnType,
      AnnotatedExecutableType overriddenMethodType,
      AnnotatedDeclaredType overriddenType,
      AnnotatedTypeMirror overriddenReturnType) {
    return new OverrideChecker(
        overriderTree,
        overriderMethodType,
        overriderType,
        overriderReturnType,
        overriddenMethodType,
        overriddenType,
        overriddenReturnType);
  }

  /**
   * Type checks that a method may override another method. Uses an OverrideChecker subclass as
   * created by {@link #createOverrideChecker}. This version of the method uses the annotated type
   * factory to get the annotated type of the overriding method, and does NOT expose that type.
   *
   * @see #checkOverride(MethodTree, AnnotatedTypeMirror.AnnotatedExecutableType,
   *     AnnotatedTypeMirror.AnnotatedDeclaredType, AnnotatedTypeMirror.AnnotatedExecutableType,
   *     AnnotatedTypeMirror.AnnotatedDeclaredType)
   * @param overriderTree declaration tree of overriding method
   * @param overriderType type of overriding class
   * @param overriddenMethodType type of overridden method
   * @param overriddenType type of overridden class
   * @return true if the override is allowed
   */
  protected boolean checkOverride(
      MethodTree overriderTree,
      AnnotatedDeclaredType overriderType,
      AnnotatedExecutableType overriddenMethodType,
      AnnotatedDeclaredType overriddenType) {

    // Get the type of the overriding method.
    AnnotatedExecutableType overriderMethodType = atypeFactory.getAnnotatedType(overriderTree);

    // Call the other version of the method, which takes overriderMethodType. Both versions
    // exist to allow checkers to override one or the other depending on their needs.
    return checkOverride(
        overriderTree, overriderMethodType, overriderType, overriddenMethodType, overriddenType);
  }

  /**
   * Type checks that a method may override another method. Uses an OverrideChecker subclass as
   * created by {@link #createOverrideChecker}. This version of the method exposes
   * AnnotatedExecutableType of the overriding method. Override this version of the method if you
   * need to access that type.
   *
   * @see #checkOverride(MethodTree, AnnotatedTypeMirror.AnnotatedDeclaredType,
   *     AnnotatedTypeMirror.AnnotatedExecutableType, AnnotatedTypeMirror.AnnotatedDeclaredType)
   * @param overriderTree declaration tree of overriding method
   * @param overriderMethodType type of the overriding method
   * @param overriderType type of overriding class
   * @param overriddenMethodType type of overridden method
   * @param overriddenType type of overridden class
   * @return true if the override is allowed
   */
  protected boolean checkOverride(
      MethodTree overriderTree,
      AnnotatedExecutableType overriderMethodType,
      AnnotatedDeclaredType overriderType,
      AnnotatedExecutableType overriddenMethodType,
      AnnotatedDeclaredType overriddenType) {

    // This needs to be done before overriderMethodType.getReturnType() and
    // overriddenMethodType.getReturnType()
    if (overriderMethodType.getTypeVariables().isEmpty()
        && !overriddenMethodType.getTypeVariables().isEmpty()) {
      overriddenMethodType = overriddenMethodType.getErased();
    }

    OverrideChecker overrideChecker =
        createOverrideChecker(
            overriderTree,
            overriderMethodType,
            overriderType,
            overriderMethodType.getReturnType(),
            overriddenMethodType,
            overriddenType,
            overriddenMethodType.getReturnType());

    return overrideChecker.checkOverride();
  }

  /**
   * Check that a method reference is allowed. Using the OverrideChecker class.
   *
   * @param memberReferenceTree the tree for the method reference
   * @return true if the method reference is allowed
   */
  protected boolean checkMethodReferenceAsOverride(
      MemberReferenceTree memberReferenceTree, Void p) {

    Pair<AnnotatedTypeMirror, AnnotatedExecutableType> result =
        atypeFactory.getFnInterfaceFromTree(memberReferenceTree);
    // The type to which the member reference is assigned -- also known as the target type of the
    // reference.
    AnnotatedTypeMirror functionalInterface = result.first;
    // The type of the single method that is declared by the functional interface.
    AnnotatedExecutableType functionType = result.second;

    // ========= Overriding Type =========
    // This doesn't get the correct type for a "MyOuter.super" based on the receiver of the
    // enclosing method.
    // That is handled separately in method receiver check.

    // The type of the expression or type use, <expression>::method or <type use>::method.
    final ExpressionTree qualifierExpression = memberReferenceTree.getQualifierExpression();
    final ReferenceKind memRefKind = ((JCMemberReference) memberReferenceTree).kind;
    AnnotatedTypeMirror enclosingType;
    if (memberReferenceTree.getMode() == ReferenceMode.NEW
        || memRefKind == ReferenceKind.UNBOUND
        || memRefKind == ReferenceKind.STATIC) {
      // The "qualifier expression" is a type tree.
      enclosingType = atypeFactory.getAnnotatedTypeFromTypeTree(qualifierExpression);
    } else {
      // The "qualifier expression" is an expression.
      enclosingType = atypeFactory.getAnnotatedType(qualifierExpression);
    }

    // ========= Overriding Executable =========
    // The ::method element, see JLS 15.13.1 Compile-Time Declaration of a Method Reference
    ExecutableElement compileTimeDeclaration =
        (ExecutableElement) TreeUtils.elementFromTree(memberReferenceTree);

    if (enclosingType.getKind() == TypeKind.DECLARED
        && ((AnnotatedDeclaredType) enclosingType).wasRaw()) {
      if (memRefKind == ReferenceKind.UNBOUND) {
        // The method reference is of the form: Type # instMethod and Type is a raw type.
        // If the first parameter of the function type, p1, is a subtype of type, then type should
        // be p1.  This has the effect of "inferring" the class type parameter.
        AnnotatedTypeMirror p1 = functionType.getParameterTypes().get(0);
        TypeMirror asSuper =
            TypesUtils.asSuper(
                p1.getUnderlyingType(),
                enclosingType.getUnderlyingType(),
                atypeFactory.getProcessingEnv());
        if (asSuper != null) {
          enclosingType = AnnotatedTypes.asSuper(atypeFactory, p1, enclosingType);
        }
      }
      // else method reference is something like ArrayList::new
      // TODO: Use diamond, <>, inference to infer the class type arguments.
      // For now this case is skipped below in checkMethodReferenceInference.
    }

    // The type of the compileTimeDeclaration if it were invoked with a receiver expression
    // of type {@code type}
    AnnotatedExecutableType invocationType =
        atypeFactory.methodFromUse(memberReferenceTree, compileTimeDeclaration, enclosingType)
            .executableType;

    if (checkMethodReferenceInference(memberReferenceTree, invocationType, enclosingType)) {
      // Type argument inference is required, skip check.
      // #checkMethodReferenceInference issued a warning.
      return true;
    }

    // This needs to be done before invocationType.getReturnType() and
    // functionType.getReturnType()
    if (invocationType.getTypeVariables().isEmpty() && !functionType.getTypeVariables().isEmpty()) {
      functionType = functionType.getErased();
    }

    // Use the function type's parameters to resolve polymorphic qualifiers.
    QualifierPolymorphism poly = atypeFactory.getQualifierPolymorphism();
    poly.resolve(functionType, invocationType);

    AnnotatedTypeMirror invocationReturnType;
    if (compileTimeDeclaration.getKind() == ElementKind.CONSTRUCTOR) {
      if (enclosingType.getKind() == TypeKind.ARRAY) {
        // Special casing for the return of array constructor
        invocationReturnType = enclosingType;
      } else {
        invocationReturnType =
            atypeFactory.getResultingTypeOfConstructorMemberReference(
                memberReferenceTree, invocationType);
      }
    } else {
      invocationReturnType = invocationType.getReturnType();
    }

    AnnotatedTypeMirror functionTypeReturnType = functionType.getReturnType();
    if (functionTypeReturnType.getKind() == TypeKind.VOID) {
      // If the functional interface return type is void, the overriding return type doesn't matter.
      functionTypeReturnType = invocationReturnType;
    }

    if (functionalInterface.getKind() == TypeKind.DECLARED) {
      // Check the member reference as if invocationType overrides functionType.
      OverrideChecker overrideChecker =
          createOverrideChecker(
              memberReferenceTree,
              invocationType,
              enclosingType,
              invocationReturnType,
              functionType,
              (AnnotatedDeclaredType) functionalInterface,
              functionTypeReturnType);
      return overrideChecker.checkOverride();
    } else {
      // If the functionalInterface is not a declared type, it must be an uninferred wildcard.
      // In that case, only return false if uninferred type arguments should not be ignored.
      return !atypeFactory.ignoreUninferredTypeArguments;
    }
  }

  /** Check if method reference type argument inference is required. Issue an error if it is. */
  private boolean checkMethodReferenceInference(
      MemberReferenceTree memberReferenceTree,
      AnnotatedExecutableType invocationType,
      AnnotatedTypeMirror type) {
    // TODO: Issue #802
    // TODO: https://github.com/typetools/checker-framework/issues/802
    // TODO: Method type argument inference
    // TODO: Enable checks for method reference with inferred type arguments.
    // For now, error on mismatch of class or method type arguments.
    boolean requiresInference = false;
    // If the function to which the member reference refers is generic, but the member
    // reference does not provide method type arguments, then Java 8 inference is required.
    // Issue 979.
    if (!invocationType.getTypeVariables().isEmpty()
        && (memberReferenceTree.getTypeArguments() == null
            || memberReferenceTree.getTypeArguments().isEmpty())) {
      // Method type args
      requiresInference = true;
    } else if (memberReferenceTree.getMode() == ReferenceMode.NEW) {
      if (type.getKind() == TypeKind.DECLARED && ((AnnotatedDeclaredType) type).wasRaw()) {
        // Class type args
        requiresInference = true;
      }
    }
    if (requiresInference) {
      if (checker.hasOption("conservativeUninferredTypeArguments")) {
        checker.reportWarning(memberReferenceTree, "methodref.inference.unimplemented");
      }
      return true;
    }
    return false;
  }

  /**
   * Class to perform method override and method reference checks.
   *
   * <p>Method references are checked similarly to method overrides, with the method reference
   * viewed as overriding the functional interface's method.
   *
   * <p>Checks that an overriding method's return type, parameter types, and receiver type are
   * correct with respect to the annotations on the overridden method's return type, parameter
   * types, and receiver type.
   *
   * <p>Furthermore, any contracts on the method must satisfy behavioral subtyping, that is,
   * postconditions must be at least as strong as the postcondition on the superclass, and
   * preconditions must be at most as strong as the condition on the superclass.
   *
   * <p>This method returns the result of the check, but also emits error messages as a side effect.
   */
  public class OverrideChecker {

    /** The declaration of an overriding method. */
    protected final Tree overriderTree;
    /** True if {@link #overriderTree} is a MEMBER_REFERENCE. */
    protected final boolean isMethodReference;

    /** The type of the overriding method. */
    protected final AnnotatedExecutableType overrider;
    /** The subtype that declares the overriding method. */
    protected final AnnotatedTypeMirror overriderType;
    /** The type of the overridden method. */
    protected final AnnotatedExecutableType overridden;
    /** The supertype that declares the overridden method. */
    protected final AnnotatedDeclaredType overriddenType;
    /** The teturn type of the overridden method. */
    protected final AnnotatedTypeMirror overriddenReturnType;
    /** The return type of the overriding method. */
    protected final AnnotatedTypeMirror overriderReturnType;

    /**
     * Create an OverrideChecker.
     *
     * <p>Notice that the return types are passed in separately. This is to support some types of
     * method references where the overrider's return type is not the appropriate type to check.
     *
     * @param overriderTree the AST node of the overriding method or method reference
     * @param overrider the type of the overriding method
     * @param overriderType the type enclosing the overrider method, usually an
     *     AnnotatedDeclaredType; for Method References may be something else
     * @param overriderReturnType the return type of the overriding method
     * @param overridden the type of the overridden method
     * @param overriddenType the declared type enclosing the overridden method
     * @param overriddenReturnType the return type of the overridden method
     */
    public OverrideChecker(
        Tree overriderTree,
        AnnotatedExecutableType overrider,
        AnnotatedTypeMirror overriderType,
        AnnotatedTypeMirror overriderReturnType,
        AnnotatedExecutableType overridden,
        AnnotatedDeclaredType overriddenType,
        AnnotatedTypeMirror overriddenReturnType) {

      this.overriderTree = overriderTree;
      this.overrider = overrider;
      this.overriderType = overriderType;
      this.overridden = overridden;
      this.overriddenType = overriddenType;
      this.overriddenReturnType = overriddenReturnType;
      this.overriderReturnType = overriderReturnType;

      this.isMethodReference = overriderTree.getKind() == Tree.Kind.MEMBER_REFERENCE;
    }

    /**
     * Perform the check.
     *
     * @return true if the override is allowed
     */
    public boolean checkOverride() {
      if (checker.shouldSkipUses(overriddenType.getUnderlyingType().asElement())) {
        return true;
      }

      boolean result = checkReturn();
      result &= checkParameters();
      if (isMethodReference) {
        result &= checkMemberReferenceReceivers();
      } else {
        result &= checkReceiverOverride();
      }
      checkPreAndPostConditions();
      checkPurity();

      return result;
    }

    /** Check that an override respects purity. */
    private void checkPurity() {
      String msgKey = isMethodReference ? "purity.methodref" : "purity.overriding";

      // check purity annotations
      EnumSet<Pure.Kind> superPurity =
          PurityUtils.getPurityKinds(atypeFactory, overridden.getElement());
      EnumSet<Pure.Kind> subPurity =
          PurityUtils.getPurityKinds(atypeFactory, overrider.getElement());
      if (!subPurity.containsAll(superPurity)) {
        checker.reportError(
            overriderTree,
            msgKey,
            overriderType,
            overrider,
            overriddenType,
            overridden,
            subPurity,
            superPurity);
      }
    }

    /** Checks that overrides obey behavioral subtyping. */
    private void checkPreAndPostConditions() {
      String msgKey = isMethodReference ? "methodref" : "override";
      if (isMethodReference) {
        // TODO: Support postconditions and method references.
        // The parse context always expects instance methods, but method references can be static.
        return;
      }

      ContractsFromMethod contractsUtils = atypeFactory.getContractsFromMethod();

      // Check preconditions
      Set<Precondition> superPre = contractsUtils.getPreconditions(overridden.getElement());
      Set<Precondition> subPre = contractsUtils.getPreconditions(overrider.getElement());
      Set<Pair<JavaExpression, AnnotationMirror>> superPre2 =
          parseAndLocalizeContracts(superPre, overridden);
      Set<Pair<JavaExpression, AnnotationMirror>> subPre2 =
          parseAndLocalizeContracts(subPre, overrider);
      @SuppressWarnings("compilermessages")
      @CompilerMessageKey String premsg = "contracts.precondition." + msgKey;
      checkContractsSubset(overriderType, overriddenType, subPre2, superPre2, premsg);

      // Check postconditions
      Set<Postcondition> superPost = contractsUtils.getPostconditions(overridden.getElement());
      Set<Postcondition> subPost = contractsUtils.getPostconditions(overrider.getElement());
      Set<Pair<JavaExpression, AnnotationMirror>> superPost2 =
          parseAndLocalizeContracts(superPost, overridden);
      Set<Pair<JavaExpression, AnnotationMirror>> subPost2 =
          parseAndLocalizeContracts(subPost, overrider);
      @SuppressWarnings("compilermessages")
      @CompilerMessageKey String postmsg = "contracts.postcondition." + msgKey;
      checkContractsSubset(overriderType, overriddenType, superPost2, subPost2, postmsg);

      // Check conditional postconditions
      Set<ConditionalPostcondition> superCPost =
          contractsUtils.getConditionalPostconditions(overridden.getElement());
      Set<ConditionalPostcondition> subCPost =
          contractsUtils.getConditionalPostconditions(overrider.getElement());
      // consider only 'true' postconditions
      Set<Postcondition> superCPostTrue = filterConditionalPostconditions(superCPost, true);
      Set<Postcondition> subCPostTrue = filterConditionalPostconditions(subCPost, true);
      Set<Pair<JavaExpression, AnnotationMirror>> superCPostTrue2 =
          parseAndLocalizeContracts(superCPostTrue, overridden);
      Set<Pair<JavaExpression, AnnotationMirror>> subCPostTrue2 =
          parseAndLocalizeContracts(subCPostTrue, overrider);
      @SuppressWarnings("compilermessages")
      @CompilerMessageKey String posttruemsg = "contracts.conditional.postcondition.true." + msgKey;
      checkContractsSubset(
          overriderType, overriddenType, superCPostTrue2, subCPostTrue2, posttruemsg);

      // consider only 'false' postconditions
      Set<Postcondition> superCPostFalse = filterConditionalPostconditions(superCPost, false);
      Set<Postcondition> subCPostFalse = filterConditionalPostconditions(subCPost, false);
      Set<Pair<JavaExpression, AnnotationMirror>> superCPostFalse2 =
          parseAndLocalizeContracts(superCPostFalse, overridden);
      Set<Pair<JavaExpression, AnnotationMirror>> subCPostFalse2 =
          parseAndLocalizeContracts(subCPostFalse, overrider);
      @SuppressWarnings("compilermessages")
      @CompilerMessageKey String postfalsemsg = "contracts.conditional.postcondition.false." + msgKey;
      checkContractsSubset(
          overriderType, overriddenType, superCPostFalse2, subCPostFalse2, postfalsemsg);
    }

    private boolean checkMemberReferenceReceivers() {
      JCTree.JCMemberReference memberTree = (JCTree.JCMemberReference) overriderTree;

      if (overriderType.getKind() == TypeKind.ARRAY) {
        // Assume the receiver for all method on arrays are @Top
        // This simplifies some logic because an AnnotatedExecutableType for an array method
        // (ie String[]::clone) has a receiver of "Array." The UNBOUND check would then
        // have to compare "Array" to "String[]".
        return true;
      }

      // These act like a traditional override
      if (memberTree.kind == JCTree.JCMemberReference.ReferenceKind.UNBOUND) {
        AnnotatedTypeMirror overriderReceiver = overrider.getReceiverType();
        AnnotatedTypeMirror overriddenReceiver = overridden.getParameterTypes().get(0);
        boolean success =
            atypeFactory.getTypeHierarchy().isSubtype(overriddenReceiver, overriderReceiver);
        if (!success) {
          checker.reportError(
              overriderTree,
              "methodref.receiver",
              overriderReceiver,
              overriddenReceiver,
              overriderType,
              overrider,
              overriddenType,
              overridden);
        }
        return success;
      }

      // The rest act like method invocations
      AnnotatedTypeMirror receiverDecl;
      AnnotatedTypeMirror receiverArg;
      switch (memberTree.kind) {
        case UNBOUND:
          throw new BugInCF("Case UNBOUND should already be handled.");
        case SUPER:
          receiverDecl = overrider.getReceiverType();
          receiverArg = atypeFactory.getAnnotatedType(memberTree.getQualifierExpression());

          final AnnotatedTypeMirror selfType = atypeFactory.getSelfType(memberTree);
          receiverArg.replaceAnnotations(selfType.getAnnotations());
          break;
        case BOUND:
          receiverDecl = overrider.getReceiverType();
          receiverArg = overriderType;
          break;
        case IMPLICIT_INNER:
          // JLS 15.13.1 "It is a compile-time error if the method reference expression is
          // of the form ClassType :: [TypeArguments] new and a compile-time error would
          // occur when determining an enclosing instance for ClassType as specified in
          // 15.9.2 (treating the method reference expression as if it were an unqualified
          // class instance creation expression)."

          // So a member reference can only refer to an inner class constructor if a type
          // that encloses the inner class can be found. So either "this" is that
          // enclosing type or "this" has an enclosing type that is that type.
          receiverDecl = overrider.getReceiverType();
          receiverArg = atypeFactory.getSelfType(memberTree);
          while (!TypesUtils.isErasedSubtype(
              receiverArg.getUnderlyingType(), receiverDecl.getUnderlyingType(), types)) {
            receiverArg = ((AnnotatedDeclaredType) receiverArg).getEnclosingType();
          }

          break;
        case TOPLEVEL:
        case STATIC:
        case ARRAY_CTOR:
        default:
          // Intentional fallthrough
          // These don't have receivers
          return true;
      }

      boolean success = atypeFactory.getTypeHierarchy().isSubtype(receiverArg, receiverDecl);
      if (!success) {
        checker.reportError(
            overriderTree,
            "methodref.receiver.bound",
            receiverArg,
            receiverDecl,
            receiverArg,
            overriderType,
            overrider);
      }

      return success;
    }

    /**
     * Issue an "override.receiver" error if the receiver override is not valid.
     *
     * @return true if the override is legal
     */
    protected boolean checkReceiverOverride() {
      AnnotatedDeclaredType overriderReceiver = overrider.getReceiverType();
      AnnotatedDeclaredType overriddenReceiver = overridden.getReceiverType();
      QualifierHierarchy qualifierHierarchy = atypeFactory.getQualifierHierarchy();
      // Check the receiver type.
      // isSubtype() requires its arguments to be actual subtypes with respect to JLS, but overrider
      // receiver is not a subtype of the overridden receiver.  So, just check primary annotations.
      // TODO: this will need to be improved for generic receivers.
      Set<AnnotationMirror> overriderAnnos = overriderReceiver.getAnnotations();
      Set<AnnotationMirror> overriddenAnnos = overriddenReceiver.getAnnotations();
      if (!qualifierHierarchy.isSubtype(overriddenAnnos, overriderAnnos)) {
        Set<AnnotationMirror> declaredAnnos =
            atypeFactory.getTypeDeclarationBounds(overriderType.getUnderlyingType());
        if (qualifierHierarchy.isSubtype(overriderAnnos, declaredAnnos)
            && qualifierHierarchy.isSubtype(declaredAnnos, overriderAnnos)) {
          // All the type of an object must be no higher than its upper bound. So if the receiver is
          // annotated with the upper bound qualifiers, then the override is safe.
          return true;
        }
        FoundRequired pair = FoundRequired.of(overriderReceiver, overriddenReceiver);
        checker.reportError(
            overriderTree,
            "override.receiver",
            pair.found,
            pair.required,
            overriderType,
            overrider,
            overriddenType,
            overridden);
        return false;
      }
      return true;
    }

    private boolean checkParameters() {
      List<AnnotatedTypeMirror> overriderParams = overrider.getParameterTypes();
      List<AnnotatedTypeMirror> overriddenParams = overridden.getParameterTypes();

      // Fix up method reference parameters.
      // See https://docs.oracle.com/javase/specs/jls/se11/html/jls-15.html#jls-15.13.1
      if (isMethodReference) {
        // The functional interface of an unbound member reference has an extra parameter
        // (the receiver).
        if (((JCTree.JCMemberReference) overriderTree)
            .hasKind(JCTree.JCMemberReference.ReferenceKind.UNBOUND)) {
          overriddenParams = new ArrayList<>(overriddenParams);
          overriddenParams.remove(0);
        }
        // Deal with varargs
        if (overrider.isVarArgs() && !overridden.isVarArgs()) {
          overriderParams = AnnotatedTypes.expandVarArgsFromTypes(overrider, overriddenParams);
        }
      }

      boolean result = true;
      for (int i = 0; i < overriderParams.size(); ++i) {
        boolean success =
            atypeFactory
                .getTypeHierarchy()
                .isSubtype(overriddenParams.get(i), overriderParams.get(i));
        if (!success) {
          success = testTypevarContainment(overriddenParams.get(i), overriderParams.get(i));
        }

        checkParametersMsg(success, i, overriderParams, overriddenParams);
        result &= success;
      }
      return result;
    }

    private void checkParametersMsg(
        boolean success,
        int index,
        List<AnnotatedTypeMirror> overriderParams,
        List<AnnotatedTypeMirror> overriddenParams) {
      if (success && !showchecks) {
        return;
      }

      String msgKey = isMethodReference ? "methodref.param" : "override.param";
      long valuePos =
          overriderTree instanceof MethodTree
              ? positions.getStartPosition(
                  root, ((MethodTree) overriderTree).getParameters().get(index))
              : positions.getStartPosition(root, overriderTree);
      Tree posTree =
          overriderTree instanceof MethodTree
              ? ((MethodTree) overriderTree).getParameters().get(index)
              : overriderTree;

      if (showchecks) {
        System.out.printf(
            " %s (line %3d):%n"
                + "     overrider: %s %s (parameter %d type %s)%n"
                + "   overridden: %s %s"
                + " (parameter %d type %s)%n",
            (success
                ? "success: overridden parameter type is subtype of overriding"
                : "FAILURE: overridden parameter type is not subtype of overriding"),
            (root.getLineMap() != null ? root.getLineMap().getLineNumber(valuePos) : -1),
            overrider,
            overriderType,
            index,
            overriderParams.get(index).toString(),
            overridden,
            overriddenType,
            index,
            overriddenParams.get(index).toString());
      }
      if (!success) {
        FoundRequired pair =
            FoundRequired.of(overriderParams.get(index), overriddenParams.get(index));
        checker.reportError(
            posTree,
            msgKey,
            overrider.getElement().getParameters().get(index).toString(),
            pair.found,
            pair.required,
            overriderType,
            overrider,
            overriddenType,
            overridden);
      }
    }

    /**
     * Returns true if the return type of the overridden method is a subtype of the return type of
     * the overriding method.
     *
     * @return true if the return type is correct
     */
    private boolean checkReturn() {
      if ((overriderReturnType.getKind() == TypeKind.VOID)) {
        // Nothing to check.
        return true;
      }
      final TypeHierarchy typeHierarchy = atypeFactory.getTypeHierarchy();
      boolean success = typeHierarchy.isSubtype(overriderReturnType, overriddenReturnType);
      if (!success) {
        // If both the overridden method have type variables as return types and both
        // types were defined in their respective methods then, they can be covariant or
        // invariant use super/subtypes for the overrides locations
        success = testTypevarContainment(overriderReturnType, overriddenReturnType);
      }

      // Sometimes the overridden return type of a method reference becomes a captured
      // type.  This leads to defaulting that often makes the overriding return type
      // invalid.  We ignore these.  This happens in Issue403/Issue404.
      if (!success
          && isMethodReference
          && TypesUtils.isCaptured(overriddenReturnType.getUnderlyingType())) {
        if (ElementUtils.isMethod(
            overridden.getElement(), functionApply, atypeFactory.getProcessingEnv())) {
          success =
              typeHierarchy.isSubtype(
                  overriderReturnType,
                  ((AnnotatedTypeVariable) overriddenReturnType).getUpperBound());
        }
      }

      checkReturnMsg(success);
      return success;
    }

    /**
     * Issue an error message or log message about checking an overriding return type.
     *
     * @param success whether the check succeeded or failed
     */
    private void checkReturnMsg(boolean success) {
      if (success && !showchecks) {
        return;
      }

      String msgKey = isMethodReference ? "methodref.return" : "override.return";
      long valuePos =
          overriderTree instanceof MethodTree
              ? positions.getStartPosition(root, ((MethodTree) overriderTree).getReturnType())
              : positions.getStartPosition(root, overriderTree);
      Tree posTree =
          overriderTree instanceof MethodTree
              ? ((MethodTree) overriderTree).getReturnType()
              : overriderTree;
      // The return type of a MethodTree is null for a constructor.
      if (posTree == null) {
        posTree = overriderTree;
      }

      if (showchecks) {
        System.out.printf(
            " %s (line %3d):%n"
                + "     overrider: %s %s (return type %s)%n"
                + "   overridden: %s %s (return type %s)%n",
            (success
                ? "success: overriding return type is subtype of overridden"
                : "FAILURE: overriding return type is not subtype of overridden"),
            (root.getLineMap() != null ? root.getLineMap().getLineNumber(valuePos) : -1),
            overrider,
            overriderType,
            overrider.getReturnType().toString(),
            overridden,
            overriddenType,
            overridden.getReturnType().toString());
      }
      if (!success) {
        FoundRequired pair = FoundRequired.of(overriderReturnType, overriddenReturnType);
        checker.reportError(
            posTree,
            msgKey,
            pair.found,
            pair.required,
            overriderType,
            overrider,
            overriddenType,
            overridden);
      }
    }
  }

  /**
   * Filters the set of conditional postconditions to return only those whose annotation result
   * value matches the value of the given boolean {@code b}. For example, if {@code b == true}, then
   * the following {@code @EnsuresNonNullIf} conditional postcondition would match:<br>
   * {@code @EnsuresNonNullIf(expression="#1", result=true)}<br>
   * {@code boolean equals(@Nullable Object o)}
   *
   * @param conditionalPostconditions each is a ConditionalPostcondition
   * @param b the value required for the {@code result} element
   * @return all the given conditional postconditions whose {@code result} is {@code b}
   */
  private Set<Postcondition> filterConditionalPostconditions(
      Set<ConditionalPostcondition> conditionalPostconditions, boolean b) {
    if (conditionalPostconditions.isEmpty()) {
      return Collections.emptySet();
    }

    Set<Postcondition> result = new LinkedHashSet<>(conditionalPostconditions.size());
    for (Contract c : conditionalPostconditions) {
      ConditionalPostcondition p = (ConditionalPostcondition) c;
      if (p.resultValue == b) {
        result.add(new Postcondition(p.expressionString, p.annotation, p.contractAnnotation));
      }
    }
    return result;
  }

  /**
   * Checks that {@code mustSubset} is a subset of {@code set} in the following sense: For every
   * expression in {@code mustSubset} there must be the same expression in {@code set}, with the
   * same (or a stronger) annotation.
   *
   * <p>This uses field {@link #visitorState} to determine where to issue an error message.
   *
   * @param overriderType the subtype
   * @param overriddenType the supertype
   * @param mustSubset annotations that should be weaker
   * @param set anontations that should be stronger
   * @param messageKey message key for error messages
   */
  private void checkContractsSubset(
      AnnotatedTypeMirror overriderType,
      AnnotatedDeclaredType overriddenType,
      Set<Pair<JavaExpression, AnnotationMirror>> mustSubset,
      Set<Pair<JavaExpression, AnnotationMirror>> set,
      @CompilerMessageKey String messageKey) {
    for (Pair<JavaExpression, AnnotationMirror> weak : mustSubset) {
      boolean found = false;

      for (Pair<JavaExpression, AnnotationMirror> strong : set) {
        // are we looking at a contract of the same receiver?
        if (weak.first.equals(strong.first)) {
          // check subtyping relationship of annotations
          QualifierHierarchy qualifierHierarchy = atypeFactory.getQualifierHierarchy();
          if (qualifierHierarchy.isSubtype(strong.second, weak.second)) {
            found = true;
            break;
          }
        }
      }

      if (!found) {
        MethodTree methodDeclTree = visitorState.getMethodTree();

        String overriddenTypeString = overriddenType.getUnderlyingType().asElement().toString();
        String overriderTypeString;
        if (overriderType.getKind() == TypeKind.DECLARED) {
          DeclaredType overriderTypeMirror =
              ((AnnotatedDeclaredType) overriderType).getUnderlyingType();
          overriderTypeString = overriderTypeMirror.asElement().toString();
        } else {
          overriderTypeString = overriderType.toString();
        }

        // weak.second is the AnnotationMirror that is too strong.  It might be from the
        // precondition or the postcondition.

        // These are the annotations that are too weak.
        StringJoiner strongRelevantAnnos = new StringJoiner(" ").setEmptyValue("no information");
        for (Pair<JavaExpression, AnnotationMirror> strong : set) {
          if (weak.first.equals(strong.first)) {
            strongRelevantAnnos.add(strong.second.toString());
          }
        }

        Object overriddenAnno;
        Object overriderAnno;
        if (messageKey.contains(".precondition.")) {
          overriddenAnno = strongRelevantAnnos;
          overriderAnno = weak.second;
        } else {
          overriddenAnno = weak.second;
          overriderAnno = strongRelevantAnnos;
        }

        checker.reportError(
            methodDeclTree,
            messageKey,
            weak.first,
            methodDeclTree.getName(),
            overriddenTypeString,
            overriddenAnno,
            overriderTypeString,
            overriderAnno);
      }
    }
  }

  /**
   * Localizes some contracts -- that is, viewpoint-adapts them to some method body, according to
   * the value of {@link #visitorState}.
   *
   * <p>The input is a set of {@link Contract}s, each of which contains an expression string and an
   * annotation. In a {@link Contract}, Java expressions are exactly as written in source code, not
   * standardized or viewpoint-adapted.
   *
   * <p>The output is a set of pairs of {@link JavaExpression} (parsed expression string) and
   * standardized annotation (with respect to the path of {@link #visitorState}. This method
   * discards any contract whose expression cannot be parsed into a JavaExpression.
   *
   * @param contractSet a set of contracts
   * @param methodType the type of the method that the contracts are for
   * @return pairs of (expression, AnnotationMirror), which are localized contracts
   */
  private Set<Pair<JavaExpression, AnnotationMirror>> parseAndLocalizeContracts(
      Set<? extends Contract> contractSet, AnnotatedExecutableType methodType) {
    if (contractSet.isEmpty()) {
      return Collections.emptySet();
    }

    // This is the path to a place where the contract is being used, which might or might not be
    // where the contract was defined.  For example, methodTree might be an overriding
    // definition, and the contract might be for a superclass.
    MethodTree methodTree = visitorState.getMethodTree();

    StringToJavaExpression stringToJavaExpr =
        expression -> {
          JavaExpression javaExpr =
              StringToJavaExpression.atMethodDecl(expression, methodType.getElement(), checker);
          // methodType.getElement() is not necessarily the same method as methodTree, so
          // viewpoint-adapt it to methodTree.
          return javaExpr.atMethodBody(methodTree);
        };

    Set<Pair<JavaExpression, AnnotationMirror>> result = new HashSet<>(contractSet.size());
    for (Contract p : contractSet) {
      String expressionString = p.expressionString;
      AnnotationMirror annotation =
          p.viewpointAdaptDependentTypeAnnotation(atypeFactory, stringToJavaExpr, methodTree);
      JavaExpression exprJe;
      try {
        // TODO: currently, these expressions are parsed many times.
        // This could be optimized to store the result the first time.
        // (same for other annotations)
        exprJe = stringToJavaExpr.toJavaExpression(expressionString);
      } catch (JavaExpressionParseException e) {
        // report errors here
        checker.report(methodTree, e.getDiagMessage());
        continue;
      }
      result.add(Pair.of(exprJe, annotation));
    }
    return result;
  }

  /**
   * Call this only when the current path is an identifier.
   *
   * @return the enclosing member select, or null if the identifier is not the field in a member
   *     selection
   */
  protected MemberSelectTree enclosingMemberSelect() {
    TreePath path = this.getCurrentPath();
    assert path.getLeaf().getKind() == Tree.Kind.IDENTIFIER
        : "expected identifier, found: " + path.getLeaf();
    if (path.getParentPath().getLeaf().getKind() == Tree.Kind.MEMBER_SELECT) {
      return (MemberSelectTree) path.getParentPath().getLeaf();
    } else {
      return null;
    }
  }

  /**
   * Returns the statement that encloses the given one.
   *
   * @param tree an AST node that is on the current path
   * @return the statement that encloses the given one
   */
  protected Tree enclosingStatement(@FindDistinct Tree tree) {
    TreePath path = this.getCurrentPath();
    while (path != null && path.getLeaf() != tree) {
      path = path.getParentPath();
    }

    if (path != null) {
      return path.getParentPath().getLeaf();
    } else {
      return null;
    }
  }

  @Override
  public Void visitIdentifier(IdentifierTree node, Void p) {
    checkAccess(node, p);
    return super.visitIdentifier(node, p);
  }

  protected void checkAccess(IdentifierTree node, Void p) {
    MemberSelectTree memberSel = enclosingMemberSelect();
    ExpressionTree tree;
    Element elem;

    if (memberSel == null) {
      tree = node;
      elem = TreeUtils.elementFromUse(node);
    } else {
      tree = memberSel;
      elem = TreeUtils.elementFromUse(memberSel);
    }

    if (elem == null || !elem.getKind().isField()) {
      return;
    }

    AnnotatedTypeMirror receiver = atypeFactory.getReceiverType(tree);

    checkAccessAllowed(elem, receiver, tree);
  }

  /**
   * Issues an error if access not allowed, based on an @Unused annotation.
   *
   * @param field the field to be accessed, whose declaration might be annotated by @Unused. It can
   *     also be (for example) {@code this}, in which case {@code receiverType} is null.
   * @param receiverType the type of the expression whose field is accessed; null if the field is
   *     static
   * @param accessTree the access expression
   */
  protected void checkAccessAllowed(
      Element field, AnnotatedTypeMirror receiverType, @FindDistinct ExpressionTree accessTree) {
    AnnotationMirror unused = atypeFactory.getDeclAnnotation(field, Unused.class);
    if (unused == null) {
      return;
    }

    String when = AnnotationUtils.getElementValueClassName(unused, unusedWhenElement).toString();

    // TODO: Don't just look at the receiver type, but at the declaration annotations on the
    // receiver.  (That will enable handling type annotations that are not part of the type
    // system being checked.)

    // TODO: This requires exactly the same type qualifier, but it should permit subqualifiers.
    if (!AnnotationUtils.containsSameByName(receiverType.getAnnotations(), when)) {
      return;
    }

    Tree tree = this.enclosingStatement(accessTree);

    if (tree != null
        && tree.getKind() == Tree.Kind.ASSIGNMENT
        && ((AssignmentTree) tree).getVariable() == accessTree
        && ((AssignmentTree) tree).getExpression().getKind() == Tree.Kind.NULL_LITERAL) {
      // Assigning unused to null is OK.
      return;
    }

    checker.reportError(accessTree, "unallowed.access", field, receiverType);
  }

  /**
   * Tests that the qualifiers present on {@code useType} are valid qualifiers, given the qualifiers
   * on the declaration of the type, {@code declarationType}.
   *
   * <p>The check is shallow, as it does not descend into generic or array types (i.e. only
   * performing the validity check on the raw type or outermost array dimension). {@link
   * BaseTypeVisitor#validateTypeOf(Tree)} would call this for each type argument or array dimension
   * separately.
   *
   * <p>In most cases, {@code useType} simply needs to be a subtype of {@code declarationType}. If a
   * type system makes exceptions to this rule, its implementation should override this method.
   *
   * <p>This method is not called if {@link
   * BaseTypeValidator#shouldCheckTopLevelDeclaredOrPrimitiveType(AnnotatedTypeMirror, Tree)}
   * returns false -- by default, it is not called on the top level for locals and expressions. To
   * enforce a type validity property everywhere, override methods such as {@link
   * BaseTypeValidator#visitDeclared} rather than this method.
   *
   * @param declarationType the type of the class (TypeElement)
   * @param useType the use of the class (instance type)
   * @param tree the tree where the type is used
   * @return true if the useType is a valid use of elemType
   */
  public boolean isValidUse(
      AnnotatedDeclaredType declarationType, AnnotatedDeclaredType useType, Tree tree) {
    // Don't use isSubtype(ATM, ATM) because it will return false if the types have qualifier
    // parameters.
    Set<? extends AnnotationMirror> tops = atypeFactory.getQualifierHierarchy().getTopAnnotations();
    Set<AnnotationMirror> upperBounds =
        atypeFactory
            .getQualifierUpperBounds()
            .getBoundQualifiers(declarationType.getUnderlyingType());
    for (AnnotationMirror top : tops) {
      AnnotationMirror upperBound =
          atypeFactory.getQualifierHierarchy().findAnnotationInHierarchy(upperBounds, top);
      AnnotationMirror qualifier = useType.getAnnotationInHierarchy(top);
      if (!atypeFactory.getQualifierHierarchy().isSubtype(qualifier, upperBound)) {
        return false;
      }
    }
    return true;
  }

  /**
   * Tests that the qualifiers present on the primitive type are valid.
   *
   * @param type the use of the primitive type
   * @param tree the tree where the type is used
   * @return true if the type is a valid use of the primitive type
   */
  public boolean isValidUse(AnnotatedPrimitiveType type, Tree tree) {
    Set<AnnotationMirror> bounds = atypeFactory.getTypeDeclarationBounds(type.getUnderlyingType());
    return atypeFactory.getQualifierHierarchy().isSubtype(type.getAnnotations(), bounds);
  }

  /**
   * Tests that the qualifiers present on the array type are valid. This method will be invoked for
   * each array level independently, i.e. this method only needs to check the top-level qualifiers
   * of an array.
   *
   * @param type the array type use
   * @param tree the tree where the type is used
   * @return true if the type is a valid array type
   */
  public boolean isValidUse(AnnotatedArrayType type, Tree tree) {
    Set<AnnotationMirror> bounds = atypeFactory.getTypeDeclarationBounds(type.getUnderlyingType());
    return atypeFactory.getQualifierHierarchy().isSubtype(type.getAnnotations(), bounds);
  }

  /**
   * Tests whether the tree expressed by the passed type tree is a valid type, and emits an error if
   * that is not the case (e.g. '@Mutable String'). If the tree is a method or constructor, check
   * the return type.
   *
   * @param tree the AST type supplied by the user
   */
  public boolean validateTypeOf(Tree tree) {
    AnnotatedTypeMirror type;
    // It's quite annoying that there is no TypeTree.
    switch (tree.getKind()) {
      case PRIMITIVE_TYPE:
      case PARAMETERIZED_TYPE:
      case TYPE_PARAMETER:
      case ARRAY_TYPE:
      case UNBOUNDED_WILDCARD:
      case EXTENDS_WILDCARD:
      case SUPER_WILDCARD:
      case ANNOTATED_TYPE:
        type = atypeFactory.getAnnotatedTypeFromTypeTree(tree);
        break;
      case METHOD:
        type = atypeFactory.getMethodReturnType((MethodTree) tree);
        if (type == null || type.getKind() == TypeKind.VOID) {
          // Nothing to do for void methods.
          // Note that for a constructor the AnnotatedExecutableType does
          // not use void as return type.
          return true;
        }
        break;
      default:
        type = atypeFactory.getAnnotatedType(tree);
    }
    return validateType(tree, type);
  }

  /**
   * Tests whether the type and corresponding type tree is a valid type, and emits an error if that
   * is not the case (e.g. '@Mutable String'). If the tree is a method or constructor, check the
   * return type.
   *
   * @param tree the type tree supplied by the user
   * @param type the type corresponding to tree
   * @return true if the type is valid
   */
  protected boolean validateType(Tree tree, AnnotatedTypeMirror type) {
    return typeValidator.isValid(type, tree);
  }

  // This is a test to ensure that all types are valid
  protected final TypeValidator typeValidator;

  protected TypeValidator createTypeValidator() {
    return new BaseTypeValidator(checker, this, atypeFactory);
  }

  // **********************************************************************
  // Random helper methods
  // **********************************************************************

  /**
   * Tests whether the expression should not be checked because of the tree referring to unannotated
   * classes, as specified in the {@code checker.skipUses} property.
   *
   * <p>It returns true if exprTree is a method invocation or a field access to a class whose
   * qualified name matches @{link checker.skipUses} expression.
   *
   * @param exprTree any expression tree
   * @return true if checker should not test exprTree
   */
  protected final boolean shouldSkipUses(ExpressionTree exprTree) {
    // System.out.printf("shouldSkipUses: %s: %s%n", exprTree.getClass(), exprTree);

    Element elm = TreeUtils.elementFromTree(exprTree);
    return checker.shouldSkipUses(elm);
  }

  // **********************************************************************
  // Overriding to avoid visit part of the tree
  // **********************************************************************

  /** Override Compilation Unit so we won't visit package names or imports. */
  @Override
  public Void visitCompilationUnit(CompilationUnitTree node, Void p) {
    Void r = scan(node.getPackageAnnotations(), p);
    // r = reduce(scan(node.getPackageName(), p), r);
    // r = reduce(scan(node.getImports(), p), r);
    r = reduce(scan(node.getTypeDecls(), p), r);
    return r;
  }
}
