@Override
    public void recordInterfaces(
        JSType type, JSType relatedType, DisambiguateProperties<JSType>.Property p) {
      ObjectType objType = ObjectType.cast(type);
      if (objType != null) {
        FunctionType constructor;
        if (objType instanceof FunctionType) {
          constructor = (FunctionType) objType;
        } else if (objType instanceof FunctionPrototypeType) {
          constructor = ((FunctionPrototypeType) objType).getOwnerFunction();
        } else {
          constructor = objType.getConstructor();
        }
        while (constructor != null) {
          for (ObjectType itype : constructor.getImplementedInterfaces()) {
            JSType top = getTypeWithProperty(p.name, itype);
            if (top != null) {
              p.addType(itype, top, relatedType);
            } else {
              recordInterfaces(itype, relatedType, p);
            }

            // If this interface invalidated this property, return now.
            if (p.skipRenaming) return;
          }
          if (constructor.isInterface() || constructor.isConstructor()) {
            constructor = constructor.getSuperClassConstructor();
          } else {
            constructor = null;
          }
        }
      }
    }
  /**
   * Infer the role of the function (whether it's a constructor or interface) and what it inherits
   * from in JSDocInfo.
   */
  FunctionTypeBuilder inferInheritance(@Nullable JSDocInfo info) {
    if (info != null) {
      isConstructor = info.isConstructor();
      isInterface = info.isInterface();

      // base type
      if (info.hasBaseType()) {
        if (isConstructor || isInterface) {
          JSType maybeBaseType = info.getBaseType().evaluate(scope, typeRegistry);
          if (maybeBaseType != null && maybeBaseType.setValidator(new ExtendedTypeValidator())) {
            baseType = (ObjectType) maybeBaseType;
          }
        } else {
          reportWarning(EXTENDS_WITHOUT_TYPEDEF, fnName);
        }
      }

      // implemented interfaces
      if (isConstructor || isInterface) {
        implementedInterfaces = Lists.newArrayList();
        for (JSTypeExpression t : info.getImplementedInterfaces()) {
          JSType maybeInterType = t.evaluate(scope, typeRegistry);
          if (maybeInterType != null
              && maybeInterType.setValidator(new ImplementedTypeValidator())) {
            implementedInterfaces.add((ObjectType) maybeInterType);
          }
        }
        if (baseType != null) {
          JSType maybeFunctionType = baseType.getConstructor();
          if (maybeFunctionType instanceof FunctionType) {
            FunctionType functionType = baseType.getConstructor();
            Iterables.addAll(implementedInterfaces, functionType.getImplementedInterfaces());
          }
        }
      } else if (info.getImplementedInterfaceCount() > 0) {
        reportWarning(IMPLEMENTS_WITHOUT_CONSTRUCTOR, fnName);
      }
    }

    return this;
  }
 @Override
 public Iterable<JSType> getTypeAlternatives(JSType type) {
   if (type.isUnionType()) {
     return ((UnionType) type).getAlternates();
   } else {
     ObjectType objType = type.toObjectType();
     if (objType != null
         && objType.getConstructor() != null
         && objType.getConstructor().isInterface()) {
       List<JSType> list = Lists.newArrayList();
       for (FunctionType impl : registry.getDirectImplementors(objType)) {
         list.add(impl.getInstanceType());
       }
       return list;
     } else {
       return null;
     }
   }
 }