@Override
    public Boolean visitTypeVariable(TypeVariable a, EqualVisitorParam p) {
      if (p.type.getKind().equals(TYPEVAR)) {
        TypeVariable b = (TypeVariable) p.type;
        TypeParameterElement aElement = (TypeParameterElement) a.asElement();
        TypeParameterElement bElement = (TypeParameterElement) b.asElement();
        Set<ComparedElements> newVisiting = visitingSetPlus(p.visiting, aElement, bElement);
        if (newVisiting.equals(p.visiting)) {
          // We're already visiting this pair of elements.
          // This can happen with our friend Eclipse when looking at <T extends Comparable<T>>.
          // It incorrectly reports the upper bound of T as T itself.
          return true;
        }
        // We use aElement.getBounds() instead of a.getUpperBound() to avoid having to deal with
        // the different way intersection types (like <T extends Number & Comparable<T>>) are
        // represented before and after Java 8. We do have an issue that this code may consider
        // that <T extends Foo & Bar> is different from <T extends Bar & Foo>, but it's very
        // hard to avoid that, and not likely to be much of a problem in practice.
        return equalLists(aElement.getBounds(), bElement.getBounds(), newVisiting)
            && equal(a.getLowerBound(), b.getLowerBound(), newVisiting)
            && a.asElement().getSimpleName().equals(b.asElement().getSimpleName());
      }
      return false;
    }
Returns an {@link Equivalence} that can be used to compare types. The standard way to compare
types is {@link javax.lang.model.util.Types#isSameType Types.isSameType}, but this alternative
may be preferred in a number of cases:

<ul>
  <li>If you don't have an instance of {@code Types}.
  <li>If you want a reliable {@code hashCode()} for the types, for example to construct a set
      of types using {@link java.util.HashSet} with {@link Equivalence#wrap(Object)}.
  <li>If you want distinct type variables to be considered equal if they have the same names
      and bounds.
  <li>If you want wildcard types to compare equal if they have the same bounds. {@code
      Types.isSameType} never considers wildcards equal, even when comparing a type to itself.
</ul>
common/src/main/java/com/google/auto/common/MoreTypes.java