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 26b0e69d4 [Rust] Bump tvm-ffi to latest (#211)
26b0e69d4 is described below

commit 26b0e69d4a7273e45c0faad3701855efc1790978
Author: Tianqi Chen <[email protected]>
AuthorDate: Fri Nov 6 12:00:59 2026 -0500

    [Rust] Bump tvm-ffi to latest (#211)
    
    Bump tvm-ffi to latest.
    
    - Adopt its cleanups: drop the repeated-frame check in the
    constraint-context mutator (tvm-ffi now skips it), and use
    `unsafe_impl_ref_downcast!` in `typed_expr_view!`.
    - Fix the Rust clippy findings and run pinned clippy in the lint job
    when Rust changes.
---
 .github/workflows/lint.yml                         | 19 ++++++++++++++
 3rdparty/tvm-ffi                                   |  2 +-
 rust/src/backend/cuda/op.rs                        |  2 ++
 rust/src/ir/attrs.rs                               |  2 ++
 rust/src/ir/global_info.rs                         |  2 ++
 rust/src/ir/location.rs                            |  3 +++
 rust/src/ir/prim/op.rs                             |  2 +-
 rust/src/ir/stmt.rs                                |  4 ++-
 rust/src/ir/type.rs                                |  6 +++++
 rust/src/macro/def_expr_op_overloads.rs            |  2 ++
 rust/src/macro/typed_expr_view.rs                  | 29 +++-------------------
 rust/src/sym/analyzer.rs                           |  2 ++
 rust/src/sym/constraint.rs                         |  4 ++-
 rust/src/tirx/tile/dispatch.rs                     |  6 +----
 rust/src/tirx/tile/instruction.rs                  |  2 ++
 rust/tests/sym/iter_affine_map.rs                  |  2 +-
 .../ir/stmt_functor_with_constraint_context.cc     | 12 +++------
 17 files changed, 56 insertions(+), 45 deletions(-)

diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 8ac5f2f9f..5b0a0c19d 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -39,3 +39,22 @@ jobs:
           fetch-depth: 0
           fetch-tags: true
       - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd  # 
v3.0.1
+      - name: Detect Rust changes
+        id: rust_changes
+        run: |
+          # The crate builds against the submodule by path, so a bump counts.
+          if [ "${{ github.event_name }}" != "pull_request" ] ||
+             ! git diff --quiet "${{ github.event.pull_request.base.sha }}" 
HEAD -- \
+               rust/ 3rdparty/tvm-ffi .github/workflows/lint.yml; then
+            echo "changed=true" >> "$GITHUB_OUTPUT"
+          fi
+      # Clippy only type-checks, so DOCS_RS skips the tvm-ffi-config lookup and
+      # no build is needed. Pin it so new lints arrive with a toolchain bump.
+      - name: Rust clippy
+        if: steps.rust_changes.outputs.changed == 'true'
+        env:
+          DOCS_RS: "1"
+        run: |
+          git submodule update --init 3rdparty/tvm-ffi
+          rustup toolchain install 1.99.1 --profile minimal --component clippy
+          cargo +1.99.1 clippy --manifest-path rust/Cargo.toml --all-targets 
-- -D warnings
diff --git a/3rdparty/tvm-ffi b/3rdparty/tvm-ffi
index 9288282fe..a472db8d8 160000
--- a/3rdparty/tvm-ffi
+++ b/3rdparty/tvm-ffi
@@ -1 +1 @@
-Subproject commit 9288282fee38e0ba681411b80bb36d211d436e60
+Subproject commit a472db8d80b57c6d6be34965e84133f7ce450c57
diff --git a/rust/src/backend/cuda/op.rs b/rust/src/backend/cuda/op.rs
index 269959368..46a2a5bbc 100644
--- a/rust/src/backend/cuda/op.rs
+++ b/rust/src/backend/cuda/op.rs
@@ -18,6 +18,8 @@
  */
 // The reflected field names `M`, `N`, and `K` are kept as they are.
 #![allow(dead_code, unused_imports, non_snake_case)]
+// The generated constructors take one argument per reflected field.
+#![allow(clippy::too_many_arguments)]
 
 //! The attributes of CUDA instructions.
 //!
diff --git a/rust/src/ir/attrs.rs b/rust/src/ir/attrs.rs
index 80a841534..006eadefa 100644
--- a/rust/src/ir/attrs.rs
+++ b/rust/src/ir/attrs.rs
@@ -17,6 +17,8 @@
  * under the License.
  */
 #![allow(dead_code, unused_imports)]
+// The generated `new` of a field-less base needs no `Default`.
+#![allow(clippy::new_without_default)]
 
 //! Attributes attached to calls, functions and modules.
 //!
diff --git a/rust/src/ir/global_info.rs b/rust/src/ir/global_info.rs
index 6ddebd1f2..9f699d843 100644
--- a/rust/src/ir/global_info.rs
+++ b/rust/src/ir/global_info.rs
@@ -17,6 +17,8 @@
  * under the License.
  */
 #![allow(dead_code, unused_imports)]
+// The generated `new` of a field-less base needs no `Default`.
+#![allow(clippy::new_without_default)]
 
 //! Module-level information that is not a function.
 //!
diff --git a/rust/src/ir/location.rs b/rust/src/ir/location.rs
index 1faeb66fc..ad29b147c 100644
--- a/rust/src/ir/location.rs
+++ b/rust/src/ir/location.rs
@@ -17,6 +17,9 @@
  * under the License.
  */
 #![allow(dead_code, unused_imports)]
+// The generated `new` of a field-less base needs no `Default`, and 
`UnknownLoc::new` fetches a
+// shared FFI singleton.
+#![allow(clippy::new_without_default)]
 
 //! Source locations of IR nodes, for diagnostics.
 //!
diff --git a/rust/src/ir/prim/op.rs b/rust/src/ir/prim/op.rs
index e4e6d7e10..f0431cabd 100644
--- a/rust/src/ir/prim/op.rs
+++ b/rust/src/ir/prim/op.rs
@@ -296,7 +296,7 @@ fn binary(
 ) -> ExprResult {
     let rhs = typed_after(rhs.classify(), &lhs);
     match (lhs.0, rhs.0) {
-        (Ok(a), Ok(b)) => ExprResult(op(a.into(), b.into())),
+        (Ok(a), Ok(b)) => ExprResult(op(a, b)),
         (Err(error), _) | (_, Err(error)) => ExprResult(Err(error)),
     }
 }
diff --git a/rust/src/ir/stmt.rs b/rust/src/ir/stmt.rs
index d500e68e8..72515fdc0 100644
--- a/rust/src/ir/stmt.rs
+++ b/rust/src/ir/stmt.rs
@@ -17,6 +17,8 @@
  * under the License.
  */
 #![allow(dead_code, unused_imports)]
+// The generated constructors take one argument per reflected field.
+#![allow(clippy::too_many_arguments)]
 
 //! Statements: bindings, assertions, loops, conditionals, tensor stores and 
sequences.
 //!
@@ -1036,7 +1038,7 @@ impl SeqStmt {
 fn flatten(seq: Array<Stmt>) -> Array<Stmt> {
     let nested_or_no_op =
         |stmt: &Stmt| stmt.downcast_ref::<SeqStmtObj>().is_some() || 
is_no_op(stmt);
-    if !seq.iter().any(|stmt| nested_or_no_op(&stmt)) {
+    if !seq.iter().any(nested_or_no_op) {
         return seq;
     }
     fn append(stmt: Stmt, flattened: &mut Vec<Stmt>) {
diff --git a/rust/src/ir/type.rs b/rust/src/ir/type.rs
index 9d2884fba..95ce36ca7 100644
--- a/rust/src/ir/type.rs
+++ b/rust/src/ir/type.rs
@@ -199,6 +199,8 @@ tvm_ffi::unsafe_impl_object_upcast!(MissingType => Type);
 impl MissingType {
     /// Return the shared type of a node whose type is not known yet, fetched 
once per thread
     /// (`ir.MissingType`).
+    // Not `Default`: `new` fetches a shared FFI singleton rather than 
building a value.
+    #[allow(clippy::new_without_default)]
     pub fn new() -> Self {
         thread_local! {
             static MISSING_TYPE: std::cell::OnceCell<MissingType> = const { 
std::cell::OnceCell::new() };
@@ -266,6 +268,8 @@ tvm_ffi::unsafe_impl_object_upcast!(NoneType => Type);
 
 impl NoneType {
     /// Return the shared type of the `None` value, fetched once per thread 
(`ir.NoneType`).
+    // Not `Default`: `new` fetches a shared FFI singleton rather than 
building a value.
+    #[allow(clippy::new_without_default)]
     pub fn new() -> Self {
         thread_local! {
             static NONE_TYPE: std::cell::OnceCell<NoneType> = const { 
std::cell::OnceCell::new() };
@@ -390,6 +394,8 @@ tvm_ffi::unsafe_impl_object_upcast!(TensorRegionType => 
Type);
 
 impl TensorRegionType {
     /// Return the shared type of a tensor region, fetched once per thread 
(`ir.TensorRegionType`).
+    // Not `Default`: `new` fetches a shared FFI singleton rather than 
building a value.
+    #[allow(clippy::new_without_default)]
     pub fn new() -> Self {
         thread_local! {
             static TENSOR_REGION_TYPE: std::cell::OnceCell<TensorRegionType> =
diff --git a/rust/src/macro/def_expr_op_overloads.rs 
b/rust/src/macro/def_expr_op_overloads.rs
index 2013f3c9c..e2332b1c3 100644
--- a/rust/src/macro/def_expr_op_overloads.rs
+++ b/rust/src/macro/def_expr_op_overloads.rs
@@ -60,6 +60,8 @@
 /// # Ok(())
 /// # }
 /// ```
+// `crate::` matches the caller's path and re-emits it, so it names the 
caller's crate.
+#[allow(clippy::crate_in_macro_def)]
 #[macro_export]
 macro_rules! def_expr_op_over_loads {
     (crate::$($ty:ident)::+ $(,)?) => {
diff --git a/rust/src/macro/typed_expr_view.rs 
b/rust/src/macro/typed_expr_view.rs
index 52d8c70f4..8d6bd490a 100644
--- a/rust/src/macro/typed_expr_view.rs
+++ b/rust/src/macro/typed_expr_view.rs
@@ -113,32 +113,9 @@ macro_rules! typed_expr_view {
             }
         }
 
-        // As `#[derive(ObjectRef)]` generates: the view is exactly one object 
pointer, so a
-        // cell or an object pointer that holds a `$name` borrows as `&$name` 
in place.
-        // SAFETY: the view is `repr(transparent)` over its `ObjectArc`, and 
the checked
-        // forms run `check_any_strict` first.
-        unsafe impl tvm_ffi::type_traits::RefFromAnyUnchecked for $name {
-            #[inline(always)]
-            unsafe fn ref_from_any_unchecked(cell: &TVMFFIAny) -> &Self {
-                unsafe { &*(::core::ptr::addr_of!(cell.data_union) as *const 
Self) }
-            }
-        }
-
-        unsafe impl tvm_ffi::type_traits::DowncastRefFromAny for $name {
-            #[inline(always)]
-            unsafe fn downcast_ref_from_any(cell: &TVMFFIAny) -> Option<&Self> 
{
-                unsafe { 
tvm_ffi::type_traits::downcast_ref_from_any_in_place::<Self>(cell) }
-            }
-        }
-
-        unsafe impl tvm_ffi::type_traits::DowncastRefFromObject for $name {
-            #[inline(always)]
-            unsafe fn downcast_ref_from_object(
-                place: &*mut tvm_ffi::tvm_ffi_sys::TVMFFIObject,
-            ) -> Option<&Self> {
-                unsafe { 
tvm_ffi::type_traits::downcast_ref_from_object_in_place::<Self>(place) }
-            }
-        }
+        // 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);
 
         impl AsRef<$name> for $name {
             #[inline(always)]
diff --git a/rust/src/sym/analyzer.rs b/rust/src/sym/analyzer.rs
index 6f44c6fde..dd11e007c 100644
--- a/rust/src/sym/analyzer.rs
+++ b/rust/src/sym/analyzer.rs
@@ -122,6 +122,8 @@ impl Deref for Analyzer {
 
 impl Analyzer {
     /// Create an analyzer that knows no facts (`sym.Analyzer`).
+    // Not `Default`: creating an analyzer allocates a stateful FFI object.
+    #[allow(clippy::new_without_default)]
     pub fn new() -> Self {
         support::infallible(
             tvm_ffi::cached_global_func!("sym.Analyzer")
diff --git a/rust/src/sym/constraint.rs b/rust/src/sym/constraint.rs
index d69637d49..630719bcb 100644
--- a/rust/src/sym/constraint.rs
+++ b/rust/src/sym/constraint.rs
@@ -17,6 +17,8 @@
  * under the License.
  */
 #![allow(dead_code, unused_imports)]
+// The generated `new` of a field-less base needs no `Default`.
+#![allow(clippy::new_without_default)]
 
 //! Constraints: the facts in scope at a point of a traversal.
 //!
@@ -412,7 +414,7 @@ impl ConstraintContextObj {
             parent.for_each_prefix(self.parent_prefix_size, callback);
         }
         for constraint in local.iter().take(prefix as usize) {
-            callback(&constraint);
+            callback(constraint);
         }
     }
 
diff --git a/rust/src/tirx/tile/dispatch.rs b/rust/src/tirx/tile/dispatch.rs
index 12d1273c2..ab937439b 100644
--- a/rust/src/tirx/tile/dispatch.rs
+++ b/rust/src/tirx/tile/dispatch.rs
@@ -257,11 +257,7 @@ impl DispatchContext {
     }
 
     /// Cache `value` under `key` across dispatches 
(`tirx.DispatchContextSharedStateSet`).
-    pub fn cache_set(
-        &self,
-        key: &str,
-        value: &(impl ObjectRefCore + tvm_ffi::type_traits::AnyCompatible),
-    ) -> Result<()> {
+    pub fn cache_set(&self, key: &str, value: &impl ObjectRefCore) -> 
Result<()> {
         let key = String::from(key);
         
tvm_ffi::cached_global_func!("tirx.DispatchContextSharedStateSet").call_packed(&[
             AnyView::from(self),
diff --git a/rust/src/tirx/tile/instruction.rs 
b/rust/src/tirx/tile/instruction.rs
index 6a8e08291..ae7ebf875 100644
--- a/rust/src/tirx/tile/instruction.rs
+++ b/rust/src/tirx/tile/instruction.rs
@@ -17,6 +17,8 @@
  * under the License.
  */
 #![allow(dead_code, unused_imports)]
+// The generated constructors take one argument per reflected field.
+#![allow(clippy::too_many_arguments)]
 
 //! The attributes of tile instruction calls.
 //!
diff --git a/rust/tests/sym/iter_affine_map.rs 
b/rust/tests/sym/iter_affine_map.rs
index 8b8ca0b26..fbd42f2d3 100644
--- a/rust/tests/sym/iter_affine_map.rs
+++ b/rust/tests/sym/iter_affine_map.rs
@@ -73,7 +73,7 @@ fn iter_maps_decompose_into_marks_and_splits() {
     let mut lower_factors = Vec::new();
     for sum in result.indices.iter() {
         assert_eq!(as_int(sum.base_().unwrap()), 0);
-        let outer = only_split(&sum);
+        let outer = only_split(sum);
         let mark: IterMark = outer.source().unwrap();
         assert_eq!(as_int(mark.extent.clone()), 4);
         let inner_sum: IterSumExpr = mark.source.clone().downcast().unwrap();
diff --git a/src/tirx/ir/stmt_functor_with_constraint_context.cc 
b/src/tirx/ir/stmt_functor_with_constraint_context.cc
index 87dbabb61..1da42574d 100644
--- a/src/tirx/ir/stmt_functor_with_constraint_context.cc
+++ b/src/tirx/ir/stmt_functor_with_constraint_context.cc
@@ -107,15 +107,9 @@ ffi::UnchangedOr<ffi::Any> 
ObjectMutatorWithConstraintContext::Mutate(ffi::AnyVi
     try {
       return (*native_vtable_)(object, this, mode);
     } catch (ffi::Error& error) {
-      // Default mutation already names the current node. A user override may 
throw
-      // before delegating; attach its frame without duplicating default 
descent's frame.
-      // Release the context handle before the update so a unique context is 
appended in place.
-      bool named = [&] {
-        auto context = ffi::VisitErrorContext::TryGetFromError(error);
-        return context.has_value() && 
!context.value()->reverse_visit_pattern.empty() &&
-               context.value()->reverse_visit_pattern.back().get() == object;
-      }();
-      if (!named) ffi::detail::UpdateVisitErrorContext(&error, value);
+      // A user override may throw before delegating; the update skips a frame 
that
+      // default descent already reported.
+      ffi::detail::UpdateVisitErrorContext(&error, value);
       throw;
     }
   }

Reply via email to