tvm_ffi::extra::structural_mutate

Struct MutationView

Source
pub struct MutationView<'a, T = Any> { /* private fields */ }
Expand description

A non-owning, move-only view carrying in-place permission.

This view cannot be copied or cloned. Consuming it transfers the same permission; narrowing its matched type does not acquire ownership.

Unlike an owning typed argument, this handle does not increment the reference count. Borrow through it to inspect the node, then consume it in default_mutate to continue recursion. A surviving owning alias still forces copying. Node borrows come from this handle, not from the callback context, so the handle can safely be passed to another context. T selects the callback’s matched FFI type; Any matches every value. The same handle is passed to consuming Dispatcher handlers. A publicly shared-borrow handle always disallows reuse. An exclusive &mut Any borrow grants permission to attempt reuse while keeping its owner borrowed.

A node borrowed through a copied view cannot survive consumption of the handle:

ⓘ
use tvm_ffi::{StructuralMutatorView, MutationView};
fn invalid<D>(value: MutationView<'_>, dispatch: &mut D, mutator: &mut StructuralMutatorView<'_, D>) {
    let view = value.as_any_view();
    let copy = view;
    let node = copy.downcast_ref::<tvm_ffi::collections::array::ArrayObj>().unwrap();
    mutator.default_mutate(dispatch, value).unwrap();
    println!("{}", node.size);
}

Moving the handle into a nested callback cannot bypass that borrow:

ⓘ
use tvm_ffi::{dispatch, structural_mutate, Any, MutationView, StructuralMutatorView, Result};
struct Inner<'a>(Option<MutationView<'a>>);
#[dispatch(mutate, MutationView)]
impl<'a> Inner<'a> {
    fn mutate_bool(&mut self, _: bool, mutator: &mut StructuralMutatorView<'_, Self>) -> Result<Any> {
        let pending = self.0.take().unwrap();
        mutator.default_mutate(self, pending).map(Into::into)
    }
}
fn invalid(value: MutationView<'_>) {
    let view = value.as_any_view();
    let node = view.downcast_ref::<tvm_ffi::collections::array::ArrayObj>().unwrap();
    structural_mutate(true, Inner(Some(value))).unwrap();
    println!("{}", node.size);
}

A copied inspection view also cannot survive low-level default mutation:

ⓘ
use tvm_ffi::{dispatch, Any, MutationView, StructuralMutatorView, Result, Unchanged};
struct Pass;
#[dispatch(mutate, MutationView)]
impl Pass {
    fn mutate_any(&mut self, value: MutationView<'_>, mutator: &mut StructuralMutatorView<'_, Self>) -> Result<Any> {
        let view = value.as_any_view();
        let copy = view;
        mutator.default_mutate(self, value).unwrap();
        println!("{}", copy.type_index());
        Ok(Any::from(Unchanged))
    }
}

Implementations§

Source§

impl<'a> MutationView<'a>

Source

pub fn borrowed(value: AnyView<'a>) -> Self

Wrap a borrowed value without granting in-place permission.

Source§

impl<'a, T> MutationView<'a, T>

Source

pub fn inplace_mode(&self) -> InplaceMode

Permission carried independently of temporary owning aliases.

Source

pub fn with_inplace_mode(self, requested: InplaceMode) -> Self

Restrict permission without upgrading a shared-borrow capability.

Source

pub fn as_any_view(&self) -> AnyView<'_>

Borrow the current value. The view and its copies borrow this handle, so their last use must precede consuming it for default mutation.

Source

pub fn downcast_ref<U: ObjectCore>(&self) -> Option<&U>

Borrow an object or subtype as U without changing ownership or permission. The reference borrows this capability and cannot survive its consumption.

Source

pub fn try_cast<U: ContainerElement>(self) -> Result<MutationView<'a, U>, Self>

Narrow the matched type without acquiring an owning reference.

Source

pub fn into_untyped(self) -> MutationView<'a>

Erase the matched type while preserving the carried permission.

Source§

impl<T: ObjectRefCore> MutationView<'_, T>

Source

pub fn field<U: MutationField>( &mut self, selector: impl for<'node> FnOnce(&'node T::ContainerType) -> &'node U, ) -> MutationView<'_, U>

Borrow a direct owning field while exclusively borrowing this capability. Permission also requires the parent to remain unique after selection. This does not grant writeback to the parent field.

Panics if the selector returns storage outside the parent representation.

Trait Implementations§

Source§

impl<T: ObjectRefCore> Deref for MutationView<'_, T>

Source§

type Target = <T as ObjectRefCore>::ContainerType

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl<'a, T> From<&'a MutationView<'_, T>> for AnyView<'a>

Source§

fn from(value: &'a MutationView<'_, T>) -> Self

Converts to this type from the input type.
Source§

impl<'a> From<&'a mut Any> for MutationView<'a>

Source§

fn from(value: &'a mut Any) -> Self

Borrow an owner exclusively without acquiring a reference count. Reuse still requires the runtime’s uniqueness and alias checks.

Auto Trait Implementations§

§

impl<'a, T> Freeze for MutationView<'a, T>

§

impl<'a, T> RefUnwindSafe for MutationView<'a, T>

§

impl<'a, T = Any> !Send for MutationView<'a, T>

§

impl<'a, T = Any> !Sync for MutationView<'a, T>

§

impl<'a, T> Unpin for MutationView<'a, T>

§

impl<'a, T> UnwindSafe for MutationView<'a, T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.