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 4290354c [CORE] Make concrete object references non-nullable (#840)
4290354c is described below
commit 4290354c8cdfbf1b354c423c41611465e9e25e16
Author: Tianqi Chen <[email protected]>
AuthorDate: Sun Oct 11 10:47:26 2026 -0400
[CORE] Make concrete object references non-nullable (#840)
Make concrete object-reference wrappers and containers explicitly
non-nullable while preserving valid empty container defaults. Keep
ObjectRef, Function, and Tensor nullable for compatibility, and use
Optional to represent absence for concrete references.
Store optional object references through pointer-sized composition
instead of ObjectRef inheritance. Update ownership access, casting,
reflection, and wrapper examples to make the distinction explicit.
---
AGENTS.md | 3 ++-
docs/concepts/object_and_class.rst | 2 +-
docs/guides/cpp_lang_guide.md | 10 +++++----
docs/guides/python_lang_guide.md | 2 +-
include/tvm/ffi/cast.h | 10 +++++++--
include/tvm/ffi/container/array.h | 5 ++++-
include/tvm/ffi/container/dict.h | 5 ++++-
include/tvm/ffi/container/list.h | 5 ++++-
include/tvm/ffi/container/map.h | 5 ++++-
include/tvm/ffi/container/tuple.h | 1 +
include/tvm/ffi/enum.h | 8 ++++----
include/tvm/ffi/extra/structural_mutate.h | 4 +++-
include/tvm/ffi/extra/structural_visit.h | 4 +++-
include/tvm/ffi/extra/visit_error_context.h | 4 +++-
include/tvm/ffi/optional.h | 30 +++++++++++++++++++--------
include/tvm/ffi/reflection/access_path.h | 12 +++++------
include/tvm/ffi/reflection/enum_def.h | 7 ++++---
include/tvm/ffi/rvalue_ref.h | 4 +++-
pyproject.toml | 3 ++-
src/ffi/testing/testing.cc | 32 +++++++++++++++++------------
tests/cpp/extra/test_dataclass.cc | 2 +-
tests/cpp/extra/test_serialization.cc | 10 ++++-----
tests/cpp/extra/test_structural_mutate.cc | 12 ++++++-----
tests/cpp/test_example.cc | 2 +-
tests/cpp/test_object.cc | 16 +++++++--------
tests/cpp/test_reflection.cc | 2 +-
tests/cpp/testing_object.h | 32 ++++++++++++++---------------
27 files changed, 141 insertions(+), 91 deletions(-)
diff --git a/AGENTS.md b/AGENTS.md
index 9cf24519..5b2e143f 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -133,7 +133,8 @@ uv run --no-project --with "clang-tidy==21.1.1" \
- Header guards: `#ifndef TVM_FFI_<PATH>_H_`.
- Object pattern: `FooObj` (data) + `Foo` (ref wrapper extending `ObjectRef`).
- `TVM_FFI_DECLARE_OBJECT_INFO("key", FooObj, ParentObj)` in the Obj class.
- - `TVM_FFI_DEFINE_OBJECT_REF_METHODS(Foo, ParentRef, FooObj)` in the Ref
class.
+ - `TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(Foo, ParentRef, FooObj)` in
the Ref class.
+ - Use `Optional<Foo>` for absence; `ObjectRef`, `Function`, and `Tensor`
retain nullable handles.
- Errors: `TVM_FFI_THROW(ErrorType) << "message"`.
- Doc comments: Doxygen (`/*! \brief ... */`).
- Every file needs an Apache 2.0 license header.
diff --git a/docs/concepts/object_and_class.rst
b/docs/concepts/object_and_class.rst
index 9a4fa8d6..e92163fd 100644
--- a/docs/concepts/object_and_class.rst
+++ b/docs/concepts/object_and_class.rst
@@ -111,7 +111,7 @@ creates the underlying object can wrap
:cpp:func:`tvm::ffi::make_object`.
Define a nullable reference class.
:c:macro:`TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TypeName, ParentType,
ObjectName) <TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE>`
- Define a non-nullable reference class.
+ Define a non-nullable reference class. Use this for ordinary concrete
wrappers.
For example, a non-nullable reference class ``MyObject`` can be defined as
follows:
diff --git a/docs/guides/cpp_lang_guide.md b/docs/guides/cpp_lang_guide.md
index fe88ea5c..203f1f00 100644
--- a/docs/guides/cpp_lang_guide.md
+++ b/docs/guides/cpp_lang_guide.md
@@ -167,7 +167,7 @@ class MyIntPair : public tvm::ffi::ObjectRef {
// Required: define object reference methods
// This macro provides the necessary methods for ObjectRef functionality
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(MyIntPair, tvm::ffi::ObjectRef,
MyIntPairObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(MyIntPair,
tvm::ffi::ObjectRef, MyIntPairObj);
};
void ExampleObjectRef() {
@@ -711,11 +711,13 @@ with copy-on-write semantics. Use `Dict<K, V>` when you
need mutable in-place op
### Optional
`Optional<T>` provides a safe way to handle values that may or may not exist.
-We specialize Optional for `ffi::String` and Object types to be more compact,
-using nullptr to indicate non-existence.
+For object references, `Optional<T>` owns one nullable object pointer without
inheriting
+from `ObjectRef`. Access the contained reference explicitly with `value()` or
`operator*`.
+A null `ObjectRef`, `Function`, or `Tensor` converts to an empty optional;
ordinary
+concrete references and containers use `Optional<T>` to represent absence.
```cpp
-#include <tvm/ffi/container/optional.h>
+#include <tvm/ffi/optional.h>
void ExampleOptional() {
namespace ffi = tvm::ffi;
diff --git a/docs/guides/python_lang_guide.md b/docs/guides/python_lang_guide.md
index 1f98deb2..b98a45b8 100644
--- a/docs/guides/python_lang_guide.md
+++ b/docs/guides/python_lang_guide.md
@@ -386,7 +386,7 @@ public:
}
// Required: define object reference methods
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TestIntPair, tvm::ffi::ObjectRef,
TestIntPairObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TestIntPair,
tvm::ffi::ObjectRef, TestIntPairObj);
};
TVM_FFI_STATIC_INIT_BLOCK() {
diff --git a/include/tvm/ffi/cast.h b/include/tvm/ffi/cast.h
index 44228fe2..033ff549 100644
--- a/include/tvm/ffi/cast.h
+++ b/include/tvm/ffi/cast.h
@@ -46,8 +46,14 @@ namespace ffi {
*/
template <typename RefType, typename ObjectType>
inline RefType GetRef(const ObjectType* ptr) {
- if constexpr (object_ref_contains_v<RefType, ObjectType>) {
- if constexpr (is_optional_type_v<RefType> || RefType::_type_is_nullable) {
+ if constexpr (is_optional_type_v<RefType>) {
+ using ValueType = typename RefType::value_type;
+ static_assert(object_ref_contains_v<ValueType, ObjectType>,
+ "GetRef requires the Optional value type to contain every
ObjectType instance");
+ if (ptr == nullptr) return std::nullopt;
+ return RefType(GetRef<ValueType>(ptr));
+ } else if constexpr (object_ref_contains_v<RefType, ObjectType>) {
+ if constexpr (RefType::_type_is_nullable) {
if (ptr == nullptr) {
return details::ObjectUnsafe::ObjectRefFromObjectPtr<RefType>(nullptr);
}
diff --git a/include/tvm/ffi/container/array.h
b/include/tvm/ffi/container/array.h
index f5421df5..0680a741 100644
--- a/include/tvm/ffi/container/array.h
+++ b/include/tvm/ffi/container/array.h
@@ -276,7 +276,9 @@ class Array : public ObjectRef {
* \brief Constructor from pointer
* \param n the container pointer
*/
- explicit Array(ObjectPtr<Object> n) : ObjectRef(std::move(n)) {}
+ explicit Array(ObjectPtr<Object> n) : ObjectRef(std::move(n)) {
+ TVM_FFI_ICHECK_NOTNULL(data_.get());
+ }
/*!
* \brief Constructor from iterator
@@ -655,6 +657,7 @@ class Array : public ObjectRef {
/// \cond Doxygen_Suppress
using ContainerType = ArrayObj;
static constexpr bool _type_container_is_exact = false;
+ static constexpr bool _type_is_nullable = false;
/// \endcond
/*!
diff --git a/include/tvm/ffi/container/dict.h b/include/tvm/ffi/container/dict.h
index 32751a09..31325149 100644
--- a/include/tvm/ffi/container/dict.h
+++ b/include/tvm/ffi/container/dict.h
@@ -173,7 +173,9 @@ class Dict : public ObjectRef {
* \brief constructor from pointer
* \param n the container pointer
*/
- explicit Dict(ObjectPtr<Object> n) : ObjectRef(n) {}
+ explicit Dict(ObjectPtr<Object> n) : ObjectRef(std::move(n)) {
+ TVM_FFI_ICHECK_NOTNULL(data_.get());
+ }
/*!
* \brief constructor from iterator
* \param begin begin of iterator
@@ -274,6 +276,7 @@ class Dict : public ObjectRef {
/// \cond Doxygen_Suppress
using ContainerType = DictObj;
static constexpr bool _type_container_is_exact = false;
+ static constexpr bool _type_is_nullable = false;
/// \endcond
/// \cond Doxygen_Suppress
diff --git a/include/tvm/ffi/container/list.h b/include/tvm/ffi/container/list.h
index bf865664..6bc0c2d4 100644
--- a/include/tvm/ffi/container/list.h
+++ b/include/tvm/ffi/container/list.h
@@ -212,7 +212,9 @@ class List : public ObjectRef {
}
/*! \brief Constructor from pointer */
- explicit List(ObjectPtr<Object> n) : ObjectRef(std::move(n)) {}
+ explicit List(ObjectPtr<Object> n) : ObjectRef(std::move(n)) {
+ TVM_FFI_ICHECK_NOTNULL(data_.get());
+ }
/*!
* \brief Constructor from iterator
@@ -465,6 +467,7 @@ class List : public ObjectRef {
/// \cond Doxygen_Suppress
using ContainerType = ListObj;
static constexpr bool _type_container_is_exact = false;
+ static constexpr bool _type_is_nullable = false;
/// \endcond
private:
diff --git a/include/tvm/ffi/container/map.h b/include/tvm/ffi/container/map.h
index 5c0807ca..542643f8 100644
--- a/include/tvm/ffi/container/map.h
+++ b/include/tvm/ffi/container/map.h
@@ -168,7 +168,9 @@ class Map : public ObjectRef {
* \brief constructor from pointer
* \param n the container pointer
*/
- explicit Map(ObjectPtr<Object> n) : ObjectRef(n) {}
+ explicit Map(ObjectPtr<Object> n) : ObjectRef(std::move(n)) {
+ TVM_FFI_ICHECK_NOTNULL(data_.get());
+ }
/*!
* \brief constructor from iterator
* \param begin begin of iterator
@@ -280,6 +282,7 @@ class Map : public ObjectRef {
/// \cond Doxygen_Suppress
using ContainerType = MapObj;
static constexpr bool _type_container_is_exact = false;
+ static constexpr bool _type_is_nullable = false;
/// \endcond
/// \cond Doxygen_Suppress
diff --git a/include/tvm/ffi/container/tuple.h
b/include/tvm/ffi/container/tuple.h
index 2d73f836..7353375c 100644
--- a/include/tvm/ffi/container/tuple.h
+++ b/include/tvm/ffi/container/tuple.h
@@ -193,6 +193,7 @@ class Tuple : public ObjectRef {
/// \cond Doxygen_Suppress
using ContainerType = ArrayObj;
static constexpr bool _type_container_is_exact = false;
+ static constexpr bool _type_is_nullable = false;
/// \endcond
private:
diff --git a/include/tvm/ffi/enum.h b/include/tvm/ffi/enum.h
index d586a699..97d12442 100644
--- a/include/tvm/ffi/enum.h
+++ b/include/tvm/ffi/enum.h
@@ -63,7 +63,7 @@ class EnumStateObj : public Object {
class EnumState : public ObjectRef {
public:
/// \cond Doxygen_Suppress
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(EnumState, ObjectRef,
EnumStateObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(EnumState, ObjectRef,
EnumStateObj);
/// \endcond
};
@@ -140,7 +140,7 @@ class EnumObj : public Object {
class Enum : public ObjectRef {
public:
/// \cond Doxygen_Suppress
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(Enum, ObjectRef, EnumObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(Enum, ObjectRef, EnumObj);
/// \endcond
};
@@ -160,7 +160,7 @@ class IntEnumObj : public EnumObj {
class IntEnum : public Enum {
public:
/// \cond Doxygen_Suppress
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(IntEnum, Enum, IntEnumObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(IntEnum, Enum, IntEnumObj);
/// \endcond
};
@@ -180,7 +180,7 @@ class StrEnumObj : public EnumObj {
class StrEnum : public Enum {
public:
/// \cond Doxygen_Suppress
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(StrEnum, Enum, StrEnumObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(StrEnum, Enum, StrEnumObj);
/// \endcond
};
diff --git a/include/tvm/ffi/extra/structural_mutate.h
b/include/tvm/ffi/extra/structural_mutate.h
index db543c39..b8db9197 100644
--- a/include/tvm/ffi/extra/structural_mutate.h
+++ b/include/tvm/ffi/extra/structural_mutate.h
@@ -766,7 +766,9 @@ class StructuralMutator : public ObjectRef {
* \brief Construct from an existing mutator object pointer.
* \param n The object pointer to wrap.
*/
- explicit StructuralMutator(ObjectPtr<StructuralMutatorObj> n) :
ObjectRef(std::move(n)) {}
+ explicit StructuralMutator(ObjectPtr<StructuralMutatorObj> n) :
ObjectRef(std::move(n)) {
+ TVM_FFI_ICHECK_NOTNULL(data_.get());
+ }
/// \cond Doxygen_Suppress
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(StructuralMutator, ObjectRef,
StructuralMutatorObj);
diff --git a/include/tvm/ffi/extra/structural_visit.h
b/include/tvm/ffi/extra/structural_visit.h
index 75df53d8..de3eba98 100644
--- a/include/tvm/ffi/extra/structural_visit.h
+++ b/include/tvm/ffi/extra/structural_visit.h
@@ -302,7 +302,9 @@ class StructuralVisitor : public ObjectRef {
* \brief Construct from an existing object pointer.
* \param n The object pointer to wrap.
*/
- explicit StructuralVisitor(ObjectPtr<StructuralVisitorObj> n) :
ObjectRef(std::move(n)) {}
+ explicit StructuralVisitor(ObjectPtr<StructuralVisitorObj> n) :
ObjectRef(std::move(n)) {
+ TVM_FFI_ICHECK_NOTNULL(data_.get());
+ }
/// \cond Doxygen_Suppress
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(StructuralVisitor, ObjectRef,
StructuralVisitorObj);
diff --git a/include/tvm/ffi/extra/visit_error_context.h
b/include/tvm/ffi/extra/visit_error_context.h
index 76c49375..4990fdc7 100644
--- a/include/tvm/ffi/extra/visit_error_context.h
+++ b/include/tvm/ffi/extra/visit_error_context.h
@@ -120,7 +120,9 @@ class VisitErrorContext : public ObjectRef {
bool allow_prefix_match = false);
/// \cond Doxygen_Suppress
- explicit VisitErrorContext(ObjectPtr<VisitErrorContextObj> n) :
ObjectRef(std::move(n)) {}
+ explicit VisitErrorContext(ObjectPtr<VisitErrorContextObj> n) :
ObjectRef(std::move(n)) {
+ TVM_FFI_ICHECK_NOTNULL(data_.get());
+ }
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(VisitErrorContext, ObjectRef,
VisitErrorContextObj);
/// \endcond
};
diff --git a/include/tvm/ffi/optional.h b/include/tvm/ffi/optional.h
index a089618b..7a14bc2a 100644
--- a/include/tvm/ffi/optional.h
+++ b/include/tvm/ffi/optional.h
@@ -368,15 +368,15 @@ class Optional<T,
/*!
* \brief Pointer-sized Optional specialization for ObjectRef types.
*
- * ObjectRef already owns an ObjectPtr<Object>. Reusing that storage keeps the
- * long-standing nullable-pointer ABI: nullptr is nullopt, and an engaged value
- * is represented by the object's pointer with no TVMFFIAny wrapper.
+ * One ObjectPtr<Object> keeps the nullable-pointer ABI: nullptr is nullopt,
and
+ * an engaged value is represented by the object's pointer with no TVMFFIAny
+ * wrapper. Optional is not an ObjectRef; access the contained reference
explicitly.
*/
template <typename T>
-class Optional<T, std::enable_if_t<use_object_ref_optional_v<T>>> : public
ObjectRef {
+class Optional<T, std::enable_if_t<use_object_ref_optional_v<T>>> {
public:
+ using value_type = T;
using ContainerType = typename T::ContainerType;
- static constexpr bool _type_container_is_exact = T::_type_container_is_exact;
Optional() = default;
// Special members are explicitly inlined to enable move cleanup
optimizations
@@ -384,7 +384,7 @@ class Optional<T,
std::enable_if_t<use_object_ref_optional_v<T>>> : public Objec
// NOLINTBEGIN(google-explicit-constructor)
TVM_FFI_INLINE Optional(const Optional&) = default;
TVM_FFI_INLINE Optional(Optional&&) noexcept = default;
- explicit Optional(UnsafeInit tag) : ObjectRef(tag) {}
+ explicit Optional(UnsafeInit) {}
Optional(std::nullopt_t) {}
Optional(std::nullptr_t) {}
TVM_FFI_INLINE Optional(std::optional<T> other) {
@@ -392,17 +392,19 @@ class Optional<T,
std::enable_if_t<use_object_ref_optional_v<T>>> : public Objec
*this = *std::move(other);
}
}
- TVM_FFI_INLINE Optional(T other) : ObjectRef(std::move(other)) {}
+ TVM_FFI_INLINE Optional(T other)
+ :
data_(details::ObjectUnsafe::ObjectPtrFromObjectRef<Object>(std::move(other)))
{}
// NOLINTEND(google-explicit-constructor)
TVM_FFI_INLINE Optional& operator=(const Optional&) = default;
TVM_FFI_INLINE Optional& operator=(Optional&& other) noexcept {
- ObjectRef::operator=(std::move(other));
+ data_ = std::move(other.data_);
+ other.data_ = nullptr;
return *this;
}
TVM_FFI_INLINE Optional& operator=(T other) {
- ObjectRef::operator=(std::move(other));
+ data_ =
details::ObjectUnsafe::ObjectPtrFromObjectRef<Object>(std::move(other));
return *this;
}
@@ -489,7 +491,17 @@ class Optional<T,
std::enable_if_t<use_object_ref_optional_v<T>>> : public Objec
return static_cast<ContainerType*>(data_.get());
}
+ TVM_FFI_INLINE const ContainerType* operator->() const { return get(); }
+ TVM_FFI_INLINE bool same_as(const Optional& other) const { return data_ ==
other.data_; }
+ TVM_FFI_INLINE bool same_as(const ObjectRef& other) const { return
data_.get() == other.get(); }
+ TVM_FFI_INLINE bool unique() const { return data_.unique(); }
+ TVM_FFI_INLINE int use_count() const { return data_.use_count(); }
+
private:
+ ObjectPtr<Object> data_;
+
+ friend struct details::ObjectUnsafe;
+
template <typename U>
TVM_FFI_INLINE auto EQToOptional(const U& other) const {
using RetType = decltype(operator*() == *other);
diff --git a/include/tvm/ffi/reflection/access_path.h
b/include/tvm/ffi/reflection/access_path.h
index 74d106ce..afaa0464 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 = lhs->parent.as<AccessPathObj>();
- rhs = rhs->parent.as<AccessPathObj>();
+ 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);
@@ -373,8 +373,8 @@ class AccessPath : public ObjectRef {
using AccessPathPair = Tuple<AccessPath, AccessPath>;
inline Optional<AccessPath> AccessPathObj::GetParent() const {
- if (auto opt_parent = this->parent.as<AccessPath>()) {
- return opt_parent;
+ if (parent) {
+ return (*parent).as<AccessPath>();
}
return std::nullopt;
}
@@ -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 = current->parent.as<AccessPathObj>();
+ 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 = rhs_path->parent.as<AccessPathObj>();
+ rhs_path = (*rhs_path->parent).as<AccessPathObj>();
}
return PathEqual(this, rhs_path);
}
diff --git a/include/tvm/ffi/reflection/enum_def.h
b/include/tvm/ffi/reflection/enum_def.h
index b32e876e..4b72fe3a 100644
--- a/include/tvm/ffi/reflection/enum_def.h
+++ b/include/tvm/ffi/reflection/enum_def.h
@@ -107,7 +107,7 @@ class EnumDef : public ReflectionDefBase {
::tvm::ffi::details::ObjectUnsafe::GetHeader(obj.get())->type_index =
type_index_;
obj->_int_index = int_index;
obj->_str_index = std::move(str_index);
- instance_ = Enum(ObjectPtr<EnumObj>(std::move(obj)));
+ instance_ =
::tvm::ffi::details::ObjectUnsafe::ObjectRefFromObjectPtr<Enum>(std::move(obj));
entries.push_back(instance_);
indexes.Set(int_key, instance_);
indexes.Set(str_key, instance_);
@@ -131,7 +131,8 @@ class EnumDef : public ReflectionDefBase {
// GCC runs attribute constructors before dynamic initialization of inline
type indices.
// Set the header explicitly so the state is not packed as `None` during
static init.
::tvm::ffi::details::ObjectUnsafe::GetHeader(state_obj.get())->type_index
= state_type_index;
- EnumState state(std::move(state_obj));
+ EnumState state =
+
::tvm::ffi::details::ObjectUnsafe::ObjectRefFromObjectPtr<EnumState>(std::move(state_obj));
constexpr TVMFFIByteArray name = AsByteArray(type_attr::kEnumState);
TVMFFIAny value_any = AnyView(state).CopyToTVMFFIAny();
TVM_FFI_CHECK_SAFE_CALL(TVMFFITypeRegisterAttr(type_index_, &name,
&value_any));
@@ -139,7 +140,7 @@ class EnumDef : public ReflectionDefBase {
}
int32_t type_index_;
- Enum instance_;
+ Enum instance_{UnsafeInit{}};
};
} // namespace reflection
diff --git a/include/tvm/ffi/rvalue_ref.h b/include/tvm/ffi/rvalue_ref.h
index c34a12e2..e55c41de 100644
--- a/include/tvm/ffi/rvalue_ref.h
+++ b/include/tvm/ffi/rvalue_ref.h
@@ -76,7 +76,9 @@ class RValueRef {
:
data_(details::ObjectUnsafe::ObjectPtrFromObjectRef<ContainerType>(std::move(data)))
{}
/*! \brief return the data as rvalue */
- TObjRef operator*() && { return TObjRef(std::move(data_)); }
+ TObjRef operator*() && {
+ return
details::ObjectUnsafe::ObjectRefFromObjectPtr<TObjRef>(std::move(data_));
+ }
private:
mutable ObjectPtr<ContainerType> data_;
diff --git a/pyproject.toml b/pyproject.toml
index 105953b2..dddadc2a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -111,7 +111,8 @@ tvm-ffi-stubgen = "tvm_ffi.stub.cli:__main__"
# __dealloc__, and Cython 3.2.8 (2026-06-30) fixed the free-threaded object
# keep-alive scheme for code executed there (cython#7769). Earlier Cython can
# collect the wrapper mid-__dealloc__ on the 3.14t build.
-requires = ["scikit-build-core>=0.10.0", "cython>=3.2.8", "setuptools-scm"]
+# scikit-build-core 1.1.0 breaks free-threaded Development.Module discovery on
CMake <4.1.2.
+requires = ["scikit-build-core>=0.10.0,!=1.1.0", "cython>=3.2.8",
"setuptools-scm"]
build-backend = "scikit_build_core.build"
[tool.scikit-build]
diff --git a/src/ffi/testing/testing.cc b/src/ffi/testing/testing.cc
index cda1078e..319c8347 100644
--- a/src/ffi/testing/testing.cc
+++ b/src/ffi/testing/testing.cc
@@ -69,7 +69,7 @@ class TestIntPair : public tvm::ffi::ObjectRef {
int64_t Sum() const { return get()->a + get()->b; }
// Required: define object reference methods
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TestIntPair, tvm::ffi::ObjectRef,
TestIntPairObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TestIntPair,
tvm::ffi::ObjectRef, TestIntPairObj);
};
class TestFrozenCxxObj : public tvm::ffi::Object {
@@ -103,7 +103,8 @@ class TestEnumVariantObj : public tvm::ffi::EnumObj {
class TestEnumVariant : public tvm::ffi::Enum {
public:
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TestEnumVariant, tvm::ffi::Enum,
TestEnumVariantObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TestEnumVariant,
tvm::ffi::Enum,
+ TestEnumVariantObj);
};
TVM_FFI_STATIC_INIT_BLOCK() {
@@ -125,7 +126,8 @@ class TestCxxIntEnumObj : public tvm::ffi::IntEnumObj {
class TestCxxIntEnum : public tvm::ffi::IntEnum {
public:
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TestCxxIntEnum,
tvm::ffi::IntEnum, TestCxxIntEnumObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TestCxxIntEnum,
tvm::ffi::IntEnum,
+ TestCxxIntEnumObj);
};
class TestCxxStrEnumObj : public tvm::ffi::StrEnumObj {
@@ -137,7 +139,8 @@ class TestCxxStrEnumObj : public tvm::ffi::StrEnumObj {
class TestCxxStrEnum : public tvm::ffi::StrEnum {
public:
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TestCxxStrEnum,
tvm::ffi::StrEnum, TestCxxStrEnumObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TestCxxStrEnum,
tvm::ffi::StrEnum,
+ TestCxxStrEnumObj);
};
TVM_FFI_STATIC_INIT_BLOCK() {
@@ -278,6 +281,8 @@ class TestCxxEnumHolderObj : public Object {
TestCxxIntEnum priority;
TestCxxStrEnum opcode;
+ explicit TestCxxEnumHolderObj(UnsafeInit) : priority(UnsafeInit{}),
opcode(UnsafeInit{}) {}
+
static constexpr bool _type_mutable = true;
TVM_FFI_DECLARE_OBJECT_INFO("testing.TestCxxEnumHolder",
TestCxxEnumHolderObj, Object);
};
@@ -436,7 +441,7 @@ class TestCompareObj : public Object {
class TestCompare : public ObjectRef {
public:
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TestCompare, ObjectRef,
TestCompareObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TestCompare, ObjectRef,
TestCompareObj);
};
class TestHashObj : public Object {
@@ -454,7 +459,7 @@ class TestHashObj : public Object {
class TestHash : public ObjectRef {
public:
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TestHash, ObjectRef, TestHashObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TestHash, ObjectRef,
TestHashObj);
};
class TestCustomHashObj : public Object {
@@ -470,7 +475,7 @@ class TestCustomHashObj : public Object {
class TestCustomHash : public ObjectRef {
public:
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TestCustomHash, ObjectRef,
TestCustomHashObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TestCustomHash, ObjectRef,
TestCustomHashObj);
};
class TestCustomCompareObj : public Object {
@@ -486,7 +491,7 @@ class TestCustomCompareObj : public Object {
class TestCustomCompare : public ObjectRef {
public:
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TestCustomCompare, ObjectRef,
TestCustomCompareObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TestCustomCompare, ObjectRef,
TestCustomCompareObj);
};
// Test object with __ffi_eq__ but deliberately no __ffi_hash__.
@@ -504,7 +509,7 @@ class TestEqWithoutHashObj : public Object {
class TestEqWithoutHash : public ObjectRef {
public:
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TestEqWithoutHash, ObjectRef,
TestEqWithoutHashObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TestEqWithoutHash, ObjectRef,
TestEqWithoutHashObj);
};
// NOLINTNEXTLINE(performance-unnecessary-value-param)
@@ -922,7 +927,10 @@ class SchemaAllTypesObj : public Object {
class SchemaAllTypes : public ObjectRef {
public:
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(SchemaAllTypes, ObjectRef,
SchemaAllTypesObj);
+ SchemaAllTypes(int64_t vi, double vf, String s)
+ : ObjectRef(make_object<SchemaAllTypesObj>(vi, vf, std::move(s))) {}
+
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(SchemaAllTypes, ObjectRef,
SchemaAllTypesObj);
};
TVM_FFI_STATIC_INIT_BLOCK() {
@@ -959,9 +967,7 @@ TVM_FFI_STATIC_INIT_BLOCK() {
// Register static creator (also a static method)
.def_static(
"make_with",
- [](int64_t vi, double vf, String s) {
- return SchemaAllTypes(make_object<SchemaAllTypesObj>(vi, vf,
std::move(s)));
- },
+ [](int64_t vi, double vf, String s) { return SchemaAllTypes(vi, vf,
std::move(s)); },
"Constructor with subset of fields");
// Global typed functions to exercise RegisterFunc with various schemas
diff --git a/tests/cpp/extra/test_dataclass.cc
b/tests/cpp/extra/test_dataclass.cc
index 4e7e21a4..f9a2c857 100644
--- a/tests/cpp/extra/test_dataclass.cc
+++ b/tests/cpp/extra/test_dataclass.cc
@@ -94,7 +94,7 @@ TEST(OstreamObjectRef, DerivedSlicing) {
}
TEST(OstreamObjectRef, NullObjectRef) {
- TNumber n; // default-constructed, null
+ ObjectRef n; // default-constructed, null
std::ostringstream os;
os << n;
EXPECT_EQ(os.str(), "None");
diff --git a/tests/cpp/extra/test_serialization.cc
b/tests/cpp/extra/test_serialization.cc
index 7c30c7f3..4cf086ba 100644
--- a/tests/cpp/extra/test_serialization.cc
+++ b/tests/cpp/extra/test_serialization.cc
@@ -47,7 +47,7 @@ class SerializationEnumObj : public EnumObj {
class SerializationEnum : public Enum {
public:
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(SerializationEnum, Enum,
SerializationEnumObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(SerializationEnum, Enum,
SerializationEnumObj);
};
class SerializationIntEnumObj : public IntEnumObj {
@@ -58,8 +58,8 @@ class SerializationIntEnumObj : public IntEnumObj {
class SerializationIntEnum : public IntEnum {
public:
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(SerializationIntEnum, IntEnum,
- SerializationIntEnumObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(SerializationIntEnum, IntEnum,
+ SerializationIntEnumObj);
};
class SerializationStrEnumObj : public StrEnumObj {
@@ -70,8 +70,8 @@ class SerializationStrEnumObj : public StrEnumObj {
class SerializationStrEnum : public StrEnum {
public:
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(SerializationStrEnum, StrEnum,
- SerializationStrEnumObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(SerializationStrEnum, StrEnum,
+ SerializationStrEnumObj);
};
TVM_FFI_STATIC_INIT_BLOCK() {
diff --git a/tests/cpp/extra/test_structural_mutate.cc
b/tests/cpp/extra/test_structural_mutate.cc
index 1cc31e75..348f94be 100644
--- a/tests/cpp/extra/test_structural_mutate.cc
+++ b/tests/cpp/extra/test_structural_mutate.cc
@@ -318,7 +318,7 @@ class TNestedMapHook : public ObjectRef {
data_ = make_object<TNestedMapHookObj>(std::move(field));
}
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TNestedMapHook, ObjectRef,
TNestedMapHookObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TNestedMapHook, ObjectRef,
TNestedMapHookObj);
};
TVM_FFI_STATIC_INIT_BLOCK() {
@@ -800,10 +800,12 @@ TEST(StructuralMap,
RegisteredMutateHookUsesAssignOrReturn) {
int nullable_var_callbacks = 0;
nullable_mapped =
- StructuralMap<WalkOrder::kPostOrder>(nullable, [&](const TVar& value) ->
Expected<Any> {
- ++nullable_var_callbacks;
- return value.defined() ? Any(value) : Any(ObjectRef(nullptr));
- }).cast<TMutatePair>();
+ StructuralMap<WalkOrder::kPostOrder>(nullable,
+ [&](const Optional<TVar>& value) ->
Expected<Any> {
+ ++nullable_var_callbacks;
+ return Any(value);
+ })
+ .cast<TMutatePair>();
EXPECT_EQ(nullable_var_callbacks, 2);
EXPECT_FALSE(nullable_mapped->lhs.defined());
EXPECT_TRUE(nullable_mapped->rhs.same_as(rhs));
diff --git a/tests/cpp/test_example.cc b/tests/cpp/test_example.cc
index 47b2d0fc..9a382958 100644
--- a/tests/cpp/test_example.cc
+++ b/tests/cpp/test_example.cc
@@ -255,7 +255,7 @@ class MyIntPair : public tvm::ffi::ObjectRef {
explicit MyIntPair(int64_t a, int64_t b) { data_ =
tvm::ffi::make_object<MyIntPairObj>(a, b); }
// Required: define object reference methods
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(MyIntPair, tvm::ffi::ObjectRef,
MyIntPairObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(MyIntPair,
tvm::ffi::ObjectRef, MyIntPairObj);
};
void ExampleObjectPtr() {
diff --git a/tests/cpp/test_object.cc b/tests/cpp/test_object.cc
index 23c7cd38..5bd7762a 100644
--- a/tests/cpp/test_object.cc
+++ b/tests/cpp/test_object.cc
@@ -40,10 +40,9 @@ namespace testing {
class TIntOrFloatRef : public ObjectRef {
public:
- TIntOrFloatRef() = default;
explicit TIntOrFloatRef(UnsafeInit tag) : ObjectRef(tag) {}
- static constexpr bool _type_is_nullable = true;
+ static constexpr bool _type_is_nullable = false;
static constexpr bool _type_container_is_exact = false;
using ContainerType = Object;
};
@@ -97,9 +96,8 @@ 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);
-// ObjectRef optionals retain the original ObjectRef/ObjectPtr representation
-// and continue to participate in the ObjectRef container concept.
-static_assert(std::is_base_of_v<ObjectRef, Optional<TInt>>);
+// ObjectRef optionals retain pointer storage without inheriting ObjectRef.
+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);
@@ -110,14 +108,14 @@ 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>);
+static_assert(object_ref_contains_v<Optional<TInt>::value_type, 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>);
static_assert(object_ref_contains_v<TIntOrFloatRef, TFloatObj>);
static_assert(!object_ref_contains_v<TIntOrFloatRef, TNumberObj>);
static_assert(object_ref_contains_is_enabled_v<TInt, TIntObj>);
-static_assert(object_ref_contains_is_enabled_v<Optional<TInt>, TIntObj>);
+static_assert(!object_ref_contains_is_enabled_v<Optional<TInt>, TIntObj>);
static_assert(object_ref_contains_is_enabled_v<TIntOrFloatRef, TIntObj>);
static_assert(!object_ref_contains_is_enabled_v<int, TIntObj>);
static_assert(!object_ref_contains_is_enabled_v<TIntObj, TIntObj>);
@@ -242,7 +240,7 @@ TEST(ObjectRef, as) {
EXPECT_TRUE(c.as<TIntObj>() == nullptr);
EXPECT_TRUE(c.as<TFloatObj>() == nullptr);
EXPECT_TRUE(c.as<TNumberObj>() == nullptr);
- auto null_number = c.as<TNumber>();
+ auto null_number = c.as<ObjectRef>();
ASSERT_TRUE(null_number.has_value()) << "Expected nullable null ObjectRef
cast to succeed";
EXPECT_TRUE(!(*null_number).defined()); //
NOLINT(bugprone-unchecked-optional-access)
EXPECT_TRUE(!c.as<TInt>().has_value());
@@ -290,7 +288,7 @@ TEST(ObjectRef, AsOrThrow) {
EXPECT_EQ(a.as<TIntObj>()->value, 10);
EXPECT_EQ(a.as_or_throw<TInt>()->value, 10);
EXPECT_EQ(b.as<TFloatObj>()->value, 20);
- EXPECT_TRUE(!c.as_or_throw<TNumber>().defined());
+ EXPECT_TRUE(!c.as_or_throw<ObjectRef>().defined());
auto const_as = const_a.as<TInt>();
ASSERT_TRUE(const_as.has_value()) << "Expected const ObjectRef as<TInt>() to
succeed";
EXPECT_EQ((*const_as).get()->value, 30); //
NOLINT(bugprone-unchecked-optional-access)
diff --git a/tests/cpp/test_reflection.cc b/tests/cpp/test_reflection.cc
index 84a80b6a..2ea12f98 100644
--- a/tests/cpp/test_reflection.cc
+++ b/tests/cpp/test_reflection.cc
@@ -59,7 +59,7 @@ struct TestObjADerived : public TestObjA {
};
struct TestObjRefADerived : public ObjectRef {
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TestObjRefADerived, ObjectRef,
TestObjADerived);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TestObjRefADerived, ObjectRef,
TestObjADerived);
};
struct PrefixLookupObj : public Object {
diff --git a/tests/cpp/testing_object.h b/tests/cpp/testing_object.h
index 0b8881c3..3cd5474d 100644
--- a/tests/cpp/testing_object.h
+++ b/tests/cpp/testing_object.h
@@ -56,7 +56,7 @@ class TNumberObj : public BasePad, public Object {
class TNumber : public ObjectRef {
public:
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TNumber, ObjectRef, TNumberObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TNumber, ObjectRef,
TNumberObj);
};
class TIntObj : public TNumberObj {
@@ -75,7 +75,7 @@ class TIntObj : public TNumberObj {
class TInt : public TNumber {
public:
- explicit TInt(int64_t value) { data_ = make_object<TIntObj>(value); }
+ explicit TInt(int64_t value) : TNumber(UnsafeInit{}) { data_ =
make_object<TIntObj>(value); }
static TInt StaticAdd(TInt lhs, TInt rhs) { return TInt(lhs->value +
rhs->value); }
@@ -127,7 +127,7 @@ class TFloatObj : public TNumberObj {
class TFloat : public TNumber {
public:
- explicit TFloat(double value) { data_ = make_object<TFloatObj>(value); }
+ explicit TFloat(double value) : TNumber(UnsafeInit{}) { data_ =
make_object<TFloatObj>(value); }
static uint64_t CustomAnyHash(const Any& src) {
double value = src.cast<TFloat>()->value;
@@ -138,7 +138,7 @@ class TFloat : public TNumber {
return lhs.cast<TFloat>()->value == rhs.cast<TFloat>()->value;
}
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TFloat, TNumber, TFloatObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TFloat, TNumber, TFloatObj);
};
inline void TFloatObj::RegisterReflection() {
@@ -181,7 +181,7 @@ class TPrimExpr : public ObjectRef {
data_ = make_object<TPrimExprObj>(dtype, value);
}
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TPrimExpr, ObjectRef,
TPrimExprObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TPrimExpr, ObjectRef,
TPrimExprObj);
};
class TVarObj : public Object {
@@ -206,7 +206,7 @@ class TVar : public ObjectRef {
public:
explicit TVar(std::string name) { data_ = make_object<TVarObj>(name); }
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TVar, ObjectRef, TVarObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TVar, ObjectRef, TVarObj);
};
class TPairObj : public Object {
@@ -232,7 +232,7 @@ class TPair : public ObjectRef {
data_ = make_object<TPairObj>(std::move(lhs), std::move(rhs));
}
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TPair, ObjectRef, TPairObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TPair, ObjectRef, TPairObj);
};
class TMutatePairObj : public Object {
@@ -288,7 +288,7 @@ class TMutatePair : public ObjectRef {
data_ = make_object<TMutatePairObj>(std::move(lhs), std::move(rhs));
}
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TMutatePair, ObjectRef,
TMutatePairObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TMutatePair, ObjectRef,
TMutatePairObj);
};
class TObjectPtrHolderObj : public Object {
@@ -323,7 +323,7 @@ class TObjectPtrHolder : public ObjectRef {
data_ = make_object<TObjectPtrHolderObj>(std::move(value),
std::move(optional_alias));
}
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TObjectPtrHolder, ObjectRef,
TObjectPtrHolderObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TObjectPtrHolder, ObjectRef,
TObjectPtrHolderObj);
};
// FreeVar test object that has a sub-field referencing another FreeVar.
@@ -365,7 +365,7 @@ class TVarWithDep : public ObjectRef {
data_ = make_object<TVarWithDepObj>(std::move(name), std::move(dep));
}
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TVarWithDep, ObjectRef,
TVarWithDepObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TVarWithDep, ObjectRef,
TVarWithDepObj);
};
// Holder with one recursive-def field and one non-recursive-def field.
@@ -377,7 +377,7 @@ class TDefHolderObj : public Object {
TDefHolderObj(TVarWithDep def_recursive, TVarWithDep def_non_recursive)
: def_recursive(std::move(def_recursive)),
def_non_recursive(std::move(def_non_recursive)) {}
- explicit TDefHolderObj(UnsafeInit) {}
+ explicit TDefHolderObj(UnsafeInit tag) : def_recursive(tag),
def_non_recursive(tag) {}
static void RegisterReflection() {
namespace refl = tvm::ffi::reflection;
@@ -398,7 +398,7 @@ class TDefHolder : public ObjectRef {
data_ = make_object<TDefHolderObj>(std::move(def_recursive),
std::move(def_non_recursive));
}
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TDefHolder, ObjectRef,
TDefHolderObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TDefHolder, ObjectRef,
TDefHolderObj);
};
class TFuncObj : public Object {
@@ -444,7 +444,7 @@ class TFunc : public ObjectRef {
data_ = make_object<TFuncObj>(params, body, comment);
}
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TFunc, ObjectRef, TFuncObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TFunc, ObjectRef, TFuncObj);
};
class TCustomFuncObj : public Object {
@@ -495,7 +495,7 @@ class TCustomFunc : public ObjectRef {
data_ = make_object<TCustomFuncObj>(params, body, comment);
}
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TCustomFunc, ObjectRef,
TCustomFuncObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TCustomFunc, ObjectRef,
TCustomFuncObj);
};
// Test object with all POD field types to exercise serialization of every
field kind.
@@ -552,7 +552,7 @@ class TAllFields : public ObjectRef {
v_array, v_map);
}
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TAllFields, ObjectRef,
TAllFieldsObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TAllFields, ObjectRef,
TAllFieldsObj);
};
// Test object with fields that have default values to test deserialization
with missing fields
@@ -590,7 +590,7 @@ class TWithDefaults : public ObjectRef {
data_ = make_object<TWithDefaultsObj>(required_val, default_int,
default_str, default_bool);
}
- TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TWithDefaults, ObjectRef,
TWithDefaultsObj);
+ TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TWithDefaults, ObjectRef,
TWithDefaultsObj);
};
} // namespace testing