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 102fe0e [OBJECT] Make object info macro compatible with CRTP (#636)
102fe0e is described below
commit 102fe0e93a9627720f3f190d6efc7450c74604a7
Author: Tianqi Chen <[email protected]>
AuthorDate: Thu Jun 18 21:48:58 2026 -0400
[OBJECT] Make object info macro compatible with CRTP (#636)
This PR makes `TVM_FFI_DECLARE_OBJECT_INFO_PREDEFINED_TYPE_KEY`
compatible with CRTP-style object declarations, and fixes the MSVC build
failure seen with that pattern.
When the macro is expanded inside a CRTP base template, the cached
`_type_index` member is declared in the current CRTP base
specialization. The `_type_index` initializer now calls
`_GetOrAllocRuntimeTypeIndex()` through current-class lookup instead of
qualifying that function through the CRTP leaf type, which avoids MSVC
lookup failures on incomplete CRTP leaf types.
Other `TypeName::` lookups are preserved so leaf-provided metadata such
as `_type_key` and child-slot overrides continue to be used.
A generic `CRTPObject<T>` / `LeafObject` regression test is added in
`test_object.cc`.
Validation:
- `cmake -S . -B build-crtp -G Ninja -DCMAKE_BUILD_TYPE=Release
-DTVM_FFI_USE_EXTRA_CXX_API=ON -DTVM_FFI_BUILD_TESTS=ON`
- `ninja -C build-crtp tvm_ffi_tests`
- `./build-crtp/lib/tvm_ffi_tests
--gtest_filter=Object.CRTPObjectInfo:Object.TypeInfo`
- `./build-crtp/lib/tvm_ffi_tests --gtest_filter=Object.*`
- `pre-commit run --files include/tvm/ffi/object.h
tests/cpp/test_object.cc`
---
include/tvm/ffi/object.h | 2 +-
tests/cpp/test_object.cc | 26 ++++++++++++++++++++++++++
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/include/tvm/ffi/object.h b/include/tvm/ffi/object.h
index 71c69f1..0150c0a 100644
--- a/include/tvm/ffi/object.h
+++ b/include/tvm/ffi/object.h
@@ -971,7 +971,7 @@ struct ObjectPtrEqual {
TypeName::_type_child_slots_can_overflow,
ParentType::_GetOrAllocRuntimeTypeIndex()); \
return tindex;
\
}
\
- static inline const int32_t _type_index =
TypeName::_GetOrAllocRuntimeTypeIndex(); \
+ static inline const int32_t _type_index = _GetOrAllocRuntimeTypeIndex();
\
TVM_FFI_INLINE static int32_t RuntimeTypeIndex() noexcept { return
TypeName::_type_index; }
/*!
diff --git a/tests/cpp/test_object.cc b/tests/cpp/test_object.cc
index 4aeddef..5a5d416 100644
--- a/tests/cpp/test_object.cc
+++ b/tests/cpp/test_object.cc
@@ -27,6 +27,23 @@ namespace {
using namespace tvm::ffi;
using namespace tvm::ffi::testing;
+template <typename T>
+class CRTPObject : public Object {
+ public:
+ static constexpr int _type_child_slots [[maybe_unused]] = 0;
+ static constexpr bool _type_final [[maybe_unused]] = true;
+ TVM_FFI_DECLARE_OBJECT_INFO_PREDEFINED_TYPE_KEY(T, Object);
+
+ private:
+ friend T;
+ CRTPObject() = default;
+};
+
+class LeafObject : public CRTPObject<LeafObject> {
+ public:
+ static constexpr const char* _type_key = "test.CRTPLeaf";
+};
+
TEST(Object, RefCounter) {
ObjectPtr<TIntObj> a = make_object<TIntObj>(11);
ObjectPtr<TIntObj> b = a;
@@ -60,6 +77,15 @@ TEST(Object, TypeInfo) {
EXPECT_GE(info->type_index, TypeIndex::kTVMFFIDynObjectBegin);
}
+TEST(Object, CRTPObjectInfo) {
+ const TypeInfo* info = TVMFFIGetTypeInfo(LeafObject::RuntimeTypeIndex());
+ ASSERT_TRUE(info != nullptr);
+ EXPECT_EQ(info->type_index, LeafObject::RuntimeTypeIndex());
+ EXPECT_EQ(info->type_depth, 1);
+ EXPECT_EQ(info->type_ancestors[0]->type_index, Object::RuntimeTypeIndex());
+ EXPECT_GE(info->type_index, TypeIndex::kTVMFFIDynObjectBegin);
+}
+
TEST(Object, InstanceCheck) {
ObjectPtr<Object> a = make_object<TIntObj>(11);
ObjectPtr<Object> b = make_object<TFloatObj>(11);