@Override
 public Void visitExecutable(AnnotatedExecutableType t, Void p) {
   Void result = super.visitExecutable(t, p);
   Element elem = t.getElement();
   if (elem.getKind() == ElementKind.CONSTRUCTOR) {
     AnnotatedDeclaredType returnType = (AnnotatedDeclaredType) t.getReturnType();
     DeclaredType underlyingType = returnType.getUnderlyingType();
     returnType.replaceAnnotation(getFreeOrRawAnnotationOfSuperType(underlyingType));
   }
   return result;
 }
  /**
   * 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.type.incompatible" error if they are not.
   *
   * <p>This method used to be visitParameterizedType, which incorrectly handles the main annotation
   * on generic types.
   */
  protected Void visitParameterizedType(AnnotatedDeclaredType type, ParameterizedTypeTree tree) {
    // System.out.printf("TypeValidator.visitParameterizedType: type: %s, tree: %s\n",
    // type, tree);

    if (TreeUtils.isDiamondTree(tree)) return null;

    final TypeElement element = (TypeElement) type.getUnderlyingType().asElement();
    if (checker.shouldSkipUses(element)) return null;

    List<AnnotatedTypeVariable> typevars = atypeFactory.typeVariablesFromUse(type, element);

    visitor.checkTypeArguments(tree, typevars, type.getTypeArguments(), tree.getTypeArguments());

    return null;
  }
  @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);
  }