Restore Skylark "support" for inheritance

Classes of the same EvalUtils.getSkylarkType are once again the same for the
type inferencer.

Also, for debugging purposes, only print SkylarkClassObject as struct, not all classes that implement ClassObject yet are considered disjoint by the type engine.

--
MOS_MIGRATED_REVID=87933890
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/ValidationTests.java b/src/test/java/com/google/devtools/build/lib/syntax/ValidationTests.java
index 62b0d85..6085ba5 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/ValidationTests.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/ValidationTests.java
@@ -13,12 +13,21 @@
 // limitations under the License.
 package com.google.devtools.build.lib.syntax;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
 import com.google.common.base.Joiner;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
+import java.util.Arrays;
+
 /**
  * Tests for the validation process of Skylark files.
  */
@@ -657,6 +666,75 @@
         "load('pkg/extension', 'a')\n");
   }
 
+  @Test
+  public void testParentWithSkylarkModule() throws Exception {
+    assertTrue(SkylarkList.class.isAnnotationPresent(SkylarkModule.class));
+    assertEquals(SkylarkList.class,
+        EvalUtils.getParentWithSkylarkModule(SkylarkList.class));
+    assertEquals(SkylarkList.class,
+        EvalUtils.getParentWithSkylarkModule(SkylarkList.EMPTY_LIST.getClass()));
+    assertEquals(SkylarkList.class,
+        EvalUtils.getParentWithSkylarkModule(
+            SkylarkList.tuple(Arrays.<Object>asList(1, 2, 3)).getClass()));
+    // TODO(bazel-team): fix that!
+    assertFalse(ClassObject.class.isAnnotationPresent(SkylarkModule.class));
+    assertTrue(ClassObject.SkylarkClassObject.class
+        .isAnnotationPresent(SkylarkModule.class));
+    assertEquals(ClassObject.SkylarkClassObject.class,
+        EvalUtils.getParentWithSkylarkModule(ClassObject.SkylarkClassObject.class));
+    assertNull(EvalUtils.getParentWithSkylarkModule(ClassObject.class));
+  }
+
+  @Test
+  public void testSkylarkTypeEquivalence() throws Exception {
+    // All subclasses of SkylarkList are made equivalent
+    assertEquals(SkylarkType.LIST, SkylarkType.of(SkylarkList.class));
+    assertEquals(SkylarkType.LIST, SkylarkType.of(SkylarkList.EMPTY_LIST.getClass()));
+    assertEquals(SkylarkType.LIST, SkylarkType.of(
+        SkylarkList.list(Arrays.<Object>asList(1, 2, 3), SkylarkType.INT).getClass()));
+    // TODO(bazel-team): make a tuple not a list anymore.
+    assertEquals(SkylarkType.LIST, SkylarkType.of(
+        SkylarkList.tuple(Arrays.<Object>asList(1, "a", "b")).getClass()));
+
+    // Also for ClassObject
+    assertEquals(SkylarkType.of(ClassObject.SkylarkClassObject.class),
+        SkylarkType.of(ClassObject.SkylarkClassObject.class));
+    assertFalse(SkylarkType.of(ClassObject.class).equals(
+        SkylarkType.of(ClassObject.SkylarkClassObject.class)));
+
+    // Also for these bazel classes, to avoid some regression.
+    // TODO(bazel-team): move to some other place to remove dependency of syntax tests on Artifact?
+    assertEquals(SkylarkType.of(Artifact.class), SkylarkType.of(Artifact.SpecialArtifact.class));
+    assertFalse(SkylarkType.of(RuleConfiguredTarget.class).equals(
+        SkylarkType.STRUCT));
+  }
+
+  @Test
+  public void testSkylarkTypeInclusion() throws Exception {
+    assertTrue(SkylarkType.INT.includes(SkylarkType.BOTTOM));
+    assertFalse(SkylarkType.BOTTOM.includes(SkylarkType.INT));
+    assertTrue(SkylarkType.TOP.includes(SkylarkType.INT));
+
+    SkylarkType combo1 = SkylarkType.Combination.of(SkylarkType.LIST, SkylarkType.INT);
+    assertTrue(SkylarkType.LIST.includes(combo1));
+
+    SkylarkType union1 = SkylarkType.Union.of(
+        SkylarkType.MAP, SkylarkType.LIST, SkylarkType.STRUCT);
+    assertTrue(union1.includes(SkylarkType.MAP));
+    assertTrue(union1.includes(SkylarkType.LIST));
+    assertTrue(union1.includes(SkylarkType.STRUCT));
+    assertTrue(union1.includes(combo1));
+    assertFalse(union1.includes(SkylarkType.STRING));
+
+    SkylarkType union2 = SkylarkType.Union.of(
+        SkylarkType.LIST, SkylarkType.MAP, SkylarkType.STRING, SkylarkType.INT);
+    SkylarkType inter1 = SkylarkType.intersection(union1, union2);
+    assertTrue(inter1.includes(SkylarkType.MAP));
+    assertTrue(inter1.includes(SkylarkType.LIST));
+    assertTrue(inter1.includes(combo1));
+    assertFalse(inter1.includes(SkylarkType.INT));
+  }
+
   private void parse(String... lines) {
     parseFileForSkylark(Joiner.on("\n").join(lines));
     syntaxEvents.assertNoEvents();