code: static TypeVariableName get(
        TypeVariable mirror, Map<TypeParameterElement, TypeVariableName> typeVariables) {
      TypeParameterElement element = (TypeParameterElement) mirror.asElement();
      TypeVariableName typeVariableName = typeVariables.get(element);
      if (typeVariableName == null) {
        // Since the bounds field is public, we need to make it an unmodifiableList. But we control
        // the List that that wraps, which means we can change it before returning.
        List<TypeName> bounds = new ArrayList<>();
        List<TypeName> visibleBounds = Collections.unmodifiableList(bounds);
        typeVariableName = new TypeVariableName(element.getSimpleName().toString(), visibleBounds);
        typeVariables.put(element, typeVariableName);
        for (TypeMirror typeMirror : element.getBounds()) {
          bounds.add(TypeName.get(typeMirror, typeVariables));
        }
        bounds.remove(OBJECT);
      }
      return typeVariableName;
    }
docs: Make a TypeVariableName for the given TypeMirror. This form is used internally to avoid
  infinite recursion in cases like {@code Enum<E extends Enum<E>>}. When we encounter such a
  thing, we will make a TypeVariableName without bounds and add that to the {@code typeVariables}
  map before looking up the bounds. Then if we encounter this TypeVariable again while
  constructing the bounds, we can just return it from the map. And, the code that put the entry
  in {@code variables} will make sure that the bounds are filled in before returning.