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 31f6c2b9d [Rust] Borrow the arguments of read-only query APIs through 
IntoObjectRef (#206)
31f6c2b9d is described below

commit 31f6c2b9d54f416040d82c0783714d5a4bab7188
Author: Tianqi Chen <[email protected]>
AuthorDate: Thu Nov 5 19:09:31 2026 -0500

    [Rust] Borrow the arguments of read-only query APIs through IntoObjectRef 
(#206)
    
    Read-only queries took their object arguments as `impl Into<T>`, so a
    caller passing `&x` paid a reference-count bump for a value the call
    only reads. They now take `impl IntoObjectRef<T>` and pass the borrow,
    as `IntoExpr` does for expressions: `&x` and its subtypes cost nothing,
    and owned values still work.
    
    ## Changes
    
    - `IRModule::lookup`, `contains_global_var` and `remove_global_var`
    borrow the `GlobalVar`.
    - `Analyzer::const_int_bound_is_bound` and `tensor_is_scalar` borrow the
    `Var`.
    - `ThreadScope::is_higher_than` borrows `other`.
    - `analysis::verify_memory`, `check_well_formed` and
    `check_well_formed_module` borrow the function or module.
    - The in-place mutation check in
    `StructuralMutatorWithConstraintContext` borrows the object with
    `downcast_ref` instead of copying it with `try_as`, so the uniqueness
    test is a strong count of 1.
    
    APIs that hand ownership on (`Pass::run`, `build`,
    `IRModule::update_func`) stay by value, so a unique reference can be
    modified in place.
---
 rust/src/ir/module.rs                                    | 14 ++++++++------
 rust/src/sym/analyzer.rs                                 |  5 +++--
 rust/src/tirx/analysis/analysis.rs                       | 16 ++++++++++------
 .../tirx/structural_mutate_with_constraint_context.rs    | 11 ++++-------
 rust/src/tirx/tensor.rs                                  |  6 ++++--
 rust/src/tirx/thread_scope.rs                            |  6 ++++--
 6 files changed, 33 insertions(+), 25 deletions(-)

diff --git a/rust/src/ir/module.rs b/rust/src/ir/module.rs
index 058b9f988..a8c2f0f73 100644
--- a/rust/src/ir/module.rs
+++ b/rust/src/ir/module.rs
@@ -65,6 +65,7 @@ use std::borrow::Borrow;
 use std::ops::Deref;
 use tvm_ffi::Any;
 use tvm_ffi::Array;
+use tvm_ffi::IntoObjectRef;
 use tvm_ffi::Map;
 use tvm_ffi::Object;
 use tvm_ffi::ObjectArc;
@@ -217,8 +218,9 @@ impl IRModule {
     }
 
     /// Remove the function of `var`, if the module has one 
(`ir.IRModuleRemove`).
-    pub fn remove_global_var(&self, var: impl Into<GlobalVar>) -> Result<()> {
-        tvm_ffi::cached_global_func!("ir.IRModuleRemove").call_tuple((self, 
&var.into()))?;
+    pub fn remove_global_var(&self, var: impl IntoObjectRef<GlobalVar>) -> 
Result<()> {
+        tvm_ffi::cached_global_func!("ir.IRModuleRemove")
+            .call_tuple((self, var.into_object_ref().borrow()))?;
         Ok(())
     }
 
@@ -230,9 +232,9 @@ impl IRModule {
     }
 
     /// Return whether the module defines a function for `var` 
(`ir.IRModuleContains`).
-    pub fn contains_global_var(&self, var: impl Into<GlobalVar>) -> 
Result<bool> {
+    pub fn contains_global_var(&self, var: impl IntoObjectRef<GlobalVar>) -> 
Result<bool> {
         tvm_ffi::cached_global_func!("ir.IRModuleContains")
-            .call_tuple((self, &var.into()))?
+            .call_tuple((self, var.into_object_ref().borrow()))?
             .try_into()
     }
 
@@ -265,9 +267,9 @@ impl IRModule {
     /// # Errors
     ///
     /// Returns an `InternalError` if the module has no function for `var`.
-    pub fn lookup(&self, var: impl Into<GlobalVar>) -> Result<BaseFunc> {
+    pub fn lookup(&self, var: impl IntoObjectRef<GlobalVar>) -> 
Result<BaseFunc> {
         tvm_ffi::cached_global_func!("ir.IRModuleLookup")
-            .call_tuple((self, &var.into()))?
+            .call_tuple((self, var.into_object_ref().borrow()))?
             .try_into()
     }
 
diff --git a/rust/src/sym/analyzer.rs b/rust/src/sym/analyzer.rs
index 9163ede65..7f19af5df 100644
--- a/rust/src/sym/analyzer.rs
+++ b/rust/src/sym/analyzer.rs
@@ -83,6 +83,7 @@ use crate::sym::int_set::IntSet;
 use std::borrow::Borrow;
 use std::ops::Deref;
 use tvm_ffi::Error;
+use tvm_ffi::IntoObjectRef;
 use tvm_ffi::Map;
 use tvm_ffi::Object;
 use tvm_ffi::ObjectArc;
@@ -178,9 +179,9 @@ impl Analyzer {
     }
 
     /// Return whether `var` has constant bounds recorded 
(`sym.AnalyzerConstIntBoundIsBound`).
-    pub fn const_int_bound_is_bound(&self, var: impl Into<Var>) -> 
Result<bool> {
+    pub fn const_int_bound_is_bound(&self, var: impl IntoObjectRef<Var>) -> 
Result<bool> {
         tvm_ffi::cached_global_func!("sym.AnalyzerConstIntBoundIsBound")
-            .call_tuple((self, &var.into()))?
+            .call_tuple((self, var.into_object_ref().borrow()))?
             .try_into()
     }
 
diff --git a/rust/src/tirx/analysis/analysis.rs 
b/rust/src/tirx/analysis/analysis.rs
index f29a6d567..656919db4 100644
--- a/rust/src/tirx/analysis/analysis.rs
+++ b/rust/src/tirx/analysis/analysis.rs
@@ -57,6 +57,7 @@ use crate::tirx::function::Function;
 use std::borrow::Borrow;
 use tvm_ffi::Any;
 use tvm_ffi::Array;
+use tvm_ffi::IntoObjectRef;
 use tvm_ffi::Result;
 // tvm-ffi-stubgen(end)
 
@@ -65,9 +66,9 @@ use tvm_ffi::Result;
 ///
 /// A function without a target attribute, or not of the default calling 
convention, is not checked
 /// and passes.
-pub fn verify_memory(func: impl Into<Function>) -> Result<bool> {
+pub fn verify_memory(func: impl IntoObjectRef<Function>) -> Result<bool> {
     tvm_ffi::cached_global_func!("tirx.analysis.VerifyMemory")
-        .call_tuple((&func.into(),))?
+        .call_tuple((func.into_object_ref().borrow(),))?
         .try_into()
 }
 
@@ -85,17 +86,20 @@ pub fn undefined_vars(
 
 /// Return whether `func` is well formed; invalid IR raises an error instead 
if `assert_mode`
 /// (`tirx.analysis.CheckWellFormed`).
-pub fn check_well_formed(func: impl Into<Function>, assert_mode: bool) -> 
Result<bool> {
+pub fn check_well_formed(func: impl IntoObjectRef<Function>, assert_mode: 
bool) -> Result<bool> {
     tvm_ffi::cached_global_func!("tirx.analysis.CheckWellFormed")
-        .call_tuple((&func.into(), assert_mode))?
+        .call_tuple((func.into_object_ref().borrow(), assert_mode))?
         .try_into()
 }
 
 /// Return whether the TIRx functions of `module` are well formed; invalid IR 
raises an error
 /// instead if `assert_mode` (`tirx.analysis.CheckWellFormed`).
-pub fn check_well_formed_module(module: impl Into<IRModule>, assert_mode: 
bool) -> Result<bool> {
+pub fn check_well_formed_module(
+    module: impl IntoObjectRef<IRModule>,
+    assert_mode: bool,
+) -> Result<bool> {
     tvm_ffi::cached_global_func!("tirx.analysis.CheckWellFormed")
-        .call_tuple((&module.into(), assert_mode))?
+        .call_tuple((module.into_object_ref().borrow(), assert_mode))?
         .try_into()
 }
 
diff --git a/rust/src/tirx/structural_mutate_with_constraint_context.rs 
b/rust/src/tirx/structural_mutate_with_constraint_context.rs
index 471848d92..758579e94 100644
--- a/rust/src/tirx/structural_mutate_with_constraint_context.rs
+++ b/rust/src/tirx/structural_mutate_with_constraint_context.rs
@@ -95,13 +95,10 @@ unsafe impl StructuralMutatorBase for 
StructuralMutatorWithConstraintContextBase
         let hook = if value.inplace_mode() == InplaceMode::Allow {
             lookup(*INPLACE).filter(|_| {
                 // Permission alone is insufficient after a callback retains an
-                // alias. The supported owning count includes this temporary;
-                // release it before invoking a hook or entering native 
descent.
-                borrowed.try_as::<ObjectRef>().is_some_and(|owner| {
-                    let unique = 
ObjectArc::strong_count(ObjectRef::data(&owner)) == 2;
-                    drop(owner);
-                    unique
-                })
+                // alias. Borrow in place so the count is the slot's own 
reference.
+                borrowed
+                    .downcast_ref::<ObjectRef>()
+                    .is_some_and(|owner| 
ObjectArc::strong_count(ObjectRef::data(owner)) == 1)
             })
         } else {
             None
diff --git a/rust/src/tirx/tensor.rs b/rust/src/tirx/tensor.rs
index 7679d5537..720b8c43e 100644
--- a/rust/src/tirx/tensor.rs
+++ b/rust/src/tirx/tensor.rs
@@ -76,9 +76,11 @@ use crate::ir::support;
 use crate::runtime::MemoryScope;
 use crate::sym::analyzer::Analyzer;
 use crate::tirx::layout::Layout;
+use std::borrow::Borrow;
 use std::ops::Deref;
 use tvm_ffi::AnyView;
 use tvm_ffi::Array;
+use tvm_ffi::IntoObjectRef;
 use tvm_ffi::ObjectArc;
 use tvm_ffi::ObjectCore;
 use tvm_ffi::Result;
@@ -228,9 +230,9 @@ impl TensorType {
 /// # Errors
 ///
 /// Returns an error if the type of `tensor` is not a [`TensorType`].
-pub fn tensor_is_scalar(tensor: impl Into<Var>, alloc_or_decl: bool) -> 
Result<bool> {
+pub fn tensor_is_scalar(tensor: impl IntoObjectRef<Var>, alloc_or_decl: bool) 
-> Result<bool> {
     tvm_ffi::cached_global_func!("tirx.TensorIsScalar")
-        .call_tuple((&tensor.into(), alloc_or_decl))?
+        .call_tuple((tensor.into_object_ref().borrow(), alloc_or_decl))?
         .try_into()
 }
 
diff --git a/rust/src/tirx/thread_scope.rs b/rust/src/tirx/thread_scope.rs
index 9bc9fd264..9c6956d82 100644
--- a/rust/src/tirx/thread_scope.rs
+++ b/rust/src/tirx/thread_scope.rs
@@ -41,7 +41,9 @@
 // tvm-ffi-stubgen(import-object): tvm_ffi::String
 
 // 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;
 use tvm_ffi::Result;
@@ -116,9 +118,9 @@ impl ThreadScope {
     /// # Errors
     ///
     /// Returns an error if the two scopes are of different backends.
-    pub fn is_higher_than(&self, other: impl Into<ThreadScope>) -> 
Result<bool> {
+    pub fn is_higher_than(&self, other: impl IntoObjectRef<ThreadScope>) -> 
Result<bool> {
         tvm_ffi::cached_global_func!("tirx.ScopeHigher")
-            .call_tuple((self, &other.into()))?
+            .call_tuple((self, other.into_object_ref().borrow()))?
             .try_into()
     }
 }

Reply via email to