@Override
 public boolean canBeAssignedTo(TypeUsage type) {
   if (!type.isReferenceTypeUsage()) {
     return false;
   }
   ReferenceTypeUsage other = type.asReferenceTypeUsage();
   if (this.getQualifiedName().equals(other.getQualifiedName())) {
     return true;
   }
   for (TypeUsage ancestor : this.getAllAncestors()) {
     if (ancestor.canBeAssignedTo(type)) {
       return true;
     }
   }
   return false;
 }
 @Override
 public <T extends TypeUsage> TypeUsage replaceTypeVariables(Map<String, T> typeParams) {
   if (this.typeParams.size() == 0) {
     return this;
   }
   List<TypeUsage> replacedParams =
       this.typeParams
           .stream()
           .map((tp) -> tp.replaceTypeVariables(typeParams))
           .collect(Collectors.toList());
   if (!replacedParams.equals(this.typeParams)) {
     ReferenceTypeUsage copy = new ReferenceTypeUsage(this.cachedTypeDefinition);
     copy.typeParams = replacedParams;
     return copy;
   } else {
     return this;
   }
 }