package org.checkerframework.framework.type;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Types;
import org.checkerframework.checker.interning.qual.FindDistinct;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedArrayType;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedDeclaredType;
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.visitor.AbstractAtmComboVisitor;
import org.checkerframework.framework.util.AnnotatedTypes;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.TypesUtils;

/**
 * Implements asSuper {@link AnnotatedTypes#asSuper(AnnotatedTypeFactory, AnnotatedTypeMirror,
 * AnnotatedTypeMirror)}.
 */
public class AsSuperVisitor extends AbstractAtmComboVisitor<AnnotatedTypeMirror, Void> {

  /** Type utilities. */
  private final Types types;
  /** The type factory. */
  private final AnnotatedTypeFactory atypeFactory;
  /**
   * Whether or not the type being visited is an uninferred type argument. If true, then the
   * underlying type may not have the correct relationship with the supertype.
   */
  private boolean isUninferredTypeArgument = false;

  /**
   * Create a new AsSuperVisitor.
   *
   * @param atypeFactory the type factory
   */
  public AsSuperVisitor(AnnotatedTypeFactory atypeFactory) {
    this.atypeFactory = atypeFactory;
    types = atypeFactory.types;
  }

  /**
   * Implements asSuper. See {@link AnnotatedTypes#asSuper(AnnotatedTypeFactory,
   * AnnotatedTypeMirror, AnnotatedTypeMirror)} for details.
   *
   * @param <T> the type of the supertype
   * @param type type from which to copy annotations
   * @param superType a type whose erased Java type is a supertype of {@code type}'s erased Java
   *     type.
   * @return a copy of {@code superType} with annotations copied from {@code type} and type
   *     variables substituted from {@code type}.
   */
  @SuppressWarnings({
    "unchecked",
    "interning:not.interned" // optimized special case
  })
  public <T extends AnnotatedTypeMirror> T asSuper(AnnotatedTypeMirror type, T superType) {
    if (type == null || superType == null) {
      throw new BugInCF("AsSuperVisitor type and supertype cannot be null.");
    }

    if (type == superType) {
      return (T) type.deepCopy();
    }

    // This visitor modifies superType and may return type, so pass it copies so that the
    // parameters to asSuper are not changed and a copy is returned.
    AnnotatedTypeMirror copyType = type.deepCopy();
    AnnotatedTypeMirror copySuperType = superType.deepCopy();
    reset();
    AnnotatedTypeMirror result = visit(copyType, copySuperType, null);

    if (result == null) {
      throw new BugInCF(
          "AsSuperVisitor returned null.%ntype: %s%nsuperType: %s", type, copySuperType);
    }

    return (T) result;
  }

  private void reset() {
    isUninferredTypeArgument = false;
  }

  @Override
  public AnnotatedTypeMirror visit(
      AnnotatedTypeMirror type, AnnotatedTypeMirror superType, Void p) {
    ensurePrimaryIsCorrectForUnions(type);
    return super.visit(type, superType, p);
  }

  /**
   * The code in this class is assuming that the primary annotation of an {@link AnnotatedUnionType}
   * is the least upper bound of its alternatives. This method makes this assumption true.
   *
   * @param type any kind of {@code AnnotatedTypeMirror}
   */
  private void ensurePrimaryIsCorrectForUnions(AnnotatedTypeMirror type) {
    if (type.getKind() == TypeKind.UNION) {
      AnnotatedUnionType annotatedUnionType = (AnnotatedUnionType) type;
      Set<AnnotationMirror> lubs = null;
      for (AnnotatedDeclaredType altern : annotatedUnionType.getAlternatives()) {
        if (lubs == null) {
          lubs = altern.getAnnotations();
        } else {
          Set<AnnotationMirror> newLubs = AnnotationUtils.createAnnotationSet();
          for (AnnotationMirror lub : lubs) {
            AnnotationMirror anno = altern.getAnnotationInHierarchy(lub);
            newLubs.add(atypeFactory.getQualifierHierarchy().leastUpperBound(anno, lub));
          }
          lubs = newLubs;
        }
      }
      type.replaceAnnotations(lubs);
    }
  }

  @Override
  protected String defaultErrorMessage(
      AnnotatedTypeMirror type, AnnotatedTypeMirror superType, Void p) {
    return String.format(
        "AsSuperVisitor: Unexpected combination: type: %s superType: %s.%n"
            + "type: %s%nsuperType: %s",
        type.getKind(), superType.getKind(), type, superType);
  }

  private AnnotatedTypeMirror errorTypeNotErasedSubtypeOfSuperType(
      AnnotatedTypeMirror type, AnnotatedTypeMirror superType, Void p) {
    if (TypesUtils.isString(superType.getUnderlyingType())) {
      // Any type can be converted to String
      return visit(atypeFactory.getStringType(type), superType, p);
    }
    if (isUninferredTypeArgument) {
      return copyPrimaryAnnos(type, superType);
    }
    throw new BugInCF(
        "AsSuperVisitor: type is not an erased subtype of supertype." + "%ntype: %s%nsuperType: %s",
        type, superType);
  }

  private AnnotatedTypeMirror copyPrimaryAnnos(AnnotatedTypeMirror from, AnnotatedTypeMirror to) {
    // There may have been annotations added by a recursive call to asSuper, so replace existing
    // annotations
    to.replaceAnnotations(new ArrayList<>(from.getAnnotations()));
    // if to is a Typevar or Wildcard, then replaceAnnotations also sets primary annotations on
    // the bounds to from.getAnnotations()

    if (to.getKind() == TypeKind.UNION) {
      // Make sure that the alternatives have a primary annotations
      // Alternatives cannot have type arguments, so asSuper isn't called recursively
      AnnotatedUnionType unionType = (AnnotatedUnionType) to;
      for (AnnotatedDeclaredType altern : unionType.getAlternatives()) {
        altern.addMissingAnnotations(unionType.getAnnotations());
      }
    }
    return to;
  }

  /**
   * A helper method for asSuper(AMT, Wildcard) methods to use to annotate the wildcard's lower
   * bound.
   *
   * <p>If the lower bound of superType is Null, then return copyPrimarayAnnos(type, superType)
   *
   * <p>otherwise, return asSuper(type, superType.getLowerBound()
   *
   * <p>An error is issued if type is a Primitive or Wildcard -- those case are handled in
   * asSuper(Primitive, Wildcard) and asSuper(Wildcard, Wildcard)
   *
   * <p>An error is issued if the lower bound of superType is not Null and type is not a subtype of
   * the lower bound.
   */
  private AnnotatedTypeMirror asSuperWildcardLowerBound(
      AnnotatedTypeMirror type, AnnotatedWildcardType superType, Void p) {
    AnnotatedTypeMirror lowerBound = superType.getSuperBound();
    return asSuperLowerBound(type, p, lowerBound);
  }

  /** Same as #asSuperWildcardLowerBound, but for Typevars. */
  private AnnotatedTypeMirror asSuperTypevarLowerBound(
      AnnotatedTypeMirror type, AnnotatedTypeVariable superType, Void p) {
    AnnotatedTypeMirror lowerBound = superType.getLowerBound();
    return asSuperLowerBound(type, p, lowerBound);
  }

  private AnnotatedTypeMirror asSuperLowerBound(
      AnnotatedTypeMirror type, Void p, AnnotatedTypeMirror lowerBound) {
    if (lowerBound.getKind() == TypeKind.NULL) {
      Set<AnnotationMirror> typeLowerBound =
          AnnotatedTypes.findEffectiveLowerBoundAnnotations(
              atypeFactory.getQualifierHierarchy(), type);
      lowerBound.replaceAnnotations(typeLowerBound);
      return lowerBound;
    }
    if (areErasedJavaTypesEquivalent(type, lowerBound)) {
      return visit(type, lowerBound, p);
    }
    // If type and lowerBound are not the same type, then lowerBound is a subtype of type,
    // but there is no way to convert type to a subtype -- there is not an asSub method.  So,
    // just copy the primary annotations.
    return copyPrimaryAnnos(type, lowerBound);
  }

  /**
   * Returns true if the underlying, erased Java type of {@code subtype} is a subtype of the
   * underlying, erased Java type of {@code supertype}.
   *
   * @param subtype a type
   * @param supertype a type
   * @return true if the underlying, erased Java type of {@code subtype} is a subtype of the
   *     underlying, erased Java type of {@code supertype}
   */
  private boolean isErasedJavaSubtype(
      AnnotatedDeclaredType subtype, AnnotatedDeclaredType supertype) {
    TypeMirror javaSubtype = types.erasure(subtype.getUnderlyingType());
    TypeMirror javaSupertype = types.erasure(supertype.getUnderlyingType());
    return types.isSubtype(javaSubtype, javaSupertype);
  }

  /**
   * Returns true if the underlying, erased Java type of {@code typeA} and {@code typeB} are
   * equivalent.
   *
   * @param typeA a type
   * @param typeB a type
   * @return true if the underlying, erased Java type of {@code typeA} and {@code typeB} are
   *     equivalent
   */
  private boolean areErasedJavaTypesEquivalent(
      AnnotatedTypeMirror typeA, AnnotatedTypeMirror typeB) {
    TypeMirror underlyingTypeA = types.erasure(typeA.getUnderlyingType());
    TypeMirror underlyingTypeB = types.erasure(typeB.getUnderlyingType());
    return types.isSameType(underlyingTypeA, underlyingTypeB);
  }

  // <editor-fold defaultstate="collapsed" desc="visitArray_Other methods">
  @Override
  public AnnotatedTypeMirror visitArray_Array(
      AnnotatedArrayType type, AnnotatedArrayType superType, Void p) {
    AnnotatedTypeMirror asSuperCT = visit(type.getComponentType(), superType.getComponentType(), p);
    superType.setComponentType(asSuperCT);
    return copyPrimaryAnnos(type, superType);
  }

  @Override
  public AnnotatedTypeMirror visitArray_Intersection(
      AnnotatedArrayType type, AnnotatedIntersectionType superType, Void p) {
    for (AnnotatedTypeMirror bounds : superType.getBounds()) {
      if (!(TypesUtils.isObject(bounds.getUnderlyingType())
          || TypesUtils.isDeclaredOfName(bounds.getUnderlyingType(), "java.lang.Cloneable")
          || TypesUtils.isDeclaredOfName(bounds.getUnderlyingType(), "java.io.Serializable"))) {
        return errorTypeNotErasedSubtypeOfSuperType(type, superType, p);
      }
      copyPrimaryAnnos(type, bounds);
    }
    return copyPrimaryAnnos(type, superType);
  }

  @Override
  public AnnotatedTypeMirror visitArray_Declared(
      AnnotatedArrayType type, AnnotatedDeclaredType superType, Void p) {

    TypeElement array = TypesUtils.getTypeElement(type.getUnderlyingType());
    TypeElement possibleArray = TypesUtils.getTypeElement(superType.getUnderlyingType());
    // If the TypeElements of type and superType are equal, then superType's underlyingType is
    // Array.class.  Array.class is the receiver of methods such as clone() of which an array
    // can be the receiver. (new int[].clone())
    boolean isArrayClass = array.equals(possibleArray);

    if (isArrayClass
        || TypesUtils.isObject(superType.getUnderlyingType())
        || TypesUtils.isDeclaredOfName(superType.getUnderlyingType(), "java.lang.Cloneable")
        || TypesUtils.isDeclaredOfName(superType.getUnderlyingType(), "java.io.Serializable")) {
      return copyPrimaryAnnos(type, superType);
    }
    return errorTypeNotErasedSubtypeOfSuperType(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitArray_Typevar(
      AnnotatedArrayType type, AnnotatedTypeVariable superType, Void p) {
    AnnotatedTypeMirror upperBound = visit(type, superType.getUpperBound(), p);
    superType.setUpperBound(upperBound);

    AnnotatedTypeMirror lowerBound = asSuperTypevarLowerBound(type, superType, p);
    superType.setLowerBound(lowerBound);

    return copyPrimaryAnnos(type, superType);
  }

  @Override
  public AnnotatedTypeMirror visitArray_Wildcard(
      AnnotatedArrayType type, AnnotatedWildcardType superType, Void p) {
    AnnotatedTypeMirror upperBound = visit(type, superType.getExtendsBound(), p);
    superType.setExtendsBound(upperBound);

    AnnotatedTypeMirror lowerBound = asSuperWildcardLowerBound(type, superType, p);
    superType.setSuperBound(lowerBound);

    return copyPrimaryAnnos(type, superType);
  }
  // </editor-fold>

  // <editor-fold defaultstate="collapsed" desc="visitDeclared_Other methods">
  @Override
  public AnnotatedTypeMirror visitDeclared_Declared(
      AnnotatedDeclaredType type, AnnotatedDeclaredType superType, Void p) {
    if (areErasedJavaTypesEquivalent(type, superType)) {
      return type;
    }

    // Not same erased Java type.
    // Walk up the directSupertypes.
    // directSupertypes() annotates type variables correctly and handles substitution.
    for (AnnotatedDeclaredType dst : type.directSupertypes()) {
      if (isErasedJavaSubtype(dst, superType)) {
        // If two direct supertypes of type, dst1 and dst2, are subtypes of superType then
        // asSuper(dst1, superType) and asSuper(dst2, superType) return equivalent ATMs, so
        // return the first one found.
        return visit(dst, superType, p);
      }
    }

    return errorTypeNotErasedSubtypeOfSuperType(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitDeclared_Intersection(
      AnnotatedDeclaredType type, AnnotatedIntersectionType superType, Void p) {
    List<AnnotatedTypeMirror> newBounds = new ArrayList<>();
    // Each type in the intersection must be a supertype of type, so call asSuper on all types
    // in the intersection.
    for (AnnotatedTypeMirror superBound : superType.getBounds()) {
      if (types.isSubtype(type.getUnderlyingType(), superBound.getUnderlyingType())) {
        AnnotatedTypeMirror found = visit(type, superBound, p);
        newBounds.add(found);
      }
    }
    // The ATM for each type in an intersection is stored in the direct super types field.
    superType.setBounds(newBounds);
    return copyPrimaryAnnos(type, superType);
  }

  @Override
  public AnnotatedTypeMirror visitDeclared_Primitive(
      AnnotatedDeclaredType type, AnnotatedPrimitiveType superType, Void p) {
    if (!TypesUtils.isBoxedPrimitive(type.getUnderlyingType())) {
      throw new BugInCF("AsSuperVisitor Declared_Primitive: type is not a boxed primitive.");
    }
    AnnotatedTypeMirror unboxedType = atypeFactory.getUnboxedType(type);
    return copyPrimaryAnnos(unboxedType, superType);
  }

  @Override
  public AnnotatedTypeMirror visitDeclared_Typevar(
      AnnotatedDeclaredType type, AnnotatedTypeVariable superType, Void p) {
    // setUpperBound() may have a side effect on parameter "type" when the upper bound of
    // "superType" equals to "type" (referencing the same object: changes will be shared)
    // copy before visiting to avoid
    // without fix, this would fail:
    // https://github.com/typetools/checker-framework/blob/ed340b2dfa1e51bbc0a7313f22638179d15bf2df/checker/tests/nullness/Issue2432b.java
    AnnotatedTypeMirror typeCopy = type.deepCopy();
    AnnotatedTypeMirror upperBound = visit(typeCopy, superType.getUpperBound(), p).asUse();
    superType.setUpperBound(upperBound);

    AnnotatedTypeMirror lowerBound = asSuperTypevarLowerBound(type, superType, p).asUse();
    superType.setLowerBound(lowerBound);

    return copyPrimaryAnnos(type, superType);
  }

  @Override
  public AnnotatedTypeMirror visitDeclared_Union(
      AnnotatedDeclaredType type, AnnotatedUnionType superType, Void p) {
    // Alternatives in a union type can't have type args, so just copy the primary annotation
    return copyPrimaryAnnos(type, superType);
  }

  @Override
  public AnnotatedTypeMirror visitDeclared_Wildcard(
      AnnotatedDeclaredType type, AnnotatedWildcardType superType, Void p) {
    AnnotatedTypeMirror upperBound = visit(type, superType.getExtendsBound(), p).asUse();
    superType.setExtendsBound(upperBound);

    AnnotatedTypeMirror lowerBound = asSuperWildcardLowerBound(type, superType, p).asUse();
    superType.setSuperBound(lowerBound);

    return copyPrimaryAnnos(type, superType);
  }

  // </editor-fold>

  // <editor-fold defaultstate="collapsed" desc="visitIntersection_Other methods">

  @Override
  public AnnotatedTypeMirror visitIntersection_Declared(
      AnnotatedIntersectionType type, AnnotatedDeclaredType superType, Void p) {
    for (AnnotatedTypeMirror bound : type.getBounds()) {
      // Find the directSuperType that is a subtype of superType, then recur on that type so that
      // type arguments in superType are annotated correctly.
      if (bound.getKind() == TypeKind.DECLARED
          && isErasedJavaSubtype((AnnotatedDeclaredType) bound, superType)) {
        AnnotatedTypeMirror asSuper = visit(bound, superType, p);

        // The directSuperType might have a primary annotation that is a supertype of primary
        // annotation on type. Copy the primary annotation, because it is more precise.
        return copyPrimaryAnnos(type, asSuper);
      }
    }
    return errorTypeNotErasedSubtypeOfSuperType(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitIntersection_Intersection(
      AnnotatedIntersectionType type, AnnotatedIntersectionType superType, Void p) {
    List<AnnotatedTypeMirror> newDirectSupertypes = new ArrayList<>();
    for (AnnotatedTypeMirror superBound : superType.getBounds()) {
      AnnotatedTypeMirror found = null;
      TypeMirror javaSupertype = types.erasure(superBound.getUnderlyingType());
      for (AnnotatedTypeMirror bound : type.getBounds()) {
        TypeMirror javaSubtype = types.erasure(bound.getUnderlyingType());
        if (types.isSubtype(javaSubtype, javaSupertype)) {
          found = visit(bound, superBound, p);
          newDirectSupertypes.add(found);
          break;
        }
      }
      if (found == null) {
        throw new BugInCF(
            "AsSuperVisitor visitIntersection_Intersection:%ntype: %s superType: %s",
            type, superType);
      }
    }
    superType.setBounds(newDirectSupertypes);
    return copyPrimaryAnnos(type, superType);
  }

  @Override
  public AnnotatedTypeMirror visitIntersection_Primitive(
      AnnotatedIntersectionType type, AnnotatedPrimitiveType superType, Void p) {
    for (AnnotatedTypeMirror bound : type.getBounds()) {
      // Find the directSuperType that is a subtype of superType, then recur on that type
      // so that type arguments in superType are annotated correctly
      if (TypesUtils.isBoxedPrimitive(bound.getUnderlyingType())) {
        AnnotatedTypeMirror asSuper = visit(bound, superType, p);

        // The directSuperType might have a primary annotation that is a supertype of primary
        // annotation on type. Copy the primary annotation, because it is more precise.
        return copyPrimaryAnnos(type, asSuper);
      }
    }
    // Cannot happen: one of the types in the intersection must be a subtype of superType.
    throw new BugInCF(
        "AsSuperVisitor visitIntersection_Primitive:%ntype: %s superType: %s", type, superType);
  }

  @Override
  public AnnotatedTypeMirror visitIntersection_Typevar(
      AnnotatedIntersectionType type, AnnotatedTypeVariable superType, Void p) {
    AnnotatedTypeMirror upperBound = visit(type, superType.getUpperBound(), p);
    superType.setUpperBound(upperBound);

    AnnotatedTypeMirror lowerBound = asSuperTypevarLowerBound(type, superType, p);
    superType.setLowerBound(lowerBound);

    return copyPrimaryAnnos(type, superType);
  }

  @Override
  public AnnotatedTypeMirror visitIntersection_Union(
      AnnotatedIntersectionType type, AnnotatedUnionType superType, Void p) {
    TypeMirror javaSupertype = types.erasure(type.getUnderlyingType());
    for (AnnotatedTypeMirror bound : type.getBounds()) {
      TypeMirror javaSubtype = types.erasure(superType.getUnderlyingType());
      if (types.isSubtype(javaSubtype, javaSupertype)) {
        AnnotatedTypeMirror asSuper = visit(bound, superType, p);
        return copyPrimaryAnnos(type, asSuper);
      }
    }
    // Cannot happen: one of the types in the intersection must be a subtype of superType.
    throw new BugInCF(
        "AsSuperVisitor visitIntersection_Union:%ntype: %s%nsuperType: %s", type, superType);
  }

  @Override
  public AnnotatedTypeMirror visitIntersection_Wildcard(
      AnnotatedIntersectionType type, AnnotatedWildcardType superType, Void p) {
    AnnotatedTypeMirror upperBound = visit(type, superType.getExtendsBound(), p);
    superType.setExtendsBound(upperBound);

    AnnotatedTypeMirror lowerBound = asSuperWildcardLowerBound(type, superType, p);
    superType.setSuperBound(lowerBound);

    return copyPrimaryAnnos(type, superType);
  }

  // </editor-fold>

  // <editor-fold defaultstate="collapsed" desc="visitPrimitive_Other methods">

  @Override
  public AnnotatedTypeMirror visitPrimitive_Primitive(
      AnnotatedPrimitiveType type, AnnotatedPrimitiveType superType, Void p) {
    return copyPrimaryAnnos(type, superType);
  }

  /**
   * A helper method for visiting a primitive and a non-primitive.
   *
   * @param type a primitive type
   * @param superType some other type
   * @param p ignore
   * @return {@code type}, viewed as a {@code superType}
   */
  private AnnotatedTypeMirror visitPrimitive_Other(
      AnnotatedPrimitiveType type, AnnotatedTypeMirror superType, Void p) {
    return visit(atypeFactory.getBoxedType(type), superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitPrimitive_Declared(
      AnnotatedPrimitiveType type, AnnotatedDeclaredType superType, Void p) {
    if (TypesUtils.isBoxedPrimitive(superType.getUnderlyingType())) {
      TypeMirror unboxedSuper = types.unboxedType(superType.getUnderlyingType());
      if (unboxedSuper.getKind() != type.getKind()
          && canBeNarrowingPrimitiveConversion(unboxedSuper)) {
        AnnotatedPrimitiveType narrowedType = atypeFactory.getNarrowedPrimitive(type, unboxedSuper);
        return visit(narrowedType, superType, p);
      }
    }
    return visitPrimitive_Other(type, superType, p);
  }

  /**
   * Returns true if the type is byte, short, char, Byte, Short, or Character. All other narrowings
   * require a cast. See JLS 5.1.3.
   *
   * @param type a type
   * @return true if assignment to the type may be a narrowing
   */
  private boolean canBeNarrowingPrimitiveConversion(TypeMirror type) {
    // See CFGBuilder.CFGTranslationPhaseOne#conversionRequiresNarrowing()
    TypeMirror unboxedType = TypesUtils.isBoxedPrimitive(type) ? types.unboxedType(type) : type;
    TypeKind unboxedKind = unboxedType.getKind();
    return unboxedKind == TypeKind.BYTE
        || unboxedKind == TypeKind.SHORT
        || unboxedKind == TypeKind.CHAR;
  }

  @Override
  public AnnotatedTypeMirror visitPrimitive_Intersection(
      AnnotatedPrimitiveType type, AnnotatedIntersectionType superType, Void p) {
    return visitPrimitive_Other(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitPrimitive_Typevar(
      AnnotatedPrimitiveType type, AnnotatedTypeVariable superType, Void p) {
    return visitPrimitive_Other(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitPrimitive_Union(
      AnnotatedPrimitiveType type, AnnotatedUnionType superType, Void p) {
    return visitPrimitive_Other(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitPrimitive_Wildcard(
      AnnotatedPrimitiveType type, AnnotatedWildcardType superType, Void p) {
    return visitPrimitive_Other(type, superType, p);
  }
  // </editor-fold>

  // <editor-fold defaultstate="collapsed" desc="visitTypevar_Other methods">
  private AnnotatedTypeMirror visitTypevar_NotTypevarNorWildcard(
      AnnotatedTypeVariable type, AnnotatedTypeMirror superType, Void p) {
    AnnotatedTypeMirror asSuper = visit(type.getUpperBound(), superType, p);
    return copyPrimaryAnnos(type, asSuper);
  }

  @Override
  public AnnotatedTypeMirror visitTypevar_Declared(
      AnnotatedTypeVariable type, AnnotatedDeclaredType superType, Void p) {
    return visitTypevar_NotTypevarNorWildcard(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitTypevar_Intersection(
      AnnotatedTypeVariable type, AnnotatedIntersectionType superType, Void p) {
    return visitTypevar_NotTypevarNorWildcard(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitTypevar_Primitive(
      AnnotatedTypeVariable type, AnnotatedPrimitiveType superType, Void p) {
    return visitTypevar_NotTypevarNorWildcard(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitTypevar_Typevar(
      AnnotatedTypeVariable type, AnnotatedTypeVariable superType, Void p) {
    // Clear the superType annotations and copy over the primary annotations before computing
    // bounds, so that the superType annotations don't override the type annotations on the bounds.
    superType.clearAnnotations();
    copyPrimaryAnnos(type, superType);

    AnnotatedTypeMirror upperBound = visit(type.getUpperBound(), superType.getUpperBound(), p);
    superType.setUpperBound(upperBound);

    AnnotatedTypeMirror lowerBound;
    if (type.getLowerBound().getKind() == TypeKind.NULL
        && superType.getLowerBound().getKind() == TypeKind.NULL) {
      lowerBound = copyPrimaryAnnos(type.getLowerBound(), superType.getLowerBound());
    } else if (type.getLowerBound().getKind() == TypeKind.NULL) {
      lowerBound = visit(type, superType.getLowerBound(), p);
    } else {
      lowerBound = asSuperTypevarLowerBound(type.getLowerBound(), superType, p);
    }
    superType.setLowerBound(lowerBound);

    return superType;
  }

  @Override
  public AnnotatedTypeMirror visitTypevar_Union(
      AnnotatedTypeVariable type, AnnotatedUnionType superType, Void p) {
    return visitTypevar_NotTypevarNorWildcard(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitTypevar_Wildcard(
      AnnotatedTypeVariable type, AnnotatedWildcardType superType, Void p) {
    AnnotatedTypeMirror upperBound = visit(type.getUpperBound(), superType.getExtendsBound(), p);
    superType.setExtendsBound(upperBound);

    AnnotatedTypeMirror lowerBound;
    if (type.getLowerBound().getKind() == TypeKind.NULL
        && superType.getSuperBound().getKind() == TypeKind.NULL) {
      lowerBound = copyPrimaryAnnos(type.getLowerBound(), superType.getSuperBound());
    } else if (type.getLowerBound().getKind() == TypeKind.NULL) {
      lowerBound = visit(type, superType.getSuperBound(), p);
    } else {
      lowerBound = asSuperWildcardLowerBound(type.getLowerBound(), superType, p);
    }
    superType.setSuperBound(lowerBound);

    return copyPrimaryAnnos(type, superType);
  }
  // </editor-fold>

  /* The primary annotation on a union type is the LUB of the primary annotations on its alternatives. #ensurePrimaryIsCorrectForUnions ensures that this is the case.

  All the alternatives in a union type must be subtype of Throwable and cannot have type arguments;
  however, a union type can be a subtype of an interface with a type argument. For example:
  interface Interface<T>{}
  class MyException1 extends Throwable implements Interface<Number>{}
  class MyException2 extends Throwable implements Interface<Number>{}

  MyException1 <: MyException1 | MyException2 <: Interface<Number>
  MyException1 | MyException2 <: Throwable & Interface<Number>
  */
  // <editor-fold defaultstate="collapsed" desc="visitUnion_Other methods">

  private AnnotatedTypeMirror visitUnion_Other(
      AnnotatedUnionType type, AnnotatedTypeMirror superType, Void p) {
    // asSuper on any of the alternatives is the same, so just use the first one.
    AnnotatedTypeMirror asSuper = visit(type.getAlternatives().get(0), superType, p);
    return copyPrimaryAnnos(type, asSuper);
  }

  @Override
  public AnnotatedTypeMirror visitUnion_Declared(
      AnnotatedUnionType type, AnnotatedDeclaredType superType, Void p) {
    return visitUnion_Other(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitUnion_Intersection(
      AnnotatedUnionType type, AnnotatedIntersectionType superType, Void p) {
    return visitUnion_Other(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitUnion_Typevar(
      AnnotatedUnionType type, AnnotatedTypeVariable superType, Void p) {
    return visitUnion_Other(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitUnion_Union(
      AnnotatedUnionType type, AnnotatedUnionType superType, Void p) {
    for (AnnotatedTypeMirror superAltern : superType.getAlternatives()) {
      copyPrimaryAnnos(type, superAltern);
    }
    return copyPrimaryAnnos(type, superType);
  }

  @Override
  public AnnotatedTypeMirror visitUnion_Wildcard(
      AnnotatedUnionType type, AnnotatedWildcardType superType, Void p) {
    return visitUnion_Other(type, superType, p);
  }
  // </editor-fold>

  // <editor-fold defaultstate="collapsed" desc="visitWildCard_Other methods">

  private AnnotatedTypeMirror visitWildcard_NotTypvarNorWildcard(
      AnnotatedWildcardType type, AnnotatedTypeMirror superType, Void p) {
    boolean oldIsUninferredTypeArgument = isUninferredTypeArgument;
    if (type.isUninferredTypeArgument()) {
      isUninferredTypeArgument = true;
    }
    AnnotatedTypeMirror asSuper = visit(type.getExtendsBound(), superType, p);
    isUninferredTypeArgument = oldIsUninferredTypeArgument;
    atypeFactory.addDefaultAnnotations(superType);

    return copyPrimaryAnnos(type, asSuper);
  }

  @Override
  public AnnotatedTypeMirror visitWildcard_Array(
      AnnotatedWildcardType type, AnnotatedArrayType superType, Void p) {
    return visitWildcard_NotTypvarNorWildcard(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitWildcard_Declared(
      AnnotatedWildcardType type, AnnotatedDeclaredType superType, Void p) {
    return visitWildcard_NotTypvarNorWildcard(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitWildcard_Intersection(
      AnnotatedWildcardType type, AnnotatedIntersectionType superType, Void p) {
    return visitWildcard_NotTypvarNorWildcard(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitWildcard_Primitive(
      AnnotatedWildcardType type, AnnotatedPrimitiveType superType, Void p) {
    return visitWildcard_NotTypvarNorWildcard(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitWildcard_Typevar(
      AnnotatedWildcardType type, AnnotatedTypeVariable superType, Void p) {
    boolean oldIsUninferredTypeArgument = isUninferredTypeArgument;
    if (type.isUninferredTypeArgument()) {
      isUninferredTypeArgument = true;
    }
    AnnotatedTypeMirror upperBound = visit(type.getExtendsBound(), superType.getUpperBound(), p);
    superType.setUpperBound(upperBound);

    AnnotatedTypeMirror lowerBound;
    if (type.getSuperBound().getKind() == TypeKind.NULL
        && superType.getLowerBound().getKind() == TypeKind.NULL) {
      lowerBound = copyPrimaryAnnos(type.getSuperBound(), superType.getLowerBound());
    } else if (type.getSuperBound().getKind() == TypeKind.NULL) {
      lowerBound = visit(type, superType.getLowerBound(), p);
    } else {
      lowerBound = asSuperTypevarLowerBound(type.getSuperBound(), superType, p);
    }
    superType.setLowerBound(lowerBound);
    isUninferredTypeArgument = oldIsUninferredTypeArgument;
    atypeFactory.addDefaultAnnotations(superType);

    return copyPrimaryAnnos(type, superType);
  }

  @Override
  public AnnotatedTypeMirror visitWildcard_Union(
      AnnotatedWildcardType type, AnnotatedUnionType superType, Void p) {
    return visitWildcard_NotTypvarNorWildcard(type, superType, p);
  }

  @Override
  public AnnotatedTypeMirror visitWildcard_Wildcard(
      AnnotatedWildcardType type, AnnotatedWildcardType superType, Void p) {
    boolean oldIsUninferredTypeArgument = isUninferredTypeArgument;
    if (type.isUninferredTypeArgument()) {
      isUninferredTypeArgument = true;
      superType.setUninferredTypeArgument();
    }
    if (types.isSubtype(
        type.getExtendsBound().getUnderlyingType(),
        superType.getExtendsBound().getUnderlyingType())) {
      AnnotatedTypeMirror upperBound =
          visit(type.getExtendsBound(), superType.getExtendsBound(), p);
      superType.setExtendsBound(upperBound);
    } else {
      // The upper bound of a wildcard can be a super type of upper bound of the type
      // parameter for which it is an argument.
      // See org.checkerframework.framework.type.AnnotatedTypeFactory.widenToUpperBound for an
      // example.  In these cases, the upper bound of type might be a super type of the
      // upper bound of superType.

      // The underlying type of the annotated type mirror returned by asSuper must be the
      // same as the passed type, so just copy the primary annotations.
      copyPrimaryAnnos(type.getExtendsBound(), superType.getExtendsBound());

      // Add defaults in case any locations are missing annotations.
      atypeFactory.addDefaultAnnotations(superType.getExtendsBound());
    }

    AnnotatedTypeMirror lowerBound;
    if (type.getSuperBound().getKind() == TypeKind.NULL
        && superType.getSuperBound().getKind() == TypeKind.NULL) {
      lowerBound = copyPrimaryAnnos(type.getSuperBound(), superType.getSuperBound());
    } else if (type.getSuperBound().getKind() == TypeKind.NULL) {
      lowerBound = visit(type, superType.getSuperBound(), p);
    } else {
      lowerBound = asSuperWildcardLowerBound(type.getSuperBound(), superType, p);
    }
    superType.setSuperBound(lowerBound);
    isUninferredTypeArgument = oldIsUninferredTypeArgument;
    atypeFactory.addDefaultAnnotations(superType);

    return copyPrimaryAnnos(type, superType);
  }

  /**
   * Returns true if the atypeFactory for this is the given value.
   *
   * @param atypeFactory a factory to compare to that of this
   * @return true if the atypeFactory for this is the given value
   */
  public boolean sameAnnotatedTypeFactory(@FindDistinct AnnotatedTypeFactory atypeFactory) {
    return this.atypeFactory == atypeFactory;
  }
  // </editor-fold>
}
