Skip to main content

tvm_ffi/extra/
structural_mutate.rs

1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements.  See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership.  The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License.  You may obtain a copy of the License at
9 *
10 *   http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied.  See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20//! Native Rust structural mutation and mapping.
21//!
22//! [`structural_mutate`] lets a mutator drive recursion, while
23//! [`structural_map`] applies callbacks around engine-owned recursion.
24
25use std::cell::{Cell, RefCell};
26use std::collections::HashMap;
27use std::ffi::c_void;
28use std::marker::PhantomData;
29use std::ops::{ControlFlow, Deref};
30use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
31use std::ptr::NonNull;
32use std::rc::Rc;
33use std::sync::atomic::{AtomicUsize, Ordering};
34use std::sync::LazyLock;
35
36use crate::any::{Any, AnyView};
37use crate::error::{Error, Result, RUNTIME_ERROR, TYPE_ERROR};
38use crate::function::Function;
39use crate::object::{self, Object, ObjectArc, ObjectCore};
40use crate::reflection::TypeAttrColumn;
41use crate::tvm_ffi_sys::TVMFFIFieldFlagBitMask::{
42    kTVMFFIFieldFlagBitMaskSEqHashIgnore, kTVMFFIFieldFlagBitSetterIsFunctionObj,
43};
44use crate::tvm_ffi_sys::{
45    TVMFFIAny, TVMFFIAnyViewToOwnedAny, TVMFFIByteArray, TVMFFIFieldInfo, TVMFFIFieldSetter,
46    TVMFFIFunctionCall, TVMFFIGetTypeInfo, TVMFFIObject, TVMFFITypeAttrColumn, TVMFFITypeIndex,
47    TVMFFITypeKeyToIndex,
48};
49use crate::tvm_ffi_sys::{TVMFFIObjectHandle, TVMFFISEqHashKind};
50
51use super::structural_common::{
52    impl_callback_chain_tuple_arities, is_plain_inline, same_shallow,
53    try_to_owned_without_normalization, with_structural_error_context, with_visit_error_context,
54};
55use super::structural_visit::{
56    field_def_region, for_each_field_info, free_var_child_region, type_attr_column, type_key_of,
57    DefRegionKind, WalkOrder,
58};
59use super::unchanged::is_unchanged;
60pub use super::unchanged::{Unchanged, UnchangedOr};
61
62const STRUCTURAL_MUTATE_ATTR: &str = "__s_mutate__";
63const STRUCTURAL_MAYBE_INPLACE_MUTATE_ATTR: &str = "__s_maybe_inplace_mutate__";
64const SHALLOW_COPY_ATTR: &str = "__ffi_shallow_copy__";
65const FLAG_SEQ_HASH_IGNORE: i64 = kTVMFFIFieldFlagBitMaskSEqHashIgnore as i64;
66const FLAG_SETTER_IS_FUNCTION: i64 = kTVMFFIFieldFlagBitSetterIsFunctionObj as i64;
67
68/// Borrowed value passed to structural map and mutation callbacks.
69pub use super::StructuralView;
70
71mod policy;
72pub use policy::{DefaultMutContextPolicy, MapWithContextPolicy, MutContextPolicy};
73
74mod callback_result_sealed {
75    use super::{Any, Result};
76
77    pub trait Sealed {}
78
79    impl<T: Into<Any>> Sealed for T {}
80    impl<T: Into<Any>> Sealed for Result<T> {}
81}
82
83/// Convert an infallible or fallible map or mutation callback result into [`Result<Any>`].
84///
85/// A callback may return any value convertible into [`Any`], or wrap it in
86/// [`Result`] to use `?`.
87///
88/// This trait is sealed and is not an extension point.
89#[doc(hidden)]
90pub trait IntoMutateResult: callback_result_sealed::Sealed {
91    fn into_mutate_result(self) -> Result<Any>;
92}
93
94impl<T: Into<Any>> IntoMutateResult for T {
95    #[inline]
96    fn into_mutate_result(self) -> Result<Any> {
97        Ok(self.into())
98    }
99}
100
101impl<T: Into<Any>> IntoMutateResult for Result<T> {
102    #[inline]
103    fn into_mutate_result(self) -> Result<Any> {
104        self.map(Into::into)
105    }
106}
107
108/// Permission to attempt in-place structural mutation along an owned path.
109///
110/// `Allow` still requires unique ownership; it does not grant permission to
111/// modify a borrowed value. Use an owned value or an engine-issued
112/// [`InplaceValue`] with the mode-aware mutation helpers.
113#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
114pub enum InplaceMode {
115    /// Use ordinary mutation, including for uniquely owned values.
116    #[default]
117    Disallow,
118    /// Permit reuse when ownership and alias checks allow it.
119    Allow,
120}
121
122impl InplaceMode {
123    fn permit(self) -> Permit {
124        match self {
125            Self::Disallow => Permit::Copy,
126            Self::Allow => Permit::MaybeInPlace,
127        }
128    }
129
130    fn permit_if_unique(self, raw: TVMFFIAny) -> Permit {
131        if self == Self::Allow && object_is_unique(raw) {
132            Permit::MaybeInPlace
133        } else {
134            Permit::Copy
135        }
136    }
137}
138
139/// A callback value carrying the engine's in-place permission.
140///
141/// Unlike an owning typed argument, this handle does not increment the reference
142/// count. Borrow through it to inspect the node, then consume it in
143/// `default_maybe_inplace_mutate` to continue recursion. A surviving owning alias
144/// still forces copying. Node borrows come from this handle, not from the
145/// callback context, so the handle can safely be passed to another context.
146/// `T` selects the callback's matched FFI type; `Any` matches every value.
147///
148/// A node borrow cannot survive consumption of the handle:
149/// ```compile_fail
150/// use tvm_ffi::{MutateContext, MutateValue};
151/// fn invalid(value: MutateValue<'_>, ctx: &mut MutateContext<'_>) {
152///     let node = value.as_node::<tvm_ffi::collections::array::ArrayObj>().unwrap();
153///     ctx.default_maybe_inplace_mutate(value).unwrap();
154///     println!("{}", node.size);
155/// }
156/// ```
157///
158/// Moving the handle into a nested callback cannot bypass that borrow:
159/// ```compile_fail
160/// use std::cell::RefCell;
161/// use tvm_ffi::{structural_mutate, MutateContext, MutateValue};
162/// fn invalid(value: MutateValue<'_>) {
163///     let node = value.as_node::<tvm_ffi::collections::array::ArrayObj>().unwrap();
164///     let pending = RefCell::new(Some(value));
165///     structural_mutate(true, |_: bool, inner: &mut MutateContext<'_>| {
166///         inner.default_maybe_inplace_mutate(pending.borrow_mut().take().unwrap())
167///     }).unwrap();
168///     println!("{}", node.size);
169/// }
170/// ```
171pub struct MutateValue<'a, T = Any> {
172    value: StructuralView,
173    mode: InplaceMode,
174    _scope: PhantomData<&'a StructuralView>,
175    _type: PhantomData<fn() -> T>,
176    _not_send_sync: PhantomData<Rc<()>>,
177}
178
179impl<'a> MutateValue<'a> {
180    fn new(value: &'a StructuralView, mode: InplaceMode) -> Self {
181        Self {
182            value: StructuralView::from_raw(value.raw()),
183            mode,
184            _scope: PhantomData,
185            _type: PhantomData,
186            _not_send_sync: PhantomData,
187        }
188    }
189
190    /// Wrap a borrowed value without granting in-place permission.
191    pub fn borrowed(value: &'a StructuralView) -> Self {
192        Self::new(value, InplaceMode::Disallow)
193    }
194}
195
196impl<'a, T> MutateValue<'a, T> {
197    /// Permission established before callback arguments acquire ownership.
198    pub fn inplace_mode(&self) -> InplaceMode {
199        self.mode
200    }
201
202    /// Borrow the current value. The borrow must end before default mutation.
203    pub fn as_value(&self) -> &StructuralView {
204        &self.value
205    }
206
207    /// Narrow the matched type without acquiring an owning reference.
208    pub fn try_cast<U: crate::type_traits::ContainerElement>(
209        self,
210    ) -> std::result::Result<MutateValue<'a, U>, Self> {
211        // SAFETY: the engine keeps the borrowed value live for this handle's
212        // lifetime. This only checks its type and does not acquire ownership.
213        if unsafe { U::container_check_any_strict(&self.value.raw()) } {
214            Ok(MutateValue {
215                value: self.value,
216                mode: self.mode,
217                _scope: PhantomData,
218                _type: PhantomData,
219                _not_send_sync: PhantomData,
220            })
221        } else {
222            Err(self)
223        }
224    }
225
226    /// Erase the matched type while preserving the engine-issued permission.
227    pub fn into_untyped(self) -> MutateValue<'a> {
228        MutateValue {
229            value: self.value,
230            mode: self.mode,
231            _scope: PhantomData,
232            _type: PhantomData,
233            _not_send_sync: PhantomData,
234        }
235    }
236
237    // Combine permissions here; policy entry and built-in descent recheck ownership.
238    fn permit(&self, requested: InplaceMode) -> Permit {
239        if self.mode == InplaceMode::Disallow {
240            Permit::Copy
241        } else {
242            requested.permit()
243        }
244    }
245}
246
247impl<T> Deref for MutateValue<'_, T> {
248    type Target = StructuralView;
249    fn deref(&self) -> &Self::Target {
250        self.as_value()
251    }
252}
253
254/// State and recursive operations shared by mutation callbacks and context policies.
255///
256/// A matched callback owns mutation of its value. Recursive operations
257/// reborrow the mutator, so mutable state cannot remain borrowed across them.
258/// The context does not store a node: inspect the callback argument and pass
259/// it explicitly to default recursion.
260pub struct MutateContext<'a, State = ()> {
261    driver: &'a mut dyn MutateContextDriver<State>,
262    def_region_kind: DefRegionKind,
263    inplace_mode: InplaceMode,
264    _not_send_sync: PhantomData<Rc<()>>,
265}
266
267/// Recursion control passed to a typed `#[dispatch(mutate)]` handler.
268///
269/// The dispatch object owns all pass state. Recursive operations take that
270/// object explicitly so Rust can safely reborrow the same `&mut self` for the
271/// child call. Node access comes only from the callback argument; default
272/// recursion takes that value explicitly.
273pub struct Mutator {
274    def_region_kind: DefRegionKind,
275    inplace_mode: InplaceMode,
276    _not_send_sync: PhantomData<Rc<()>>,
277}
278
279impl Mutator {
280    /// Engine-established permission for this callback's current value.
281    ///
282    /// This is not authority to modify a borrow: default in-place descent also
283    /// requires consuming a [`MutateValue`].
284    pub fn inplace_mode(&self) -> InplaceMode {
285        self.inplace_mode
286    }
287
288    /// Definition-region state active at the callback's current value.
289    #[inline(always)]
290    pub fn def_region_kind(&self) -> DefRegionKind {
291        self.def_region_kind
292    }
293
294    /// Mutate a borrowed child through the same typed dispatch object.
295    #[inline(always)]
296    pub fn mutate<D, T>(&mut self, dispatch: &mut D, value: &T) -> Result<Any>
297    where
298        D: MutateDispatch,
299        for<'x> AnyView<'x>: From<&'x T>,
300    {
301        StructuralMutator::mutate(dispatch, value, self.def_region_kind)
302    }
303
304    /// Mutate a borrowed child under an explicit definition-region state.
305    #[inline(always)]
306    pub fn mutate_with<D, T>(
307        &mut self,
308        dispatch: &mut D,
309        value: &T,
310        def_region_kind: DefRegionKind,
311    ) -> Result<Any>
312    where
313        D: MutateDispatch,
314        for<'x> AnyView<'x>: From<&'x T>,
315    {
316        StructuralMutator::mutate(dispatch, value, def_region_kind)
317    }
318
319    /// Mutate an owned child and permit reuse when it remains uniquely owned.
320    #[inline(always)]
321    pub fn maybe_inplace_mutate<D, T>(&mut self, dispatch: &mut D, value: T) -> Result<Any>
322    where
323        D: MutateDispatch,
324        T: Into<Any>,
325    {
326        self.maybe_inplace_mutate_with(dispatch, value, self.def_region_kind)
327    }
328
329    /// Mutate an owned child under an explicit definition-region state.
330    #[inline(always)]
331    pub fn maybe_inplace_mutate_with<D, T>(
332        &mut self,
333        dispatch: &mut D,
334        value: T,
335        def_region_kind: DefRegionKind,
336    ) -> Result<Any>
337    where
338        D: MutateDispatch,
339        T: Into<Any>,
340    {
341        self.maybe_inplace_mutate_with_mode(dispatch, value, def_region_kind, InplaceMode::Allow)
342    }
343
344    /// Mutate an owned child under an explicit region and in-place permission.
345    ///
346    /// `Disallow` keeps this input on the copy path even when uniquely owned.
347    #[inline(always)]
348    pub fn maybe_inplace_mutate_with_mode<D, T>(
349        &mut self,
350        dispatch: &mut D,
351        value: T,
352        def_region_kind: DefRegionKind,
353        mode: InplaceMode,
354    ) -> Result<Any>
355    where
356        D: MutateDispatch,
357        T: Into<Any>,
358    {
359        StructuralMutator::maybe_inplace_mutate_with_mode(dispatch, value, def_region_kind, mode)
360    }
361
362    /// Apply default copy-only mutation to an explicitly borrowed value.
363    #[inline(always)]
364    pub fn default_mutate<D, T>(&mut self, dispatch: &mut D, value: &T) -> Result<Any>
365    where
366        D: MutateDispatch,
367        for<'x> AnyView<'x>: From<&'x T>,
368    {
369        StructuralMutator::default_mutate(dispatch, value, self.def_region_kind)
370    }
371
372    /// Mutate a borrowed child while preserving an unchanged result.
373    #[inline]
374    pub fn mutate_result<D, T>(&mut self, dispatch: &mut D, value: &T) -> Result<UnchangedOr<Any>>
375    where
376        D: MutateDispatch,
377        for<'x> AnyView<'x>: From<&'x T>,
378    {
379        self.mutate_with_result(dispatch, value, self.def_region_kind)
380    }
381
382    /// Mutate a borrowed child under an explicit region, preserving unchanged.
383    #[inline]
384    pub fn mutate_with_result<D, T>(
385        &mut self,
386        dispatch: &mut D,
387        value: &T,
388        kind: DefRegionKind,
389    ) -> Result<UnchangedOr<Any>>
390    where
391        D: MutateDispatch,
392        for<'x> AnyView<'x>: From<&'x T>,
393    {
394        StructuralMutator::mutate_result(dispatch, value, kind)
395    }
396
397    /// Apply default mutation without materializing an unchanged original.
398    #[inline]
399    pub fn default_mutate_result<D, T>(
400        &mut self,
401        dispatch: &mut D,
402        value: &T,
403    ) -> Result<UnchangedOr<Any>>
404    where
405        D: MutateDispatch,
406        for<'x> AnyView<'x>: From<&'x T>,
407    {
408        StructuralMutator::default_mutate_result(dispatch, value, self.def_region_kind)
409    }
410
411    /// Consume the handle for default descent with its existing permission.
412    #[inline]
413    pub fn default_maybe_inplace_mutate<D: MutateDispatch, T>(
414        &mut self,
415        dispatch: &mut D,
416        value: MutateValue<'_, T>,
417    ) -> Result<Any> {
418        let mode = value.inplace_mode();
419        self.default_mutate_with_mode(dispatch, value, mode)
420    }
421
422    /// Consume the handle for default descent, preserving permission and `Unchanged`.
423    #[inline]
424    pub fn default_maybe_inplace_mutate_result<D: MutateDispatch, T>(
425        &mut self,
426        dispatch: &mut D,
427        value: MutateValue<'_, T>,
428    ) -> Result<UnchangedOr<Any>> {
429        let mode = value.inplace_mode();
430        self.default_mutate_with_mode_result(dispatch, value, mode)
431    }
432
433    /// Continue default mutation after relinquishing the callback value's borrows.
434    ///
435    /// The requested mode can restrict, but cannot upgrade, the engine-issued
436    /// permission. Retained owning aliases force copying.
437    pub fn default_mutate_with_mode<D: MutateDispatch, T>(
438        &mut self,
439        dispatch: &mut D,
440        value: MutateValue<'_, T>,
441        mode: InplaceMode,
442    ) -> Result<Any> {
443        let raw = value.value.raw();
444        let permit = value.permit(mode);
445        user_default_mutate(dispatch, raw, self.def_region_kind, permit)
446            .and_then(|result| resolve_result(result, raw))
447    }
448
449    /// Consume the callback value for default descent, preserving `Unchanged`.
450    pub fn default_mutate_with_mode_result<D: MutateDispatch, T>(
451        &mut self,
452        dispatch: &mut D,
453        value: MutateValue<'_, T>,
454        mode: InplaceMode,
455    ) -> Result<UnchangedOr<Any>> {
456        let permit = value.permit(mode);
457        user_default_mutate(dispatch, value.value.raw(), self.def_region_kind, permit)
458            .and_then(UnchangedOr::from_carrier)
459    }
460
461    /// Look up an invocation-local identity substitution.
462    #[inline(always)]
463    pub fn var_remap_get<D: MutateDispatch>(
464        &mut self,
465        dispatch: &mut D,
466        var: &StructuralView,
467    ) -> Result<Option<Any>> {
468        StructuralMutator::var_remap_get(dispatch, var)
469    }
470
471    /// Store an invocation-local identity substitution.
472    #[inline(always)]
473    pub fn var_remap_set<D: MutateDispatch>(
474        &mut self,
475        dispatch: &mut D,
476        var: &StructuralView,
477        mutated_value: &Any,
478    ) -> Result<()> {
479        StructuralMutator::var_remap_set(dispatch, var, mutated_value)
480    }
481}
482
483/// Internal operations used by [`MutateContext`].
484///
485/// Borrowed inputs carry a lifetime; in-place entry requires an owned
486/// value or a consumed capability, never a bare ABI value plus permission.
487trait MutateContextDriver<State> {
488    fn state(&self) -> &State;
489    fn state_mut(&mut self) -> &mut State;
490    fn mutate_borrowed(&mut self, value: AnyView<'_>, kind: DefRegionKind) -> Result<Any>;
491    fn mutate_owned(&mut self, value: Any, kind: DefRegionKind, mode: InplaceMode) -> Result<Any>;
492    fn default_mutate_borrowed(&mut self, value: AnyView<'_>, kind: DefRegionKind) -> Result<Any>;
493    /// Consume the handle to exclude node borrows before default descent.
494    fn default_mutate_value(
495        &mut self,
496        value: MutateValue<'_>,
497        kind: DefRegionKind,
498        _mode: InplaceMode,
499    ) -> Result<Any> {
500        self.default_mutate_borrowed(AnyView::from(value.as_value()), kind)
501    }
502    fn var_remap_get(&mut self, var: &StructuralView) -> Result<Option<Any>>;
503    fn var_remap_set(&mut self, var: &StructuralView, mutated_value: &Any) -> Result<()>;
504}
505
506impl<State> MutateContext<'_, State> {
507    /// User state shared by every callback in this mutation.
508    #[inline(always)]
509    pub fn state(&self) -> &State {
510        self.driver.state()
511    }
512
513    /// Mutably borrow the user state.
514    #[inline(always)]
515    pub fn state_mut(&mut self) -> &mut State {
516        self.driver.state_mut()
517    }
518
519    /// Engine-established permission for this callback's current value.
520    ///
521    /// This is not authority to modify a borrow: default in-place descent also
522    /// requires consuming a [`MutateValue`].
523    pub fn inplace_mode(&self) -> InplaceMode {
524        self.inplace_mode
525    }
526
527    /// Definition-region state active at the callback's current value.
528    #[inline(always)]
529    pub fn def_region_kind(&self) -> DefRegionKind {
530        self.def_region_kind
531    }
532
533    /// Run recursive operations in a definition region, preserving an outer Pattern.
534    /// The previous context is restored on return, error, or unwinding.
535    pub fn with_def_region_kind<T>(
536        &mut self,
537        kind: DefRegionKind,
538        callback: impl FnOnce(&mut MutateContext<'_, State>) -> Result<T>,
539    ) -> Result<T> {
540        with_mutation_region(kind, |kind| {
541            callback(&mut MutateContext {
542                driver: &mut *self.driver,
543                def_region_kind: kind,
544                inplace_mode: self.inplace_mode,
545                _not_send_sync: PhantomData,
546            })
547        })
548    }
549
550    /// Mutate a borrowed value through the same callback chain. The value and
551    /// its descendants begin on the non-in-place path.
552    #[inline(always)]
553    pub fn mutate<T>(&mut self, value: &T) -> Result<Any>
554    where
555        for<'x> AnyView<'x>: From<&'x T>,
556    {
557        self.mutate_with(value, self.def_region_kind)
558    }
559
560    /// Mutate a borrowed value under an explicit definition-region state.
561    #[inline(always)]
562    pub fn mutate_with<T>(&mut self, value: &T, def_region_kind: DefRegionKind) -> Result<Any>
563    where
564        for<'x> AnyView<'x>: From<&'x T>,
565    {
566        let view = AnyView::from(value);
567        self.driver
568            .mutate_borrowed(view, def_region_kind)
569            .and_then(|result| resolve_result(result, *view.as_raw_ffi_any()))
570    }
571
572    /// Mutate an owned value, allowing an in-place attempt when it remains
573    /// uniquely owned and no matched callback borrows it.
574    #[inline(always)]
575    pub fn maybe_inplace_mutate<T: Into<Any>>(&mut self, value: T) -> Result<Any> {
576        self.maybe_inplace_mutate_with(value, self.def_region_kind)
577    }
578
579    /// Mutate an owned value under an explicit definition-region state.
580    #[inline(always)]
581    pub fn maybe_inplace_mutate_with<T: Into<Any>>(
582        &mut self,
583        value: T,
584        def_region_kind: DefRegionKind,
585    ) -> Result<Any> {
586        self.maybe_inplace_mutate_with_mode(value, def_region_kind, InplaceMode::Allow)
587    }
588
589    /// Mutate an owned value under an explicit region and in-place permission.
590    ///
591    /// `Disallow` keeps this input on the copy path even when uniquely owned.
592    #[inline(always)]
593    pub fn maybe_inplace_mutate_with_mode<T: Into<Any>>(
594        &mut self,
595        value: T,
596        def_region_kind: DefRegionKind,
597        mode: InplaceMode,
598    ) -> Result<Any> {
599        self.driver
600            .mutate_owned(value.into(), def_region_kind, mode)
601    }
602
603    /// Apply default copy-only mutation to an explicitly borrowed value.
604    ///
605    /// This may be called repeatedly while holding node borrows. The value's
606    /// children re-enter callback dispatch, but the value itself does not.
607    #[inline(always)]
608    pub fn default_mutate<T>(&mut self, value: &T) -> Result<Any>
609    where
610        for<'x> AnyView<'x>: From<&'x T>,
611    {
612        let view = AnyView::from(value);
613        let raw = *view.as_raw_ffi_any();
614        self.driver
615            .default_mutate_borrowed(view, self.def_region_kind)
616            .and_then(|result| resolve_result(result, raw))
617    }
618
619    /// Mutate a borrowed child while preserving an unchanged result.
620    #[inline]
621    pub fn mutate_result<T>(&mut self, value: &T) -> Result<UnchangedOr<Any>>
622    where
623        for<'x> AnyView<'x>: From<&'x T>,
624    {
625        self.mutate_with_result(value, self.def_region_kind)
626    }
627
628    /// Mutate a borrowed child under an explicit region, preserving unchanged.
629    #[inline]
630    pub fn mutate_with_result<T>(
631        &mut self,
632        value: &T,
633        kind: DefRegionKind,
634    ) -> Result<UnchangedOr<Any>>
635    where
636        for<'x> AnyView<'x>: From<&'x T>,
637    {
638        let view = AnyView::from(value);
639        self.driver
640            .mutate_borrowed(view, kind)
641            .and_then(UnchangedOr::from_carrier)
642    }
643
644    /// Apply default mutation without materializing an unchanged original.
645    #[inline]
646    pub fn default_mutate_result<T>(&mut self, value: &T) -> Result<UnchangedOr<Any>>
647    where
648        for<'x> AnyView<'x>: From<&'x T>,
649    {
650        let view = AnyView::from(value);
651        self.driver
652            .default_mutate_borrowed(view, self.def_region_kind)
653            .and_then(UnchangedOr::from_carrier)
654    }
655
656    /// Consume the handle for default descent with its existing permission.
657    #[inline]
658    pub fn default_maybe_inplace_mutate<T>(&mut self, value: MutateValue<'_, T>) -> Result<Any> {
659        let mode = value.inplace_mode();
660        self.default_mutate_with_mode(value, mode)
661    }
662
663    /// Consume the handle for default descent, preserving permission and `Unchanged`.
664    #[inline]
665    pub fn default_maybe_inplace_mutate_result<T>(
666        &mut self,
667        value: MutateValue<'_, T>,
668    ) -> Result<UnchangedOr<Any>> {
669        let mode = value.inplace_mode();
670        self.default_mutate_with_mode_result(value, mode)
671    }
672
673    /// Continue default mutation after relinquishing the callback value's borrows.
674    ///
675    /// The mode can restrict, but cannot upgrade, the handle's permission.
676    /// Retained owning aliases force copying; temporary handles can be dropped
677    /// before this call to preserve reuse of the current value.
678    pub fn default_mutate_with_mode<T>(
679        &mut self,
680        value: MutateValue<'_, T>,
681        mode: InplaceMode,
682    ) -> Result<Any> {
683        let raw = value.value.raw();
684        self.driver
685            .default_mutate_value(value.into_untyped(), self.def_region_kind, mode)
686            .and_then(|result| resolve_result(result, raw))
687    }
688
689    /// Consume the callback value for default descent, preserving `Unchanged`.
690    pub fn default_mutate_with_mode_result<T>(
691        &mut self,
692        value: MutateValue<'_, T>,
693        mode: InplaceMode,
694    ) -> Result<UnchangedOr<Any>> {
695        self.driver
696            .default_mutate_value(value.into_untyped(), self.def_region_kind, mode)
697            .and_then(UnchangedOr::from_carrier)
698    }
699
700    /// Look up an invocation-local identity substitution.
701    #[inline(always)]
702    pub fn var_remap_get(&mut self, var: &StructuralView) -> Result<Option<Any>> {
703        self.driver.var_remap_get(var)
704    }
705
706    /// Store an invocation-local identity substitution.
707    #[inline(always)]
708    pub fn var_remap_set(&mut self, var: &StructuralView, mutated_value: &Any) -> Result<()> {
709        self.driver.var_remap_set(var, mutated_value)
710    }
711}
712
713/// Conversion into the mutator argument accepted by [`structural_mutate`].
714///
715/// Accepts a mutable low-level [`StructuralMutator`], a generated
716/// [`MutateDispatch`], or a first-match callback chain. Generated dispatch
717/// objects keep mutable pass state directly on themselves; [`MutateCallbacks`]
718/// remains available for closure callback chains with separate state.
719#[diagnostic::on_unimplemented(
720    message = "`{Self}` is not a supported `structural_mutate` mutator",
721    note = "accepted mutators: `&mut U` where `U: StructuralMutator`; a generated `MutateDispatch`; an `Fn` callback over an FFI value type `T`, `&N` of an object node type, or `&StructuralView`, or a consuming `MutateValue<T>`, followed by `&mut MutateContext<'_, State>`; or a tuple of up to 12 such callbacks (tuples may nest)",
722    note = "callback arguments need explicit type annotations; use `MutateCallbacks::new(state, callbacks)` for ordinary mutable callback state"
723)]
724pub trait IntoMutator<Marker> {
725    #[doc(hidden)]
726    fn mutate_root(self, root: Any) -> Result<Any>;
727}
728
729impl<U: StructuralMutator> IntoMutator<U> for &mut U {
730    fn mutate_root(self, root: Any) -> Result<Any> {
731        run_structural_mutator(root, self)
732    }
733}
734
735/// One typed callback in a callback-driven structural mutator.
736pub trait MutateChainLink<State, Marker>: mutate_sealed::SealedLink<State, Marker> {
737    #[doc(hidden)]
738    fn try_mutate(
739        &self,
740        value: &mut Option<MutateValue<'_>>,
741        mutator: &mut MutateContext<'_, State>,
742    ) -> Option<Result<Any>>;
743}
744
745/// Ordered typed callback dispatch for [`structural_mutate`].
746///
747/// `None` means no handler matched, so structural mutation applies its default
748/// behavior. A generated `#[dispatch(mutate)]` implementation tests
749/// `mutate_*` methods in source order and passes the same [`Mutator`] to the
750/// first match. The implementation owns its pass state and receives `&mut
751/// self`, while [`Mutator`] controls recursion, the definition region, and
752/// in-place permission. Handlers can consume [`MutateValue`] and take an
753/// optional `&mut Mutator` to inspect the region and in-place permission.
754pub trait MutateDispatch: Sized {
755    fn dispatch_mutate(
756        &mut self,
757        value: &StructuralView,
758        mutator: &mut Mutator,
759    ) -> Option<Result<Any>>;
760
761    /// Dispatch an engine-issued value. Existing borrowed dispatchers retain
762    /// their copy-only default recursion; generated dispatch supports consuming it.
763    fn dispatch_mutate_value(
764        &mut self,
765        value: MutateValue<'_>,
766        mutator: &mut Mutator,
767    ) -> Option<Result<Any>> {
768        self.dispatch_mutate(value.as_value(), mutator)
769    }
770
771    #[doc(hidden)]
772    fn on_default_mutate(&mut self, value: MutateValue<'_>, kind: DefRegionKind) -> Result<Any> {
773        default_mutate_driver(
774            self,
775            value.value.raw(),
776            kind,
777            value.permit(value.inplace_mode()),
778        )
779    }
780}
781
782impl<D: MutateDispatch> IntoMutator<ByMutateDispatch> for D {
783    #[inline]
784    fn mutate_root(mut self, root: Any) -> Result<Any> {
785        run_structural_mutator(root, &mut self)
786    }
787}
788
789mod mutate_sealed {
790    use super::{IntoMutateResult, MutateContext, MutateValue, ObjectCore, StructuralView};
791
792    pub trait SealedLink<State, Marker> {}
793
794    impl<F, State, T, O> SealedLink<State, super::ByMutateValue<T>> for F
795    where
796        F: for<'value, 'mutator, 'driver> Fn(
797            MutateValue<'value, T>,
798            &'mutator mut MutateContext<'driver, State>,
799        ) -> O,
800        O: IntoMutateResult,
801    {
802    }
803
804    impl<F, State, T, O> SealedLink<State, super::ByMutateOwned<T>> for F
805    where
806        F: for<'mutator, 'driver> Fn(T, &'mutator mut MutateContext<'driver, State>) -> O,
807        O: IntoMutateResult,
808    {
809    }
810
811    impl<F, State, N: ObjectCore, O> SealedLink<State, super::ByMutateNode<N>> for F
812    where
813        F: for<'value, 'mutator, 'driver> Fn(
814            &'value N,
815            &'mutator mut MutateContext<'driver, State>,
816        ) -> O,
817        O: IntoMutateResult,
818    {
819    }
820
821    impl<F, State, O> SealedLink<State, super::ByMutateCatchAll> for F
822    where
823        F: for<'value, 'mutator, 'driver> Fn(
824            &'value StructuralView,
825            &'mutator mut MutateContext<'driver, State>,
826        ) -> O,
827        O: IntoMutateResult,
828    {
829    }
830}
831
832#[doc(hidden)]
833pub enum ByMutateDispatch {}
834
835#[doc(hidden)]
836pub struct ByMutateValue<T>(PhantomData<T>);
837
838impl<F, State, T, O> MutateChainLink<State, ByMutateValue<T>> for F
839where
840    F: for<'value, 'mutator, 'driver> Fn(
841        MutateValue<'value, T>,
842        &'mutator mut MutateContext<'driver, State>,
843    ) -> O,
844    T: crate::type_traits::ContainerElement,
845    O: IntoMutateResult,
846{
847    fn try_mutate(
848        &self,
849        value: &mut Option<MutateValue<'_>>,
850        mutator: &mut MutateContext<'_, State>,
851    ) -> Option<Result<Any>> {
852        match value
853            .take()
854            .expect("unconsumed callback value")
855            .try_cast::<T>()
856        {
857            Ok(typed) => Some(self(typed, mutator).into_mutate_result()),
858            Err(original) => {
859                *value = Some(original);
860                None
861            }
862        }
863    }
864}
865
866#[doc(hidden)]
867pub struct ByMutateOwned<T>(PhantomData<T>);
868
869impl<F, State, T, O> MutateChainLink<State, ByMutateOwned<T>> for F
870where
871    F: for<'mutator, 'driver> Fn(T, &'mutator mut MutateContext<'driver, State>) -> O,
872    T: crate::type_traits::AnyCompatible,
873    O: IntoMutateResult,
874{
875    fn try_mutate(
876        &self,
877        value: &mut Option<MutateValue<'_>>,
878        mutator: &mut MutateContext<'_, State>,
879    ) -> Option<Result<Any>> {
880        value
881            .as_ref()
882            .expect("unconsumed callback value")
883            .cast::<T>()
884            .map(|typed| self(typed, mutator).into_mutate_result())
885    }
886}
887
888#[doc(hidden)]
889pub struct ByMutateNode<N>(PhantomData<N>);
890
891impl<F, State, N, O> MutateChainLink<State, ByMutateNode<N>> for F
892where
893    F: for<'value, 'mutator, 'driver> Fn(
894        &'value N,
895        &'mutator mut MutateContext<'driver, State>,
896    ) -> O,
897    N: ObjectCore,
898    O: IntoMutateResult,
899{
900    fn try_mutate(
901        &self,
902        value: &mut Option<MutateValue<'_>>,
903        mutator: &mut MutateContext<'_, State>,
904    ) -> Option<Result<Any>> {
905        value
906            .as_ref()
907            .expect("unconsumed callback value")
908            .as_node::<N>()
909            .map(|node| self(node, mutator).into_mutate_result())
910    }
911}
912
913#[doc(hidden)]
914pub enum ByMutateCatchAll {}
915
916impl<F, State, O> MutateChainLink<State, ByMutateCatchAll> for F
917where
918    F: for<'value, 'mutator, 'driver> Fn(
919        &'value StructuralView,
920        &'mutator mut MutateContext<'driver, State>,
921    ) -> O,
922    O: IntoMutateResult,
923{
924    fn try_mutate(
925        &self,
926        value: &mut Option<MutateValue<'_>>,
927        mutator: &mut MutateContext<'_, State>,
928    ) -> Option<Result<Any>> {
929        Some(
930            self(
931                value
932                    .as_ref()
933                    .expect("unconsumed callback value")
934                    .as_value(),
935                mutator,
936            )
937            .into_mutate_result(),
938        )
939    }
940}
941
942#[doc(hidden)]
943pub struct ByMutateChainLink<Markers>(PhantomData<fn(Markers)>);
944
945macro_rules! impl_mutate_chain_link {
946    ($(($F:ident, $M:ident, $idx:tt)),+) => {
947        impl<State, $($F, $M,)+>
948            mutate_sealed::SealedLink<State, ByMutateChainLink<($($M,)+)>> for ($($F,)+)
949        where
950            $($F: MutateChainLink<State, $M>,)+
951        {
952        }
953
954        impl<State, $($F, $M,)+> MutateChainLink<State, ByMutateChainLink<($($M,)+)>>
955            for ($($F,)+)
956        where
957            $($F: MutateChainLink<State, $M>,)+
958        {
959            fn try_mutate(
960                &self,
961                value: &mut Option<MutateValue<'_>>,
962                mutator: &mut MutateContext<'_, State>,
963            ) -> Option<Result<Any>> {
964                $(
965                    if let Some(result) = self.$idx.try_mutate(value, mutator) {
966                        return Some(result);
967                    }
968                )+
969                None
970            }
971        }
972    };
973}
974
975impl_callback_chain_tuple_arities!(impl_mutate_chain_link);
976
977/// A reusable typed-dispatch or callback mutator with shared user state.
978pub struct MutateCallbacks<State, Link, Marker, Policy = DefaultMutContextPolicy> {
979    policy: Option<Rc<Policy>>,
980    state: State,
981    callbacks: Rc<Link>,
982    _marker: PhantomData<fn(Marker)>,
983}
984
985impl<State, Link, Marker> MutateCallbacks<State, Link, Marker>
986where
987    Link: MutateChainLink<State, Marker>,
988{
989    /// Construct a stateful callback mutator.
990    pub fn new(state: State, callbacks: Link) -> Self {
991        Self {
992            state,
993            callbacks: Rc::new(callbacks),
994            policy: None,
995            _marker: PhantomData,
996        }
997    }
998}
999
1000impl<State, Link, Marker, Policy> MutateCallbacks<State, Link, Marker, Policy> {
1001    /// Customize default descent while sharing the callback state.
1002    pub fn with_policy<P: MutContextPolicy<State>>(
1003        self,
1004        policy: P,
1005    ) -> MutateCallbacks<State, Link, Marker, P> {
1006        MutateCallbacks {
1007            policy: Some(Rc::new(policy)),
1008            state: self.state,
1009            callbacks: self.callbacks,
1010            _marker: PhantomData,
1011        }
1012    }
1013
1014    /// Shared access to the callback state.
1015    pub fn state(&self) -> &State {
1016        &self.state
1017    }
1018
1019    /// Mutable access to callback state outside an active recursive call.
1020    pub fn state_mut(&mut self) -> &mut State {
1021        &mut self.state
1022    }
1023
1024    /// Consume the mutator and return its state.
1025    pub fn into_state(self) -> State {
1026        self.state
1027    }
1028}
1029
1030struct DirectMutateCallbacks<'a, Link, Marker> {
1031    state: (),
1032    callbacks: &'a Link,
1033    _marker: PhantomData<fn(Marker)>,
1034}
1035
1036#[doc(hidden)]
1037pub trait MutateCallbackState<State> {
1038    fn callback_state(&self) -> &State;
1039    fn callback_state_mut(&mut self) -> &mut State;
1040}
1041
1042impl<State, Link, Marker, Policy> MutateCallbackState<State>
1043    for MutateCallbacks<State, Link, Marker, Policy>
1044{
1045    fn callback_state(&self) -> &State {
1046        &self.state
1047    }
1048
1049    fn callback_state_mut(&mut self) -> &mut State {
1050        &mut self.state
1051    }
1052}
1053
1054impl<Link, Marker> MutateCallbackState<()> for DirectMutateCallbacks<'_, Link, Marker> {
1055    fn callback_state(&self) -> &() {
1056        &self.state
1057    }
1058
1059    fn callback_state_mut(&mut self) -> &mut () {
1060        &mut self.state
1061    }
1062}
1063
1064#[doc(hidden)]
1065pub struct ByMutateCallbacks<Marker>(PhantomData<fn(Marker)>);
1066
1067impl<Link, Marker> IntoMutator<ByMutateCallbacks<Marker>> for Link
1068where
1069    Link: MutateChainLink<(), Marker>,
1070{
1071    fn mutate_root(self, root: Any) -> Result<Any> {
1072        let callbacks = self;
1073        let mut mutator = DirectMutateCallbacks::<Link, Marker> {
1074            state: (),
1075            callbacks: &callbacks,
1076            _marker: PhantomData,
1077        };
1078        run_structural_mutator(root, &mut mutator)
1079    }
1080}
1081
1082/// Ordered typed replacement dispatch for [`structural_map`].
1083///
1084/// `None` means no handler matched and preserves the current value.  A
1085/// generated `#[dispatch(map)]` implementation tests `map_*` methods in
1086/// source order and returns the first match.
1087pub trait MapDispatch: Sized {
1088    fn dispatch_map(
1089        &mut self,
1090        value: &StructuralView,
1091        def_region_kind: DefRegionKind,
1092    ) -> Option<Result<Any>>;
1093}
1094
1095/// Internal root-mapping protocol used by [`IntoMapper`].
1096#[doc(hidden)]
1097pub trait NativeMap: Sized {
1098    fn map_root(&mut self, root: Any, order: WalkOrder) -> Result<Any>;
1099}
1100
1101impl<D: MapDispatch> NativeMap for D {
1102    fn map_root(&mut self, root: Any, order: WalkOrder) -> Result<Any> {
1103        run_native_mapper::<_, DefaultMutContextPolicy>(root, self, None, order)
1104    }
1105}
1106
1107impl<V: MapDispatch> MapDispatch for &mut V {
1108    #[inline]
1109    fn dispatch_map(
1110        &mut self,
1111        value: &StructuralView,
1112        def_region_kind: DefRegionKind,
1113    ) -> Option<Result<Any>> {
1114        (**self).dispatch_map(value, def_region_kind)
1115    }
1116}
1117
1118/// Conversion into the mapper consumed by [`structural_map`].
1119#[diagnostic::on_unimplemented(
1120    message = "unsupported structural-map callback shape",
1121    label = "this value cannot be used as a structural mapper",
1122    note = "pass `&mut` a `MapDispatch`, a supported closure or callback tuple, or a `MapWithContextPolicy`"
1123)]
1124pub trait IntoMapper<Marker> {
1125    type Mapper: NativeMap;
1126    fn into_mapper(self) -> Self::Mapper;
1127}
1128
1129#[doc(hidden)]
1130pub enum ByMapDispatch {}
1131
1132impl<'a, V: MapDispatch> IntoMapper<ByMapDispatch> for &'a mut V {
1133    type Mapper = &'a mut V;
1134
1135    #[inline]
1136    fn into_mapper(self) -> Self::Mapper {
1137        self
1138    }
1139}
1140
1141/// One typed callback in a structural-map tuple.
1142///
1143/// Links use first-match order and may receive an owned FFI value, borrowed
1144/// object node, or `&StructuralView`, optionally followed by [`DefRegionKind`].
1145pub trait MapChainLink<Marker>: sealed_map::SealedMapLink<Marker> {
1146    #[doc(hidden)]
1147    fn try_map(
1148        &mut self,
1149        value: &StructuralView,
1150        def_region_kind: DefRegionKind,
1151    ) -> Option<Result<Any>>;
1152}
1153
1154mod sealed_map {
1155    use super::{DefRegionKind, IntoMutateResult, MapDispatch, ObjectCore, StructuralView};
1156
1157    pub trait SealedMapLink<Marker> {}
1158
1159    impl<F, T, O> SealedMapLink<super::ByMapOwned<T>> for F
1160    where
1161        F: FnMut(T) -> O,
1162        O: IntoMutateResult,
1163    {
1164    }
1165
1166    impl<F, T, O> SealedMapLink<super::ByMapOwnedKind<T>> for F
1167    where
1168        F: FnMut(T, DefRegionKind) -> O,
1169        O: IntoMutateResult,
1170    {
1171    }
1172
1173    impl<F, N: ObjectCore, O> SealedMapLink<super::ByMapNode<N>> for F
1174    where
1175        F: for<'a> FnMut(&'a N) -> O,
1176        O: IntoMutateResult,
1177    {
1178    }
1179
1180    impl<F, N: ObjectCore, O> SealedMapLink<super::ByMapNodeKind<N>> for F
1181    where
1182        F: for<'a> FnMut(&'a N, DefRegionKind) -> O,
1183        O: IntoMutateResult,
1184    {
1185    }
1186
1187    impl<F, O> SealedMapLink<super::ByMapCatchAll> for F
1188    where
1189        F: for<'a> FnMut(&'a StructuralView) -> O,
1190        O: IntoMutateResult,
1191    {
1192    }
1193
1194    impl<F, O> SealedMapLink<super::ByMapCatchAllKind> for F
1195    where
1196        F: for<'a> FnMut(&'a StructuralView, DefRegionKind) -> O,
1197        O: IntoMutateResult,
1198    {
1199    }
1200
1201    impl<V: MapDispatch> SealedMapLink<super::ByMapDispatchLink> for &mut V {}
1202}
1203
1204#[doc(hidden)]
1205pub struct ByMapOwned<T>(PhantomData<T>);
1206
1207impl<F, T, O> MapChainLink<ByMapOwned<T>> for F
1208where
1209    F: FnMut(T) -> O,
1210    T: crate::type_traits::AnyCompatible,
1211    O: IntoMutateResult,
1212{
1213    #[inline]
1214    fn try_map(
1215        &mut self,
1216        value: &StructuralView,
1217        _def_region_kind: DefRegionKind,
1218    ) -> Option<Result<Any>> {
1219        value
1220            .cast::<T>()
1221            .map(|typed| self(typed).into_mutate_result())
1222    }
1223}
1224
1225#[doc(hidden)]
1226pub struct ByMapOwnedKind<T>(PhantomData<T>);
1227
1228impl<F, T, O> MapChainLink<ByMapOwnedKind<T>> for F
1229where
1230    F: FnMut(T, DefRegionKind) -> O,
1231    T: crate::type_traits::AnyCompatible,
1232    O: IntoMutateResult,
1233{
1234    #[inline]
1235    fn try_map(
1236        &mut self,
1237        value: &StructuralView,
1238        def_region_kind: DefRegionKind,
1239    ) -> Option<Result<Any>> {
1240        value
1241            .cast::<T>()
1242            .map(|typed| self(typed, def_region_kind).into_mutate_result())
1243    }
1244}
1245
1246#[doc(hidden)]
1247pub struct ByMapNode<N>(PhantomData<N>);
1248
1249impl<F, N, O> MapChainLink<ByMapNode<N>> for F
1250where
1251    F: for<'a> FnMut(&'a N) -> O,
1252    N: ObjectCore,
1253    O: IntoMutateResult,
1254{
1255    #[inline]
1256    fn try_map(
1257        &mut self,
1258        value: &StructuralView,
1259        _def_region_kind: DefRegionKind,
1260    ) -> Option<Result<Any>> {
1261        value
1262            .as_node::<N>()
1263            .map(|node| self(node).into_mutate_result())
1264    }
1265}
1266
1267#[doc(hidden)]
1268pub struct ByMapNodeKind<N>(PhantomData<N>);
1269
1270impl<F, N, O> MapChainLink<ByMapNodeKind<N>> for F
1271where
1272    F: for<'a> FnMut(&'a N, DefRegionKind) -> O,
1273    N: ObjectCore,
1274    O: IntoMutateResult,
1275{
1276    #[inline]
1277    fn try_map(
1278        &mut self,
1279        value: &StructuralView,
1280        def_region_kind: DefRegionKind,
1281    ) -> Option<Result<Any>> {
1282        value
1283            .as_node::<N>()
1284            .map(|node| self(node, def_region_kind).into_mutate_result())
1285    }
1286}
1287
1288#[doc(hidden)]
1289pub enum ByMapCatchAll {}
1290
1291impl<F, O> MapChainLink<ByMapCatchAll> for F
1292where
1293    F: for<'a> FnMut(&'a StructuralView) -> O,
1294    O: IntoMutateResult,
1295{
1296    #[inline]
1297    fn try_map(
1298        &mut self,
1299        value: &StructuralView,
1300        _def_region_kind: DefRegionKind,
1301    ) -> Option<Result<Any>> {
1302        Some(self(value).into_mutate_result())
1303    }
1304}
1305
1306#[doc(hidden)]
1307pub enum ByMapCatchAllKind {}
1308
1309impl<F, O> MapChainLink<ByMapCatchAllKind> for F
1310where
1311    F: for<'a> FnMut(&'a StructuralView, DefRegionKind) -> O,
1312    O: IntoMutateResult,
1313{
1314    #[inline]
1315    fn try_map(
1316        &mut self,
1317        value: &StructuralView,
1318        def_region_kind: DefRegionKind,
1319    ) -> Option<Result<Any>> {
1320        Some(self(value, def_region_kind).into_mutate_result())
1321    }
1322}
1323
1324#[doc(hidden)]
1325pub struct ByMapChainLink<Markers>(PhantomData<fn(Markers)>);
1326
1327#[doc(hidden)]
1328pub enum ByMapDispatchLink {}
1329
1330impl<V: MapDispatch> MapChainLink<ByMapDispatchLink> for &mut V {
1331    #[inline]
1332    fn try_map(
1333        &mut self,
1334        value: &StructuralView,
1335        def_region_kind: DefRegionKind,
1336    ) -> Option<Result<Any>> {
1337        self.dispatch_map(value, def_region_kind)
1338    }
1339}
1340
1341/// Adapter from a [`MapChainLink`] to [`MapDispatch`].
1342#[doc(hidden)]
1343pub struct MapChain<Link, Marker> {
1344    link: Link,
1345    marker: PhantomData<fn(Marker)>,
1346}
1347
1348impl<Link, Marker> MapChain<Link, Marker> {
1349    #[inline]
1350    fn new(link: Link) -> Self {
1351        MapChain {
1352            link,
1353            marker: PhantomData,
1354        }
1355    }
1356}
1357
1358impl<Link, Marker> MapDispatch for MapChain<Link, Marker>
1359where
1360    Link: MapChainLink<Marker>,
1361{
1362    #[inline]
1363    fn dispatch_map(
1364        &mut self,
1365        value: &StructuralView,
1366        def_region_kind: DefRegionKind,
1367    ) -> Option<Result<Any>> {
1368        self.link.try_map(value, def_region_kind)
1369    }
1370}
1371
1372macro_rules! impl_map_chain_link {
1373    ($(($F:ident, $M:ident, $idx:tt)),+) => {
1374        impl<$($F, $M,)+> sealed_map::SealedMapLink<ByMapChainLink<($($M,)+)>> for ($($F,)+)
1375        where
1376            $($F: MapChainLink<$M>,)+
1377        {
1378        }
1379
1380        impl<$($F, $M,)+> MapChainLink<ByMapChainLink<($($M,)+)>> for ($($F,)+)
1381        where
1382            $($F: MapChainLink<$M>,)+
1383        {
1384            #[inline]
1385            fn try_map(
1386                &mut self,
1387                value: &StructuralView,
1388                def_region_kind: DefRegionKind,
1389            ) -> Option<Result<Any>> {
1390                $(
1391                    if let Some(result) = self.$idx.try_map(value, def_region_kind) {
1392                        return Some(result);
1393                    }
1394                )+
1395                None
1396            }
1397        }
1398
1399        impl<$($F, $M,)+> IntoMapper<($($M,)+)> for ($($F,)+)
1400        where
1401            $($F: MapChainLink<$M>,)+
1402        {
1403            type Mapper = MapChain<($($F,)+), ByMapChainLink<($($M,)+)>>;
1404
1405            #[inline]
1406            fn into_mapper(self) -> Self::Mapper {
1407                MapChain::new(self)
1408            }
1409        }
1410    };
1411}
1412
1413impl_callback_chain_tuple_arities!(impl_map_chain_link);
1414
1415macro_rules! impl_bare_map_link {
1416    ($(($marker:ident, $($fn_args:ty),+)),+ $(,)?) => {
1417        $(
1418            impl<F, T, O> IntoMapper<$marker<T>> for F
1419            where
1420                F: FnMut($($fn_args),+) -> O,
1421                Self: MapChainLink<$marker<T>>,
1422                O: IntoMutateResult,
1423            {
1424                type Mapper = MapChain<F, $marker<T>>;
1425
1426                #[inline]
1427                fn into_mapper(self) -> Self::Mapper {
1428                    MapChain::new(self)
1429                }
1430            }
1431        )+
1432    };
1433}
1434
1435impl_bare_map_link!(
1436    (ByMapOwned, T),
1437    (ByMapOwnedKind, T, DefRegionKind),
1438    (ByMapNode, &T),
1439    (ByMapNodeKind, &T, DefRegionKind),
1440);
1441
1442impl<F, O> IntoMapper<ByMapCatchAll> for F
1443where
1444    F: for<'a> FnMut(&'a StructuralView) -> O,
1445    O: IntoMutateResult,
1446{
1447    type Mapper = MapChain<F, ByMapCatchAll>;
1448
1449    #[inline]
1450    fn into_mapper(self) -> Self::Mapper {
1451        MapChain::new(self)
1452    }
1453}
1454
1455impl<F, O> IntoMapper<ByMapCatchAllKind> for F
1456where
1457    F: for<'a> FnMut(&'a StructuralView, DefRegionKind) -> O,
1458    O: IntoMutateResult,
1459{
1460    type Mapper = MapChain<F, ByMapCatchAllKind>;
1461
1462    #[inline]
1463    fn into_mapper(self) -> Self::Mapper {
1464        MapChain::new(self)
1465    }
1466}
1467
1468/// Engine-issued permission to attempt in-place mutation of one value.
1469///
1470/// The engine issues it only when the current ownership path permits reuse.
1471pub struct InplaceValue<'a> {
1472    value: StructuralView,
1473    _scope: PhantomData<&'a mut TVMFFIAny>,
1474}
1475
1476impl<'a> InplaceValue<'a> {
1477    #[inline]
1478    fn from_raw(raw: &'a mut TVMFFIAny) -> Self {
1479        Self {
1480            value: StructuralView::from_raw(*raw),
1481            _scope: PhantomData,
1482        }
1483    }
1484
1485    /// Borrow the value without its in-place capability.
1486    #[inline]
1487    pub fn as_value(&self) -> &StructuralView {
1488        &self.value
1489    }
1490
1491    /// Retain an owning copy of the value.
1492    ///
1493    /// Retaining an object creates an alias. The default in-place helper
1494    /// rechecks uniqueness and automatically falls back to copying.
1495    #[inline]
1496    pub fn to_owned(&self) -> Any {
1497        self.value.to_owned()
1498    }
1499}
1500
1501impl Deref for InplaceValue<'_> {
1502    type Target = StructuralView;
1503
1504    #[inline]
1505    fn deref(&self) -> &Self::Target {
1506        self.as_value()
1507    }
1508}
1509
1510/// Identity substitutions for a custom [`StructuralMutator`] remapping policy.
1511///
1512/// The map owns its keys and values so object addresses remain stable.
1513#[derive(Default)]
1514pub struct StructuralVarRemap {
1515    entries: HashMap<NonNull<TVMFFIObject>, MemoEntry>,
1516}
1517
1518impl StructuralVarRemap {
1519    /// Look up an identity replacement previously stored for `var`.
1520    pub fn get(&self, var: &StructuralView) -> Result<Option<Any>> {
1521        let key = object_identity_key(var.raw())?;
1522        Ok(self.entries.get(&key).map(|entry| entry.result.clone()))
1523    }
1524
1525    /// Store a descent result or an [`Unchanged`] marker for `var`.
1526    pub fn set(&mut self, var: &StructuralView, mutated_value: &Any) -> Result<()> {
1527        let key = object_identity_key(var.raw())?;
1528        self.entries.insert(
1529            key,
1530            MemoEntry {
1531                _original: var.to_owned(),
1532                result: mutated_value.clone(),
1533            },
1534        );
1535        Ok(())
1536    }
1537
1538    /// Remove every recorded identity substitution.
1539    pub fn clear(&mut self) {
1540        self.entries.clear();
1541    }
1542}
1543
1544/// A low-level mutator that controls its own recursion.
1545///
1546/// Implementations descend with the `mutate` or `default_*` helpers.
1547/// Prefer mutation callbacks or `#[dispatch(mutate)]` for typed dispatch with
1548/// recursion supplied through [`Mutator`].
1549pub trait StructuralMutator: Sized {
1550    /// Dispatch one borrowed value without modifying its source storage.
1551    ///
1552    /// The structural-mutation engine calls this hook for each value.
1553    fn dispatch_mutate(
1554        &mut self,
1555        value: &StructuralView,
1556        def_region_kind: DefRegionKind,
1557    ) -> Result<Any>;
1558
1559    /// Dispatch one value for which the engine permits an in-place attempt.
1560    ///
1561    /// The default delegates to [`Self::dispatch_mutate`] and therefore remains
1562    /// non-in-place. Override this method to opt into the default container
1563    /// reuse path.
1564    fn dispatch_maybe_inplace_mutate(
1565        &mut self,
1566        value: InplaceValue<'_>,
1567        def_region_kind: DefRegionKind,
1568    ) -> Result<Any> {
1569        self.dispatch_mutate(value.as_value(), def_region_kind)
1570    }
1571
1572    #[doc(hidden)]
1573    fn on_default_mutate(&mut self, value: MutateValue<'_>, kind: DefRegionKind) -> Result<Any> {
1574        default_mutate_driver(
1575            self,
1576            value.value.raw(),
1577            kind,
1578            value.permit(value.inplace_mode()),
1579        )
1580    }
1581
1582    /// Re-enter this mutator for a borrowed value. The value and all of its
1583    /// descendants use the non-in-place path.
1584    fn mutate<T>(&mut self, value: &T, def_region_kind: DefRegionKind) -> Result<Any>
1585    where
1586        for<'x> AnyView<'x>: From<&'x T>,
1587    {
1588        let view = AnyView::from(value);
1589        dispatch_user_raw(self, *view.as_raw_ffi_any(), def_region_kind, Permit::Copy)
1590            .and_then(|result| resolve_result(result, *view.as_raw_ffi_any()))
1591    }
1592
1593    /// Re-enter this mutator for an owned value, permitting reuse only when
1594    /// the converted value remains uniquely owned.
1595    fn maybe_inplace_mutate<T>(&mut self, value: T, def_region_kind: DefRegionKind) -> Result<Any>
1596    where
1597        T: Into<Any>,
1598    {
1599        self.maybe_inplace_mutate_with_mode(value, def_region_kind, InplaceMode::Allow)
1600    }
1601
1602    /// Re-enter for an owned value with an explicit region and in-place permission.
1603    ///
1604    /// `Allow` checks uniqueness before dispatch; `Disallow` uses ordinary
1605    /// mutation without checking uniqueness. An independently owned replacement
1606    /// or a later explicit owned entry can establish a new permission boundary.
1607    fn maybe_inplace_mutate_with_mode<T>(
1608        &mut self,
1609        value: T,
1610        def_region_kind: DefRegionKind,
1611        mode: InplaceMode,
1612    ) -> Result<Any>
1613    where
1614        T: Into<Any>,
1615    {
1616        let value = value.into();
1617        let result = dispatch_user_raw(
1618            self,
1619            *value.as_raw_ffi_any(),
1620            def_region_kind,
1621            mode.permit(),
1622        )?;
1623        Ok(if is_unchanged(&result) { value } else { result })
1624    }
1625
1626    /// Apply default non-in-place mutation to a borrowed typed value.
1627    ///
1628    /// Unlike [Self::mutate], this bypasses dispatch for the value
1629    /// itself while its children still re-enter this mutator. This lets a
1630    /// typed structural-mutate handler recurse through its current node
1631    /// before applying a post-order rewrite.
1632    fn default_mutate<T>(&mut self, value: &T, def_region_kind: DefRegionKind) -> Result<Any>
1633    where
1634        for<'x> AnyView<'x>: From<&'x T>,
1635    {
1636        let view = AnyView::from(value);
1637        user_default_mutate(self, *view.as_raw_ffi_any(), def_region_kind, Permit::Copy)
1638            .and_then(|result| resolve_result(result, *view.as_raw_ffi_any()))
1639    }
1640
1641    /// Apply the default mutation under an engine-issued in-place capability.
1642    ///
1643    /// Uniqueness is checked again here because user code may have retained
1644    /// an owning alias after the capability was issued.
1645    fn default_maybe_inplace_mutate(
1646        &mut self,
1647        value: InplaceValue<'_>,
1648        def_region_kind: DefRegionKind,
1649    ) -> Result<Any> {
1650        self.default_maybe_inplace_mutate_with_mode(value, def_region_kind, InplaceMode::Allow)
1651    }
1652
1653    /// Apply default mutation with a capability and an explicit permission.
1654    ///
1655    /// `Disallow` overrides the capability and uses the copy path. `Allow`
1656    /// rechecks uniqueness because the handler may have retained an owning
1657    /// alias. Consuming the capability prevents a borrow from it surviving this
1658    /// call. Unlike the C++ default-descent API, safe Rust cannot simply trust
1659    /// the earlier uniqueness check after arbitrary user code has run.
1660    fn default_maybe_inplace_mutate_with_mode(
1661        &mut self,
1662        value: InplaceValue<'_>,
1663        def_region_kind: DefRegionKind,
1664        mode: InplaceMode,
1665    ) -> Result<Any> {
1666        let raw = value.raw();
1667        let permit = mode.permit_if_unique(raw);
1668        user_default_mutate(self, raw, def_region_kind, permit)
1669            .and_then(|result| resolve_result(result, raw))
1670    }
1671
1672    /// Re-enter this mutator for a borrowed value, preserving unchanged.
1673    fn mutate_result<T>(&mut self, value: &T, kind: DefRegionKind) -> Result<UnchangedOr<Any>>
1674    where
1675        for<'x> AnyView<'x>: From<&'x T>,
1676    {
1677        let view = AnyView::from(value);
1678        dispatch_user_raw(self, *view.as_raw_ffi_any(), kind, Permit::Copy)
1679            .and_then(UnchangedOr::from_carrier)
1680    }
1681
1682    /// Default mutation of a borrowed typed value, preserving unchanged.
1683    fn default_mutate_result<T>(
1684        &mut self,
1685        value: &T,
1686        kind: DefRegionKind,
1687    ) -> Result<UnchangedOr<Any>>
1688    where
1689        for<'x> AnyView<'x>: From<&'x T>,
1690    {
1691        let view = AnyView::from(value);
1692        user_default_mutate(self, *view.as_raw_ffi_any(), kind, Permit::Copy)
1693            .and_then(UnchangedOr::from_carrier)
1694    }
1695
1696    /// Default mutation under an engine-issued capability, preserving unchanged.
1697    fn default_maybe_inplace_mutate_result(
1698        &mut self,
1699        value: InplaceValue<'_>,
1700        kind: DefRegionKind,
1701    ) -> Result<UnchangedOr<Any>> {
1702        self.default_maybe_inplace_mutate_with_mode_result(value, kind, InplaceMode::Allow)
1703    }
1704
1705    /// Default mutation with a capability and permission, preserving unchanged.
1706    ///
1707    /// Uses the same ownership checks as [`Self::default_maybe_inplace_mutate_with_mode`].
1708    fn default_maybe_inplace_mutate_with_mode_result(
1709        &mut self,
1710        value: InplaceValue<'_>,
1711        kind: DefRegionKind,
1712        mode: InplaceMode,
1713    ) -> Result<UnchangedOr<Any>> {
1714        let raw = value.raw();
1715        let permit = mode.permit_if_unique(raw);
1716        user_default_mutate(self, raw, kind, permit).and_then(UnchangedOr::from_carrier)
1717    }
1718
1719    /// Look up a FreeVar or DAG-node substitution from the active mutation.
1720    fn var_remap_get(&mut self, var: &StructuralView) -> Result<Option<Any>> {
1721        invocation_var_remap_get(self, var)
1722    }
1723
1724    /// Store a FreeVar or DAG-node substitution for the active mutation.
1725    fn var_remap_set(&mut self, var: &StructuralView, mutated_value: &Any) -> Result<()> {
1726        invocation_var_remap_set(self, var, mutated_value)
1727    }
1728}
1729
1730impl<D: MutateDispatch> StructuralMutator for D {
1731    fn on_default_mutate(&mut self, value: MutateValue<'_>, kind: DefRegionKind) -> Result<Any> {
1732        MutateDispatch::on_default_mutate(self, value, kind)
1733    }
1734
1735    #[inline(always)]
1736    fn dispatch_mutate(
1737        &mut self,
1738        value: &StructuralView,
1739        def_region_kind: DefRegionKind,
1740    ) -> Result<Any> {
1741        let mut mutator = Mutator {
1742            def_region_kind,
1743            inplace_mode: InplaceMode::Disallow,
1744            _not_send_sync: PhantomData,
1745        };
1746        match MutateDispatch::dispatch_mutate_value(
1747            self,
1748            MutateValue::borrowed(value),
1749            &mut mutator,
1750        ) {
1751            Some(result) => result,
1752            None => user_default_mutate(self, value.raw(), def_region_kind, Permit::Copy),
1753        }
1754    }
1755
1756    #[inline(always)]
1757    fn dispatch_maybe_inplace_mutate(
1758        &mut self,
1759        value: InplaceValue<'_>,
1760        def_region_kind: DefRegionKind,
1761    ) -> Result<Any> {
1762        let mut mutator = Mutator {
1763            def_region_kind,
1764            inplace_mode: InplaceMode::Allow,
1765            _not_send_sync: PhantomData,
1766        };
1767        match MutateDispatch::dispatch_mutate_value(
1768            self,
1769            MutateValue::new(value.as_value(), InplaceMode::Allow),
1770            &mut mutator,
1771        ) {
1772            Some(result) => result,
1773            None => {
1774                let raw = value.raw();
1775                let permit = if object_is_unique(raw) {
1776                    Permit::MaybeInPlace
1777                } else {
1778                    Permit::Copy
1779                };
1780                user_default_mutate(self, raw, def_region_kind, permit)
1781            }
1782        }
1783    }
1784}
1785
1786#[doc(hidden)]
1787pub fn default_mutate_with_policy<D: MutateDispatch + MutateCallbackState<D>>(
1788    dispatch: &mut D,
1789    policy: &impl MutContextPolicy<D>,
1790    value: MutateValue<'_>,
1791    kind: DefRegionKind,
1792) -> Result<Any> {
1793    policy::mutate_with_policy(
1794        &mut policy::MutationDescent { driver: dispatch },
1795        policy,
1796        value,
1797        kind,
1798    )
1799}
1800
1801// Closure callback chains use a type-erased context driver so one concrete
1802// function signature can recurse through the complete chain.
1803#[inline(always)]
1804fn try_mutate_callbacks<State, Link, Marker, Driver>(
1805    driver: &mut Driver,
1806    callback_ptr: *const Link,
1807    value: &StructuralView,
1808    def_region_kind: DefRegionKind,
1809    inplace_mode: InplaceMode,
1810) -> Option<Result<Any>>
1811where
1812    Link: MutateChainLink<State, Marker>,
1813    Driver: MutateContextDriver<State>,
1814{
1815    let mut mutator = MutateContext {
1816        driver,
1817        def_region_kind,
1818        inplace_mode,
1819        _not_send_sync: PhantomData,
1820    };
1821    // SAFETY: The owning `Rc` or the direct callback's stack slot remains live
1822    // and is never modified through the driver during recursive reentry.
1823    unsafe {
1824        (&*callback_ptr).try_mutate(
1825            &mut Some(MutateValue::new(value, inplace_mode)),
1826            &mut mutator,
1827        )
1828    }
1829}
1830
1831impl<State, Link, Marker, Policy> StructuralMutator for MutateCallbacks<State, Link, Marker, Policy>
1832where
1833    Policy: MutContextPolicy<State>,
1834    Link: MutateChainLink<State, Marker>,
1835{
1836    #[inline(always)]
1837    fn dispatch_mutate(
1838        &mut self,
1839        value: &StructuralView,
1840        def_region_kind: DefRegionKind,
1841    ) -> Result<Any> {
1842        let callback_ptr = Rc::as_ptr(&self.callbacks);
1843        match try_mutate_callbacks::<State, Link, Marker, _>(
1844            self,
1845            callback_ptr,
1846            value,
1847            def_region_kind,
1848            InplaceMode::Disallow,
1849        ) {
1850            Some(result) => result,
1851            None => user_default_mutate(self, value.raw(), def_region_kind, Permit::Copy),
1852        }
1853    }
1854
1855    #[inline(always)]
1856    fn dispatch_maybe_inplace_mutate(
1857        &mut self,
1858        value: InplaceValue<'_>,
1859        def_region_kind: DefRegionKind,
1860    ) -> Result<Any> {
1861        let callback_ptr = Rc::as_ptr(&self.callbacks);
1862        match try_mutate_callbacks::<State, Link, Marker, _>(
1863            self,
1864            callback_ptr,
1865            value.as_value(),
1866            def_region_kind,
1867            InplaceMode::Allow,
1868        ) {
1869            Some(result) => result,
1870            None => self
1871                .default_maybe_inplace_mutate_result(value, def_region_kind)
1872                .map(Any::from),
1873        }
1874    }
1875
1876    fn on_default_mutate(&mut self, value: MutateValue<'_>, kind: DefRegionKind) -> Result<Any> {
1877        match self.policy.clone() {
1878            Some(policy) => policy::mutate_with_policy(
1879                &mut policy::MutationDescent { driver: self },
1880                policy.as_ref(),
1881                value,
1882                kind,
1883            ),
1884            None => default_mutate_driver(
1885                self,
1886                value.value.raw(),
1887                kind,
1888                value.permit(value.inplace_mode()),
1889            ),
1890        }
1891    }
1892}
1893
1894impl<Link, Marker> StructuralMutator for DirectMutateCallbacks<'_, Link, Marker>
1895where
1896    Link: MutateChainLink<(), Marker>,
1897{
1898    #[inline(always)]
1899    fn dispatch_mutate(
1900        &mut self,
1901        value: &StructuralView,
1902        def_region_kind: DefRegionKind,
1903    ) -> Result<Any> {
1904        let callback_ptr = std::ptr::from_ref(self.callbacks);
1905        match try_mutate_callbacks::<(), Link, Marker, _>(
1906            self,
1907            callback_ptr,
1908            value,
1909            def_region_kind,
1910            InplaceMode::Disallow,
1911        ) {
1912            Some(result) => result,
1913            None => user_default_mutate(self, value.raw(), def_region_kind, Permit::Copy),
1914        }
1915    }
1916
1917    #[inline(always)]
1918    fn dispatch_maybe_inplace_mutate(
1919        &mut self,
1920        value: InplaceValue<'_>,
1921        def_region_kind: DefRegionKind,
1922    ) -> Result<Any> {
1923        let callback_ptr = std::ptr::from_ref(self.callbacks);
1924        match try_mutate_callbacks::<(), Link, Marker, _>(
1925            self,
1926            callback_ptr,
1927            value.as_value(),
1928            def_region_kind,
1929            InplaceMode::Allow,
1930        ) {
1931            Some(result) => result,
1932            None => self
1933                .default_maybe_inplace_mutate_result(value, def_region_kind)
1934                .map(Any::from),
1935        }
1936    }
1937}
1938
1939impl<State, Driver> MutateContextDriver<State> for Driver
1940where
1941    Driver: StructuralMutator + MutateCallbackState<State>,
1942{
1943    #[inline(always)]
1944    fn state(&self) -> &State {
1945        self.callback_state()
1946    }
1947
1948    #[inline(always)]
1949    fn state_mut(&mut self) -> &mut State {
1950        self.callback_state_mut()
1951    }
1952
1953    #[inline(always)]
1954    fn mutate_borrowed(&mut self, value: AnyView<'_>, kind: DefRegionKind) -> Result<Any> {
1955        dispatch_user_raw(self, *value.as_raw_ffi_any(), kind, Permit::Copy)
1956    }
1957
1958    #[inline(always)]
1959    fn mutate_owned(&mut self, value: Any, kind: DefRegionKind, mode: InplaceMode) -> Result<Any> {
1960        StructuralMutator::maybe_inplace_mutate_with_mode(self, value, kind, mode)
1961    }
1962
1963    #[inline(always)]
1964    fn default_mutate_borrowed(&mut self, value: AnyView<'_>, kind: DefRegionKind) -> Result<Any> {
1965        user_default_mutate(self, *value.as_raw_ffi_any(), kind, Permit::Copy)
1966    }
1967
1968    fn default_mutate_value(
1969        &mut self,
1970        value: MutateValue<'_>,
1971        kind: DefRegionKind,
1972        mode: InplaceMode,
1973    ) -> Result<Any> {
1974        let permit = value.permit(mode);
1975        user_default_mutate(self, value.value.raw(), kind, permit)
1976    }
1977
1978    #[inline(always)]
1979    fn var_remap_get(&mut self, var: &StructuralView) -> Result<Option<Any>> {
1980        <Self as StructuralMutator>::var_remap_get(self, var)
1981    }
1982
1983    #[inline(always)]
1984    fn var_remap_set(&mut self, var: &StructuralView, mutated_value: &Any) -> Result<()> {
1985        <Self as StructuralMutator>::var_remap_set(self, var, mutated_value)
1986    }
1987}
1988
1989#[derive(Clone, Copy, PartialEq, Eq)]
1990enum Permit {
1991    Copy,
1992    MaybeInPlace,
1993}
1994
1995impl Permit {
1996    fn inplace_mode(self, raw: TVMFFIAny) -> InplaceMode {
1997        if self == Self::MaybeInPlace && object_is_unique(raw) {
1998            InplaceMode::Allow
1999        } else {
2000            InplaceMode::Disallow
2001        }
2002    }
2003}
2004
2005struct MemoEntry {
2006    // Keeps the pointer-valued key alive so its address cannot be reused
2007    // during the same mapping invocation.
2008    _original: Any,
2009    result: Any,
2010}
2011
2012struct NativeMapper<'a, D, Policy, const PRE_ORDER: bool> {
2013    dispatch: &'a mut D,
2014    policy: Option<Rc<Policy>>,
2015    remap: StructuralVarRemap,
2016}
2017
2018fn run_native_mapper<D: MapDispatch, Policy: MutContextPolicy<D>>(
2019    root: Any,
2020    dispatch: &mut D,
2021    policy: Option<Rc<Policy>>,
2022    order: WalkOrder,
2023) -> Result<Any> {
2024    match order {
2025        WalkOrder::PreOrder => NativeMapper::<_, _, true>::run(root, dispatch, policy),
2026        WalkOrder::PostOrder => NativeMapper::<_, _, false>::run(root, dispatch, policy),
2027    }
2028}
2029
2030impl<D: MapDispatch, Policy: MutContextPolicy<D>, const PRE_ORDER: bool>
2031    NativeMapper<'_, D, Policy, PRE_ORDER>
2032{
2033    fn run(root: Any, dispatch: &mut D, policy: Option<Rc<Policy>>) -> Result<Any> {
2034        run_structural_mutator(
2035            root,
2036            &mut NativeMapper::<_, _, PRE_ORDER> {
2037                dispatch,
2038                policy,
2039                remap: StructuralVarRemap::default(),
2040            },
2041        )
2042    }
2043
2044    #[inline(always)]
2045    fn map_raw(
2046        &mut self,
2047        raw: TVMFFIAny,
2048        def_region_kind: DefRegionKind,
2049        permit: Permit,
2050    ) -> Result<Any> {
2051        // Plain inline values have no children or structural identity.  Map
2052        // them directly instead of routing through identity lookup and the
2053        // default-mutation path, whose owning conversion crosses the C ABI.
2054        // Raw strings, byte-array views, and ObjectRValueRef are deliberately
2055        // excluded because converting those borrowed special values into an
2056        // Any performs normalization rather than a bitwise copy.
2057        if self.policy.is_none() && is_plain_inline(raw.type_index) {
2058            let value = StructuralView::from_raw(raw);
2059            return match self.dispatch.dispatch_map(&value, def_region_kind) {
2060                Some(result) => {
2061                    let mapped = result?;
2062                    // A pre-order callback may replace an inline leaf with a subtree.
2063                    if PRE_ORDER && !is_plain_inline(mapped.type_index()) {
2064                        let descended =
2065                            self.map_default_root(&mapped, def_region_kind, Permit::Copy)?;
2066                        Ok(if is_unchanged(&descended) {
2067                            mapped
2068                        } else {
2069                            descended
2070                        })
2071                    } else {
2072                        Ok(mapped)
2073                    }
2074                }
2075                // SAFETY: `is_plain_inline` excludes every borrowed
2076                // representation that needs normalization.  These values own
2077                // no external resource, so their owning form is the same
2078                // bitwise TVMFFIAny value.
2079                None => Ok(unsafe { Any::from_raw_ffi_any(raw) }),
2080            };
2081        }
2082
2083        self.map_current_raw(raw, def_region_kind, permit)
2084    }
2085
2086    fn map_current_raw(
2087        &mut self,
2088        raw: TVMFFIAny,
2089        def_region_kind: DefRegionKind,
2090        permit: Permit,
2091    ) -> Result<Any> {
2092        match PRE_ORDER {
2093            true => {
2094                // A replacement inherits the input's permission, established
2095                // before the callback can acquire or release ownership.
2096                let permit = permit.inplace_mode(raw).permit();
2097                let value = StructuralView::from_raw(raw);
2098                let Some(callback_result) = self.dispatch.dispatch_map(&value, def_region_kind)
2099                else {
2100                    return self.default_map_current_raw(raw, def_region_kind, permit);
2101                };
2102                let mapped = callback_result.map_err(|error| with_value_context(error, raw))?;
2103                let mapped_raw = *mapped.as_raw_ffi_any();
2104                if is_unchanged(&mapped) || same_shallow(raw, mapped_raw) {
2105                    // Release the callback's temporary ownership before the
2106                    // runtime uniqueness check observes the original.
2107                    drop(mapped);
2108                    self.default_map_current_raw(raw, def_region_kind, permit)
2109                } else {
2110                    let descended = self.map_default_root(&mapped, def_region_kind, permit)?;
2111                    Ok(if is_unchanged(&descended) {
2112                        mapped
2113                    } else {
2114                        descended
2115                    })
2116                }
2117            }
2118            false => {
2119                let mapped = self.default_map_current_raw(raw, def_region_kind, permit)?;
2120                let original = StructuralView::from_raw(raw);
2121                let value = if is_unchanged(&mapped) {
2122                    &original
2123                } else {
2124                    StructuralView::from_any(&mapped)
2125                };
2126                // Keep child rewrites when the callback leaves its input unchanged.
2127                match self.dispatch.dispatch_map(value, def_region_kind) {
2128                    Some(Ok(result)) if is_unchanged(&result) => Ok(mapped),
2129                    Some(result) => result.map_err(|error| with_value_context(error, value.raw())),
2130                    None => Ok(mapped),
2131                }
2132            }
2133        }
2134    }
2135
2136    /// Descend into a pre-order replacement without dispatching its root again.
2137    fn map_default_root(
2138        &mut self,
2139        mapped: &Any,
2140        def_region_kind: DefRegionKind,
2141        permit: Permit,
2142    ) -> Result<Any> {
2143        let raw = *mapped.as_raw_ffi_any();
2144        self.default_map_current_raw(raw, def_region_kind, permit)
2145    }
2146}
2147
2148/// Internal mutation operations shared by the native mapper and a user
2149/// [`StructuralMutator`].
2150trait MutationDriver: Sized {
2151    fn dispatch_raw(
2152        &mut self,
2153        raw: TVMFFIAny,
2154        def_region_kind: DefRegionKind,
2155        permit: Permit,
2156    ) -> Result<Any>;
2157
2158    // The ABI entry has already installed and validated the active region.
2159    #[inline(always)]
2160    fn dispatch_abi_raw<const INPLACE: bool>(
2161        &mut self,
2162        raw: TVMFFIAny,
2163        kind: DefRegionKind,
2164    ) -> TVMFFIAny {
2165        let permit = if INPLACE {
2166            Permit::MaybeInPlace
2167        } else {
2168            Permit::Copy
2169        };
2170        result_into_raw(self.dispatch_raw(raw, kind, permit))
2171    }
2172
2173    fn var_remap_get_raw(&mut self, raw: TVMFFIAny) -> Result<Option<Any>>;
2174
2175    fn var_remap_set_raw(&mut self, raw: TVMFFIAny, replacement: &Any) -> Result<()>;
2176
2177    fn call_registered_hook(
2178        &mut self,
2179        raw: TVMFFIAny,
2180        def_region_kind: DefRegionKind,
2181        permit: Permit,
2182    ) -> Result<Option<Any>> {
2183        let (mutator, context) = checked_driver_context(self)?;
2184        let Some(attr) = structural_mutate_hook(raw, permit) else {
2185            // No foreign call needs access to the driver on a hook miss.
2186            return Ok(None);
2187        };
2188        with_current_driver_context(mutator, context, || {
2189            call_structural_mutate_hook(mutator, raw, def_region_kind, attr).map(Some)
2190        })
2191    }
2192
2193    fn default_map_current_raw(
2194        &mut self,
2195        raw: TVMFFIAny,
2196        def_region_kind: DefRegionKind,
2197        permit: Permit,
2198    ) -> Result<Any> {
2199        default_mutate_driver(self, raw, def_region_kind, permit)
2200    }
2201
2202    fn map_reflected(
2203        &mut self,
2204        raw: TVMFFIAny,
2205        def_region_kind: DefRegionKind,
2206        type_info: *const crate::tvm_ffi_sys::TVMFFITypeInfo,
2207    ) -> Result<Any> {
2208        let seq_hash_kind = unsafe {
2209            if (*type_info).metadata.is_null() {
2210                TVMFFISEqHashKind::kTVMFFISEqHashKindUnsupported as i32
2211            } else {
2212                (*(*type_info).metadata).structural_eq_hash_kind
2213            }
2214        };
2215        let inherited_region = free_var_child_region(def_region_kind, seq_hash_kind);
2216        // Match the C++ reflected-mutation contract: resolve and invoke the
2217        // shallow-copy hook before inspecting any fields. Besides providing
2218        // isolated setter storage, this means a missing or failing hook is an
2219        // error even when no field eventually changes.
2220        let output = shallow_copy(raw)?;
2221        let output_raw = *output.as_raw_ffi_any();
2222        let output_object = unsafe { output_raw.data_union.v_obj.cast::<u8>() };
2223        if output_object.is_null() {
2224            return Err(runtime_error(
2225                "native structural map: shallow copy has a null object pointer",
2226            ));
2227        }
2228
2229        let mut field_changed = false;
2230        let mut failure: Option<Error> = None;
2231        unsafe {
2232            for_each_field_info(type_info, &mut |field| {
2233                if field.flags & FLAG_SEQ_HASH_IGNORE != 0 {
2234                    return ControlFlow::Continue(());
2235                }
2236                match self.map_reflected_field(
2237                    output_object,
2238                    field,
2239                    inherited_region,
2240                    &mut field_changed,
2241                ) {
2242                    Ok(()) => ControlFlow::Continue(()),
2243                    Err(error) => {
2244                        failure = Some(error);
2245                        ControlFlow::Break(())
2246                    }
2247                }
2248            });
2249        }
2250        if let Some(error) = failure {
2251            return Err(error);
2252        }
2253        if field_changed {
2254            Ok(output)
2255        } else {
2256            Ok(Unchanged.into())
2257        }
2258    }
2259
2260    unsafe fn map_reflected_field(
2261        &mut self,
2262        output_object: *mut u8,
2263        field: &TVMFFIFieldInfo,
2264        inherited_region: DefRegionKind,
2265        field_changed: &mut bool,
2266    ) -> Result<()> {
2267        let Some(getter) = field.getter else {
2268            return Err(runtime_error(&format!(
2269                "native structural map: reflected field `{}` has no getter",
2270                field.name.as_str()
2271            )));
2272        };
2273        // Read every field from the copy so earlier setters' side effects are
2274        // visible to later field mappings, exactly as in the C++ fallback.
2275        let field_offset = usize::try_from(field.offset).map_err(|_| {
2276            runtime_error(&format!(
2277                "native structural map: reflected field `{}` has an invalid offset",
2278                field.name.as_str()
2279            ))
2280        })?;
2281        // SAFETY: registered reflection metadata guarantees that the field
2282        // offset lies within this object's allocation. The checked conversion
2283        // above also prevents truncation on 32-bit targets.
2284        let source_address = output_object.add(field_offset).cast::<c_void>();
2285        // Own the output slot before entering foreign code. A getter may
2286        // populate an owning result and still report an error.
2287        let mut child = Any::new();
2288        if getter(source_address, Any::as_data_ptr(&mut child)) != 0 {
2289            return Err(with_error_context(
2290                Error::from_raised(),
2291                &format!("field `{}`", field.name.as_str()),
2292            ));
2293        }
2294        // Reflection getters return owning values. Keep the child alive for
2295        // the complete recursive call, then let normal Drop release it.
2296        let child_raw = *child.as_raw_ffi_any();
2297        let child_region = field_def_region(field, inherited_region);
2298        let mapped = self
2299            .dispatch_raw(child_raw, child_region, Permit::Copy)
2300            .map_err(|error| {
2301                with_error_context(error, &format!("field `{}`", field.name.as_str()))
2302            })?;
2303        if is_unchanged(&mapped) || same_shallow(child_raw, *mapped.as_raw_ffi_any()) {
2304            return Ok(());
2305        }
2306
2307        call_field_setter(field, source_address, mapped.as_raw_ffi_any()).map_err(|error| {
2308            with_error_context(error, &format!("field `{}`", field.name.as_str()))
2309        })?;
2310        *field_changed = true;
2311        Ok(())
2312    }
2313}
2314
2315type StructuralMutatorHandle = *mut RuntimeStructuralMutatorObj;
2316
2317type FStructuralMutate =
2318    unsafe extern "C" fn(StructuralMutatorHandle, AnyView<'static>) -> TVMFFIAny;
2319type FStructuralVarRemapGet =
2320    unsafe extern "C" fn(StructuralMutatorHandle, AnyView<'static>) -> TVMFFIAny;
2321type FStructuralVarRemapSet =
2322    unsafe extern "C" fn(StructuralMutatorHandle, AnyView<'static>, AnyView<'static>) -> TVMFFIAny;
2323
2324/// Rust mirror of the C++ `StructuralMutatorVTable` ABI.
2325#[repr(C)]
2326struct StructuralMutatorVTable {
2327    mutate: FStructuralMutate,
2328    maybe_inplace_mutate: FStructuralMutate,
2329    var_remap_get: FStructuralVarRemapGet,
2330    var_remap_set: FStructuralVarRemapSet,
2331}
2332
2333type RuntimeVarRemapGetCallback = unsafe fn(*mut c_void, TVMFFIAny) -> Result<Option<Any>>;
2334type RuntimeVarRemapSetCallback = unsafe fn(*mut c_void, TVMFFIAny, &Any) -> Result<()>;
2335
2336struct RuntimeMutatorCallbacks {
2337    var_remap_get: RuntimeVarRemapGetCallback,
2338    var_remap_set: RuntimeVarRemapSetCallback,
2339}
2340
2341/// Active Rust mutator with the exact C++ `StructuralMutatorObj` prefix.
2342///
2343/// C++ type hooks read `vtable` and `def_region_mode`; Rust keeps its erased
2344/// driver state after that shared prefix.
2345#[repr(C)]
2346struct RuntimeStructuralMutatorObj {
2347    base: Object,
2348    vtable: *const StructuralMutatorVTable,
2349    def_region_mode: i32,
2350    // `context` is available only while a registered type hook is allowed to
2351    // re-enter Rust. `context_identity` is never dereferenced; it verifies
2352    // that a helper is being called on the mutator that started this run.
2353    context: *mut c_void,
2354    context_identity: *mut c_void,
2355    owner_thread: std::thread::ThreadId,
2356    callbacks: RuntimeMutatorCallbacks,
2357    // Identity substitutions for the active traversal.
2358    remap: RefCell<StructuralVarRemap>,
2359    panic: Option<Box<dyn std::any::Any + Send>>,
2360}
2361
2362const _: () = {
2363    assert!(
2364        std::mem::offset_of!(RuntimeStructuralMutatorObj, vtable)
2365            == std::mem::size_of::<TVMFFIObject>()
2366    );
2367    assert!(
2368        std::mem::offset_of!(RuntimeStructuralMutatorObj, def_region_mode)
2369            == std::mem::size_of::<TVMFFIObject>() + std::mem::size_of::<*const c_void>()
2370    );
2371};
2372
2373// SAFETY: `RuntimeStructuralMutatorObj` is `repr(C)` and starts with `Object`,
2374// so `object_header_mut` returns the allocation's actual TVMFFIObject header.
2375// `type_index` resolves the registered `ffi.StructuralMutator` subtype whose
2376// C++ prefix is checked by the compile-time offset assertions above.
2377unsafe impl ObjectCore for RuntimeStructuralMutatorObj {
2378    const TYPE_KEY: &'static str = "ffi.StructuralMutator";
2379    const TYPE_DEPTH: i32 = Object::TYPE_DEPTH + 1;
2380
2381    fn type_index() -> i32 {
2382        static TYPE_INDEX: LazyLock<i32> = LazyLock::new(|| unsafe {
2383            let key = TVMFFIByteArray::from_str(RuntimeStructuralMutatorObj::TYPE_KEY);
2384            let mut type_index = 0;
2385            let return_code = TVMFFITypeKeyToIndex(&key, &mut type_index);
2386            if return_code != 0 {
2387                panic!(
2388                    "ffi.StructuralMutator is not registered: {}",
2389                    Error::from_raised()
2390                );
2391            }
2392            type_index
2393        });
2394        *TYPE_INDEX
2395    }
2396
2397    unsafe fn object_header_mut(this: &mut Self) -> &mut TVMFFIObject {
2398        Object::object_header_mut(&mut this.base)
2399    }
2400}
2401
2402struct RuntimeMutatorVTable<D>(PhantomData<D>);
2403
2404impl<D: MutationDriver> RuntimeMutatorVTable<D> {
2405    const VTABLE: StructuralMutatorVTable = StructuralMutatorVTable {
2406        mutate: rust_vtable_mutate::<D>,
2407        maybe_inplace_mutate: rust_vtable_maybe_inplace_mutate::<D>,
2408        var_remap_get: rust_vtable_var_remap_get,
2409        var_remap_set: rust_vtable_var_remap_set,
2410    };
2411}
2412
2413struct RuntimeContextGuard {
2414    mutator: StructuralMutatorHandle,
2415    context: *mut c_void,
2416}
2417
2418impl Drop for RuntimeContextGuard {
2419    fn drop(&mut self) {
2420        // SAFETY: the guard is created only for a live mutator on its owner
2421        // thread. Restoring the pointer makes the same registered hook able to
2422        // invoke another child after this callback returns.
2423        unsafe { (*self.mutator).context = self.context };
2424    }
2425}
2426
2427/// Temporarily take the erased driver context out of the runtime object.
2428///
2429/// # Safety
2430///
2431/// `mutator` must be null or point to a live [`RuntimeStructuralMutatorObj`].
2432/// A non-null context must have been installed by the current run. Its runtime
2433/// callback table must reconstruct it according to that run's mutable-driver
2434/// contract.
2435unsafe fn take_runtime_context(mutator: StructuralMutatorHandle) -> Result<RuntimeContextGuard> {
2436    if !is_active_mutator(mutator) {
2437        return Err(inactive_mutator_error(mutator, "callback"));
2438    }
2439    let context = (*mutator).context;
2440    if context.is_null() {
2441        let message = if (*mutator).context_identity.is_null() {
2442            "structural mutator was retained after its active call"
2443        } else {
2444            "structural mutator may only be called by its active registered hook"
2445        };
2446        return Err(runtime_error(message));
2447    }
2448    // No raw context pointer remains callable while Rust executes the selected
2449    // mutable-driver entry.
2450    (*mutator).context = std::ptr::null_mut();
2451    Ok(RuntimeContextGuard { mutator, context })
2452}
2453
2454unsafe extern "C" fn rust_vtable_mutate<D: MutationDriver>(
2455    mutator: StructuralMutatorHandle,
2456    value: AnyView<'static>,
2457) -> TVMFFIAny {
2458    // SAFETY: this function is installed only in the vtable of a live
2459    // RuntimeStructuralMutatorObj built for D; `value` is borrowed for this call.
2460    rust_vtable_mutate_impl::<D, false>(mutator, value)
2461}
2462
2463unsafe extern "C" fn rust_vtable_maybe_inplace_mutate<D: MutationDriver>(
2464    mutator: StructuralMutatorHandle,
2465    value: AnyView<'static>,
2466) -> TVMFFIAny {
2467    // SAFETY: same vtable and borrowed-value contract as
2468    // `rust_vtable_mutate`.
2469    rust_vtable_mutate_impl::<D, true>(mutator, value)
2470}
2471
2472/// Run one typed vtable mutation callback and convert its result to ABI form.
2473///
2474/// # Safety
2475///
2476/// `mutator` must be a live runtime mutator created for `D`, and `value`
2477/// must remain valid for this call.
2478#[inline(always)]
2479unsafe fn rust_vtable_mutate_impl<D: MutationDriver, const INPLACE: bool>(
2480    mutator: StructuralMutatorHandle,
2481    value: AnyView<'static>,
2482) -> TVMFFIAny {
2483    let context_guard = match take_runtime_context(mutator) {
2484        Ok(guard) => guard,
2485        Err(error) => return result_into_raw(Err(error)),
2486    };
2487    let context = context_guard.context;
2488    let raw = *value.as_raw_ffi_any();
2489    let outcome = catch_unwind(AssertUnwindSafe(
2490        #[inline]
2491        || {
2492            let kind = match def_region_from_raw((*mutator).def_region_mode) {
2493                Ok(kind) => kind,
2494                Err(error) => return result_into_raw(Err(error)),
2495            };
2496            // take_runtime_context verified that this mutator is already active.
2497            runtime_dispatch_mutate::<D, INPLACE>(context, raw, kind)
2498        },
2499    ));
2500    match outcome {
2501        Ok(result) => result,
2502        Err(payload) => mutation_panic_result(mutator, payload),
2503    }
2504}
2505
2506#[cold]
2507unsafe fn mutation_panic_result(
2508    mutator: StructuralMutatorHandle,
2509    payload: Box<dyn std::any::Any + Send>,
2510) -> TVMFFIAny {
2511    (*mutator).panic = Some(payload);
2512    result_into_raw(Err(runtime_error("panic in structural mutator callback")))
2513}
2514
2515unsafe extern "C" fn rust_vtable_var_remap_get(
2516    mutator: StructuralMutatorHandle,
2517    var: AnyView<'static>,
2518) -> TVMFFIAny {
2519    let context_guard = match take_runtime_context(mutator) {
2520        Ok(guard) => guard,
2521        Err(error) => return result_into_raw(Err(error)),
2522    };
2523    let callback = (*mutator).callbacks.var_remap_get;
2524    let context = context_guard.context;
2525    let raw = *var.as_raw_ffi_any();
2526    match catch_unwind(AssertUnwindSafe(|| callback(context, raw))) {
2527        Ok(Ok(Some(replacement))) => Any::into_raw_ffi_any(replacement),
2528        Ok(Ok(None)) => TVMFFIAny::new(),
2529        Ok(Err(error)) => result_into_raw(Err(error)),
2530        Err(payload) => {
2531            (*mutator).panic = Some(payload);
2532            result_into_raw(Err(runtime_error("panic in structural var-remap lookup")))
2533        }
2534    }
2535}
2536
2537unsafe extern "C" fn rust_vtable_var_remap_set(
2538    mutator: StructuralMutatorHandle,
2539    var: AnyView<'static>,
2540    replacement: AnyView<'static>,
2541) -> TVMFFIAny {
2542    let context_guard = match take_runtime_context(mutator) {
2543        Ok(guard) => guard,
2544        Err(error) => return result_into_raw(Err(error)),
2545    };
2546    let callback = (*mutator).callbacks.var_remap_set;
2547    let context = context_guard.context;
2548    let var_raw = *var.as_raw_ffi_any();
2549    let replacement_raw = *replacement.as_raw_ffi_any();
2550    match catch_unwind(AssertUnwindSafe(|| {
2551        let replacement = owned_from_raw(replacement_raw)?;
2552        callback(context, var_raw, &replacement)
2553    })) {
2554        Ok(Ok(())) => TVMFFIAny::new(),
2555        Ok(Err(error)) => result_into_raw(Err(error)),
2556        Err(payload) => {
2557            (*mutator).panic = Some(payload);
2558            result_into_raw(Err(runtime_error(
2559                "panic in structural var-remap insertion",
2560            )))
2561        }
2562    }
2563}
2564
2565thread_local! {
2566    static ACTIVE_MUTATOR: Cell<StructuralMutatorHandle> = const {
2567        Cell::new(std::ptr::null_mut())
2568    };
2569}
2570
2571fn with_active_mutator<T>(handle: StructuralMutatorHandle, callback: impl FnOnce() -> T) -> T {
2572    ACTIVE_MUTATOR.with(|active| {
2573        let previous = active.replace(handle);
2574        struct Restore<'a> {
2575            active: &'a Cell<StructuralMutatorHandle>,
2576            previous: StructuralMutatorHandle,
2577        }
2578        impl Drop for Restore<'_> {
2579            fn drop(&mut self) {
2580                self.active.set(self.previous);
2581            }
2582        }
2583        let _restore = Restore { active, previous };
2584        callback()
2585    })
2586}
2587
2588fn active_mutator() -> Result<StructuralMutatorHandle> {
2589    ACTIVE_MUTATOR.with(|active| {
2590        let handle = active.get();
2591        if handle.is_null() {
2592            Err(runtime_error(
2593                "structural mutator helper called outside structural_mutate",
2594            ))
2595        } else {
2596            Ok(handle)
2597        }
2598    })
2599}
2600
2601fn invocation_var_remap_get<U: Sized>(
2602    mutator: &mut U,
2603    var: &StructuralView,
2604) -> Result<Option<Any>> {
2605    let active = active_mutator()?;
2606    let context = std::ptr::from_mut(mutator).cast::<c_void>();
2607    unsafe {
2608        if (*active).context_identity != context {
2609            return Err(runtime_error(
2610                "default structural var-remap used by a non-active mutator",
2611            ));
2612        }
2613        (*active).remap.borrow().get(var)
2614    }
2615}
2616
2617fn invocation_var_remap_set<U: Sized>(
2618    mutator: &mut U,
2619    var: &StructuralView,
2620    mutated_value: &Any,
2621) -> Result<()> {
2622    let active = active_mutator()?;
2623    let context = std::ptr::from_mut(mutator).cast::<c_void>();
2624    unsafe {
2625        if (*active).context_identity != context {
2626            return Err(runtime_error(
2627                "default structural var-remap used by a non-active mutator",
2628            ));
2629        }
2630        (*active).remap.borrow_mut().set(var, mutated_value)
2631    }
2632}
2633
2634#[inline]
2635fn is_active_mutator(handle: StructuralMutatorHandle) -> bool {
2636    !handle.is_null() && ACTIVE_MUTATOR.with(|active| active.get() == handle)
2637}
2638
2639#[cold]
2640fn inactive_mutator_error(mutator: StructuralMutatorHandle, operation: &str) -> Error {
2641    if mutator.is_null() {
2642        return runtime_error("null active structural mutator");
2643    }
2644    // The immutable owner id lets a foreign thread be rejected before reading
2645    // context fields that the owner thread may be updating.
2646    unsafe {
2647        if (*mutator).owner_thread != std::thread::current().id() {
2648            return runtime_error(&format!(
2649                "structural mutator {operation} invoked from a different thread"
2650            ));
2651        }
2652        if (*mutator).context_identity.is_null() {
2653            runtime_error("structural mutator was retained after its active call")
2654        } else {
2655            runtime_error(&format!(
2656                "structural mutator {operation} may only be used by its active registered hook"
2657            ))
2658        }
2659    }
2660}
2661
2662/// Expose the current mutable reborrow only for the duration of one registered
2663/// type hook. Nested vtable calls then reborrow from this pointer, and
2664/// [`take_runtime_context`] hides it again while Rust is executing.
2665fn with_current_driver_context<T>(
2666    mutator: StructuralMutatorHandle,
2667    context: *mut c_void,
2668    callback: impl FnOnce() -> Result<T>,
2669) -> Result<T> {
2670    // checked_driver_context validated this reborrow; no user code runs
2671    // between that check and exposing the pointer to the registered hook.
2672    unsafe {
2673        (*mutator).context = context;
2674        struct HideContext {
2675            mutator: StructuralMutatorHandle,
2676        }
2677        impl Drop for HideContext {
2678            fn drop(&mut self) {
2679                // SAFETY: this scope owns the temporary exposure and runs on
2680                // the mutator's owner thread.
2681                unsafe { (*self.mutator).context = std::ptr::null_mut() };
2682            }
2683        }
2684        let _hide = HideContext { mutator };
2685        callback()
2686    }
2687}
2688
2689fn checked_driver_context<D>(driver: &mut D) -> Result<(StructuralMutatorHandle, *mut c_void)> {
2690    let mutator = active_mutator()?;
2691    let context = std::ptr::from_mut(driver).cast::<c_void>();
2692    unsafe {
2693        if (*mutator).context_identity != context {
2694            return Err(runtime_error(
2695                "structural mutator helper called on a non-active mutator",
2696            ));
2697        }
2698        if !(*mutator).context.is_null() {
2699            return Err(runtime_error(
2700                "structural mutator driver context is already exposed",
2701            ));
2702        }
2703
2704        Ok((mutator, context))
2705    }
2706}
2707
2708fn def_region_from_raw(kind: i32) -> Result<DefRegionKind> {
2709    match kind {
2710        x if x == DefRegionKind::None as i32 => Ok(DefRegionKind::None),
2711        x if x == DefRegionKind::Pattern as i32 => Ok(DefRegionKind::Pattern),
2712        x if x == DefRegionKind::Simple as i32 => Ok(DefRegionKind::Simple),
2713        _ => Err(runtime_error("invalid structural definition-region kind")),
2714    }
2715}
2716
2717impl<D: MapDispatch, Policy: MutContextPolicy<D>, const PRE_ORDER: bool> MutationDriver
2718    for NativeMapper<'_, D, Policy, PRE_ORDER>
2719{
2720    fn dispatch_raw(
2721        &mut self,
2722        raw: TVMFFIAny,
2723        def_region_kind: DefRegionKind,
2724        permit: Permit,
2725    ) -> Result<Any> {
2726        with_mutation_region(def_region_kind, |kind| self.map_raw(raw, kind, permit))
2727    }
2728
2729    #[inline(always)]
2730    fn dispatch_abi_raw<const INPLACE: bool>(
2731        &mut self,
2732        raw: TVMFFIAny,
2733        kind: DefRegionKind,
2734    ) -> TVMFFIAny {
2735        let permit = if INPLACE {
2736            Permit::MaybeInPlace
2737        } else {
2738            Permit::Copy
2739        };
2740        result_into_raw(self.map_raw(raw, kind, permit))
2741    }
2742
2743    #[inline]
2744    fn default_map_current_raw(
2745        &mut self,
2746        raw: TVMFFIAny,
2747        kind: DefRegionKind,
2748        permit: Permit,
2749    ) -> Result<Any> {
2750        match self.policy.clone() {
2751            Some(policy) => {
2752                let view = StructuralView::from_raw(raw);
2753                policy::mutate_with_policy(
2754                    &mut policy::MutationDescent { driver: self },
2755                    policy.as_ref(),
2756                    MutateValue::new(&view, permit.inplace_mode(raw)),
2757                    kind,
2758                )
2759            }
2760            None => default_mutate_driver(self, raw, kind, permit),
2761        }
2762    }
2763
2764    fn var_remap_get_raw(&mut self, raw: TVMFFIAny) -> Result<Option<Any>> {
2765        self.remap.get(&StructuralView::from_raw(raw))
2766    }
2767
2768    fn var_remap_set_raw(&mut self, raw: TVMFFIAny, replacement: &Any) -> Result<()> {
2769        self.remap.set(&StructuralView::from_raw(raw), replacement)
2770    }
2771}
2772
2773impl<U: StructuralMutator> MutationDriver for U {
2774    #[inline]
2775    fn dispatch_raw(
2776        &mut self,
2777        raw: TVMFFIAny,
2778        def_region_kind: DefRegionKind,
2779        permit: Permit,
2780    ) -> Result<Any> {
2781        dispatch_user_raw(self, raw, def_region_kind, permit)
2782    }
2783
2784    #[inline(always)]
2785    fn dispatch_abi_raw<const INPLACE: bool>(
2786        &mut self,
2787        raw: TVMFFIAny,
2788        kind: DefRegionKind,
2789    ) -> TVMFFIAny {
2790        if INPLACE && raw.type_index < TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 {
2791            return result_into_raw(
2792                self.dispatch_mutate(&StructuralView::from_raw(raw), kind)
2793                    .map_err(|error| with_value_context(error, raw)),
2794            );
2795        }
2796        let permit = if INPLACE {
2797            Permit::MaybeInPlace
2798        } else {
2799            Permit::Copy
2800        };
2801        result_into_raw(dispatch_user_current_raw(self, raw, kind, permit))
2802    }
2803
2804    fn var_remap_get_raw(&mut self, raw: TVMFFIAny) -> Result<Option<Any>> {
2805        self.var_remap_get(&StructuralView::from_raw(raw))
2806    }
2807
2808    fn var_remap_set_raw(&mut self, raw: TVMFFIAny, replacement: &Any) -> Result<()> {
2809        self.var_remap_set(&StructuralView::from_raw(raw), replacement)
2810    }
2811}
2812
2813/// Invoke the concrete Rust driver selected when the runtime mutator was built.
2814///
2815/// # Safety
2816///
2817/// `context` must come from the current mutable reborrow of a live `D`; the
2818/// runtime object hides that pointer until this call returns.
2819#[inline(always)]
2820unsafe fn runtime_dispatch_mutate<D: MutationDriver, const INPLACE: bool>(
2821    context: *mut c_void,
2822    raw: TVMFFIAny,
2823    def_region_kind: DefRegionKind,
2824) -> TVMFFIAny {
2825    (&mut *context.cast::<D>()).dispatch_abi_raw::<INPLACE>(raw, def_region_kind)
2826}
2827
2828/// Dispatch a variable-remap lookup through the erased driver context.
2829///
2830/// # Safety
2831///
2832/// `context` must satisfy the same requirements as [`runtime_dispatch_mutate`].
2833unsafe fn runtime_var_remap_get<D: MutationDriver>(
2834    context: *mut c_void,
2835    raw: TVMFFIAny,
2836) -> Result<Option<Any>> {
2837    (&mut *context.cast::<D>()).var_remap_get_raw(raw)
2838}
2839
2840/// Dispatch a variable-remap insertion through the erased driver context.
2841///
2842/// # Safety
2843///
2844/// `context` must satisfy the same requirements as [`runtime_dispatch_mutate`], and
2845/// `replacement` must remain alive for this call.
2846unsafe fn runtime_var_remap_set<D: MutationDriver>(
2847    context: *mut c_void,
2848    raw: TVMFFIAny,
2849    replacement: &Any,
2850) -> Result<()> {
2851    (&mut *context.cast::<D>()).var_remap_set_raw(raw, replacement)
2852}
2853
2854fn run_structural_mutator<D: MutationDriver>(root: Any, driver: &mut D) -> Result<Any> {
2855    let context = std::ptr::from_mut(driver).cast::<c_void>();
2856    let callbacks = RuntimeMutatorCallbacks {
2857        var_remap_get: runtime_var_remap_get::<D>,
2858        var_remap_set: runtime_var_remap_set::<D>,
2859    };
2860    run_structural_mutator_with_context(
2861        root,
2862        context,
2863        callbacks,
2864        &RuntimeMutatorVTable::<D>::VTABLE,
2865    )
2866}
2867
2868fn run_structural_mutator_with_context(
2869    root: Any,
2870    context: *mut c_void,
2871    callbacks: RuntimeMutatorCallbacks,
2872    vtable: &'static StructuralMutatorVTable,
2873) -> Result<Any> {
2874    let mut active = ObjectArc::new(RuntimeStructuralMutatorObj {
2875        base: Object::new(),
2876        vtable,
2877        def_region_mode: DefRegionKind::None as i32,
2878        context,
2879        context_identity: context,
2880        owner_thread: std::thread::current().id(),
2881        callbacks,
2882        remap: RefCell::new(StructuralVarRemap::default()),
2883        panic: None,
2884    });
2885    let handle = unsafe { ObjectArc::as_raw_mut(&mut active) };
2886    let result = with_active_mutator(handle, || {
2887        call_mutator(
2888            handle,
2889            *root.as_raw_ffi_any(),
2890            DefRegionKind::None,
2891            Permit::MaybeInPlace,
2892        )
2893    });
2894    // A structural hook may only use the active mutator synchronously on this
2895    // thread. Make a retained reference fail instead of exposing a dangling
2896    // Rust state pointer. Release invocation-local identity owners here as
2897    // well: foreign code may retain the ABI object after the run ends.
2898    unsafe {
2899        (*handle).remap.get_mut().clear();
2900        (*handle).context = std::ptr::null_mut();
2901        (*handle).context_identity = std::ptr::null_mut();
2902    }
2903    let panic = unsafe { (*handle).panic.take() };
2904    if let Some(payload) = panic {
2905        drop(result);
2906        resume_unwind(payload);
2907    }
2908    result.map(|result| if is_unchanged(&result) { root } else { result })
2909}
2910
2911fn call_mutator(
2912    mutator: StructuralMutatorHandle,
2913    raw: TVMFFIAny,
2914    def_region_kind: DefRegionKind,
2915    permit: Permit,
2916) -> Result<Any> {
2917    if mutator.is_null() {
2918        return Err(runtime_error("no active structural mutator"));
2919    }
2920    let use_inplace = permit == Permit::MaybeInPlace && object_is_unique(raw);
2921    let callback = unsafe {
2922        if use_inplace {
2923            (*(*mutator).vtable).maybe_inplace_mutate
2924        } else {
2925            (*(*mutator).vtable).mutate
2926        }
2927    };
2928    with_mutator_def_region(mutator, def_region_kind, |_| unsafe {
2929        let view = AnyView::from_raw_ffi_any(raw);
2930        result_from_raw(callback(mutator, view))
2931    })
2932}
2933
2934#[inline]
2935fn structural_mutate_hook(raw: TVMFFIAny, permit: Permit) -> Option<TVMFFIAny> {
2936    let use_inplace = permit == Permit::MaybeInPlace && object_is_unique(raw);
2937    if use_inplace {
2938        if let Some(attr) = structural_maybe_inplace_mutate_column()
2939            .and_then(|column| column.get_raw(raw.type_index))
2940        {
2941            if attr.type_index == TVMFFITypeIndex::kTVMFFIOpaquePtr as i32
2942                || attr.type_index == TVMFFITypeIndex::kTVMFFIFunction as i32
2943            {
2944                return Some(attr);
2945            }
2946        }
2947    }
2948    let attr = structural_mutate_column().and_then(|column| column.get_raw(raw.type_index))?;
2949    (attr.type_index != TVMFFITypeIndex::kTVMFFINone as i32).then_some(attr)
2950}
2951
2952fn call_structural_mutate_hook(
2953    mutator: StructuralMutatorHandle,
2954    raw: TVMFFIAny,
2955    def_region_kind: DefRegionKind,
2956    attr: TVMFFIAny,
2957) -> Result<Any> {
2958    with_mutator_def_region(mutator, def_region_kind, |_| unsafe {
2959        match attr.type_index {
2960            x if x == TVMFFITypeIndex::kTVMFFIOpaquePtr as i32 => {
2961                let pointer = attr.data_union.v_ptr;
2962                if pointer.is_null() {
2963                    return Err(runtime_error("structural mutation hook is null"));
2964                }
2965                // SAFETY: the `__s_mutate__`/`__s_maybe_inplace_mutate__`
2966                // registration protocol defines an opaque-pointer attribute
2967                // as exactly an FStructuralMutate function pointer.
2968                let hook: FStructuralMutate = std::mem::transmute(pointer);
2969                let value = AnyView::from_raw_ffi_any(raw);
2970                result_from_raw(hook(mutator, value))
2971            }
2972            x if x == TVMFFITypeIndex::kTVMFFIFunction as i32 => {
2973                let function = Function::try_from(AnyView::from_raw_ffi_any(attr))?;
2974                let mutator_value = borrowed_mutator_view(mutator);
2975                let value = AnyView::from_raw_ffi_any(raw);
2976                function.call_packed(&[mutator_value, value])
2977            }
2978            _ => Err(Error::new(
2979                TYPE_ERROR,
2980                "__s_mutate__ must be an opaque function pointer or ffi.Function",
2981                "",
2982            )),
2983        }
2984    })
2985}
2986
2987/// Borrow a live runtime mutator as an object-valued ABI argument.
2988///
2989/// # Safety
2990///
2991/// `mutator` must point to a live object and outlive the returned view. The
2992/// view does not increment the object's reference count.
2993unsafe fn borrowed_mutator_view<'a>(mutator: StructuralMutatorHandle) -> AnyView<'a> {
2994    let object = mutator.cast::<TVMFFIObject>();
2995    let mut raw = TVMFFIAny::new();
2996    raw.type_index = (*object).type_index;
2997    raw.small_str_len = 0;
2998    raw.data_union.v_obj = object;
2999    AnyView::from_raw_ffi_any(raw)
3000}
3001
3002#[inline(always)]
3003fn result_into_raw(result: Result<Any>) -> TVMFFIAny {
3004    unsafe {
3005        match result {
3006            Ok(value) => Any::into_raw_ffi_any(value),
3007            Err(error) => Any::into_raw_ffi_any(Any::from(error)),
3008        }
3009    }
3010}
3011
3012/// Resolve only at an owning-value API boundary; internal Any carriers and
3013/// native hooks keep the unchanged tag to avoid acquiring the original.
3014#[inline]
3015fn resolve_result(result: Any, original: TVMFFIAny) -> Result<Any> {
3016    if is_unchanged(&result) {
3017        owned_from_raw(original)
3018    } else {
3019        Ok(result)
3020    }
3021}
3022
3023/// Take ownership of one value returned by a structural-mutation ABI hook.
3024///
3025/// # Safety
3026///
3027/// `raw` must contain one owning TVMFFIAny result that has not already been
3028/// consumed. An Error object is converted into the Rust error channel.
3029#[inline(always)]
3030unsafe fn result_from_raw(raw: TVMFFIAny) -> Result<Any> {
3031    let value = Any::from_raw_ffi_any(raw);
3032    if value.type_index() != TVMFFITypeIndex::kTVMFFIError as i32 {
3033        return Ok(value);
3034    }
3035    match Error::try_from(value) {
3036        Ok(error) | Err(error) => Err(error),
3037    }
3038}
3039
3040#[inline(always)]
3041fn with_mutator_def_region<T>(
3042    mutator: StructuralMutatorHandle,
3043    kind: DefRegionKind,
3044    callback: impl FnOnce(DefRegionKind) -> T,
3045) -> T {
3046    unsafe {
3047        let previous = (*mutator).def_region_mode;
3048        // Precedence: a pattern region propagates; entering any kind inside it has no effect.
3049        let effective = if previous == DefRegionKind::Pattern as i32 {
3050            DefRegionKind::Pattern
3051        } else {
3052            (*mutator).def_region_mode = kind as i32;
3053            kind
3054        };
3055        struct Restore {
3056            mutator: StructuralMutatorHandle,
3057            previous: i32,
3058        }
3059        impl Drop for Restore {
3060            fn drop(&mut self) {
3061                if self.previous != DefRegionKind::Pattern as i32 {
3062                    unsafe { (*self.mutator).def_region_mode = self.previous };
3063                }
3064            }
3065        }
3066        let _restore = Restore { mutator, previous };
3067        // One call site keeps the continuation visible to the inliner.
3068        callback(effective)
3069    }
3070}
3071
3072#[inline(always)]
3073fn with_mutation_region<T>(
3074    kind: DefRegionKind,
3075    callback: impl FnOnce(DefRegionKind) -> Result<T>,
3076) -> Result<T> {
3077    let mutator = active_mutator()?;
3078    with_mutator_def_region(mutator, kind, callback)
3079}
3080
3081#[inline(always)]
3082fn dispatch_user_raw<U: StructuralMutator>(
3083    mutator: &mut U,
3084    raw: TVMFFIAny,
3085    def_region_kind: DefRegionKind,
3086    permit: Permit,
3087) -> Result<Any> {
3088    with_mutation_region(
3089        def_region_kind,
3090        #[inline(always)]
3091        |kind| dispatch_user_current_raw(mutator, raw, kind, permit),
3092    )
3093}
3094
3095#[inline(always)]
3096fn dispatch_user_current_raw<U: StructuralMutator>(
3097    mutator: &mut U,
3098    raw: TVMFFIAny,
3099    kind: DefRegionKind,
3100    permit: Permit,
3101) -> Result<Any> {
3102    let result = if permit == Permit::MaybeInPlace && object_is_unique(raw) {
3103        let mut scoped_raw = raw;
3104        mutator.dispatch_maybe_inplace_mutate(InplaceValue::from_raw(&mut scoped_raw), kind)
3105    } else {
3106        mutator.dispatch_mutate(&StructuralView::from_raw(raw), kind)
3107    };
3108    result.map_err(|error| with_value_context(error, raw))
3109}
3110
3111fn user_default_mutate<U: StructuralMutator>(
3112    mutator: &mut U,
3113    raw: TVMFFIAny,
3114    def_region_kind: DefRegionKind,
3115    permit: Permit,
3116) -> Result<Any> {
3117    with_mutation_region(def_region_kind, |kind| {
3118        let value = StructuralView::from_raw(raw);
3119        mutator.on_default_mutate(MutateValue::new(&value, permit.inplace_mode(raw)), kind)
3120    })
3121    .map_err(|error| with_value_context(error, raw))
3122}
3123
3124fn default_mutate_driver<D: MutationDriver>(
3125    driver: &mut D,
3126    raw: TVMFFIAny,
3127    def_region_kind: DefRegionKind,
3128    permit: Permit,
3129) -> Result<Any> {
3130    default_mutate_driver_impl(driver, raw, def_region_kind, permit)
3131        .map_err(|error| with_value_context(error, raw))
3132}
3133
3134fn default_mutate_driver_impl<D: MutationDriver>(
3135    driver: &mut D,
3136    raw: TVMFFIAny,
3137    def_region_kind: DefRegionKind,
3138    permit: Permit,
3139) -> Result<Any> {
3140    // Match C++ DefaultMutateExpected: a registered type hook owns any
3141    // identity-remap policy for that type. Automatic remapping applies only
3142    // to the reflected fallback below.
3143    if let Some(mutated) = driver.call_registered_hook(raw, def_region_kind, permit)? {
3144        return Ok(mutated);
3145    }
3146    if raw.type_index < TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 {
3147        return owned_from_raw(raw);
3148    }
3149
3150    let type_info = checked_type_info(raw.type_index)?;
3151    let kind = unsafe {
3152        if (*type_info).metadata.is_null() {
3153            None
3154        } else {
3155            Some((*(*type_info).metadata).structural_eq_hash_kind)
3156        }
3157    };
3158    let is_free_var = kind == Some(TVMFFISEqHashKind::kTVMFFISEqHashKindFreeVar as i32);
3159    let is_dag_node = kind == Some(TVMFFISEqHashKind::kTVMFFISEqHashKindDAGNode as i32);
3160    if is_free_var || is_dag_node {
3161        if let Some(mutated) = driver.var_remap_get_raw(raw)? {
3162            // The ABI uses None for a miss; an Unchanged marker is a cached result.
3163            if mutated.type_index() != TVMFFITypeIndex::kTVMFFINone as i32 {
3164                return Ok(mutated);
3165            }
3166        }
3167    }
3168    // A variable use with no binding retains its identity without visiting fields.
3169    if is_free_var && def_region_kind == DefRegionKind::None {
3170        return Ok(Unchanged.into());
3171    }
3172
3173    let result = driver.map_reflected(raw, def_region_kind, type_info)?;
3174    if is_dag_node
3175        || (is_free_var && (def_region_kind == DefRegionKind::Pattern || !is_unchanged(&result)))
3176    {
3177        // Keep markers for DAG nodes and pattern definitions. An unchanged simple
3178        // definition needs no binding: subsequent uses retain the original on a miss.
3179        driver.var_remap_set_raw(raw, &result)?;
3180    }
3181    Ok(result)
3182}
3183
3184/// Mutate a structured value with a mutator or typed callback chain.
3185///
3186/// The root is consumed to establish the ownership boundary for optional
3187/// in-place mutation. A matching callback supplies the final value; unmatched
3188/// values use default mutation.
3189pub fn structural_mutate<R, M>(root: R, mutator: impl IntoMutator<M>) -> Result<Any>
3190where
3191    R: Into<Any>,
3192{
3193    mutator.mutate_root(root.into())
3194}
3195
3196/// Transform a structured value graph with ordered replacement callbacks.
3197///
3198/// The root is consumed. A uniquely owned built-in container may therefore be
3199/// reused in place, while passing `root.clone()` keeps the original shared and
3200/// selects copy-on-write behavior. Map and Dict keys are anchors and are not
3201/// mapped. Their registered structural hooks own container traversal.
3202///
3203/// Callbacks run at every occurrence. Default reflected descent handles FreeVar
3204/// and DAG-node remapping; registered hooks own their type's remapping policy.
3205/// Callback replacements are not automatically recorded as substitutions.
3206///
3207/// In-place changes completed before an error are not rolled back. Because
3208/// this function consumes `root`, an error does not return the partly mapped
3209/// root to the caller.
3210pub fn structural_map<R, M, H>(root: R, mapper: H, order: WalkOrder) -> Result<Any>
3211where
3212    R: Into<Any>,
3213    H: IntoMapper<M>,
3214{
3215    mapper.into_mapper().map_root(root.into(), order)
3216}
3217
3218fn shallow_copy(raw: TVMFFIAny) -> Result<Any> {
3219    let Some(attr) = shallow_copy_column().and_then(|column| column.get_raw(raw.type_index)) else {
3220        return Err(Error::new(
3221            TYPE_ERROR,
3222            &format!(
3223                "type `{}` cannot use reflected structural mutation because it does not define `{SHALLOW_COPY_ATTR}`",
3224                type_key_of(raw.type_index)
3225            ),
3226            "",
3227        ));
3228    };
3229    if attr.type_index != TVMFFITypeIndex::kTVMFFIFunction as i32 {
3230        return Err(Error::new(
3231            TYPE_ERROR,
3232            &format!("{SHALLOW_COPY_ATTR} must be an ffi.Function"),
3233            "",
3234        ));
3235    }
3236    let function = unsafe { attr.data_union.v_obj };
3237    if function.is_null() {
3238        return Err(runtime_error("shallow copy function pointer is null"));
3239    }
3240    // The registry owns this function throughout the call; borrowing it avoids
3241    // an atomic retain/release for every reflected node.
3242    let mut result = Any::new();
3243    let status =
3244        unsafe { TVMFFIFunctionCall(function.cast(), &raw, 1, Any::as_data_ptr(&mut result)) };
3245    if status != 0 {
3246        return Err(Error::from_raised());
3247    }
3248    let result_raw = *result.as_raw_ffi_any();
3249    let result_pointer = unsafe { result_raw.data_union.v_obj };
3250    let source_pointer = unsafe { raw.data_union.v_obj };
3251    if result_raw.type_index != raw.type_index
3252        || result_pointer.is_null()
3253        || result_pointer == source_pointer
3254    {
3255        return Err(Error::new(
3256            TYPE_ERROR,
3257            "shallow copy callback must return a distinct object with the same type as its input",
3258            "",
3259        ));
3260    }
3261    Ok(result)
3262}
3263
3264fn call_field_setter(
3265    field: &TVMFFIFieldInfo,
3266    field_address: *mut c_void,
3267    value: &TVMFFIAny,
3268) -> Result<()> {
3269    if field.setter.is_null() {
3270        return Err(Error::new(
3271            TYPE_ERROR,
3272            &format!(
3273                "cannot structurally mutate field `{}` because it does not define a setter",
3274                field.name.as_str()
3275            ),
3276            "",
3277        ));
3278    }
3279    let return_code = unsafe {
3280        if field.flags & FLAG_SETTER_IS_FUNCTION == 0 {
3281            // SAFETY: reflection registration requires a non-Function setter
3282            // pointer to use the TVMFFIFieldSetter signature.
3283            let setter: TVMFFIFieldSetter = std::mem::transmute(field.setter);
3284            setter(field_address, value)
3285        } else {
3286            let mut args = [TVMFFIAny::new(), *value];
3287            args[0].type_index = TVMFFITypeIndex::kTVMFFIOpaquePtr as i32;
3288            args[0].data_union.v_ptr = field_address;
3289            // Own the result slot before entering foreign code so a partial
3290            // owning result is released on both success and failure.
3291            let mut result = Any::new();
3292            TVMFFIFunctionCall(
3293                field.setter as TVMFFIObjectHandle,
3294                args.as_ptr(),
3295                2,
3296                Any::as_data_ptr(&mut result),
3297            )
3298        }
3299    };
3300    if return_code == 0 {
3301        Ok(())
3302    } else {
3303        Err(Error::from_raised())
3304    }
3305}
3306
3307fn object_identity_key(raw: TVMFFIAny) -> Result<NonNull<TVMFFIObject>> {
3308    if raw.type_index < TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 {
3309        return Err(var_remap_key_error());
3310    }
3311    let pointer = unsafe { raw.data_union.v_obj };
3312    NonNull::new(pointer)
3313        .ok_or_else(|| runtime_error("native structural map: identity object has a null pointer"))
3314}
3315
3316#[cold]
3317fn var_remap_key_error() -> Error {
3318    Error::new(
3319        TYPE_ERROR,
3320        "variable-remap keys must be object-backed values",
3321        "",
3322    )
3323}
3324
3325#[inline]
3326fn checked_type_info(type_index: i32) -> Result<*const crate::tvm_ffi_sys::TVMFFITypeInfo> {
3327    let info = unsafe { TVMFFIGetTypeInfo(type_index) };
3328    if info.is_null() {
3329        Err(unregistered_type_error(type_index))
3330    } else {
3331        Ok(info)
3332    }
3333}
3334
3335#[cold]
3336fn unregistered_type_error(type_index: i32) -> Error {
3337    runtime_error(&format!(
3338        "native structural map: unregistered type index {type_index}"
3339    ))
3340}
3341
3342#[inline]
3343fn object_is_unique(raw: TVMFFIAny) -> bool {
3344    if raw.type_index < TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 {
3345        return false;
3346    }
3347    let pointer = unsafe { raw.data_union.v_obj };
3348    !pointer.is_null() && unsafe { object::unsafe_::strong_count(pointer) == 1 }
3349}
3350
3351#[inline]
3352fn owned_from_raw(raw: TVMFFIAny) -> Result<Any> {
3353    if let Some(owned) = try_to_owned_without_normalization(raw) {
3354        return Ok(owned);
3355    }
3356    if raw.type_index >= TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 {
3357        return Err(runtime_error(
3358            "native structural map: object-backed value has a null pointer",
3359        ));
3360    }
3361
3362    // Raw string/bytes views and ObjectRValueRef require normalization (or a
3363    // move) rather than a bitwise copy; keep the generic C ABI conversion for
3364    // those uncommon representations.
3365    let mut owned = Any::new();
3366    let return_code = unsafe { TVMFFIAnyViewToOwnedAny(&raw, Any::as_data_ptr(&mut owned)) };
3367    if return_code == 0 {
3368        Ok(owned)
3369    } else {
3370        Err(Error::from_raised())
3371    }
3372}
3373
3374#[cold]
3375fn with_value_context(error: Error, raw: TVMFFIAny) -> Error {
3376    if raw.type_index < TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 {
3377        error
3378    } else {
3379        with_error_context(
3380            with_visit_error_context(error, raw),
3381            &format!("object `{}`", type_key_of(raw.type_index)),
3382        )
3383    }
3384}
3385
3386#[cold]
3387fn with_error_context(error: Error, frame: &str) -> Error {
3388    with_structural_error_context(error, "map", frame)
3389}
3390
3391#[cold]
3392#[inline(never)]
3393fn runtime_error(message: &str) -> Error {
3394    Error::new(RUNTIME_ERROR, message, "")
3395}
3396
3397fn cached_column(cache: &'static AtomicUsize, name: &'static str) -> Option<TypeAttrColumn> {
3398    let cached = cache.load(Ordering::Relaxed);
3399    if cached != 0 {
3400        let pointer = cached as *mut TVMFFITypeAttrColumn;
3401        return Some(unsafe { TypeAttrColumn::from_non_null(NonNull::new_unchecked(pointer)) });
3402    }
3403    let column = type_attr_column(name)?;
3404    // TypeAttrColumn is a transparent NonNull wrapper shared with the
3405    // structural-visit module. Registry column addresses are immortal.
3406    cache.store(column.as_ptr() as usize, Ordering::Relaxed);
3407    Some(column)
3408}
3409
3410static STRUCTURAL_MUTATE_COLUMN: AtomicUsize = AtomicUsize::new(0);
3411static STRUCTURAL_MAYBE_INPLACE_MUTATE_COLUMN: AtomicUsize = AtomicUsize::new(0);
3412static SHALLOW_COPY_COLUMN: AtomicUsize = AtomicUsize::new(0);
3413
3414fn structural_mutate_column() -> Option<TypeAttrColumn> {
3415    cached_column(&STRUCTURAL_MUTATE_COLUMN, STRUCTURAL_MUTATE_ATTR)
3416}
3417
3418fn structural_maybe_inplace_mutate_column() -> Option<TypeAttrColumn> {
3419    cached_column(
3420        &STRUCTURAL_MAYBE_INPLACE_MUTATE_COLUMN,
3421        STRUCTURAL_MAYBE_INPLACE_MUTATE_ATTR,
3422    )
3423}
3424
3425fn shallow_copy_column() -> Option<TypeAttrColumn> {
3426    cached_column(&SHALLOW_COPY_COLUMN, SHALLOW_COPY_ATTR)
3427}