Work around an Eclipse bug where the upper bound of a type variable like <T extends Comparable<T>> can show up as being T, leading to infinite recursion. MoreTypes isn't tested with Eclipse at the moment, unfortunately, but the bug showed up in AutoValue's CompileWithEclipseTest when I tried to add a <T extends Comparable<T>> to AutoValueTest.
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=83609722
diff --git a/common/src/main/java/com/google/auto/common/MoreTypes.java b/common/src/main/java/com/google/auto/common/MoreTypes.java
index 274d11c..5a5423a 100644
--- a/common/src/main/java/com/google/auto/common/MoreTypes.java
+++ b/common/src/main/java/com/google/auto/common/MoreTypes.java
@@ -131,8 +131,9 @@
             DeclaredType b = (DeclaredType) p.type;
             Element aElement = a.asElement();
             Element bElement = b.asElement();
-            ComparedElements comparedElements = new ComparedElements(aElement, bElement);
-            if (p.visiting.contains(comparedElements)) {
+            Set<ComparedElements> newVisiting = visitingSetPlus(p.visiting, aElement, bElement);
+            if (newVisiting.equals(p.visiting)) {
+              // We're already visiting this pair of elements.
               // This can happen for example with Enum in Enum<E extends Enum<E>>. Return a
               // provisional true value since if the Elements are not in fact equal the original
               // visitor of Enum will discover that. We have to check both Elements being compared
@@ -140,8 +141,6 @@
               // differs at exactly this point.
               return true;
             }
-            Set<ComparedElements> newVisiting = new HashSet<ComparedElements>(p.visiting);
-            newVisiting.add(comparedElements);
             return aElement.equals(bElement)
                 && equal(a.getEnclosingType(), a.getEnclosingType(), newVisiting)
                 && equalLists(a.getTypeArguments(), b.getTypeArguments(), newVisiting);
@@ -171,8 +170,17 @@
         public Boolean visitTypeVariable(TypeVariable a, EqualVisitorParam p) {
           if (p.type.getKind().equals(TYPEVAR)) {
             TypeVariable b = (TypeVariable) p.type;
-            return equal(a.getUpperBound(), b.getUpperBound(), p.visiting)
-                && equal(a.getLowerBound(), b.getLowerBound(), p.visiting);
+            Element aElement = a.asElement();
+            Element bElement = 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;
+            }
+            return equal(a.getUpperBound(), b.getUpperBound(), newVisiting)
+                && equal(a.getLowerBound(), b.getLowerBound(), newVisiting);
           }
           return false;
         }
@@ -191,6 +199,14 @@
         public Boolean visitUnknown(TypeMirror a, EqualVisitorParam p) {
           throw new UnsupportedOperationException();
         }
+
+        private Set<ComparedElements> visitingSetPlus(
+            Set<ComparedElements> visiting, Element a, Element b) {
+          ComparedElements comparedElements = new ComparedElements(a, b);
+          Set<ComparedElements> newVisiting = new HashSet<ComparedElements>(visiting);
+          newVisiting.add(comparedElements);
+          return newVisiting;
+        }
       };
 
   private static final Class<?> INTERSECTION_TYPE;