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 a6e9f0ced [Rust] Bump tvm-ffi to the locked-down Rust API
(apache/tvm-ffi#937, #938) (#208)
a6e9f0ced is described below
commit a6e9f0ced84f9da1896afb3151926160a7617647
Author: Tianqi Chen <[email protected]>
AuthorDate: Thu Nov 5 23:21:44 2026 -0500
[Rust] Bump tvm-ffi to the locked-down Rust API (apache/tvm-ffi#937, #938)
(#208)
Bumps tvm-ffi to the Rust API that is being locked down:
apache/tvm-ffi#937 (casts and lookups aligned with std and C++) and
apache/tvm-ffi#938 (thread safety only where it holds; `TryFrom` between
references). Migrates TIRx to it.
## Thread safety
- **Mutable classes are declared so:** `IRModule`, `PassContext`,
`IterMapResult`, `TargetKind` and `Target` set `_type_mutable = true`,
as their handles already hand out mutable pointers.
- **Every other class is `ImmutableObject`:** the regenerated bindings
mark each class C++ does not declare mutable. Expressions, statements,
types and functions are now `Send + Sync`; mutable classes and erased
`ObjectRef`/`Any` handles stay single-threaded.
- **`Op` is `ImmutableObject` by hand**, as its binding is hand-written:
registration counts as initialization. Its validator slot is written
only then, so `Op` crosses threads too.
## API migration
- **Bindings regenerated:** upcasts use `unsafe_impl_object_upcast!`.
- **Casts:**
- `ObjectRefCast` imports are gone, since `same_as`, `downcast_ref` and
`downcast` are on `ObjectRefCore`.
- Downcasts with `?` use `try_into()`.
- The typed views' hand-written `TryFrom` impls are replaced by the
generated ones.
- `try_as` becomes `TryFrom`, or `downcast_ref` where a value is only
inspected.
- **Typed views implement `Debug`**, as derived references do.
- **Renames:** `ObjectArc::as_ptr`, `VisitInterrupt::new`,
`reflection::get_method`, `TypeAttrColumn` for type attributes,
`Error::from_panic`, and `implements_function_with_imports`.
- **`Array::iter()` borrows** each element.
- **Callbacks are `Send + Sync`:** one test now captures a typed value
instead of an `Any`.
- The IR guide's cast section teaches `try_into` and `downcast`.
---
3rdparty/tvm-ffi | 2 +-
docs/ir_guides/working_with_ir_in_rust.rst | 36 ++---
examples/extension_guides/rust/src/lib.rs | 12 +-
examples/ir_guides/rust/src/lib.rs | 17 ++-
include/tvm/ir/module.h | 2 +
include/tvm/ir/transform.h | 2 +
include/tvm/sym/iter_affine_map.h | 2 +
include/tvm/target/target.h | 2 +
include/tvm/target/target_kind.h | 2 +
rust/examples/define_ir.rs | 4 +-
rust/src/backend/cuda/op.rs | 18 ++-
rust/src/codegen.rs | 2 +-
rust/src/ir/attrs.rs | 12 +-
rust/src/ir/base.rs | 6 +-
rust/src/ir/expr.rs | 140 ++++++++++++------
rust/src/ir/function.rs | 6 +-
rust/src/ir/global_info.rs | 4 +
rust/src/ir/location.rs | 26 +++-
rust/src/ir/op.rs | 33 ++++-
rust/src/ir/op_def.rs | 8 +-
rust/src/ir/prim/expr.rs | 162 +++++++++++++++++----
rust/src/ir/prim/vector_expr.rs | 18 ++-
rust/src/ir/stmt.rs | 90 +++++++++---
rust/src/ir/support.rs | 12 +-
rust/src/ir/transform/core.rs | 20 ++-
rust/src/ir/transform/instrument.rs | 2 +-
rust/src/ir/type.rs | 64 ++++++--
rust/src/macro/def_expr_op_overloads.rs | 2 +-
rust/src/macro/typed_expr_view.rs | 28 ++--
rust/src/runtime.rs | 4 +
rust/src/sym/analyzer.rs | 18 ++-
rust/src/sym/constraint.rs | 28 +++-
rust/src/sym/int_set.rs | 6 +-
rust/src/sym/iter_affine_map.rs | 18 ++-
rust/src/tirx/function.rs | 6 +-
rust/src/tirx/index_map.rs | 6 +-
rust/src/tirx/layout.rs | 20 ++-
rust/src/tirx/op.rs | 6 +-
.../structural_walk_with_constraint_context.rs | 4 +-
rust/src/tirx/tensor.rs | 6 +-
rust/src/tirx/thread_scope.rs | 4 +
rust/src/tirx/tile/dispatch.rs | 14 +-
rust/src/tirx/tile/instruction.rs | 12 +-
rust/src/tirx/transform/function_pass.rs | 6 +-
rust/src/tirx/transform/transform.rs | 12 +-
rust/src/tirx/type.rs | 6 +-
rust/tests/ir/expr.rs | 35 +++--
rust/tests/ir/op_def.rs | 14 +-
rust/tests/ir/prim.rs | 6 +-
rust/tests/ir/prim/op.rs | 35 +++--
rust/tests/sym/int_set.rs | 6 +-
rust/tests/sym/iter_affine_map.rs | 10 +-
rust/tests/target/main.rs | 6 +-
rust/tests/tirx/main.rs | 8 +-
rust/tests/tirx/op.rs | 6 +-
.../tirx/structural_map_with_constraint_context.rs | 2 +-
.../structural_mutate_with_constraint_context.rs | 2 +-
.../structural_visit_with_constraint_context.rs | 12 +-
.../structural_walk_with_constraint_context.rs | 2 +-
rust/tests/tirx/tile/dispatch.rs | 4 +-
60 files changed, 770 insertions(+), 288 deletions(-)
diff --git a/3rdparty/tvm-ffi b/3rdparty/tvm-ffi
index 34fafd9ee..5fdba0f4c 160000
--- a/3rdparty/tvm-ffi
+++ b/3rdparty/tvm-ffi
@@ -1 +1 @@
-Subproject commit 34fafd9ee80003a725851dd9adc8cd186fb0daf3
+Subproject commit 5fdba0f4c562465435ab4a860da602ab80f6820d
diff --git a/docs/ir_guides/working_with_ir_in_rust.rst
b/docs/ir_guides/working_with_ir_in_rust.rst
index 334d56146..5f7e1fd47 100644
--- a/docs/ir_guides/working_with_ir_in_rust.rst
+++ b/docs/ir_guides/working_with_ir_in_rust.rst
@@ -111,7 +111,7 @@ key constructs are:
directly, clone cheaply
* - ``.into()``
- Convert to a parent type
- * - |try_cast|_
+ * - |downcast|_
- Convert to a child type, with a checked ``Result``
* - |match_any!|_
- Branch on the node type
@@ -146,7 +146,7 @@ its type.
As in C++, the operators take a ``PrimExpr``, an expression whose type is a
``PrimType``. ``x`` is a ``PrimVar``, a variable of a primitive type, because a
plain ``Var`` may have any type: it takes part in arithmetic only after
-``downcast_ref::<PrimVar>()`` or ``try_cast::<PrimVar>()`` checks it, and
``&var + 1``
+``downcast_ref::<PrimVar>()`` or ``downcast::<PrimVar>()`` checks it, and
``&var + 1``
does not compile.
An operator can still fail, for example on mismatched types, so
@@ -162,7 +162,7 @@ Objects and Managed References
**Every node type comes as a pair: an underlying object and a named
managed reference.** The top of
``x * 2 + 1`` is an addition, so let's convert the expression to ``Add``
-with ``try_cast``, which the next subsection explains, and read its two
+with ``try_into``, which the next subsection explains, and read its two
operands:
.. literalinclude:: ../../examples/ir_guides/rust/src/lib.rs
@@ -229,9 +229,10 @@ Casts
**Casts move a managed reference up and down the type hierarchy.** A
function that takes any expression wants an ``Expr``, while reading the
operands needs an ``Add``. ``.into()`` converts to a parent type through
-``From``/``Into`` and cannot fail. ``.try_cast()`` converts to a child
-type: like ``TryFrom``, it checks the node's actual type and returns a
-``Result``.
+``From``/``Into`` and cannot fail. ``.try_into()``, or ``T::try_from``,
+converts to a child type: it checks the node's actual type and fails with a
+``TypeError`` naming both types, ready for ``?``. ``try_from(&value)``
+borrows and clones only on success.
.. literalinclude:: ../../examples/ir_guides/rust/src/lib.rs
:language: rust
@@ -248,17 +249,18 @@ The output is:
``value`` is an ``Expr`` again, but the node behind it is still an
addition, so the cast back to ``Add`` succeeds.
-What if we guess wrong? The cast to ``Mul`` returns an ``Err``, and its
-message names both type keys: the actual type ``prim.Add`` and the
-requested ``prim.Mul``.
+What if we guess wrong? The cast to ``Mul`` fails with a ``TypeError`` that
+names both type keys: the actual type ``prim.Add`` and the requested
+``prim.Mul``.
.. note::
- ``try_cast`` consumes the managed reference it converts, so we clone
- ``value`` before the first cast; the clone costs one reference-count
- increment. For read-only inspection, ``value.downcast_ref::<Add>()``
- returns ``Option<&Add>`` without consuming or cloning the reference.
- ``Any`` and ``AnyView`` provide the same borrowed downcast.
+ To try several types in turn, ``value.downcast::<Add>()`` takes the
+ reference and hands it back unchanged in ``Err``, as
+ ``Box<dyn Any>::downcast`` does in the standard library. For read-only
+ inspection, ``value.downcast_ref::<Add>()`` returns ``Option<&Add>``
+ without consuming or cloning the reference. ``Any`` and ``AnyView``
+ provide the same borrowed downcast.
Casting to one type at a time gets tedious when a node can be one of
many; that is what matching is for.
@@ -775,7 +777,7 @@ Quick Reference
- What it does
* - |match_any!|_
- Branches on the node type; the first matching arm runs
- * - |try_cast|_, |downcast_ref|_
+ * - |downcast|_, |downcast_ref|_
- Downcasts to one type, as a managed reference in a ``Result`` or a
borrowed object in an ``Option``
* - ``.into()``
@@ -813,8 +815,8 @@ Quick Reference
.. _Add: ../reference/rust/generated/tvm_tirx/ir/prim/expr/struct.Add.html
.. |script| replace:: ``script``
.. _script: ../reference/rust/generated/tvm_tirx/script/fn.script.html
-.. |try_cast| replace:: ``.try_cast()``
-.. _try_cast:
../reference/rust/generated/tvm_ffi/object/trait.ObjectRefCast.html
+.. |downcast| replace:: ``.downcast()``
+.. _downcast:
../reference/rust/generated/tvm_ffi/object/trait.ObjectRefCore.html#method.downcast
.. |structural_walk| replace:: ``structural_walk``
.. _structural_walk:
../reference/rust/generated/tvm_ffi/extra/structural_walk/fn.structural_walk.html
.. |structural_map| replace:: ``structural_map``
diff --git a/examples/extension_guides/rust/src/lib.rs
b/examples/extension_guides/rust/src/lib.rs
index 533addb7b..c99b7844a 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,
ObjectRefCast, ObjectRefCore,
- Result, Unchanged, UnchangedOr, WalkOrder,
+ self, def_object_ref, dispatch, rs_object, Any, AnyView, Error,
ObjectRefCore, Result,
+ Unchanged, UnchangedOr, WalkOrder,
};
// begin type
@@ -70,7 +70,7 @@ fn check_call(call: &CallObj, count: usize) -> Result<()> {
/// `bfloat16`.
fn float_part(ty: &Type) -> Result<PrimType> {
let elem: PrimType =
- ty.clone().try_cast().map_err(|_| type_error("expected a scalar
float"))?;
+ ty.clone().downcast().map_err(|_| type_error("expected a scalar
float"))?;
let bits = elem.dtype.bits;
let float = elem.dtype == dtype::float(bits) || elem.dtype ==
dtype::bfloat(bits);
require(float, "expected a scalar float")?;
@@ -89,13 +89,13 @@ fn infer_complex(call: &CallObj) -> Result<Type> {
// end inference
fn complex_arg(call: &CallObj, index: usize) -> Result<ComplexType> {
- let op: Op = call.op.clone().try_cast()?;
+ let op = Op::try_from(&call.op)?;
let ty: ComplexType = call
.args
.get(index)?
.ty
.clone()
- .try_cast()
+ .downcast()
.map_err(|_| type_error(&format!("{} expects a complex value",
op.name.as_str())))?;
float_part(&ty.dtype.clone().into())?;
Ok(ty)
@@ -115,7 +115,7 @@ fn infer_part(call: &CallObj) -> Result<Type> {
// Explicit result types bypass inference, so validation checks the inputs and
result again.
fn validate_call(call: &CallObj) -> Result<()> {
- let op: Op = call.op.clone().try_cast()?;
+ let op = Op::try_from(&call.op)?;
let expected = match op.name.as_str() {
"my_ext.complex" => infer_complex(call)?,
"my_ext.cmul" => infer_cmul(call)?,
diff --git a/examples/ir_guides/rust/src/lib.rs
b/examples/ir_guides/rust/src/lib.rs
index 412fd962d..21c4e7418 100644
--- a/examples/ir_guides/rust/src/lib.rs
+++ b/examples/ir_guides/rust/src/lib.rs
@@ -35,8 +35,8 @@ use
tvm_tirx::tirx::structural_walk_with_constraint_context::structural_walk_wit
use tvm_tirx::tirx::Function;
use tvm_tirx::tvm_ffi::{
self, dispatch, match_any, Any, AnyView, Array, DefRegionKind,
MutationView, ObjectIdentity,
- ObjectRefCast, ObjectRefCore, Result, StructuralMutatorView,
StructuralVisitorView, Unchanged,
- UnchangedOr, VisitInterrupt, WalkOrder, WalkResult,
+ ObjectRefCore, Result, StructuralMutatorView, StructuralVisitorView,
Unchanged, UnchangedOr,
+ VisitInterrupt, WalkOrder, WalkResult,
};
/// A Python list of strings.
@@ -63,7 +63,7 @@ fn construct() -> Result<tvm_ffi::String> {
// [objects.begin]
fn objects() -> Result<Strings> {
let (_, expr) = x_times_2_plus_1()?;
- let add: Add = expr.try_cast()?;
+ let add: Add = expr.try_into()?;
let alias = add.clone();
Ok(lines([
format!("a = {}", script(&add.a)?.as_str()),
@@ -76,11 +76,12 @@ fn objects() -> Result<Strings> {
// [casts.begin]
fn casts() -> Result<Strings> {
let (_, expr) = x_times_2_plus_1()?;
- let add: Add = expr.try_cast()?;
+ let add: Add = expr.try_into()?;
let value: Expr = add.into();
- let again: Add = value.clone().try_cast()?;
+ let again = Add::try_from(&value)?;
let mut out = vec![format!("back to Add: {}", script(&again)?.as_str())];
- if let Err(err) = value.try_cast::<Mul>() {
+ // A wrong guess is a `TypeError` naming both types.
+ if let Err(err) = Mul::try_from(&value) {
out.push(format!("as Mul: {}", err.message()));
}
Ok(lines(out))
@@ -151,7 +152,7 @@ fn print() -> Result<tvm_ffi::String> {
fn written_tensors(func: Function) -> Result<Strings> {
let mut writes = Vec::new();
let on_store = |store: TensorStore| -> Result<WalkResult> {
- let dest: Var = store.dest.clone().try_cast()?;
+ let dest = Var::try_from(&store.dest)?;
writes.push(dest.name.clone());
Ok(WalkResult::Advance)
};
@@ -175,7 +176,7 @@ fn first_write(func: Function) ->
Result<Option<TensorStore>> {
fn specialize(func: Function, n: Var, value: i64) -> Result<Function> {
let specialize_var = |var: Var| -> Result<Expr> {
if var.same_as(&n) {
- let ty: PrimType = var.ty.clone().try_cast()?;
+ let ty = PrimType::try_from(&var.ty)?;
return Ok(make_const(ty, value)?.into());
}
Ok(var.into())
diff --git a/include/tvm/ir/module.h b/include/tvm/ir/module.h
index dcb417482..ca3cb2738 100644
--- a/include/tvm/ir/module.h
+++ b/include/tvm/ir/module.h
@@ -278,6 +278,8 @@ class IRModuleObj : public ffi::Object {
static constexpr TVMFFISEqHashKind _type_s_eq_hash_kind =
kTVMFFISEqHashKindTreeNode;
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("ir.IRModule", IRModuleObj, ffi::Object);
+ // Shared instances are mutated in place, so the class is mutable.
+ static constexpr bool _type_mutable = true;
private:
friend class IRModule;
diff --git a/include/tvm/ir/transform.h b/include/tvm/ir/transform.h
index 27fe8f922..2ce1d5915 100644
--- a/include/tvm/ir/transform.h
+++ b/include/tvm/ir/transform.h
@@ -663,6 +663,8 @@ class PassContextObj : public ffi::Object {
.def_ro("config", &PassContextObj::config);
}
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("transform.PassContext", PassContextObj,
ffi::Object);
+ // Shared instances are mutated in place, so the class is mutable.
+ static constexpr bool _type_mutable = true;
};
inline PassContext::PassContext(ffi::UnsafeInit tag,
ffi::ObjectPtr<PassContextObj> n)
diff --git a/include/tvm/sym/iter_affine_map.h
b/include/tvm/sym/iter_affine_map.h
index 4ad3c4374..182253f61 100644
--- a/include/tvm/sym/iter_affine_map.h
+++ b/include/tvm/sym/iter_affine_map.h
@@ -300,6 +300,8 @@ class IterMapResultObj : public ffi::Object {
.def_ro("padding_predicate", &IterMapResultObj::padding_predicate);
}
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("sym.IterMapResult", IterMapResultObj,
ffi::Object);
+ // Shared instances are mutated in place, so the class is mutable.
+ static constexpr bool _type_mutable = true;
};
/*!
diff --git a/include/tvm/target/target.h b/include/tvm/target/target.h
index 7843098fb..b6d4cc343 100644
--- a/include/tvm/target/target.h
+++ b/include/tvm/target/target.h
@@ -145,6 +145,8 @@ class TargetObj : public ffi::Object {
static constexpr TVMFFISEqHashKind _type_s_eq_hash_kind =
kTVMFFISEqHashKindTreeNode;
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("target.Target", TargetObj, ffi::Object);
+ // Shared instances are mutated in place, so the class is mutable.
+ static constexpr bool _type_mutable = true;
private:
/*! \brief Internal string repr. */
diff --git a/include/tvm/target/target_kind.h b/include/tvm/target/target_kind.h
index e5c9a104a..91929229a 100644
--- a/include/tvm/target/target_kind.h
+++ b/include/tvm/target/target_kind.h
@@ -70,6 +70,8 @@ class TargetKindObj : public ffi::Object {
static constexpr TVMFFISEqHashKind _type_s_eq_hash_kind =
kTVMFFISEqHashKindUniqueInstance;
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("target.TargetKind", TargetKindObj,
ffi::Object);
+ // Shared instances are mutated in place, so the class is mutable.
+ static constexpr bool _type_mutable = true;
private:
/*! \brief ConfigSchema for validating and resolving target attributes */
diff --git a/rust/examples/define_ir.rs b/rust/examples/define_ir.rs
index f3a7a1398..3e0a308ed 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, ObjectRefCast,
Result};
+use tvm_tirx::tvm_ffi::{self, def_object_ref, rs_object, Array, Result};
fn first_arg_type(call: &CallObj) -> Result<Type> {
Ok(call.args.get(0)?.ty.clone())
@@ -42,7 +42,7 @@ fn first_arg_type(call: &CallObj) -> Result<Type> {
/// The variable a loop binds in its body: an index of the extent's type.
fn loop_index(call: &CallObj) -> Result<Array<Var>> {
- let ty: PrimType = call.args.get(0)?.ty.clone().try_cast()?;
+ let ty: PrimType = PrimType::try_from(&call.args.get(0)?.ty)?;
Ok(Array::from_vec(vec![Var::new("i", ty, UNKNOWN_LOC)]))
}
diff --git a/rust/src/backend/cuda/op.rs b/rust/src/backend/cuda/op.rs
index 8477e040a..2717fd4d9 100644
--- a/rust/src/backend/cuda/op.rs
+++ b/rust/src/backend/cuda/op.rs
@@ -156,7 +156,11 @@ impl TCGen05InstrDescriptorAttrs {
}
}
-tvm_ffi::impl_object_upcast!(TCGen05InstrDescriptorAttrs => Attrs);
+// SAFETY: `tirx.cuda.TCGen05InstrDescriptorAttrs` is not `_type_mutable`: a
shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for
TCGen05InstrDescriptorAttrsObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(TCGen05InstrDescriptorAttrs => Attrs);
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin):
object/tirx.cuda.TCGen05InstrDescriptorBlockScaledAttrs
@@ -287,7 +291,11 @@ impl TCGen05InstrDescriptorBlockScaledAttrs {
}
}
-tvm_ffi::impl_object_upcast!(TCGen05InstrDescriptorBlockScaledAttrs => Attrs);
+// SAFETY: `tirx.cuda.TCGen05InstrDescriptorBlockScaledAttrs` is not
`_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for
TCGen05InstrDescriptorBlockScaledAttrsObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(TCGen05InstrDescriptorBlockScaledAttrs =>
Attrs);
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/tirx.cuda.TensorMapEncodeTiledAttr
@@ -380,5 +388,9 @@ impl TensorMapEncodeTiledAttr {
}
}
-tvm_ffi::impl_object_upcast!(TensorMapEncodeTiledAttr => Attrs);
+// SAFETY: `tirx.cuda.TensorMapEncodeTiledAttr` is not `_type_mutable`: a
shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for TensorMapEncodeTiledAttrObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(TensorMapEncodeTiledAttr => Attrs);
// tvm-ffi-stubgen(end)
diff --git a/rust/src/codegen.rs b/rust/src/codegen.rs
index 106f96d43..b4004ba9c 100644
--- a/rust/src/codegen.rs
+++ b/rust/src/codegen.rs
@@ -68,7 +68,7 @@ use tvm_ffi::String;
/// let module = IRModule::from_functions(&functions, None, &Map::new())?;
///
/// let compiled = codegen::build_module(&module, Target::new("c")?)?;
-/// assert!(compiled.implements_function("add_one", true)?);
+/// assert!(compiled.implements_function_with_imports("add_one")?);
/// # Ok::<(), tvm_tirx::tvm_ffi::Error>(())
/// ```
pub fn build_module(module: impl Into<IRModule>, target: impl Into<Target>) ->
Result<Module> {
diff --git a/rust/src/ir/attrs.rs b/rust/src/ir/attrs.rs
index bb4b6fcee..28a17eb32 100644
--- a/rust/src/ir/attrs.rs
+++ b/rust/src/ir/attrs.rs
@@ -34,7 +34,7 @@
//! let module = IRModule::from_functions(&Map::new(),
Some(&DictAttrs::new(dict)), &Map::new())?;
//!
//! let prefix = module.attrs.dict.get(&"system_lib_prefix".into())?.unwrap();
-//! assert_eq!(prefix.try_as::<String>().unwrap(), "my_lib_");
+//! assert_eq!(String::try_from(prefix)?, "my_lib_");
//! # Ok::<(), tvm_tirx::tvm_ffi::Error>(())
//! ```
@@ -105,6 +105,10 @@ unsafe impl UnsafeInit for AttrsObj {
}
}
}
+
+// SAFETY: `ir.Attrs` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for AttrsObj {}
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/ir.DictAttrs
@@ -158,5 +162,9 @@ impl DictAttrs {
}
}
-tvm_ffi::impl_object_upcast!(DictAttrs => Attrs);
+// SAFETY: `ir.DictAttrs` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for DictAttrsObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(DictAttrs => Attrs);
// tvm-ffi-stubgen(end)
diff --git a/rust/src/ir/base.rs b/rust/src/ir/base.rs
index 02f0d1124..b375d3941 100644
--- a/rust/src/ir/base.rs
+++ b/rust/src/ir/base.rs
@@ -33,7 +33,7 @@
//! # Function::register_global("my_ext.double", double)?;
//! let double = EnvFunc::new("my_ext.double",
Function::get_global("my_ext.double")?);
//!
-//! assert_eq!(double.func.call_tuple((21_i64,))?.try_as::<i64>(), Some(42));
+//! assert_eq!(i64::try_from(double.func.call_tuple((21_i64,))?)?, 42);
//! # Ok::<(), tvm_tirx::tvm_ffi::Error>(())
//! ```
@@ -89,4 +89,8 @@ impl EnvFunc {
Self { base: ObjectArc::new(obj) }
}
}
+
+// SAFETY: `ir.EnvFunc` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for EnvFuncObj {}
// tvm-ffi-stubgen(end)
diff --git a/rust/src/ir/expr.rs b/rust/src/ir/expr.rs
index 4d027b2a5..27021fb70 100644
--- a/rust/src/ir/expr.rs
+++ b/rust/src/ir/expr.rs
@@ -74,12 +74,11 @@
// tvm-ffi-stubgen(import-object): crate::ir::prim::op::ExprResult
// tvm-ffi-stubgen(import-object): crate::ir::r#type::PrimTypeObj
// tvm-ffi-stubgen(import-object): tvm_ffi::Error
-// tvm-ffi-stubgen(import-object): tvm_ffi::ObjectRefCast
+// tvm-ffi-stubgen(import-object): tvm_ffi::ObjectRefCore
// tvm-ffi-stubgen(import-object): tvm_ffi::object::is_instance_of
// tvm-ffi-stubgen(import-object): tvm_ffi::tvm_ffi_sys::TVMFFIAny
// tvm-ffi-stubgen(import-object): tvm_ffi::type_traits::AnyCompatible
// tvm-ffi-stubgen(import-object): tvm_ffi::AnyView
-// tvm-ffi-stubgen(import-object): tvm_ffi::ObjectRefCore
// tvm-ffi-stubgen(import-object): tvm_ffi::Result
// tvm-ffi-stubgen(import-object): tvm_ffi::tvm_ffi_sys::TVMFFITypeIndex
// tvm-ffi-stubgen(import-object): crate::ir::location::UNKNOWN_LOC
@@ -130,7 +129,6 @@ use tvm_ffi::DLDataType;
use tvm_ffi::Error;
use tvm_ffi::Object;
use tvm_ffi::ObjectArc;
-use tvm_ffi::ObjectRefCast;
use tvm_ffi::ObjectRefCore;
use tvm_ffi::Result;
use tvm_ffi::ShallowCopy;
@@ -207,6 +205,10 @@ unsafe impl UnsafeInit for ExprObj {
}
}
}
+
+// SAFETY: `ir.Expr` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for ExprObj {}
// tvm-ffi-stubgen(end)
/// An index of [`Expr::subscript`]: an expression, or a `start:stop:step`
slice.
@@ -265,7 +267,7 @@ impl Expr {
/// `IntoObjectRef<T>` is an `IntoExpr<T>`, so a new expression type converts
into each type it
/// upcasts to without a list to maintain. The conversion never checks a type:
an [`Expr`] or a
/// [`Var`] is not a `PrimExpr` until it is checked, as in C++, by
`downcast_ref`, which borrows it
-/// in place (C++ `as`), or `try_cast`, which takes it (C++ `as_or_throw`).
Its one error is the
+/// in place (C++ `as`), or `downcast`, which takes it (C++ `as_or_throw`).
Its one error is the
/// first error an [`ExprResult`] operand raised.
///
/// # Examples
@@ -450,30 +452,14 @@ crate::r#macro::typed_expr_view! {
mismatch = typed_expr_mismatch, fallback = int_literal
}
-tvm_ffi::impl_object_upcast!(PrimExpr => Expr, IntExpr => Expr, IntExpr =>
PrimExpr);
-
-impl TryFrom<PrimExpr> for IntExpr {
- type Error = Error;
-
- fn try_from(value: PrimExpr) -> Result<Self> {
- value.try_cast()
- }
-}
-
-impl TryFrom<&PrimExpr> for IntExpr {
- type Error = Error;
-
- fn try_from(value: &PrimExpr) -> Result<Self> {
- value.clone().try_cast()
- }
-}
+tvm_ffi::unsafe_impl_object_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 {
type Error = Error;
fn try_from(value: ExprResult) -> Result<Self> {
- PrimExpr::try_from(value)?.try_cast()
+ PrimExpr::try_from(value)?.try_into()
}
}
@@ -728,7 +714,11 @@ unsafe impl UnsafeInit for StagingExprObj {
}
}
-tvm_ffi::impl_object_upcast!(StagingExpr => Expr);
+// SAFETY: `ir.StagingExpr` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for StagingExprObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(StagingExpr => Expr);
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/ir.OpaqueExpr
@@ -794,7 +784,11 @@ unsafe impl UnsafeInit for OpaqueExprObj {
}
}
-tvm_ffi::impl_object_upcast!(OpaqueExpr => Expr);
+// SAFETY: `ir.OpaqueExpr` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for OpaqueExprObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(OpaqueExpr => Expr);
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/ir.GlobalVar
@@ -852,7 +846,11 @@ impl GlobalVar {
}
}
-tvm_ffi::impl_object_upcast!(GlobalVar => Expr);
+// SAFETY: `ir.GlobalVar` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for GlobalVarObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(GlobalVar => Expr);
// tvm-ffi-stubgen(end)
impl GlobalVar {
@@ -918,7 +916,11 @@ impl Tuple {
}
}
-tvm_ffi::impl_object_upcast!(Tuple => Expr);
+// SAFETY: `ir.Tuple` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for TupleObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Tuple => Expr);
// tvm-ffi-stubgen(end)
impl Tuple {
@@ -998,7 +1000,11 @@ impl TupleGetItem {
}
}
-tvm_ffi::impl_object_upcast!(TupleGetItem => Expr);
+// SAFETY: `ir.TupleGetItem` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for TupleGetItemObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(TupleGetItem => Expr);
// tvm-ffi-stubgen(end)
impl TupleGetItem {
@@ -1108,7 +1114,11 @@ impl TensorLoad {
}
}
-tvm_ffi::impl_object_upcast!(TensorLoad => Expr, TensorLoad => PrimExpr);
+// SAFETY: `ir.TensorLoad` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for TensorLoadObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(TensorLoad => Expr, TensorLoad =>
PrimExpr);
// tvm-ffi-stubgen(end)
impl TensorLoad {
@@ -1210,7 +1220,11 @@ unsafe impl UnsafeInit for ConstantObj {
}
}
-tvm_ffi::impl_object_upcast!(Constant => Expr);
+// SAFETY: `ir.Constant` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for ConstantObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Constant => Expr);
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/ir.FloatImm
@@ -1264,7 +1278,11 @@ impl FloatImm {
}
}
-tvm_ffi::impl_object_upcast!(FloatImm => Expr, FloatImm => Constant, FloatImm
=> PrimExpr);
+// SAFETY: `ir.FloatImm` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for FloatImmObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(FloatImm => Expr, FloatImm => Constant,
FloatImm => PrimExpr);
// tvm-ffi-stubgen(end)
impl FloatImm {
@@ -1462,7 +1480,11 @@ impl IntImm {
}
}
-tvm_ffi::impl_object_upcast!(IntImm => Expr, IntImm => Constant, IntImm =>
PrimExpr);
+// SAFETY: `ir.IntImm` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for IntImmObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(IntImm => Expr, IntImm => Constant, IntImm
=> PrimExpr);
// tvm-ffi-stubgen(end)
impl IntImm {
@@ -1661,7 +1683,11 @@ impl GenericConst {
}
}
-tvm_ffi::impl_object_upcast!(GenericConst => Expr, GenericConst => Constant);
+// SAFETY: `ir.GenericConst` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for GenericConstObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(GenericConst => Expr, GenericConst =>
Constant);
// tvm-ffi-stubgen(end)
impl GenericConst {
@@ -1754,7 +1780,11 @@ impl DataTypeImm {
}
}
-tvm_ffi::impl_object_upcast!(DataTypeImm => Expr, DataTypeImm => Constant);
+// SAFETY: `ir.DataTypeImm` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for DataTypeImmObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(DataTypeImm => Expr, DataTypeImm =>
Constant);
// tvm-ffi-stubgen(end)
impl DataTypeImm {
@@ -1821,7 +1851,11 @@ impl StringImm {
}
}
-tvm_ffi::impl_object_upcast!(StringImm => Expr, StringImm => Constant);
+// SAFETY: `ir.StringImm` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for StringImmObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(StringImm => Expr, StringImm => Constant);
// tvm-ffi-stubgen(end)
impl StringImm {
@@ -1907,7 +1941,11 @@ impl Call {
}
}
-tvm_ffi::impl_object_upcast!(Call => Expr);
+// SAFETY: `ir.Call` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for CallObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Call => Expr);
// tvm-ffi-stubgen(end)
impl Call {
@@ -2042,7 +2080,11 @@ impl TensorRegion {
}
}
-tvm_ffi::impl_object_upcast!(TensorRegion => Expr);
+// SAFETY: `ir.TensorRegion` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for TensorRegionObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(TensorRegion => Expr);
// tvm-ffi-stubgen(end)
impl TensorRegion {
@@ -2127,7 +2169,11 @@ unsafe impl UnsafeInit for VarObj {
}
}
-tvm_ffi::impl_object_upcast!(Var => Expr);
+// SAFETY: `ir.Var` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for VarObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Var => Expr);
// tvm-ffi-stubgen(end)
impl Var {
@@ -2144,7 +2190,7 @@ crate::r#macro::typed_expr_view! {
///
/// A `PrimVar` is a view of a `Var`, as [`PrimExpr`] is of an `Expr`:
[`PrimVar::new`] types it
/// by a `PrimType`, and a `Var` becomes one only through the check of C++
`PrimVar`, by
- /// `downcast_ref`, which borrows it in place, or `try_cast`, which takes
it. It converts into a
+ /// `downcast_ref`, which borrows it in place, or `downcast`, which takes
it. It converts into a
/// `Var`, a `PrimExpr` and an `Expr` for free, and reads the variable
through `Deref`.
///
/// # Examples
@@ -2152,7 +2198,7 @@ crate::r#macro::typed_expr_view! {
/// ```
/// use tvm_tirx::ir::{MissingType, PrimExpr, PrimType, PrimVar, Var,
UNKNOWN_LOC};
/// use tvm_tirx::script::script;
- /// use tvm_tirx::tvm_ffi::{ObjectRefCast, ObjectRefCore};
+ /// use tvm_tirx::tvm_ffi::{ObjectRefCore};
///
/// let i = PrimVar::new("i", PrimType::int(32), UNKNOWN_LOC);
/// assert_eq!(i.name.as_str(), "i");
@@ -2161,7 +2207,7 @@ crate::r#macro::typed_expr_view! {
/// let var: Var = i.into();
/// assert!(var.downcast_ref::<PrimVar>().is_some());
/// let untyped = Var::new("u", MissingType::new(), UNKNOWN_LOC);
- /// assert!(untyped.try_cast::<PrimVar>().is_err());
+ /// assert!(untyped.downcast::<PrimVar>().is_err());
/// # Ok::<(), tvm_tirx::tvm_ffi::Error>(())
/// ```
///
@@ -2176,7 +2222,7 @@ crate::r#macro::typed_expr_view! {
fallback = no_literal
}
-tvm_ffi::impl_object_upcast!(PrimVar => Expr, PrimVar => Var, PrimVar =>
PrimExpr);
+tvm_ffi::unsafe_impl_object_upcast!(PrimVar => Expr, PrimVar => Var, PrimVar
=> PrimExpr);
impl PrimVar {
/// Create the variable `name` of the primitive type `ty` (C++
`PrimVar(name, ty, loc)`).
@@ -2244,7 +2290,11 @@ impl LambdaExpr {
}
}
-tvm_ffi::impl_object_upcast!(LambdaExpr => Expr, LambdaExpr => StagingExpr);
+// SAFETY: `ir.LambdaExpr` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for LambdaExprObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(LambdaExpr => Expr, LambdaExpr =>
StagingExpr);
// tvm-ffi-stubgen(end)
impl LambdaExpr {
@@ -2326,6 +2376,10 @@ impl Range {
Self { base: ObjectArc::new(obj) }
}
}
+
+// SAFETY: `ir.Range` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for RangeObj {}
// tvm-ffi-stubgen(end)
impl Range {
@@ -2377,7 +2431,7 @@ impl Range {
// The operators apply to the expressions typed by a `PrimType`, the subtypes
of `PrimExpr`, as the
// C++ operators take `PrimExpr`; the typed views get theirs from
`typed_expr_view!`. An `Expr`, a
-// `Var` or a `Call` is checked first, with `downcast_ref` or `try_cast`.
+// `Var` or a `Call` is checked first, with `downcast_ref` or `downcast`.
crate::def_expr_op_over_loads!(IntImm);
crate::def_expr_op_over_loads!(FloatImm);
crate::def_expr_op_over_loads!(TensorLoad);
diff --git a/rust/src/ir/function.rs b/rust/src/ir/function.rs
index c0c31ae9f..447176f57 100644
--- a/rust/src/ir/function.rs
+++ b/rust/src/ir/function.rs
@@ -134,7 +134,11 @@ unsafe impl UnsafeInit for BaseFuncObj {
}
}
-tvm_ffi::impl_object_upcast!(BaseFunc => Expr);
+// SAFETY: `ir.BaseFunc` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for BaseFuncObj {}
+
+tvm_ffi::unsafe_impl_object_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 c4815bf20..d632355f6 100644
--- a/rust/src/ir/global_info.rs
+++ b/rust/src/ir/global_info.rs
@@ -87,4 +87,8 @@ unsafe impl UnsafeInit for GlobalInfoObj {
}
}
}
+
+// SAFETY: `ir.GlobalInfo` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for GlobalInfoObj {}
// tvm-ffi-stubgen(end)
diff --git a/rust/src/ir/location.rs b/rust/src/ir/location.rs
index 5d278e2a6..9d24336cd 100644
--- a/rust/src/ir/location.rs
+++ b/rust/src/ir/location.rs
@@ -111,6 +111,10 @@ unsafe impl UnsafeInit for LocationObj {
}
}
}
+
+// SAFETY: `ir.Location` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for LocationObj {}
// tvm-ffi-stubgen(end)
impl Location {
@@ -171,7 +175,11 @@ impl UnknownLoc {
}
}
-tvm_ffi::impl_object_upcast!(UnknownLoc => Location);
+// SAFETY: `ir.UnknownLoc` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for UnknownLocObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(UnknownLoc => Location);
// tvm-ffi-stubgen(end)
impl UnknownLoc {
@@ -271,7 +279,11 @@ impl SourceLoc {
}
}
-tvm_ffi::impl_object_upcast!(SourceLoc => Location);
+// SAFETY: `ir.SourceLoc` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for SourceLocObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(SourceLoc => Location);
// tvm-ffi-stubgen(end)
// `ir.SourceLoc` stores its arguments as given: the generated
`SourceLoc::new` is the same.
@@ -328,7 +340,11 @@ impl CallSiteLoc {
}
}
-tvm_ffi::impl_object_upcast!(CallSiteLoc => Location);
+// SAFETY: `ir.CallSiteLoc` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for CallSiteLocObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(CallSiteLoc => Location);
// tvm-ffi-stubgen(end)
// `ir.CallSiteLoc` stores its arguments as given: the generated
`CallSiteLoc::new` is the same.
@@ -376,6 +392,10 @@ impl SourceName {
Self { base: ObjectArc::new(obj) }
}
}
+
+// SAFETY: `ir.SourceName` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for SourceNameObj {}
// tvm-ffi-stubgen(end)
impl SourceName {
diff --git a/rust/src/ir/op.rs b/rust/src/ir/op.rs
index 9e3914171..a6a452e06 100644
--- a/rust/src/ir/op.rs
+++ b/rust/src/ir/op.rs
@@ -99,7 +99,7 @@ pub struct OpObj {
/// The type key of the operator's `Call.attrs`, or empty when it declares
none.
pub attrs_type_key: String,
attrs_type_index: u32,
- validator: Any,
+ validator: ValidatorCell,
validator_is_custom: bool,
}
@@ -119,6 +119,20 @@ const _: () = {
assert!(::core::mem::offset_of!(OpObj, validator_is_custom) == 152);
};
+// SAFETY: `ir.Op` is not `_type_mutable`: registration finishes initializing
an entry, and a
+// shared one is never mutated after.
+unsafe impl tvm_ffi::object::ImmutableObject for OpObj {}
+
+/// The validator slot of an operator: an opaque pointer to a C ABI adapter,
written while the
+/// operator is registered and only read after, so it may be shared as the
rest of `OpObj` is.
+#[repr(transparent)]
+struct ValidatorCell(Any);
+
+// SAFETY: the cell is written only during registration, which counts as
initialization (as for
+// the rest of `OpObj`), and holds a native function pointer that is safe to
call from any thread.
+unsafe impl Send for ValidatorCell {}
+unsafe impl Sync for ValidatorCell {}
+
/// A registered operator, the callee of a [`Call`](crate::ir::Call) to it.
///
/// The registry keeps one object per name, so `call.op.same_as(&op)` tests
whether a call is to
@@ -153,7 +167,7 @@ impl OpObj {
/// Return the validator that
[`Call::validate`](crate::ir::Call::validate) runs: a native
/// function pointer, a packed function, or `None`.
pub fn validator(&self) -> &Any {
- &self.validator
+ &self.validator.0
}
/// Return whether the validator was set with
@@ -241,15 +255,18 @@ impl Op {
// SAFETY: C++ `OpDef` writes these members of the registry's node in
place too. No
// reference into the node is live, and registration is not
synchronized with readers.
unsafe {
- let node = ObjectArc::as_raw(ObjectRefCore::data(self)) as *mut
OpObj;
- let previous =
std::ptr::replace(std::ptr::addr_of_mut!((*node).validator), validator);
+ let node = ObjectArc::as_ptr(ObjectRefCore::data(self)) as *mut
OpObj;
+ let previous = std::ptr::replace(
+ std::ptr::addr_of_mut!((*node).validator),
+ ValidatorCell(validator),
+ );
std::ptr::addr_of_mut!((*node).validator_is_custom).write(custom);
drop(previous);
}
}
}
-tvm_ffi::impl_object_upcast!(Op => Expr);
+tvm_ffi::unsafe_impl_object_upcast!(Op => Expr);
// tvm-ffi-stubgen(begin): object/ir.ArgumentInfo
/// Complete: reflected fields fill [24, 56) exactly.
@@ -295,6 +312,10 @@ impl ArgumentInfo {
Self { base: ObjectArc::new(obj) }
}
}
+
+// SAFETY: `ir.ArgumentInfo` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for ArgumentInfoObj {}
// tvm-ffi-stubgen(end)
// The crate has no `ffi.List` binding, so the column is read through the
`TVMFFISeqCell` that
@@ -317,7 +338,7 @@ impl<T> OpAttrMap<T> {
// The cell is read on every lookup because growth may move the
element buffer.
let cell = unsafe {
let data = tvm_ffi::object::ObjectRefCore::data(&self.column);
- &*(ObjectArc::as_raw(data) as *const support::SeqCell)
+ &*(ObjectArc::as_ptr(data) as *const support::SeqCell)
};
let index = op.index as usize;
if index >= cell.size as usize {
diff --git a/rust/src/ir/op_def.rs b/rust/src/ir/op_def.rs
index 6f70a46bf..6fb4c8366 100644
--- a/rust/src/ir/op_def.rs
+++ b/rust/src/ir/op_def.rs
@@ -240,7 +240,7 @@ impl OpDef {
self.then(|op| {
let packed: Vec<AnyView> =
std::iter::once(AnyView::from(op)).chain(args.iter().copied()).collect();
- tvm_ffi::Function::from_type_key_method("ir.Op",
method)?.call_packed(&packed)?;
+ tvm_ffi::reflection::get_method("ir.Op",
method)?.call_packed(&packed)?;
Ok(())
})
}
@@ -427,10 +427,10 @@ fn call_hook<N, R: Into<Any>>(node: *const N, hook: impl
Fn(&N) -> Result<R>) ->
let value = match result {
Ok(Ok(value)) => value,
Ok(Err(error)) => Any::from(error),
- Err(payload) =>
Any::from(tvm_ffi::function_internal::panic_to_error(payload)),
+ Err(payload) => Any::from(tvm_ffi::Error::from_panic(payload)),
};
- // SAFETY: the C++ caller takes ownership of the value.
- unsafe { Any::into_raw_ffi_any(value) }
+ // The C++ caller takes ownership of the value.
+ Any::into_raw_ffi_any(value)
}
/// Signature descriptors for [`OpDef::signature`], C++ `sig::arg<T>` and
friends.
diff --git a/rust/src/ir/prim/expr.rs b/rust/src/ir/prim/expr.rs
index 28bc94ad2..3b176d98a 100644
--- a/rust/src/ir/prim/expr.rs
+++ b/rust/src/ir/prim/expr.rs
@@ -363,7 +363,11 @@ impl Cast {
}
}
-tvm_ffi::impl_object_upcast!(Cast => Expr, Cast => PrimExpr);
+// SAFETY: `prim.Cast` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for CastObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Cast => Expr, Cast => PrimExpr);
// tvm-ffi-stubgen(end)
impl Cast {
@@ -449,7 +453,11 @@ impl LShift {
}
}
-tvm_ffi::impl_object_upcast!(LShift => Expr, LShift => PrimExpr);
+// SAFETY: `prim.LShift` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for LShiftObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(LShift => Expr, LShift => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -515,7 +523,11 @@ impl RShift {
}
}
-tvm_ffi::impl_object_upcast!(RShift => Expr, RShift => PrimExpr);
+// SAFETY: `prim.RShift` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for RShiftObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(RShift => Expr, RShift => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -581,7 +593,11 @@ impl BitwiseAnd {
}
}
-tvm_ffi::impl_object_upcast!(BitwiseAnd => Expr, BitwiseAnd => PrimExpr);
+// SAFETY: `prim.BitwiseAnd` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for BitwiseAndObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(BitwiseAnd => Expr, BitwiseAnd =>
PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -647,7 +663,11 @@ impl BitwiseOr {
}
}
-tvm_ffi::impl_object_upcast!(BitwiseOr => Expr, BitwiseOr => PrimExpr);
+// SAFETY: `prim.BitwiseOr` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for BitwiseOrObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(BitwiseOr => Expr, BitwiseOr => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -713,7 +733,11 @@ impl BitwiseXor {
}
}
-tvm_ffi::impl_object_upcast!(BitwiseXor => Expr, BitwiseXor => PrimExpr);
+// SAFETY: `prim.BitwiseXor` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for BitwiseXorObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(BitwiseXor => Expr, BitwiseXor =>
PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -777,7 +801,11 @@ impl BitwiseNot {
}
}
-tvm_ffi::impl_object_upcast!(BitwiseNot => Expr, BitwiseNot => PrimExpr);
+// SAFETY: `prim.BitwiseNot` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for BitwiseNotObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(BitwiseNot => Expr, BitwiseNot =>
PrimExpr);
// tvm-ffi-stubgen(end)
impl BitwiseNot {
@@ -858,7 +886,11 @@ impl Add {
}
}
-tvm_ffi::impl_object_upcast!(Add => Expr, Add => PrimExpr);
+// SAFETY: `prim.Add` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for AddObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Add => Expr, Add => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -923,7 +955,11 @@ impl Sub {
}
}
-tvm_ffi::impl_object_upcast!(Sub => Expr, Sub => PrimExpr);
+// SAFETY: `prim.Sub` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for SubObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Sub => Expr, Sub => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -988,7 +1024,11 @@ impl Mul {
}
}
-tvm_ffi::impl_object_upcast!(Mul => Expr, Mul => PrimExpr);
+// SAFETY: `prim.Mul` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for MulObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Mul => Expr, Mul => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -1053,7 +1093,11 @@ impl Div {
}
}
-tvm_ffi::impl_object_upcast!(Div => Expr, Div => PrimExpr);
+// SAFETY: `prim.Div` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for DivObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Div => Expr, Div => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -1118,7 +1162,11 @@ impl Mod {
}
}
-tvm_ffi::impl_object_upcast!(Mod => Expr, Mod => PrimExpr);
+// SAFETY: `prim.Mod` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for ModObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Mod => Expr, Mod => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -1183,7 +1231,11 @@ impl FloorDiv {
}
}
-tvm_ffi::impl_object_upcast!(FloorDiv => Expr, FloorDiv => PrimExpr);
+// SAFETY: `prim.FloorDiv` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for FloorDivObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(FloorDiv => Expr, FloorDiv => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -1249,7 +1301,11 @@ impl FloorMod {
}
}
-tvm_ffi::impl_object_upcast!(FloorMod => Expr, FloorMod => PrimExpr);
+// SAFETY: `prim.FloorMod` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for FloorModObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(FloorMod => Expr, FloorMod => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -1315,7 +1371,11 @@ impl Min {
}
}
-tvm_ffi::impl_object_upcast!(Min => Expr, Min => PrimExpr);
+// SAFETY: `prim.Min` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for MinObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Min => Expr, Min => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -1380,7 +1440,11 @@ impl Max {
}
}
-tvm_ffi::impl_object_upcast!(Max => Expr, Max => PrimExpr);
+// SAFETY: `prim.Max` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for MaxObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Max => Expr, Max => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -1448,7 +1512,11 @@ impl EQ {
}
}
-tvm_ffi::impl_object_upcast!(EQ => Expr, EQ => PrimExpr);
+// SAFETY: `prim.EQ` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for EQObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(EQ => Expr, EQ => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -1514,7 +1582,11 @@ impl NE {
}
}
-tvm_ffi::impl_object_upcast!(NE => Expr, NE => PrimExpr);
+// SAFETY: `prim.NE` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for NEObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(NE => Expr, NE => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -1580,7 +1652,11 @@ impl LT {
}
}
-tvm_ffi::impl_object_upcast!(LT => Expr, LT => PrimExpr);
+// SAFETY: `prim.LT` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for LTObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(LT => Expr, LT => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -1646,7 +1722,11 @@ impl LE {
}
}
-tvm_ffi::impl_object_upcast!(LE => Expr, LE => PrimExpr);
+// SAFETY: `prim.LE` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for LEObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(LE => Expr, LE => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -1712,7 +1792,11 @@ impl GT {
}
}
-tvm_ffi::impl_object_upcast!(GT => Expr, GT => PrimExpr);
+// SAFETY: `prim.GT` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for GTObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(GT => Expr, GT => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -1778,7 +1862,11 @@ impl GE {
}
}
-tvm_ffi::impl_object_upcast!(GE => Expr, GE => PrimExpr);
+// SAFETY: `prim.GE` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for GEObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(GE => Expr, GE => PrimExpr);
// tvm-ffi-stubgen(end)
binary_new! {
@@ -1847,7 +1935,11 @@ impl And {
}
}
-tvm_ffi::impl_object_upcast!(And => Expr, And => PrimExpr);
+// SAFETY: `prim.And` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for AndObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(And => Expr, And => PrimExpr);
// tvm-ffi-stubgen(end)
impl And {
@@ -1925,7 +2017,11 @@ impl Or {
}
}
-tvm_ffi::impl_object_upcast!(Or => Expr, Or => PrimExpr);
+// SAFETY: `prim.Or` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for OrObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Or => Expr, Or => PrimExpr);
// tvm-ffi-stubgen(end)
impl Or {
@@ -2001,7 +2097,11 @@ impl Not {
}
}
-tvm_ffi::impl_object_upcast!(Not => Expr, Not => PrimExpr);
+// SAFETY: `prim.Not` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for NotObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Not => Expr, Not => PrimExpr);
// tvm-ffi-stubgen(end)
impl Not {
@@ -2095,7 +2195,11 @@ impl Select {
}
}
-tvm_ffi::impl_object_upcast!(Select => Expr, Select => PrimExpr);
+// SAFETY: `prim.Select` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for SelectObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Select => Expr, Select => PrimExpr);
// tvm-ffi-stubgen(end)
impl Select {
@@ -2220,7 +2324,11 @@ impl Let {
}
}
-tvm_ffi::impl_object_upcast!(Let => Expr, Let => PrimExpr);
+// SAFETY: `prim.Let` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for LetObj {}
+
+tvm_ffi::unsafe_impl_object_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 cf894924e..10c6c4088 100644
--- a/rust/src/ir/prim/vector_expr.rs
+++ b/rust/src/ir/prim/vector_expr.rs
@@ -175,7 +175,11 @@ impl Ramp {
}
}
-tvm_ffi::impl_object_upcast!(Ramp => Expr, Ramp => PrimExpr);
+// SAFETY: `prim.Ramp` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for RampObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Ramp => Expr, Ramp => PrimExpr);
// tvm-ffi-stubgen(end)
impl Ramp {
@@ -285,7 +289,11 @@ impl Broadcast {
}
}
-tvm_ffi::impl_object_upcast!(Broadcast => Expr, Broadcast => PrimExpr);
+// SAFETY: `prim.Broadcast` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for BroadcastObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Broadcast => Expr, Broadcast => PrimExpr);
// tvm-ffi-stubgen(end)
impl Broadcast {
@@ -373,7 +381,11 @@ impl Shuffle {
}
}
-tvm_ffi::impl_object_upcast!(Shuffle => Expr, Shuffle => PrimExpr);
+// SAFETY: `prim.Shuffle` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for ShuffleObj {}
+
+tvm_ffi::unsafe_impl_object_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 7eeade055..34101612c 100644
--- a/rust/src/ir/stmt.rs
+++ b/rust/src/ir/stmt.rs
@@ -188,6 +188,10 @@ unsafe impl UnsafeInit for StmtObj {
}
}
}
+
+// SAFETY: `ir.Stmt` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for StmtObj {}
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/ir.Bind
@@ -246,7 +250,11 @@ impl Bind {
}
}
-tvm_ffi::impl_object_upcast!(Bind => Stmt);
+// SAFETY: `ir.Bind` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for BindObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Bind => Stmt);
// tvm-ffi-stubgen(end)
impl Bind {
@@ -339,7 +347,11 @@ impl AssertStmt {
}
}
-tvm_ffi::impl_object_upcast!(AssertStmt => Stmt);
+// SAFETY: `ir.AssertStmt` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for AssertStmtObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(AssertStmt => Stmt);
// tvm-ffi-stubgen(end)
impl AssertStmt {
@@ -455,7 +467,11 @@ impl For {
}
}
-tvm_ffi::impl_object_upcast!(For => Stmt);
+// SAFETY: `ir.For` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for ForObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(For => Stmt);
// tvm-ffi-stubgen(end)
/// How a [`For`] loop runs its iterations, as C++ `ir::ForKind`.
@@ -633,7 +649,11 @@ impl While {
}
}
-tvm_ffi::impl_object_upcast!(While => Stmt);
+// SAFETY: `ir.While` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for WhileObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(While => Stmt);
// tvm-ffi-stubgen(end)
impl While {
@@ -722,7 +742,11 @@ impl TensorStore {
}
}
-tvm_ffi::impl_object_upcast!(TensorStore => Stmt);
+// SAFETY: `ir.TensorStore` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for TensorStoreObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(TensorStore => Stmt);
// tvm-ffi-stubgen(end)
impl TensorStore {
@@ -845,7 +869,11 @@ impl RegionStmt {
}
}
-tvm_ffi::impl_object_upcast!(RegionStmt => Stmt);
+// SAFETY: `ir.RegionStmt` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for RegionStmtObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(RegionStmt => Stmt);
// tvm-ffi-stubgen(end)
impl RegionStmt {
@@ -895,7 +923,7 @@ impl RegionStmt {
}
let mut definitions = std::collections::HashSet::new();
for var in body_params.iter().chain(result_vars.iter()) {
- if !definitions.insert(object_address(&var)) {
+ if !definitions.insert(object_address(var)) {
let condition = "definitions.insert(var.get()).second";
let message = "RegionStmt parameters and results must be
distinct definitions";
return Err(support::check_failed(tvm_ffi::VALUE_ERROR,
condition, message));
@@ -937,7 +965,7 @@ fn region_body_params(op: &Op, args: &Array<Expr>, attrs:
&DictAttrs) -> Result<
let message = format!("FRegionGetBodyParams for {name} must return
typed variables");
return Err(support::check_failed(tvm_ffi::VALUE_ERROR, condition,
&message));
}
- if !definitions.insert(object_address(¶m)) {
+ if !definitions.insert(object_address(param)) {
let condition = "definitions.insert(param.get()).second";
let message =
format!("FRegionGetBodyParams for {name} must return distinct
definitions");
@@ -949,8 +977,8 @@ fn region_body_params(op: &Op, args: &Array<Expr>, attrs:
&DictAttrs) -> Result<
/// The address of the object `value` refers to, which identifies a definition.
fn object_address<T: ObjectRefCore>(value: &T) -> usize {
- // SAFETY: the pointer is only compared, never dereferenced.
- unsafe { ObjectArc::as_raw(ObjectRefCore::data(value)) as usize }
+ // The pointer is only compared, never dereferenced.
+ ObjectArc::as_ptr(ObjectRefCore::data(value)) as usize
}
// tvm-ffi-stubgen(begin): object/ir.SeqStmt
@@ -1004,7 +1032,11 @@ impl SeqStmt {
}
}
-tvm_ffi::impl_object_upcast!(SeqStmt => Stmt);
+// SAFETY: `ir.SeqStmt` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for SeqStmtObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(SeqStmt => Stmt);
// tvm-ffi-stubgen(end)
impl SeqStmt {
@@ -1025,13 +1057,13 @@ fn flatten(seq: Array<Stmt>) -> Array<Stmt> {
}
fn append(stmt: Stmt, flattened: &mut Vec<Stmt>) {
match stmt.downcast_ref::<SeqStmtObj>() {
- Some(nested) => nested.seq.iter().for_each(|child| append(child,
flattened)),
+ Some(nested) => nested.seq.iter().for_each(|child|
append(child.clone(), flattened)),
None if is_no_op(&stmt) => {}
None => flattened.push(stmt),
}
}
let mut flattened = Vec::new();
- seq.iter().for_each(|stmt| append(stmt, &mut flattened));
+ seq.iter().for_each(|stmt| append(stmt.clone(), &mut flattened));
Array::from_vec(flattened)
}
@@ -1046,7 +1078,7 @@ fn is_no_op(stmt: &Stmt) -> bool {
/// statement as the sequence of it at its location (C++ `SeqStmt(stmt)`).
fn into_body(stmt: Stmt) -> Result<SeqStmt> {
if stmt.downcast_ref::<SeqStmtObj>().is_some() {
- return Ok(tvm_ffi::ObjectRefCast::try_cast(stmt).expect("a SeqStmt"));
+ return Ok(stmt.downcast().expect("a SeqStmt"));
}
let loc = stmt.loc.clone();
Ok(SeqStmt::from_fields(loc, flatten(Array::from_vec(vec![stmt]))))
@@ -1115,7 +1147,11 @@ impl If {
}
}
-tvm_ffi::impl_object_upcast!(If => Stmt);
+// SAFETY: `ir.If` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for IfObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(If => Stmt);
// tvm-ffi-stubgen(end)
impl If {
@@ -1185,7 +1221,11 @@ impl Evaluate {
}
}
-tvm_ffi::impl_object_upcast!(Evaluate => Stmt);
+// SAFETY: `ir.Evaluate` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for EvaluateObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Evaluate => Stmt);
// tvm-ffi-stubgen(end)
impl Evaluate {
@@ -1245,7 +1285,11 @@ impl Break {
}
}
-tvm_ffi::impl_object_upcast!(Break => Stmt);
+// SAFETY: `ir.Break` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for BreakObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Break => Stmt);
// tvm-ffi-stubgen(end)
// `ir.Break` stores its location as given: the generated `Break::new` is the
same.
@@ -1301,7 +1345,11 @@ impl Return {
}
}
-tvm_ffi::impl_object_upcast!(Return => Stmt);
+// SAFETY: `ir.Return` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for ReturnObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Return => Stmt);
// tvm-ffi-stubgen(end)
impl Return {
@@ -1361,7 +1409,11 @@ impl Continue {
}
}
-tvm_ffi::impl_object_upcast!(Continue => Stmt);
+// SAFETY: `ir.Continue` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for ContinueObj {}
+
+tvm_ffi::unsafe_impl_object_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/support.rs b/rust/src/ir/support.rs
index 0b92e484e..1e2e0e928 100644
--- a/rust/src/ir/support.rs
+++ b/rust/src/ir/support.rs
@@ -121,7 +121,7 @@ where
/// A dtype as C++ prints it, such as `int32`.
pub(crate) fn dtype_name(dtype: DLDataType) -> std::string::String {
- DLDataTypeExt::to_string(&dtype).as_str().to_string()
+ dtype.to_string()
}
/// The registered key of a type index (C++ `TypeIndexToTypeKey`).
@@ -216,7 +216,7 @@ pub(crate) fn shared<T: Clone + 'static>(
pub(crate) fn prim_type(expr: &(impl AsRef<Expr> + ?Sized)) ->
Result<PrimType> {
let expr = expr.as_ref();
match expr.ty.downcast_ref::<PrimTypeObj>() {
- Some(_) =>
Ok(tvm_ffi::ObjectRefCast::try_cast(expr.ty.clone()).expect("a PrimType")),
+ Some(_) => Ok(expr.ty.downcast_ref::<PrimType>().cloned().expect("a
PrimType")),
None => Err(not_a_prim_expr(expr)),
}
}
@@ -302,7 +302,7 @@ pub(crate) fn array_cells<T:
tvm_ffi::type_traits::ContainerElement + Clone>(
// SAFETY: an `ffi.Array` is the object header followed by
`TVMFFISeqCell`, and `array` keeps
// its `size` elements alive.
unsafe {
- let cell = &*(ObjectArc::as_raw(ObjectRefCore::data(array)) as *const
SeqCell);
+ let cell = &*(ObjectArc::as_ptr(ObjectRefCore::data(array)) as *const
SeqCell);
if cell.size == 0 {
return &[];
}
@@ -348,7 +348,7 @@ impl NativeHook {
// SAFETY: `node` keeps the object alive for the call, and the
adapter returns an
// owned value.
Self::Adapter(adapter) => unsafe {
- let node = ObjectArc::as_raw(ObjectRefCore::data(node)) as
*const c_void;
+ let node = ObjectArc::as_ptr(ObjectRefCore::data(node)) as
*const c_void;
Any::from_raw_ffi_any(adapter(node))
},
Self::Packed(function) =>
function.call_packed(&[AnyView::from(node)])?,
@@ -402,8 +402,8 @@ where
*const *const TVMFFIObject,
) -> TVMFFIAny;
fn object<T: ObjectRefCore>(value: &T) -> *const TVMFFIObject {
- // SAFETY: the pointer is only read while `value` keeps the object
alive.
- unsafe { ObjectArc::as_raw(ObjectRefCore::data(value)) as *const
TVMFFIObject }
+ // The pointer is only read while `value` keeps the object alive.
+ ObjectArc::as_ptr(ObjectRefCore::data(value)) as *const TVMFFIObject
}
let address: *mut c_void = hook.try_into()?;
let (a, b, c) = (object(a), object(b), object(c));
diff --git a/rust/src/ir/transform/core.rs b/rust/src/ir/transform/core.rs
index ca4955126..dce5543af 100644
--- a/rust/src/ir/transform/core.rs
+++ b/rust/src/ir/transform/core.rs
@@ -150,6 +150,10 @@ impl PassInfo {
Self { base: ObjectArc::new(obj) }
}
}
+
+// SAFETY: `transform.PassInfo` is not `_type_mutable`: a shared instance is
never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for PassInfoObj {}
// tvm-ffi-stubgen(end)
// `PassInfo::new` above has the semantics of the native `transform.PassInfo`,
which only stores
@@ -191,7 +195,11 @@ impl ModulePassObj {
}
}
-tvm_ffi::impl_object_upcast!(ModulePass => Pass);
+// SAFETY: `transform.ModulePass` is not `_type_mutable`: a shared instance is
never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for ModulePassObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(ModulePass => Pass);
// tvm-ffi-stubgen(end)
impl ModulePass {
@@ -256,7 +264,11 @@ impl SequentialObj {
}
}
-tvm_ffi::impl_object_upcast!(Sequential => Pass);
+// SAFETY: `transform.Sequential` is not `_type_mutable`: a shared instance is
never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for SequentialObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(Sequential => Pass);
// tvm-ffi-stubgen(end)
impl Sequential {
@@ -482,6 +494,10 @@ impl PassInstrumentObj {
FieldGetter::new(Self::type_index(), "name")?.get(self)
}
}
+
+// SAFETY: `transform.PassInstrument` is not `_type_mutable`: a shared
instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for PassInstrumentObj {}
// tvm-ffi-stubgen(end)
/// Create a pass that logs `header` and the module, which it returns unchanged
diff --git a/rust/src/ir/transform/instrument.rs
b/rust/src/ir/transform/instrument.rs
index 74e399432..355aea5fa 100644
--- a/rust/src/ir/transform/instrument.rs
+++ b/rust/src/ir/transform/instrument.rs
@@ -102,7 +102,7 @@ impl Deref for BasePassInstrumentObj {
}
}
-tvm_ffi::impl_object_upcast!(BasePassInstrument => PassInstrument);
+tvm_ffi::unsafe_impl_object_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 45ddf4cf5..7818dfcd5 100644
--- a/rust/src/ir/type.rs
+++ b/rust/src/ir/type.rs
@@ -137,6 +137,10 @@ unsafe impl UnsafeInit for TypeObj {
}
}
}
+
+// SAFETY: `ir.Type` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for TypeObj {}
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/ir.MissingType
@@ -189,7 +193,11 @@ impl MissingType {
}
}
-tvm_ffi::impl_object_upcast!(MissingType => Type);
+// SAFETY: `ir.MissingType` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for MissingTypeObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(MissingType => Type);
// tvm-ffi-stubgen(end)
impl MissingType {
@@ -255,7 +263,11 @@ impl NoneType {
}
}
-tvm_ffi::impl_object_upcast!(NoneType => Type);
+// SAFETY: `ir.NoneType` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for NoneTypeObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(NoneType => Type);
// tvm-ffi-stubgen(end)
impl NoneType {
@@ -320,7 +332,11 @@ impl AnyType {
}
}
-tvm_ffi::impl_object_upcast!(AnyType => Type);
+// SAFETY: `ir.AnyType` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for AnyTypeObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(AnyType => Type);
// tvm-ffi-stubgen(end)
// `ir.AnyType` stores its location as given: the generated `AnyType::new` is
the same.
@@ -375,7 +391,11 @@ impl TensorRegionType {
}
}
-tvm_ffi::impl_object_upcast!(TensorRegionType => Type);
+// SAFETY: `ir.TensorRegionType` is not `_type_mutable`: a shared instance is
never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for TensorRegionTypeObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(TensorRegionType => Type);
// tvm-ffi-stubgen(end)
impl TensorRegionType {
@@ -441,7 +461,11 @@ impl OpaqueType {
}
}
-tvm_ffi::impl_object_upcast!(OpaqueType => Type);
+// SAFETY: `ir.OpaqueType` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for OpaqueTypeObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(OpaqueType => Type);
// tvm-ffi-stubgen(end)
// `ir.OpaqueType` allocates a fresh type at the unknown location: the
generated
@@ -498,7 +522,11 @@ impl PrimType {
}
}
-tvm_ffi::impl_object_upcast!(PrimType => Type);
+// SAFETY: `ir.PrimType` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for PrimTypeObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(PrimType => Type);
// tvm-ffi-stubgen(end)
impl PrimType {
@@ -638,7 +666,11 @@ impl StringType {
}
}
-tvm_ffi::impl_object_upcast!(StringType => Type);
+// SAFETY: `ir.StringType` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for StringTypeObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(StringType => Type);
// tvm-ffi-stubgen(end)
// `ir.StringType` allocates a fresh type at the unknown location: the
generated
@@ -700,7 +732,11 @@ impl PtrType {
}
}
-tvm_ffi::impl_object_upcast!(PtrType => Type);
+// SAFETY: `ir.PtrType` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for PtrTypeObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(PtrType => Type);
// tvm-ffi-stubgen(end)
impl PtrType {
@@ -772,7 +808,11 @@ impl TupleType {
}
}
-tvm_ffi::impl_object_upcast!(TupleType => Type);
+// SAFETY: `ir.TupleType` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for TupleTypeObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(TupleType => Type);
// tvm-ffi-stubgen(end)
impl TupleType {
@@ -843,7 +883,11 @@ impl FuncType {
}
}
-tvm_ffi::impl_object_upcast!(FuncType => Type);
+// SAFETY: `ir.FuncType` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for FuncTypeObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(FuncType => Type);
// tvm-ffi-stubgen(end)
impl FuncType {
diff --git a/rust/src/macro/def_expr_op_overloads.rs
b/rust/src/macro/def_expr_op_overloads.rs
index 5c3d377b7..2013f3c9c 100644
--- a/rust/src/macro/def_expr_op_overloads.rs
+++ b/rust/src/macro/def_expr_op_overloads.rs
@@ -50,7 +50,7 @@
/// }
///
/// // Every thread index is an `int32`, as `new` makes it.
-/// tvm_ffi::impl_object_upcast!(ThreadIndex => PrimExpr);
+/// tvm_ffi::unsafe_impl_object_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 6f1ba93bb..52d8c70f4 100644
--- a/rust/src/macro/typed_expr_view.rs
+++ b/rust/src/macro/typed_expr_view.rs
@@ -170,6 +170,14 @@ 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);
+
+ // The type key and address, as `#[derive(ObjectRef)]` prints a
reference, so a
+ // `downcast` result can be unwrapped.
+ impl ::core::fmt::Debug for $name {
+ fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) ->
::core::fmt::Result {
+ tvm_ffi::object::fmt_object_ref(self, f)
+ }
+ }
crate::def_expr_op_over_loads!($name);
impl From<&$name> for $name {
@@ -199,7 +207,7 @@ macro_rules! typed_expr_view {
/// Return the type of this expression, the [`PrimType`] the view
guarantees (C++
/// `PrimExpr::ty()`).
pub fn ty(&self) -> PrimType {
- self.base.ty.clone().try_cast().expect("a view is typed by a
`PrimType`")
+ self.base.ty.downcast_ref::<PrimType>().cloned().expect("a
view is typed by a `PrimType`")
}
/// Return the dtype of this expression's type.
@@ -208,24 +216,6 @@ macro_rules! typed_expr_view {
ty.expect("a view is typed by a `PrimType`").dtype
}
}
-
- /// Convert an expression into the view; a `TypeError` names a type
the view does not
- /// accept.
- impl TryFrom<Expr> for $name {
- type Error = Error;
-
- fn try_from(value: Expr) -> Result<Self> {
- value.try_cast()
- }
- }
-
- impl TryFrom<&Expr> for $name {
- type Error = Error;
-
- fn try_from(value: &Expr) -> Result<Self> {
- value.clone().try_cast()
- }
- }
};
}
diff --git a/rust/src/runtime.rs b/rust/src/runtime.rs
index 9a2902064..b5aada2ac 100644
--- a/rust/src/runtime.rs
+++ b/rust/src/runtime.rs
@@ -94,6 +94,10 @@ impl Deref for MemoryScope {
&self.base
}
}
+
+// SAFETY: `runtime.MemoryScope` is not `_type_mutable`: a shared instance is
never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for MemoryScopeObj {}
// tvm-ffi-stubgen(end)
impl MemoryScope {
diff --git a/rust/src/sym/analyzer.rs b/rust/src/sym/analyzer.rs
index c2a24c8fe..9eaa63f82 100644
--- a/rust/src/sym/analyzer.rs
+++ b/rust/src/sym/analyzer.rs
@@ -440,6 +440,10 @@ impl ConstIntBound {
Self { base: ObjectArc::new(obj) }
}
}
+
+// SAFETY: `sym.ConstIntBound` is not `_type_mutable`: a shared instance is
never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for ConstIntBoundObj {}
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/sym.ModularSet
@@ -486,6 +490,10 @@ impl ModularSet {
Self { base: ObjectArc::new(obj) }
}
}
+
+// SAFETY: `sym.ModularSet` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for ModularSetObj {}
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/sym.RewriteSimplifierStats
@@ -565,6 +573,10 @@ impl RewriteSimplifierStats {
Self { base: ObjectArc::new(obj) }
}
}
+
+// SAFETY: `sym.RewriteSimplifierStats` is not `_type_mutable`: a shared
instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for RewriteSimplifierStatsObj {}
// tvm-ffi-stubgen(end)
//
---------------------------------------------------------------------------------------------
@@ -599,7 +611,7 @@ impl Deref for CanonicalExprObj {
}
}
-tvm_ffi::impl_object_upcast!(CanonicalExpr => Expr);
+tvm_ffi::unsafe_impl_object_upcast!(CanonicalExpr => Expr);
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/sym.SplitExpr
@@ -631,7 +643,7 @@ impl Deref for SplitExprObj {
}
}
-tvm_ffi::impl_object_upcast!(SplitExpr => Expr, SplitExpr => CanonicalExpr,
SplitExpr => PrimExpr);
+tvm_ffi::unsafe_impl_object_upcast!(SplitExpr => Expr, SplitExpr =>
CanonicalExpr, SplitExpr => PrimExpr);
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/sym.SumExpr
@@ -663,5 +675,5 @@ impl Deref for SumExprObj {
}
}
-tvm_ffi::impl_object_upcast!(SumExpr => Expr, SumExpr => CanonicalExpr,
SumExpr => PrimExpr);
+tvm_ffi::unsafe_impl_object_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 5822dd286..dbc482c53 100644
--- a/rust/src/sym/constraint.rs
+++ b/rust/src/sym/constraint.rs
@@ -121,6 +121,10 @@ unsafe impl UnsafeInit for ConstraintObj {
}
}
}
+
+// SAFETY: `sym.Constraint` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for ConstraintObj {}
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/sym.BindingConstraint
@@ -175,7 +179,11 @@ impl BindingConstraint {
}
}
-tvm_ffi::impl_object_upcast!(BindingConstraint => Constraint);
+// SAFETY: `sym.BindingConstraint` is not `_type_mutable`: a shared instance
is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for BindingConstraintObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(BindingConstraint => Constraint);
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/sym.PredicateConstraint
@@ -230,7 +238,11 @@ impl PredicateConstraint {
}
}
-tvm_ffi::impl_object_upcast!(PredicateConstraint => Constraint);
+// SAFETY: `sym.PredicateConstraint` is not `_type_mutable`: a shared instance
is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for PredicateConstraintObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(PredicateConstraint => Constraint);
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/sym.RangeConstraint
@@ -285,7 +297,11 @@ impl RangeConstraint {
}
}
-tvm_ffi::impl_object_upcast!(RangeConstraint => Constraint);
+// SAFETY: `sym.RangeConstraint` is not `_type_mutable`: a shared instance is
never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for RangeConstraintObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(RangeConstraint => Constraint);
// tvm-ffi-stubgen(end)
/// The object of a [`ConstraintContext`], with the layout of the native one
and a stable identity.
@@ -378,8 +394,7 @@ impl ConstraintContextObj {
/// Capture the visible prefix in an independently extensible child.
pub fn snapshot(&self) -> Result<ConstraintContext> {
- let parent = AnyView::from(self)
- .try_as::<ConstraintContext>()
+ let parent = ConstraintContext::try_from(AnyView::from(self))
.expect("context has its registered native type");
ConstraintContext::with_parent_prefix_size(parent, self.local_size())
}
@@ -394,8 +409,7 @@ impl ConstraintContextObj {
/// The callback may append without entering this iteration; each borrowed
constraint is valid
/// only during its callback.
pub fn for_each(&self, mut callback: impl FnMut(&Constraint)) {
- let retained = AnyView::from(self)
- .try_as::<ConstraintContext>()
+ let retained = ConstraintContext::try_from(AnyView::from(self))
.expect("context has its registered native type");
retained.for_each_prefix(retained.local_size(), &mut callback);
}
diff --git a/rust/src/sym/int_set.rs b/rust/src/sym/int_set.rs
index c45ffd50f..c0ed0f2ba 100644
--- a/rust/src/sym/int_set.rs
+++ b/rust/src/sym/int_set.rs
@@ -163,7 +163,11 @@ impl IntervalSetObj {
}
}
-tvm_ffi::impl_object_upcast!(IntervalSet => IntSet);
+// SAFETY: `sym.IntervalSet` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for IntervalSetObj {}
+
+tvm_ffi::unsafe_impl_object_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 bd1de01ba..b9ef5ca39 100644
--- a/rust/src/sym/iter_affine_map.rs
+++ b/rust/src/sym/iter_affine_map.rs
@@ -122,7 +122,7 @@ impl Deref for IterMapExprObj {
}
}
-tvm_ffi::impl_object_upcast!(IterMapExpr => Expr, IterMapExpr => PrimExpr);
+tvm_ffi::unsafe_impl_object_upcast!(IterMapExpr => Expr, IterMapExpr =>
PrimExpr);
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/sym.IterMapResult
@@ -224,6 +224,10 @@ impl IterMark {
Self { base: ObjectArc::new(obj) }
}
}
+
+// SAFETY: `sym.IterMark` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for IterMarkObj {}
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/sym.IterSplitExpr
@@ -274,7 +278,11 @@ impl IterSplitExprObj {
}
}
-tvm_ffi::impl_object_upcast!(IterSplitExpr => Expr, IterSplitExpr =>
IterMapExpr, IterSplitExpr => PrimExpr);
+// SAFETY: `sym.IterSplitExpr` is not `_type_mutable`: a shared instance is
never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for IterSplitExprObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(IterSplitExpr => Expr, IterSplitExpr =>
IterMapExpr, IterSplitExpr => PrimExpr);
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/sym.IterSumExpr
@@ -317,7 +325,11 @@ impl IterSumExprObj {
}
}
-tvm_ffi::impl_object_upcast!(IterSumExpr => Expr, IterSumExpr => IterMapExpr,
IterSumExpr => PrimExpr);
+// SAFETY: `sym.IterSumExpr` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for IterSumExprObj {}
+
+tvm_ffi::unsafe_impl_object_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/tirx/function.rs b/rust/src/tirx/function.rs
index 683f5e939..b57671869 100644
--- a/rust/src/tirx/function.rs
+++ b/rust/src/tirx/function.rs
@@ -148,7 +148,11 @@ impl Function {
}
}
-tvm_ffi::impl_object_upcast!(Function => Expr, Function => BaseFunc);
+// SAFETY: `tirx.Function` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for FunctionObj {}
+
+tvm_ffi::unsafe_impl_object_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 ad76da310..6fe599159 100644
--- a/rust/src/tirx/index_map.rs
+++ b/rust/src/tirx/index_map.rs
@@ -38,7 +38,7 @@
//! assert_eq!(script(&transpose)?, "T.index_map(lambda i, j: (j, i))");
//!
//! let text =
-//! |exprs: Array<PrimExpr>| exprs.iter().map(|e|
script(&e)).collect::<Result<Vec<_>>>();
+//! |exprs: Array<PrimExpr>|
exprs.iter().map(script).collect::<Result<Vec<_>>>();
//! assert_eq!(text(transpose.map_indices([1, 2], None)?)?, ["2", "1"]);
//!
//! # Ok::<(), tvm_tirx::tvm_ffi::Error>(())
@@ -128,6 +128,10 @@ impl IndexMap {
Self { base: ObjectArc::new(obj) }
}
}
+
+// SAFETY: `tirx.IndexMap` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for IndexMapObj {}
// tvm-ffi-stubgen(end)
// The native `tirx.IndexMap` stores its fields as given, as the generated
`IndexMap::new` does.
diff --git a/rust/src/tirx/layout.rs b/rust/src/tirx/layout.rs
index 5789e0336..4147dfbfb 100644
--- a/rust/src/tirx/layout.rs
+++ b/rust/src/tirx/layout.rs
@@ -261,7 +261,11 @@ impl TileLayoutObj {
}
}
-tvm_ffi::impl_object_upcast!(TileLayout => Layout);
+// SAFETY: `tirx.TileLayout` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for TileLayoutObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(TileLayout => Layout);
// tvm-ffi-stubgen(end)
impl TileLayout {
@@ -376,6 +380,10 @@ impl Iter {
Self { base: ObjectArc::new(obj) }
}
}
+
+// SAFETY: `tirx.Iter` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for IterObj {}
// tvm-ffi-stubgen(end)
// The native `tirx.Iter` stores its fields as given, as the generated
`Iter::new` does.
@@ -402,6 +410,10 @@ impl Deref for Axis {
&self.base
}
}
+
+// SAFETY: `tirx.Axis` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for AxisObj {}
// tvm-ffi-stubgen(end)
impl Axis {
@@ -498,7 +510,11 @@ impl ComposeLayoutObj {
}
}
-tvm_ffi::impl_object_upcast!(ComposeLayout => Layout);
+// SAFETY: `tirx.ComposeLayout` is not `_type_mutable`: a shared instance is
never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for ComposeLayoutObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(ComposeLayout => Layout);
// tvm-ffi-stubgen(end)
impl ComposeLayout {
diff --git a/rust/src/tirx/op.rs b/rust/src/tirx/op.rs
index 8c437ef8e..ac7bb8c6b 100644
--- a/rust/src/tirx/op.rs
+++ b/rust/src/tirx/op.rs
@@ -169,7 +169,11 @@ impl CallFFIKernelAttr {
}
}
-tvm_ffi::impl_object_upcast!(CallFFIKernelAttr => Attrs);
+// SAFETY: `tirx.CallFFIKernelAttr` is not `_type_mutable`: a shared instance
is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for CallFFIKernelAttrObj {}
+
+tvm_ffi::unsafe_impl_object_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_walk_with_constraint_context.rs
b/rust/src/tirx/structural_walk_with_constraint_context.rs
index 5352d20aa..cc650f209 100644
--- a/rust/src/tirx/structural_walk_with_constraint_context.rs
+++ b/rust/src/tirx/structural_walk_with_constraint_context.rs
@@ -102,11 +102,11 @@ where
}
WalkResult::Interrupt => {
core::hint::cold_path();
- Ok(Some(VisitInterrupt::with(Any::new())))
+ Ok(Some(VisitInterrupt::new(Any::new())))
}
WalkResult::InterruptWith(payload) => {
core::hint::cold_path();
- Ok(Some(VisitInterrupt::with(payload)))
+ Ok(Some(VisitInterrupt::new(payload)))
}
}
}
diff --git a/rust/src/tirx/tensor.rs b/rust/src/tirx/tensor.rs
index d5de159c1..278bd697b 100644
--- a/rust/src/tirx/tensor.rs
+++ b/rust/src/tirx/tensor.rs
@@ -165,7 +165,11 @@ impl TensorType {
}
}
-tvm_ffi::impl_object_upcast!(TensorType => Type);
+// SAFETY: `tirx.TensorType` is not `_type_mutable`: a shared instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for TensorTypeObj {}
+
+tvm_ffi::unsafe_impl_object_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 7c71de7bb..761b55dbb 100644
--- a/rust/src/tirx/thread_scope.rs
+++ b/rust/src/tirx/thread_scope.rs
@@ -83,6 +83,10 @@ impl Deref for ThreadScope {
&self.base
}
}
+
+// SAFETY: `tirx.ThreadScope` is not `_type_mutable`: a shared instance is
never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for ThreadScopeObj {}
// tvm-ffi-stubgen(end)
impl ThreadScope {
diff --git a/rust/src/tirx/tile/dispatch.rs b/rust/src/tirx/tile/dispatch.rs
index fc195b5ca..25eb54ed4 100644
--- a/rust/src/tirx/tile/dispatch.rs
+++ b/rust/src/tirx/tile/dispatch.rs
@@ -51,7 +51,7 @@
// does.
// tvm-ffi-stubgen(import-object): crate::ir::stmt::Stmt
// tvm-ffi-stubgen(import-object): tvm_ffi::AnyView
-// tvm-ffi-stubgen(import-object): tvm_ffi::ObjectRefCast
+// tvm-ffi-stubgen(import-object): tvm_ffi::ObjectRefCore
// tvm-ffi-stubgen(import-object): crate::ir::expr::IntoExpr
// tvm-ffi-stubgen(import-object): crate::ir::expr::PrimExpr
// tvm-ffi-stubgen(import-object): crate::ir::expr::PrimVar
@@ -78,7 +78,7 @@ use tvm_ffi::Map;
use tvm_ffi::Object;
use tvm_ffi::ObjectArc;
use tvm_ffi::ObjectCore;
-use tvm_ffi::ObjectRefCast;
+use tvm_ffi::ObjectRefCore;
use tvm_ffi::Result;
use tvm_ffi::String;
use tvm_ffi::object::ObjectRef;
@@ -148,6 +148,10 @@ impl DispatchContextObj {
FieldGetter::new(Self::type_index(), "scope_kind")?.get(self)
}
}
+
+// SAFETY: `tirx.DispatchContext` is not `_type_mutable`: a shared instance is
never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for DispatchContextObj {}
// tvm-ffi-stubgen(end)
impl DispatchContext {
@@ -255,7 +259,11 @@ impl DispatchContext {
}
/// Cache `value` under `key` across dispatches
(`tirx.DispatchContextSharedStateSet`).
- pub fn cache_set(&self, key: &str, value: &impl ObjectRefCast) ->
Result<()> {
+ pub fn cache_set(
+ &self,
+ key: &str,
+ value: &(impl ObjectRefCore + tvm_ffi::type_traits::AnyCompatible),
+ ) -> 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 1cb906312..aece34084 100644
--- a/rust/src/tirx/tile/instruction.rs
+++ b/rust/src/tirx/tile/instruction.rs
@@ -105,7 +105,11 @@ impl ScopeAttrs {
}
}
-tvm_ffi::impl_object_upcast!(ScopeAttrs => Attrs);
+// SAFETY: `tirx.tensor.ScopeAttrs` is not `_type_mutable`: a shared instance
is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for ScopeAttrsObj {}
+
+tvm_ffi::unsafe_impl_object_upcast!(ScopeAttrs => Attrs);
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/tirx.tensor.TrnAttrs
@@ -197,7 +201,11 @@ impl TrnAttrs {
}
}
-tvm_ffi::impl_object_upcast!(TrnAttrs => Attrs);
+// SAFETY: `tirx.tensor.TrnAttrs` is not `_type_mutable`: a shared instance is
never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for TrnAttrsObj {}
+
+tvm_ffi::unsafe_impl_object_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 33465d7c8..8fd6701b8 100644
--- a/rust/src/tirx/transform/function_pass.rs
+++ b/rust/src/tirx/transform/function_pass.rs
@@ -106,7 +106,11 @@ impl FunctionPassObj {
}
}
-tvm_ffi::impl_object_upcast!(FunctionPass => Pass);
+// SAFETY: `tirx.FunctionPass` is not `_type_mutable`: a shared instance is
never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for FunctionPassObj {}
+
+tvm_ffi::unsafe_impl_object_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 c836614e8..f8e74876a 100644
--- a/rust/src/tirx/transform/transform.rs
+++ b/rust/src/tirx/transform/transform.rs
@@ -27,7 +27,7 @@
//!
//! ```
//! use tvm_tirx::tirx::{transform, Function};
-//! use tvm_tirx::tvm_ffi::ObjectRefCast;
+//! use tvm_tirx::tvm_ffi::{Error, ObjectRefCore};
//! # use tvm_tirx::ir::{BaseFunc, DictAttrs, Evaluate, GlobalVar, IRModule,
MissingType, SeqStmt};
//! # use tvm_tirx::ir::{Var, UNKNOWN_LOC};
//! # use tvm_tirx::tvm_ffi::Map;
@@ -38,7 +38,7 @@
//! # let module = IRModule::from_functions(&functions.into_iter().collect(),
None, &Map::new())?;
//!
//! let module = transform::remove_no_op()?.run(module)?;
-//! let main: Function = module.lookup_name("main")?.try_cast()?;
+//! let main: Function = module.lookup_name("main")?.try_into()?;
//! assert!(main.body.seq.is_empty());
//! # Ok::<(), tvm_tirx::tvm_ffi::Error>(())
//! ```
@@ -106,6 +106,10 @@ impl RemoveNoOpConfig {
Self { base: ObjectArc::new(obj) }
}
}
+
+// SAFETY: `tirx.transform.RemoveNoOpConfig` is not `_type_mutable`: a shared
instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for RemoveNoOpConfigObj {}
// tvm-ffi-stubgen(end)
// tvm-ffi-stubgen(begin): object/tirx.transform.UnrollLoopConfig
@@ -180,6 +184,10 @@ impl UnrollLoopConfig {
Self { base: ObjectArc::new(obj) }
}
}
+
+// SAFETY: `tirx.transform.UnrollLoopConfig` is not `_type_mutable`: a shared
instance is never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for UnrollLoopConfigObj {}
// tvm-ffi-stubgen(end)
/// Infer and mark an unambiguous TIRx entry function
(`tirx.transform.AnnotateEntryFunc`).
diff --git a/rust/src/tirx/type.rs b/rust/src/tirx/type.rs
index ba655ff0a..7c0740b79 100644
--- a/rust/src/tirx/type.rs
+++ b/rust/src/tirx/type.rs
@@ -93,7 +93,11 @@ impl TensorMapType {
}
}
-tvm_ffi::impl_object_upcast!(TensorMapType => Type);
+// SAFETY: `tirx.TensorMapType` is not `_type_mutable`: a shared instance is
never
+// mutated, as C++ changes it only through copy-on-write.
+unsafe impl tvm_ffi::object::ImmutableObject for TensorMapTypeObj {}
+
+tvm_ffi::unsafe_impl_object_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 d1c3a6acc..eaefbf6b1 100644
--- a/rust/tests/ir/expr.rs
+++ b/rust/tests/ir/expr.rs
@@ -22,8 +22,8 @@
use tvm_tirx::ir::prim::Broadcast;
use tvm_tirx::ir::*;
use tvm_tirx::tvm_ffi::{
- Any, AnyView, Array, BigInt, DLDataType, Function, ObjectRefCast,
ObjectRefCore, Result,
- String as FfiString, TYPE_ERROR,
+ Any, AnyView, Array, BigInt, DLDataType, Function, ObjectRefCore, Result,
String as FfiString,
+ TYPE_ERROR,
};
use super::{int32, int32_var, op, parse_dtype, tensor_var};
@@ -215,7 +215,7 @@ fn builtin_constants() {
agree("Expr::from(bool)", Ok(Expr::from(false)), int(dtype::bool(), 0));
agree("Expr::from(f32)", Ok(Expr::from(0.5f32)), float(dtype::float(32),
0.5));
agree("Expr::from(f64)", Ok(Expr::from(0.5f64)), float(dtype::float(64),
0.5));
- let folded: IntImm = op("prim._OpAdd", 1i32, 2i32).try_cast().unwrap();
+ let folded: IntImm = op("prim._OpAdd", 1i32, 2i32).downcast().unwrap();
assert_eq!(folded.value, BigInt::from(3));
}
@@ -348,7 +348,7 @@ fn test_op(name: &str, attrs: &[(&str, Any)]) -> Op {
}
Op::register(name, "").unwrap();
let op = Op::get(name).unwrap();
- let set_attr = Function::from_type_key_method("ir.Op",
"_set_attr").unwrap();
+ let set_attr = tvm_ffi::reflection::get_method("ir.Op",
"_set_attr").unwrap();
for (key, value) in attrs {
let key = FfiString::from(*key);
set_attr
@@ -365,15 +365,14 @@ fn calls_agree_with_cpp() {
let f32_ty: Type = PrimType::float(32).into();
let one: Expr = FloatImm::float32(1.0).into();
let i16_ty: Type = PrimType::int(16).into();
- let returns = |value: Any| {
- Function::from_packed(move |_args: &[AnyView]| -> Result<Any> {
Ok(value.clone()) })
- };
- let packed_infer = test_op(
- "rust_test.packed_infer",
- &[("FInferType", returns(Any::from(i16_ty.clone())).into())],
- );
+ // A callback captures thread-safe state: a typed value, converted on each
call.
+ fn returns<T: Clone + Into<Any> + Send + Sync + 'static>(value: T) ->
Function {
+ Function::from_packed(move |_args: &[AnyView]| -> Result<Any> {
Ok(value.clone().into()) })
+ }
+ let packed_infer =
+ test_op("rust_test.packed_infer", &[("FInferType",
returns(i16_ty.clone()).into())]);
let packed_mistyped =
- test_op("rust_test.packed_mistyped", &[("FInferType",
returns(Any::from(5i64)).into())]);
+ test_op("rust_test.packed_mistyped", &[("FInferType",
returns(5i64).into())]);
let fixed =
test_op("rust_test.fixed_return", &[("TFixedReturnType",
Any::from(f32_ty.clone()))]);
let plain = test_op("rust_test.no_inference", &[]);
@@ -547,8 +546,8 @@ fn operators_take_views() {
let error = PrimExpr::try_from(Expr::from(tensor_var("A"))).err().unwrap();
assert_eq!(error.kind(), TYPE_ERROR);
assert!(error.message().contains("ir.Var[ty=tirx.TensorType]"), "{error}");
- // `ObjectRefCast` downcasts between views as it does between node types.
- let back: IntExpr = sum.try_cast().unwrap();
+ // `ObjectRefCore` downcasts between views as it does between node types.
+ let back: IntExpr = sum.downcast().unwrap();
assert_eq!(back.dtype(), dtype::int(32));
}
@@ -571,17 +570,17 @@ fn prim_vars_are_views() {
assert!(i.as_expr().same_as(&i));
// A `Var` narrows only through the check of C++ `PrimVar`: `downcast_ref`
borrows it in place
- // and `try_cast` takes it.
+ // and `downcast` takes it.
assert!(var.downcast_ref::<PrimVar>().unwrap().same_as(&i));
let vector = Var::new("v", PrimType::float(32).with_lanes(4).unwrap(),
UNKNOWN_LOC);
- assert_eq!(vector.try_cast::<PrimVar>().unwrap().dtype().lanes, 4);
+ assert_eq!(vector.downcast::<PrimVar>().unwrap().dtype().lanes, 4);
let untyped = Var::new("u", MissingType::new(), UNKNOWN_LOC);
assert!(untyped.downcast_ref::<PrimVar>().is_none());
- let error = untyped.try_cast::<PrimVar>().err().unwrap();
+ let error = PrimVar::try_from(&untyped).unwrap_err();
assert_eq!(error.kind(), TYPE_ERROR);
// C++ `TypeTraits<PrimVar>` names the variable class on both sides.
assert_eq!(error.message(), "Cannot convert from type `ir.Var` to
`ir.Var`");
- assert!(tensor_var("A").try_cast::<PrimVar>().is_err());
+ assert!(tensor_var("A").downcast::<PrimVar>().is_err());
// It takes part in arithmetic as a `PrimExpr`.
let sum = PrimExpr::try_from(&i * 4 + 1).unwrap();
diff --git a/rust/tests/ir/op_def.rs b/rust/tests/ir/op_def.rs
index 4d50c2ef9..994e3f158 100644
--- a/rust/tests/ir/op_def.rs
+++ b/rust/tests/ir/op_def.rs
@@ -39,8 +39,8 @@ 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, ObjectRefCast, ObjectRefCore, Result, String as
FfiString,
- ATTRIBUTE_ERROR, INTERNAL_ERROR, TYPE_ERROR, VALUE_ERROR,
+ Function, Map, ObjectCore, ObjectRefCore, Result, String as FfiString,
ATTRIBUTE_ERROR,
+ INTERNAL_ERROR, TYPE_ERROR, VALUE_ERROR,
};
use super::{int32, parse_dtype, tensor_var};
@@ -487,8 +487,8 @@ fn is_block_registered(block: &StaticInitBlock) -> bool {
}
fn launch_body_params(call: &CallObj) -> Result<Array<Var>> {
- let tag = call.args.get(0)?.try_cast::<StringImm>()?;
- let extent_ty: PrimType = call.args.get(1)?.ty.clone().try_cast()?;
+ let tag = StringImm::try_from(call.args.get(0)?)?;
+ let extent_ty: PrimType = PrimType::try_from(&call.args.get(1)?.ty)?;
let dtype = extent_ty.dtype;
if tag.value.as_str().is_empty() {
let message = "Check failed: (!tag->value.empty()) is false:
launch_thread expects a \
@@ -616,7 +616,11 @@ fn static_init_blocks_define_operators_and_types() {
// The type `register_type` registers with them: tvm-ffi constructs it
from its fields,
// positionally or by keyword, and reads it back from a JSON graph.
- let init = Function::from_type_attr(BlockTypeObj::type_index(),
"__ffi_init__").unwrap();
+ let init: Function =
tvm_ffi::reflection::TypeAttrColumn::new("__ffi_init__")
+ .and_then(|column| column.get(BlockTypeObj::type_index()))
+ .unwrap()
+ .try_into()
+ .unwrap();
let kwargs = global("ffi.GetKwargsObject").call_tuple(()).unwrap();
let (elem, count, four) = (Type::from(PrimType::int(32)),
FfiString::from("count"), 4i64);
let built = init
diff --git a/rust/tests/ir/prim.rs b/rust/tests/ir/prim.rs
index 753d72f80..58bbc3ae6 100644
--- a/rust/tests/ir/prim.rs
+++ b/rust/tests/ir/prim.rs
@@ -26,7 +26,7 @@ mod vector_expr;
use tvm_tirx::ir::prim;
use tvm_tirx::ir::{UNKNOWN_LOC, Expr, IntImm, PrimType, PrimVar};
-use tvm_tirx::tvm_ffi::{DLDataTypeExt, ObjectRefCast};
+use tvm_tirx::tvm_ffi::{DLDataTypeExt, ObjectRefCore};
use crate::common::serial;
@@ -37,12 +37,12 @@ fn var(name: &str, ty: PrimType) -> PrimVar {
/// The dtype of a primitive expression, by name.
fn dtype(expr: &impl AsRef<Expr>) -> String {
- let ty: PrimType = expr.as_ref().ty.clone().try_cast().unwrap();
+ let ty: PrimType = expr.as_ref().ty.clone().downcast().unwrap();
ty.dtype.to_string().as_str().to_owned()
}
fn int_value(expr: impl Into<Expr>) -> i64 {
- let imm: IntImm = expr.into().try_cast().unwrap();
+ let imm: IntImm = expr.into().downcast().unwrap();
imm.value.to_i64().unwrap()
}
diff --git a/rust/tests/ir/prim/op.rs b/rust/tests/ir/prim/op.rs
index 6b546de34..6f2316e00 100644
--- a/rust/tests/ir/prim/op.rs
+++ b/rust/tests/ir/prim/op.rs
@@ -31,8 +31,7 @@ use tvm_tirx::ir::{
};
use tvm_tirx::sym;
use tvm_tirx::tvm_ffi::{
- Any, AnyCompatible, AnyView, BigInt, ObjectRefCast, ObjectRefCore, Result,
String as FfiString,
- TYPE_ERROR,
+ Any, AnyCompatible, AnyView, BigInt, ObjectRefCore, Result, String as
FfiString, TYPE_ERROR,
};
use super::{dtype, int_value, var};
@@ -431,20 +430,20 @@ fn located_variants() {
let _serial = serial();
let x = var("x", PrimType::int(32));
let here: Location = SourceLoc::new(SourceName::get("ops.rs").unwrap(), 1,
2, 3, 4).into();
- let located: prim::FloorDiv = op::floordiv_at(&x, 4,
here.clone()).unwrap().try_cast().unwrap();
+ let located: prim::FloorDiv = op::floordiv_at(&x, 4,
here.clone()).unwrap().downcast().unwrap();
assert!(located.loc.same_as(&here));
- let unlocated: prim::FloorDiv = op::floordiv(&x,
4).unwrap().try_cast().unwrap();
+ let unlocated: prim::FloorDiv = op::floordiv(&x,
4).unwrap().downcast().unwrap();
assert!(unlocated.loc.downcast_ref::<UnknownLocObj>().is_some());
// A folded constant is at the unknown location, as C++ `TryConstFold`
builds it.
- let folded: IntImm = op::add_at(1, 2,
here.clone()).unwrap().try_cast().unwrap();
+ let folded: IntImm = op::add_at(1, 2,
here.clone()).unwrap().downcast().unwrap();
assert!(folded.loc.downcast_ref::<UnknownLocObj>().is_some());
- let cast: Cast = op::cast_at(&x, PrimType::int(64),
here.clone()).unwrap().try_cast().unwrap();
+ let cast: Cast = op::cast_at(&x, PrimType::int(64),
here.clone()).unwrap().downcast().unwrap();
assert!(cast.loc.same_as(&here));
let call: Call =
- op::exp_at(var("f", PrimType::float(32)),
here.clone()).unwrap().try_cast().unwrap();
+ op::exp_at(var("f", PrimType::float(32)),
here.clone()).unwrap().downcast().unwrap();
assert!(call.loc.same_as(&here));
let limit: IntImm =
- op::max_value_at(PrimType::int(8),
here.clone()).unwrap().try_cast().unwrap();
+ op::max_value_at(PrimType::int(8),
here.clone()).unwrap().downcast().unwrap();
assert!(limit.loc.same_as(&here));
}
@@ -859,11 +858,11 @@ fn arithmetic_operators() {
assert_eq!(folded!(op::shift_left, 1, 3), 8);
assert_eq!(folded!(op::shift_right, 8, 3), 1);
let not = op::bitwise_not(0).unwrap();
- assert!(not.try_cast::<prim::BitwiseNot>().is_ok(), "the node, not
folded");
+ assert!(not.downcast::<prim::BitwiseNot>().is_ok(), "the node, not
folded");
// On a variable they build the nodes.
let floordiv = op::floordiv(&x, 2).unwrap();
- assert!(floordiv.try_cast::<prim::FloorDiv>().is_ok());
+ assert!(floordiv.downcast::<prim::FloorDiv>().is_ok());
assert_eq!(dtype(&op::pow(2.0f32, 3.0f32).unwrap()), "float32");
}
@@ -875,11 +874,11 @@ fn comparison_and_logic_operators() {
for cmp in [op::eq, op::ne, op::lt, op::le, op::gt, op::ge] {
assert_eq!(dtype(&cmp(PrimExpr::from(&x), one.clone()).unwrap()),
"bool");
}
- assert!(op::lt(&x, &one).unwrap().try_cast::<prim::LT>().is_ok());
+ assert!(op::lt(&x, &one).unwrap().downcast::<prim::LT>().is_ok());
let conds = [op::lt(&x, &one).unwrap(), op::gt(&x, -5).unwrap()];
- assert!(op::all(conds.clone()).unwrap().try_cast::<prim::And>().is_ok());
- assert!(op::any(conds.clone()).unwrap().try_cast::<prim::Or>().is_ok());
+ assert!(op::all(conds.clone()).unwrap().downcast::<prim::And>().is_ok());
+ assert!(op::any(conds.clone()).unwrap().downcast::<prim::Or>().is_ok());
assert!(structural_equal(&op::all([&conds[0]]).unwrap(), &conds[0]));
assert!(op::any(Vec::<PrimExpr>::new()).is_err());
assert!(structural_equal(
@@ -916,7 +915,7 @@ fn math_operators() {
assert_eq!(int_value(op::abs(-3).unwrap()), 3);
assert_eq!(int_value(op::max_value(PrimType::int(8)).unwrap()), 127);
assert_eq!(int_value(op::min_value(PrimType::int(8)).unwrap()), -128);
- let inf: FloatImm =
op::infinity(PrimType::float(32)).unwrap().try_cast().unwrap();
+ let inf: FloatImm =
op::infinity(PrimType::float(32)).unwrap().downcast().unwrap();
assert!(inf.value.is_infinite());
}
@@ -932,26 +931,26 @@ fn make_const() {
assert!(op::make_const(PrimType::uint(8), -1).is_err());
assert!(op::make_const(PrimType::int(8), 128).is_err());
for ty in [PrimType::float(16), PrimType::bfloat(16), PrimType::float(64)]
{
- let two: FloatImm = op::make_const(ty.clone(),
2).unwrap().try_cast().unwrap();
+ let two: FloatImm = op::make_const(ty.clone(),
2).unwrap().downcast().unwrap();
assert_eq!(two.value, 2.0);
assert!(structural_equal(&two.ty, &ty));
}
// A float value too, as C++ `MakeConst(ty, double)`.
- let half: FloatImm = op::make_const(PrimType::float(32),
0.5).unwrap().try_cast().unwrap();
+ let half: FloatImm = op::make_const(PrimType::float(32),
0.5).unwrap().downcast().unwrap();
assert_eq!(half.value, 0.5);
assert_eq!(int_value(op::make_const(PrimType::int(32), 2.0).unwrap()), 2);
assert!(op::make_const(PrimType::void(), 0).is_err());
let vector = op::make_const(PrimType::int(32).with_lanes(4).unwrap(),
1).unwrap();
assert_eq!(dtype(&vector), "int32x4");
- let broadcast: prim::Broadcast = vector.try_cast().unwrap();
+ let broadcast: prim::Broadcast = vector.downcast().unwrap();
assert_eq!(int_value(broadcast.value.clone()), 1);
assert_eq!(int_value(broadcast.lanes.clone()), 4);
let scalable = PrimType::int(32).with_scalable_lanes(4).unwrap();
let vector = op::make_const(scalable.clone(), 1).unwrap();
assert!(structural_equal(&vector.ty, &scalable));
- let broadcast: prim::Broadcast = vector.try_cast().unwrap();
+ let broadcast: prim::Broadcast = vector.downcast().unwrap();
let lanes = broadcast.lanes.downcast_ref::<prim::MulObj>().expect("vscale
* 4");
assert_eq!(int_value(lanes.b.clone()), 4);
}
diff --git a/rust/tests/sym/int_set.rs b/rust/tests/sym/int_set.rs
index 44a0d37a0..7263f5254 100644
--- a/rust/tests/sym/int_set.rs
+++ b/rust/tests/sym/int_set.rs
@@ -21,7 +21,7 @@
use tvm_tirx::ir::{IntImm, Location, PrimExpr, Range, Var};
use tvm_tirx::sym::*;
-use tvm_tirx::tvm_ffi::{Map, Object, ObjectRefCast};
+use tvm_tirx::tvm_ffi::{Map, Object, ObjectRefCore};
use super::{fixture, int32, op, range, var, Fixture};
use crate::common::{assert_type_contracts, global};
@@ -47,8 +47,8 @@ fn interval_sets_are_read_through_accessors() {
.unwrap()
.try_into()
.unwrap();
- let interval: IntervalSet = set.try_cast().unwrap();
- let as_int = |expr: PrimExpr|
expr.try_cast::<IntImm>().unwrap().value.to_i64().unwrap();
+ let interval: IntervalSet = set.downcast().unwrap();
+ let as_int = |expr: PrimExpr|
expr.downcast::<IntImm>().unwrap().value.to_i64().unwrap();
assert_eq!(as_int(interval.min_value().unwrap()), 2);
assert_eq!(as_int(interval.max_value().unwrap()), 20);
}
diff --git a/rust/tests/sym/iter_affine_map.rs
b/rust/tests/sym/iter_affine_map.rs
index efb85f5f9..8b8ca0b26 100644
--- a/rust/tests/sym/iter_affine_map.rs
+++ b/rust/tests/sym/iter_affine_map.rs
@@ -21,7 +21,7 @@
use tvm_tirx::ir::{ExprObj, IntImm, PrimExpr, PrimVar, Range, Var};
use tvm_tirx::sym::*;
-use tvm_tirx::tvm_ffi::{Array, Map, Object, ObjectIdentity, ObjectRefCast};
+use tvm_tirx::tvm_ffi::{Array, Map, Object, ObjectIdentity, ObjectRefCore};
use super::{fixture, int32, op, range, var, Fixture};
use crate::common::{assert_type_contracts, global};
@@ -37,8 +37,8 @@ fn generated_types_match_the_registry() {
}
fn mark_is(mark: &IterMark, var: &PrimVar, extent: i64) -> bool {
- let source: PrimVar = mark.source.clone().try_cast().unwrap();
- let extent_imm: IntImm = mark.extent.clone().try_cast().unwrap();
+ let source: PrimVar = mark.source.clone().downcast().unwrap();
+ let extent_imm: IntImm = mark.extent.clone().downcast().unwrap();
ObjectIdentity::of(&source) == ObjectIdentity::of(var)
&& extent_imm.value.to_i64() == Some(extent)
}
@@ -62,7 +62,7 @@ fn iter_maps_decompose_into_marks_and_splits() {
result.errors.iter().map(|e| e.to_string()).collect::<Vec<_>>()
);
assert_eq!(result.indices.len(), 2);
- let as_int = |expr: PrimExpr|
expr.try_cast::<IntImm>().unwrap().value.to_i64().unwrap();
+ let as_int = |expr: PrimExpr|
expr.downcast::<IntImm>().unwrap().value.to_i64().unwrap();
// Each index is one split of a mark of extent 4, whose source is itself a
sum over the
// mark of x on [0, 16): x // 4 takes lower factor 4 of it, x % 4 lower
factor 1.
let only_split = |sum: &IterSumExpr| -> IterSplitExpr {
@@ -76,7 +76,7 @@ fn iter_maps_decompose_into_marks_and_splits() {
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().try_cast().unwrap();
+ let inner_sum: IterSumExpr = mark.source.clone().downcast().unwrap();
let inner = only_split(&inner_sum);
let x_mark: IterMark = inner.source().unwrap();
assert!(mark_is(&x_mark, &x, 16));
diff --git a/rust/tests/target/main.rs b/rust/tests/target/main.rs
index 9740e2e0e..c05d203da 100644
--- a/rust/tests/target/main.rs
+++ b/rust/tests/target/main.rs
@@ -24,7 +24,7 @@
mod common;
use tvm_tirx::target::{self, Target, TargetKind, TargetKindObj, TargetObj};
-use tvm_tirx::tvm_ffi::{Any, Map, Object, ObjectRefCast, String as FfiString,
TypeIndex};
+use tvm_tirx::tvm_ffi::{Any, Map, Object, ObjectRefCore, String as FfiString,
TypeIndex};
use common::{assert_type_contracts, empty_module, global, load_llvm_backend};
@@ -70,9 +70,9 @@ fn native_targets_are_read_through_accessors() {
.unwrap()
.try_into()
.unwrap();
- let host: Target = with_host.host().unwrap().unwrap().try_cast().unwrap();
+ let host: Target = with_host.host().unwrap().unwrap().downcast().unwrap();
assert_eq!(host.kind().unwrap().name().unwrap().as_str(), "llvm");
-
assert!(with_host.host().unwrap().unwrap().try_cast::<TargetKind>().is_err());
+
assert!(with_host.host().unwrap().unwrap().downcast::<TargetKind>().is_err());
}
#[test]
diff --git a/rust/tests/tirx/main.rs b/rust/tests/tirx/main.rs
index 8a58df347..a827743aa 100644
--- a/rust/tests/tirx/main.rs
+++ b/rust/tests/tirx/main.rs
@@ -45,7 +45,7 @@ use tvm_tirx::ir::{
};
use tvm_tirx::runtime::MemoryScope;
use tvm_tirx::tirx::{Axis, Function, Iter, TileLayout};
-use tvm_tirx::tvm_ffi::{Array, Map, ObjectRefCast, String as FfiString};
+use tvm_tirx::tvm_ffi::{Array, Map, ObjectRefCore, String as FfiString};
use common::global;
@@ -62,7 +62,7 @@ fn var(name: &str, ty: impl Into<Type>) -> Var {
}
fn prim_var(name: &str, ty: impl Into<PrimType>) -> PrimVar {
- var(name, ty.into()).try_cast().unwrap()
+ var(name, ty.into()).downcast().unwrap()
}
fn op(name: &str, a: impl Into<Expr>, b: impl Into<Expr>) -> PrimExpr {
@@ -77,8 +77,8 @@ fn range(extent: i64) -> Range {
.unwrap()
}
-fn as_i64(expr: &(impl ObjectRefCast + Clone)) -> i64 {
- expr.clone().try_cast::<IntImm>().unwrap().value.to_i64().unwrap()
+fn as_i64(expr: &impl ObjectRefCore) -> i64 {
+ expr.downcast_ref::<IntImm>().unwrap().value.to_i64().unwrap()
}
/// A new scope of the test's own, since the builtin ones cannot be registered
again.
diff --git a/rust/tests/tirx/op.rs b/rust/tests/tirx/op.rs
index 8629889be..7a3cb1c58 100644
--- a/rust/tests/tirx/op.rs
+++ b/rust/tests/tirx/op.rs
@@ -25,9 +25,7 @@ use tvm_tirx::ir::{
StringImm, Type, UNKNOWN_LOC,
};
use tvm_tirx::tirx::{fast_erf_float_expr, gpu_thread_return, logaddexp,
reinterpret};
-use tvm_tirx::tvm_ffi::{
- AnyView, DLDataTypeExt, Function, ObjectRefCast, ObjectRefCore, String as
FfiString,
-};
+use tvm_tirx::tvm_ffi::{AnyView, DLDataTypeExt, Function, ObjectRefCore,
String as FfiString};
use super::{memory_scope, var};
use crate::common::{agree, global, serial, structural_equal};
@@ -154,5 +152,5 @@ fn fast_erf_follows_the_native_lowering() {
// The operator chain checks its operands as C++ does: an integer argument
is matched to the
// float constants; a non-primitive one now fails the `PrimVar` check
before the call.
assert!(fast_erf_float_expr(prim_var("int32"), 32).is_ok());
- assert!(var("s", ptr("int8")).try_cast::<PrimVar>().is_err());
+ assert!(var("s", ptr("int8")).downcast::<PrimVar>().is_err());
}
diff --git a/rust/tests/tirx/structural_map_with_constraint_context.rs
b/rust/tests/tirx/structural_map_with_constraint_context.rs
index a97ac30ea..c50b48835 100644
--- a/rust/tests/tirx/structural_map_with_constraint_context.rs
+++ b/rust/tests/tirx/structural_map_with_constraint_context.rs
@@ -92,7 +92,7 @@ fn
ordered_mapping_collects_result_facts_and_restores_scopes() {
.value
.to_i64()
.unwrap(),
- context.to_array().iter().collect::<Vec<_>>(),
+
context.to_array().iter().cloned().collect::<Vec<_>>(),
));
Unchanged
},
diff --git a/rust/tests/tirx/structural_mutate_with_constraint_context.rs
b/rust/tests/tirx/structural_mutate_with_constraint_context.rs
index 4309d7d16..86ded3449 100644
--- a/rust/tests/tirx/structural_mutate_with_constraint_context.rs
+++ b/rust/tests/tirx/structural_mutate_with_constraint_context.rs
@@ -70,7 +70,7 @@ impl Rewrite {
view: &mut View<'_, Self>,
) -> Result<UnchangedOr<Any>> {
let marker =
node.value.downcast_ref::<IntImmObj>().unwrap().value.to_i64().unwrap();
- self.facts.push((marker,
view.base().constraints().to_array().iter().collect()));
+ self.facts.push((marker,
view.base().constraints().to_array().iter().cloned().collect()));
view.default_mutate(self, node)
}
fn mutate_for(
diff --git a/rust/tests/tirx/structural_visit_with_constraint_context.rs
b/rust/tests/tirx/structural_visit_with_constraint_context.rs
index a26641601..1d7276712 100644
--- a/rust/tests/tirx/structural_visit_with_constraint_context.rs
+++ b/rust/tests/tirx/structural_visit_with_constraint_context.rs
@@ -55,7 +55,10 @@ impl Observe {
self.array = Some(context.to_array());
self.live = Some(context.clone());
}
- self.facts.push((value.value.to_i64().unwrap(),
context.to_array().iter().collect()));
+ self.facts.push((
+ value.value.to_i64().unwrap(),
+ context.to_array().iter().cloned().collect(),
+ ));
}
visitor.default_visit(self, node)
}
@@ -172,7 +175,7 @@ fn interrupts_restore_native_scope_and_errors_terminate() {
if self.fail {
Err(Error::new(RUNTIME_ERROR, "constraint stop", ""))
} else {
- Ok(Some(VisitInterrupt::with(17_i64)))
+ Ok(Some(VisitInterrupt::new(17_i64)))
}
}
}
@@ -205,7 +208,10 @@ fn
lazy_call_arms_gain_predicates_but_eager_select_arms_do_not() {
) -> Result<Option<VisitInterrupt>> {
let value = node.value.to_i64().unwrap();
if [21, 22, 31, 32].contains(&value) {
- self.0.push((value,
visitor.base().constraints().to_array().iter().collect()));
+ self.0.push((
+ value,
+
visitor.base().constraints().to_array().iter().cloned().collect(),
+ ));
}
Ok(None)
}
diff --git a/rust/tests/tirx/structural_walk_with_constraint_context.rs
b/rust/tests/tirx/structural_walk_with_constraint_context.rs
index 8ce561aeb..2cb1c34f8 100644
--- a/rust/tests/tirx/structural_walk_with_constraint_context.rs
+++ b/rust/tests/tirx/structural_walk_with_constraint_context.rs
@@ -86,7 +86,7 @@ fn
typed_walk_callbacks_collect_facts_and_restore_analyzer_scopes() {
let marker =
&node.value.downcast_ref::<IntImmObj>().unwrap().value;
facts.push((
marker.to_i64().unwrap(),
- context.to_array().iter().collect::<Vec<_>>(),
+
context.to_array().iter().cloned().collect::<Vec<_>>(),
));
analyzer.sync_constraint_context(context)?;
loop_bounds.push(if
analyzer.const_int_bound_is_bound(&i)? {
diff --git a/rust/tests/tirx/tile/dispatch.rs b/rust/tests/tirx/tile/dispatch.rs
index d40ab38cc..f30f16130 100644
--- a/rust/tests/tirx/tile/dispatch.rs
+++ b/rust/tests/tirx/tile/dispatch.rs
@@ -23,7 +23,7 @@ use tvm_tirx::ir::{Location, UNKNOWN_LOC, PrimExpr, PrimType,
Stmt, Var};
use tvm_tirx::target::Target;
use tvm_tirx::tirx::tile::DispatchContext;
use tvm_tirx::tirx::{TensorType, ThreadScope};
-use tvm_tirx::tvm_ffi::{Any, Map, ObjectRefCast, String as FfiString};
+use tvm_tirx::tvm_ffi::{Any, Map, ObjectRefCore, String as FfiString};
use crate::common::{global, serial, structural_equal};
use crate::{int32, memory_scope, prim_var, var};
@@ -53,7 +53,7 @@ fn dispatch_contexts() {
assert!(ctx.cache_get("key").unwrap().is_none());
ctx.cache_set("key", &tx_var).unwrap();
let cached = ctx.cache_get("key").unwrap().unwrap();
- assert!(structural_equal(&cached.try_cast::<Var>().unwrap(), &tx_var));
+ assert!(structural_equal(&cached.downcast::<Var>().unwrap(), &tx_var));
let stmt: Stmt = global("ir.Evaluate")
.call_tuple((int32(0), Location::unknown()))