TypeSpec implements TraceType

PiperOrigin-RevId: 429619999
Change-Id: I0fddaf8c8ed55179faa23071bcc6e8b092f4681a
diff --git a/tensorflow/python/framework/BUILD b/tensorflow/python/framework/BUILD
index 1d5d197..e57220b 100644
--- a/tensorflow/python/framework/BUILD
+++ b/tensorflow/python/framework/BUILD
@@ -1247,6 +1247,7 @@
         ":dtypes",
         ":tensor_shape",
         "//tensorflow/python:platform",
+        "//tensorflow/python/types",
         "//tensorflow/python/util",
         "//third_party/py/numpy",
     ],
diff --git a/tensorflow/python/framework/type_spec.py b/tensorflow/python/framework/type_spec.py
index 9b130d3..62fdc73 100644
--- a/tensorflow/python/framework/type_spec.py
+++ b/tensorflow/python/framework/type_spec.py
@@ -18,9 +18,9 @@
 import collections
 import functools
 import re
-
-import typing
+from typing import List, Optional, Sequence, Any
 import warnings
+
 import numpy as np
 
 from tensorflow.python.framework import composite_tensor
@@ -43,31 +43,8 @@
                  "tensorflow.python.framework.ops")
 
 
-# TODO(b/202447704): Merge into TypeSpec.
-class TypeSpecTraceType(trace.TraceType):
-  """A wrapper to support encoding of TypeSpecs through TraceType."""
-
-  def __init__(self, spec):
-    self._spec = spec
-
-  def is_subtype_of(self, other):
-    # TODO(b/202429845): Implement for subtyping.
-    return self == other
-
-  def most_specific_common_supertype(self, others):
-    # TODO(b/202430155) Implement for shape relaxation.
-    return None
-
-  def __hash__(self) -> int:
-    return hash(self._spec)
-
-  def __eq__(self, other) -> bool:
-    return isinstance(
-        other, TypeSpecTraceType) and self._spec == other._spec
-
-
 @tf_export("TypeSpec", v1=["TypeSpec", "data.experimental.Structure"])
-class TypeSpec(object, metaclass=abc.ABCMeta):
+class TypeSpec(trace.TraceType, metaclass=abc.ABCMeta):
   """Specifies a TensorFlow value type.
 
   A `tf.TypeSpec` provides metadata describing an object accepted or returned
@@ -120,6 +97,94 @@
     """
     raise NotImplementedError("%s.value_type" % type(self).__name__)
 
+  def is_subtype_of(self, other: trace.TraceType) -> bool:
+    """Returns True if `self` is a subtype of `other`.
+
+    Implements the tf.types.experimental.func.TraceType interface.
+
+    If not overridden by a subclass, the default behavior is to assume the
+    TypeSpec is covariant upon attributes that implement TraceType and
+    invariant upon rest of the attributes as well as the structure and type
+    of the TypeSpec.
+
+    Args:
+      other: A TraceType object.
+    """
+    if type(self) is not type(other):
+      return False
+
+    is_subtype = True
+    def check_attribute(attribute_self, attribute_other):
+      nonlocal is_subtype
+      if not is_subtype:
+        return
+
+      if isinstance(attribute_self, trace.TraceType):
+        if not attribute_self.is_subtype_of(attribute_other):
+          is_subtype = False
+          return
+      else:
+        if attribute_self != attribute_other:
+          is_subtype = False
+
+    try:
+      # TODO(b/217959193): Replace _serialize with parameter decomposition.
+      nest.map_structure(check_attribute, self._serialize(),
+                         other._serialize())  # pylint: disable=protected-access
+    except (ValueError, TypeError):
+      return False
+
+    return is_subtype
+
+  def most_specific_common_supertype(
+      self,
+      others: Sequence[trace.TraceType]) -> Optional["TypeSpec"]:
+    """Returns the most specific supertype TypeSpec  of `self` and `others`.
+
+    Implements the tf.types.experimental.func.TraceType interface.
+
+    If not overridden by a subclass, the default behavior is to assume the
+    TypeSpec is covariant upon attributes that implement TraceType and
+    invariant upon rest of the attributes as well as the structure and type
+    of the TypeSpec.
+
+    Args:
+      others: A sequence of TraceTypes.
+    """
+    if any(type(self) is not type(other) for other in others):
+      return None
+
+    has_supertype = True
+    def make_supertype_attribute(attribute_self, *attribute_others):
+      nonlocal has_supertype
+      if not has_supertype:
+        return
+
+      if isinstance(attribute_self, trace.TraceType):
+        attribute_supertype = attribute_self.most_specific_common_supertype(
+            attribute_others)
+        if attribute_supertype is None:
+          has_supertype = False
+          return
+        return attribute_supertype
+      else:
+        if not all(attribute_self == attribute_other
+                   for attribute_other in attribute_others):
+          has_supertype = False
+          return
+        return attribute_self
+
+    try:
+      # TODO(b/217959193): Replace _serialize with parameter decomposition.
+      serialized_supertype = nest.map_structure(
+          make_supertype_attribute, self._serialize(),
+          *(o._serialize() for o in others))  # pylint: disable=protected-access
+    except (ValueError, TypeError):
+      return None
+
+    return self._deserialize(serialized_supertype) if has_supertype else None
+
+  # TODO(b/202447704): Reduce internal usages.
   def is_compatible_with(self, spec_or_value):
     """Returns true if `spec_or_value` is compatible with this TypeSpec."""
     # === Subclassing ===
@@ -136,6 +201,7 @@
       return False
     return self.__is_compatible(self._serialize(), spec_or_value._serialize())  # pylint: disable=protected-access
 
+  # TODO(b/202447704): Deprecate.
   def most_specific_compatible_type(self, other: "TypeSpec") -> "TypeSpec":
     """Returns the most specific TypeSpec compatible with `self` and `other`.
 
@@ -237,7 +303,7 @@
 
   # === Tensor list encoding for values ===
 
-  def _to_tensor_list(self, value) -> typing.List["ops.Tensor"]:
+  def _to_tensor_list(self, value) -> List["ops.Tensor"]:
     """Encodes `value` as a flat list of `tf.Tensor`.
 
     By default, this just flattens `self._to_components(value)` using
@@ -257,7 +323,7 @@
     """
     return nest.flatten(self._to_components(value), expand_composites=True)
 
-  def _from_tensor_list(self, tensor_list: typing.List["ops.Tensor"]):
+  def _from_tensor_list(self, tensor_list: List["ops.Tensor"]) -> Any:
     """Reconstructs a value from a flat list of `tf.Tensor`.
 
     Args:
@@ -274,8 +340,8 @@
     self.__check_tensor_list(tensor_list)
     return self._from_compatible_tensor_list(tensor_list)
 
-  def _from_compatible_tensor_list(self,
-                                   tensor_list: typing.List["ops.Tensor"]):
+  def _from_compatible_tensor_list(
+      self, tensor_list: List["ops.Tensor"]) -> Any:
     """Reconstructs a value from a compatible flat list of `tf.Tensor`.
 
     Args:
@@ -372,8 +438,14 @@
 
   # === Private Helper Methods ===
 
-  def __tf_tracing_type__(self, _):
-    return TypeSpecTraceType(self)
+  # TODO(b/216206374): Currently this usage is used to represent a Tensor
+  # argument not a TensorSpec argument as it should be.
+  def __tf_tracing_type__(self,
+                          context: trace.TracingContext) -> trace.TraceType:
+    if context.include_tensor_ranks_only:
+      return self._with_tensor_ranks_only()
+    else:
+      return self
 
   def __check_tensor_list(self, tensor_list):
     """Raises an exception if tensor_list incompatible w/ flat_tensor_specs."""
@@ -733,7 +805,7 @@
     raise NotImplementedError(f"{type(self).__name__}._unbatch")
 
   @property
-  def _flat_tensor_specs(self) -> typing.List[TypeSpec]:
+  def _flat_tensor_specs(self) -> List[TypeSpec]:
     """A list of TensorSpecs compatible with self._to_tensor_list(v)."""
     component_flat_tensor_specs = nest.map_structure(
         functools.partial(get_batchable_flat_tensor_specs, context_spec=self),
@@ -742,7 +814,7 @@
 
   def _to_tensor_list(
       self,
-      value: composite_tensor.CompositeTensor) -> typing.List["ops.Tensor"]:
+      value: composite_tensor.CompositeTensor) -> List["ops.Tensor"]:
     """Encodes `value` as a flat list of `ops.Tensor`."""
     component_tensor_lists = nest.map_structure(
         batchable_to_tensor_list,
@@ -752,7 +824,7 @@
 
   def _to_batched_tensor_list(
       self,
-      value: composite_tensor.CompositeTensor) -> typing.List["ops.Tensor"]:
+      value: composite_tensor.CompositeTensor) -> List["ops.Tensor"]:
     """Encodes `value` as a flat list of `ops.Tensor` each with rank>0."""
     get_spec_tensor_list = lambda spec, v: (  # pylint: disable=g-long-lambda
         batchable_to_tensor_list(spec, v, minimum_rank=1)
@@ -767,7 +839,7 @@
     return tensor_list
 
   def _from_compatible_tensor_list(
-      self, tensor_list: typing.List["ops.Tensor"]
+      self, tensor_list: List["ops.Tensor"]
   ) -> composite_tensor.CompositeTensor:
     """Reconstructs a value from a compatible flat list of `ops.Tensor`."""
     flat_specs = nest.map_structure(
diff --git a/tensorflow/python/framework/type_spec_test.py b/tensorflow/python/framework/type_spec_test.py
index 91f4ab6..462e6a5 100644
--- a/tensorflow/python/framework/type_spec_test.py
+++ b/tensorflow/python/framework/type_spec_test.py
@@ -83,6 +83,24 @@
                value.color)
 
 
+@type_spec.register("tf.TwoTensorsSpecTwin")
+class TwoTensorsSpecTwin(TwoTensorsSpec):
+  pass
+
+
+@type_spec.register("tf.TwoTensorsSpecVariableSerialize")
+class TwoTensorsSpecVariableSerialize(TwoTensorsSpec):
+
+  def _serialize(self):
+    if self.color == "smaller_tuple":
+      return (self.x_shape, self.x_dtype, self.y_shape, self.y_dtype)
+    elif self.color == "different_order":
+      return (self.y_shape, self.x_shape, self.y_dtype, self.color,
+              self.x_dtype)
+
+    return (self.x_shape, self.x_dtype, self.y_shape, self.y_dtype, self.color)
+
+
 type_spec.register_type_spec_from_value_converter(
     TwoTensors, TwoTensorsSpec.from_value)
 
@@ -271,6 +289,133 @@
     self.assertFalse(v2 == v1)
 
   @parameterized.named_parameters(
+      ("SameValue", TwoTensorsSpec([5, 3], dtypes.int32, [None], dtypes.bool),
+       TwoTensorsSpec([5, 3], dtypes.int32, [None], dtypes.bool)),
+      ("UnknownDim", TwoTensorsSpec([5, 3], dtypes.int32, [8], dtypes.bool),
+       TwoTensorsSpec([5, None], dtypes.int32, [None], dtypes.bool)),
+      ("UnknownRank", TwoTensorsSpec([5, 3], dtypes.int32, [8], dtypes.bool),
+       TwoTensorsSpec(None, dtypes.int32, None, dtypes.bool)),
+      ("NamedTuple",
+       NestOfTensorsSpec(
+           _TestNamedTuple(
+               a=tensor_spec.TensorSpec([8, 5], dtypes.int32),
+               b=tensor_spec.TensorSpec([8, 12], dtypes.int32))),
+       NestOfTensorsSpec(
+           _TestNamedTuple(
+               a=tensor_spec.TensorSpec([None, 5], dtypes.int32),
+               b=tensor_spec.TensorSpec([None, None], dtypes.int32)))),
+      (
+          "NamedTupleRedefined",
+          NestOfTensorsSpec(
+              _TestNamedTuple2(  # Separate but equivalent type.
+                  a=tensor_spec.TensorSpec([8, 5], dtypes.int32),
+                  b=tensor_spec.TensorSpec([8, 12], dtypes.int32))),
+          NestOfTensorsSpec(
+              _TestNamedTuple(
+                  a=tensor_spec.TensorSpec([None, 5], dtypes.int32),
+                  b=tensor_spec.TensorSpec([None, None], dtypes.int32)))),
+  )
+  def testIsSubtypeOf(self, v1, v2):
+    self.assertTrue(v1.is_subtype_of(v2))
+
+  @parameterized.named_parameters(
+      ("DifferentType",
+       TwoTensorsSpec([5, 3], dtypes.int32, [None], dtypes.bool),
+       TwoTensorsSpecTwin([5, 3], dtypes.int32, [None], dtypes.bool),
+      ),
+      ("DifferentDtype",
+       TwoTensorsSpec([5, 3], dtypes.int32, [None], dtypes.bool),
+       TwoTensorsSpec([5, 3], dtypes.int32, [None], dtypes.float32)),
+      ("DifferentRank", TwoTensorsSpec([5, 3], dtypes.int32, [None],
+                                       dtypes.bool),
+       TwoTensorsSpec([5, 3], dtypes.int32, [None, None], dtypes.bool)),
+      ("DifferentDimSize",
+       TwoTensorsSpec([5, 3], dtypes.int32, [None], dtypes.bool),
+       TwoTensorsSpec([5, 8], dtypes.int32, [None], dtypes.bool)),
+      ("DifferentMetadata",
+       TwoTensorsSpec([5, 3], dtypes.int32, [3], dtypes.bool, "red"),
+       TwoTensorsSpec([5, 3], dtypes.int32, [3], dtypes.bool, "blue")),
+      ("SwappedValues", TwoTensorsSpec([5, 3], dtypes.int32, [None],
+                                       dtypes.bool),
+       TwoTensorsSpec([None], dtypes.bool, [5, 3], dtypes.int32)),
+      ("SwappedDimensions",
+       TwoTensorsSpec([3, 5], dtypes.int32, [None], dtypes.int32),
+       TwoTensorsSpec([5, 3], dtypes.int32, [None], dtypes.int32)),
+      ("Supertype", TwoTensorsSpec([5, None], dtypes.int32, [None],
+                                   dtypes.bool),
+       TwoTensorsSpec([5, 3], dtypes.int32, [8], dtypes.bool)),
+      ("SerializeDifferentStructure",
+       TwoTensorsSpecVariableSerialize([5, None], dtypes.int32, [None],
+                                       dtypes.bool),
+       TwoTensorsSpecVariableSerialize([5, None], dtypes.int32, [None],
+                                       dtypes.bool, "smaller_tuple")),
+      ("SerializeDifferentOrder",
+       TwoTensorsSpecVariableSerialize([5, None], dtypes.int32, [None],
+                                       dtypes.bool),
+       TwoTensorsSpecVariableSerialize([5, None], dtypes.int32, [None],
+                                       dtypes.bool, "different_order")),
+  )
+  def testIsNotSubtypeOf(self, v1, v2):
+    self.assertFalse(v1.is_subtype_of(v2))
+
+  @parameterized.named_parameters(
+      ("SameValue", TwoTensorsSpec([5, 3], dtypes.int32, [None], dtypes.bool),
+       TwoTensorsSpec([5, 3], dtypes.int32, [None], dtypes.bool),
+       TwoTensorsSpec([5, 3], dtypes.int32, [None], dtypes.bool)),
+      ("DifferentValue",
+       TwoTensorsSpec([2, 1], dtypes.int32, [None], dtypes.bool),
+       TwoTensorsSpec([5, 3], dtypes.int32, [None], dtypes.bool),
+       TwoTensorsSpec([None, None], dtypes.int32, [None], dtypes.bool)),
+      ("DifferentRank",
+       TwoTensorsSpec([3, 2, 1], dtypes.int32, [None], dtypes.bool),
+       TwoTensorsSpec([5, 3], dtypes.int32, [None], dtypes.bool),
+       TwoTensorsSpec(None, dtypes.int32, [None], dtypes.bool)),
+      (
+          "NamedTupleRedefined",
+          NestOfTensorsSpec(
+              _TestNamedTuple2(  # Separate but equivalent type.
+                  a=tensor_spec.TensorSpec([8, 3], dtypes.int32),
+                  b=tensor_spec.TensorSpec([8, 12], dtypes.int32))),
+          NestOfTensorsSpec(
+              _TestNamedTuple(
+                  a=tensor_spec.TensorSpec([None, 5], dtypes.int32),
+                  b=tensor_spec.TensorSpec([7, None], dtypes.int32))),
+          NestOfTensorsSpec(
+              _TestNamedTuple(
+                  a=tensor_spec.TensorSpec([None, None], dtypes.int32),
+                  b=tensor_spec.TensorSpec([None, None], dtypes.int32)))),
+  )
+  def testMostSpecificCommonSupertype(self, v1, v2, result):
+    self.assertEqual(v1.most_specific_common_supertype([v2]), result)
+    self.assertEqual(v2.most_specific_common_supertype([v1]), result)
+
+  @parameterized.named_parameters(
+      ("DifferentType",
+       TwoTensorsSpec([5, 3], dtypes.int32, [None], dtypes.bool),
+       TwoTensorsSpecTwin([5, 3], dtypes.int32, [None], dtypes.bool),
+      ),
+      ("DifferentDtype",
+       TwoTensorsSpec([5, 3], dtypes.int32, [None], dtypes.bool),
+       TwoTensorsSpec([5, 3], dtypes.int32, [None], dtypes.float32)),
+      ("DifferentMetadata",
+       TwoTensorsSpec([5, 3], dtypes.int32, [3], dtypes.bool, "red"),
+       TwoTensorsSpec([5, 3], dtypes.int32, [3], dtypes.bool, "blue")),
+      ("SerializeDifferentStructure",
+       TwoTensorsSpecVariableSerialize([5, None], dtypes.int32, [None],
+                                       dtypes.bool),
+       TwoTensorsSpecVariableSerialize([5, None], dtypes.int32, [None],
+                                       dtypes.bool, "smaller_tuple")),
+      ("SerializeDifferentOrder",
+       TwoTensorsSpecVariableSerialize([5, None], dtypes.int32, [None],
+                                       dtypes.bool),
+       TwoTensorsSpecVariableSerialize([5, None], dtypes.int32, [None],
+                                       dtypes.bool, "different_order")),
+  )
+  def testNoCommonSupertype(self, v1, v2):
+    self.assertIsNone(v1.most_specific_common_supertype([v2]))
+    self.assertIsNone(v2.most_specific_common_supertype([v1]))
+
+  @parameterized.named_parameters(
       ("SameValue",
        TwoTensorsSpec([5, 3], dtypes.int32, [None], dtypes.bool),
        TwoTensorsSpec([5, 3], dtypes.int32, [None], dtypes.bool)),
diff --git a/tensorflow/tools/api/golden/v1/tensorflow.-indexed-slices-spec.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.-indexed-slices-spec.pbtxt
index f011045..9467854 100644
--- a/tensorflow/tools/api/golden/v1/tensorflow.-indexed-slices-spec.pbtxt
+++ b/tensorflow/tools/api/golden/v1/tensorflow.-indexed-slices-spec.pbtxt
@@ -2,6 +2,7 @@
 tf_class {
   is_instance: "<class \'tensorflow.python.framework.indexed_slices.IndexedSlicesSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "value_type"
@@ -16,6 +17,14 @@
     argspec: "args=[\'self\', \'spec_or_value\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v1/tensorflow.-optional-spec.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.-optional-spec.pbtxt
index 68d4589..aab53ce 100644
--- a/tensorflow/tools/api/golden/v1/tensorflow.-optional-spec.pbtxt
+++ b/tensorflow/tools/api/golden/v1/tensorflow.-optional-spec.pbtxt
@@ -2,6 +2,7 @@
 tf_class {
   is_instance: "<class \'tensorflow.python.data.ops.optional_ops.OptionalSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "value_type"
@@ -20,6 +21,14 @@
     argspec: "args=[\'self\', \'spec_or_value\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v1/tensorflow.-ragged-tensor-spec.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.-ragged-tensor-spec.pbtxt
index a9043ab..2b7cea5 100644
--- a/tensorflow/tools/api/golden/v1/tensorflow.-ragged-tensor-spec.pbtxt
+++ b/tensorflow/tools/api/golden/v1/tensorflow.-ragged-tensor-spec.pbtxt
@@ -3,6 +3,7 @@
   is_instance: "<class \'tensorflow.python.ops.ragged.ragged_tensor.RaggedTensorSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.BatchableTypeSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "dtype"
@@ -41,6 +42,14 @@
     argspec: "args=[\'self\', \'spec_or_value\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v1/tensorflow.-sparse-tensor-spec.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.-sparse-tensor-spec.pbtxt
index 80d9853..1390d25 100644
--- a/tensorflow/tools/api/golden/v1/tensorflow.-sparse-tensor-spec.pbtxt
+++ b/tensorflow/tools/api/golden/v1/tensorflow.-sparse-tensor-spec.pbtxt
@@ -3,6 +3,7 @@
   is_instance: "<class \'tensorflow.python.framework.sparse_tensor.SparseTensorSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.BatchableTypeSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "dtype"
@@ -29,6 +30,14 @@
     argspec: "args=[\'self\', \'spec_or_value\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v1/tensorflow.-tensor-array-spec.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.-tensor-array-spec.pbtxt
index c2980e9..bc3efdc 100644
--- a/tensorflow/tools/api/golden/v1/tensorflow.-tensor-array-spec.pbtxt
+++ b/tensorflow/tools/api/golden/v1/tensorflow.-tensor-array-spec.pbtxt
@@ -2,6 +2,7 @@
 tf_class {
   is_instance: "<class \'tensorflow.python.ops.tensor_array_ops.TensorArraySpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "value_type"
@@ -20,6 +21,14 @@
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v1/tensorflow.-tensor-spec.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.-tensor-spec.pbtxt
index 55ec596..ed71970 100644
--- a/tensorflow/tools/api/golden/v1/tensorflow.-tensor-spec.pbtxt
+++ b/tensorflow/tools/api/golden/v1/tensorflow.-tensor-spec.pbtxt
@@ -4,6 +4,7 @@
   is_instance: "<class \'tensorflow.python.framework.tensor_spec.DenseSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.BatchableTypeSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "dtype"
@@ -38,6 +39,14 @@
     argspec: "args=[\'self\', \'spec_or_tensor\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v1/tensorflow.-type-spec.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.-type-spec.pbtxt
index bad5fb5..4d7b693a 100644
--- a/tensorflow/tools/api/golden/v1/tensorflow.-type-spec.pbtxt
+++ b/tensorflow/tools/api/golden/v1/tensorflow.-type-spec.pbtxt
@@ -1,6 +1,7 @@
 path: "tensorflow.TypeSpec"
 tf_class {
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "value_type"
@@ -14,6 +15,14 @@
     argspec: "args=[\'self\', \'spec_or_value\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.-dataset-spec.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.-dataset-spec.pbtxt
index f56e119..8863862 100644
--- a/tensorflow/tools/api/golden/v1/tensorflow.data.-dataset-spec.pbtxt
+++ b/tensorflow/tools/api/golden/v1/tensorflow.data.-dataset-spec.pbtxt
@@ -3,6 +3,7 @@
   is_instance: "<class \'tensorflow.python.data.ops.dataset_ops.DatasetSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.BatchableTypeSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "element_spec"
@@ -25,6 +26,14 @@
     argspec: "args=[\'self\', \'spec_or_value\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-dataset-structure.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-dataset-structure.pbtxt
index fc65345..ef7bb91 100644
--- a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-dataset-structure.pbtxt
+++ b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-dataset-structure.pbtxt
@@ -3,6 +3,7 @@
   is_instance: "<class \'tensorflow.python.data.ops.dataset_ops.DatasetSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.BatchableTypeSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "element_spec"
@@ -25,6 +26,14 @@
     argspec: "args=[\'self\', \'spec_or_value\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-optional-structure.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-optional-structure.pbtxt
index 7874a69..6af724f 100644
--- a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-optional-structure.pbtxt
+++ b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-optional-structure.pbtxt
@@ -2,6 +2,7 @@
 tf_class {
   is_instance: "<class \'tensorflow.python.data.ops.optional_ops.OptionalSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "value_type"
@@ -20,6 +21,14 @@
     argspec: "args=[\'self\', \'spec_or_value\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-structure.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-structure.pbtxt
index 3cf2e7b..68cd20f 100644
--- a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-structure.pbtxt
+++ b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-structure.pbtxt
@@ -1,6 +1,7 @@
 path: "tensorflow.data.experimental.Structure"
 tf_class {
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "value_type"
@@ -14,6 +15,14 @@
     argspec: "args=[\'self\', \'spec_or_value\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-indexed-slices-spec.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-indexed-slices-spec.pbtxt
index f011045..9467854 100644
--- a/tensorflow/tools/api/golden/v2/tensorflow.-indexed-slices-spec.pbtxt
+++ b/tensorflow/tools/api/golden/v2/tensorflow.-indexed-slices-spec.pbtxt
@@ -2,6 +2,7 @@
 tf_class {
   is_instance: "<class \'tensorflow.python.framework.indexed_slices.IndexedSlicesSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "value_type"
@@ -16,6 +17,14 @@
     argspec: "args=[\'self\', \'spec_or_value\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-optional-spec.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-optional-spec.pbtxt
index 68d4589..aab53ce 100644
--- a/tensorflow/tools/api/golden/v2/tensorflow.-optional-spec.pbtxt
+++ b/tensorflow/tools/api/golden/v2/tensorflow.-optional-spec.pbtxt
@@ -2,6 +2,7 @@
 tf_class {
   is_instance: "<class \'tensorflow.python.data.ops.optional_ops.OptionalSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "value_type"
@@ -20,6 +21,14 @@
     argspec: "args=[\'self\', \'spec_or_value\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-ragged-tensor-spec.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-ragged-tensor-spec.pbtxt
index a9043ab..2b7cea5 100644
--- a/tensorflow/tools/api/golden/v2/tensorflow.-ragged-tensor-spec.pbtxt
+++ b/tensorflow/tools/api/golden/v2/tensorflow.-ragged-tensor-spec.pbtxt
@@ -3,6 +3,7 @@
   is_instance: "<class \'tensorflow.python.ops.ragged.ragged_tensor.RaggedTensorSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.BatchableTypeSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "dtype"
@@ -41,6 +42,14 @@
     argspec: "args=[\'self\', \'spec_or_value\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-sparse-tensor-spec.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-sparse-tensor-spec.pbtxt
index 80d9853..1390d25 100644
--- a/tensorflow/tools/api/golden/v2/tensorflow.-sparse-tensor-spec.pbtxt
+++ b/tensorflow/tools/api/golden/v2/tensorflow.-sparse-tensor-spec.pbtxt
@@ -3,6 +3,7 @@
   is_instance: "<class \'tensorflow.python.framework.sparse_tensor.SparseTensorSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.BatchableTypeSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "dtype"
@@ -29,6 +30,14 @@
     argspec: "args=[\'self\', \'spec_or_value\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-tensor-array-spec.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-tensor-array-spec.pbtxt
index c2980e9..bc3efdc 100644
--- a/tensorflow/tools/api/golden/v2/tensorflow.-tensor-array-spec.pbtxt
+++ b/tensorflow/tools/api/golden/v2/tensorflow.-tensor-array-spec.pbtxt
@@ -2,6 +2,7 @@
 tf_class {
   is_instance: "<class \'tensorflow.python.ops.tensor_array_ops.TensorArraySpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "value_type"
@@ -20,6 +21,14 @@
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-tensor-spec.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-tensor-spec.pbtxt
index 55ec596..ed71970 100644
--- a/tensorflow/tools/api/golden/v2/tensorflow.-tensor-spec.pbtxt
+++ b/tensorflow/tools/api/golden/v2/tensorflow.-tensor-spec.pbtxt
@@ -4,6 +4,7 @@
   is_instance: "<class \'tensorflow.python.framework.tensor_spec.DenseSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.BatchableTypeSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "dtype"
@@ -38,6 +39,14 @@
     argspec: "args=[\'self\', \'spec_or_tensor\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-type-spec.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-type-spec.pbtxt
index bad5fb5..4d7b693a 100644
--- a/tensorflow/tools/api/golden/v2/tensorflow.-type-spec.pbtxt
+++ b/tensorflow/tools/api/golden/v2/tensorflow.-type-spec.pbtxt
@@ -1,6 +1,7 @@
 path: "tensorflow.TypeSpec"
 tf_class {
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "value_type"
@@ -14,6 +15,14 @@
     argspec: "args=[\'self\', \'spec_or_value\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v2/tensorflow.data.-dataset-spec.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.data.-dataset-spec.pbtxt
index f56e119..8863862 100644
--- a/tensorflow/tools/api/golden/v2/tensorflow.data.-dataset-spec.pbtxt
+++ b/tensorflow/tools/api/golden/v2/tensorflow.data.-dataset-spec.pbtxt
@@ -3,6 +3,7 @@
   is_instance: "<class \'tensorflow.python.data.ops.dataset_ops.DatasetSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.BatchableTypeSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "element_spec"
@@ -25,6 +26,14 @@
     argspec: "args=[\'self\', \'spec_or_value\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }
diff --git a/tensorflow/tools/api/golden/v2/tensorflow.data.-iterator-spec.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.data.-iterator-spec.pbtxt
index 6020b40..146375a 100644
--- a/tensorflow/tools/api/golden/v2/tensorflow.data.-iterator-spec.pbtxt
+++ b/tensorflow/tools/api/golden/v2/tensorflow.data.-iterator-spec.pbtxt
@@ -2,6 +2,7 @@
 tf_class {
   is_instance: "<class \'tensorflow.python.data.ops.iterator_ops.IteratorSpec\'>"
   is_instance: "<class \'tensorflow.python.framework.type_spec.TypeSpec\'>"
+  is_instance: "<class \'tensorflow.python.types.trace.TraceType\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "value_type"
@@ -20,6 +21,14 @@
     argspec: "args=[\'self\', \'spec_or_value\'], varargs=None, keywords=None, defaults=None"
   }
   member_method {
+    name: "is_subtype_of"
+    argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
+    name: "most_specific_common_supertype"
+    argspec: "args=[\'self\', \'others\'], varargs=None, keywords=None, defaults=None"
+  }
+  member_method {
     name: "most_specific_compatible_type"
     argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None"
   }