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 5411a642 [FFI] Back Optional and Variant by TVMFFIAny for a stable ABI 
layout (#657)
5411a642 is described below

commit 5411a642d98bba14d4cb1e19a793c5b6758be019
Author: Tianqi Chen <[email protected]>
AuthorDate: Mon Jul 6 10:11:18 2026 +0800

    [FFI] Back Optional and Variant by TVMFFIAny for a stable ABI layout (#657)
    
    This PR makes `tvm::ffi::Optional<T>` and `tvm::ffi::Variant<...>`
    layout stable across the contained type `T` by backing them with `Any`.
    Note that `Optional<T>` still falls back to `std::optional<T>` when `T`
    does not support Any storage.
    
    This helps stabilize the future object-layout ABI of `Optional` and
    `Variant`.
---
 include/tvm/ffi/container/variant.h      | 119 +++------
 include/tvm/ffi/extra/json.h             |   2 +-
 include/tvm/ffi/extra/module.h           |   2 +-
 include/tvm/ffi/object.h                 |   5 +-
 include/tvm/ffi/optional.h               | 426 +++++++++++++------------------
 include/tvm/ffi/reflection/access_path.h |   8 +-
 rust/tvm-ffi/src/lib.rs                  |   3 +-
 rust/tvm-ffi/src/option.rs               | 350 -------------------------
 rust/tvm-ffi/src/optional.rs             | 200 +++++++++++++++
 rust/tvm-ffi/src/string.rs               |  17 --
 rust/tvm-ffi/tests/test_optional.rs      | 209 ++++++++-------
 src/ffi/extra/json_writer.cc             |   7 +-
 tests/cpp/test_object.cc                 |   8 +-
 tests/cpp/test_optional.cc               | 111 ++++----
 tests/cpp/test_variant.cc                |   8 +-
 15 files changed, 613 insertions(+), 862 deletions(-)

diff --git a/include/tvm/ffi/container/variant.h 
b/include/tvm/ffi/container/variant.h
index 8ad8097f..2a027f56 100644
--- a/include/tvm/ffi/container/variant.h
+++ b/include/tvm/ffi/container/variant.h
@@ -34,77 +34,18 @@
 
 namespace tvm {
 namespace ffi {
-namespace details {
-/*!
- * \brief Base class for Variant.
- *
- * \tparam all_storage_object Whether all types are derived from ObjectRef.
- */
-template <bool all_storage_object = false>
-class VariantBase {
- public:
-  TVM_FFI_INLINE bool same_as(const VariantBase<all_storage_object>& other) 
const {
-    return data_.same_as(other.data_);
-  }
-
- protected:
-  template <typename T>
-  explicit VariantBase(T other) : data_(std::move(other)) {}
-
-  TVM_FFI_INLINE void SetData(Any other_data) { data_ = std::move(other_data); 
}
-
-  TVM_FFI_INLINE Any MoveToAny() && { return std::move(data_); }
-
-  TVM_FFI_INLINE AnyView ToAnyView() const { return data_.operator AnyView(); }
-
-  Any data_;
-};
-
-// Specialization for all object ref case, backed by ObjectRef.
-template <>
-class VariantBase<true> : public ObjectRef {
- protected:
-  template <typename T>
-  explicit VariantBase(const T& other) : ObjectRef(other) {}
-  template <typename T,
-            typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, 
VariantBase<true>>>>
-  explicit VariantBase(T&& other) : ObjectRef(std::forward<T>(other)) {}
-  explicit VariantBase(UnsafeInit tag) : ObjectRef(tag) {}
-  explicit VariantBase(Any other)
-      : 
ObjectRef(details::AnyUnsafe::MoveFromAnyAfterCheck<ObjectRef>(std::move(other)))
 {}
-
-  TVM_FFI_INLINE void SetData(ObjectPtr<Object> other) { data_ = 
std::move(other); }
-
-  TVM_FFI_INLINE Any MoveToAny() && { return Any(ObjectRef(std::move(data_))); 
}
-
-  TVM_FFI_INLINE AnyView ToAnyView() const {
-    TVMFFIAny any_data;
-    if (data_ == nullptr) {
-      any_data.type_index = TypeIndex::kTVMFFINone;
-      any_data.zero_padding = 0;
-      any_data.v_int64 = 0;
-    } else {
-      TVM_FFI_CLEAR_PTR_PADDING_IN_FFI_ANY(&any_data);
-      any_data.type_index = data_->type_index();
-      any_data.zero_padding = 0;
-      any_data.v_obj = 
details::ObjectUnsafe::TVMFFIObjectPtrFromObjectPtr<Object>(data_);
-    }
-    return AnyView::CopyFromTVMFFIAny(any_data);
-  }
-};
-}  // namespace details
-
 /*!
  * \brief A typed variant container.
  *
- * When all values are ObjectRef, Variant is backed by ObjectRef,
- * otherwise it is backed by Any.
+ * \note Variant is always backed by a single Any (TVMFFIAny). Even when every
+ *       alternative derives from ObjectRef, Variant is not ObjectRef-derived;
+ *       this keeps the layout independent of the contained types
+ *       (sizeof(Variant<...>) == sizeof(Any)).
  */
 template <typename... V>
-class Variant : public details::VariantBase<details::all_object_ref_v<V...>> {
+class Variant {
  public:
   /// \cond Doxygen_Suppress
-  using TParent = details::VariantBase<details::all_object_ref_v<V...>>;
   static_assert(details::all_storage_enabled_v<V...>,
                 "All types used in Variant<...> must be compatible with Any");
   /// \cond Doxygen_Suppress
@@ -123,37 +64,31 @@ class Variant : public 
details::VariantBase<details::all_object_ref_v<V...>> {
    * \brief Constructor from another variant
    * \param other The other variant
    */
-  Variant(const Variant<V...>& other) : TParent(other.data_) {}
+  Variant(const Variant<V...>& other) = default;
   /*!
    * \brief Constructor from another variant
    * \param other The other variant
    */
-  Variant(Variant<V...>&& other) noexcept : TParent(std::move(other.data_)) {}
+  Variant(Variant<V...>&& other) noexcept = default;
 
   /*!
    * \brief Assignment from another variant
    * \param other The other variant
    */
-  TVM_FFI_INLINE Variant& operator=(const Variant<V...>& other) {
-    this->SetData(other.data_);
-    return *this;
-  }
+  Variant& operator=(const Variant<V...>& other) = default;
 
   /*!
    * \brief Assignment from another variant
    * \param other The other variant
    */
-  TVM_FFI_INLINE Variant& operator=(Variant<V...>&& other) noexcept {
-    this->SetData(std::move(other.data_));
-    return *this;
-  }
+  Variant& operator=(Variant<V...>&& other) noexcept = default;
 
   /*!
-   * \brief Constructor from another variant
-   * \param other The other variant
+   * \brief Constructor from a contained value
+   * \param other The value to store
    */
   template <typename T, typename = enable_if_variant_contains_t<T>>
-  Variant(T other) : TParent(std::move(other)) {}  // NOLINT(*)
+  Variant(T other) : data_(std::move(other)) {}  // NOLINT(*)
 
   /*!
    * \brief Assignment from another variant
@@ -171,7 +106,7 @@ class Variant : public 
details::VariantBase<details::all_object_ref_v<V...>> {
    */
   template <typename T, typename = enable_if_variant_contains_t<T>>
   TVM_FFI_INLINE std::optional<T> as() const {
-    return this->TParent::ToAnyView().template as<T>();
+    return ToAnyView().template as<T>();
   }
 
   /*!
@@ -182,7 +117,7 @@ class Variant : public 
details::VariantBase<details::all_object_ref_v<V...>> {
    */
   template <typename T, typename = std::enable_if_t<std::is_base_of_v<Object, 
T>>>
   TVM_FFI_INLINE const T* as() const {
-    return this->TParent::ToAnyView().template as<const 
T*>().value_or(nullptr);
+    return ToAnyView().template as<const T*>().value_or(nullptr);
   }
 
   /*!
@@ -192,7 +127,7 @@ class Variant : public 
details::VariantBase<details::all_object_ref_v<V...>> {
    */
   template <typename T, typename = enable_if_variant_contains_t<T>>
   TVM_FFI_INLINE T get() const& {
-    return this->TParent::ToAnyView().template cast<T>();
+    return ToAnyView().template cast<T>();
   }
 
   /*!
@@ -202,21 +137,30 @@ class Variant : public 
details::VariantBase<details::all_object_ref_v<V...>> {
    */
   template <typename T, typename = enable_if_variant_contains_t<T>>
   TVM_FFI_INLINE T get() && {
-    return std::move(*this).TParent::MoveToAny().template cast<T>();
+    return std::move(*this).MoveToAny().template cast<T>();
   }
 
   /*!
    * \brief Get the type key of the variant
    * \return The type key of the variant
    */
-  TVM_FFI_INLINE std::string GetTypeKey() const { return 
this->TParent::ToAnyView().GetTypeKey(); }
+  TVM_FFI_INLINE std::string GetTypeKey() const { return 
ToAnyView().GetTypeKey(); }
+
+  /*!
+   * \brief Shallow-compare with another variant.
+   * \param other The other variant.
+   * \return Whether the two hold the same underlying value.
+   */
+  TVM_FFI_INLINE bool same_as(const Variant<V...>& other) const {
+    return data_.same_as(other.data_);
+  }
 
  private:
   friend struct TypeTraits<Variant<V...>>;
   friend struct ObjectPtrHash;
   friend struct ObjectPtrEqual;
   // constructor from any
-  explicit Variant(Any data) : TParent(std::move(data)) {}
+  explicit Variant(Any data) : data_(std::move(data)) {}
   /*!
    * \brief Get the object pointer from the variant
    * \note This function is only available if all types used in Variant<...> 
are derived from
@@ -227,11 +171,12 @@ class Variant : public 
details::VariantBase<details::all_object_ref_v<V...>> {
     static_assert(all_object_v,
                   "All types used in Variant<...> must be derived from 
ObjectRef "
                   "to enable ObjectPtrHash/ObjectPtrEqual");
-    return this->data_.get();
+    return details::AnyUnsafe::ObjectPtrFromAnyAfterCheck(this->data_);
   }
-  // rexpose to friend class
-  using TParent::MoveToAny;
-  using TParent::ToAnyView;
+  TVM_FFI_INLINE AnyView ToAnyView() const { return data_.operator AnyView(); }
+  TVM_FFI_INLINE Any MoveToAny() && { return std::move(data_); }
+  /*! \brief The underlying Any backing store. */
+  Any data_;
 };
 
 template <typename... V>
diff --git a/include/tvm/ffi/extra/json.h b/include/tvm/ffi/extra/json.h
index 24ab2f0d..e7bff00d 100644
--- a/include/tvm/ffi/extra/json.h
+++ b/include/tvm/ffi/extra/json.h
@@ -76,7 +76,7 @@ TVM_FFI_EXTRA_CXX_API json::Value Parse(const String& 
json_str, String* error_ms
  * \return The output JSON string.
  */
 TVM_FFI_EXTRA_CXX_API String Stringify(const json::Value& value,
-                                       Optional<int> indent = std::nullopt);
+                                       const Optional<int>& indent = 
std::nullopt);
 
 }  // namespace json
 }  // namespace ffi
diff --git a/include/tvm/ffi/extra/module.h b/include/tvm/ffi/extra/module.h
index 5c2142ec..8a824a3e 100644
--- a/include/tvm/ffi/extra/module.h
+++ b/include/tvm/ffi/extra/module.h
@@ -70,7 +70,7 @@ class TVM_FFI_EXTRA_CXX_API ModuleObj : public Object {
    * \param name The name of the function.
    * \return True if the module implements the function, false otherwise.
    */
-  virtual bool ImplementsFunction(const String& name) { return 
GetFunction(name).defined(); }
+  virtual bool ImplementsFunction(const String& name) { return 
GetFunction(name).has_value(); }
   /*!
    * \brief Get the docstring of the function, if available.
    * \param name The name of the function.
diff --git a/include/tvm/ffi/object.h b/include/tvm/ffi/object.h
index 4868ab14..27bf8c38 100644
--- a/include/tvm/ffi/object.h
+++ b/include/tvm/ffi/object.h
@@ -670,8 +670,9 @@ class WeakObjectPtr {
  * \brief Optional data type in FFI.
  * \tparam T The underlying type of the optional.
  *
- * \note Compared to std::optional, Optional<ObjectRef>
- *   akes less storage as it used nullptr to represent nullopt.
+ * \note For storage-enabled T, Optional<T> is backed by a single TVMFFIAny 
(Any)
+ *   and uses kTVMFFINone to represent nullopt, so its layout is independent 
of T.
+ *   For non-storage-enabled T it falls back to std::optional<T>.
  */
 template <typename T, typename = void>
 class Optional;
diff --git a/include/tvm/ffi/optional.h b/include/tvm/ffi/optional.h
index eb63fafb..c79d5328 100644
--- a/include/tvm/ffi/optional.h
+++ b/include/tvm/ffi/optional.h
@@ -20,11 +20,17 @@
 /*!
  * \file tvm/ffi/optional.h
  * \brief Runtime Optional container types.
- * \note Optional<T> specializes for T is ObjectRef and used nullptr to 
indicate nullopt.
+ * \note Optional<T> uses a hybrid representation. For types that enable Any
+ *       storage (`TypeTraits<T>::storage_enabled`), it is backed by a single
+ *       TVMFFIAny (Any) with nullopt represented as kTVMFFINone, mirroring
+ *       Variant<...>; the layout is then independent of T (sizeof == 
sizeof(Any))
+ *       which keeps the ABI stable. For types that do not enable storage (e.g.
+ *       non-owning view types) it falls back to std::optional<T>.
  */
 #ifndef TVM_FFI_OPTIONAL_H_
 #define TVM_FFI_OPTIONAL_H_
 
+#include <tvm/ffi/any.h>
 #include <tvm/ffi/error.h>
 #include <tvm/ffi/object.h>
 #include <tvm/ffi/string.h>
@@ -44,59 +50,46 @@ inline constexpr bool is_optional_type_v = false;
 
 template <typename T>
 inline constexpr bool is_optional_type_v<Optional<T>> = true;
-
-// we can safely used ptr based optional for ObjectRef types
-// that do not have additional data members and virtual functions.
-template <typename T>
-inline constexpr bool use_ptr_based_optional_v =
-    (std::is_base_of_v<ObjectRef, T> && !is_optional_type_v<T>);
 /// \endcond
 
-// Specialization for non-ObjectRef types.
-// simply fallback to std::optional
+// Fallback specialization for types that do NOT enable Any storage
+// (`TypeTraits<T>::storage_enabled == false`), such as non-owning view types
+// that cannot be moved into an Any. These simply reuse std::optional<T>.
 template <typename T>
-class Optional<T, std::enable_if_t<!use_ptr_based_optional_v<T> && 
!std::is_same_v<T, String> &&
-                                   !std::is_same_v<T, Bytes>>> {
+class Optional<T, std::enable_if_t<!TypeTraits<T>::storage_enabled>> {
  public:
   // default constructors.
   Optional() = default;
   // NOLINTBEGIN(google-explicit-constructor)
-  Optional(const Optional<T>& other) : data_(other.data_) {}
-  Optional(Optional<T>&& other) noexcept : data_(std::move(other.data_)) {}
+  Optional(const Optional& other) = default;
+  Optional(Optional&& other) noexcept = default;
   Optional(std::optional<T> other) : data_(std::move(other)) {}
   Optional(std::nullopt_t) {}
   Optional(T other) : data_(std::move(other)) {}
   // NOLINTEND(google-explicit-constructor)
 
-  TVM_FFI_INLINE Optional<T>& operator=(const Optional<T>& other) {
-    data_ = other.data_;
-    return *this;
-  }
-
-  TVM_FFI_INLINE Optional<T>& operator=(Optional<T>&& other) noexcept {
-    data_ = std::move(other.data_);
-    return *this;
-  }
+  Optional& operator=(const Optional& other) = default;
+  Optional& operator=(Optional&& other) noexcept = default;
 
-  TVM_FFI_INLINE Optional<T>& operator=(T other) {
+  TVM_FFI_INLINE Optional& operator=(T other) {
     data_ = std::move(other);
     return *this;
   }
 
-  TVM_FFI_INLINE Optional<T>& operator=(std::nullopt_t) {
+  TVM_FFI_INLINE Optional& operator=(std::nullopt_t) {
     data_ = std::nullopt;
     return *this;
   }
 
   TVM_FFI_INLINE const T& value() const& {
-    if (!data_.has_value()) {
+    if (TVM_FFI_PREDICT_FALSE(!data_.has_value())) {
       TVM_FFI_THROW(RuntimeError) << "Back optional access";
     }
     return *data_;
   }
 
   TVM_FFI_INLINE T&& value() && {
-    if (!data_.has_value()) {
+    if (TVM_FFI_PREDICT_FALSE(!data_.has_value())) {
       TVM_FFI_THROW(RuntimeError) << "Back optional access";
     }
     return *std::move(data_);
@@ -111,10 +104,8 @@ class Optional<T, 
std::enable_if_t<!use_ptr_based_optional_v<T> && !std::is_same
 
   TVM_FFI_INLINE bool has_value() const noexcept { return data_.has_value(); }
 
-  TVM_FFI_INLINE bool operator==(const Optional<T>& other) const { return 
data_ == other.data_; }
-
-  TVM_FFI_INLINE bool operator!=(const Optional<T>& other) const { return 
data_ != other.data_; }
-
+  TVM_FFI_INLINE bool operator==(const Optional& other) const { return data_ 
== other.data_; }
+  TVM_FFI_INLINE bool operator!=(const Optional& other) const { return data_ 
!= other.data_; }
   template <typename U>
   TVM_FFI_INLINE bool operator==(const U& other) const {
     return data_ == other;
@@ -127,14 +118,12 @@ class Optional<T, 
std::enable_if_t<!use_ptr_based_optional_v<T> && !std::is_same
   // NOLINTBEGIN(bugprone-unchecked-optional-access)
   /*!
    * \brief Direct access to the value.
-   * \return the xvalue reference to the stored value.
    * \note only use this function after checking has_value()
    */
   TVM_FFI_INLINE T&& operator*() && noexcept { return *std::move(data_); }
   /*!
    * \brief Direct access to the value.
-   * \return the const reference to the stored value.
-   * \note only use this function  after checking has_value()
+   * \note only use this function after checking has_value()
    */
   TVM_FFI_INLINE const T& operator*() const& noexcept { return *data_; }
   // NOLINTEND(bugprone-unchecked-optional-access)
@@ -143,276 +132,203 @@ class Optional<T, 
std::enable_if_t<!use_ptr_based_optional_v<T> && !std::is_same
   std::optional<T> data_;
 };
 
-// Specialization for String type, use nullptr to indicate nullopt
-template <typename T>
-class Optional<T, std::enable_if_t<std::is_same_v<T, String> || 
std::is_same_v<T, Bytes>>> {
- public:
-  // default constructors.
-  Optional() = default;
-  // NOLINTBEGIN(google-explicit-constructor)
-  Optional(const Optional<T>& other) : data_(other.data_) {}
-  Optional(Optional<T>&& other) : data_(std::move(other.data_)) {}
-  Optional(std::nullopt_t) {}
-  Optional(T other) : data_(std::move(other)) {}
-  // NOLINTEND(google-explicit-constructor)
-
-  TVM_FFI_INLINE Optional<T>& operator=(const Optional<T>& other) {
-    data_ = other.data_;
-    return *this;
-  }
-
-  TVM_FFI_INLINE Optional<T>& operator=(Optional<T>&& other) {
-    data_ = std::move(other.data_);
-    return *this;
-  }
-
-  TVM_FFI_INLINE Optional<T>& operator=(T other) {
-    data_ = std::move(other);
-    return *this;
-  }
-
-  TVM_FFI_INLINE Optional<T>& operator=(std::nullopt_t) {
-    T(details::BytesBaseCell(std::nullopt)).swap(data_);
-    return *this;
-  }
-
-  TVM_FFI_INLINE const T& value() const& {
-    if (data_.data_ == std::nullopt) {
-      TVM_FFI_THROW(RuntimeError) << "Back optional access";
-    }
-    return data_;
-  }
-
-  TVM_FFI_INLINE String&& value() && {
-    if (data_.data_ == std::nullopt) {
-      TVM_FFI_THROW(RuntimeError) << "Back optional access";
-    }
-    return std::move(data_);
-  }
-
-  template <typename U = T>
-  TVM_FFI_INLINE T value_or(U&& default_value) const {
-    if (data_.data_ == std::nullopt) {
-      return std::forward<U>(default_value);
-    }
-    return data_;
-  }
-
-  TVM_FFI_INLINE explicit operator bool() const noexcept { return data_.data_ 
!= std::nullopt; }
-
-  TVM_FFI_INLINE bool has_value() const noexcept { return data_.data_ != 
std::nullopt; }
-
-  TVM_FFI_INLINE bool operator==(const Optional<T>& other) const {
-    if (data_.data_ == std::nullopt) {
-      return other.data_.data_ == std::nullopt;
-    }
-    if (other.data_.data_ == std::nullopt) {
-      return false;
-    }
-    return data_ == other.data_;
-  }
-
-  TVM_FFI_INLINE bool operator!=(const Optional<T>& other) const { return 
!(*this == other); }
-
-  template <typename U>
-  TVM_FFI_INLINE bool operator==(const U& other) const {
-    if constexpr (std::is_same_v<U, std::nullopt_t>) {
-      return data_.data_ == std::nullopt;
-    } else {
-      if (data_.data_ == std::nullopt) {
-        return false;
-      }
-      return data_ == other;
-    }
-  }
-  template <typename U>
-  TVM_FFI_INLINE bool operator!=(const U& other) const {
-    if constexpr (std::is_same_v<U, std::nullopt_t>) {
-      return data_.data_ != std::nullopt;
-    } else {
-      if (data_.data_ == std::nullopt) {
-        return true;
-      }
-      return data_ != other;
-    }
-  }
-
-  /*!
-   * \brief Direct access to the value.
-   * \return the xvalue reference to the stored value.
-   * \note only use this function after checking has_value()
-   */
-  TVM_FFI_INLINE T&& operator*() && noexcept { return std::move(data_); }
-  /*!
-   * \brief Direct access to the value.
-   * \return the const reference to the stored value.
-   * \note only use this function  after checking has_value()
-   */
-  TVM_FFI_INLINE const T& operator*() const& noexcept { return data_; }
-
- private:
-  // this is a private initializer
-  T data_{details::BytesBaseCell(std::nullopt)};
-};
-
-// Specialization for ObjectRef types.
-// nullptr is treated as std::nullopt.
+/*!
+ * \brief Optional container backed by a single TVMFFIAny (Any) for 
storage-enabled T.
+ *
+ * Mirrors the Variant<...> implementation: the value is stored in a single Any
+ * and nullopt is represented as kTVMFFINone. The layout is therefore 
independent
+ * of T (sizeof(Optional<T>) == sizeof(Any)) which keeps the ABI stable across
+ * contained types.
+ *
+ * \note None/null is treated as nullopt. For a nullable T, a null value reads
+ *       back as "no value" (has_value() == false). This gives one stable
+ *       cross-language ABI representation, consistent with Python's None. If a
+ *       use case must distinguish nullopt from a stored null, use 
std::optional
+ *       instead.
+ *
+ * \tparam T The underlying value type (must enable Any storage).
+ */
 template <typename T>
-class Optional<T, std::enable_if_t<use_ptr_based_optional_v<T>>> : public 
ObjectRef {
+class Optional<T, std::enable_if_t<TypeTraits<T>::storage_enabled>> {
  public:
-  using ContainerType = typename T::ContainerType;
-  static constexpr bool _type_container_is_exact = T::_type_container_is_exact;
+  /*! \brief default constructor, represents nullopt (Any() is kTVMFFINone). */
   Optional() = default;
   // NOLINTBEGIN(google-explicit-constructor)
-  Optional(const Optional<T>& other) : ObjectRef(other) {}
-  Optional(Optional<T>&& other) noexcept : ObjectRef(std::move(other)) {}
-  explicit Optional(ffi::UnsafeInit tag) : ObjectRef(tag) {}
+  /*! \brief construct nullopt from std::nullopt. */
   Optional(std::nullopt_t) {}
+  /*! \brief copy constructor. */
+  Optional(const Optional& other) = default;
+  /*! \brief move constructor. */
+  Optional(Optional&& other) noexcept = default;
+  /*! \brief construct from a value of type T (copy). */
+  Optional(const T& value) : data_(value) {}
+  /*! \brief construct from a value of type T (move). */
+  Optional(T&& value) : data_(std::move(value)) {}
+  /*! \brief construct from a std::optional<T>. */
   Optional(std::optional<T> other) {
     if (other.has_value()) {
-      *this = *std::move(other);
+      data_ = Any(*std::move(other));
     }
   }
-  Optional(T other) : ObjectRef(std::move(other)) {}
   // NOLINTEND(google-explicit-constructor)
 
-  TVM_FFI_INLINE Optional<T>& operator=(T other) {
-    ObjectRef::operator=(std::move(other));
-    return *this;
-  }
+  /*! \brief copy assignment. */
+  Optional& operator=(const Optional& other) = default;
+  /*! \brief move assignment. */
+  Optional& operator=(Optional&& other) noexcept = default;
 
-  TVM_FFI_INLINE Optional<T>& operator=(const Optional<T>& other) {
-    data_ = other.data_;
+  TVM_FFI_INLINE Optional& operator=(T other) {
+    data_ = Any(std::move(other));
     return *this;
   }
 
-  TVM_FFI_INLINE Optional<T>& operator=(std::nullptr_t) {
-    data_ = nullptr;
+  TVM_FFI_INLINE Optional& operator=(std::nullopt_t) {
+    data_.reset();
     return *this;
   }
 
-  TVM_FFI_INLINE Optional<T>& operator=(Optional<T>&& other) {
-    data_ = std::move(other.data_);
+  TVM_FFI_INLINE Optional& operator=(std::nullptr_t) {
+    data_.reset();
     return *this;
   }
 
   TVM_FFI_INLINE T value() const& {
-    if (data_ == nullptr) {
+    if (TVM_FFI_PREDICT_FALSE(!has_value())) {
       TVM_FFI_THROW(RuntimeError) << "Back optional access";
     }
-    return details::ObjectUnsafe::ObjectRefFromObjectPtr<T>(data_);
+    // The invariant guarantees the stored value is exactly a T, so decode it
+    // directly with the low-level after-check path (no conversion/cast).
+    return details::AnyUnsafe::CopyFromAnyViewAfterCheck<T>(data_);
   }
 
   TVM_FFI_INLINE T value() && {
-    if (data_ == nullptr) {
+    if (TVM_FFI_PREDICT_FALSE(!has_value())) {
       TVM_FFI_THROW(RuntimeError) << "Back optional access";
     }
-    return details::ObjectUnsafe::ObjectRefFromObjectPtr<T>(std::move(data_));
+    return details::AnyUnsafe::MoveFromAnyAfterCheck<T>(std::move(data_));
   }
 
   template <typename U = std::remove_cv_t<T>>
   TVM_FFI_INLINE T value_or(U&& default_value) const {
-    return data_ != nullptr ? 
details::ObjectUnsafe::ObjectRefFromObjectPtr<T>(data_)
-                            : T(std::forward<U>(default_value));
+    if (has_value()) {
+      return details::AnyUnsafe::CopyFromAnyViewAfterCheck<T>(data_);
+    }
+    return T(std::forward<U>(default_value));
   }
 
-  TVM_FFI_INLINE explicit operator bool() const { return data_ != nullptr; }
+  TVM_FFI_INLINE explicit operator bool() const noexcept { return has_value(); 
}
 
-  TVM_FFI_INLINE bool has_value() const { return data_ != nullptr; }
+  TVM_FFI_INLINE bool has_value() const noexcept {
+    return data_.type_index() != TypeIndex::kTVMFFINone;
+  }
 
   /*!
-   * \brief Direct access to the value.
-   * \return the const reference to the stored value.
-   * \note only use this function after checking has_value()
+   * \brief Try to reinterpret the stored value as a type U (strict, no 
conversion).
+   * \tparam U The type to reinterpret to.
+   * \return std::optional<U> for ObjectRef-like U, or const U* when U is an 
Object type.
+   * \note Returns an empty result when nullopt or the strict type check fails.
    */
-  TVM_FFI_INLINE T operator*() const& noexcept {
-    return details::ObjectUnsafe::ObjectRefFromObjectPtr<T>(data_);
+  template <typename U>
+  TVM_FFI_INLINE auto as() const {
+    return data_.template as<U>();
   }
 
   /*!
    * \brief Direct access to the value.
-   * \return the const reference to the stored value.
-   * \note only use this function  after checking has_value()
+   * \note only use this function after checking has_value()
+   */
+  TVM_FFI_INLINE T operator*() const& {
+    return details::AnyUnsafe::CopyFromAnyViewAfterCheck<T>(data_);
+  }
+  /*!
+   * \brief Direct access to the value, moved out of the storage.
+   * \note only use this function after checking has_value()
    */
-  TVM_FFI_INLINE T operator*() && noexcept {
-    return details::ObjectUnsafe::ObjectRefFromObjectPtr<T>(std::move(data_));
+  TVM_FFI_INLINE T operator*() && {
+    return details::AnyUnsafe::MoveFromAnyAfterCheck<T>(std::move(data_));
   }
 
+  // comparison with nullopt / nullptr
+  TVM_FFI_INLINE bool operator==(std::nullopt_t) const noexcept { return 
!has_value(); }
+  TVM_FFI_INLINE bool operator!=(std::nullopt_t) const noexcept { return 
has_value(); }
   TVM_FFI_INLINE bool operator==(std::nullptr_t) const noexcept { return 
!has_value(); }
   TVM_FFI_INLINE bool operator!=(std::nullptr_t) const noexcept { return 
has_value(); }
 
-  // operator overloadings
-  TVM_FFI_INLINE auto operator==(const Optional<T>& other) const {
+  // comparison with another Optional<T>
+  TVM_FFI_INLINE auto operator==(const Optional& other) const {
     // support case where sub-class returns a symbolic ref type.
-    return EQToOptional(other);
+    using RetType = decltype(std::declval<T>() == std::declval<T>());
+    if (data_.same_as(other.data_)) return RetType(true);
+    if (has_value() && other.has_value()) return **this == *other;
+    return RetType(false);
+  }
+  TVM_FFI_INLINE auto operator!=(const Optional& other) const {
+    using RetType = decltype(std::declval<T>() != std::declval<T>());
+    if (data_.same_as(other.data_)) return RetType(false);
+    if (has_value() && other.has_value()) return **this != *other;
+    return RetType(true);
   }
-  TVM_FFI_INLINE auto operator!=(const Optional<T>& other) const { return 
NEToOptional(other); }
 
+  // comparison with a std::optional<T>
   TVM_FFI_INLINE auto operator==(const std::optional<T>& other) const {
-    // support case where sub-class returns a symbolic ref type.
-    return EQToOptional(other);
+    using RetType = decltype(std::declval<T>() == std::declval<T>());
+    if (has_value() && other.has_value()) return **this == *other;
+    return RetType(!has_value() && !other.has_value());
   }
   TVM_FFI_INLINE auto operator!=(const std::optional<T>& other) const {
-    return NEToOptional(other);
-  }
-
-  TVM_FFI_INLINE auto operator==(const T& other) const {
-    using RetType = decltype(value() == other);
-    if (same_as(other)) return RetType(true);
-    if (has_value()) return operator*() == other;
-    return RetType(false);
+    using RetType = decltype(std::declval<T>() != std::declval<T>());
+    if (has_value() && other.has_value()) return **this != *other;
+    return RetType(has_value() != other.has_value());
   }
 
-  TVM_FFI_INLINE auto operator!=(const T& other) const { return !(*this == 
other); }
-
-  template <typename U>
+  // comparison with a value of another type U
+  template <typename U, typename = std::enable_if_t<!is_optional_type_v<U> &&
+                                                    !std::is_same_v<U, 
std::nullopt_t> &&
+                                                    !std::is_same_v<U, 
std::nullptr_t>>>
   TVM_FFI_INLINE auto operator==(const U& other) const {
-    using RetType = decltype(value() == other);
+    using RetType = decltype(std::declval<T>() == std::declval<U>());
+    if constexpr (std::is_base_of_v<ObjectRef, T> && 
std::is_base_of_v<ObjectRef, U>) {
+      // support case where sub-class returns a symbolic ref type.
+      if (data_.same_as(other)) return RetType(true);
+    }
     if (!has_value()) return RetType(false);
-    return operator*() == other;
+    return **this == other;
   }
-
-  template <typename U>
+  template <typename U, typename = std::enable_if_t<!is_optional_type_v<U> &&
+                                                    !std::is_same_v<U, 
std::nullopt_t> &&
+                                                    !std::is_same_v<U, 
std::nullptr_t>>>
   TVM_FFI_INLINE auto operator!=(const U& other) const {
-    using RetType = decltype(value() != other);
+    using RetType = decltype(std::declval<T>() != std::declval<U>());
+    if constexpr (std::is_base_of_v<ObjectRef, T> && 
std::is_base_of_v<ObjectRef, U>) {
+      if (data_.same_as(other)) return RetType(false);
+    }
     if (!has_value()) return RetType(true);
-    return operator*() != other;
+    return **this != other;
   }
 
   /*!
-   * \return The internal object pointer with container type of T.
-   * \note This function do not perform not-null checking.
+   * \brief Shallow-compare with another Optional<T>.
+   * \return Whether the two refer to the same underlying value.
    */
-  TVM_FFI_INLINE const ContainerType* get() const {
-    return static_cast<ContainerType*>(data_.get());
-  }
+  TVM_FFI_INLINE bool same_as(const Optional& other) const { return 
data_.same_as(other.data_); }
 
- private:
-  template <typename U>
-  TVM_FFI_INLINE auto EQToOptional(const U& other) const {
-    // support case where sub-class returns a symbolic ref type.
-    using RetType = decltype(operator*() == *other);
-    if (same_as(other)) return RetType(true);
-    if (has_value() && other.has_value()) {
-      return operator*() == *other;
-    } else {
-      // one of them is nullptr.
-      return RetType(false);
-    }
+  /*!
+   * \brief Shallow-compare with a value of an ObjectRef type.
+   * \return Whether the two refer to the same underlying object.
+   */
+  template <typename U = T, typename = 
std::enable_if_t<std::is_base_of_v<ObjectRef, U>>>
+  TVM_FFI_INLINE bool same_as(const U& other) const {
+    return data_.same_as(other);
   }
 
-  template <typename U>
-  TVM_FFI_INLINE auto NEToOptional(const U& other) const {
-    // support case where sub-class returns a symbolic ref type.
-    using RetType = decltype(operator*() != *other);
-    if (same_as(other)) return RetType(false);
-    if (has_value() && other.has_value()) {
-      return operator*() != *other;
-    } else {
-      // one of them is nullptr.
-      return RetType(true);
-    }
-  }
+ private:
+  friend struct TypeTraits<Optional<T>>;
+  // construct directly from an Any backing store.
+  explicit Optional(Any data) : data_(std::move(data)) {}
+  TVM_FFI_INLINE AnyView ToAnyView() const { return data_.operator AnyView(); }
+  TVM_FFI_INLINE Any MoveToAny() && { return std::move(data_); }
+  /*! \brief The underlying Any backing store, kTVMFFINone represents nullopt. 
*/
+  Any data_;
 };
 
 template <typename T>
@@ -420,19 +336,33 @@ inline constexpr bool 
use_default_type_traits_v<Optional<T>> = false;
 
 template <typename T>
 struct TypeTraits<Optional<T>> : public TypeTraitsBase {
+  // storage_enabled propagates from T: Optional<T> can live in an Any exactly
+  // when T can. This keeps nested Optional<Optional<T>> and Optional<T> used
+  // inside Variant<...>/containers Any-backed iff T is storage-enabled.
+  static constexpr bool storage_enabled = TypeTraits<T>::storage_enabled;
+
   TVM_FFI_INLINE static void CopyToAnyView(const Optional<T>& src, TVMFFIAny* 
result) {
-    if (src.has_value()) {
-      TypeTraits<T>::CopyToAnyView(*src, result);
+    if constexpr (TypeTraits<T>::storage_enabled) {
+      // Storage-enabled: the Any already holds the exact representation.
+      *result = src.ToAnyView().CopyToTVMFFIAny();
     } else {
-      TypeTraits<std::nullptr_t>::CopyToAnyView(nullptr, 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);
+    if constexpr (TypeTraits<T>::storage_enabled) {
+      *result = 
details::AnyUnsafe::MoveAnyToTVMFFIAny(std::move(src).MoveToAny());
     } else {
-      TypeTraits<std::nullptr_t>::CopyToAnyView(nullptr, result);
+      if (src.has_value()) {
+        TypeTraits<T>::MoveToAny(*std::move(src), result);
+      } else {
+        TypeTraits<std::nullptr_t>::CopyToAnyView(nullptr, result);
+      }
     }
   }
 
@@ -442,17 +372,21 @@ struct TypeTraits<Optional<T>> : public TypeTraitsBase {
   }
 
   TVM_FFI_INLINE static Optional<T> CopyFromAnyViewAfterCheck(const TVMFFIAny* 
src) {
-    if (src->type_index == TypeIndex::kTVMFFINone) {
-      return Optional<T>(std::nullopt);
+    if constexpr (TypeTraits<T>::storage_enabled) {
+      return Optional<T>(Any(AnyView::CopyFromTVMFFIAny(*src)));
+    } else {
+      if (src->type_index == TypeIndex::kTVMFFINone) return 
Optional<T>(std::nullopt);
+      return Optional<T>(TypeTraits<T>::CopyFromAnyViewAfterCheck(src));
     }
-    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);
+    if constexpr (TypeTraits<T>::storage_enabled) {
+      return Optional<T>(details::AnyUnsafe::MoveTVMFFIAnyToAny(src));
+    } else {
+      if (src->type_index == TypeIndex::kTVMFFINone) return 
Optional<T>(std::nullopt);
+      return Optional<T>(TypeTraits<T>::MoveFromAnyAfterCheck(src));
     }
-    return TypeTraits<T>::MoveFromAnyAfterCheck(src);
   }
 
   TVM_FFI_INLINE static std::optional<Optional<T>> TryCastFromAnyView(const 
TVMFFIAny* src) {
diff --git a/include/tvm/ffi/reflection/access_path.h 
b/include/tvm/ffi/reflection/access_path.h
index e4ebc2aa..74d106ce 100644
--- a/include/tvm/ffi/reflection/access_path.h
+++ b/include/tvm/ffi/reflection/access_path.h
@@ -305,8 +305,8 @@ class AccessPathObj : public Object {
       if (!(*lhs->step)->StepEqual(*(rhs->step))) {
         return false;
       }
-      lhs = static_cast<const AccessPathObj*>(lhs->parent.get());
-      rhs = static_cast<const AccessPathObj*>(rhs->parent.get());
+      lhs = lhs->parent.as<AccessPathObj>();
+      rhs = rhs->parent.as<AccessPathObj>();
       // fast path for same pointer
       if (lhs == rhs) return true;
       TVM_FFI_ICHECK(lhs != nullptr);
@@ -415,7 +415,7 @@ inline Array<AccessStep> AccessPathObj::ToSteps() const {
   while (current->parent.has_value()) {
     TVM_FFI_ICHECK(current->step.has_value());
     reverse_steps.push_back(*(current->step));
-    current = static_cast<const AccessPathObj*>(current->parent.get());
+    current = current->parent.as<AccessPathObj>();
     TVM_FFI_ICHECK(current != nullptr);
   }
   return Array<AccessStep>(reverse_steps.rbegin(), reverse_steps.rend());
@@ -432,7 +432,7 @@ inline bool AccessPathObj::IsPrefixOf(const AccessPath& 
other) const {
   const AccessPathObj* rhs_path = other.get();
   while (rhs_path->depth > this->depth) {
     TVM_FFI_ICHECK(rhs_path->parent.has_value());
-    rhs_path = static_cast<const AccessPathObj*>(rhs_path->parent.get());
+    rhs_path = rhs_path->parent.as<AccessPathObj>();
   }
   return PathEqual(this, rhs_path);
 }
diff --git a/rust/tvm-ffi/src/lib.rs b/rust/tvm-ffi/src/lib.rs
index a05e3c06..72b8d160 100644
--- a/rust/tvm-ffi/src/lib.rs
+++ b/rust/tvm-ffi/src/lib.rs
@@ -27,7 +27,7 @@ pub mod function;
 pub mod function_internal;
 pub mod macros;
 pub mod object;
-pub mod option;
+pub mod optional;
 pub mod string;
 pub mod type_traits;
 pub use tvm_ffi_sys;
@@ -46,6 +46,7 @@ pub use crate::error::{
 pub use crate::extra::module::Module;
 pub use crate::function::Function;
 pub use crate::object::{Object, ObjectArc, ObjectCore, 
ObjectCoreWithExtraItems, ObjectRefCore};
+pub use crate::optional::Optional;
 pub use crate::string::{Bytes, String};
 pub use crate::type_traits::AnyCompatible;
 
diff --git a/rust/tvm-ffi/src/option.rs b/rust/tvm-ffi/src/option.rs
deleted file mode 100644
index d40e3ce9..00000000
--- a/rust/tvm-ffi/src/option.rs
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * 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.
- */
-//! In-place mirrors of C++ `ffi::Optional<T>` (`include/tvm/ffi/optional.h`).
-//!
-//! `ffi::Optional<T>` stores its value inline, in one of three ABI layouts
-//! depending on `T`. The types here decode such a field's bytes directly — no
-//! FFI call, no allocation, no reflection getter/setter. Pick the counterpart 
for
-//! the field's `T`:
-//!
-//! - POD scalar (`i32`, `f64`, `bool`, …) → [`OptionPod<T>`](OptionPod)
-//! - `String` → [`OptionStr`]
-//! - `ObjectRef` subtype → [`OptionObjRef<T>`](OptionObjRef), an alias of 
plain
-//!   `Option<T>` (a single nullable pointer, `nullptr` == `None`)
-//!
-//! # `OptionPod<T>` — POD scalars
-//! Mirrors the `std::optional<T>` fallback as `#[repr(C)] { value: T, engaged:
-//! bool }` (payload at offset 0, flag at `size_of::<T>()`), byte-verified 
against
-//! libstdc++/libc++. `T` must implement [`OptionalCompatiblePod`] — the 
marker trait
-//! carried by the fixed set of fixed-width scalars. Read with 
[`get`](OptionPod::get),
-//! write with [`set`](OptionPod::set).
-//!
-//! # `OptionStr` — `String`
-//! The C++ `String` specialization keeps the 16-byte string cell inline and 
marks
-//! `nullopt` with the `type_index == kTVMFFINone` sentinel; [`OptionStr`] 
wraps
-//! [`String`] the same way and reuses its refcounting `Clone`/`Drop`. Borrow 
with
-//! [`as_str`](OptionStr::as_str), write with [`set`](OptionStr::set).
-//! (`ffi::Optional<Bytes>` would follow the same pattern.)
-
-use crate::String;
-use std::fmt::{self, Debug};
-use std::mem::MaybeUninit;
-
-//-----------------------------------------------------
-// OptionPod<T> — POD scalars
-//-----------------------------------------------------
-
-/// Marker for a POD scalar `T` that can back an [`OptionPod<T>`]; see the
-/// [module docs](self).
-///
-/// Unsafe: an implementor guarantees `T` is trivially copyable and its Rust
-/// representation is byte-identical to the C++ field type (`i32` ↔ `int32_t`,
-/// `f64` ↔ `double`, …), so the mirror can overlay the C++ `std::optional<T>`.
-///
-/// Non-scalar payloads are rejected at compile time with a pointer to the
-/// right counterpart:
-///
-/// ```compile_fail,E0277
-/// // `Array` is an `ObjectRef` subtype → use `Option<Array<i64>>` 
(`OptionObjRef`).
-/// let _ = tvm_ffi::option::OptionPod::<tvm_ffi::Array<i64>>::none();
-/// ```
-#[diagnostic::on_unimplemented(
-    message = "`OptionPod<{Self}>` only mirrors `ffi::Optional` of fixed-width 
POD scalars",
-    label = "`{Self}` is not a fixed-width POD scalar",
-    note = "for an `ObjectRef` subtype use plain `Option<{Self}>` (alias 
`tvm_ffi::option::OptionObjRef`): the C++ side is a single nullable pointer",
-    note = "for `String` use `tvm_ffi::option::OptionStr`"
-)]
-pub unsafe trait OptionalCompatiblePod: Copy {}
-
-/// In-place mirror of C++ `ffi::Optional<T>` for POD `T`, laid out as
-/// `std::optional<T>`: `{ T value @0; bool engaged @sizeof(T) }`.
-///
-/// Layout-compatible with the C++ type; see the [module docs](self).
-#[repr(C)]
-#[derive(Clone, Copy)]
-pub struct OptionPod<T: OptionalCompatiblePod> {
-    value: MaybeUninit<T>,
-    engaged: bool,
-}
-
-impl<T: OptionalCompatiblePod> OptionPod<T> {
-    /// Builds an engaged optional holding `value`.
-    #[inline]
-    pub fn some(value: T) -> Self {
-        // Only payload+flag are written; padding isn't part of the ABI.
-        Self {
-            value: MaybeUninit::new(value),
-            engaged: true,
-        }
-    }
-
-    /// Builds a disengaged optional (`nullopt`).
-    #[inline]
-    pub fn none() -> Self {
-        // Zeroed (not `uninit`) payload keeps the byte-image tests reading 
init bytes.
-        Self {
-            value: MaybeUninit::zeroed(),
-            engaged: false,
-        }
-    }
-
-    /// Decodes the value in place. No FFI call, no allocation.
-    #[inline]
-    pub fn get(&self) -> Option<T> {
-        if self.engaged {
-            // The payload is written whenever `engaged` is set.
-            Some(unsafe { self.value.assume_init() })
-        } else {
-            None
-        }
-    }
-
-    /// Returns whether a value is present.
-    #[inline]
-    pub fn has_value(&self) -> bool {
-        self.engaged
-    }
-
-    /// Returns whether the optional is `nullopt`.
-    #[inline]
-    pub fn is_none(&self) -> bool {
-        !self.has_value()
-    }
-
-    /// Overwrites the value in place.
-    ///
-    /// Mirrors C++ assignment: `Some(v)` engages and stores `v`; `None`
-    /// disengages without touching the payload bytes, as 
`std::optional::reset`
-    /// does for trivial `T`.
-    #[inline]
-    pub fn set(&mut self, value: Option<T>) {
-        match value {
-            Some(v) => {
-                self.value = MaybeUninit::new(v);
-                self.engaged = true;
-            }
-            None => self.engaged = false,
-        }
-    }
-}
-
-impl<T: OptionalCompatiblePod> Default for OptionPod<T> {
-    /// `nullopt`, matching the C++ default constructor.
-    #[inline]
-    fn default() -> Self {
-        Self::none()
-    }
-}
-
-impl<T: OptionalCompatiblePod + PartialEq> PartialEq for OptionPod<T> {
-    #[inline]
-    fn eq(&self, other: &Self) -> bool {
-        self.get() == other.get()
-    }
-}
-
-impl<T: OptionalCompatiblePod + Eq> Eq for OptionPod<T> {}
-
-impl<T: OptionalCompatiblePod> From<Option<T>> for OptionPod<T> {
-    #[inline]
-    fn from(value: Option<T>) -> Self {
-        match value {
-            Some(v) => Self::some(v),
-            None => Self::none(),
-        }
-    }
-}
-
-impl<T: OptionalCompatiblePod> From<OptionPod<T>> for Option<T> {
-    #[inline]
-    fn from(value: OptionPod<T>) -> Self {
-        value.get()
-    }
-}
-
-impl<T: OptionalCompatiblePod + Debug> Debug for OptionPod<T> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.get() {
-            Some(v) => write!(f, "OptionPod::Some({v:?})"),
-            None => f.write_str("OptionPod::None"),
-        }
-    }
-}
-
-// Registers each supported scalar from one list: the `OptionalCompatiblePod` 
impl and a
-// compile-time guard that `OptionPod<T>` matches the `std::optional<T>` 
footprint
-// (`size == round_up(size_of::<T>()+1, align)`). One list keeps the impl and 
its
-// layout check from drifting.
-macro_rules! impl_optional_compatible_pod {
-    ($($t:ty),* $(,)?) => { $(
-        // Fixed-width scalar; repr matches the C++ field's `std::optional`
-        // fallback (layout proven by the `const` block below).
-        unsafe impl OptionalCompatiblePod for $t {}
-        const _: () = {
-            let tsz = core::mem::size_of::<$t>();
-            let tal = core::mem::align_of::<$t>();
-            let expect = (tsz + 1).div_ceil(tal) * tal;
-            assert!(core::mem::align_of::<OptionPod<$t>>() == tal);
-            assert!(core::mem::size_of::<OptionPod<$t>>() == expect);
-        };
-    )* };
-}
-// Keep in sync with the static_assert guard at the end of 
include/tvm/ffi/optional.h.
-impl_optional_compatible_pod!(bool, i8, i16, i32, i64, u8, u16, u32, u64, f32, 
f64);
-
-//-----------------------------------------------------
-// OptionStr — String
-//-----------------------------------------------------
-
-/// In-place mirror of C++ `ffi::Optional<String>`: the 16-byte string cell
-/// itself, with `type_index == kTVMFFINone` meaning `nullopt` (the C++
-/// String/Bytes spec stores the sentinel in-cell, not as a separate flag).
-/// Reuses [`String`]'s `Clone`/`Drop`, whose refcounting is a no-op on the
-/// `nullopt` cell (`type_index` below `kTVMFFIStaticObjectBegin`).
-#[repr(transparent)]
-#[derive(Clone)]
-pub struct OptionStr {
-    // Never handed out or accessed while disengaged (a `nullopt` cell is not a
-    // valid string).
-    inner: String,
-}
-
-// Must stay 16 bytes to overlay C++ `ffi::Optional<String>` (parity with the 
POD
-// guard in `impl_optional_compatible_pod!`).
-const _: () = assert!(
-    std::mem::size_of::<OptionStr>() == 16
-        && std::mem::align_of::<OptionStr>() == 
std::mem::align_of::<crate::TVMFFIAny>()
-);
-
-impl OptionStr {
-    /// An engaged optional holding `value`.
-    #[inline]
-    pub fn some(value: String) -> Self {
-        Self { inner: value }
-    }
-
-    /// A disengaged optional (`nullopt`).
-    #[inline]
-    pub fn none() -> Self {
-        Self {
-            inner: String::none_cell(),
-        }
-    }
-
-    /// Whether a value is present.
-    #[inline]
-    pub fn has_value(&self) -> bool {
-        !self.inner.is_none_cell()
-    }
-
-    /// Whether the optional is `nullopt`.
-    #[inline]
-    pub fn is_none(&self) -> bool {
-        self.inner.is_none_cell()
-    }
-
-    /// Borrows the engaged string as `&str`, or `None` when `nullopt`.
-    #[inline]
-    pub fn as_str(&self) -> Option<&str> {
-        if self.has_value() {
-            Some(self.inner.as_str())
-        } else {
-            None
-        }
-    }
-
-    /// Takes the value out, consuming self.
-    #[inline]
-    pub fn get(self) -> Option<String> {
-        let OptionStr { inner } = self; // no `Drop` impl, so the move is 
allowed
-        if inner.is_none_cell() {
-            None
-        } else {
-            Some(inner)
-        }
-    }
-
-    /// Overwrites the value in place, dropping the previous one first 
(dec-ref'd
-    /// if it was a heap string).
-    #[inline]
-    pub fn set(&mut self, value: Option<String>) {
-        // Assignment drops the old `String` (dec_ref if heap) before moving 
in the new.
-        self.inner = match value {
-            Some(s) => s,
-            None => String::none_cell(),
-        };
-    }
-}
-
-impl Default for OptionStr {
-    /// `nullopt`, matching the C++ default constructor.
-    #[inline]
-    fn default() -> Self {
-        Self::none()
-    }
-}
-
-impl From<Option<String>> for OptionStr {
-    #[inline]
-    fn from(value: Option<String>) -> Self {
-        match value {
-            Some(s) => Self::some(s),
-            None => Self::none(),
-        }
-    }
-}
-
-impl From<OptionStr> for Option<String> {
-    #[inline]
-    fn from(value: OptionStr) -> Self {
-        value.get()
-    }
-}
-
-impl PartialEq for OptionStr {
-    // NOT derivable: derived eq would run `String::eq` on a `nullopt` cell and
-    // dereference its null object pointer; `as_str` checks the sentinel first.
-    #[inline]
-    fn eq(&self, other: &Self) -> bool {
-        self.as_str() == other.as_str()
-    }
-}
-
-impl Eq for OptionStr {}
-
-impl Debug for OptionStr {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.as_str() {
-            Some(s) => write!(f, "OptionStr::Some({s:?})"),
-            None => f.write_str("OptionStr::None"),
-        }
-    }
-}
-
-//-----------------------------------------------------
-// OptionObjRef — ObjectRef subtypes
-//-----------------------------------------------------
-
-/// Alias of [`Option`] for `ObjectRef`-subtype fields.
-///
-/// C++ `ffi::Optional<SomeRef>` is a single nullable pointer, so 
`Option<SomeRef>`
-/// (niche-optimized over the ref's non-null [`ObjectArc`](crate::ObjectArc)
-/// pointer) already mirrors it in place: `None` == `nullptr`. The alias only
-/// names that contract for consistency.
-pub type OptionObjRef<T> = Option<T>;
diff --git a/rust/tvm-ffi/src/optional.rs b/rust/tvm-ffi/src/optional.rs
new file mode 100644
index 00000000..33c85231
--- /dev/null
+++ b/rust/tvm-ffi/src/optional.rs
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ */
+//! In-place mirror of C++ `ffi::Optional<T>` (`include/tvm/ffi/optional.h`).
+//!
+//! C++ `ffi::Optional<T>` is uniformly backed by a single 16-byte `TVMFFIAny`
+//! regardless of `T`, with `type_index == kTVMFFINone` meaning `nullopt`. This
+//! makes the layout independent of the contained type, so a single Rust type
+//! mirrors every `T`.
+//!
+//! [`Optional<T>`] is `#[repr(transparent)]` over [`Any`] (the same 16-byte
+//! `TVMFFIAny` cell) and decodes such a field's bytes in place — no FFI call, 
no
+//! reflection getter/setter. It is named `Optional` (not `Option`) to 
distinguish
+//! it from Rust's [`std::option::Option`], matching the C++ `ffi::Optional` 
name.
+//!
+//! It replaces the earlier per-`T` mirrors (`OptionPod<T>` / `OptionStr` /
+//! `OptionObjRef<T>`): those tracked the three now-removed C++ storage layouts
+//! (`std::optional<T>`, the `String`/`Bytes` sentinel cell, and an `ObjectRef`
+//! pointer). With the uniform `TVMFFIAny` backing they collapse into this one
+//! type.
+
+use crate::any::Any;
+use crate::string::String;
+use crate::type_traits::AnyCompatible;
+use std::fmt::{self, Debug};
+use std::marker::PhantomData;
+use tvm_ffi_sys::TVMFFITypeIndex as TypeIndex;
+
+/// In-place mirror of C++ `ffi::Optional<T>`: a single 16-byte `TVMFFIAny` 
cell
+/// (wrapped as [`Any`]) whose `type_index == kTVMFFINone` encodes `nullopt`.
+///
+/// Layout-compatible with the C++ type (`size_of == 16`); see the [module
+/// docs](self). Reuses [`Any`]'s reference-counting `Clone`/`Drop`, which are 
a
+/// no-op on the `nullopt` cell (`type_index` below 
`kTVMFFIStaticObjectBegin`).
+#[repr(transparent)]
+pub struct Optional<T: AnyCompatible> {
+    // Holds either the value's `TVMFFIAny` representation or a `kTVMFFINone` 
cell.
+    data: Any,
+    _marker: PhantomData<T>,
+}
+
+// Must stay 16 bytes / `TVMFFIAny`-aligned to overlay a C++ `ffi::Optional<T>`
+// field in place, independent of `T`.
+const _: () = assert!(
+    std::mem::size_of::<Optional<i64>>() == 16
+        && std::mem::size_of::<Optional<String>>() == 16
+        && std::mem::align_of::<Optional<i64>>() == 
std::mem::align_of::<crate::TVMFFIAny>()
+);
+
+impl<T: AnyCompatible> Optional<T> {
+    /// An engaged optional holding `value`.
+    #[inline]
+    pub fn some(value: T) -> Self {
+        Self {
+            data: Any::from(value),
+            _marker: PhantomData,
+        }
+    }
+
+    /// A disengaged optional (`nullopt`, a `kTVMFFINone` cell).
+    #[inline]
+    pub fn none() -> Self {
+        Self {
+            data: Any::new(),
+            _marker: PhantomData,
+        }
+    }
+
+    /// Whether a value is present.
+    #[inline]
+    pub fn has_value(&self) -> bool {
+        self.data.type_index() != TypeIndex::kTVMFFINone as i32
+    }
+
+    /// Whether the optional is `nullopt`.
+    #[inline]
+    pub fn is_none(&self) -> bool {
+        !self.has_value()
+    }
+
+    /// Decodes the value in place, cloning it out (ref-counted `inc_ref` for
+    /// object payloads). Returns `None` when `nullopt`. No FFI call.
+    #[inline]
+    pub fn get(&self) -> Option<T> {
+        self.data.try_as::<T>()
+    }
+
+    /// Takes the value out, consuming self (moves the payload, no `inc_ref`).
+    #[inline]
+    pub fn into_option(self) -> Option<T> {
+        if self.has_value() {
+            // Move the value out of the owning `Any` without dropping it, then
+            // transfer ownership of the payload into `T` (no inc/dec ref).
+            let mut raw = unsafe { Any::into_raw_ffi_any(self.data) };
+            Some(unsafe { T::move_from_any_after_check(&mut raw) })
+        } else {
+            None
+        }
+    }
+
+    /// Overwrites the value in place, dropping the previous one first 
(dec-ref'd
+    /// if it was an object payload).
+    #[inline]
+    pub fn set(&mut self, value: Option<T>) {
+        // Assignment drops the old `Any` (dec_ref if object) before storing 
the new.
+        self.data = match value {
+            Some(v) => Any::from(v),
+            None => Any::new(),
+        };
+    }
+}
+
+impl Optional<String> {
+    /// Borrows the engaged string as `&str`, or `None` when `nullopt`.
+    ///
+    /// Reinterprets the in-cell string without cloning: an engaged cell holds 
a
+    /// `String`'s exact 16-byte representation, so `&Any` can be viewed as
+    /// `&String`.
+    #[inline]
+    pub fn as_str(&self) -> Option<&str> {
+        if self.has_value() {
+            // SAFETY: an engaged `Optional<String>` cell is byte-identical to 
a
+            // `String` (both are `#[repr(transparent)]` over the 16-byte 
cell),
+            // and the borrow is tied to `&self`.
+            let s = unsafe { &*(&self.data as *const Any as *const String) };
+            Some(s.as_str())
+        } else {
+            None
+        }
+    }
+}
+
+impl<T: AnyCompatible> Default for Optional<T> {
+    /// `nullopt`, matching the C++ default constructor.
+    #[inline]
+    fn default() -> Self {
+        Self::none()
+    }
+}
+
+impl<T: AnyCompatible> Clone for Optional<T> {
+    #[inline]
+    fn clone(&self) -> Self {
+        Self {
+            // `Any::clone` inc_refs an object payload; a `nullopt` cell is a 
no-op.
+            data: self.data.clone(),
+            _marker: PhantomData,
+        }
+    }
+}
+
+impl<T: AnyCompatible + PartialEq> PartialEq for Optional<T> {
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        self.get() == other.get()
+    }
+}
+
+impl<T: AnyCompatible + Eq> Eq for Optional<T> {}
+
+impl<T: AnyCompatible> From<Option<T>> for Optional<T> {
+    #[inline]
+    fn from(value: Option<T>) -> Self {
+        match value {
+            Some(v) => Self::some(v),
+            None => Self::none(),
+        }
+    }
+}
+
+impl<T: AnyCompatible> From<Optional<T>> for Option<T> {
+    #[inline]
+    fn from(value: Optional<T>) -> Self {
+        value.into_option()
+    }
+}
+
+impl<T: AnyCompatible + Debug> Debug for Optional<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self.get() {
+            Some(v) => write!(f, "Optional::Some({v:?})"),
+            None => f.write_str("Optional::None"),
+        }
+    }
+}
diff --git a/rust/tvm-ffi/src/string.rs b/rust/tvm-ffi/src/string.rs
index 70768d6f..94739a4c 100644
--- a/rust/tvm-ffi/src/string.rs
+++ b/rust/tvm-ffi/src/string.rs
@@ -284,23 +284,6 @@ impl String {
     pub fn as_str(&self) -> &str {
         unsafe { std::str::from_utf8_unchecked(self.as_bytes()) }
     }
-
-    /// Whether the cell is the `nullopt` sentinel (`type_index == 
kTVMFFINone`).
-    /// Such a cell is NOT a valid string; only 
[`OptionStr`](crate::option::OptionStr)
-    /// holds one, and never calls string accessors on it.
-    #[inline]
-    pub(crate) fn is_none_cell(&self) -> bool {
-        self.data.type_index == TypeIndex::kTVMFFINone as i32
-    }
-
-    /// A `nullopt` sentinel cell for [`OptionStr`](crate::option::OptionStr).
-    /// `TVMFFIAny::new()` is exactly the all-zero `kTVMFFINone` cell.
-    #[inline]
-    pub(crate) fn none_cell() -> Self {
-        Self {
-            data: TVMFFIAny::new(),
-        }
-    }
 }
 
 impl<T> From<T> for String
diff --git a/rust/tvm-ffi/tests/test_optional.rs 
b/rust/tvm-ffi/tests/test_optional.rs
index 18eadec0..c90ca468 100644
--- a/rust/tvm-ffi/tests/test_optional.rs
+++ b/rust/tvm-ffi/tests/test_optional.rs
@@ -16,57 +16,70 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-use tvm_ffi::option::{OptionObjRef, OptionPod, OptionStr, 
OptionalCompatiblePod};
 use tvm_ffi::*;
 
-/// Payload+flag bytes `[0, size_of::<T>()]`; padding is excluded (not ABI, not
-/// guaranteed initialized).
-fn image<T: OptionalCompatiblePod>(opt: &OptionPod<T>) -> Vec<u8> {
-    let p = opt as *const OptionPod<T> as *const u8;
-    let n = std::mem::size_of::<T>() + 1; // payload + flag, no padding
-    // Payload and flag are always initialized; padding is not read.
-    unsafe { std::slice::from_raw_parts(p, n).to_vec() }
+/// The 16-byte `TVMFFIAny` cell backing an `Optional<T>` (type_index@0,
+/// small_str_len@4, union@8); no padding.
+fn cell_image<T: AnyCompatible>(opt: &Optional<T>) -> [u8; 16] {
+    let p = opt as *const Optional<T> as *const u8;
+    let mut b = [0u8; 16];
+    // `Optional<T>` is a fully-initialized 16-byte cell.
+    unsafe { std::ptr::copy_nonoverlapping(p, b.as_mut_ptr(), 16) };
+    b
 }
 
-/// The scalar's own bytes, to assert the optional's payload matches it 
verbatim.
-fn raw_bytes<T: OptionalCompatiblePod>(v: &T) -> Vec<u8> {
-    let p = v as *const T as *const u8;
-    // size_of::<T>() bytes of an initialized `Copy` scalar.
-    unsafe { std::slice::from_raw_parts(p, std::mem::size_of::<T>()).to_vec() }
+#[test]
+fn layout_is_uniform_16_bytes() {
+    // Independent of `T`: every `Optional<T>` is the 16-byte `TVMFFIAny` cell.
+    assert_eq!(std::mem::size_of::<Optional<i32>>(), 16);
+    assert_eq!(std::mem::size_of::<Optional<i64>>(), 16);
+    assert_eq!(std::mem::size_of::<Optional<bool>>(), 16);
+    assert_eq!(std::mem::size_of::<Optional<f64>>(), 16);
+    assert_eq!(std::mem::size_of::<Optional<String>>(), 16);
+    assert_eq!(std::mem::size_of::<Optional<Array<i64>>>(), 16);
+    assert_eq!(
+        std::mem::align_of::<Optional<i32>>(),
+        std::mem::align_of::<Optional<Array<i64>>>()
+    );
 }
 
 #[test]
-#[cfg(target_endian = "little")]
-fn byte_image_some_i32_matches_cpp() {
-    // C++ probe (both STLs): some(0x12345678) => 78 56 34 12 | 01 ..
-    let o = OptionPod::<i32>::some(0x1234_5678);
-    let b = image(&o);
-    assert_eq!(&b[0..4], &0x1234_5678_i32.to_le_bytes());
-    assert_eq!(b[4], 1, "engaged flag must sit at offset size_of::<i32>()");
+fn none_is_all_zero_cell() {
+    // `kTVMFFINone == 0` and the union is zeroed, so `nullopt` is 16 zero 
bytes.
+    assert_eq!(cell_image(&Optional::<i32>::none()), [0u8; 16]);
+    assert_eq!(cell_image(&Optional::<String>::none()), [0u8; 16]);
+    assert_eq!(cell_image(&Optional::<Array<i64>>::none()), [0u8; 16]);
 }
 
 #[test]
 #[cfg(target_endian = "little")]
-fn byte_image_some_i64_matches_cpp() {
-    let o = OptionPod::<i64>::some(0x1122_3344_5566_7788);
-    let b = image(&o);
-    assert_eq!(&b[0..8], &0x1122_3344_5566_7788_i64.to_le_bytes());
-    assert_eq!(b[8], 1, "engaged flag must sit at offset size_of::<i64>()");
+fn byte_image_some_int_matches_ffi_any() {
+    // some(0x12345678) => type_index = kTVMFFIInt @0, v_int64 = value @8.
+    let o = Optional::<i32>::some(0x1234_5678);
+    let b = cell_image(&o);
+    assert_eq!(
+        &b[0..4],
+        &(TypeIndex::kTVMFFIInt as i32).to_le_bytes(),
+        "type_index must be kTVMFFIInt"
+    );
+    assert_eq!(&b[4..8], &[0u8; 4], "zero padding");
+    assert_eq!(
+        &b[8..16],
+        &0x1234_5678_i64.to_le_bytes(),
+        "payload sits in v_int64 @8"
+    );
 }
 
-/// Payload@0 and flag@`size_of::<T>()` for every supported type, not just 
i32/i64.
 #[test]
-fn flag_offset_all_supported_types() {
-    fn check<T: OptionalCompatiblePod + PartialEq + std::fmt::Debug>(val: T) {
+fn pod_roundtrip_all_supported_types() {
+    fn check<T: AnyCompatible + PartialEq + Copy + std::fmt::Debug>(val: T) {
         let ty = std::any::type_name::<T>();
-        let sz = std::mem::size_of::<T>();
-        let some = OptionPod::<T>::some(val);
-        let b = image(&some);
-        assert_eq!(&b[0..sz], &raw_bytes(&val)[..], "payload@0 for {ty}");
-        assert_eq!(b[sz], 1, "engaged flag must sit at offset size_of for 
{ty}");
+        let some = Optional::<T>::some(val);
+        assert!(some.has_value(), "engaged has_value for {ty}");
         assert_eq!(some.get(), Some(val), "engaged roundtrip for {ty}");
-        let none = OptionPod::<T>::none();
-        assert_eq!(image(&none)[sz], 0, "flag must be clear for none for 
{ty}");
+
+        let none = Optional::<T>::none();
+        assert!(none.is_none(), "disengaged is_none for {ty}");
         assert!(none.get().is_none(), "disengaged roundtrip for {ty}");
     }
     check::<bool>(true);
@@ -84,7 +97,7 @@ fn flag_offset_all_supported_types() {
 
 #[test]
 fn roundtrip_get_set() {
-    let mut o = OptionPod::<i32>::some(42);
+    let mut o = Optional::<i32>::some(42);
     assert_eq!(o.get(), Some(42));
     assert!(o.has_value());
 
@@ -98,90 +111,84 @@ fn roundtrip_get_set() {
 
 #[test]
 fn conversions_and_default() {
-    assert_eq!(OptionPod::<f64>::from(Some(2.5)).get(), Some(2.5));
-    assert_eq!(OptionPod::<f64>::from(None).get(), None);
-    let back: Option<i16> = OptionPod::<i16>::some(9).into();
+    assert_eq!(Optional::<f64>::from(Some(2.5)).get(), Some(2.5));
+    assert_eq!(Optional::<f64>::from(None).get(), None);
+    let back: Option<i16> = Optional::<i16>::some(9).into();
     assert_eq!(back, Some(9));
-    assert_eq!(OptionPod::<u8>::default().get(), None);
-    assert_eq!(OptionPod::<bool>::some(true).get(), Some(true));
+    assert_eq!(Optional::<u8>::default().get(), None);
+    assert_eq!(Optional::<bool>::some(true).get(), Some(true));
 }
 
 #[test]
-#[allow(clippy::clone_on_copy)] // explicitly exercising the Clone impl
-fn clone_preserves_state() {
-    let some = OptionPod::<i64>::some(123);
+fn clone_preserves_state_pod() {
+    let some = Optional::<i64>::some(123);
     assert_eq!(some.clone().get(), Some(123));
-    let none = OptionPod::<i64>::none();
+    let none = Optional::<i64>::none();
     assert_eq!(none.clone().get(), None);
 }
 
 #[test]
-fn equality() {
-    assert_eq!(OptionPod::<i32>::some(1), OptionPod::<i32>::some(1));
-    assert_ne!(OptionPod::<i32>::some(1), OptionPod::<i32>::some(2));
-    assert_ne!(OptionPod::<i32>::some(1), OptionPod::<i32>::none());
-    assert_eq!(OptionPod::<i32>::none(), OptionPod::<i32>::none());
-    // `set(None)` leaves stale payload bytes; equality must still see plain 
None.
-    let mut stale = OptionPod::<i32>::some(7);
-    stale.set(None);
-    assert_eq!(stale, OptionPod::<i32>::none());
-
-    let a = || OptionStr::some(String::from("a"));
+fn equality_pod_and_string() {
+    assert_eq!(Optional::<i32>::some(1), Optional::<i32>::some(1));
+    assert_ne!(Optional::<i32>::some(1), Optional::<i32>::some(2));
+    assert_ne!(Optional::<i32>::some(1), Optional::<i32>::none());
+    assert_eq!(Optional::<i32>::none(), Optional::<i32>::none());
+    // `set(None)` resets to a plain `nullopt` cell; equality must still hold.
+    let mut cleared = Optional::<i32>::some(7);
+    cleared.set(None);
+    assert_eq!(cleared, Optional::<i32>::none());
+
+    let a = || Optional::<String>::some(String::from("a"));
     assert_eq!(a(), a());
-    assert_ne!(a(), OptionStr::some(String::from("b")));
-    assert_ne!(a(), OptionStr::none());
-    assert_eq!(OptionStr::none(), OptionStr::none());
-}
-
-// 16-byte cell (type_index@0, small_str_len@4, union@8); no padding.
-fn str_image(o: &OptionStr) -> [u8; 16] {
-    let p = o as *const OptionStr as *const u8;
-    let mut b = [0u8; 16];
-    // OptionStr is a fully-initialized 16-byte TVMFFIAny cell.
-    unsafe { std::ptr::copy_nonoverlapping(p, b.as_mut_ptr(), 16) };
-    b
+    assert_ne!(a(), Optional::<String>::some(String::from("b")));
+    assert_ne!(a(), Optional::<String>::none());
+    assert_eq!(Optional::<String>::none(), Optional::<String>::none());
 }
 
 #[test]
 #[cfg(target_endian = "little")]
-fn optional_str_byte_image_matches_cpp() {
-    // C++ probe: ffi::Optional<String> none => 16 zero bytes;
-    //            some("hi")           => 0b 00 00 00 | 02 00 00 00 | 68 69 00 
...
-    assert_eq!(str_image(&OptionStr::none()), [0u8; 16]);
-    let some = OptionStr::some(String::from("hi"));
-    let b = str_image(&some);
-    assert_eq!(&b[0..4], &[0x0b, 0, 0, 0], "type_index = kTVMFFISmallStr");
+fn string_byte_image_matches_ffi_any() {
+    // ffi::Optional<String> none => 16 zero bytes;
+    // some("hi") => kTVMFFISmallStr @0 | small_str_len=2 @4 | "hi" inline @8.
+    assert_eq!(cell_image(&Optional::<String>::none()), [0u8; 16]);
+    let some = Optional::<String>::some(String::from("hi"));
+    let b = cell_image(&some);
+    assert_eq!(
+        &b[0..4],
+        &(TypeIndex::kTVMFFISmallStr as i32).to_le_bytes(),
+        "type_index = kTVMFFISmallStr"
+    );
     assert_eq!(&b[4..8], &[0x02, 0, 0, 0], "small_str_len = 2");
     assert_eq!(&b[8..10], b"hi", "inline payload");
 }
 
 #[test]
-fn optional_str_roundtrip_and_conversions() {
+fn string_roundtrip_and_as_str() {
     // small (inline) string
-    let s = OptionStr::some(String::from("hi"));
+    let s = Optional::<String>::some(String::from("hi"));
     assert!(s.has_value());
     assert_eq!(s.as_str(), Some("hi"));
     assert_eq!(s.get().as_deref(), Some("hi"));
 
     // nullopt
-    let n = OptionStr::none();
+    let n = Optional::<String>::none();
     assert!(n.is_none());
     assert_eq!(n.as_str(), None);
     assert_eq!(n.get(), None);
 
     // conversions + default
-    let from_some: OptionStr = Some(String::from("x")).into();
+    let from_some: Optional<String> = Some(String::from("x")).into();
     assert_eq!(from_some.as_str(), Some("x"));
-    let back: Option<String> = OptionStr::none().into();
+    let back: Option<String> = Optional::<String>::none().into();
     assert!(back.is_none());
-    assert!(OptionStr::default().is_none());
+    assert!(Optional::<String>::default().is_none());
 }
 
 #[test]
-fn optional_str_heap_clone_no_double_free() {
+fn string_heap_clone_no_double_free() {
     // long (heap) string exercises refcounted Clone/Drop through the wrapper.
     let long = String::from("a-very-long-heap-allocated-string-value");
-    let a = OptionStr::some(long);
+    let a = Optional::<String>::some(long);
     let b = a.clone();
     assert_eq!(a.as_str(), Some("a-very-long-heap-allocated-string-value"));
     assert_eq!(b.as_str(), Some("a-very-long-heap-allocated-string-value"));
@@ -189,16 +196,15 @@ fn optional_str_heap_clone_no_double_free() {
 }
 
 #[test]
-fn optional_str_set_in_place() {
-    // Start engaged with a heap string, then replace it: `set` must drop
-    // (dec_ref) the old heap string before moving the new one in.
-    let mut o = 
OptionStr::some(String::from("first-long-heap-allocated-value"));
+fn string_set_in_place() {
+    // Replace an engaged heap string: `set` must drop (dec_ref) the old heap
+    // string before storing the new one.
+    let mut o = 
Optional::<String>::some(String::from("first-long-heap-allocated-value"));
     assert_eq!(o.as_str(), Some("first-long-heap-allocated-value"));
 
     o.set(Some(String::from("second-long-heap-allocated-value")));
     assert_eq!(o.as_str(), Some("second-long-heap-allocated-value"));
 
-    // disengage (drops the heap string), then re-engage
     o.set(None);
     assert!(o.is_none());
     assert_eq!(o.as_str(), None);
@@ -208,13 +214,24 @@ fn optional_str_set_in_place() {
 }
 
 #[test]
-fn option_obj_ref_is_nullable_pointer() {
-    // `OptionObjRef<SomeRef>` == `Option<SomeRef>`: the niche over the ref's
-    // non-null object pointer makes it a single nullable pointer, `None` == 
`nullptr`.
-    assert_eq!(
-        std::mem::size_of::<OptionObjRef<Array<i64>>>(),
-        std::mem::size_of::<*mut ()>()
-    );
-    let none: OptionObjRef<Array<i64>> = None;
+fn object_ref_payload_roundtrip_and_clone() {
+    // An ObjectRef payload is now the same 16-byte cell (was an 8-byte 
pointer).
+    let arr = Array::new(vec![1i64, 2, 3]);
+    let opt = Optional::<Array<i64>>::some(arr);
+    assert!(opt.has_value());
+    let got = opt.get().expect("engaged");
+    assert_eq!(got.len(), 3);
+
+    // clone shares the underlying object; both drop without double-free.
+    let cloned = opt.clone();
+    assert!(cloned.has_value());
+    assert_eq!(cloned.get().expect("engaged").len(), 3);
+
+    // move the payload out
+    let moved: Option<Array<i64>> = opt.into_option();
+    assert_eq!(moved.expect("moved").len(), 3);
+
+    let none = Optional::<Array<i64>>::none();
     assert!(none.is_none());
+    assert!(none.get().is_none());
 }
diff --git a/src/ffi/extra/json_writer.cc b/src/ffi/extra/json_writer.cc
index 77f4411a..fe906048 100644
--- a/src/ffi/extra/json_writer.cc
+++ b/src/ffi/extra/json_writer.cc
@@ -44,8 +44,7 @@ namespace json {
 
 class JSONWriter {
  public:
-  // NOLINTNEXTLINE(performance-unnecessary-value-param)
-  static String Stringify(const json::Value& value, Optional<int> indent) {
+  static String Stringify(const json::Value& value, const Optional<int>& 
indent) {
     JSONWriter writer(indent.value_or(0));
     writer.WriteValue(value);
     return String(std::move(writer.result_));
@@ -270,8 +269,8 @@ class JSONWriter {
   std::unordered_set<const void*> active_lists_;
 };
 
-String Stringify(const json::Value& value, Optional<int> indent) {
-  return JSONWriter::Stringify(value, indent);  // 
NOLINT(performance-unnecessary-value-param)
+String Stringify(const json::Value& value, const Optional<int>& indent) {
+  return JSONWriter::Stringify(value, indent);
 }
 
 TVM_FFI_STATIC_INIT_BLOCK() {
diff --git a/tests/cpp/test_object.cc b/tests/cpp/test_object.cc
index a597e425..620fb119 100644
--- a/tests/cpp/test_object.cc
+++ b/tests/cpp/test_object.cc
@@ -80,7 +80,9 @@ inline constexpr bool object_ref_contains_is_enabled_v<
 static_assert(ObjectRef::_type_container_is_exact);
 static_assert(TNumber::_type_container_is_exact);
 static_assert(TInt::_type_container_is_exact);
-static_assert(Optional<TInt>::_type_container_is_exact);
+// Optional<T> is uniformly Any-backed and is no longer an ObjectRef, so it 
does
+// not participate in the ObjectRef container concept.
+static_assert(!std::is_base_of_v<ObjectRef, Optional<TInt>>);
 static_assert(!TIntOrFloatRef::_type_container_is_exact);
 static_assert(!Array<TInt>::_type_container_is_exact);
 static_assert(!List<TInt>::_type_container_is_exact);
@@ -91,7 +93,9 @@ static_assert(!Variant<TInt, 
TFloat>::_type_container_is_exact);
 
 static_assert(object_ref_contains_v<TNumber, TIntObj>);
 static_assert(object_ref_contains_v<TInt, TIntObj>);
-static_assert(object_ref_contains_v<Optional<TInt>, TIntObj>);
+// Optional<T> is no longer an ObjectRef, so it is outside the 
object-ref-contains
+// concept entirely (the trait is not even enabled for it).
+static_assert(!object_ref_contains_is_enabled_v<Optional<TInt>, TIntObj>);
 static_assert(!object_ref_contains_v<TInt, TFloatObj>);
 static_assert(!object_ref_contains_v<Array<TInt>, ArrayObj>);
 static_assert(object_ref_contains_v<TIntOrFloatRef, TIntObj>);
diff --git a/tests/cpp/test_optional.cc b/tests/cpp/test_optional.cc
index f9dedd1d..e0a696e5 100644
--- a/tests/cpp/test_optional.cc
+++ b/tests/cpp/test_optional.cc
@@ -19,6 +19,7 @@
 #include <gtest/gtest.h>
 #include <tvm/ffi/any.h>
 #include <tvm/ffi/container/array.h>
+#include <tvm/ffi/container/tensor.h>
 #include <tvm/ffi/memory.h>
 #include <tvm/ffi/optional.h>
 
@@ -32,10 +33,42 @@ namespace {
 using namespace tvm::ffi;
 using namespace tvm::ffi::testing;
 
+// Regression guard: TypeTraits<Optional<T>>::storage_enabled must PROPAGATE 
from
+// TypeTraits<T>::storage_enabled (pass-through), not be hardcoded. This keeps 
a
+// nested Optional<Optional<T>> and Optional<T> used inside 
Variant<...>/containers
+// Any-backed exactly when T itself is storage-enabled.
+static_assert(TypeTraits<Optional<int>>::storage_enabled == 
TypeTraits<int>::storage_enabled);
+static_assert(TypeTraits<Optional<int>>::storage_enabled, "int is 
storage-enabled");
+static_assert(TypeTraits<Optional<TInt>>::storage_enabled == 
TypeTraits<TInt>::storage_enabled);
+static_assert(TypeTraits<Optional<TInt>>::storage_enabled, "ObjectRef is 
storage-enabled");
+// A non-owning view type is NOT storage-enabled; the pass-through must carry 
that.
+static_assert(!TypeTraits<TensorView>::storage_enabled);
+static_assert(TypeTraits<Optional<TensorView>>::storage_enabled ==
+              TypeTraits<TensorView>::storage_enabled);
+static_assert(!TypeTraits<Optional<TensorView>>::storage_enabled,
+              "Optional<view> must not be storage-enabled");
+// Because Optional<int>/Optional<TInt> are storage-enabled, the outer
+// Optional<Optional<T>> uses the Any-backed representation (sizeof == 
sizeof(Any)),
+// and Optional<T> is accepted as a storage type (e.g. inside 
Variant/containers).
+static_assert(sizeof(Optional<Optional<int>>) == sizeof(Any));
+static_assert(sizeof(Optional<Optional<TInt>>) == sizeof(Any));
+static_assert(details::storage_enabled_v<Optional<int>>);
+
+TEST(Optional, StorageEnabledPassThrough) {
+  // Optional<int> is storage-enabled, so a nested Optional round-trips through
+  // Any via the Any-backed path.
+  Optional<Optional<int>> nested = Optional<int>(7);
+  Any any = nested;
+  auto back = any.cast<Optional<Optional<int>>>();
+  EXPECT_TRUE(back.has_value());
+  EXPECT_EQ(back.value().value(), 7);
+}
+
 TEST(Optional, TInt) {
   Optional<TInt> x;
   Optional<TInt> y = TInt(11);
-  static_assert(sizeof(Optional<TInt>) == sizeof(ObjectRef));
+  // Optional<T> is uniformly backed by a single Any (TVMFFIAny) regardless of 
T.
+  static_assert(sizeof(Optional<TInt>) == sizeof(Any));
 
   EXPECT_TRUE(!x.has_value());
   EXPECT_EQ(x.value_or(TInt(12))->value, 12);
@@ -51,7 +84,6 @@ TEST(Optional, TInt) {
 
   // move from any to optional
   auto y2 = std::move(z_any).cast<Optional<TInt>>();
-  EXPECT_EQ(y2.use_count(), 1);
   EXPECT_TRUE(y2.has_value());
   EXPECT_EQ(y2.value_or(TInt(12))->value, 11);
 }
@@ -59,7 +91,8 @@ TEST(Optional, TInt) {
 TEST(Optional, double) {
   Optional<double> x;
   Optional<double> y = 11.0;
-  static_assert(sizeof(Optional<double>) > sizeof(ObjectRef));
+  // Layout is independent of the contained type: sizeof(Optional<T>) == 
sizeof(Any).
+  static_assert(sizeof(Optional<double>) == sizeof(Any));
 
   EXPECT_TRUE(!x.has_value());
   EXPECT_EQ(x.value_or(12), 12);
@@ -120,20 +153,31 @@ TEST(Optional, AnyConvertArray) {
 
 TEST(Optional, OptionalOfOptional) {
   // testcase of optional<optional>
+  //
+  // Because nullopt is uniformly represented as kTVMFFINone in the single
+  // TVMFFIAny backing, an engaged outer Optional that holds an empty inner
+  // Optional collapses to nullopt (the two states share the kTVMFFINone bit
+  // pattern). This matches the behavior of round-tripping a nested Optional
+  // through Any. Engaged-outer/engaged-inner still nests correctly.
   Optional<Optional<int>> opt_opt_int;
   EXPECT_TRUE(!opt_opt_int.has_value());
 
+  // engaged outer holding an empty inner collapses to nullopt.
   Optional<Optional<int>> opt_opt_int2 = Optional<int>(std::nullopt);
-  EXPECT_TRUE(opt_opt_int2.has_value());
-  EXPECT_TRUE(!opt_opt_int2.value().has_value());
+  EXPECT_TRUE(!opt_opt_int2.has_value());
+
+  // engaged outer holding an engaged inner nests correctly.
+  Optional<Optional<int>> opt_opt_int3 = Optional<int>(7);
+  EXPECT_TRUE(opt_opt_int3.has_value());
+  EXPECT_TRUE(opt_opt_int3.value().has_value());
+  EXPECT_EQ(opt_opt_int3.value().value(), 7);
 
   // Optional<Optional<ObjectRef>>
   Optional<Optional<TInt>> opt_opt_tint;
   EXPECT_TRUE(!opt_opt_tint.has_value());
 
   Optional<Optional<TInt>> opt_opt_tint2 = Optional<TInt>(std::nullopt);
-  EXPECT_TRUE(opt_opt_tint2.has_value());
-  EXPECT_TRUE(!opt_opt_tint2.value().has_value());
+  EXPECT_TRUE(!opt_opt_tint2.has_value());
   opt_opt_tint2 = std::nullopt;
   EXPECT_TRUE(!opt_opt_tint2.has_value());
 
@@ -191,7 +235,7 @@ TEST(Optional, String) {
   EXPECT_TRUE(opt_str == "hello");
   EXPECT_TRUE(opt_str == String("hello"));
   EXPECT_TRUE(opt_str != std::nullopt);
-  static_assert(sizeof(Optional<String>) == sizeof(String));
+  static_assert(sizeof(Optional<String>) == sizeof(Any));
 }
 
 TEST(Optional, Bytes) {
@@ -203,49 +247,18 @@ TEST(Optional, Bytes) {
   EXPECT_TRUE(opt_bytes.has_value());
   EXPECT_EQ(opt_bytes.value().operator std::string(), "hello");
   EXPECT_TRUE(opt_bytes != std::nullopt);
-  static_assert(sizeof(Optional<Bytes>) == sizeof(Bytes));
+  static_assert(sizeof(Optional<Bytes>) == sizeof(Any));
 }
 
-// The Rust binding (rust/tvm-ffi/src/option.rs) mirrors Optional<T> in place 
as
-// `{ T value; bool engaged; }`; fail early if a toolchain's std::optional 
deviates from that.
+// Optional<T> is uniformly backed by a single TVMFFIAny (Any), so its layout 
is
+// independent of the contained type: every Optional<T> has the size and
+// alignment of a TVMFFIAny. (The Rust binding's in-place Optional<T> mirror 
is a
+// separate follow-up that adopts this uniform 16-byte representation.)
 template <typename... T>
-constexpr bool all_optional_layouts_match_rust_mirror_v =
-    ((sizeof(Optional<T>) == sizeof(T) + alignof(T) && alignof(Optional<T>) == 
alignof(T)) && ...);
+constexpr bool all_optional_layouts_uniform_v =
+    ((sizeof(Optional<T>) == sizeof(TVMFFIAny) && alignof(Optional<T>) == 
alignof(TVMFFIAny)) &&
+     ...);
 static_assert(
-    all_optional_layouts_match_rust_mirror_v<bool, int8_t, int16_t, int32_t, 
int64_t, uint8_t,
-                                             uint16_t, uint32_t, uint64_t, 
float, double>);
-// Same contract for the String/Bytes specialization (Rust OptionStr overlays 
the cell).
-static_assert(sizeof(Optional<String>) == sizeof(TVMFFIAny) &&
-              sizeof(Optional<Bytes>) == sizeof(TVMFFIAny));
-
-// The overlay also assumes the field order `{ T value @0; bool engaged 
@sizeof(T) }`;
-// pin that here (the static_asserts above pin only size/align).
-template <typename T>
-void CheckRustMirrorFieldOrder(T v) {
-  Optional<T> opt(v);
-  const char* base = reinterpret_cast<const char*>(&opt);
-  T payload;
-  std::memcpy(&payload, base, sizeof(T));
-  EXPECT_EQ(payload, v) << "payload must sit at offset 0";
-  bool engaged = false;
-  std::memcpy(&engaged, base + sizeof(T), sizeof(bool));
-  EXPECT_TRUE(engaged) << "engaged flag must sit at offset sizeof(T)";
-  opt = std::nullopt;
-  std::memcpy(&engaged, base + sizeof(T), sizeof(bool));
-  EXPECT_FALSE(engaged) << "disengaging must clear the flag at offset 
sizeof(T)";
-}
-
-TEST(Optional, RustMirrorFieldOrder) {
-  CheckRustMirrorFieldOrder<bool>(true);
-  CheckRustMirrorFieldOrder<int8_t>(0x12);
-  CheckRustMirrorFieldOrder<int16_t>(0x1234);
-  CheckRustMirrorFieldOrder<int32_t>(0x12345678);
-  CheckRustMirrorFieldOrder<int64_t>(0x1122334455667788LL);
-  CheckRustMirrorFieldOrder<uint8_t>(0xAB);
-  CheckRustMirrorFieldOrder<uint16_t>(0xABCD);
-  CheckRustMirrorFieldOrder<uint32_t>(0xABCDEF01u);
-  CheckRustMirrorFieldOrder<uint64_t>(0xABCDEF0123456789ULL);
-  CheckRustMirrorFieldOrder<float>(1.5f);
-  CheckRustMirrorFieldOrder<double>(2.5);
-}
+    all_optional_layouts_uniform_v<bool, int8_t, int16_t, int32_t, int64_t, 
uint8_t, uint16_t,
+                                   uint32_t, uint64_t, float, double, String, 
Bytes>);
 }  // namespace
diff --git a/tests/cpp/test_variant.cc b/tests/cpp/test_variant.cc
index 40a55769..77291108 100644
--- a/tests/cpp/test_variant.cc
+++ b/tests/cpp/test_variant.cc
@@ -138,7 +138,9 @@ TEST(Variant, Upcast) {
 TEST(Variant, AllObjectRef) {
   Variant<TInt, Array<TInt>> v0 = TInt(1);
   EXPECT_EQ(v0.get<TInt>()->value, 1);
-  static_assert(std::is_base_of_v<ObjectRef, decltype(v0)>);
+  // Variant is uniformly backed by a single Any (TVMFFIAny), even when every
+  // alternative derives from ObjectRef, so it is not ObjectRef-derived.
+  static_assert(!std::is_base_of_v<ObjectRef, decltype(v0)>);
   Any any0 = v0;
   EXPECT_EQ(any0.cast<TInt>()->value, 1);
   auto v2 = any0.cast<Variant<TInt, Array<TInt>>>();
@@ -148,7 +150,9 @@ TEST(Variant, AllObjectRef) {
   EXPECT_EQ(v0.get<Array<TInt>>().size(), 2);
   EXPECT_EQ(v0.get<Array<TInt>>()[0]->value, 2);
   EXPECT_EQ(v0.get<Array<TInt>>()[1]->value, 3);
-  EXPECT_EQ(sizeof(v0), sizeof(ObjectRef));
+  // The uniform TVMFFIAny backing makes the layout independent of the 
contained
+  // alternatives: sizeof(Variant<...>) == sizeof(Any).
+  EXPECT_EQ(sizeof(v0), sizeof(Any));
 }
 
 TEST(Variant, PODSameAs) {

Reply via email to