public boolean isSubtypeOneLevel(AnnotatedTypeMirror sup, AnnotatedTypeMirror sub) {
    // Current implementation only need to deal with one level
    // Err... cannot handle type variables quite yet
    if (sup.getKind() == TypeKind.TYPEVAR
        || sup.getKind() == TypeKind.WILDCARD
        || sub.getKind() == TypeKind.TYPEVAR
        || sub.getKind() == TypeKind.WILDCARD) return true;

    // TODO: Need to handle Generics and Arrays
    if (sup.hasAnnotation(READONLY)
        || sup.hasAnnotation(PLACE_HOLDER)
        || sub.hasAnnotation(PLACE_HOLDER)) return true;
    else if (sup.hasAnnotation(I)) {
      // t1 is a subtype of t2, if and only they have the same
      // immutability argument
      if (!sub.hasAnnotation(I)) return false;

      AnnotationUtils annoUtils = new AnnotationUtils(this.env);
      String t1Arg =
          annoUtils.parseStringValue(
              sub.getAnnotation(I.class.getCanonicalName()), IMMUTABILITY_KEY);
      String t2Arg =
          annoUtils.parseStringValue(
              sup.getAnnotation(I.class.getCanonicalName()), IMMUTABILITY_KEY);

      return ((t1Arg != null) && (t2Arg != null) && t1Arg.equals(t2Arg));
    }

    return ((sup.hasAnnotation(IMMUTABLE) && sub.hasAnnotation(IMMUTABLE))
        || (sup.hasAnnotation(MUTABLE) && sub.hasAnnotation(MUTABLE))
        || (sup.hasAnnotation(ASSIGNS_FIELDS) && sub.hasAnnotation(ASSIGNS_FIELDS))
        || (sup.hasAnnotation(ASSIGNS_FIELDS) && sub.hasAnnotation(MUTABLE)));
  }