private Pair<ParameterizedTypeTree, AnnotatedDeclaredType> extractParameterizedTypeTree(
      Tree tree, AnnotatedDeclaredType type) {
    ParameterizedTypeTree typeargtree = null;

    switch (tree.getKind()) {
      case VARIABLE:
        Tree lt = ((VariableTree) tree).getType();
        if (lt instanceof ParameterizedTypeTree) {
          typeargtree = (ParameterizedTypeTree) lt;
        } else {
          // System.out.println("Found a: " + lt);
        }
        break;
      case PARAMETERIZED_TYPE:
        typeargtree = (ParameterizedTypeTree) tree;
        break;
      case NEW_CLASS:
        NewClassTree nct = (NewClassTree) tree;
        ExpressionTree nctid = nct.getIdentifier();
        if (nctid.getKind() == Tree.Kind.PARAMETERIZED_TYPE) {
          typeargtree = (ParameterizedTypeTree) nctid;
          /*
           * This is quite tricky... for anonymous class instantiations,
           * the type at this point has no type arguments. By doing the
           * following, we get the type arguments again.
           */
          type = (AnnotatedDeclaredType) atypeFactory.getAnnotatedType(typeargtree);
        }
        break;
      case ANNOTATED_TYPE:
        AnnotatedTypeTree tr = (AnnotatedTypeTree) tree;
        ExpressionTree undtr = tr.getUnderlyingType();
        if (undtr instanceof ParameterizedTypeTree) {
          typeargtree = (ParameterizedTypeTree) undtr;
        } else if (undtr instanceof IdentifierTree) {
          // @Something D -> Nothing to do
        } else {
          // TODO: add more test cases to ensure that nested types are
          // handled correctly,
          // e.g. @Nullable() List<@Nullable Object>[][]
          Pair<ParameterizedTypeTree, AnnotatedDeclaredType> p =
              extractParameterizedTypeTree(undtr, type);
          typeargtree = p.first;
          type = p.second;
        }
        break;
      case IDENTIFIER:
      case ARRAY_TYPE:
      case NEW_ARRAY:
      case MEMBER_SELECT:
      case UNBOUNDED_WILDCARD:
      case EXTENDS_WILDCARD:
      case SUPER_WILDCARD:
      case TYPE_PARAMETER:
        // Nothing to do.
        // System.out.println("Found a: " + (tree instanceof
        // ParameterizedTypeTree));
        break;
      default:
        // the parameterized type is the result of some expression tree.
        // No need to do anything further.
        break;
        // System.err.printf("TypeValidator.visitDeclared unhandled tree: %s of kind %s\n",
        //                 tree, tree.getKind());
    }

    return Pair.of(typeargtree, type);
  }
  @Override
  public Void visitDeclared(AnnotatedDeclaredType type, Tree tree) {
    if (checker.shouldSkipUses(type.getUnderlyingType().asElement()))
      return super.visitDeclared(type, tree);

    {
      // Ensure that type use is a subtype of the element type
      // isValidUse determines the erasure of the types.
      AnnotatedDeclaredType elemType =
          (AnnotatedDeclaredType)
              atypeFactory.getAnnotatedType(type.getUnderlyingType().asElement());

      if (!visitor.isValidUse(elemType, type, tree)) {
        reportError(type, tree);
      }
    }

    // System.out.println("Type: " + type);
    // System.out.println("Tree: " + tree);
    // System.out.println("Tree kind: " + tree.getKind());

    /*
     * Try to reconstruct the ParameterizedTypeTree from the given tree.
     * TODO: there has to be a nicer way to do this...
     */
    Pair<ParameterizedTypeTree, AnnotatedDeclaredType> p = extractParameterizedTypeTree(tree, type);
    ParameterizedTypeTree typeargtree = p.first;
    type = p.second;

    if (typeargtree != null) {
      // We have a ParameterizedTypeTree -> visit it.

      visitParameterizedType(type, typeargtree);

      /*
       * Instead of calling super with the unchanged "tree", adapt the
       * second argument to be the corresponding type argument tree. This
       * ensures that the first and second parameter to this method always
       * correspond. visitDeclared is the only method that had this
       * problem.
       */
      List<? extends AnnotatedTypeMirror> tatypes = type.getTypeArguments();

      if (tatypes == null) return null;

      // May be zero for a "diamond" (inferred type args in constructor
      // invocation).
      int numTypeArgs = typeargtree.getTypeArguments().size();
      if (numTypeArgs != 0) {
        // TODO: this should be an equality, but in
        // http://buffalo.cs.washington.edu:8080/job/jdk6-daikon-typecheck/2061/console
        // it failed with:
        // daikon/Debug.java; message: size mismatch for type arguments:
        // @NonNull Object and Class<?>
        // but I didn't manage to reduce it to a test case.
        assert tatypes.size() <= numTypeArgs
            : "size mismatch for type arguments: " + type + " and " + typeargtree;

        for (int i = 0; i < tatypes.size(); ++i) {
          scan(tatypes.get(i), typeargtree.getTypeArguments().get(i));
        }
      }

      return null;

      // Don't call the super version, because it creates a mismatch
      // between
      // the first and second parameters.
      // return super.visitDeclared(type, tree);
    }

    return super.visitDeclared(type, tree);
  }
  /**
   * Get the type of element from the realTypeFactory. Copy it's annotations to inferenceType. Add
   * a @VarAnnot to all definite type use locations (locations that can be defaulted) in
   * inferenceType and add an equality constraint between it and the "real" annotations
   *
   * @param element The bytecode declaration from which inferenceType was created
   * @param inferenceType The type of element. inferenceType will be annotated by this method
   */
  public void annotate(final Element element, final AnnotatedTypeMirror inferenceType) {
    final AnnotatedTypeMirror realType = realTypeFactory.getAnnotatedType(element);

    CopyUtil.copyAnnotations(realType, inferenceType);
    inferenceTypeFactory.getNewConstantToVariableAnnotator().visit(inferenceType);
  }