This is an automated email from the ASF dual-hosted git repository.

tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-ffi.git


The following commit(s) were added to refs/heads/main by this push:
     new e8a5516f [CORE] Invert object/type_traits dependency layering (#638)
e8a5516f is described below

commit e8a5516fa1e0e02d087d4efd7e6e9ba2244cf28a
Author: Tianqi Chen <[email protected]>
AuthorDate: Fri Jun 19 21:58:39 2026 -0400

    [CORE] Invert object/type_traits dependency layering (#638)
    
    ## Summary
    - invert the header dependency so `object.h` includes `type_traits.h`,
    and move shared type metadata/helpers like `StaticTypeKey`,
    `TypeIndexToTypeKey`, and `details::type_contains_v` into
    `type_traits.h`
    - move object and `Optional` trait specializations into their owning
    headers, move `DLTensor*` traits into `tensor.h`, and keep the
    `uint64_t` overflow-checked specialization near the end of `any.h`
    - add a narrow ASF header checker skip for `.agents/skills/**/SKILL.md`
    so skill files can keep frontmatter at byte 0
---
 .agents/skills/devtools/SKILL.md              |  17 -
 include/tvm/ffi/any.h                         |  17 +
 include/tvm/ffi/container/container_details.h |  14 -
 include/tvm/ffi/container/tensor.h            |  44 +++
 include/tvm/ffi/object.h                      | 262 ++++++++++-----
 include/tvm/ffi/optional.h                    |  62 ++++
 include/tvm/ffi/type_traits.h                 | 461 +++++++-------------------
 tests/cpp/test_any.cc                         |   1 +
 tests/cpp/test_function.cc                    |   1 +
 tests/lint/check_asf_header.py                |   6 +-
 10 files changed, 426 insertions(+), 459 deletions(-)

diff --git a/.agents/skills/devtools/SKILL.md b/.agents/skills/devtools/SKILL.md
index b1ef105f..92841f19 100644
--- a/.agents/skills/devtools/SKILL.md
+++ b/.agents/skills/devtools/SKILL.md
@@ -1,20 +1,3 @@
-<!--- Licensed to the Apache Software Foundation (ASF) under one -->
-<!--- or more contributor license agreements.  See the NOTICE file -->
-<!--- distributed with this work for additional information -->
-<!--- regarding copyright ownership.  The ASF licenses this file -->
-<!--- to you under the Apache License, Version 2.0 (the -->
-<!--- "License"); you may not use this file except in compliance -->
-<!--- with the License.  You may obtain a copy of the License at -->
-
-<!---   http://www.apache.org/licenses/LICENSE-2.0 -->
-
-<!--- Unless required by applicable law or agreed to in writing, -->
-<!--- software distributed under the License is distributed on an -->
-<!--- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -->
-<!--- KIND, either express or implied.  See the License for the -->
-<!--- specific language governing permissions and limitations -->
-<!--- under the License. -->
-
 ---
 name: devtools
 description: Developer reference for Apache TVM-FFI.
diff --git a/include/tvm/ffi/any.h b/include/tvm/ffi/any.h
index 9d7ccee5..5d754f7d 100644
--- a/include/tvm/ffi/any.h
+++ b/include/tvm/ffi/any.h
@@ -823,6 +823,23 @@ struct AnyEqual {
     }
   }
 };
+
+// Placed near the end because this specialization depends on error handling.
+template <>
+struct TypeTraits<uint64_t> : public TypeTraitsIntBase<uint64_t> {
+  TVM_FFI_INLINE static void CopyToAnyView(const uint64_t& src, TVMFFIAny* 
result) {
+    if (src > static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
+      TVM_FFI_THROW(OverflowError)
+          << "Integer value " << src << " is too large to fit in int64_t. "
+          << "Consider explicitly casting to int64_t first if this is 
intentional.";
+    }
+    TypeTraitsIntBase<uint64_t>::CopyInt64ToAnyView(static_cast<int64_t>(src), 
result);
+  }
+
+  TVM_FFI_INLINE static void MoveToAny(uint64_t src, TVMFFIAny* result) {
+    CopyToAnyView(src, result);
+  }
+};
 }  // namespace ffi
 
 // Expose to the tvm namespace for usability
diff --git a/include/tvm/ffi/container/container_details.h 
b/include/tvm/ffi/container/container_details.h
index 37277a6a..b0c5317e 100644
--- a/include/tvm/ffi/container/container_details.h
+++ b/include/tvm/ffi/container/container_details.h
@@ -178,20 +178,6 @@ inline constexpr bool all_storage_enabled_v = 
(storage_enabled_v<T> && ...);
  */
 template <typename... T>
 inline constexpr bool all_object_ref_v = (std::is_base_of_v<ObjectRef, T> && 
...);
-/**
- * \brief Check if Any storage of Derived can always be directly used as Base.
- *
- * \tparam Base The base type.
- * \tparam Derived The derived type.
- * \return True if Derived's storage can be used as Base's storage, false 
otherwise.
- */
-template <typename Base, typename Derived>
-inline constexpr bool type_contains_v =
-    std::is_base_of_v<Base, Derived> || std::is_same_v<Base, Derived>;
-// special case for Any
-template <typename Derived>
-inline constexpr bool type_contains_v<Any, Derived> = true;
-
 /*!
  * \brief Create a string of the container type.
  * \tparam V The types of the elements in the container.
diff --git a/include/tvm/ffi/container/tensor.h 
b/include/tvm/ffi/container/tensor.h
index d08e23a9..4f6e108b 100644
--- a/include/tvm/ffi/container/tensor.h
+++ b/include/tvm/ffi/container/tensor.h
@@ -884,6 +884,50 @@ inline size_t GetDataSize(const TensorView& tensor) {
   return GetDataSize(tensor.numel(), tensor.dtype());
 }
 
+// DLTensor* support lives with Tensor/TensorView because the conversion path
+// is tensor-specific and can reuse the FFI error layer.
+template <>
+struct TypeTraits<DLTensor*> : public TypeTraitsBase {
+  static constexpr bool storage_enabled = false;
+  static constexpr int32_t field_static_type_index = 
TypeIndex::kTVMFFIDLTensorPtr;
+
+  TVM_FFI_INLINE static void CopyToAnyView(DLTensor* src, TVMFFIAny* result) {
+    TVM_FFI_ICHECK_NOTNULL(src);
+    result->type_index = TypeIndex::kTVMFFIDLTensorPtr;
+    result->zero_padding = 0;
+    TVM_FFI_CLEAR_PTR_PADDING_IN_FFI_ANY(result);
+    result->v_ptr = src;
+  }
+
+  TVM_FFI_INLINE static bool CheckAnyStrict(const TVMFFIAny* src) {
+    return src->type_index == TypeIndex::kTVMFFIDLTensorPtr;
+  }
+
+  TVM_FFI_INLINE static DLTensor* CopyFromAnyViewAfterCheck(const TVMFFIAny* 
src) {
+    TVM_FFI_UNSAFE_ASSUME(src->type_index == TypeIndex::kTVMFFIDLTensorPtr);
+    return static_cast<DLTensor*>(src->v_ptr);
+  }
+
+  TVM_FFI_INLINE static void MoveToAny(DLTensor*, TVMFFIAny*) {
+    TVM_FFI_THROW(RuntimeError)
+        << "DLTensor* cannot be held in Any as it does not retain ownership, 
use Tensor instead";
+  }
+
+  TVM_FFI_INLINE static std::optional<DLTensor*> TryCastFromAnyView(const 
TVMFFIAny* src) {
+    if (src->type_index == TypeIndex::kTVMFFIDLTensorPtr) {
+      return static_cast<DLTensor*>(src->v_ptr);
+    } else if (src->type_index == TypeIndex::kTVMFFITensor) {
+      return TVMFFITensorGetDLTensorPtr(src->v_obj);
+    }
+    return std::nullopt;
+  }
+
+  TVM_FFI_INLINE static std::string TypeStr() { return 
StaticTypeKey::kTVMFFIDLTensorPtr; }
+  TVM_FFI_INLINE static std::string TypeSchema() {
+    return R"({"type":")" + std::string(StaticTypeKey::kTVMFFIDLTensorPtr) + 
R"("})";
+  }
+};
+
 // TensorView type, allow implicit casting from DLTensor*
 // NOTE: we deliberately do not support MoveToAny and MoveFromAny since it 
does not retain ownership
 template <>
diff --git a/include/tvm/ffi/object.h b/include/tvm/ffi/object.h
index 0150c0ab..2048cc5b 100644
--- a/include/tvm/ffi/object.h
+++ b/include/tvm/ffi/object.h
@@ -25,6 +25,7 @@
 
 #include <tvm/ffi/base_details.h>
 #include <tvm/ffi/c_api.h>
+#include <tvm/ffi/type_traits.h>
 
 #include <optional>
 #include <string>
@@ -34,16 +35,6 @@
 namespace tvm {
 namespace ffi {
 
-/*!
- * \brief TypeIndex enum, alias of TVMFFITypeIndex.
- */
-using TypeIndex = TVMFFITypeIndex;
-
-/*!
- * \brief TypeInfo, alias of TVMFFITypeInfo.
- */
-using TypeInfo = TVMFFITypeInfo;
-
 /*!
  * \brief Helper tag to explicitly request unsafe initialization.
  *
@@ -62,78 +53,6 @@ using TypeInfo = TVMFFITypeInfo;
  */
 struct UnsafeInit {};
 
-/*!
- * \brief Known type keys for pre-defined types.
- */
-struct StaticTypeKey {
-  /*! \brief The type key for Any */
-  static constexpr const char* kTVMFFIAny = "Any";
-  /*! \brief The type key for None */
-  static constexpr const char* kTVMFFINone = "None";
-  /*! \brief The type key for bool */
-  static constexpr const char* kTVMFFIBool = "bool";
-  /*! \brief The type key for int */
-  static constexpr const char* kTVMFFIInt = "int";
-  /*! \brief The type key for float */
-  static constexpr const char* kTVMFFIFloat = "float";
-  /*! \brief The type key for void* */
-  static constexpr const char* kTVMFFIOpaquePtr = "void*";
-  /*! \brief The type key for DataType */
-  static constexpr const char* kTVMFFIDataType = "DataType";
-  /*! \brief The type key for Device */
-  static constexpr const char* kTVMFFIDevice = "Device";
-  /*! \brief The type key for DLTensor* */
-  static constexpr const char* kTVMFFIDLTensorPtr = "DLTensor*";
-  /*! \brief The type key for const char* */
-  static constexpr const char* kTVMFFIRawStr = "const char*";
-  /*! \brief The type key for TVMFFIByteArray* */
-  static constexpr const char* kTVMFFIByteArrayPtr = "TVMFFIByteArray*";
-  /*! \brief The type key for ObjectRValueRef */
-  static constexpr const char* kTVMFFIObjectRValueRef = "ObjectRValueRef";
-  /*! \brief The type key for SmallStr */
-  static constexpr const char* kTVMFFISmallStr = "ffi.SmallStr";
-  /*! \brief The type key for SmallBytes */
-  static constexpr const char* kTVMFFISmallBytes = "ffi.SmallBytes";
-  /*! \brief The type key for Error */
-  static constexpr const char* kTVMFFIError = "ffi.Error";
-  /*! \brief The type key for Bytes */
-  static constexpr const char* kTVMFFIBytes = "ffi.Bytes";
-  /*! \brief The type key for String */
-  static constexpr const char* kTVMFFIStr = "ffi.String";
-  /*! \brief The type key for Shape */
-  static constexpr const char* kTVMFFIShape = "ffi.Shape";
-  /*! \brief The type key for Tensor */
-  static constexpr const char* kTVMFFITensor = "ffi.Tensor";
-  /*! \brief The type key for Object */
-  static constexpr const char* kTVMFFIObject = "ffi.Object";
-  /*! \brief The type key for Function */
-  static constexpr const char* kTVMFFIFunction = "ffi.Function";
-  /*! \brief The type key for Array */
-  static constexpr const char* kTVMFFIArray = "ffi.Array";
-  /*! \brief The type key for List */
-  static constexpr const char* kTVMFFIList = "ffi.List";
-  /*! \brief The type key for Map */
-  static constexpr const char* kTVMFFIMap = "ffi.Map";
-  /*! \brief The type key for Module */
-  static constexpr const char* kTVMFFIModule = "ffi.Module";
-  /*! \brief The type key for Dict */
-  static constexpr const char* kTVMFFIDict = "ffi.Dict";
-  /*! \brief The type key for VisitInterrupt */
-  static constexpr const char* kTVMFFIVisitInterrupt = "ffi.VisitInterrupt";
-  /*! \brief The type key for OpaquePyObject */
-  static constexpr const char* kTVMFFIOpaquePyObject = "ffi.OpaquePyObject";
-};
-
-/*!
- * \brief Get type key from type index
- * \param type_index The input type index
- * \return the type key
- */
-inline std::string TypeIndexToTypeKey(int32_t type_index) {
-  const TypeInfo* type_info = TVMFFIGetTypeInfo(type_index);
-  return std::string(type_info->type_key.data, type_info->type_key.size);
-}
-
 namespace details {
 // Helper to perform
 // unsafe operations related to object
@@ -1257,7 +1176,186 @@ struct ObjectUnsafe {
     return GetHeader(obj_ptr);
   }
 };
+
 }  // namespace details
+
+template <typename T>
+struct TypeToRuntimeTypeIndex<T, std::enable_if_t<std::is_base_of_v<ObjectRef, 
T>>> {
+  static int32_t v() { return T::ContainerType::RuntimeTypeIndex(); }
+};
+
+template <typename TObjRef>
+struct ObjectRefTypeTraitsBase : public TypeTraitsBase {
+  static constexpr int32_t field_static_type_index = TypeIndex::kTVMFFIObject;
+  using ContainerType = typename TObjRef::ContainerType;
+
+  TVM_FFI_INLINE static void CopyToAnyView(const TObjRef& src, TVMFFIAny* 
result) {
+    if constexpr (TObjRef::_type_is_nullable) {
+      if (!src.defined()) {
+        TypeTraits<std::nullptr_t>::CopyToAnyView(nullptr, result);
+        return;
+      }
+    }
+    TVMFFIObject* obj_ptr = 
details::ObjectUnsafe::TVMFFIObjectPtrFromObjectRef(src);
+    result->type_index = obj_ptr->type_index;
+    result->zero_padding = 0;
+    TVM_FFI_CLEAR_PTR_PADDING_IN_FFI_ANY(result);
+    result->v_obj = obj_ptr;
+  }
+
+  TVM_FFI_INLINE static void MoveToAny(TObjRef src, TVMFFIAny* result) {
+    if constexpr (TObjRef::_type_is_nullable) {
+      if (!src.defined()) {
+        TypeTraits<std::nullptr_t>::CopyToAnyView(nullptr, result);
+        return;
+      }
+    }
+    TVMFFIObject* obj_ptr = 
details::ObjectUnsafe::MoveObjectRefToTVMFFIObjectPtr(std::move(src));
+    result->type_index = obj_ptr->type_index;
+    result->zero_padding = 0;
+    TVM_FFI_CLEAR_PTR_PADDING_IN_FFI_ANY(result);
+    result->v_obj = obj_ptr;
+  }
+
+  TVM_FFI_INLINE static bool CheckAnyStrict(const TVMFFIAny* src) {
+    if constexpr (TObjRef::_type_is_nullable) {
+      if (src->type_index == TypeIndex::kTVMFFINone) return true;
+    }
+    return src->type_index >= TypeIndex::kTVMFFIStaticObjectBegin &&
+           details::IsObjectInstance<ContainerType>(src->type_index);
+  }
+
+  TVM_FFI_INLINE static TObjRef CopyFromAnyViewAfterCheck(const TVMFFIAny* 
src) {
+    if constexpr (TObjRef::_type_is_nullable) {
+      if (src->type_index == TypeIndex::kTVMFFINone) {
+        return details::ObjectUnsafe::ObjectRefFromObjectPtr<TObjRef>(nullptr);
+      }
+    }
+    return details::ObjectUnsafe::ObjectRefFromObjectPtr<TObjRef>(
+        details::ObjectUnsafe::ObjectPtrFromUnowned<Object>(src->v_obj));
+  }
+
+  TVM_FFI_INLINE static TObjRef MoveFromAnyAfterCheck(TVMFFIAny* src) {
+    if constexpr (TObjRef::_type_is_nullable) {
+      if (src->type_index == TypeIndex::kTVMFFINone) {
+        return details::ObjectUnsafe::ObjectRefFromObjectPtr<TObjRef>(nullptr);
+      }
+    }
+    ObjectPtr<ContainerType> obj_ptr =
+        details::ObjectUnsafe::ObjectPtrFromOwned<ContainerType>(src->v_obj);
+    TypeTraits<std::nullptr_t>::MoveToAny(nullptr, src);
+    return 
details::ObjectUnsafe::ObjectRefFromObjectPtr<TObjRef>(std::move(obj_ptr));
+  }
+
+  TVM_FFI_INLINE static std::optional<TObjRef> TryCastFromAnyView(const 
TVMFFIAny* src) {
+    if constexpr (TObjRef::_type_is_nullable) {
+      if (src->type_index == TypeIndex::kTVMFFINone) {
+        return details::ObjectUnsafe::ObjectRefFromObjectPtr<TObjRef>(nullptr);
+      }
+    }
+    if (src->type_index >= TypeIndex::kTVMFFIStaticObjectBegin &&
+        details::IsObjectInstance<ContainerType>(src->type_index)) {
+      return details::ObjectUnsafe::ObjectRefFromObjectPtr<TObjRef>(
+          
details::ObjectUnsafe::ObjectPtrFromUnowned<ContainerType>(src->v_obj));
+    }
+    return std::nullopt;
+  }
+
+  TVM_FFI_INLINE static std::string TypeStr() { return 
ContainerType::_type_key; }
+  TVM_FFI_INLINE static std::string TypeSchema() {
+    return R"({"type":")" + std::string(ContainerType::_type_key) + R"("})";
+  }
+};
+
+template <typename TObjRef>
+struct TypeTraits<TObjRef, std::enable_if_t<std::is_base_of_v<ObjectRef, 
TObjRef> &&
+                                            
use_default_type_traits_v<TObjRef>>>
+    : public ObjectRefTypeTraitsBase<TObjRef> {};
+
+/*!
+ * \brief Helper class to define ObjectRef that can be auto-converted from a
+ *        fallback type, the Traits<ObjectRefType> must be derived from it
+ *        and define a static methods named ConvertFallbackValue for each
+ *        FallbackType
+ *
+ *        The conversion will go through the FallbackTypes in the order
+ *        specified in the template parameter.
+ * \tparam ObjectRefType The type of the ObjectRef.
+ * \tparam FallbackTypes The type of the fallback value.
+ */
+template <typename ObjectRefType, typename... FallbackTypes>
+struct ObjectRefWithFallbackTraitsBase : public 
ObjectRefTypeTraitsBase<ObjectRefType> {
+  /// \cond Doxygen_Suppress
+  TVM_FFI_INLINE static std::optional<ObjectRefType> TryCastFromAnyView(const 
TVMFFIAny* src) {
+    if (auto opt_obj = 
ObjectRefTypeTraitsBase<ObjectRefType>::TryCastFromAnyView(src)) {
+      return opt_obj;
+    }
+    return TryFallbackTypes<FallbackTypes...>(src);
+  }
+
+  template <typename FallbackType, typename... Rest>
+  TVM_FFI_INLINE static std::optional<ObjectRefType> TryFallbackTypes(const 
TVMFFIAny* src) {
+    static_assert(!std::is_same_v<bool, FallbackType>,
+                  "Using bool as FallbackType can cause bug because int will 
be detected as bool, "
+                  "use tvm::ffi::StrictBool instead");
+    if (auto opt_fallback = TypeTraits<FallbackType>::TryCastFromAnyView(src)) 
{
+      return 
TypeTraits<ObjectRefType>::ConvertFallbackValue(*std::move(opt_fallback));
+    }
+    if constexpr (sizeof...(Rest) > 0) {
+      return TryFallbackTypes<Rest...>(src);
+    }
+    return std::nullopt;
+  }
+  /// \endcond
+};
+
+template <typename TObject>
+struct TypeTraits<TObject*, std::enable_if_t<std::is_base_of_v<Object, 
TObject>>>
+    : public TypeTraitsBase {
+  TVM_FFI_INLINE static void CopyToAnyView(TObject* src, TVMFFIAny* result) {
+    TVMFFIObject* obj_ptr = details::ObjectUnsafe::GetHeader(src);
+    result->type_index = obj_ptr->type_index;
+    result->zero_padding = 0;
+    TVM_FFI_CLEAR_PTR_PADDING_IN_FFI_ANY(result);
+    result->v_obj = obj_ptr;
+  }
+
+  TVM_FFI_INLINE static void MoveToAny(TObject* src, TVMFFIAny* result) {
+    TVMFFIObject* obj_ptr = details::ObjectUnsafe::GetHeader(src);
+    result->type_index = obj_ptr->type_index;
+    result->zero_padding = 0;
+    TVM_FFI_CLEAR_PTR_PADDING_IN_FFI_ANY(result);
+    result->v_obj = obj_ptr;
+    details::ObjectUnsafe::IncRefObjectHandle(result->v_obj);
+  }
+
+  TVM_FFI_INLINE static bool CheckAnyStrict(const TVMFFIAny* src) {
+    return src->type_index >= TypeIndex::kTVMFFIStaticObjectBegin &&
+           details::IsObjectInstance<TObject>(src->type_index);
+  }
+
+  TVM_FFI_INLINE static TObject* CopyFromAnyViewAfterCheck(const TVMFFIAny* 
src) {
+    if constexpr (!std::is_const_v<TObject>) {
+      static_assert(TObject::_type_mutable, "TObject must be mutable to enable 
cast from Any");
+    }
+    return details::ObjectUnsafe::RawObjectPtrFromUnowned<TObject>(src->v_obj);
+  }
+
+  TVM_FFI_INLINE static std::optional<TObject*> TryCastFromAnyView(const 
TVMFFIAny* src) {
+    if constexpr (!std::is_const_v<TObject>) {
+      static_assert(TObject::_type_mutable, "TObject must be mutable to enable 
cast from Any");
+    }
+    if (CheckAnyStrict(src)) return CopyFromAnyViewAfterCheck(src);
+    return std::nullopt;
+  }
+
+  TVM_FFI_INLINE static std::string TypeStr() { return TObject::_type_key; }
+  TVM_FFI_INLINE static std::string TypeSchema() {
+    return R"({"type":")" + std::string(TObject::_type_key) + R"("})";
+  }
+};
+
 }  // namespace ffi
 }  // namespace tvm
+
 #endif  // TVM_FFI_OBJECT_H_
diff --git a/include/tvm/ffi/optional.h b/include/tvm/ffi/optional.h
index f43a078f..b28f7105 100644
--- a/include/tvm/ffi/optional.h
+++ b/include/tvm/ffi/optional.h
@@ -413,6 +413,68 @@ class Optional<T, 
std::enable_if_t<use_ptr_based_optional_v<T>>> : public Object
     }
   }
 };
+
+template <typename T>
+inline constexpr bool use_default_type_traits_v<Optional<T>> = false;
+
+template <typename T>
+struct TypeTraits<Optional<T>> : public TypeTraitsBase {
+  TVM_FFI_INLINE static void CopyToAnyView(const Optional<T>& src, TVMFFIAny* 
result) {
+    if (src.has_value()) {
+      TypeTraits<T>::CopyToAnyView(*src, result);
+    } else {
+      TypeTraits<std::nullptr_t>::CopyToAnyView(nullptr, result);
+    }
+  }
+
+  TVM_FFI_INLINE static void MoveToAny(Optional<T> src, TVMFFIAny* result) {
+    if (src.has_value()) {
+      TypeTraits<T>::MoveToAny(*std::move(src), result);
+    } else {
+      TypeTraits<std::nullptr_t>::CopyToAnyView(nullptr, result);
+    }
+  }
+
+  TVM_FFI_INLINE static bool CheckAnyStrict(const TVMFFIAny* src) {
+    if (src->type_index == TypeIndex::kTVMFFINone) return true;
+    return TypeTraits<T>::CheckAnyStrict(src);
+  }
+
+  TVM_FFI_INLINE static Optional<T> CopyFromAnyViewAfterCheck(const TVMFFIAny* 
src) {
+    if (src->type_index == TypeIndex::kTVMFFINone) {
+      return Optional<T>(std::nullopt);
+    }
+    return TypeTraits<T>::CopyFromAnyViewAfterCheck(src);
+  }
+
+  TVM_FFI_INLINE static Optional<T> MoveFromAnyAfterCheck(TVMFFIAny* src) {
+    if (src->type_index == TypeIndex::kTVMFFINone) {
+      return Optional<T>(std::nullopt);
+    }
+    return TypeTraits<T>::MoveFromAnyAfterCheck(src);
+  }
+
+  TVM_FFI_INLINE static std::optional<Optional<T>> TryCastFromAnyView(const 
TVMFFIAny* src) {
+    if (src->type_index == TypeIndex::kTVMFFINone) return 
Optional<T>(std::nullopt);
+    if (std::optional<T> opt = TypeTraits<T>::TryCastFromAnyView(src)) {
+      return Optional<T>(*std::move(opt));
+    }
+    // Important to be explicit here because nullopt can convert to
+    // std::optional<T>(nullopt), which would incorrectly signal success.
+    return std::optional<Optional<T>>(std::nullopt);
+  }
+
+  TVM_FFI_INLINE static std::string GetMismatchTypeInfo(const TVMFFIAny* src) {
+    return TypeTraits<T>::GetMismatchTypeInfo(src);
+  }
+
+  TVM_FFI_INLINE static std::string TypeStr() {
+    return "Optional<" + TypeTraits<T>::TypeStr() + ">";
+  }
+  TVM_FFI_INLINE static std::string TypeSchema() {
+    return R"({"type":"Optional","args":[)" + details::TypeSchema<T>::v() + 
"]}";
+  }
+};
 }  // namespace ffi
 }  // namespace tvm
 #endif  // TVM_FFI_OPTIONAL_H_
diff --git a/include/tvm/ffi/type_traits.h b/include/tvm/ffi/type_traits.h
index deb82474..2810e3fe 100644
--- a/include/tvm/ffi/type_traits.h
+++ b/include/tvm/ffi/type_traits.h
@@ -17,18 +17,17 @@
  * under the License.
  */
 /*!
- * \file tvm/ffi/object.h
- * \brief A managed object in the TVM FFI.
+ * \file tvm/ffi/type_traits.h
+ * \brief Type trait helpers for FFI values.
  */
 #ifndef TVM_FFI_TYPE_TRAITS_H_
 #define TVM_FFI_TYPE_TRAITS_H_
 
 #include <tvm/ffi/base_details.h>
 #include <tvm/ffi/c_api.h>
-#include <tvm/ffi/error.h>
-#include <tvm/ffi/object.h>
 
 #include <limits>
+#include <optional>
 #include <string>
 #include <type_traits>
 #include <utility>
@@ -38,6 +37,104 @@ namespace ffi {
 
 class Any;
 
+/*!
+ * \brief TypeIndex enum, alias of TVMFFITypeIndex.
+ */
+using TypeIndex = TVMFFITypeIndex;
+/*!
+ * \brief TypeInfo, alias of TVMFFITypeInfo.
+ */
+using TypeInfo = TVMFFITypeInfo;
+
+/*!
+ * \brief Known type keys for pre-defined types.
+ */
+struct StaticTypeKey {
+  /*! \brief The type key for Any */
+  static constexpr const char* kTVMFFIAny = "Any";
+  /*! \brief The type key for None */
+  static constexpr const char* kTVMFFINone = "None";
+  /*! \brief The type key for bool */
+  static constexpr const char* kTVMFFIBool = "bool";
+  /*! \brief The type key for int */
+  static constexpr const char* kTVMFFIInt = "int";
+  /*! \brief The type key for float */
+  static constexpr const char* kTVMFFIFloat = "float";
+  /*! \brief The type key for void* */
+  static constexpr const char* kTVMFFIOpaquePtr = "void*";
+  /*! \brief The type key for DataType */
+  static constexpr const char* kTVMFFIDataType = "DataType";
+  /*! \brief The type key for Device */
+  static constexpr const char* kTVMFFIDevice = "Device";
+  /*! \brief The type key for DLTensor* */
+  static constexpr const char* kTVMFFIDLTensorPtr = "DLTensor*";
+  /*! \brief The type key for const char* */
+  static constexpr const char* kTVMFFIRawStr = "const char*";
+  /*! \brief The type key for TVMFFIByteArray* */
+  static constexpr const char* kTVMFFIByteArrayPtr = "TVMFFIByteArray*";
+  /*! \brief The type key for ObjectRValueRef */
+  static constexpr const char* kTVMFFIObjectRValueRef = "ObjectRValueRef";
+  /*! \brief The type key for SmallStr */
+  static constexpr const char* kTVMFFISmallStr = "ffi.SmallStr";
+  /*! \brief The type key for SmallBytes */
+  static constexpr const char* kTVMFFISmallBytes = "ffi.SmallBytes";
+  /*! \brief The type key for Error */
+  static constexpr const char* kTVMFFIError = "ffi.Error";
+  /*! \brief The type key for Bytes */
+  static constexpr const char* kTVMFFIBytes = "ffi.Bytes";
+  /*! \brief The type key for String */
+  static constexpr const char* kTVMFFIStr = "ffi.String";
+  /*! \brief The type key for Shape */
+  static constexpr const char* kTVMFFIShape = "ffi.Shape";
+  /*! \brief The type key for Tensor */
+  static constexpr const char* kTVMFFITensor = "ffi.Tensor";
+  /*! \brief The type key for Object */
+  static constexpr const char* kTVMFFIObject = "ffi.Object";
+  /*! \brief The type key for Function */
+  static constexpr const char* kTVMFFIFunction = "ffi.Function";
+  /*! \brief The type key for Array */
+  static constexpr const char* kTVMFFIArray = "ffi.Array";
+  /*! \brief The type key for List */
+  static constexpr const char* kTVMFFIList = "ffi.List";
+  /*! \brief The type key for Map */
+  static constexpr const char* kTVMFFIMap = "ffi.Map";
+  /*! \brief The type key for Module */
+  static constexpr const char* kTVMFFIModule = "ffi.Module";
+  /*! \brief The type key for Dict */
+  static constexpr const char* kTVMFFIDict = "ffi.Dict";
+  /*! \brief The type key for VisitInterrupt */
+  static constexpr const char* kTVMFFIVisitInterrupt = "ffi.VisitInterrupt";
+  /*! \brief The type key for OpaquePyObject */
+  static constexpr const char* kTVMFFIOpaquePyObject = "ffi.OpaquePyObject";
+};
+
+/*!
+ * \brief Get type key from type index
+ * \param type_index The input type index
+ * \return the type key
+ */
+inline std::string TypeIndexToTypeKey(int32_t type_index) {
+  const TypeInfo* type_info = TVMFFIGetTypeInfo(type_index);
+  return std::string(type_info->type_key.data, type_info->type_key.size);
+}
+
+namespace details {
+/*!
+ * \brief Check whether `Derived` can reuse `Base` storage directly.
+ *
+ * \tparam Base The base type.
+ * \tparam Derived The derived type.
+ * \return True if Derived's storage can be used as Base's storage, false 
otherwise.
+ */
+template <typename Base, typename Derived>
+inline constexpr bool type_contains_v =
+    std::is_base_of_v<Base, Derived> || std::is_same_v<Base, Derived>;
+
+// Special case for Any, which can store any compatible value directly.
+template <typename Derived>
+inline constexpr bool type_contains_v<Any, Derived> = true;
+}  // namespace details
+
 /*!
  * \brief TypeTraits that specifies the conversion behavior from/to FFI Any.
  *
@@ -126,11 +223,6 @@ struct TypeToRuntimeTypeIndex {
   static int32_t v() { return TypeToFieldStaticTypeIndex<T>::value; }
 };
 
-template <typename T>
-struct TypeToRuntimeTypeIndex<T, std::enable_if_t<std::is_base_of_v<ObjectRef, 
T>>> {
-  static int32_t v() { return T::ContainerType::RuntimeTypeIndex(); }
-};
-
 // None
 template <>
 struct TypeTraits<std::nullptr_t> : public TypeTraitsBase {
@@ -277,26 +369,16 @@ struct TypeTraits<bool> : public TypeTraitsBase {
   }
 };
 
-// Integer POD values
 template <typename Int>
-struct TypeTraits<Int, std::enable_if_t<std::is_integral_v<Int>>> : public 
TypeTraitsBase {
+struct TypeTraitsIntBase : public TypeTraitsBase {
   static constexpr int32_t field_static_type_index = TypeIndex::kTVMFFIInt;
 
-  TVM_FFI_INLINE static void CopyToAnyView(const Int& src, TVMFFIAny* result) {
-    if constexpr (std::is_unsigned_v<Int> && sizeof(Int) >= sizeof(int64_t)) {
-      if (src > static_cast<Int>(std::numeric_limits<int64_t>::max())) {
-        TVM_FFI_THROW(OverflowError)
-            << "Integer value " << src << " is too large to fit in int64_t. "
-            << "Consider explicitly casting to int64_t first if this is 
intentional.";
-      }
-    }
+  TVM_FFI_INLINE static void CopyInt64ToAnyView(int64_t src, TVMFFIAny* 
result) {
     result->type_index = TypeIndex::kTVMFFIInt;
     result->zero_padding = 0;
-    result->v_int64 = static_cast<int64_t>(src);  // 
NOLINT(bugprone-signed-char-misuse)
+    result->v_int64 = src;
   }
 
-  TVM_FFI_INLINE static void MoveToAny(Int src, TVMFFIAny* result) { 
CopyToAnyView(src, result); }
-
   TVM_FFI_INLINE static bool CheckAnyStrict(const TVMFFIAny* src) {
     // NOTE: CheckAnyStrict is always strict and should be consistent with 
MoveToAny
     return src->type_index == TypeIndex::kTVMFFIInt;
@@ -325,6 +407,16 @@ struct TypeTraits<Int, 
std::enable_if_t<std::is_integral_v<Int>>> : public TypeT
   }
 };
 
+// Integer POD values
+template <typename Int>
+struct TypeTraits<Int, std::enable_if_t<std::is_integral_v<Int>>> : public 
TypeTraitsIntBase<Int> {
+  TVM_FFI_INLINE static void CopyToAnyView(const Int& src, TVMFFIAny* result) {
+    TypeTraitsIntBase<Int>::CopyInt64ToAnyView(static_cast<int64_t>(src), 
result);
+  }
+
+  TVM_FFI_INLINE static void MoveToAny(Int src, TVMFFIAny* result) { 
CopyToAnyView(src, result); }
+};
+
 /// \cond Doxygen_Suppress
 
 // trait to check if a type is an integeral enum
@@ -340,45 +432,15 @@ constexpr bool is_integeral_enum_v<T, true> = 
std::is_integral_v<std::underlying
 
 // Enum Integer POD values
 template <typename IntEnum>
-struct TypeTraits<IntEnum, std::enable_if_t<is_integeral_enum_v<IntEnum>>> : 
public TypeTraitsBase {
-  static constexpr int32_t field_static_type_index = TypeIndex::kTVMFFIInt;
-
+struct TypeTraits<IntEnum, std::enable_if_t<is_integeral_enum_v<IntEnum>>>
+    : public TypeTraitsIntBase<IntEnum> {
   TVM_FFI_INLINE static void CopyToAnyView(const IntEnum& src, TVMFFIAny* 
result) {
-    result->type_index = TypeIndex::kTVMFFIInt;
-    result->zero_padding = 0;
-    result->v_int64 = static_cast<int64_t>(src);
+    TypeTraitsIntBase<IntEnum>::CopyInt64ToAnyView(static_cast<int64_t>(src), 
result);
   }
 
   TVM_FFI_INLINE static void MoveToAny(IntEnum src, TVMFFIAny* result) {
     CopyToAnyView(src, result);
   }
-
-  TVM_FFI_INLINE static bool CheckAnyStrict(const TVMFFIAny* src) {
-    // NOTE: CheckAnyStrict is always strict and should be consistent with 
MoveToAny
-    return src->type_index == TypeIndex::kTVMFFIInt;
-  }
-
-  TVM_FFI_INLINE static IntEnum CopyFromAnyViewAfterCheck(const TVMFFIAny* 
src) {
-    TVM_FFI_UNSAFE_ASSUME(src->type_index == TypeIndex::kTVMFFIInt);
-    return static_cast<IntEnum>(src->v_int64);
-  }
-
-  TVM_FFI_INLINE static IntEnum MoveFromAnyAfterCheck(TVMFFIAny* src) {
-    // POD type, we can just copy the value
-    return CopyFromAnyViewAfterCheck(src);
-  }
-
-  TVM_FFI_INLINE static std::optional<IntEnum> TryCastFromAnyView(const 
TVMFFIAny* src) {
-    if (src->type_index == TypeIndex::kTVMFFIInt || src->type_index == 
TypeIndex::kTVMFFIBool) {
-      return static_cast<IntEnum>(src->v_int64);
-    }
-    return std::nullopt;
-  }
-
-  TVM_FFI_INLINE static std::string TypeStr() { return 
StaticTypeKey::kTVMFFIInt; }
-  TVM_FFI_INLINE static std::string TypeSchema() {
-    return R"({"type":")" + std::string(StaticTypeKey::kTVMFFIInt) + R"("})";
-  }
 };
 
 // Float POD values
@@ -515,144 +577,6 @@ struct TypeTraits<DLDevice> : public TypeTraitsBase {
   }
 };
 
-// DLTensor*, requirement: not nullable, do not retain ownership
-template <>
-struct TypeTraits<DLTensor*> : public TypeTraitsBase {
-  static constexpr bool storage_enabled = false;
-  static constexpr int32_t field_static_type_index = 
TypeIndex::kTVMFFIDLTensorPtr;
-
-  TVM_FFI_INLINE static void CopyToAnyView(DLTensor* src, TVMFFIAny* result) {
-    TVM_FFI_ICHECK_NOTNULL(src);
-    result->type_index = TypeIndex::kTVMFFIDLTensorPtr;
-    result->zero_padding = 0;
-    TVM_FFI_CLEAR_PTR_PADDING_IN_FFI_ANY(result);
-    result->v_ptr = src;
-  }
-
-  TVM_FFI_INLINE static bool CheckAnyStrict(const TVMFFIAny* src) {
-    return src->type_index == TypeIndex::kTVMFFIDLTensorPtr;
-  }
-
-  TVM_FFI_INLINE static DLTensor* CopyFromAnyViewAfterCheck(const TVMFFIAny* 
src) {
-    TVM_FFI_UNSAFE_ASSUME(src->type_index == TypeIndex::kTVMFFIDLTensorPtr);
-    return static_cast<DLTensor*>(src->v_ptr);
-  }
-
-  TVM_FFI_INLINE static void MoveToAny(DLTensor*, TVMFFIAny*) {
-    TVM_FFI_THROW(RuntimeError)
-        << "DLTensor* cannot be held in Any as it does not retain ownership, 
use Tensor instead";
-  }
-
-  TVM_FFI_INLINE static std::optional<DLTensor*> TryCastFromAnyView(const 
TVMFFIAny* src) {
-    if (src->type_index == TypeIndex::kTVMFFIDLTensorPtr) {
-      return static_cast<DLTensor*>(src->v_ptr);
-    } else if (src->type_index == TypeIndex::kTVMFFITensor) {
-      // Conversion from Tensor pointer to DLTensor
-      // based on the assumption that Tensor always follows the TVMFFIObject 
header
-      static_assert(sizeof(TVMFFIObject) == 24);
-      return reinterpret_cast<DLTensor*>(reinterpret_cast<char*>(src->v_obj) +
-                                         sizeof(TVMFFIObject));
-    }
-    return std::nullopt;
-  }
-
-  TVM_FFI_INLINE static std::string TypeStr() { return "DLTensor*"; }
-  TVM_FFI_INLINE static std::string TypeSchema() { return 
R"({"type":"DLTensor*"})"; }
-};
-
-// Traits for ObjectRef, None to ObjectRef will always fail.
-// use std::optional<ObjectRef> instead for nullable references.
-template <typename TObjRef>
-struct ObjectRefTypeTraitsBase : public TypeTraitsBase {
-  static constexpr int32_t field_static_type_index = TypeIndex::kTVMFFIObject;
-  using ContainerType = typename TObjRef::ContainerType;
-
-  TVM_FFI_INLINE static void CopyToAnyView(const TObjRef& src, TVMFFIAny* 
result) {
-    if constexpr (TObjRef::_type_is_nullable) {
-      if (!src.defined()) {
-        TypeTraits<std::nullptr_t>::CopyToAnyView(nullptr, result);
-        return;
-      }
-    }
-    TVMFFIObject* obj_ptr = 
details::ObjectUnsafe::TVMFFIObjectPtrFromObjectRef(src);
-    result->type_index = obj_ptr->type_index;
-    result->zero_padding = 0;
-    TVM_FFI_CLEAR_PTR_PADDING_IN_FFI_ANY(result);
-    result->v_obj = obj_ptr;
-  }
-
-  TVM_FFI_INLINE static void MoveToAny(TObjRef src, TVMFFIAny* result) {
-    if constexpr (TObjRef::_type_is_nullable) {
-      if (!src.defined()) {
-        TypeTraits<std::nullptr_t>::CopyToAnyView(nullptr, result);
-        return;
-      }
-    }
-    TVMFFIObject* obj_ptr = 
details::ObjectUnsafe::MoveObjectRefToTVMFFIObjectPtr(std::move(src));
-    result->type_index = obj_ptr->type_index;
-    result->zero_padding = 0;
-    TVM_FFI_CLEAR_PTR_PADDING_IN_FFI_ANY(result);
-    result->v_obj = obj_ptr;
-  }
-
-  TVM_FFI_INLINE static bool CheckAnyStrict(const TVMFFIAny* src) {
-    if constexpr (TObjRef::_type_is_nullable) {
-      if (src->type_index == TypeIndex::kTVMFFINone) return true;
-    }
-    return (src->type_index >= TypeIndex::kTVMFFIStaticObjectBegin &&
-            details::IsObjectInstance<ContainerType>(src->type_index));
-  }
-
-  TVM_FFI_INLINE static TObjRef CopyFromAnyViewAfterCheck(const TVMFFIAny* 
src) {
-    if constexpr (TObjRef::_type_is_nullable) {
-      if (src->type_index == TypeIndex::kTVMFFINone) {
-        return details::ObjectUnsafe::ObjectRefFromObjectPtr<TObjRef>(nullptr);
-      }
-    }
-    return details::ObjectUnsafe::ObjectRefFromObjectPtr<TObjRef>(
-        details::ObjectUnsafe::ObjectPtrFromUnowned<Object>(src->v_obj));
-  }
-
-  TVM_FFI_INLINE static TObjRef MoveFromAnyAfterCheck(TVMFFIAny* src) {
-    if constexpr (TObjRef::_type_is_nullable) {
-      if (src->type_index == TypeIndex::kTVMFFINone) {
-        return details::ObjectUnsafe::ObjectRefFromObjectPtr<TObjRef>(nullptr);
-      }
-    }
-    // move out the object pointer
-    ObjectPtr<ContainerType> obj_ptr =
-        details::ObjectUnsafe::ObjectPtrFromOwned<ContainerType>(src->v_obj);
-    // reset the src to nullptr
-    TypeTraits<std::nullptr_t>::MoveToAny(nullptr, src);
-    return 
details::ObjectUnsafe::ObjectRefFromObjectPtr<TObjRef>(std::move(obj_ptr));
-  }
-
-  TVM_FFI_INLINE static std::optional<TObjRef> TryCastFromAnyView(const 
TVMFFIAny* src) {
-    if constexpr (TObjRef::_type_is_nullable) {
-      if (src->type_index == TypeIndex::kTVMFFINone) {
-        return details::ObjectUnsafe::ObjectRefFromObjectPtr<TObjRef>(nullptr);
-      }
-    }
-    if (src->type_index >= TypeIndex::kTVMFFIStaticObjectBegin) {
-      if (details::IsObjectInstance<ContainerType>(src->type_index)) {
-        return details::ObjectUnsafe::ObjectRefFromObjectPtr<TObjRef>(
-            
details::ObjectUnsafe::ObjectPtrFromUnowned<ContainerType>(src->v_obj));
-      }
-    }
-    return std::nullopt;
-  }
-
-  TVM_FFI_INLINE static std::string TypeStr() { return 
ContainerType::_type_key; }
-  TVM_FFI_INLINE static std::string TypeSchema() {
-    return R"({"type":")" + std::string(ContainerType::_type_key) + R"("})";
-  }
-};
-
-template <typename TObjRef>
-struct TypeTraits<TObjRef, std::enable_if_t<std::is_base_of_v<ObjectRef, 
TObjRef> &&
-                                            
use_default_type_traits_v<TObjRef>>>
-    : public ObjectRefTypeTraitsBase<TObjRef> {};
-
 /*!
  * \brief Helper class that convert to T only via the FallbackTypes
  *
@@ -689,157 +613,6 @@ struct FallbackOnlyTraitsBase : public TypeTraitsBase {
   /// \endcond
 };
 
-/*!
- * \brief Helper class to define ObjectRef that can be auto-converted from a
- *        fallback type, the Traits<ObjectRefType> must be derived from it
- *        and define a static methods named ConvertFallbackValue for each
- *        FallbackType
- *
- *        The conversion will go through the FallbackTypes in the order
- *        specified in the template parameter.
- * \tparam ObjectRefType The type of the ObjectRef.
- * \tparam FallbackTypes The type of the fallback value.
- */
-template <typename ObjectRefType, typename... FallbackTypes>
-struct ObjectRefWithFallbackTraitsBase : public 
ObjectRefTypeTraitsBase<ObjectRefType> {
-  /// \cond Doxygen_Suppress
-  TVM_FFI_INLINE static std::optional<ObjectRefType> TryCastFromAnyView(const 
TVMFFIAny* src) {
-    if (auto opt_obj = 
ObjectRefTypeTraitsBase<ObjectRefType>::TryCastFromAnyView(src)) {
-      return opt_obj;
-    }
-    // apply fallback types in TryCastFromAnyView
-    return TryFallbackTypes<FallbackTypes...>(src);
-  }
-
-  template <typename FallbackType, typename... Rest>
-  TVM_FFI_INLINE static std::optional<ObjectRefType> TryFallbackTypes(const 
TVMFFIAny* src) {
-    static_assert(!std::is_same_v<bool, FallbackType>,
-                  "Using bool as FallbackType can cause bug because int will 
be detected as bool, "
-                  "use tvm::ffi::StrictBool instead");
-    if (auto opt_fallback = TypeTraits<FallbackType>::TryCastFromAnyView(src)) 
{
-      return 
TypeTraits<ObjectRefType>::ConvertFallbackValue(*std::move(opt_fallback));
-    }
-    if constexpr (sizeof...(Rest) > 0) {
-      return TryFallbackTypes<Rest...>(src);
-    }
-    return std::nullopt;
-  }
-  /// \endcond
-};
-
-// Traits for weak pointer of object
-// NOTE: we require the weak pointer cast from
-
-template <typename TObject>
-struct TypeTraits<TObject*, std::enable_if_t<std::is_base_of_v<Object, 
TObject>>>
-    : public TypeTraitsBase {
-  TVM_FFI_INLINE static void CopyToAnyView(TObject* src, TVMFFIAny* result) {
-    TVMFFIObject* obj_ptr = details::ObjectUnsafe::GetHeader(src);
-    result->type_index = obj_ptr->type_index;
-    result->zero_padding = 0;
-    TVM_FFI_CLEAR_PTR_PADDING_IN_FFI_ANY(result);
-    result->v_obj = obj_ptr;
-  }
-
-  TVM_FFI_INLINE static void MoveToAny(TObject* src, TVMFFIAny* result) {
-    TVMFFIObject* obj_ptr = details::ObjectUnsafe::GetHeader(src);
-    result->type_index = obj_ptr->type_index;
-    result->zero_padding = 0;
-    TVM_FFI_CLEAR_PTR_PADDING_IN_FFI_ANY(result);
-    result->v_obj = obj_ptr;
-    // needs to increase ref because original weak ptr do not own the code
-    details::ObjectUnsafe::IncRefObjectHandle(result->v_obj);
-  }
-
-  TVM_FFI_INLINE static bool CheckAnyStrict(const TVMFFIAny* src) {
-    return src->type_index >= TypeIndex::kTVMFFIStaticObjectBegin &&
-           details::IsObjectInstance<TObject>(src->type_index);
-  }
-
-  TVM_FFI_INLINE static TObject* CopyFromAnyViewAfterCheck(const TVMFFIAny* 
src) {
-    if constexpr (!std::is_const_v<TObject>) {
-      static_assert(TObject::_type_mutable, "TObject must be mutable to enable 
cast from Any");
-    }
-    return details::ObjectUnsafe::RawObjectPtrFromUnowned<TObject>(src->v_obj);
-  }
-
-  TVM_FFI_INLINE static std::optional<TObject*> TryCastFromAnyView(const 
TVMFFIAny* src) {
-    if constexpr (!std::is_const_v<TObject>) {
-      static_assert(TObject::_type_mutable, "TObject must be mutable to enable 
cast from Any");
-    }
-    if (CheckAnyStrict(src)) return CopyFromAnyViewAfterCheck(src);
-    return std::nullopt;
-  }
-
-  TVM_FFI_INLINE static std::string TypeStr() { return TObject::_type_key; }
-  TVM_FFI_INLINE static std::string TypeSchema() {
-    return R"({"type":")" + std::string(TObject::_type_key) + R"("})";
-  }
-};
-
-template <typename T>
-inline constexpr bool use_default_type_traits_v<Optional<T>> = false;
-
-template <typename T>
-struct TypeTraits<Optional<T>> : public TypeTraitsBase {
-  TVM_FFI_INLINE static void CopyToAnyView(const Optional<T>& src, TVMFFIAny* 
result) {
-    if (src.has_value()) {
-      TypeTraits<T>::CopyToAnyView(*src, result);
-    } else {
-      TypeTraits<std::nullptr_t>::CopyToAnyView(nullptr, result);
-    }
-  }
-
-  TVM_FFI_INLINE static void MoveToAny(Optional<T> src, TVMFFIAny* result) {
-    if (src.has_value()) {
-      TypeTraits<T>::MoveToAny(*std::move(src), result);
-    } else {
-      TypeTraits<std::nullptr_t>::CopyToAnyView(nullptr, result);
-    }
-  }
-
-  TVM_FFI_INLINE static bool CheckAnyStrict(const TVMFFIAny* src) {
-    if (src->type_index == TypeIndex::kTVMFFINone) return true;
-    return TypeTraits<T>::CheckAnyStrict(src);
-  }
-
-  TVM_FFI_INLINE static Optional<T> CopyFromAnyViewAfterCheck(const TVMFFIAny* 
src) {
-    if (src->type_index == TypeIndex::kTVMFFINone) {
-      return Optional<T>(std::nullopt);
-    }
-    return TypeTraits<T>::CopyFromAnyViewAfterCheck(src);
-  }
-
-  TVM_FFI_INLINE static Optional<T> MoveFromAnyAfterCheck(TVMFFIAny* src) {
-    if (src->type_index == TypeIndex::kTVMFFINone) {
-      return Optional<T>(std::nullopt);
-    }
-    return TypeTraits<T>::MoveFromAnyAfterCheck(src);
-  }
-
-  TVM_FFI_INLINE static std::optional<Optional<T>> TryCastFromAnyView(const 
TVMFFIAny* src) {
-    if (src->type_index == TypeIndex::kTVMFFINone) return 
Optional<T>(std::nullopt);
-    if (std::optional<T> opt = TypeTraits<T>::TryCastFromAnyView(src)) {
-      return Optional<T>(*std::move(opt));
-    } else {
-      // important to be explicit here
-      // because nullopt can convert to std::optional<T>(nullopt) which 
indicate success
-      // return std::optional<Optional<T>>(std::nullopt) to indicate failure
-      return std::optional<Optional<T>>(std::nullopt);
-    }
-  }
-
-  TVM_FFI_INLINE static std::string GetMismatchTypeInfo(const TVMFFIAny* src) {
-    return TypeTraits<T>::GetMismatchTypeInfo(src);
-  }
-
-  TVM_FFI_INLINE static std::string TypeStr() {
-    return "Optional<" + TypeTraits<T>::TypeStr() + ">";
-  }
-  TVM_FFI_INLINE static std::string TypeSchema() {
-    return R"({"type":"Optional","args":[)" + details::TypeSchema<T>::v() + 
"]}";
-  }
-};
 }  // namespace ffi
 }  // namespace tvm
 #endif  // TVM_FFI_TYPE_TRAITS_H_
diff --git a/tests/cpp/test_any.cc b/tests/cpp/test_any.cc
index 2686b7a8..bc8d36d6 100644
--- a/tests/cpp/test_any.cc
+++ b/tests/cpp/test_any.cc
@@ -18,6 +18,7 @@
  */
 #include <gtest/gtest.h>
 #include <tvm/ffi/any.h>
+#include <tvm/ffi/container/tensor.h>
 #include <tvm/ffi/memory.h>
 
 #include <limits>
diff --git a/tests/cpp/test_function.cc b/tests/cpp/test_function.cc
index fddb8fd8..1a915539 100644
--- a/tests/cpp/test_function.cc
+++ b/tests/cpp/test_function.cc
@@ -22,6 +22,7 @@
 #include <tvm/ffi/any.h>
 #include <tvm/ffi/container/array.h>
 #include <tvm/ffi/container/map.h>
+#include <tvm/ffi/container/tensor.h>
 #include <tvm/ffi/extra/json.h>
 #include <tvm/ffi/function.h>
 #include <tvm/ffi/memory.h>
diff --git a/tests/lint/check_asf_header.py b/tests/lint/check_asf_header.py
index efc35464..80e27f0d 100644
--- a/tests/lint/check_asf_header.py
+++ b/tests/lint/check_asf_header.py
@@ -170,8 +170,10 @@ FMT_MAP = {
     "bat": header_cmdstyle,
 }
 
-# Files and patterns to skip during header checking
-SKIP_LIST: list[str] = []
+# Files and patterns to skip during header checking.
+SKIP_LIST: list[str] = [
+    ".agents/skills/**/SKILL.md",
+]
 
 
 def should_skip_file(filepath: str) -> bool:


Reply via email to