Derive Macro Object
#[derive(Object)]
{
// Attributes available to this derive:
#[type_key]
#[type_index]
#[type_final]
#[type_register]
#[type_child_slots]
#[type_child_slots_can_overflow]
#[type_s_eq_hash_kind]
#[type_reflection]
#[reflect]
}
Expand description
namespace to re-export derive macros
Derive ObjectCore for an object struct whose first field is its parent.
#[type_key = "..."] names the type, and #[type_index(...)] gives it a
static index. Otherwise a type defined in Rust declares #[type_register]:
it is registered under its parent on first use of type_index(), or takes
the index its key already has, as C++ TVM_FFI_DECLARE_OBJECT_INFO does.
Without #[type_register], the type binds a key its defining library,
usually C++, has registered, and type_index() panics if that library is
not loaded yet, so a binding never registers a key with the wrong child
slots.
#[type_final], and with #[type_register] #[type_child_slots = N] and
#[type_child_slots_can_overflow = bool], mirror C++ _type_final,
_type_child_slots (default 0) and _type_child_slots_can_overflow
(default true).
With #[type_register], fields marked #[reflect] are registered with the
type table when the type is, as C++ refl::ObjectDef<T>().def_ro(...)
does: a getter, a setter, the doc string and the type schema per field,
the metadata, and the __ffi_shallow_copy__ and __ffi_type_final__
type attributes. C++ structural equality and hashing, repr, deep copy
and Python then see the fields. #[reflect(writable, seq_hash_ignore, ...)] adds the FieldFlags of those names, name = "..." registers
the field under another name, and doc = "..." sets its doc string,
otherwise the field’s /// doc comment. #[type_s_eq_hash_kind = "TreeNode"] names the SEqHashKind; without it the type keeps its
nearest reflected ancestor’s, as a C++ subclass inherits
_type_s_eq_hash_kind. #[type_reflection(path)] names a function
fn(&mut ObjectDef<Self>) that registers the type’s methods, as C++
refl::ObjectDef<T>().def(...) does. A type with any of these attributes
also gets ShallowCopy, which shallow-copies the parent and clones every
other field, so the parent must implement ShallowCopy (Object and
reflected Rust types do) and the fields must be Clone; a reflected
field’s type must implement AnyCompatible.
Registrations from Rust hold one lock, so they do not race each other. The
runtime’s type table is not locked otherwise: as for C++, a type must not
be registered while another thread loads a library that registers types.
Calling type_index() before starting such threads registers a type
eagerly.