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-tirx.git


The following commit(s) were added to refs/heads/main by this push:
     new c12898dcf [Rust] Bump tvm-ffi to 658bd6c (#213)
c12898dcf is described below

commit c12898dcf18d1f6a85ba97c65d950fb0f0cbbe6c
Author: Linzhang Li <[email protected]>
AuthorDate: Fri Nov 6 15:53:02 2026 -0500

    [Rust] Bump tvm-ffi to 658bd6c (#213)
    
    This bumps tvm-ffi from `a472db8` to apache/tvm-ffi@658bd6c, and
    regenerates the bindings with its stub generator. It also fixes the lint
    job on main, which has failed since #212.
    
    - apache/tvm-ffi#944 makes the structural visit and mutate engines
    easier to read, without changing the public API.
    - apache/tvm-ffi#945 makes `#[derive(ObjectRef)]` the only way to
    declare an object reference, and removes `def_object_ref!`.
    
    ## Changes
    
    - **Bindings regenerated.** `#[derive(ObjectRef)]` now gives a reference
    its `Deref` to the object.
    - The stub generator therefore no longer emits an `impl Deref` for each
    reference, and those impls are gone.
      - The upcasts use the renamed `unsafe_impl_object_ref_upcast!`.
      - No generated block is edited by hand.
    - **`def_object_ref!` becomes `#[derive(ObjectRef)]`.** The crate docs,
    the tests, `rust/examples/define_ir.rs` and
    `examples/extension_guides/rust` now declare a reference like this:
      ```rust
      #[derive(Clone, tvm_ffi::derive::ObjectRef)]
      #[object_ref(parent = Type)]
      pub struct PairType {
          data: tvm_ffi::ObjectArc<PairTypeObj>,
      }
      ```
    They build it with the derive's private `from_object`, instead of
    `PairTypeObj::new(..).into()`.
    `docs/advanced/defining_ir_extensions.rst` now explains the derive in
    place of the macro.
    - **Hand-written references.**
    - `Op` and `ConstraintContext` drop their own `Deref`, which the derive
    now provides.
    - The typed expression views (`PrimExpr`, `IntExpr`, `PrimVar`) use the
    renamed `unsafe_impl_object_ref_downcast_ref!`.
    - They also use `impl_any_compatible_conversions!` instead of its three
    parts, which are now hidden.
    - **Lint.** The pinned `cargo +1.99.1 clippy ... -D warnings` step that
    #211 added fails on main. #212's PR checks ran before #211 landed, so
    they did not include it.
    - `OpaqueType::new` and `StringType::new` now allow
    `new_without_default`, as `MissingType::new` and the other IR nodes do.
    - The `Subscript` indices no longer call an `.into()` that #212 made
    redundant.
    
    ## Migration for code built on the crate
    
    | Before | After |
    | --- | --- |
    | `def_object_ref!(pub X, Parent, XObj);` | `#[derive(Clone,
    tvm_ffi::derive::ObjectRef)]` `#[object_ref(parent = Parent)]` `pub
    struct X { data: tvm_ffi::ObjectArc<XObj> }` |
    | `XObj::new(..).into()`, `X::from(XObj::new(..))` |
    `X::from_object(XObj::new(..))`, in the module that declares `X` |
    | `tvm_ffi::unsafe_impl_object_upcast!(..)` |
    `tvm_ffi::unsafe_impl_object_ref_upcast!(..)` |
    | `tvm_ffi::unsafe_impl_ref_downcast!(..)` |
    `tvm_ffi::unsafe_impl_object_ref_downcast_ref!(..)` |
    | a hand-written `impl Deref` on a `#[derive(ObjectRef)]` type | remove
    it, or opt out with `#[object_ref(skip_deref)]` |
---
 3rdparty/tvm-ffi                          |   2 +-
 docs/advanced/defining_ir_extensions.rst  |  35 ++---
 examples/extension_guides/rust/src/lib.rs |  12 +-
 rust/examples/define_ir.rs                |   8 +-
 rust/src/backend/cuda/op.rs               |  27 +---
 rust/src/ir/attrs.rs                      |  16 +-
 rust/src/ir/base.rs                       |   8 -
 rust/src/ir/expr.rs                       | 162 +++-----------------
 rust/src/ir/function.rs                   |   9 +-
 rust/src/ir/global_info.rs                |   8 -
 rust/src/ir/location.rs                   |  41 +----
 rust/src/ir/module.rs                     |   8 -
 rust/src/ir/op.rs                         |  16 +-
 rust/src/ir/prim/expr.rs                  | 243 ++++--------------------------
 rust/src/ir/prim/vector_expr.rs           |  27 +---
 rust/src/ir/stmt.rs                       | 115 ++------------
 rust/src/ir/transform/core.rs             |  46 +-----
 rust/src/ir/transform/instrument.rs       |   9 +-
 rust/src/ir/type.rs                       | 101 ++-----------
 rust/src/ir/type_def.rs                   |  10 +-
 rust/src/ir/unique_name_supply.rs         |   8 -
 rust/src/lib.rs                           |  18 ++-
 rust/src/macro/def_expr_op_overloads.rs   |  12 +-
 rust/src/macro/typed_expr_view.rs         |   6 +-
 rust/src/runtime.rs                       |   8 -
 rust/src/sym/analyzer.rs                  |  55 +------
 rust/src/sym/constraint.rs                |  41 +----
 rust/src/sym/int_set.rs                   |  16 +-
 rust/src/sym/iter_affine_map.rs           |  41 +----
 rust/src/target.rs                        |  15 --
 rust/src/tirx/function.rs                 |   9 +-
 rust/src/tirx/index_map.rs                |   8 -
 rust/src/tirx/layout.rs                   |  39 +----
 rust/src/tirx/op.rs                       |   9 +-
 rust/src/tirx/structural.rs               |  15 --
 rust/src/tirx/tensor.rs                   |   9 +-
 rust/src/tirx/thread_scope.rs             |   8 -
 rust/src/tirx/tile/dispatch.rs            |   8 -
 rust/src/tirx/tile/instruction.rs         |  18 +--
 rust/src/tirx/transform/function_pass.rs  |   9 +-
 rust/src/tirx/transform/transform.rs      |  15 --
 rust/src/tirx/type.rs                     |   9 +-
 rust/tests/ir/expr.rs                     |   7 +-
 rust/tests/ir/op_def.rs                   |  12 +-
 rust/tests/ir/type.rs                     |  12 +-
 45 files changed, 184 insertions(+), 1126 deletions(-)

diff --git a/3rdparty/tvm-ffi b/3rdparty/tvm-ffi
index a472db8d8..658bd6c58 160000
--- a/3rdparty/tvm-ffi
+++ b/3rdparty/tvm-ffi
@@ -1 +1 @@
-Subproject commit a472db8d80b57c6d6be34965e84133f7ce450c57
+Subproject commit 658bd6c584aa462e37a9e8ce69ce74c1a519f9bf
diff --git a/docs/advanced/defining_ir_extensions.rst 
b/docs/advanced/defining_ir_extensions.rst
index d728efd77..75adc950e 100644
--- a/docs/advanced/defining_ir_extensions.rst
+++ b/docs/advanced/defining_ir_extensions.rst
@@ -73,31 +73,28 @@ real and imaginary parts, as in ``TensorType``:
 
 .. note::
 
-   **What does def_object_ref! do?**
-
-   ``def_object_ref!(ObjRef, Parent, Obj)`` defines ``ObjRef``, the reference
-   type of the object type ``Obj``, as the C++ macro
-   ``TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE`` does. An ``ObjRef`` holds
-   a reference-counted pointer to an ``Obj``, and the macro gives it these
-   conversions:
-
-   - an ``Obj`` converts into an ``ObjRef`` with ``into()``;
-   - an ``ObjRef`` dereferences to its ``Obj``, so its fields read directly;
-   - an ``ObjRef`` converts into ``Parent``, the reference to the parent
-     object, with ``into()``.
-
-   A visibility such as ``pub`` before ``ObjRef`` applies to the reference.
-   Here, ``def_object_ref!(pub ComplexType, Type, ComplexTypeObj)`` defines the
-   public reference ``ComplexType``: ``ty.dtype`` reads the field of a
-   ``ComplexType``, and a ``ComplexType`` converts into a ``Type`` wherever one
-   is expected, such as the result of type inference.
+   **What does #[derive(ObjectRef)] do?**
+
+   ``#[derive(ObjectRef)]`` makes ``ComplexType``, whose one field is an
+   ``ObjectArc<ComplexTypeObj>``, the reference type of the object type
+   ``ComplexTypeObj``, as the C++ macro
+   ``TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE`` does. A reference holds a
+   reference-counted pointer to its object, and the derive gives it:
+
+   - ``Deref`` to the object, so its fields read directly: ``ty.dtype``;
+   - a private ``from_object``, which wraps a new ``ComplexTypeObj`` for the
+     type's own code, such as type inference;
+   - with ``#[object_ref(parent = Type)]``, the conversion of a
+     ``ComplexType`` into a ``Type``, the reference to the parent object, with
+     ``into()`` wherever one is expected, such as the result of type
+     inference.
 
 In Rust, as in C++, the type is defined in two parts: ``ComplexTypeObj`` is the
 object that holds the fields, and ``ComplexType`` is a reference-counted
 reference to it, which IR nodes store and functions pass around.
 ``base: TypeObj`` makes the object an IR type, and ``rs_object`` registers its
 fields for reflection, through which Python and IR JSON loading construct the
-type as they construct a C++ one. ``def_object_ref!`` defines the reference.
+type as they construct a C++ one. ``#[derive(ObjectRef)]`` defines the 
reference.
 
 The ``static_init_block!`` registers the type when the library loads.
 
diff --git a/examples/extension_guides/rust/src/lib.rs 
b/examples/extension_guides/rust/src/lib.rs
index c99b7844a..027c597a6 100644
--- a/examples/extension_guides/rust/src/lib.rs
+++ b/examples/extension_guides/rust/src/lib.rs
@@ -30,8 +30,8 @@ use tvm_tirx::ir::{
 use tvm_tirx::tirx::transform::FunctionPass;
 use tvm_tirx::tirx::Function;
 use tvm_tirx::tvm_ffi::{
-    self, def_object_ref, dispatch, rs_object, Any, AnyView, Error, 
ObjectRefCore, Result,
-    Unchanged, UnchangedOr, WalkOrder,
+    self, dispatch, rs_object, Any, AnyView, Error, ObjectRefCore, Result, 
Unchanged, UnchangedOr,
+    WalkOrder,
 };
 
 // begin type
@@ -41,7 +41,11 @@ pub struct ComplexTypeObj {
     base: TypeObj,
     pub dtype: PrimType,
 }
-def_object_ref!(pub ComplexType, Type, ComplexTypeObj);
+#[derive(Clone, tvm_ffi::derive::ObjectRef)]
+#[object_ref(parent = Type)]
+pub struct ComplexType {
+    data: tvm_ffi::ObjectArc<ComplexTypeObj>,
+}
 
 tvm_ffi::static_init_block! {
     register_type::<ComplexType>()?;
@@ -83,7 +87,7 @@ fn infer_complex(call: &CallObj) -> Result<Type> {
     let elem = float_part(&call.args.get(0)?.ty)?;
     let im = float_part(&call.args.get(1)?.ty)?;
     require(elem.dtype == im.dtype, "my_ext.complex expects parts of the same 
type")?;
-    let ty: ComplexType = ComplexTypeObj::new(TypeObj::new(call.loc.clone()), 
elem).into();
+    let ty = 
ComplexType::from_object(ComplexTypeObj::new(TypeObj::new(call.loc.clone()), 
elem));
     Ok(ty.into())
 }
 // end inference
diff --git a/rust/examples/define_ir.rs b/rust/examples/define_ir.rs
index 3e0a308ed..e8ff8d526 100644
--- a/rust/examples/define_ir.rs
+++ b/rust/examples/define_ir.rs
@@ -34,7 +34,7 @@ use tvm_tirx::ir::{
     register_type, CallEffectKind, CallObj, DictAttrs, Expr, OpDef, PrimType, 
Type, TypeObj, Var,
     UNKNOWN_LOC,
 };
-use tvm_tirx::tvm_ffi::{self, def_object_ref, rs_object, Array, Result};
+use tvm_tirx::tvm_ffi::{self, rs_object, Array, Result};
 
 fn first_arg_type(call: &CallObj) -> Result<Type> {
     Ok(call.args.get(0)?.ty.clone())
@@ -55,7 +55,11 @@ pub struct ExamplePairTypeObj {
     pub first: Type,
     pub second: Type,
 }
-def_object_ref!(pub ExamplePairType, Type, ExamplePairTypeObj);
+#[derive(Clone, tvm_ffi::derive::ObjectRef)]
+#[object_ref(parent = Type)]
+pub struct ExamplePairType {
+    data: tvm_ffi::ObjectArc<ExamplePairTypeObj>,
+}
 
 tvm_ffi::static_init_block! {
     OpDef::new("tirx.example_clamp", "Clamp an index to the range `[0, 
bound)`.")
diff --git a/rust/src/backend/cuda/op.rs b/rust/src/backend/cuda/op.rs
index 46a2a5bbc..b55bbd3dd 100644
--- a/rust/src/backend/cuda/op.rs
+++ b/rust/src/backend/cuda/op.rs
@@ -70,13 +70,6 @@ pub struct TCGen05InstrDescriptorAttrs {
     base: ObjectArc<TCGen05InstrDescriptorAttrsObj>,
 }
 
-impl Deref for TCGen05InstrDescriptorAttrs {
-    type Target = TCGen05InstrDescriptorAttrsObj;
-    fn deref(&self) -> &TCGen05InstrDescriptorAttrsObj {
-        &self.base
-    }
-}
-
 impl Deref for TCGen05InstrDescriptorAttrsObj {
     type Target = AttrsObj;
     fn deref(&self) -> &AttrsObj {
@@ -160,7 +153,7 @@ impl TCGen05InstrDescriptorAttrs {
 
 unsafe impl tvm_ffi::object::ImmutableObject for 
TCGen05InstrDescriptorAttrsObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(TCGen05InstrDescriptorAttrs => Attrs);
+tvm_ffi::unsafe_impl_object_ref_upcast!(TCGen05InstrDescriptorAttrs => Attrs);
 // tvm-ffi-stubgen(end)
 
 // tvm-ffi-stubgen(begin): 
object/tirx.cuda.TCGen05InstrDescriptorBlockScaledAttrs
@@ -199,13 +192,6 @@ pub struct TCGen05InstrDescriptorBlockScaledAttrs {
     base: ObjectArc<TCGen05InstrDescriptorBlockScaledAttrsObj>,
 }
 
-impl Deref for TCGen05InstrDescriptorBlockScaledAttrs {
-    type Target = TCGen05InstrDescriptorBlockScaledAttrsObj;
-    fn deref(&self) -> &TCGen05InstrDescriptorBlockScaledAttrsObj {
-        &self.base
-    }
-}
-
 impl Deref for TCGen05InstrDescriptorBlockScaledAttrsObj {
     type Target = AttrsObj;
     fn deref(&self) -> &AttrsObj {
@@ -293,7 +279,7 @@ impl TCGen05InstrDescriptorBlockScaledAttrs {
 
 unsafe impl tvm_ffi::object::ImmutableObject for 
TCGen05InstrDescriptorBlockScaledAttrsObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(TCGen05InstrDescriptorBlockScaledAttrs => 
Attrs);
+tvm_ffi::unsafe_impl_object_ref_upcast!(TCGen05InstrDescriptorBlockScaledAttrs 
=> Attrs);
 // tvm-ffi-stubgen(end)
 
 // tvm-ffi-stubgen(begin): object/tirx.cuda.TensorMapEncodeTiledAttr
@@ -324,13 +310,6 @@ pub struct TensorMapEncodeTiledAttr {
     base: ObjectArc<TensorMapEncodeTiledAttrObj>,
 }
 
-impl Deref for TensorMapEncodeTiledAttr {
-    type Target = TensorMapEncodeTiledAttrObj;
-    fn deref(&self) -> &TensorMapEncodeTiledAttrObj {
-        &self.base
-    }
-}
-
 impl Deref for TensorMapEncodeTiledAttrObj {
     type Target = AttrsObj;
     fn deref(&self) -> &AttrsObj {
@@ -388,5 +367,5 @@ impl TensorMapEncodeTiledAttr {
 
 unsafe impl tvm_ffi::object::ImmutableObject for TensorMapEncodeTiledAttrObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(TensorMapEncodeTiledAttr => Attrs);
+tvm_ffi::unsafe_impl_object_ref_upcast!(TensorMapEncodeTiledAttr => Attrs);
 // tvm-ffi-stubgen(end)
diff --git a/rust/src/ir/attrs.rs b/rust/src/ir/attrs.rs
index 49bb77c1b..433713c3e 100644
--- a/rust/src/ir/attrs.rs
+++ b/rust/src/ir/attrs.rs
@@ -72,13 +72,6 @@ pub struct Attrs {
     base: ObjectArc<AttrsObj>,
 }
 
-impl Deref for Attrs {
-    type Target = AttrsObj;
-    fn deref(&self) -> &AttrsObj {
-        &self.base
-    }
-}
-
 impl AttrsObj {
     pub fn new() -> Self {
         let base = Object::new();
@@ -133,13 +126,6 @@ pub struct DictAttrs {
     base: ObjectArc<DictAttrsObj>,
 }
 
-impl Deref for DictAttrs {
-    type Target = DictAttrsObj;
-    fn deref(&self) -> &DictAttrsObj {
-        &self.base
-    }
-}
-
 impl Deref for DictAttrsObj {
     type Target = AttrsObj;
     fn deref(&self) -> &AttrsObj {
@@ -164,5 +150,5 @@ impl DictAttrs {
 
 unsafe impl tvm_ffi::object::ImmutableObject for DictAttrsObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(DictAttrs => Attrs);
+tvm_ffi::unsafe_impl_object_ref_upcast!(DictAttrs => Attrs);
 // tvm-ffi-stubgen(end)
diff --git a/rust/src/ir/base.rs b/rust/src/ir/base.rs
index 351a83cdc..e7fe1db7e 100644
--- a/rust/src/ir/base.rs
+++ b/rust/src/ir/base.rs
@@ -42,7 +42,6 @@
 // tvm-ffi-stubgen(import-object): tvm_ffi::Result
 
 // tvm-ffi-stubgen(begin): import-section
-use std::ops::Deref;
 use tvm_ffi::Function;
 use tvm_ffi::Object;
 use tvm_ffi::ObjectArc;
@@ -73,13 +72,6 @@ pub struct EnvFunc {
     base: ObjectArc<EnvFuncObj>,
 }
 
-impl Deref for EnvFunc {
-    type Target = EnvFuncObj;
-    fn deref(&self) -> &EnvFuncObj {
-        &self.base
-    }
-}
-
 impl EnvFuncObj {
     pub(crate) fn new(name: String, func: Function) -> Self {
         let base = Object::new();
diff --git a/rust/src/ir/expr.rs b/rust/src/ir/expr.rs
index 668e571e7..4ea215a3b 100644
--- a/rust/src/ir/expr.rs
+++ b/rust/src/ir/expr.rs
@@ -164,13 +164,6 @@ pub struct Expr {
     base: ObjectArc<ExprObj>,
 }
 
-impl Deref for Expr {
-    type Target = ExprObj;
-    fn deref(&self) -> &ExprObj {
-        &self.base
-    }
-}
-
 impl ExprObj {
     pub fn new(loc: Location, ty: Type) -> Self {
         let base = Object::new();
@@ -451,7 +444,7 @@ crate::r#macro::typed_expr_view! {
     mismatch = typed_expr_mismatch, fallback = int_literal
 }
 
-tvm_ffi::unsafe_impl_object_upcast!(PrimExpr => Expr, IntExpr => Expr, IntExpr 
=> PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(PrimExpr => Expr, IntExpr => Expr, 
IntExpr => PrimExpr);
 
 /// The built expression, checked to be an integer, or the first error raised 
while building it.
 impl TryFrom<ExprResult> for IntExpr {
@@ -670,13 +663,6 @@ pub struct StagingExpr {
     base: ObjectArc<StagingExprObj>,
 }
 
-impl Deref for StagingExpr {
-    type Target = StagingExprObj;
-    fn deref(&self) -> &StagingExprObj {
-        &self.base
-    }
-}
-
 impl Deref for StagingExprObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -715,7 +701,7 @@ unsafe impl UnsafeInit for StagingExprObj {
 
 unsafe impl tvm_ffi::object::ImmutableObject for StagingExprObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(StagingExpr => Expr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(StagingExpr => Expr);
 // tvm-ffi-stubgen(end)
 
 // tvm-ffi-stubgen(begin): object/ir.OpaqueExpr
@@ -738,13 +724,6 @@ pub struct OpaqueExpr {
     base: ObjectArc<OpaqueExprObj>,
 }
 
-impl Deref for OpaqueExpr {
-    type Target = OpaqueExprObj;
-    fn deref(&self) -> &OpaqueExprObj {
-        &self.base
-    }
-}
-
 impl Deref for OpaqueExprObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -783,7 +762,7 @@ unsafe impl UnsafeInit for OpaqueExprObj {
 
 unsafe impl tvm_ffi::object::ImmutableObject for OpaqueExprObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(OpaqueExpr => Expr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(OpaqueExpr => Expr);
 // tvm-ffi-stubgen(end)
 
 // tvm-ffi-stubgen(begin): object/ir.GlobalVar
@@ -808,13 +787,6 @@ pub struct GlobalVar {
     base: ObjectArc<GlobalVarObj>,
 }
 
-impl Deref for GlobalVar {
-    type Target = GlobalVarObj;
-    fn deref(&self) -> &GlobalVarObj {
-        &self.base
-    }
-}
-
 impl Deref for GlobalVarObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -843,7 +815,7 @@ impl GlobalVar {
 
 unsafe impl tvm_ffi::object::ImmutableObject for GlobalVarObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(GlobalVar => Expr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(GlobalVar => Expr);
 // tvm-ffi-stubgen(end)
 
 impl GlobalVar {
@@ -876,13 +848,6 @@ pub struct Tuple {
     base: ObjectArc<TupleObj>,
 }
 
-impl Deref for Tuple {
-    type Target = TupleObj;
-    fn deref(&self) -> &TupleObj {
-        &self.base
-    }
-}
-
 impl Deref for TupleObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -911,7 +876,7 @@ impl Tuple {
 
 unsafe impl tvm_ffi::object::ImmutableObject for TupleObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Tuple => Expr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Tuple => Expr);
 // tvm-ffi-stubgen(end)
 
 impl Tuple {
@@ -957,13 +922,6 @@ pub struct TupleGetItem {
     base: ObjectArc<TupleGetItemObj>,
 }
 
-impl Deref for TupleGetItem {
-    type Target = TupleGetItemObj;
-    fn deref(&self) -> &TupleGetItemObj {
-        &self.base
-    }
-}
-
 impl Deref for TupleGetItemObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -993,7 +951,7 @@ impl TupleGetItem {
 
 unsafe impl tvm_ffi::object::ImmutableObject for TupleGetItemObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(TupleGetItem => Expr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(TupleGetItem => Expr);
 // tvm-ffi-stubgen(end)
 
 impl TupleGetItem {
@@ -1069,13 +1027,6 @@ pub struct TensorLoad {
     base: ObjectArc<TensorLoadObj>,
 }
 
-impl Deref for TensorLoad {
-    type Target = TensorLoadObj;
-    fn deref(&self) -> &TensorLoadObj {
-        &self.base
-    }
-}
-
 impl Deref for TensorLoadObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1105,7 +1056,7 @@ impl TensorLoad {
 
 unsafe impl tvm_ffi::object::ImmutableObject for TensorLoadObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(TensorLoad => Expr, TensorLoad => 
PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(TensorLoad => Expr, TensorLoad => 
PrimExpr);
 // tvm-ffi-stubgen(end)
 
 impl TensorLoad {
@@ -1164,13 +1115,6 @@ pub struct Constant {
     base: ObjectArc<ConstantObj>,
 }
 
-impl Deref for Constant {
-    type Target = ConstantObj;
-    fn deref(&self) -> &ConstantObj {
-        &self.base
-    }
-}
-
 impl Deref for ConstantObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1209,7 +1153,7 @@ unsafe impl UnsafeInit for ConstantObj {
 
 unsafe impl tvm_ffi::object::ImmutableObject for ConstantObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Constant => Expr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Constant => Expr);
 // tvm-ffi-stubgen(end)
 
 // tvm-ffi-stubgen(begin): object/ir.FloatImm
@@ -1234,13 +1178,6 @@ pub struct FloatImm {
     base: ObjectArc<FloatImmObj>,
 }
 
-impl Deref for FloatImm {
-    type Target = FloatImmObj;
-    fn deref(&self) -> &FloatImmObj {
-        &self.base
-    }
-}
-
 impl Deref for FloatImmObj {
     type Target = ConstantObj;
     fn deref(&self) -> &ConstantObj {
@@ -1265,7 +1202,7 @@ impl FloatImm {
 
 unsafe impl tvm_ffi::object::ImmutableObject for FloatImmObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(FloatImm => Expr, FloatImm => Constant, 
FloatImm => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(FloatImm => Expr, FloatImm => 
Constant, FloatImm => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 impl FloatImm {
@@ -1430,13 +1367,6 @@ pub struct IntImm {
     base: ObjectArc<IntImmObj>,
 }
 
-impl Deref for IntImm {
-    type Target = IntImmObj;
-    fn deref(&self) -> &IntImmObj {
-        &self.base
-    }
-}
-
 impl Deref for IntImmObj {
     type Target = ConstantObj;
     fn deref(&self) -> &ConstantObj {
@@ -1465,7 +1395,7 @@ impl IntImm {
 
 unsafe impl tvm_ffi::object::ImmutableObject for IntImmObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(IntImm => Expr, IntImm => Constant, IntImm 
=> PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(IntImm => Expr, IntImm => Constant, 
IntImm => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 impl IntImm {
@@ -1631,13 +1561,6 @@ pub struct GenericConst {
     base: ObjectArc<GenericConstObj>,
 }
 
-impl Deref for GenericConst {
-    type Target = GenericConstObj;
-    fn deref(&self) -> &GenericConstObj {
-        &self.base
-    }
-}
-
 impl Deref for GenericConstObj {
     type Target = ConstantObj;
     fn deref(&self) -> &ConstantObj {
@@ -1666,7 +1589,7 @@ impl GenericConst {
 
 unsafe impl tvm_ffi::object::ImmutableObject for GenericConstObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(GenericConst => Expr, GenericConst => 
Constant);
+tvm_ffi::unsafe_impl_object_ref_upcast!(GenericConst => Expr, GenericConst => 
Constant);
 // tvm-ffi-stubgen(end)
 
 impl GenericConst {
@@ -1726,13 +1649,6 @@ pub struct DataTypeImm {
     base: ObjectArc<DataTypeImmObj>,
 }
 
-impl Deref for DataTypeImm {
-    type Target = DataTypeImmObj;
-    fn deref(&self) -> &DataTypeImmObj {
-        &self.base
-    }
-}
-
 impl Deref for DataTypeImmObj {
     type Target = ConstantObj;
     fn deref(&self) -> &ConstantObj {
@@ -1761,7 +1677,7 @@ impl DataTypeImm {
 
 unsafe impl tvm_ffi::object::ImmutableObject for DataTypeImmObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(DataTypeImm => Expr, DataTypeImm => 
Constant);
+tvm_ffi::unsafe_impl_object_ref_upcast!(DataTypeImm => Expr, DataTypeImm => 
Constant);
 // tvm-ffi-stubgen(end)
 
 impl DataTypeImm {
@@ -1795,13 +1711,6 @@ pub struct StringImm {
     base: ObjectArc<StringImmObj>,
 }
 
-impl Deref for StringImm {
-    type Target = StringImmObj;
-    fn deref(&self) -> &StringImmObj {
-        &self.base
-    }
-}
-
 impl Deref for StringImmObj {
     type Target = ConstantObj;
     fn deref(&self) -> &ConstantObj {
@@ -1830,7 +1739,7 @@ impl StringImm {
 
 unsafe impl tvm_ffi::object::ImmutableObject for StringImmObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(StringImm => Expr, StringImm => Constant);
+tvm_ffi::unsafe_impl_object_ref_upcast!(StringImm => Expr, StringImm => 
Constant);
 // tvm-ffi-stubgen(end)
 
 impl StringImm {
@@ -1866,13 +1775,6 @@ pub struct Call {
     base: ObjectArc<CallObj>,
 }
 
-impl Deref for Call {
-    type Target = CallObj;
-    fn deref(&self) -> &CallObj {
-        &self.base
-    }
-}
-
 impl Deref for CallObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1918,7 +1820,7 @@ impl Call {
 
 unsafe impl tvm_ffi::object::ImmutableObject for CallObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Call => Expr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Call => Expr);
 // tvm-ffi-stubgen(end)
 
 impl Call {
@@ -2019,13 +1921,6 @@ pub struct TensorRegion {
     base: ObjectArc<TensorRegionObj>,
 }
 
-impl Deref for TensorRegion {
-    type Target = TensorRegionObj;
-    fn deref(&self) -> &TensorRegionObj {
-        &self.base
-    }
-}
-
 impl Deref for TensorRegionObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -2055,7 +1950,7 @@ impl TensorRegion {
 
 unsafe impl tvm_ffi::object::ImmutableObject for TensorRegionObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(TensorRegion => Expr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(TensorRegion => Expr);
 // tvm-ffi-stubgen(end)
 
 impl TensorRegion {
@@ -2092,13 +1987,6 @@ pub struct Var {
     base: ObjectArc<VarObj>,
 }
 
-impl Deref for Var {
-    type Target = VarObj;
-    fn deref(&self) -> &VarObj {
-        &self.base
-    }
-}
-
 impl Deref for VarObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -2142,7 +2030,7 @@ unsafe impl UnsafeInit for VarObj {
 
 unsafe impl tvm_ffi::object::ImmutableObject for VarObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Var => Expr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Var => Expr);
 // tvm-ffi-stubgen(end)
 
 impl Var {
@@ -2191,7 +2079,7 @@ crate::r#macro::typed_expr_view! {
     fallback = no_literal
 }
 
-tvm_ffi::unsafe_impl_object_upcast!(PrimVar => Expr, PrimVar => Var, PrimVar 
=> PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(PrimVar => Expr, PrimVar => Var, 
PrimVar => PrimExpr);
 
 impl PrimVar {
     /// Create the variable `name` of the primitive type `ty` (C++ 
`PrimVar(name, ty, loc)`).
@@ -2225,13 +2113,6 @@ pub struct LambdaExpr {
     base: ObjectArc<LambdaExprObj>,
 }
 
-impl Deref for LambdaExpr {
-    type Target = LambdaExprObj;
-    fn deref(&self) -> &LambdaExprObj {
-        &self.base
-    }
-}
-
 impl Deref for LambdaExprObj {
     type Target = StagingExprObj;
     fn deref(&self) -> &StagingExprObj {
@@ -2261,7 +2142,7 @@ impl LambdaExpr {
 
 unsafe impl tvm_ffi::object::ImmutableObject for LambdaExprObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(LambdaExpr => Expr, LambdaExpr => 
StagingExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(LambdaExpr => Expr, LambdaExpr => 
StagingExpr);
 // tvm-ffi-stubgen(end)
 
 impl LambdaExpr {
@@ -2318,13 +2199,6 @@ pub struct Range {
     base: ObjectArc<RangeObj>,
 }
 
-impl Deref for Range {
-    type Target = RangeObj;
-    fn deref(&self) -> &RangeObj {
-        &self.base
-    }
-}
-
 impl RangeObj {
     pub(crate) fn new(begin: PrimExpr, extent: PrimExpr, loc: Location) -> 
Self {
         let base = Object::new();
diff --git a/rust/src/ir/function.rs b/rust/src/ir/function.rs
index 9c6e72e52..84bdd2292 100644
--- a/rust/src/ir/function.rs
+++ b/rust/src/ir/function.rs
@@ -90,13 +90,6 @@ pub struct BaseFunc {
     base: ObjectArc<BaseFuncObj>,
 }
 
-impl Deref for BaseFunc {
-    type Target = BaseFuncObj;
-    fn deref(&self) -> &BaseFuncObj {
-        &self.base
-    }
-}
-
 impl Deref for BaseFuncObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -136,7 +129,7 @@ unsafe impl UnsafeInit for BaseFuncObj {
 
 unsafe impl tvm_ffi::object::ImmutableObject for BaseFuncObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(BaseFunc => Expr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(BaseFunc => Expr);
 // tvm-ffi-stubgen(end)
 
 impl BaseFunc {
diff --git a/rust/src/ir/global_info.rs b/rust/src/ir/global_info.rs
index 9f699d843..06c269e54 100644
--- a/rust/src/ir/global_info.rs
+++ b/rust/src/ir/global_info.rs
@@ -26,7 +26,6 @@
 //! entries an [`IRModule`](super::IRModule) keeps by name in `global_infos`.
 
 // tvm-ffi-stubgen(begin): import-section
-use std::ops::Deref;
 use std::ptr::addr_of_mut;
 use tvm_ffi::Object;
 use tvm_ffi::ObjectArc;
@@ -54,13 +53,6 @@ pub struct GlobalInfo {
     base: ObjectArc<GlobalInfoObj>,
 }
 
-impl Deref for GlobalInfo {
-    type Target = GlobalInfoObj;
-    fn deref(&self) -> &GlobalInfoObj {
-        &self.base
-    }
-}
-
 impl GlobalInfoObj {
     pub fn new() -> Self {
         let base = Object::new();
diff --git a/rust/src/ir/location.rs b/rust/src/ir/location.rs
index 6292624f2..076505f8e 100644
--- a/rust/src/ir/location.rs
+++ b/rust/src/ir/location.rs
@@ -79,13 +79,6 @@ pub struct Location {
     base: ObjectArc<LocationObj>,
 }
 
-impl Deref for Location {
-    type Target = LocationObj;
-    fn deref(&self) -> &LocationObj {
-        &self.base
-    }
-}
-
 impl LocationObj {
     pub fn new() -> Self {
         let base = Object::new();
@@ -134,13 +127,6 @@ pub struct UnknownLoc {
     base: ObjectArc<UnknownLocObj>,
 }
 
-impl Deref for UnknownLoc {
-    type Target = UnknownLocObj;
-    fn deref(&self) -> &UnknownLocObj {
-        &self.base
-    }
-}
-
 impl Deref for UnknownLocObj {
     type Target = LocationObj;
     fn deref(&self) -> &LocationObj {
@@ -150,7 +136,7 @@ impl Deref for UnknownLocObj {
 
 unsafe impl tvm_ffi::object::ImmutableObject for UnknownLocObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(UnknownLoc => Location);
+tvm_ffi::unsafe_impl_object_ref_upcast!(UnknownLoc => Location);
 // tvm-ffi-stubgen(end)
 
 impl UnknownLoc {
@@ -208,13 +194,6 @@ pub struct SourceLoc {
     base: ObjectArc<SourceLocObj>,
 }
 
-impl Deref for SourceLoc {
-    type Target = SourceLocObj;
-    fn deref(&self) -> &SourceLocObj {
-        &self.base
-    }
-}
-
 impl Deref for SourceLocObj {
     type Target = LocationObj;
     fn deref(&self) -> &LocationObj {
@@ -252,7 +231,7 @@ impl SourceLoc {
 
 unsafe impl tvm_ffi::object::ImmutableObject for SourceLocObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(SourceLoc => Location);
+tvm_ffi::unsafe_impl_object_ref_upcast!(SourceLoc => Location);
 // tvm-ffi-stubgen(end)
 
 // `ir.SourceLoc` stores its arguments as given: the generated 
`SourceLoc::new` is the same.
@@ -280,13 +259,6 @@ pub struct CallSiteLoc {
     base: ObjectArc<CallSiteLocObj>,
 }
 
-impl Deref for CallSiteLoc {
-    type Target = CallSiteLocObj;
-    fn deref(&self) -> &CallSiteLocObj {
-        &self.base
-    }
-}
-
 impl Deref for CallSiteLocObj {
     type Target = LocationObj;
     fn deref(&self) -> &LocationObj {
@@ -311,7 +283,7 @@ impl CallSiteLoc {
 
 unsafe impl tvm_ffi::object::ImmutableObject for CallSiteLocObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(CallSiteLoc => Location);
+tvm_ffi::unsafe_impl_object_ref_upcast!(CallSiteLoc => Location);
 // tvm-ffi-stubgen(end)
 
 // `ir.CallSiteLoc` stores its arguments as given: the generated 
`CallSiteLoc::new` is the same.
@@ -338,13 +310,6 @@ pub struct SourceName {
     base: ObjectArc<SourceNameObj>,
 }
 
-impl Deref for SourceName {
-    type Target = SourceNameObj;
-    fn deref(&self) -> &SourceNameObj {
-        &self.base
-    }
-}
-
 impl SourceNameObj {
     pub(crate) fn new(name: String) -> Self {
         let base = Object::new();
diff --git a/rust/src/ir/module.rs b/rust/src/ir/module.rs
index 4c52e23bc..94e3819e8 100644
--- a/rust/src/ir/module.rs
+++ b/rust/src/ir/module.rs
@@ -66,7 +66,6 @@ use crate::ir::function::BaseFunc;
 use crate::ir::global_info::GlobalInfo;
 use crate::ir::support;
 use std::borrow::Borrow;
-use std::ops::Deref;
 use tvm_ffi::Any;
 use tvm_ffi::Array;
 use tvm_ffi::IntoObjectRef;
@@ -103,13 +102,6 @@ pub struct IRModule {
     base: ObjectArc<IRModuleObj>,
 }
 
-impl Deref for IRModule {
-    type Target = IRModuleObj;
-    fn deref(&self) -> &IRModuleObj {
-        &self.base
-    }
-}
-
 impl IRModuleObj {
     pub(crate) fn new(
         functions: Map<GlobalVar, BaseFunc>,
diff --git a/rust/src/ir/op.rs b/rust/src/ir/op.rs
index 5ba6274c9..4d617d2af 100644
--- a/rust/src/ir/op.rs
+++ b/rust/src/ir/op.rs
@@ -143,13 +143,6 @@ pub struct Op {
     base: ObjectArc<OpObj>,
 }
 
-impl Deref for Op {
-    type Target = OpObj;
-    fn deref(&self) -> &OpObj {
-        &self.base
-    }
-}
-
 impl Deref for OpObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -266,7 +259,7 @@ impl Op {
     }
 }
 
-tvm_ffi::unsafe_impl_object_upcast!(Op => Expr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Op => Expr);
 
 // tvm-ffi-stubgen(begin): object/ir.ArgumentInfo
 /// Complete: reflected fields fill [24, 56) exactly.
@@ -291,13 +284,6 @@ pub struct ArgumentInfo {
     base: ObjectArc<ArgumentInfoObj>,
 }
 
-impl Deref for ArgumentInfo {
-    type Target = ArgumentInfoObj;
-    fn deref(&self) -> &ArgumentInfoObj {
-        &self.base
-    }
-}
-
 impl ArgumentInfoObj {
     pub(crate) fn new(name: String, doc: String) -> Self {
         let base = Object::new();
diff --git a/rust/src/ir/prim/expr.rs b/rust/src/ir/prim/expr.rs
index 6222fd31a..87c8dcb70 100644
--- a/rust/src/ir/prim/expr.rs
+++ b/rust/src/ir/prim/expr.rs
@@ -330,13 +330,6 @@ pub struct Cast {
     base: ObjectArc<CastObj>,
 }
 
-impl Deref for Cast {
-    type Target = CastObj;
-    fn deref(&self) -> &CastObj {
-        &self.base
-    }
-}
-
 impl Deref for CastObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -365,7 +358,7 @@ impl Cast {
 
 unsafe impl tvm_ffi::object::ImmutableObject for CastObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Cast => Expr, Cast => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Cast => Expr, Cast => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 impl Cast {
@@ -417,13 +410,6 @@ pub struct LShift {
     base: ObjectArc<LShiftObj>,
 }
 
-impl Deref for LShift {
-    type Target = LShiftObj;
-    fn deref(&self) -> &LShiftObj {
-        &self.base
-    }
-}
-
 impl Deref for LShiftObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -453,7 +439,7 @@ impl LShift {
 
 unsafe impl tvm_ffi::object::ImmutableObject for LShiftObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(LShift => Expr, LShift => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(LShift => Expr, LShift => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -485,13 +471,6 @@ pub struct RShift {
     base: ObjectArc<RShiftObj>,
 }
 
-impl Deref for RShift {
-    type Target = RShiftObj;
-    fn deref(&self) -> &RShiftObj {
-        &self.base
-    }
-}
-
 impl Deref for RShiftObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -521,7 +500,7 @@ impl RShift {
 
 unsafe impl tvm_ffi::object::ImmutableObject for RShiftObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(RShift => Expr, RShift => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(RShift => Expr, RShift => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -553,13 +532,6 @@ pub struct BitwiseAnd {
     base: ObjectArc<BitwiseAndObj>,
 }
 
-impl Deref for BitwiseAnd {
-    type Target = BitwiseAndObj;
-    fn deref(&self) -> &BitwiseAndObj {
-        &self.base
-    }
-}
-
 impl Deref for BitwiseAndObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -589,7 +561,7 @@ impl BitwiseAnd {
 
 unsafe impl tvm_ffi::object::ImmutableObject for BitwiseAndObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(BitwiseAnd => Expr, BitwiseAnd => 
PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(BitwiseAnd => Expr, BitwiseAnd => 
PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -621,13 +593,6 @@ pub struct BitwiseOr {
     base: ObjectArc<BitwiseOrObj>,
 }
 
-impl Deref for BitwiseOr {
-    type Target = BitwiseOrObj;
-    fn deref(&self) -> &BitwiseOrObj {
-        &self.base
-    }
-}
-
 impl Deref for BitwiseOrObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -657,7 +622,7 @@ impl BitwiseOr {
 
 unsafe impl tvm_ffi::object::ImmutableObject for BitwiseOrObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(BitwiseOr => Expr, BitwiseOr => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(BitwiseOr => Expr, BitwiseOr => 
PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -689,13 +654,6 @@ pub struct BitwiseXor {
     base: ObjectArc<BitwiseXorObj>,
 }
 
-impl Deref for BitwiseXor {
-    type Target = BitwiseXorObj;
-    fn deref(&self) -> &BitwiseXorObj {
-        &self.base
-    }
-}
-
 impl Deref for BitwiseXorObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -725,7 +683,7 @@ impl BitwiseXor {
 
 unsafe impl tvm_ffi::object::ImmutableObject for BitwiseXorObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(BitwiseXor => Expr, BitwiseXor => 
PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(BitwiseXor => Expr, BitwiseXor => 
PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -756,13 +714,6 @@ pub struct BitwiseNot {
     base: ObjectArc<BitwiseNotObj>,
 }
 
-impl Deref for BitwiseNot {
-    type Target = BitwiseNotObj;
-    fn deref(&self) -> &BitwiseNotObj {
-        &self.base
-    }
-}
-
 impl Deref for BitwiseNotObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -791,7 +742,7 @@ impl BitwiseNot {
 
 unsafe impl tvm_ffi::object::ImmutableObject for BitwiseNotObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(BitwiseNot => Expr, BitwiseNot => 
PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(BitwiseNot => Expr, BitwiseNot => 
PrimExpr);
 // tvm-ffi-stubgen(end)
 
 impl BitwiseNot {
@@ -838,13 +789,6 @@ pub struct Add {
     base: ObjectArc<AddObj>,
 }
 
-impl Deref for Add {
-    type Target = AddObj;
-    fn deref(&self) -> &AddObj {
-        &self.base
-    }
-}
-
 impl Deref for AddObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -874,7 +818,7 @@ impl Add {
 
 unsafe impl tvm_ffi::object::ImmutableObject for AddObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Add => Expr, Add => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Add => Expr, Add => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -905,13 +849,6 @@ pub struct Sub {
     base: ObjectArc<SubObj>,
 }
 
-impl Deref for Sub {
-    type Target = SubObj;
-    fn deref(&self) -> &SubObj {
-        &self.base
-    }
-}
-
 impl Deref for SubObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -941,7 +878,7 @@ impl Sub {
 
 unsafe impl tvm_ffi::object::ImmutableObject for SubObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Sub => Expr, Sub => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Sub => Expr, Sub => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -972,13 +909,6 @@ pub struct Mul {
     base: ObjectArc<MulObj>,
 }
 
-impl Deref for Mul {
-    type Target = MulObj;
-    fn deref(&self) -> &MulObj {
-        &self.base
-    }
-}
-
 impl Deref for MulObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1008,7 +938,7 @@ impl Mul {
 
 unsafe impl tvm_ffi::object::ImmutableObject for MulObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Mul => Expr, Mul => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Mul => Expr, Mul => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -1039,13 +969,6 @@ pub struct Div {
     base: ObjectArc<DivObj>,
 }
 
-impl Deref for Div {
-    type Target = DivObj;
-    fn deref(&self) -> &DivObj {
-        &self.base
-    }
-}
-
 impl Deref for DivObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1075,7 +998,7 @@ impl Div {
 
 unsafe impl tvm_ffi::object::ImmutableObject for DivObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Div => Expr, Div => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Div => Expr, Div => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -1106,13 +1029,6 @@ pub struct Mod {
     base: ObjectArc<ModObj>,
 }
 
-impl Deref for Mod {
-    type Target = ModObj;
-    fn deref(&self) -> &ModObj {
-        &self.base
-    }
-}
-
 impl Deref for ModObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1142,7 +1058,7 @@ impl Mod {
 
 unsafe impl tvm_ffi::object::ImmutableObject for ModObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Mod => Expr, Mod => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Mod => Expr, Mod => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -1173,13 +1089,6 @@ pub struct FloorDiv {
     base: ObjectArc<FloorDivObj>,
 }
 
-impl Deref for FloorDiv {
-    type Target = FloorDivObj;
-    fn deref(&self) -> &FloorDivObj {
-        &self.base
-    }
-}
-
 impl Deref for FloorDivObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1209,7 +1118,7 @@ impl FloorDiv {
 
 unsafe impl tvm_ffi::object::ImmutableObject for FloorDivObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(FloorDiv => Expr, FloorDiv => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(FloorDiv => Expr, FloorDiv => 
PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -1241,13 +1150,6 @@ pub struct FloorMod {
     base: ObjectArc<FloorModObj>,
 }
 
-impl Deref for FloorMod {
-    type Target = FloorModObj;
-    fn deref(&self) -> &FloorModObj {
-        &self.base
-    }
-}
-
 impl Deref for FloorModObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1277,7 +1179,7 @@ impl FloorMod {
 
 unsafe impl tvm_ffi::object::ImmutableObject for FloorModObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(FloorMod => Expr, FloorMod => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(FloorMod => Expr, FloorMod => 
PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -1309,13 +1211,6 @@ pub struct Min {
     base: ObjectArc<MinObj>,
 }
 
-impl Deref for Min {
-    type Target = MinObj;
-    fn deref(&self) -> &MinObj {
-        &self.base
-    }
-}
-
 impl Deref for MinObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1345,7 +1240,7 @@ impl Min {
 
 unsafe impl tvm_ffi::object::ImmutableObject for MinObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Min => Expr, Min => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Min => Expr, Min => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -1376,13 +1271,6 @@ pub struct Max {
     base: ObjectArc<MaxObj>,
 }
 
-impl Deref for Max {
-    type Target = MaxObj;
-    fn deref(&self) -> &MaxObj {
-        &self.base
-    }
-}
-
 impl Deref for MaxObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1412,7 +1300,7 @@ impl Max {
 
 unsafe impl tvm_ffi::object::ImmutableObject for MaxObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Max => Expr, Max => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Max => Expr, Max => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -1446,13 +1334,6 @@ pub struct EQ {
     base: ObjectArc<EQObj>,
 }
 
-impl Deref for EQ {
-    type Target = EQObj;
-    fn deref(&self) -> &EQObj {
-        &self.base
-    }
-}
-
 impl Deref for EQObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1482,7 +1363,7 @@ impl EQ {
 
 unsafe impl tvm_ffi::object::ImmutableObject for EQObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(EQ => Expr, EQ => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(EQ => Expr, EQ => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -1514,13 +1395,6 @@ pub struct NE {
     base: ObjectArc<NEObj>,
 }
 
-impl Deref for NE {
-    type Target = NEObj;
-    fn deref(&self) -> &NEObj {
-        &self.base
-    }
-}
-
 impl Deref for NEObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1550,7 +1424,7 @@ impl NE {
 
 unsafe impl tvm_ffi::object::ImmutableObject for NEObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(NE => Expr, NE => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(NE => Expr, NE => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -1582,13 +1456,6 @@ pub struct LT {
     base: ObjectArc<LTObj>,
 }
 
-impl Deref for LT {
-    type Target = LTObj;
-    fn deref(&self) -> &LTObj {
-        &self.base
-    }
-}
-
 impl Deref for LTObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1618,7 +1485,7 @@ impl LT {
 
 unsafe impl tvm_ffi::object::ImmutableObject for LTObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(LT => Expr, LT => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(LT => Expr, LT => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -1650,13 +1517,6 @@ pub struct LE {
     base: ObjectArc<LEObj>,
 }
 
-impl Deref for LE {
-    type Target = LEObj;
-    fn deref(&self) -> &LEObj {
-        &self.base
-    }
-}
-
 impl Deref for LEObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1686,7 +1546,7 @@ impl LE {
 
 unsafe impl tvm_ffi::object::ImmutableObject for LEObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(LE => Expr, LE => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(LE => Expr, LE => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -1718,13 +1578,6 @@ pub struct GT {
     base: ObjectArc<GTObj>,
 }
 
-impl Deref for GT {
-    type Target = GTObj;
-    fn deref(&self) -> &GTObj {
-        &self.base
-    }
-}
-
 impl Deref for GTObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1754,7 +1607,7 @@ impl GT {
 
 unsafe impl tvm_ffi::object::ImmutableObject for GTObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(GT => Expr, GT => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(GT => Expr, GT => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -1786,13 +1639,6 @@ pub struct GE {
     base: ObjectArc<GEObj>,
 }
 
-impl Deref for GE {
-    type Target = GEObj;
-    fn deref(&self) -> &GEObj {
-        &self.base
-    }
-}
-
 impl Deref for GEObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1822,7 +1668,7 @@ impl GE {
 
 unsafe impl tvm_ffi::object::ImmutableObject for GEObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(GE => Expr, GE => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(GE => Expr, GE => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 binary_new! {
@@ -1857,13 +1703,6 @@ pub struct And {
     base: ObjectArc<AndObj>,
 }
 
-impl Deref for And {
-    type Target = AndObj;
-    fn deref(&self) -> &AndObj {
-        &self.base
-    }
-}
-
 impl Deref for AndObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1893,7 +1732,7 @@ impl And {
 
 unsafe impl tvm_ffi::object::ImmutableObject for AndObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(And => Expr, And => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(And => Expr, And => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 impl And {
@@ -1937,13 +1776,6 @@ pub struct Or {
     base: ObjectArc<OrObj>,
 }
 
-impl Deref for Or {
-    type Target = OrObj;
-    fn deref(&self) -> &OrObj {
-        &self.base
-    }
-}
-
 impl Deref for OrObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -1973,7 +1805,7 @@ impl Or {
 
 unsafe impl tvm_ffi::object::ImmutableObject for OrObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Or => Expr, Or => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Or => Expr, Or => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 impl Or {
@@ -2016,13 +1848,6 @@ pub struct Not {
     base: ObjectArc<NotObj>,
 }
 
-impl Deref for Not {
-    type Target = NotObj;
-    fn deref(&self) -> &NotObj {
-        &self.base
-    }
-}
-
 impl Deref for NotObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -2051,7 +1876,7 @@ impl Not {
 
 unsafe impl tvm_ffi::object::ImmutableObject for NotObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Not => Expr, Not => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Not => Expr, Not => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 impl Not {
@@ -2098,13 +1923,6 @@ pub struct Select {
     base: ObjectArc<SelectObj>,
 }
 
-impl Deref for Select {
-    type Target = SelectObj;
-    fn deref(&self) -> &SelectObj {
-        &self.base
-    }
-}
-
 impl Deref for SelectObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -2147,7 +1965,7 @@ impl Select {
 
 unsafe impl tvm_ffi::object::ImmutableObject for SelectObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Select => Expr, Select => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Select => Expr, Select => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 impl Select {
@@ -2231,13 +2049,6 @@ pub struct Let {
     base: ObjectArc<LetObj>,
 }
 
-impl Deref for Let {
-    type Target = LetObj;
-    fn deref(&self) -> &LetObj {
-        &self.base
-    }
-}
-
 impl Deref for LetObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -2274,7 +2085,7 @@ impl Let {
 
 unsafe impl tvm_ffi::object::ImmutableObject for LetObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Let => Expr, Let => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Let => Expr, Let => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 impl Let {
diff --git a/rust/src/ir/prim/vector_expr.rs b/rust/src/ir/prim/vector_expr.rs
index 8d3e5dd96..de27e17e7 100644
--- a/rust/src/ir/prim/vector_expr.rs
+++ b/rust/src/ir/prim/vector_expr.rs
@@ -134,13 +134,6 @@ pub struct Ramp {
     base: ObjectArc<RampObj>,
 }
 
-impl Deref for Ramp {
-    type Target = RampObj;
-    fn deref(&self) -> &RampObj {
-        &self.base
-    }
-}
-
 impl Deref for RampObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -177,7 +170,7 @@ impl Ramp {
 
 unsafe impl tvm_ffi::object::ImmutableObject for RampObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Ramp => Expr, Ramp => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Ramp => Expr, Ramp => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 impl Ramp {
@@ -253,13 +246,6 @@ pub struct Broadcast {
     base: ObjectArc<BroadcastObj>,
 }
 
-impl Deref for Broadcast {
-    type Target = BroadcastObj;
-    fn deref(&self) -> &BroadcastObj {
-        &self.base
-    }
-}
-
 impl Deref for BroadcastObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -289,7 +275,7 @@ impl Broadcast {
 
 unsafe impl tvm_ffi::object::ImmutableObject for BroadcastObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Broadcast => Expr, Broadcast => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Broadcast => Expr, Broadcast => 
PrimExpr);
 // tvm-ffi-stubgen(end)
 
 impl Broadcast {
@@ -338,13 +324,6 @@ pub struct Shuffle {
     base: ObjectArc<ShuffleObj>,
 }
 
-impl Deref for Shuffle {
-    type Target = ShuffleObj;
-    fn deref(&self) -> &ShuffleObj {
-        &self.base
-    }
-}
-
 impl Deref for ShuffleObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -379,7 +358,7 @@ impl Shuffle {
 
 unsafe impl tvm_ffi::object::ImmutableObject for ShuffleObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Shuffle => Expr, Shuffle => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Shuffle => Expr, Shuffle => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 impl Shuffle {
diff --git a/rust/src/ir/stmt.rs b/rust/src/ir/stmt.rs
index 60ab7149e..d2cc580b1 100644
--- a/rust/src/ir/stmt.rs
+++ b/rust/src/ir/stmt.rs
@@ -159,13 +159,6 @@ pub struct Stmt {
     base: ObjectArc<StmtObj>,
 }
 
-impl Deref for Stmt {
-    type Target = StmtObj;
-    fn deref(&self) -> &StmtObj {
-        &self.base
-    }
-}
-
 impl StmtObj {
     pub fn new(loc: Location) -> Self {
         let base = Object::new();
@@ -222,13 +215,6 @@ pub struct Bind {
     base: ObjectArc<BindObj>,
 }
 
-impl Deref for Bind {
-    type Target = BindObj;
-    fn deref(&self) -> &BindObj {
-        &self.base
-    }
-}
-
 impl Deref for BindObj {
     type Target = StmtObj;
     fn deref(&self) -> &StmtObj {
@@ -257,7 +243,7 @@ impl Bind {
 
 unsafe impl tvm_ffi::object::ImmutableObject for BindObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Bind => Stmt);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Bind => Stmt);
 // tvm-ffi-stubgen(end)
 
 impl Bind {
@@ -306,13 +292,6 @@ pub struct AssertStmt {
     base: ObjectArc<AssertStmtObj>,
 }
 
-impl Deref for AssertStmt {
-    type Target = AssertStmtObj;
-    fn deref(&self) -> &AssertStmtObj {
-        &self.base
-    }
-}
-
 impl Deref for AssertStmtObj {
     type Target = StmtObj;
     fn deref(&self) -> &StmtObj {
@@ -352,7 +331,7 @@ impl AssertStmt {
 
 unsafe impl tvm_ffi::object::ImmutableObject for AssertStmtObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(AssertStmt => Stmt);
+tvm_ffi::unsafe_impl_object_ref_upcast!(AssertStmt => Stmt);
 // tvm-ffi-stubgen(end)
 
 impl AssertStmt {
@@ -439,13 +418,6 @@ pub struct For {
     base: ObjectArc<ForObj>,
 }
 
-impl Deref for For {
-    type Target = ForObj;
-    fn deref(&self) -> &ForObj {
-        &self.base
-    }
-}
-
 impl Deref for ForObj {
     type Target = StmtObj;
     fn deref(&self) -> &StmtObj {
@@ -497,7 +469,7 @@ impl For {
 
 unsafe impl tvm_ffi::object::ImmutableObject for ForObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(For => Stmt);
+tvm_ffi::unsafe_impl_object_ref_upcast!(For => Stmt);
 // tvm-ffi-stubgen(end)
 
 impl Default for ForKind {
@@ -634,13 +606,6 @@ pub struct While {
     base: ObjectArc<WhileObj>,
 }
 
-impl Deref for While {
-    type Target = WhileObj;
-    fn deref(&self) -> &WhileObj {
-        &self.base
-    }
-}
-
 impl Deref for WhileObj {
     type Target = StmtObj;
     fn deref(&self) -> &StmtObj {
@@ -669,7 +634,7 @@ impl While {
 
 unsafe impl tvm_ffi::object::ImmutableObject for WhileObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(While => Stmt);
+tvm_ffi::unsafe_impl_object_ref_upcast!(While => Stmt);
 // tvm-ffi-stubgen(end)
 
 impl While {
@@ -719,13 +684,6 @@ pub struct TensorStore {
     base: ObjectArc<TensorStoreObj>,
 }
 
-impl Deref for TensorStore {
-    type Target = TensorStoreObj;
-    fn deref(&self) -> &TensorStoreObj {
-        &self.base
-    }
-}
-
 impl Deref for TensorStoreObj {
     type Target = StmtObj;
     fn deref(&self) -> &StmtObj {
@@ -760,7 +718,7 @@ impl TensorStore {
 
 unsafe impl tvm_ffi::object::ImmutableObject for TensorStoreObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(TensorStore => Stmt);
+tvm_ffi::unsafe_impl_object_ref_upcast!(TensorStore => Stmt);
 // tvm-ffi-stubgen(end)
 
 impl TensorStore {
@@ -830,13 +788,6 @@ pub struct RegionStmt {
     base: ObjectArc<RegionStmtObj>,
 }
 
-impl Deref for RegionStmt {
-    type Target = RegionStmtObj;
-    fn deref(&self) -> &RegionStmtObj {
-        &self.base
-    }
-}
-
 impl Deref for RegionStmtObj {
     type Target = StmtObj;
     fn deref(&self) -> &StmtObj {
@@ -885,7 +836,7 @@ impl RegionStmt {
 
 unsafe impl tvm_ffi::object::ImmutableObject for RegionStmtObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(RegionStmt => Stmt);
+tvm_ffi::unsafe_impl_object_ref_upcast!(RegionStmt => Stmt);
 // tvm-ffi-stubgen(end)
 
 impl RegionStmt {
@@ -1015,13 +966,6 @@ pub struct SeqStmt {
     base: ObjectArc<SeqStmtObj>,
 }
 
-impl Deref for SeqStmt {
-    type Target = SeqStmtObj;
-    fn deref(&self) -> &SeqStmtObj {
-        &self.base
-    }
-}
-
 impl Deref for SeqStmtObj {
     type Target = StmtObj;
     fn deref(&self) -> &StmtObj {
@@ -1046,7 +990,7 @@ impl SeqStmt {
 
 unsafe impl tvm_ffi::object::ImmutableObject for SeqStmtObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(SeqStmt => Stmt);
+tvm_ffi::unsafe_impl_object_ref_upcast!(SeqStmt => Stmt);
 // tvm-ffi-stubgen(end)
 
 impl SeqStmt {
@@ -1118,13 +1062,6 @@ pub struct If {
     base: ObjectArc<IfObj>,
 }
 
-impl Deref for If {
-    type Target = IfObj;
-    fn deref(&self) -> &IfObj {
-        &self.base
-    }
-}
-
 impl Deref for IfObj {
     type Target = StmtObj;
     fn deref(&self) -> &StmtObj {
@@ -1159,7 +1096,7 @@ impl If {
 
 unsafe impl tvm_ffi::object::ImmutableObject for IfObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(If => Stmt);
+tvm_ffi::unsafe_impl_object_ref_upcast!(If => Stmt);
 // tvm-ffi-stubgen(end)
 
 impl If {
@@ -1200,13 +1137,6 @@ pub struct Evaluate {
     base: ObjectArc<EvaluateObj>,
 }
 
-impl Deref for Evaluate {
-    type Target = EvaluateObj;
-    fn deref(&self) -> &EvaluateObj {
-        &self.base
-    }
-}
-
 impl Deref for EvaluateObj {
     type Target = StmtObj;
     fn deref(&self) -> &StmtObj {
@@ -1231,7 +1161,7 @@ impl Evaluate {
 
 unsafe impl tvm_ffi::object::ImmutableObject for EvaluateObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Evaluate => Stmt);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Evaluate => Stmt);
 // tvm-ffi-stubgen(end)
 
 impl Evaluate {
@@ -1262,13 +1192,6 @@ pub struct Break {
     base: ObjectArc<BreakObj>,
 }
 
-impl Deref for Break {
-    type Target = BreakObj;
-    fn deref(&self) -> &BreakObj {
-        &self.base
-    }
-}
-
 impl Deref for BreakObj {
     type Target = StmtObj;
     fn deref(&self) -> &StmtObj {
@@ -1293,7 +1216,7 @@ impl Break {
 
 unsafe impl tvm_ffi::object::ImmutableObject for BreakObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Break => Stmt);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Break => Stmt);
 // tvm-ffi-stubgen(end)
 
 // `ir.Break` stores its location as given: the generated `Break::new` is the 
same.
@@ -1320,13 +1243,6 @@ pub struct Return {
     base: ObjectArc<ReturnObj>,
 }
 
-impl Deref for Return {
-    type Target = ReturnObj;
-    fn deref(&self) -> &ReturnObj {
-        &self.base
-    }
-}
-
 impl Deref for ReturnObj {
     type Target = StmtObj;
     fn deref(&self) -> &StmtObj {
@@ -1351,7 +1267,7 @@ impl Return {
 
 unsafe impl tvm_ffi::object::ImmutableObject for ReturnObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Return => Stmt);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Return => Stmt);
 // tvm-ffi-stubgen(end)
 
 impl Return {
@@ -1382,13 +1298,6 @@ pub struct Continue {
     base: ObjectArc<ContinueObj>,
 }
 
-impl Deref for Continue {
-    type Target = ContinueObj;
-    fn deref(&self) -> &ContinueObj {
-        &self.base
-    }
-}
-
 impl Deref for ContinueObj {
     type Target = StmtObj;
     fn deref(&self) -> &StmtObj {
@@ -1413,7 +1322,7 @@ impl Continue {
 
 unsafe impl tvm_ffi::object::ImmutableObject for ContinueObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Continue => Stmt);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Continue => Stmt);
 // tvm-ffi-stubgen(end)
 
 // `ir.Continue` stores its location as given: the generated `Continue::new` 
is the same.
diff --git a/rust/src/ir/transform/core.rs b/rust/src/ir/transform/core.rs
index 62cd4771f..e93ea3bd4 100644
--- a/rust/src/ir/transform/core.rs
+++ b/rust/src/ir/transform/core.rs
@@ -84,13 +84,6 @@ pub struct PassObj {
 pub struct Pass {
     base: ObjectArc<PassObj>,
 }
-
-impl Deref for Pass {
-    type Target = PassObj;
-    fn deref(&self) -> &PassObj {
-        &self.base
-    }
-}
 // tvm-ffi-stubgen(end)
 
 impl Pass {
@@ -134,13 +127,6 @@ pub struct PassInfo {
     base: ObjectArc<PassInfoObj>,
 }
 
-impl Deref for PassInfo {
-    type Target = PassInfoObj;
-    fn deref(&self) -> &PassInfoObj {
-        &self.base
-    }
-}
-
 impl PassInfoObj {
     pub(crate) fn new(opt_level: i32, name: String) -> Self {
         let base = Object::new();
@@ -178,13 +164,6 @@ pub struct ModulePass {
     base: ObjectArc<ModulePassObj>,
 }
 
-impl Deref for ModulePass {
-    type Target = ModulePassObj;
-    fn deref(&self) -> &ModulePassObj {
-        &self.base
-    }
-}
-
 impl Deref for ModulePassObj {
     type Target = PassObj;
     fn deref(&self) -> &PassObj {
@@ -200,7 +179,7 @@ impl ModulePassObj {
 
 unsafe impl tvm_ffi::object::ImmutableObject for ModulePassObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(ModulePass => Pass);
+tvm_ffi::unsafe_impl_object_ref_upcast!(ModulePass => Pass);
 // tvm-ffi-stubgen(end)
 
 impl ModulePass {
@@ -241,13 +220,6 @@ pub struct Sequential {
     base: ObjectArc<SequentialObj>,
 }
 
-impl Deref for Sequential {
-    type Target = SequentialObj;
-    fn deref(&self) -> &SequentialObj {
-        &self.base
-    }
-}
-
 impl Deref for SequentialObj {
     type Target = PassObj;
     fn deref(&self) -> &PassObj {
@@ -267,7 +239,7 @@ impl SequentialObj {
 
 unsafe impl tvm_ffi::object::ImmutableObject for SequentialObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Sequential => Pass);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Sequential => Pass);
 // tvm-ffi-stubgen(end)
 
 impl Sequential {
@@ -317,13 +289,6 @@ pub struct PassContext {
     base: ObjectArc<PassContextObj>,
 }
 
-impl Deref for PassContext {
-    type Target = PassContextObj;
-    fn deref(&self) -> &PassContextObj {
-        &self.base
-    }
-}
-
 impl PassContextObj {
     pub(crate) fn new(
         opt_level: i32,
@@ -482,13 +447,6 @@ pub struct PassInstrument {
     base: ObjectArc<PassInstrumentObj>,
 }
 
-impl Deref for PassInstrument {
-    type Target = PassInstrumentObj;
-    fn deref(&self) -> &PassInstrumentObj {
-        &self.base
-    }
-}
-
 impl PassInstrumentObj {
     pub fn name(&self) -> Result<String> {
         FieldGetter::new(Self::type_index(), "name")?.get(self)
diff --git a/rust/src/ir/transform/instrument.rs 
b/rust/src/ir/transform/instrument.rs
index fd8852902..13012de06 100644
--- a/rust/src/ir/transform/instrument.rs
+++ b/rust/src/ir/transform/instrument.rs
@@ -88,13 +88,6 @@ pub struct BasePassInstrument {
     base: ObjectArc<BasePassInstrumentObj>,
 }
 
-impl Deref for BasePassInstrument {
-    type Target = BasePassInstrumentObj;
-    fn deref(&self) -> &BasePassInstrumentObj {
-        &self.base
-    }
-}
-
 impl Deref for BasePassInstrumentObj {
     type Target = PassInstrumentObj;
     fn deref(&self) -> &PassInstrumentObj {
@@ -102,7 +95,7 @@ impl Deref for BasePassInstrumentObj {
     }
 }
 
-tvm_ffi::unsafe_impl_object_upcast!(BasePassInstrument => PassInstrument);
+tvm_ffi::unsafe_impl_object_ref_upcast!(BasePassInstrument => PassInstrument);
 // tvm-ffi-stubgen(end)
 
 /// A hook of a [`BasePassInstrument`], called when a pass context is entered 
or exited.
diff --git a/rust/src/ir/type.rs b/rust/src/ir/type.rs
index 0dee57515..2d12768f4 100644
--- a/rust/src/ir/type.rs
+++ b/rust/src/ir/type.rs
@@ -103,13 +103,6 @@ pub struct Type {
     base: ObjectArc<TypeObj>,
 }
 
-impl Deref for Type {
-    type Target = TypeObj;
-    fn deref(&self) -> &TypeObj {
-        &self.base
-    }
-}
-
 impl TypeObj {
     pub fn new(loc: Location) -> Self {
         let base = Object::new();
@@ -164,13 +157,6 @@ pub struct MissingType {
     base: ObjectArc<MissingTypeObj>,
 }
 
-impl Deref for MissingType {
-    type Target = MissingTypeObj;
-    fn deref(&self) -> &MissingTypeObj {
-        &self.base
-    }
-}
-
 impl Deref for MissingTypeObj {
     type Target = TypeObj;
     fn deref(&self) -> &TypeObj {
@@ -195,7 +181,7 @@ impl MissingType {
 
 unsafe impl tvm_ffi::object::ImmutableObject for MissingTypeObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(MissingType => Type);
+tvm_ffi::unsafe_impl_object_ref_upcast!(MissingType => Type);
 // tvm-ffi-stubgen(end)
 
 impl MissingType {
@@ -234,13 +220,6 @@ pub struct NoneType {
     base: ObjectArc<NoneTypeObj>,
 }
 
-impl Deref for NoneType {
-    type Target = NoneTypeObj;
-    fn deref(&self) -> &NoneTypeObj {
-        &self.base
-    }
-}
-
 impl Deref for NoneTypeObj {
     type Target = TypeObj;
     fn deref(&self) -> &TypeObj {
@@ -265,7 +244,7 @@ impl NoneType {
 
 unsafe impl tvm_ffi::object::ImmutableObject for NoneTypeObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(NoneType => Type);
+tvm_ffi::unsafe_impl_object_ref_upcast!(NoneType => Type);
 // tvm-ffi-stubgen(end)
 
 impl NoneType {
@@ -303,13 +282,6 @@ pub struct AnyType {
     base: ObjectArc<AnyTypeObj>,
 }
 
-impl Deref for AnyType {
-    type Target = AnyTypeObj;
-    fn deref(&self) -> &AnyTypeObj {
-        &self.base
-    }
-}
-
 impl Deref for AnyTypeObj {
     type Target = TypeObj;
     fn deref(&self) -> &TypeObj {
@@ -334,7 +306,7 @@ impl AnyType {
 
 unsafe impl tvm_ffi::object::ImmutableObject for AnyTypeObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(AnyType => Type);
+tvm_ffi::unsafe_impl_object_ref_upcast!(AnyType => Type);
 // tvm-ffi-stubgen(end)
 
 // `ir.AnyType` stores its location as given: the generated `AnyType::new` is 
the same.
@@ -360,13 +332,6 @@ pub struct TensorRegionType {
     base: ObjectArc<TensorRegionTypeObj>,
 }
 
-impl Deref for TensorRegionType {
-    type Target = TensorRegionTypeObj;
-    fn deref(&self) -> &TensorRegionTypeObj {
-        &self.base
-    }
-}
-
 impl Deref for TensorRegionTypeObj {
     type Target = TypeObj;
     fn deref(&self) -> &TypeObj {
@@ -391,7 +356,7 @@ impl TensorRegionType {
 
 unsafe impl tvm_ffi::object::ImmutableObject for TensorRegionTypeObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(TensorRegionType => Type);
+tvm_ffi::unsafe_impl_object_ref_upcast!(TensorRegionType => Type);
 // tvm-ffi-stubgen(end)
 
 impl TensorRegionType {
@@ -430,13 +395,6 @@ pub struct OpaqueType {
     base: ObjectArc<OpaqueTypeObj>,
 }
 
-impl Deref for OpaqueType {
-    type Target = OpaqueTypeObj;
-    fn deref(&self) -> &OpaqueTypeObj {
-        &self.base
-    }
-}
-
 impl Deref for OpaqueTypeObj {
     type Target = TypeObj;
     fn deref(&self) -> &TypeObj {
@@ -461,11 +419,13 @@ impl OpaqueType {
 
 unsafe impl tvm_ffi::object::ImmutableObject for OpaqueTypeObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(OpaqueType => Type);
+tvm_ffi::unsafe_impl_object_ref_upcast!(OpaqueType => Type);
 // tvm-ffi-stubgen(end)
 
 impl OpaqueType {
     /// Create an opaque type at the unknown location (C++ `OpaqueType()`).
+    // Not `Default`, as no IR node is: the C++ constructor builds it.
+    #[allow(clippy::new_without_default)]
     pub fn new() -> Self {
         Self::from_fields(UNKNOWN_LOC)
     }
@@ -493,13 +453,6 @@ pub struct PrimType {
     base: ObjectArc<PrimTypeObj>,
 }
 
-impl Deref for PrimType {
-    type Target = PrimTypeObj;
-    fn deref(&self) -> &PrimTypeObj {
-        &self.base
-    }
-}
-
 impl Deref for PrimTypeObj {
     type Target = TypeObj;
     fn deref(&self) -> &TypeObj {
@@ -524,7 +477,7 @@ impl PrimType {
 
 unsafe impl tvm_ffi::object::ImmutableObject for PrimTypeObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(PrimType => Type);
+tvm_ffi::unsafe_impl_object_ref_upcast!(PrimType => Type);
 // tvm-ffi-stubgen(end)
 
 impl PrimType {
@@ -635,13 +588,6 @@ pub struct StringType {
     base: ObjectArc<StringTypeObj>,
 }
 
-impl Deref for StringType {
-    type Target = StringTypeObj;
-    fn deref(&self) -> &StringTypeObj {
-        &self.base
-    }
-}
-
 impl Deref for StringTypeObj {
     type Target = TypeObj;
     fn deref(&self) -> &TypeObj {
@@ -666,11 +612,13 @@ impl StringType {
 
 unsafe impl tvm_ffi::object::ImmutableObject for StringTypeObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(StringType => Type);
+tvm_ffi::unsafe_impl_object_ref_upcast!(StringType => Type);
 // tvm-ffi-stubgen(end)
 
 impl StringType {
     /// Create the string type at the unknown location (C++ `StringType()`).
+    // Not `Default`, as no IR node is: the C++ constructor builds it.
+    #[allow(clippy::new_without_default)]
     pub fn new() -> Self {
         Self::from_fields(UNKNOWN_LOC)
     }
@@ -699,13 +647,6 @@ pub struct PtrType {
     base: ObjectArc<PtrTypeObj>,
 }
 
-impl Deref for PtrType {
-    type Target = PtrTypeObj;
-    fn deref(&self) -> &PtrTypeObj {
-        &self.base
-    }
-}
-
 impl Deref for PtrTypeObj {
     type Target = TypeObj;
     fn deref(&self) -> &TypeObj {
@@ -734,7 +675,7 @@ impl PtrType {
 
 unsafe impl tvm_ffi::object::ImmutableObject for PtrTypeObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(PtrType => Type);
+tvm_ffi::unsafe_impl_object_ref_upcast!(PtrType => Type);
 // tvm-ffi-stubgen(end)
 
 impl PtrType {
@@ -777,13 +718,6 @@ pub struct TupleType {
     base: ObjectArc<TupleTypeObj>,
 }
 
-impl Deref for TupleType {
-    type Target = TupleTypeObj;
-    fn deref(&self) -> &TupleTypeObj {
-        &self.base
-    }
-}
-
 impl Deref for TupleTypeObj {
     type Target = TypeObj;
     fn deref(&self) -> &TypeObj {
@@ -808,7 +742,7 @@ impl TupleType {
 
 unsafe impl tvm_ffi::object::ImmutableObject for TupleTypeObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(TupleType => Type);
+tvm_ffi::unsafe_impl_object_ref_upcast!(TupleType => Type);
 // tvm-ffi-stubgen(end)
 
 impl TupleType {
@@ -846,13 +780,6 @@ pub struct FuncType {
     base: ObjectArc<FuncTypeObj>,
 }
 
-impl Deref for FuncType {
-    type Target = FuncTypeObj;
-    fn deref(&self) -> &FuncTypeObj {
-        &self.base
-    }
-}
-
 impl Deref for FuncTypeObj {
     type Target = TypeObj;
     fn deref(&self) -> &TypeObj {
@@ -881,7 +808,7 @@ impl FuncType {
 
 unsafe impl tvm_ffi::object::ImmutableObject for FuncTypeObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(FuncType => Type);
+tvm_ffi::unsafe_impl_object_ref_upcast!(FuncType => Type);
 // tvm-ffi-stubgen(end)
 
 impl FuncType {
diff --git a/rust/src/ir/type_def.rs b/rust/src/ir/type_def.rs
index 2266c7274..609b91c7c 100644
--- a/rust/src/ir/type_def.rs
+++ b/rust/src/ir/type_def.rs
@@ -40,7 +40,7 @@ use super::support;
 /// ```
 /// use tvm_tirx::ir::{register_type, PrimType, Type, TypeObj, Var, 
UNKNOWN_LOC};
 /// use tvm_tirx::script::script;
-/// use tvm_tirx::tvm_ffi::{self, def_object_ref, rs_object};
+/// use tvm_tirx::tvm_ffi::{self, rs_object};
 ///
 /// #[rs_object("my_ext.PairType", final)]
 /// pub struct PairTypeObj {
@@ -49,11 +49,15 @@ use super::support;
 ///     #[reflect(kw_only)]
 ///     pub second: Type,
 /// }
-/// def_object_ref!(pub PairType, Type, PairTypeObj);
+/// #[derive(Clone, tvm_ffi::derive::ObjectRef)]
+/// #[object_ref(parent = Type)]
+/// pub struct PairType {
+///     data: tvm_ffi::ObjectArc<PairTypeObj>,
+/// }
 ///
 /// impl PairType {
 ///     pub fn new(first: impl Into<Type>, second: impl Into<Type>) -> Self {
-///         PairTypeObj::new(TypeObj::new(UNKNOWN_LOC.into()), first, 
second).into()
+///         
Self::from_object(PairTypeObj::new(TypeObj::new(UNKNOWN_LOC.into()), first, 
second))
 ///     }
 /// }
 ///
diff --git a/rust/src/ir/unique_name_supply.rs 
b/rust/src/ir/unique_name_supply.rs
index 64085e297..73a6aba0e 100644
--- a/rust/src/ir/unique_name_supply.rs
+++ b/rust/src/ir/unique_name_supply.rs
@@ -42,7 +42,6 @@
 
 // tvm-ffi-stubgen(begin): import-section
 use crate::ir::support;
-use std::ops::Deref;
 use tvm_ffi::Object;
 use tvm_ffi::ObjectArc;
 use tvm_ffi::Result;
@@ -64,13 +63,6 @@ pub struct UniqueNameSupplyObj {
 pub struct UniqueNameSupply {
     base: ObjectArc<UniqueNameSupplyObj>,
 }
-
-impl Deref for UniqueNameSupply {
-    type Target = UniqueNameSupplyObj;
-    fn deref(&self) -> &UniqueNameSupplyObj {
-        &self.base
-    }
-}
 // tvm-ffi-stubgen(end)
 
 impl UniqueNameSupply {
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index f76be4360..356e3ac5e 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -71,10 +71,14 @@
 //! use tvm_tirx::ir::{register_type, CallEffectKind, CallObj, Op, OpDef, 
Type};
 //! use tvm_tirx::tvm_ffi::{self, Result};
 //! # use tvm_tirx::ir::TypeObj;
-//! # use tvm_tirx::tvm_ffi::{def_object_ref, rs_object, ObjectRefCore};
+//! # use tvm_tirx::tvm_ffi::{rs_object, ObjectRefCore};
 //! # #[rs_object("my_ext.PairType", final)]
 //! # pub struct PairTypeObj { base: TypeObj, pub first: Type, pub second: 
Type }
-//! # def_object_ref!(pub PairType, Type, PairTypeObj);
+//! # #[derive(Clone, tvm_ffi::derive::ObjectRef)]
+//! # #[object_ref(parent = Type)]
+//! # pub struct PairType {
+//! #     data: tvm_ffi::ObjectArc<PairTypeObj>,
+//! # }
 //!
 //! fn index_type(call: &CallObj) -> Result<Type> {
 //!     Ok(call.args.get(0)?.ty.clone())
@@ -101,7 +105,7 @@
 //!
 //! ```
 //! use tvm_tirx::ir::{PrimType, Type, TypeObj, UNKNOWN_LOC};
-//! use tvm_tirx::tvm_ffi::{self, def_object_ref, rs_object, ObjectRefCore};
+//! use tvm_tirx::tvm_ffi::{self, rs_object, ObjectRefCore};
 //!
 //! #[rs_object("my_ext.PairType", final)]
 //! pub struct PairTypeObj {
@@ -112,11 +116,15 @@
 //!     pub note: tvm_ffi::String,
 //! }
 //!
-//! def_object_ref!(pub PairType, Type, PairTypeObj);
+//! #[derive(Clone, tvm_ffi::derive::ObjectRef)]
+//! #[object_ref(parent = Type)]
+//! pub struct PairType {
+//!     data: tvm_ffi::ObjectArc<PairTypeObj>,
+//! }
 //!
 //! impl PairType {
 //!     pub fn new(first: impl Into<Type>, second: impl Into<Type>) -> Self {
-//!         PairTypeObj::new(TypeObj::new(UNKNOWN_LOC.into()), first, second, 
"").into()
+//!         
Self::from_object(PairTypeObj::new(TypeObj::new(UNKNOWN_LOC.into()), first, 
second, ""))
 //!     }
 //! }
 //!
diff --git a/rust/src/macro/def_expr_op_overloads.rs 
b/rust/src/macro/def_expr_op_overloads.rs
index 9e9ceb36f..06659231a 100644
--- a/rust/src/macro/def_expr_op_overloads.rs
+++ b/rust/src/macro/def_expr_op_overloads.rs
@@ -32,25 +32,29 @@
 /// ```
 /// use tvm_tirx::ir::{Expr, ExprObj, PrimExpr, PrimType, UNKNOWN_LOC};
 /// use tvm_tirx::sym::Analyzer;
-/// use tvm_tirx::tvm_ffi::{self, def_object_ref, rs_object, ObjectRefCore};
+/// use tvm_tirx::tvm_ffi::{self, rs_object, ObjectRefCore};
 ///
 /// #[rs_object("my_ext.ThreadIndex", final)]
 /// pub struct ThreadIndexObj {
 ///     base: ExprObj,
 ///     pub axis: i64,
 /// }
-/// def_object_ref!(pub ThreadIndex, Expr, ThreadIndexObj);
+/// #[derive(Clone, tvm_ffi::derive::ObjectRef)]
+/// #[object_ref(parent = Expr)]
+/// pub struct ThreadIndex {
+///     data: tvm_ffi::ObjectArc<ThreadIndexObj>,
+/// }
 ///
 /// impl ThreadIndex {
 ///     /// The `int32` index of the thread along `axis`.
 ///     pub fn new(axis: i64) -> Self {
 ///         let base = ExprObj::new(UNKNOWN_LOC.into(), 
PrimType::int(32).into());
-///         Self::from(ThreadIndexObj::new(base, axis))
+///         Self::from_object(ThreadIndexObj::new(base, axis))
 ///     }
 /// }
 ///
 /// // Every thread index is an `int32`, as `new` makes it.
-/// tvm_ffi::unsafe_impl_object_upcast!(ThreadIndex => PrimExpr);
+/// tvm_ffi::unsafe_impl_object_ref_upcast!(ThreadIndex => PrimExpr);
 /// tvm_tirx::def_expr_op_over_loads!(ThreadIndex);
 ///
 /// # fn main() -> tvm_tirx::tvm_ffi::Result<()> {
diff --git a/rust/src/macro/typed_expr_view.rs 
b/rust/src/macro/typed_expr_view.rs
index 8d6bd490a..7112e2759 100644
--- a/rust/src/macro/typed_expr_view.rs
+++ b/rust/src/macro/typed_expr_view.rs
@@ -115,7 +115,7 @@ macro_rules! typed_expr_view {
 
         // SAFETY: the view is `repr(transparent)` over one object pointer, and
         // `check_any_strict` is its type check.
-        tvm_ffi::unsafe_impl_ref_downcast!($name);
+        tvm_ffi::unsafe_impl_object_ref_downcast_ref!($name);
 
         impl AsRef<$name> for $name {
             #[inline(always)]
@@ -144,9 +144,7 @@ macro_rules! typed_expr_view {
             }
         }
 
-        tvm_ffi::impl_try_from_any!($name);
-        tvm_ffi::impl_arg_into_ref!($name);
-        tvm_ffi::impl_into_arg_holder_default!($name);
+        tvm_ffi::impl_any_compatible_conversions!($name);
 
         // The type key and address, as `#[derive(ObjectRef)]` prints a 
reference, so a
         // `downcast` result can be unwrapped.
diff --git a/rust/src/runtime.rs b/rust/src/runtime.rs
index 7c3738636..c755e7ca6 100644
--- a/rust/src/runtime.rs
+++ b/rust/src/runtime.rs
@@ -50,7 +50,6 @@
 // tvm-ffi-stubgen(import-object): tvm_ffi::Tensor
 
 // tvm-ffi-stubgen(begin): import-section
-use std::ops::Deref;
 use tvm_ffi::Any;
 use tvm_ffi::DLDataType;
 use tvm_ffi::DLDevice;
@@ -88,13 +87,6 @@ pub struct MemoryScope {
     base: ObjectArc<MemoryScopeObj>,
 }
 
-impl Deref for MemoryScope {
-    type Target = MemoryScopeObj;
-    fn deref(&self) -> &MemoryScopeObj {
-        &self.base
-    }
-}
-
 unsafe impl tvm_ffi::object::ImmutableObject for MemoryScopeObj {}
 // tvm-ffi-stubgen(end)
 
diff --git a/rust/src/sym/analyzer.rs b/rust/src/sym/analyzer.rs
index 088fd6ebb..c33d8c904 100644
--- a/rust/src/sym/analyzer.rs
+++ b/rust/src/sym/analyzer.rs
@@ -111,13 +111,6 @@ pub struct AnalyzerObj {
 pub struct Analyzer {
     base: ObjectArc<AnalyzerObj>,
 }
-
-impl Deref for Analyzer {
-    type Target = AnalyzerObj;
-    fn deref(&self) -> &AnalyzerObj {
-        &self.base
-    }
-}
 // tvm-ffi-stubgen(end)
 
 impl Analyzer {
@@ -421,13 +414,6 @@ pub struct ConstIntBound {
     base: ObjectArc<ConstIntBoundObj>,
 }
 
-impl Deref for ConstIntBound {
-    type Target = ConstIntBoundObj;
-    fn deref(&self) -> &ConstIntBoundObj {
-        &self.base
-    }
-}
-
 impl ConstIntBoundObj {
     pub(crate) fn new(min_value: i64, max_value: i64) -> Self {
         let base = Object::new();
@@ -469,13 +455,6 @@ pub struct ModularSet {
     base: ObjectArc<ModularSetObj>,
 }
 
-impl Deref for ModularSet {
-    type Target = ModularSetObj;
-    fn deref(&self) -> &ModularSetObj {
-        &self.base
-    }
-}
-
 impl ModularSetObj {
     pub(crate) fn new(coeff: i64, base_: i64) -> Self {
         let base = Object::new();
@@ -521,13 +500,6 @@ pub struct RewriteSimplifierStats {
     base: ObjectArc<RewriteSimplifierStatsObj>,
 }
 
-impl Deref for RewriteSimplifierStats {
-    type Target = RewriteSimplifierStatsObj;
-    fn deref(&self) -> &RewriteSimplifierStatsObj {
-        &self.base
-    }
-}
-
 impl RewriteSimplifierStatsObj {
     pub(crate) fn new(
         nodes_visited: i64,
@@ -593,13 +565,6 @@ pub struct CanonicalExpr {
     base: ObjectArc<CanonicalExprObj>,
 }
 
-impl Deref for CanonicalExpr {
-    type Target = CanonicalExprObj;
-    fn deref(&self) -> &CanonicalExprObj {
-        &self.base
-    }
-}
-
 impl Deref for CanonicalExprObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -607,7 +572,7 @@ impl Deref for CanonicalExprObj {
     }
 }
 
-tvm_ffi::unsafe_impl_object_upcast!(CanonicalExpr => Expr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(CanonicalExpr => Expr);
 // tvm-ffi-stubgen(end)
 
 // tvm-ffi-stubgen(begin): object/sym.SplitExpr
@@ -625,13 +590,6 @@ pub struct SplitExpr {
     base: ObjectArc<SplitExprObj>,
 }
 
-impl Deref for SplitExpr {
-    type Target = SplitExprObj;
-    fn deref(&self) -> &SplitExprObj {
-        &self.base
-    }
-}
-
 impl Deref for SplitExprObj {
     type Target = CanonicalExprObj;
     fn deref(&self) -> &CanonicalExprObj {
@@ -639,7 +597,7 @@ impl Deref for SplitExprObj {
     }
 }
 
-tvm_ffi::unsafe_impl_object_upcast!(SplitExpr => Expr, SplitExpr => 
CanonicalExpr, SplitExpr => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(SplitExpr => Expr, SplitExpr => 
CanonicalExpr, SplitExpr => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 // tvm-ffi-stubgen(begin): object/sym.SumExpr
@@ -657,13 +615,6 @@ pub struct SumExpr {
     base: ObjectArc<SumExprObj>,
 }
 
-impl Deref for SumExpr {
-    type Target = SumExprObj;
-    fn deref(&self) -> &SumExprObj {
-        &self.base
-    }
-}
-
 impl Deref for SumExprObj {
     type Target = CanonicalExprObj;
     fn deref(&self) -> &CanonicalExprObj {
@@ -671,5 +622,5 @@ impl Deref for SumExprObj {
     }
 }
 
-tvm_ffi::unsafe_impl_object_upcast!(SumExpr => Expr, SumExpr => CanonicalExpr, 
SumExpr => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(SumExpr => Expr, SumExpr => 
CanonicalExpr, SumExpr => PrimExpr);
 // tvm-ffi-stubgen(end)
diff --git a/rust/src/sym/constraint.rs b/rust/src/sym/constraint.rs
index 02baba18a..687c55121 100644
--- a/rust/src/sym/constraint.rs
+++ b/rust/src/sym/constraint.rs
@@ -88,13 +88,6 @@ pub struct Constraint {
     base: ObjectArc<ConstraintObj>,
 }
 
-impl Deref for Constraint {
-    type Target = ConstraintObj;
-    fn deref(&self) -> &ConstraintObj {
-        &self.base
-    }
-}
-
 impl ConstraintObj {
     pub fn new() -> Self {
         let base = Object::new();
@@ -150,13 +143,6 @@ pub struct BindingConstraint {
     base: ObjectArc<BindingConstraintObj>,
 }
 
-impl Deref for BindingConstraint {
-    type Target = BindingConstraintObj;
-    fn deref(&self) -> &BindingConstraintObj {
-        &self.base
-    }
-}
-
 impl Deref for BindingConstraintObj {
     type Target = ConstraintObj;
     fn deref(&self) -> &ConstraintObj {
@@ -181,7 +167,7 @@ impl BindingConstraint {
 
 unsafe impl tvm_ffi::object::ImmutableObject for BindingConstraintObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(BindingConstraint => Constraint);
+tvm_ffi::unsafe_impl_object_ref_upcast!(BindingConstraint => Constraint);
 // tvm-ffi-stubgen(end)
 
 // tvm-ffi-stubgen(begin): object/sym.PredicateConstraint
@@ -207,13 +193,6 @@ pub struct PredicateConstraint {
     base: ObjectArc<PredicateConstraintObj>,
 }
 
-impl Deref for PredicateConstraint {
-    type Target = PredicateConstraintObj;
-    fn deref(&self) -> &PredicateConstraintObj {
-        &self.base
-    }
-}
-
 impl Deref for PredicateConstraintObj {
     type Target = ConstraintObj;
     fn deref(&self) -> &ConstraintObj {
@@ -238,7 +217,7 @@ impl PredicateConstraint {
 
 unsafe impl tvm_ffi::object::ImmutableObject for PredicateConstraintObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(PredicateConstraint => Constraint);
+tvm_ffi::unsafe_impl_object_ref_upcast!(PredicateConstraint => Constraint);
 // tvm-ffi-stubgen(end)
 
 // tvm-ffi-stubgen(begin): object/sym.RangeConstraint
@@ -264,13 +243,6 @@ pub struct RangeConstraint {
     base: ObjectArc<RangeConstraintObj>,
 }
 
-impl Deref for RangeConstraint {
-    type Target = RangeConstraintObj;
-    fn deref(&self) -> &RangeConstraintObj {
-        &self.base
-    }
-}
-
 impl Deref for RangeConstraintObj {
     type Target = ConstraintObj;
     fn deref(&self) -> &ConstraintObj {
@@ -295,7 +267,7 @@ impl RangeConstraint {
 
 unsafe impl tvm_ffi::object::ImmutableObject for RangeConstraintObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(RangeConstraint => Constraint);
+tvm_ffi::unsafe_impl_object_ref_upcast!(RangeConstraint => Constraint);
 // tvm-ffi-stubgen(end)
 
 /// The object of a [`ConstraintContext`], with the layout of the native one 
and a stable identity.
@@ -324,13 +296,6 @@ pub struct ConstraintContext {
     base: ObjectArc<ConstraintContextObj>,
 }
 
-impl Deref for ConstraintContext {
-    type Target = ConstraintContextObj;
-    fn deref(&self) -> &Self::Target {
-        &self.base
-    }
-}
-
 impl ConstraintContext {
     /// Create an empty root context, with the complete native-compatible 
layout (C++
     /// `ConstraintContext()`).
diff --git a/rust/src/sym/int_set.rs b/rust/src/sym/int_set.rs
index 37de5508d..122fb550f 100644
--- a/rust/src/sym/int_set.rs
+++ b/rust/src/sym/int_set.rs
@@ -87,13 +87,6 @@ pub struct IntSetObj {
 pub struct IntSet {
     base: ObjectArc<IntSetObj>,
 }
-
-impl Deref for IntSet {
-    type Target = IntSetObj;
-    fn deref(&self) -> &IntSetObj {
-        &self.base
-    }
-}
 // tvm-ffi-stubgen(end)
 
 impl IntSet {
@@ -139,13 +132,6 @@ pub struct IntervalSet {
     base: ObjectArc<IntervalSetObj>,
 }
 
-impl Deref for IntervalSet {
-    type Target = IntervalSetObj;
-    fn deref(&self) -> &IntervalSetObj {
-        &self.base
-    }
-}
-
 impl Deref for IntervalSetObj {
     type Target = IntSetObj;
     fn deref(&self) -> &IntSetObj {
@@ -165,7 +151,7 @@ impl IntervalSetObj {
 
 unsafe impl tvm_ffi::object::ImmutableObject for IntervalSetObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(IntervalSet => IntSet);
+tvm_ffi::unsafe_impl_object_ref_upcast!(IntervalSet => IntSet);
 // tvm-ffi-stubgen(end)
 
 impl IntervalSet {
diff --git a/rust/src/sym/iter_affine_map.rs b/rust/src/sym/iter_affine_map.rs
index ee7a32391..ca70a2ae1 100644
--- a/rust/src/sym/iter_affine_map.rs
+++ b/rust/src/sym/iter_affine_map.rs
@@ -110,13 +110,6 @@ pub struct IterMapExpr {
     base: ObjectArc<IterMapExprObj>,
 }
 
-impl Deref for IterMapExpr {
-    type Target = IterMapExprObj;
-    fn deref(&self) -> &IterMapExprObj {
-        &self.base
-    }
-}
-
 impl Deref for IterMapExprObj {
     type Target = ExprObj;
     fn deref(&self) -> &ExprObj {
@@ -124,7 +117,7 @@ impl Deref for IterMapExprObj {
     }
 }
 
-tvm_ffi::unsafe_impl_object_upcast!(IterMapExpr => Expr, IterMapExpr => 
PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(IterMapExpr => Expr, IterMapExpr => 
PrimExpr);
 // tvm-ffi-stubgen(end)
 
 // tvm-ffi-stubgen(begin): object/sym.IterMapResult
@@ -151,13 +144,6 @@ pub struct IterMapResult {
     base: ObjectArc<IterMapResultObj>,
 }
 
-impl Deref for IterMapResult {
-    type Target = IterMapResultObj;
-    fn deref(&self) -> &IterMapResultObj {
-        &self.base
-    }
-}
-
 impl IterMapResultObj {
     pub(crate) fn new(
         indices: Array<IterSumExpr>,
@@ -205,13 +191,6 @@ pub struct IterMark {
     base: ObjectArc<IterMarkObj>,
 }
 
-impl Deref for IterMark {
-    type Target = IterMarkObj;
-    fn deref(&self) -> &IterMarkObj {
-        &self.base
-    }
-}
-
 impl IterMarkObj {
     pub(crate) fn new(source: PrimExpr, extent: PrimExpr) -> Self {
         let base = Object::new();
@@ -246,13 +225,6 @@ pub struct IterSplitExpr {
     base: ObjectArc<IterSplitExprObj>,
 }
 
-impl Deref for IterSplitExpr {
-    type Target = IterSplitExprObj;
-    fn deref(&self) -> &IterSplitExprObj {
-        &self.base
-    }
-}
-
 impl Deref for IterSplitExprObj {
     type Target = IterMapExprObj;
     fn deref(&self) -> &IterMapExprObj {
@@ -280,7 +252,7 @@ impl IterSplitExprObj {
 
 unsafe impl tvm_ffi::object::ImmutableObject for IterSplitExprObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(IterSplitExpr => Expr, IterSplitExpr => 
IterMapExpr, IterSplitExpr => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(IterSplitExpr => Expr, IterSplitExpr 
=> IterMapExpr, IterSplitExpr => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 // tvm-ffi-stubgen(begin): object/sym.IterSumExpr
@@ -299,13 +271,6 @@ pub struct IterSumExpr {
     base: ObjectArc<IterSumExprObj>,
 }
 
-impl Deref for IterSumExpr {
-    type Target = IterSumExprObj;
-    fn deref(&self) -> &IterSumExprObj {
-        &self.base
-    }
-}
-
 impl Deref for IterSumExprObj {
     type Target = IterMapExprObj;
     fn deref(&self) -> &IterMapExprObj {
@@ -325,7 +290,7 @@ impl IterSumExprObj {
 
 unsafe impl tvm_ffi::object::ImmutableObject for IterSumExprObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(IterSumExpr => Expr, IterSumExpr => 
IterMapExpr, IterSumExpr => PrimExpr);
+tvm_ffi::unsafe_impl_object_ref_upcast!(IterSumExpr => Expr, IterSumExpr => 
IterMapExpr, IterSumExpr => PrimExpr);
 // tvm-ffi-stubgen(end)
 
 // `IterMark::new` is generated: the native `sym.IterMark` constructor stores 
the fields as given.
diff --git a/rust/src/target.rs b/rust/src/target.rs
index b47ffc0bb..18748266b 100644
--- a/rust/src/target.rs
+++ b/rust/src/target.rs
@@ -48,7 +48,6 @@
 
 // tvm-ffi-stubgen(begin): import-section
 use crate::ir::module::IRModule;
-use std::ops::Deref;
 use tvm_ffi::Any;
 use tvm_ffi::Array;
 use tvm_ffi::FieldGetter;
@@ -78,13 +77,6 @@ pub struct Target {
     base: ObjectArc<TargetObj>,
 }
 
-impl Deref for Target {
-    type Target = TargetObj;
-    fn deref(&self) -> &TargetObj {
-        &self.base
-    }
-}
-
 impl TargetObj {
     pub fn kind(&self) -> Result<TargetKind> {
         FieldGetter::new(Self::type_index(), "kind")?.get(self)
@@ -220,13 +212,6 @@ pub struct TargetKind {
     base: ObjectArc<TargetKindObj>,
 }
 
-impl Deref for TargetKind {
-    type Target = TargetKindObj;
-    fn deref(&self) -> &TargetKindObj {
-        &self.base
-    }
-}
-
 impl TargetKindObj {
     pub fn name(&self) -> Result<String> {
         FieldGetter::new(Self::type_index(), "name")?.get(self)
diff --git a/rust/src/tirx/function.rs b/rust/src/tirx/function.rs
index 0d7c8948c..a55127e6a 100644
--- a/rust/src/tirx/function.rs
+++ b/rust/src/tirx/function.rs
@@ -98,13 +98,6 @@ pub struct Function {
     base: ObjectArc<FunctionObj>,
 }
 
-impl Deref for Function {
-    type Target = FunctionObj;
-    fn deref(&self) -> &FunctionObj {
-        &self.base
-    }
-}
-
 impl Deref for FunctionObj {
     type Target = BaseFuncObj;
     fn deref(&self) -> &BaseFuncObj {
@@ -150,7 +143,7 @@ impl Function {
 
 unsafe impl tvm_ffi::object::ImmutableObject for FunctionObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(Function => Expr, Function => BaseFunc);
+tvm_ffi::unsafe_impl_object_ref_upcast!(Function => Expr, Function => 
BaseFunc);
 // tvm-ffi-stubgen(end)
 
 impl Function {
diff --git a/rust/src/tirx/index_map.rs b/rust/src/tirx/index_map.rs
index 6dc704434..6442dd7fb 100644
--- a/rust/src/tirx/index_map.rs
+++ b/rust/src/tirx/index_map.rs
@@ -66,7 +66,6 @@ use crate::ir::expr::PrimExpr;
 use crate::ir::expr::PrimVar;
 use crate::ir::expr::Range;
 use crate::sym::analyzer::Analyzer;
-use std::ops::Deref;
 use tvm_ffi::Any;
 use tvm_ffi::Array;
 use tvm_ffi::Object;
@@ -100,13 +99,6 @@ pub struct IndexMap {
     base: ObjectArc<IndexMapObj>,
 }
 
-impl Deref for IndexMap {
-    type Target = IndexMapObj;
-    fn deref(&self) -> &IndexMapObj {
-        &self.base
-    }
-}
-
 impl IndexMapObj {
     pub(crate) fn new(
         initial_indices: Array<PrimVar>,
diff --git a/rust/src/tirx/layout.rs b/rust/src/tirx/layout.rs
index 06fb1b23a..84de6b747 100644
--- a/rust/src/tirx/layout.rs
+++ b/rust/src/tirx/layout.rs
@@ -103,13 +103,6 @@ pub struct LayoutObj {
 pub struct Layout {
     base: ObjectArc<LayoutObj>,
 }
-
-impl Deref for Layout {
-    type Target = LayoutObj;
-    fn deref(&self) -> &LayoutObj {
-        &self.base
-    }
-}
 // tvm-ffi-stubgen(end)
 
 impl Layout {
@@ -241,13 +234,6 @@ pub struct TileLayout {
     base: ObjectArc<TileLayoutObj>,
 }
 
-impl Deref for TileLayout {
-    type Target = TileLayoutObj;
-    fn deref(&self) -> &TileLayoutObj {
-        &self.base
-    }
-}
-
 impl Deref for TileLayoutObj {
     type Target = LayoutObj;
     fn deref(&self) -> &LayoutObj {
@@ -271,7 +257,7 @@ impl TileLayoutObj {
 
 unsafe impl tvm_ffi::object::ImmutableObject for TileLayoutObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(TileLayout => Layout);
+tvm_ffi::unsafe_impl_object_ref_upcast!(TileLayout => Layout);
 // tvm-ffi-stubgen(end)
 
 impl TileLayout {
@@ -363,13 +349,6 @@ pub struct Iter {
     base: ObjectArc<IterObj>,
 }
 
-impl Deref for Iter {
-    type Target = IterObj;
-    fn deref(&self) -> &IterObj {
-        &self.base
-    }
-}
-
 impl IterObj {
     pub(crate) fn new(extent: PrimExpr, stride: PrimExpr, axis: Axis) -> Self {
         let base = Object::new();
@@ -410,13 +389,6 @@ pub struct Axis {
     base: ObjectArc<AxisObj>,
 }
 
-impl Deref for Axis {
-    type Target = AxisObj;
-    fn deref(&self) -> &AxisObj {
-        &self.base
-    }
-}
-
 unsafe impl tvm_ffi::object::ImmutableObject for AxisObj {}
 // tvm-ffi-stubgen(end)
 
@@ -474,13 +446,6 @@ pub struct ComposeLayout {
     base: ObjectArc<ComposeLayoutObj>,
 }
 
-impl Deref for ComposeLayout {
-    type Target = ComposeLayoutObj;
-    fn deref(&self) -> &ComposeLayoutObj {
-        &self.base
-    }
-}
-
 impl Deref for ComposeLayoutObj {
     type Target = LayoutObj;
     fn deref(&self) -> &LayoutObj {
@@ -520,7 +485,7 @@ impl ComposeLayoutObj {
 
 unsafe impl tvm_ffi::object::ImmutableObject for ComposeLayoutObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(ComposeLayout => Layout);
+tvm_ffi::unsafe_impl_object_ref_upcast!(ComposeLayout => Layout);
 // tvm-ffi-stubgen(end)
 
 impl ComposeLayout {
diff --git a/rust/src/tirx/op.rs b/rust/src/tirx/op.rs
index a59275c7b..24a890618 100644
--- a/rust/src/tirx/op.rs
+++ b/rust/src/tirx/op.rs
@@ -125,13 +125,6 @@ pub struct CallFFIKernelAttr {
     base: ObjectArc<CallFFIKernelAttrObj>,
 }
 
-impl Deref for CallFFIKernelAttr {
-    type Target = CallFFIKernelAttrObj;
-    fn deref(&self) -> &CallFFIKernelAttrObj {
-        &self.base
-    }
-}
-
 impl Deref for CallFFIKernelAttrObj {
     type Target = AttrsObj;
     fn deref(&self) -> &AttrsObj {
@@ -171,7 +164,7 @@ impl CallFFIKernelAttr {
 
 unsafe impl tvm_ffi::object::ImmutableObject for CallFFIKernelAttrObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(CallFFIKernelAttr => Attrs);
+tvm_ffi::unsafe_impl_object_ref_upcast!(CallFFIKernelAttr => Attrs);
 // tvm-ffi-stubgen(end)
 
 // The native `tirx.CallFFIKernelAttr` stores its fields as given, as the 
generated
diff --git a/rust/src/tirx/structural.rs b/rust/src/tirx/structural.rs
index 3918c1b0b..113f761b9 100644
--- a/rust/src/tirx/structural.rs
+++ b/rust/src/tirx/structural.rs
@@ -27,7 +27,6 @@
 
 // tvm-ffi-stubgen(begin): import-section
 use crate::sym::constraint::ConstraintContext;
-use std::ops::Deref;
 use tvm_ffi::FieldGetter;
 use tvm_ffi::Object;
 use tvm_ffi::ObjectArc;
@@ -68,13 +67,6 @@ pub struct StructuralMutatorWithConstraintContext {
     base: ObjectArc<StructuralMutatorWithConstraintContextObj>,
 }
 
-impl Deref for StructuralMutatorWithConstraintContext {
-    type Target = StructuralMutatorWithConstraintContextObj;
-    fn deref(&self) -> &StructuralMutatorWithConstraintContextObj {
-        &self.base
-    }
-}
-
 impl StructuralMutatorWithConstraintContextObj {
     pub fn constraints(&self) -> Result<ConstraintContext> {
         FieldGetter::new(Self::type_index(), "constraints")?.get(self)
@@ -97,13 +89,6 @@ pub struct StructuralVisitorWithConstraintContext {
     base: ObjectArc<StructuralVisitorWithConstraintContextObj>,
 }
 
-impl Deref for StructuralVisitorWithConstraintContext {
-    type Target = StructuralVisitorWithConstraintContextObj;
-    fn deref(&self) -> &StructuralVisitorWithConstraintContextObj {
-        &self.base
-    }
-}
-
 impl StructuralVisitorWithConstraintContextObj {
     pub fn constraints(&self) -> Result<ConstraintContext> {
         FieldGetter::new(Self::type_index(), "constraints")?.get(self)
diff --git a/rust/src/tirx/tensor.rs b/rust/src/tirx/tensor.rs
index 41b914572..994682266 100644
--- a/rust/src/tirx/tensor.rs
+++ b/rust/src/tirx/tensor.rs
@@ -115,13 +115,6 @@ pub struct TensorType {
     base: ObjectArc<TensorTypeObj>,
 }
 
-impl Deref for TensorType {
-    type Target = TensorTypeObj;
-    fn deref(&self) -> &TensorTypeObj {
-        &self.base
-    }
-}
-
 impl Deref for TensorTypeObj {
     type Target = TypeObj;
     fn deref(&self) -> &TypeObj {
@@ -167,7 +160,7 @@ impl TensorType {
 
 unsafe impl tvm_ffi::object::ImmutableObject for TensorTypeObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(TensorType => Type);
+tvm_ffi::unsafe_impl_object_ref_upcast!(TensorType => Type);
 // tvm-ffi-stubgen(end)
 
 /// The runtime's allocation alignment (C++ `runtime::kAllocAlignment`, which 
a build may set),
diff --git a/rust/src/tirx/thread_scope.rs b/rust/src/tirx/thread_scope.rs
index c450045dd..027e0e06d 100644
--- a/rust/src/tirx/thread_scope.rs
+++ b/rust/src/tirx/thread_scope.rs
@@ -44,7 +44,6 @@
 
 // tvm-ffi-stubgen(begin): import-section
 use std::borrow::Borrow;
-use std::ops::Deref;
 use tvm_ffi::IntoObjectRef;
 use tvm_ffi::Object;
 use tvm_ffi::ObjectArc;
@@ -77,13 +76,6 @@ pub struct ThreadScope {
     base: ObjectArc<ThreadScopeObj>,
 }
 
-impl Deref for ThreadScope {
-    type Target = ThreadScopeObj;
-    fn deref(&self) -> &ThreadScopeObj {
-        &self.base
-    }
-}
-
 unsafe impl tvm_ffi::object::ImmutableObject for ThreadScopeObj {}
 // tvm-ffi-stubgen(end)
 
diff --git a/rust/src/tirx/tile/dispatch.rs b/rust/src/tirx/tile/dispatch.rs
index ab937439b..3707ee91b 100644
--- a/rust/src/tirx/tile/dispatch.rs
+++ b/rust/src/tirx/tile/dispatch.rs
@@ -69,7 +69,6 @@ use crate::ir::expr::Var;
 use crate::ir::stmt::Stmt;
 use crate::target::Target;
 use crate::tirx::thread_scope::ThreadScope;
-use std::ops::Deref;
 use tvm_ffi::Any;
 use tvm_ffi::AnyView;
 use tvm_ffi::Array;
@@ -100,13 +99,6 @@ pub struct DispatchContext {
     base: ObjectArc<DispatchContextObj>,
 }
 
-impl Deref for DispatchContext {
-    type Target = DispatchContextObj;
-    fn deref(&self) -> &DispatchContextObj {
-        &self.base
-    }
-}
-
 impl DispatchContextObj {
     pub fn target(&self) -> Result<Target> {
         FieldGetter::new(Self::type_index(), "target")?.get(self)
diff --git a/rust/src/tirx/tile/instruction.rs 
b/rust/src/tirx/tile/instruction.rs
index ae7ebf875..44b119176 100644
--- a/rust/src/tirx/tile/instruction.rs
+++ b/rust/src/tirx/tile/instruction.rs
@@ -78,13 +78,6 @@ pub struct ScopeAttrs {
     base: ObjectArc<ScopeAttrsObj>,
 }
 
-impl Deref for ScopeAttrs {
-    type Target = ScopeAttrsObj;
-    fn deref(&self) -> &ScopeAttrsObj {
-        &self.base
-    }
-}
-
 impl Deref for ScopeAttrsObj {
     type Target = AttrsObj;
     fn deref(&self) -> &AttrsObj {
@@ -109,7 +102,7 @@ impl ScopeAttrs {
 
 unsafe impl tvm_ffi::object::ImmutableObject for ScopeAttrsObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(ScopeAttrs => Attrs);
+tvm_ffi::unsafe_impl_object_ref_upcast!(ScopeAttrs => Attrs);
 // tvm-ffi-stubgen(end)
 
 // tvm-ffi-stubgen(begin): object/tirx.tensor.TrnAttrs
@@ -142,13 +135,6 @@ pub struct TrnAttrs {
     base: ObjectArc<TrnAttrsObj>,
 }
 
-impl Deref for TrnAttrs {
-    type Target = TrnAttrsObj;
-    fn deref(&self) -> &TrnAttrsObj {
-        &self.base
-    }
-}
-
 impl Deref for TrnAttrsObj {
     type Target = AttrsObj;
     fn deref(&self) -> &AttrsObj {
@@ -203,7 +189,7 @@ impl TrnAttrs {
 
 unsafe impl tvm_ffi::object::ImmutableObject for TrnAttrsObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(TrnAttrs => Attrs);
+tvm_ffi::unsafe_impl_object_ref_upcast!(TrnAttrs => Attrs);
 // tvm-ffi-stubgen(end)
 
 /// Return the tensor region `value` covers: a `TensorLoad` converted, a 
[`TensorRegion`] as is
diff --git a/rust/src/tirx/transform/function_pass.rs 
b/rust/src/tirx/transform/function_pass.rs
index 673c048bc..19451bf65 100644
--- a/rust/src/tirx/transform/function_pass.rs
+++ b/rust/src/tirx/transform/function_pass.rs
@@ -87,13 +87,6 @@ pub struct FunctionPass {
     base: ObjectArc<FunctionPassObj>,
 }
 
-impl Deref for FunctionPass {
-    type Target = FunctionPassObj;
-    fn deref(&self) -> &FunctionPassObj {
-        &self.base
-    }
-}
-
 impl Deref for FunctionPassObj {
     type Target = PassObj;
     fn deref(&self) -> &PassObj {
@@ -109,7 +102,7 @@ impl FunctionPassObj {
 
 unsafe impl tvm_ffi::object::ImmutableObject for FunctionPassObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(FunctionPass => Pass);
+tvm_ffi::unsafe_impl_object_ref_upcast!(FunctionPass => Pass);
 // tvm-ffi-stubgen(end)
 
 impl FunctionPass {
diff --git a/rust/src/tirx/transform/transform.rs 
b/rust/src/tirx/transform/transform.rs
index d11550449..6bb73ef41 100644
--- a/rust/src/tirx/transform/transform.rs
+++ b/rust/src/tirx/transform/transform.rs
@@ -56,7 +56,6 @@
 use crate::ir::transform::core::Pass;
 use crate::target::Target;
 use crate::tirx::function::Function;
-use std::ops::Deref;
 use tvm_ffi::Object;
 use tvm_ffi::ObjectArc;
 use tvm_ffi::Result;
@@ -86,13 +85,6 @@ pub struct RemoveNoOpConfig {
     base: ObjectArc<RemoveNoOpConfigObj>,
 }
 
-impl Deref for RemoveNoOpConfig {
-    type Target = RemoveNoOpConfigObj;
-    fn deref(&self) -> &RemoveNoOpConfigObj {
-        &self.base
-    }
-}
-
 impl RemoveNoOpConfigObj {
     pub(crate) fn new(max_simplification_steps: i64, ignore_profiler_call: 
bool) -> Self {
         let base = Object::new();
@@ -137,13 +129,6 @@ pub struct UnrollLoopConfig {
     base: ObjectArc<UnrollLoopConfigObj>,
 }
 
-impl Deref for UnrollLoopConfig {
-    type Target = UnrollLoopConfigObj;
-    fn deref(&self) -> &UnrollLoopConfigObj {
-        &self.base
-    }
-}
-
 impl UnrollLoopConfigObj {
     pub(crate) fn new(
         auto_max_step: i32,
diff --git a/rust/src/tirx/type.rs b/rust/src/tirx/type.rs
index e0655f82d..3320d0889 100644
--- a/rust/src/tirx/type.rs
+++ b/rust/src/tirx/type.rs
@@ -64,13 +64,6 @@ pub struct TensorMapType {
     base: ObjectArc<TensorMapTypeObj>,
 }
 
-impl Deref for TensorMapType {
-    type Target = TensorMapTypeObj;
-    fn deref(&self) -> &TensorMapTypeObj {
-        &self.base
-    }
-}
-
 impl Deref for TensorMapTypeObj {
     type Target = TypeObj;
     fn deref(&self) -> &TypeObj {
@@ -95,7 +88,7 @@ impl TensorMapType {
 
 unsafe impl tvm_ffi::object::ImmutableObject for TensorMapTypeObj {}
 
-tvm_ffi::unsafe_impl_object_upcast!(TensorMapType => Type);
+tvm_ffi::unsafe_impl_object_ref_upcast!(TensorMapType => Type);
 // tvm-ffi-stubgen(end)
 
 // The native `tirx.TensorMapType` stores the location as given, as the 
generated
diff --git a/rust/tests/ir/expr.rs b/rust/tests/ir/expr.rs
index 9ca6c1390..ce246f91a 100644
--- a/rust/tests/ir/expr.rs
+++ b/rust/tests/ir/expr.rs
@@ -49,17 +49,14 @@ fn expressions() {
     assert!(structural_equal(&item.ty, &i32_ty));
     assert!(TupleGetItem::new(&tuple, 2, UNKNOWN_LOC).is_err());
     let subscripted =
-        Expr::from(&tuple).subscript([Subscript::Index(int32(0).into())], 
UNKNOWN_LOC).unwrap();
+        Expr::from(&tuple).subscript([Subscript::Index(int32(0))], 
UNKNOWN_LOC).unwrap();
     assert!(Expr::try_from(subscripted).is_ok());
 
     let a = tensor_var("A");
     let load = TensorLoad::new(&a, [&x], UNKNOWN_LOC).unwrap();
     assert_eq!(load.indices.len(), 1);
     let slice = Expr::from(&a)
-        .subscript(
-            [Subscript::Slice(Some(int32(0).into()), Some(int32(4).into()), 
None)],
-            UNKNOWN_LOC,
-        )
+        .subscript([Subscript::Slice(Some(int32(0)), Some(int32(4)), None)], 
UNKNOWN_LOC)
         .unwrap();
     assert!(Expr::try_from(slice).is_ok());
 
diff --git a/rust/tests/ir/op_def.rs b/rust/tests/ir/op_def.rs
index 94de9e05e..5a3490d3a 100644
--- a/rust/tests/ir/op_def.rs
+++ b/rust/tests/ir/op_def.rs
@@ -38,9 +38,9 @@ use tvm_tirx::tirx::{CallFFIKernelAttr, TensorVar};
 use tvm_tirx::tvm_ffi::static_init::{StaticInitBlock, STATIC_INIT_BLOCKS};
 use tvm_tirx::tvm_ffi::tvm_ffi_sys::TVMFFITypeIndex;
 use tvm_tirx::tvm_ffi::{
-    self, def_object_ref, rs_object, run_static_init_blocks, Any, AnyView, 
Array, Error, ErrorKind,
-    Function, Map, ObjectCore, ObjectRefCore, Result, String as FfiString, 
ATTRIBUTE_ERROR,
-    INTERNAL_ERROR, TYPE_ERROR, VALUE_ERROR,
+    self, rs_object, run_static_init_blocks, Any, AnyView, Array, Error, 
ErrorKind, Function, Map,
+    ObjectCore, ObjectRefCore, Result, String as FfiString, ATTRIBUTE_ERROR, 
INTERNAL_ERROR,
+    TYPE_ERROR, VALUE_ERROR,
 };
 
 use super::{int32, parse_dtype, tensor_var};
@@ -421,7 +421,11 @@ pub struct BlockTypeObj {
     #[reflect(kw_only)]
     pub count: i64,
 }
-def_object_ref!(pub BlockType, Type, BlockTypeObj);
+#[derive(Clone, tvm_ffi::derive::ObjectRef)]
+#[object_ref(parent = Type)]
+pub struct BlockType {
+    data: tvm_ffi::ObjectArc<BlockTypeObj>,
+}
 
 tvm_ffi::static_init_block! {
     OpDef::new("rust_test.defined_identity", "
diff --git a/rust/tests/ir/type.rs b/rust/tests/ir/type.rs
index 5418f71ec..3565a942b 100644
--- a/rust/tests/ir/type.rs
+++ b/rust/tests/ir/type.rs
@@ -28,7 +28,7 @@ use tvm_tirx::ir::{
     OpaqueType, PrimType, PtrType, StringType, TensorRegionType, TupleType, 
Type, TypeObj, Var,
     VarObj,
 };
-use tvm_tirx::tvm_ffi::{def_object_ref, rs_object, structural_map};
+use tvm_tirx::tvm_ffi::{rs_object, structural_map};
 use tvm_tirx::tvm_ffi::{
     Any, AnyView, Array, DLDataType, DLDataTypeExt, FieldGetter, ObjectCore, 
ObjectRefCore, Result,
     ShallowCopy, String as FfiString, WalkOrder,
@@ -131,19 +131,23 @@ pub struct PairTypeObj {
     pub note: FfiString,
 }
 
-def_object_ref!(pub PairType, Type, PairTypeObj);
+#[derive(Clone, tvm_ffi::derive::ObjectRef)]
+#[object_ref(parent = Type)]
+pub struct PairType {
+    data: tvm_ffi::ObjectArc<PairTypeObj>,
+}
 
 impl PairType {
     /// A copy with the fields `edit` assigns replaced (C++ `CopyOnWrite()`).
     fn with(&self, edit: impl FnOnce(&mut PairTypeObj)) -> Self {
         let mut node = self.shallow_copy();
         edit(&mut node);
-        node.into()
+        Self::from_object(node)
     }
 }
 
 fn pair(lhs: Type, rhs: Type, tag: i64, note: &str) -> PairType {
-    PairTypeObj::new(TypeObj::new(UNKNOWN_LOC.into()), lhs, rhs, tag, 
note).into()
+    PairType::from_object(PairTypeObj::new(TypeObj::new(UNKNOWN_LOC.into()), 
lhs, rhs, tag, note))
 }
 
 fn int_float_pair(tag: i64, note: &str) -> PairType {

Reply via email to