1use 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,
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
68pub use super::structural_common::StructuralValue as MapValue;
70
71#[doc(hidden)]
73pub type MapResult = Result<Any>;
74
75mod callback_result_sealed {
76 use super::{Any, Result};
77
78 pub trait Sealed {}
79
80 impl<T: Into<Any>> Sealed for T {}
81 impl<T: Into<Any>> Sealed for Result<T> {}
82}
83
84#[doc(hidden)]
91pub trait IntoMapResult: callback_result_sealed::Sealed {
92 fn into_map_result(self) -> MapResult;
93}
94
95impl<T: Into<Any>> IntoMapResult for T {
96 #[inline]
97 fn into_map_result(self) -> MapResult {
98 Ok(self.into())
99 }
100}
101
102impl<T: Into<Any>> IntoMapResult for Result<T> {
103 #[inline]
104 fn into_map_result(self) -> MapResult {
105 self.map(Into::into)
106 }
107}
108
109pub struct MutateContext<'a, State, Driver: ?Sized = dyn MutateContextDriver<State> + 'a> {
114 driver: &'a mut Driver,
115 current: MapValue,
116 def_region_kind: DefRegionKind,
117 _state: PhantomData<fn() -> State>,
118 _not_send_sync: PhantomData<Rc<()>>,
119}
120
121pub type CallbackMutator<'a, State = (), Driver = dyn MutateContextDriver<State> + 'a> =
126 MutateContext<'a, State, Driver>;
127
128pub struct Mutator {
134 current: MapValue,
135 def_region_kind: DefRegionKind,
136 _not_send_sync: PhantomData<Rc<()>>,
137}
138
139impl Mutator {
140 #[inline(always)]
142 pub fn current(&self) -> &MapValue {
143 &self.current
144 }
145
146 #[inline(always)]
148 pub fn def_region_kind(&self) -> DefRegionKind {
149 self.def_region_kind
150 }
151
152 #[inline(always)]
154 pub fn region(&self) -> DefRegionKind {
155 self.def_region_kind
156 }
157
158 #[inline(always)]
160 pub fn mutate<D, T>(&mut self, dispatch: &mut D, value: &T) -> Result<Any>
161 where
162 D: MutateDispatch,
163 for<'x> AnyView<'x>: From<&'x T>,
164 {
165 StructuralMutator::mutate(dispatch, value, self.def_region_kind)
166 }
167
168 #[inline(always)]
170 pub fn mutate_with<D, T>(
171 &mut self,
172 dispatch: &mut D,
173 value: &T,
174 def_region_kind: DefRegionKind,
175 ) -> Result<Any>
176 where
177 D: MutateDispatch,
178 for<'x> AnyView<'x>: From<&'x T>,
179 {
180 StructuralMutator::mutate(dispatch, value, def_region_kind)
181 }
182
183 #[inline(always)]
185 pub fn maybe_inplace_mutate<D, T>(&mut self, dispatch: &mut D, value: T) -> Result<Any>
186 where
187 D: MutateDispatch,
188 T: Into<Any>,
189 {
190 self.maybe_inplace_mutate_with(dispatch, value, self.def_region_kind)
191 }
192
193 #[inline(always)]
195 pub fn maybe_inplace_mutate_with<D, T>(
196 &mut self,
197 dispatch: &mut D,
198 value: T,
199 def_region_kind: DefRegionKind,
200 ) -> Result<Any>
201 where
202 D: MutateDispatch,
203 T: Into<Any>,
204 {
205 StructuralMutator::maybe_inplace_mutate(dispatch, value, def_region_kind)
206 }
207
208 #[inline(always)]
210 pub fn default_mutate<D: MutateDispatch>(&mut self, dispatch: &mut D) -> Result<Any> {
211 StructuralMutator::default_mutate(dispatch, &self.current, self.def_region_kind)
212 }
213
214 #[inline]
216 pub fn mutate_result<D, T>(&mut self, dispatch: &mut D, value: &T) -> Result<UnchangedOr<Any>>
217 where
218 D: MutateDispatch,
219 for<'x> AnyView<'x>: From<&'x T>,
220 {
221 self.mutate_with_result(dispatch, value, self.def_region_kind)
222 }
223
224 #[inline]
226 pub fn mutate_with_result<D, T>(
227 &mut self,
228 dispatch: &mut D,
229 value: &T,
230 kind: DefRegionKind,
231 ) -> Result<UnchangedOr<Any>>
232 where
233 D: MutateDispatch,
234 for<'x> AnyView<'x>: From<&'x T>,
235 {
236 StructuralMutator::mutate_result(dispatch, value, kind)
237 }
238
239 #[inline]
241 pub fn default_mutate_result<D: MutateDispatch>(
242 &mut self,
243 dispatch: &mut D,
244 ) -> Result<UnchangedOr<Any>> {
245 StructuralMutator::default_mutate_result(dispatch, &self.current, self.def_region_kind)
246 }
247
248 #[inline(always)]
250 pub fn var_remap_get<D: MutateDispatch>(
251 &mut self,
252 dispatch: &mut D,
253 var: &MapValue,
254 ) -> Result<Option<Any>> {
255 StructuralMutator::var_remap_get(dispatch, var)
256 }
257
258 #[inline(always)]
260 pub fn var_remap_set<D: MutateDispatch>(
261 &mut self,
262 dispatch: &mut D,
263 var: &MapValue,
264 mutated_value: &Any,
265 ) -> Result<()> {
266 StructuralMutator::var_remap_set(dispatch, var, mutated_value)
267 }
268}
269
270#[doc(hidden)]
271pub trait MutateContextDriver<State> {
277 fn state(&self) -> &State;
278 fn state_mut(&mut self) -> &mut State;
279 fn mutate_raw(
280 &mut self,
281 raw: TVMFFIAny,
282 def_region_kind: DefRegionKind,
283 permit: Permit,
284 ) -> Result<Any>;
285 fn default_mutate_raw(&mut self, raw: TVMFFIAny, def_region_kind: DefRegionKind)
286 -> Result<Any>;
287 fn var_remap_get_raw(&mut self, raw: TVMFFIAny) -> Result<Option<Any>>;
288 fn var_remap_set_raw(&mut self, raw: TVMFFIAny, mutated_value: &Any) -> Result<()>;
289}
290
291impl<State, Driver> MutateContext<'_, State, Driver>
292where
293 Driver: MutateContextDriver<State> + ?Sized,
294{
295 #[inline(always)]
297 pub fn state(&self) -> &State {
298 self.driver.state()
299 }
300
301 #[inline(always)]
303 pub fn state_mut(&mut self) -> &mut State {
304 self.driver.state_mut()
305 }
306
307 #[inline(always)]
309 pub fn current(&self) -> &MapValue {
310 &self.current
311 }
312
313 #[inline(always)]
315 pub fn def_region_kind(&self) -> DefRegionKind {
316 self.def_region_kind
317 }
318
319 #[inline]
321 pub fn region(&self) -> DefRegionKind {
322 self.def_region_kind
323 }
324
325 #[inline(always)]
328 pub fn mutate<T>(&mut self, value: &T) -> Result<Any>
329 where
330 for<'x> AnyView<'x>: From<&'x T>,
331 {
332 self.mutate_with(value, self.def_region_kind)
333 }
334
335 #[inline(always)]
337 pub fn mutate_with<T>(&mut self, value: &T, def_region_kind: DefRegionKind) -> Result<Any>
338 where
339 for<'x> AnyView<'x>: From<&'x T>,
340 {
341 let view = AnyView::from(value);
342 self.driver
343 .mutate_raw(*view.as_raw_ffi_any(), def_region_kind, Permit::Copy)
344 .and_then(|result| resolve_result(result, *view.as_raw_ffi_any()))
345 }
346
347 #[inline(always)]
350 pub fn maybe_inplace_mutate<T: Into<Any>>(&mut self, value: T) -> Result<Any> {
351 self.maybe_inplace_mutate_with(value, self.def_region_kind)
352 }
353
354 #[inline(always)]
356 pub fn maybe_inplace_mutate_with<T: Into<Any>>(
357 &mut self,
358 value: T,
359 def_region_kind: DefRegionKind,
360 ) -> Result<Any> {
361 let value = value.into();
362 let result = self.driver.mutate_raw(
363 *value.as_raw_ffi_any(),
364 def_region_kind,
365 Permit::MaybeInPlace,
366 )?;
367 Ok(if is_unchanged(&result) { value } else { result })
368 }
369
370 #[inline(always)]
375 pub fn default_mutate(&mut self) -> Result<Any> {
376 self.driver
377 .default_mutate_raw(self.current.raw(), self.def_region_kind)
378 .and_then(|result| resolve_result(result, self.current.raw()))
379 }
380
381 #[inline]
383 pub fn mutate_result<T>(&mut self, value: &T) -> Result<UnchangedOr<Any>>
384 where
385 for<'x> AnyView<'x>: From<&'x T>,
386 {
387 self.mutate_with_result(value, self.def_region_kind)
388 }
389
390 #[inline]
392 pub fn mutate_with_result<T>(
393 &mut self,
394 value: &T,
395 kind: DefRegionKind,
396 ) -> Result<UnchangedOr<Any>>
397 where
398 for<'x> AnyView<'x>: From<&'x T>,
399 {
400 let view = AnyView::from(value);
401 self.driver
402 .mutate_raw(*view.as_raw_ffi_any(), kind, Permit::Copy)
403 .and_then(UnchangedOr::from_carrier)
404 }
405
406 #[inline]
408 pub fn default_mutate_result(&mut self) -> Result<UnchangedOr<Any>> {
409 self.driver
410 .default_mutate_raw(self.current.raw(), self.def_region_kind)
411 .and_then(UnchangedOr::from_carrier)
412 }
413
414 #[inline(always)]
416 pub fn var_remap_get(&mut self, var: &MapValue) -> Result<Option<Any>> {
417 self.driver.var_remap_get_raw(var.raw())
418 }
419
420 #[inline(always)]
422 pub fn var_remap_set(&mut self, var: &MapValue, mutated_value: &Any) -> Result<()> {
423 self.driver.var_remap_set_raw(var.raw(), mutated_value)
424 }
425}
426
427#[diagnostic::on_unimplemented(
434 message = "`{Self}` is not a supported `structural_mutate` mutator",
435 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 `&MapValue`, followed by `&mut CallbackMutator<State>`; or a tuple of up to 12 such callbacks (tuples may nest)",
436 note = "callback arguments need explicit type annotations; use `MutateCallbacks::new(state, callbacks)` for ordinary mutable callback state"
437)]
438pub trait IntoMutator<Marker> {
439 #[doc(hidden)]
440 fn mutate_root(self, root: Any) -> Result<Any>;
441}
442
443impl<U: StructuralMutator> IntoMutator<U> for &mut U {
444 fn mutate_root(self, root: Any) -> Result<Any> {
445 run_structural_mutator(root, self)
446 }
447}
448
449#[doc(hidden)]
454pub trait IntoMutateResult: callback_result_sealed::Sealed {
455 fn into_mutate_result(self) -> Result<Any>;
456}
457
458impl<T: Into<Any>> IntoMutateResult for T {
459 #[inline]
460 fn into_mutate_result(self) -> Result<Any> {
461 Ok(self.into())
462 }
463}
464
465impl<T: Into<Any>> IntoMutateResult for Result<T> {
466 #[inline]
467 fn into_mutate_result(self) -> Result<Any> {
468 self.map(Into::into)
469 }
470}
471
472#[doc(hidden)]
473pub type MutateResult = Result<Any>;
474
475#[doc(hidden)]
476pub enum DynamicMutateCallbacks {}
478
479pub trait MutateChainLink<State, Marker>: mutate_sealed::SealedLink<State, Marker> {
481 #[doc(hidden)]
482 type Strategy;
483
484 #[doc(hidden)]
485 fn try_mutate(
486 &self,
487 value: &MapValue,
488 mutator: &mut MutateContext<'_, State>,
489 ) -> Option<MutateResult>;
490}
491
492pub trait MutateDispatch: Sized {
500 fn dispatch_mutate(&mut self, value: &MapValue, mutator: &mut Mutator) -> Option<MutateResult>;
501}
502
503impl<D: MutateDispatch> IntoMutator<ByMutateDispatch> for D {
504 #[inline]
505 fn mutate_root(mut self, root: Any) -> Result<Any> {
506 run_structural_mutator(root, &mut self)
507 }
508}
509
510mod mutate_sealed {
511 use super::{IntoMutateResult, MapValue, MutateContext, ObjectCore};
512
513 pub trait SealedLink<State, Marker> {}
514
515 impl<F, State, T, O> SealedLink<State, super::ByMutateOwned<T>> for F
516 where
517 F: for<'mutator, 'driver> Fn(T, &'mutator mut MutateContext<'driver, State>) -> O,
518 O: IntoMutateResult,
519 {
520 }
521
522 impl<F, State, N: ObjectCore, O> SealedLink<State, super::ByMutateNode<N>> for F
523 where
524 F: for<'value, 'mutator, 'driver> Fn(
525 &'value N,
526 &'mutator mut MutateContext<'driver, State>,
527 ) -> O,
528 O: IntoMutateResult,
529 {
530 }
531
532 impl<F, State, O> SealedLink<State, super::ByMutateCatchAll> for F
533 where
534 F: for<'value, 'mutator, 'driver> Fn(
535 &'value MapValue,
536 &'mutator mut MutateContext<'driver, State>,
537 ) -> O,
538 O: IntoMutateResult,
539 {
540 }
541}
542
543#[doc(hidden)]
544pub enum ByMutateDispatch {}
545
546#[doc(hidden)]
547pub struct ByMutateOwned<T>(PhantomData<T>);
548
549impl<F, State, T, O> MutateChainLink<State, ByMutateOwned<T>> for F
550where
551 F: for<'mutator, 'driver> Fn(T, &'mutator mut MutateContext<'driver, State>) -> O,
552 T: crate::type_traits::AnyCompatible,
553 O: IntoMutateResult,
554{
555 type Strategy = DynamicMutateCallbacks;
556
557 fn try_mutate(
558 &self,
559 value: &MapValue,
560 mutator: &mut MutateContext<'_, State>,
561 ) -> Option<MutateResult> {
562 value
563 .cast::<T>()
564 .map(|typed| self(typed, mutator).into_mutate_result())
565 }
566}
567
568#[doc(hidden)]
569pub struct ByMutateNode<N>(PhantomData<N>);
570
571impl<F, State, N, O> MutateChainLink<State, ByMutateNode<N>> for F
572where
573 F: for<'value, 'mutator, 'driver> Fn(
574 &'value N,
575 &'mutator mut MutateContext<'driver, State>,
576 ) -> O,
577 N: ObjectCore,
578 O: IntoMutateResult,
579{
580 type Strategy = DynamicMutateCallbacks;
581
582 fn try_mutate(
583 &self,
584 value: &MapValue,
585 mutator: &mut MutateContext<'_, State>,
586 ) -> Option<MutateResult> {
587 value
588 .as_node::<N>()
589 .map(|node| self(node, mutator).into_mutate_result())
590 }
591}
592
593#[doc(hidden)]
594pub enum ByMutateCatchAll {}
595
596impl<F, State, O> MutateChainLink<State, ByMutateCatchAll> for F
597where
598 F: for<'value, 'mutator, 'driver> Fn(
599 &'value MapValue,
600 &'mutator mut MutateContext<'driver, State>,
601 ) -> O,
602 O: IntoMutateResult,
603{
604 type Strategy = DynamicMutateCallbacks;
605
606 fn try_mutate(
607 &self,
608 value: &MapValue,
609 mutator: &mut MutateContext<'_, State>,
610 ) -> Option<MutateResult> {
611 Some(self(value, mutator).into_mutate_result())
612 }
613}
614
615#[doc(hidden)]
616pub struct ByMutateChainLink<Markers>(PhantomData<fn(Markers)>);
617
618macro_rules! impl_mutate_chain_link {
619 ($(($F:ident, $M:ident, $idx:tt)),+) => {
620 impl<State, $($F, $M,)+>
621 mutate_sealed::SealedLink<State, ByMutateChainLink<($($M,)+)>> for ($($F,)+)
622 where
623 $($F: MutateChainLink<State, $M>,)+
624 {
625 }
626
627 impl<State, $($F, $M,)+> MutateChainLink<State, ByMutateChainLink<($($M,)+)>>
628 for ($($F,)+)
629 where
630 $($F: MutateChainLink<State, $M>,)+
631 {
632 type Strategy = DynamicMutateCallbacks;
633
634 fn try_mutate(
635 &self,
636 value: &MapValue,
637 mutator: &mut MutateContext<'_, State>,
638 ) -> Option<MutateResult> {
639 $(
640 if let Some(result) = self.$idx.try_mutate(value, mutator) {
641 return Some(result);
642 }
643 )+
644 None
645 }
646 }
647 };
648}
649
650impl_callback_chain_tuple_arities!(impl_mutate_chain_link);
651
652pub struct MutateCallbacks<State, Link, Marker> {
654 state: State,
655 callbacks: Rc<Link>,
656 _marker: PhantomData<fn(Marker)>,
657}
658
659impl<State, Link, Marker> MutateCallbacks<State, Link, Marker>
660where
661 Link: MutateChainLink<State, Marker>,
662{
663 pub fn new(state: State, callbacks: Link) -> Self {
665 Self {
666 state,
667 callbacks: Rc::new(callbacks),
668 _marker: PhantomData,
669 }
670 }
671}
672
673impl<State, Link, Marker> MutateCallbacks<State, Link, Marker> {
674 pub fn state(&self) -> &State {
676 &self.state
677 }
678
679 pub fn state_mut(&mut self) -> &mut State {
681 &mut self.state
682 }
683
684 pub fn into_state(self) -> State {
686 self.state
687 }
688}
689
690struct DirectMutateCallbacks<'a, Link, Marker> {
691 state: (),
692 callbacks: &'a Link,
693 _marker: PhantomData<fn(Marker)>,
694}
695
696trait MutateCallbackState<State> {
697 fn callback_state(&self) -> &State;
698 fn callback_state_mut(&mut self) -> &mut State;
699}
700
701impl<State, Link, Marker> MutateCallbackState<State> for MutateCallbacks<State, Link, Marker> {
702 fn callback_state(&self) -> &State {
703 &self.state
704 }
705
706 fn callback_state_mut(&mut self) -> &mut State {
707 &mut self.state
708 }
709}
710
711impl<Link, Marker> MutateCallbackState<()> for DirectMutateCallbacks<'_, Link, Marker> {
712 fn callback_state(&self) -> &() {
713 &self.state
714 }
715
716 fn callback_state_mut(&mut self) -> &mut () {
717 &mut self.state
718 }
719}
720
721#[doc(hidden)]
722pub struct ByMutateCallbacks<Marker>(PhantomData<fn(Marker)>);
723
724impl<Link, Marker> IntoMutator<ByMutateCallbacks<Marker>> for Link
725where
726 Link: MutateChainLink<(), Marker>,
727 Link::Strategy: MutateCallbackStrategy<(), Link, Marker>,
728{
729 fn mutate_root(self, root: Any) -> Result<Any> {
730 let callbacks = self;
731 let mut mutator = DirectMutateCallbacks::<Link, Marker> {
732 state: (),
733 callbacks: &callbacks,
734 _marker: PhantomData,
735 };
736 run_structural_mutator(root, &mut mutator)
737 }
738}
739
740pub trait MapDispatch: Sized {
746 fn dispatch_map(
747 &mut self,
748 value: &MapValue,
749 def_region_kind: DefRegionKind,
750 ) -> Option<MapResult>;
751}
752
753impl<V: MapDispatch> MapDispatch for &mut V {
754 #[inline]
755 fn dispatch_map(
756 &mut self,
757 value: &MapValue,
758 def_region_kind: DefRegionKind,
759 ) -> Option<MapResult> {
760 (**self).dispatch_map(value, def_region_kind)
761 }
762}
763
764#[diagnostic::on_unimplemented(
766 message = "unsupported structural-map callback shape",
767 label = "this value cannot be used as a structural mapper",
768 note = "pass `&mut` a type implementing `MapDispatch`, a supported closure, or a tuple of callbacks"
769)]
770pub trait IntoMapper<Marker> {
771 type Mapper: MapDispatch;
772 fn into_mapper(self) -> Self::Mapper;
773}
774
775#[doc(hidden)]
776pub enum ByMapDispatch {}
777
778impl<'a, V: MapDispatch> IntoMapper<ByMapDispatch> for &'a mut V {
779 type Mapper = &'a mut V;
780
781 #[inline]
782 fn into_mapper(self) -> Self::Mapper {
783 self
784 }
785}
786
787pub trait MapChainLink<Marker>: sealed_map::SealedMapLink<Marker> {
792 #[doc(hidden)]
793 fn try_map(&mut self, value: &MapValue, def_region_kind: DefRegionKind) -> Option<MapResult>;
794}
795
796mod sealed_map {
797 use super::{DefRegionKind, IntoMapResult, MapDispatch, MapValue, ObjectCore};
798
799 pub trait SealedMapLink<Marker> {}
800
801 impl<F, T, O> SealedMapLink<super::ByMapOwned<T>> for F
802 where
803 F: FnMut(T) -> O,
804 O: IntoMapResult,
805 {
806 }
807
808 impl<F, T, O> SealedMapLink<super::ByMapOwnedKind<T>> for F
809 where
810 F: FnMut(T, DefRegionKind) -> O,
811 O: IntoMapResult,
812 {
813 }
814
815 impl<F, N: ObjectCore, O> SealedMapLink<super::ByMapNode<N>> for F
816 where
817 F: for<'a> FnMut(&'a N) -> O,
818 O: IntoMapResult,
819 {
820 }
821
822 impl<F, N: ObjectCore, O> SealedMapLink<super::ByMapNodeKind<N>> for F
823 where
824 F: for<'a> FnMut(&'a N, DefRegionKind) -> O,
825 O: IntoMapResult,
826 {
827 }
828
829 impl<F, O> SealedMapLink<super::ByMapCatchAll> for F
830 where
831 F: for<'a> FnMut(&'a MapValue) -> O,
832 O: IntoMapResult,
833 {
834 }
835
836 impl<F, O> SealedMapLink<super::ByMapCatchAllKind> for F
837 where
838 F: for<'a> FnMut(&'a MapValue, DefRegionKind) -> O,
839 O: IntoMapResult,
840 {
841 }
842
843 impl<V: MapDispatch> SealedMapLink<super::ByMapDispatchLink> for &mut V {}
844}
845
846#[doc(hidden)]
847pub struct ByMapOwned<T>(PhantomData<T>);
848
849impl<F, T, O> MapChainLink<ByMapOwned<T>> for F
850where
851 F: FnMut(T) -> O,
852 T: crate::type_traits::AnyCompatible,
853 O: IntoMapResult,
854{
855 #[inline]
856 fn try_map(&mut self, value: &MapValue, _def_region_kind: DefRegionKind) -> Option<MapResult> {
857 value.cast::<T>().map(|typed| self(typed).into_map_result())
858 }
859}
860
861#[doc(hidden)]
862pub struct ByMapOwnedKind<T>(PhantomData<T>);
863
864impl<F, T, O> MapChainLink<ByMapOwnedKind<T>> for F
865where
866 F: FnMut(T, DefRegionKind) -> O,
867 T: crate::type_traits::AnyCompatible,
868 O: IntoMapResult,
869{
870 #[inline]
871 fn try_map(&mut self, value: &MapValue, def_region_kind: DefRegionKind) -> Option<MapResult> {
872 value
873 .cast::<T>()
874 .map(|typed| self(typed, def_region_kind).into_map_result())
875 }
876}
877
878#[doc(hidden)]
879pub struct ByMapNode<N>(PhantomData<N>);
880
881impl<F, N, O> MapChainLink<ByMapNode<N>> for F
882where
883 F: for<'a> FnMut(&'a N) -> O,
884 N: ObjectCore,
885 O: IntoMapResult,
886{
887 #[inline]
888 fn try_map(&mut self, value: &MapValue, _def_region_kind: DefRegionKind) -> Option<MapResult> {
889 value
890 .as_node::<N>()
891 .map(|node| self(node).into_map_result())
892 }
893}
894
895#[doc(hidden)]
896pub struct ByMapNodeKind<N>(PhantomData<N>);
897
898impl<F, N, O> MapChainLink<ByMapNodeKind<N>> for F
899where
900 F: for<'a> FnMut(&'a N, DefRegionKind) -> O,
901 N: ObjectCore,
902 O: IntoMapResult,
903{
904 #[inline]
905 fn try_map(&mut self, value: &MapValue, def_region_kind: DefRegionKind) -> Option<MapResult> {
906 value
907 .as_node::<N>()
908 .map(|node| self(node, def_region_kind).into_map_result())
909 }
910}
911
912#[doc(hidden)]
913pub enum ByMapCatchAll {}
914
915impl<F, O> MapChainLink<ByMapCatchAll> for F
916where
917 F: for<'a> FnMut(&'a MapValue) -> O,
918 O: IntoMapResult,
919{
920 #[inline]
921 fn try_map(&mut self, value: &MapValue, _def_region_kind: DefRegionKind) -> Option<MapResult> {
922 Some(self(value).into_map_result())
923 }
924}
925
926#[doc(hidden)]
927pub enum ByMapCatchAllKind {}
928
929impl<F, O> MapChainLink<ByMapCatchAllKind> for F
930where
931 F: for<'a> FnMut(&'a MapValue, DefRegionKind) -> O,
932 O: IntoMapResult,
933{
934 #[inline]
935 fn try_map(&mut self, value: &MapValue, def_region_kind: DefRegionKind) -> Option<MapResult> {
936 Some(self(value, def_region_kind).into_map_result())
937 }
938}
939
940#[doc(hidden)]
941pub struct ByMapChainLink<Markers>(PhantomData<fn(Markers)>);
942
943#[doc(hidden)]
944pub enum ByMapDispatchLink {}
945
946impl<V: MapDispatch> MapChainLink<ByMapDispatchLink> for &mut V {
947 #[inline]
948 fn try_map(&mut self, value: &MapValue, def_region_kind: DefRegionKind) -> Option<MapResult> {
949 self.dispatch_map(value, def_region_kind)
950 }
951}
952
953#[doc(hidden)]
955pub struct MapChain<Link, Marker> {
956 link: Link,
957 marker: PhantomData<fn(Marker)>,
958}
959
960impl<Link, Marker> MapChain<Link, Marker> {
961 #[inline]
962 fn new(link: Link) -> Self {
963 MapChain {
964 link,
965 marker: PhantomData,
966 }
967 }
968}
969
970impl<Link, Marker> MapDispatch for MapChain<Link, Marker>
971where
972 Link: MapChainLink<Marker>,
973{
974 #[inline]
975 fn dispatch_map(
976 &mut self,
977 value: &MapValue,
978 def_region_kind: DefRegionKind,
979 ) -> Option<MapResult> {
980 self.link.try_map(value, def_region_kind)
981 }
982}
983
984macro_rules! impl_map_chain_link {
985 ($(($F:ident, $M:ident, $idx:tt)),+) => {
986 impl<$($F, $M,)+> sealed_map::SealedMapLink<ByMapChainLink<($($M,)+)>> for ($($F,)+)
987 where
988 $($F: MapChainLink<$M>,)+
989 {
990 }
991
992 impl<$($F, $M,)+> MapChainLink<ByMapChainLink<($($M,)+)>> for ($($F,)+)
993 where
994 $($F: MapChainLink<$M>,)+
995 {
996 #[inline]
997 fn try_map(
998 &mut self,
999 value: &MapValue,
1000 def_region_kind: DefRegionKind,
1001 ) -> Option<MapResult> {
1002 $(
1003 if let Some(result) = self.$idx.try_map(value, def_region_kind) {
1004 return Some(result);
1005 }
1006 )+
1007 None
1008 }
1009 }
1010
1011 impl<$($F, $M,)+> IntoMapper<($($M,)+)> for ($($F,)+)
1012 where
1013 $($F: MapChainLink<$M>,)+
1014 {
1015 type Mapper = MapChain<($($F,)+), ByMapChainLink<($($M,)+)>>;
1016
1017 #[inline]
1018 fn into_mapper(self) -> Self::Mapper {
1019 MapChain::new(self)
1020 }
1021 }
1022 };
1023}
1024
1025impl_callback_chain_tuple_arities!(impl_map_chain_link);
1026
1027macro_rules! impl_bare_map_link {
1028 ($(($marker:ident, $($fn_args:ty),+)),+ $(,)?) => {
1029 $(
1030 impl<F, T, O> IntoMapper<$marker<T>> for F
1031 where
1032 F: FnMut($($fn_args),+) -> O,
1033 Self: MapChainLink<$marker<T>>,
1034 O: IntoMapResult,
1035 {
1036 type Mapper = MapChain<F, $marker<T>>;
1037
1038 #[inline]
1039 fn into_mapper(self) -> Self::Mapper {
1040 MapChain::new(self)
1041 }
1042 }
1043 )+
1044 };
1045}
1046
1047impl_bare_map_link!(
1048 (ByMapOwned, T),
1049 (ByMapOwnedKind, T, DefRegionKind),
1050 (ByMapNode, &T),
1051 (ByMapNodeKind, &T, DefRegionKind),
1052);
1053
1054impl<F, O> IntoMapper<ByMapCatchAll> for F
1055where
1056 F: for<'a> FnMut(&'a MapValue) -> O,
1057 O: IntoMapResult,
1058{
1059 type Mapper = MapChain<F, ByMapCatchAll>;
1060
1061 #[inline]
1062 fn into_mapper(self) -> Self::Mapper {
1063 MapChain::new(self)
1064 }
1065}
1066
1067impl<F, O> IntoMapper<ByMapCatchAllKind> for F
1068where
1069 F: for<'a> FnMut(&'a MapValue, DefRegionKind) -> O,
1070 O: IntoMapResult,
1071{
1072 type Mapper = MapChain<F, ByMapCatchAllKind>;
1073
1074 #[inline]
1075 fn into_mapper(self) -> Self::Mapper {
1076 MapChain::new(self)
1077 }
1078}
1079
1080pub struct InplaceValue<'a> {
1084 value: MapValue,
1085 _scope: PhantomData<&'a mut TVMFFIAny>,
1086}
1087
1088impl<'a> InplaceValue<'a> {
1089 #[inline]
1090 fn from_raw(raw: &'a mut TVMFFIAny) -> Self {
1091 Self {
1092 value: MapValue::from_raw(*raw),
1093 _scope: PhantomData,
1094 }
1095 }
1096
1097 #[inline]
1099 pub fn as_value(&self) -> &MapValue {
1100 &self.value
1101 }
1102
1103 #[inline]
1108 pub fn to_owned(&self) -> Any {
1109 self.value.to_owned()
1110 }
1111}
1112
1113impl Deref for InplaceValue<'_> {
1114 type Target = MapValue;
1115
1116 #[inline]
1117 fn deref(&self) -> &Self::Target {
1118 self.as_value()
1119 }
1120}
1121
1122#[derive(Default)]
1126pub struct StructuralVarRemap {
1127 entries: HashMap<NonNull<TVMFFIObject>, MemoEntry>,
1128}
1129
1130impl StructuralVarRemap {
1131 pub fn get(&self, var: &MapValue) -> Result<Option<Any>> {
1133 let key = object_identity_key(var.raw())?;
1134 Ok(self.entries.get(&key).map(|entry| entry.result.clone()))
1135 }
1136
1137 pub fn set(&mut self, var: &MapValue, mutated_value: &Any) -> Result<()> {
1139 let key = object_identity_key(var.raw())?;
1140 self.entries.insert(
1141 key,
1142 MemoEntry {
1143 _original: var.to_owned(),
1144 result: mutated_value.clone(),
1145 },
1146 );
1147 Ok(())
1148 }
1149
1150 pub fn clear(&mut self) {
1152 self.entries.clear();
1153 }
1154}
1155
1156pub trait StructuralMutator: Sized {
1162 fn dispatch_mutate(&mut self, value: &MapValue, def_region_kind: DefRegionKind) -> Result<Any>;
1166
1167 fn dispatch_maybe_inplace_mutate(
1173 &mut self,
1174 value: InplaceValue<'_>,
1175 def_region_kind: DefRegionKind,
1176 ) -> Result<Any> {
1177 self.dispatch_mutate(value.as_value(), def_region_kind)
1178 }
1179
1180 fn mutate<T>(&mut self, value: &T, def_region_kind: DefRegionKind) -> Result<Any>
1183 where
1184 for<'x> AnyView<'x>: From<&'x T>,
1185 {
1186 let view = AnyView::from(value);
1187 dispatch_user_raw(self, *view.as_raw_ffi_any(), def_region_kind, Permit::Copy)
1188 .and_then(|result| resolve_result(result, *view.as_raw_ffi_any()))
1189 }
1190
1191 fn maybe_inplace_mutate<T>(&mut self, value: T, def_region_kind: DefRegionKind) -> Result<Any>
1194 where
1195 T: Into<Any>,
1196 {
1197 let value = value.into();
1198 let result = dispatch_user_raw(
1199 self,
1200 *value.as_raw_ffi_any(),
1201 def_region_kind,
1202 Permit::MaybeInPlace,
1203 )?;
1204 Ok(if is_unchanged(&result) { value } else { result })
1205 }
1206
1207 fn default_mutate(&mut self, value: &MapValue, def_region_kind: DefRegionKind) -> Result<Any> {
1209 user_default_mutate(self, value.raw(), def_region_kind, Permit::Copy)
1210 .and_then(|result| resolve_result(result, value.raw()))
1211 }
1212
1213 fn default_mutate_value<T>(&mut self, value: &T, def_region_kind: DefRegionKind) -> Result<Any>
1220 where
1221 for<'x> AnyView<'x>: From<&'x T>,
1222 {
1223 let view = AnyView::from(value);
1224 user_default_mutate(self, *view.as_raw_ffi_any(), def_region_kind, Permit::Copy)
1225 .and_then(|result| resolve_result(result, *view.as_raw_ffi_any()))
1226 }
1227
1228 fn default_maybe_inplace_mutate(
1233 &mut self,
1234 value: InplaceValue<'_>,
1235 def_region_kind: DefRegionKind,
1236 ) -> Result<Any> {
1237 let raw = value.raw();
1238 let permit = if object_is_unique(raw) {
1239 Permit::MaybeInPlace
1240 } else {
1241 Permit::Copy
1242 };
1243 user_default_mutate(self, raw, def_region_kind, permit)
1244 .and_then(|result| resolve_result(result, raw))
1245 }
1246
1247 fn mutate_result<T>(&mut self, value: &T, kind: DefRegionKind) -> Result<UnchangedOr<Any>>
1249 where
1250 for<'x> AnyView<'x>: From<&'x T>,
1251 {
1252 let view = AnyView::from(value);
1253 dispatch_user_raw(self, *view.as_raw_ffi_any(), kind, Permit::Copy)
1254 .and_then(UnchangedOr::from_carrier)
1255 }
1256
1257 fn default_mutate_result(
1259 &mut self,
1260 value: &MapValue,
1261 kind: DefRegionKind,
1262 ) -> Result<UnchangedOr<Any>> {
1263 user_default_mutate(self, value.raw(), kind, Permit::Copy)
1264 .and_then(UnchangedOr::from_carrier)
1265 }
1266
1267 fn default_mutate_value_result<T>(
1269 &mut self,
1270 value: &T,
1271 kind: DefRegionKind,
1272 ) -> Result<UnchangedOr<Any>>
1273 where
1274 for<'x> AnyView<'x>: From<&'x T>,
1275 {
1276 let view = AnyView::from(value);
1277 user_default_mutate(self, *view.as_raw_ffi_any(), kind, Permit::Copy)
1278 .and_then(UnchangedOr::from_carrier)
1279 }
1280
1281 fn default_maybe_inplace_mutate_result(
1283 &mut self,
1284 value: InplaceValue<'_>,
1285 kind: DefRegionKind,
1286 ) -> Result<UnchangedOr<Any>> {
1287 let raw = value.raw();
1288 let permit = if object_is_unique(raw) {
1289 Permit::MaybeInPlace
1290 } else {
1291 Permit::Copy
1292 };
1293 user_default_mutate(self, raw, kind, permit).and_then(UnchangedOr::from_carrier)
1294 }
1295
1296 fn var_remap_get(&mut self, var: &MapValue) -> Result<Option<Any>> {
1298 invocation_var_remap_get(self, var)
1299 }
1300
1301 fn var_remap_set(&mut self, var: &MapValue, mutated_value: &Any) -> Result<()> {
1303 invocation_var_remap_set(self, var, mutated_value)
1304 }
1305}
1306
1307impl<D: MutateDispatch> StructuralMutator for D {
1308 #[inline(always)]
1309 fn dispatch_mutate(&mut self, value: &MapValue, def_region_kind: DefRegionKind) -> Result<Any> {
1310 let mut mutator = Mutator {
1311 current: MapValue::from_raw(value.raw()),
1312 def_region_kind,
1313 _not_send_sync: PhantomData,
1314 };
1315 match MutateDispatch::dispatch_mutate(self, value, &mut mutator) {
1316 Some(result) => result,
1317 None => user_default_mutate(self, value.raw(), def_region_kind, Permit::Copy),
1318 }
1319 }
1320
1321 #[inline(always)]
1322 fn dispatch_maybe_inplace_mutate(
1323 &mut self,
1324 value: InplaceValue<'_>,
1325 def_region_kind: DefRegionKind,
1326 ) -> Result<Any> {
1327 let mut mutator = Mutator {
1328 current: MapValue::from_raw(value.raw()),
1329 def_region_kind,
1330 _not_send_sync: PhantomData,
1331 };
1332 match MutateDispatch::dispatch_mutate(self, value.as_value(), &mut mutator) {
1333 Some(result) => result,
1334 None => {
1335 let raw = value.raw();
1336 let permit = if object_is_unique(raw) {
1337 Permit::MaybeInPlace
1338 } else {
1339 Permit::Copy
1340 };
1341 user_default_mutate(self, raw, def_region_kind, permit)
1342 }
1343 }
1344 }
1345}
1346
1347trait MutateCallbackStrategy<State, Link, Marker> {
1350 fn try_mutate<Driver>(
1351 driver: &mut Driver,
1352 callback_ptr: *const Link,
1353 value: &MapValue,
1354 def_region_kind: DefRegionKind,
1355 ) -> Option<MutateResult>
1356 where
1357 Driver: MutateContextDriver<State>;
1358}
1359
1360impl<State, Link, Marker> MutateCallbackStrategy<State, Link, Marker> for DynamicMutateCallbacks
1361where
1362 Link: MutateChainLink<State, Marker>,
1363{
1364 #[inline(always)]
1365 fn try_mutate<Driver>(
1366 driver: &mut Driver,
1367 callback_ptr: *const Link,
1368 value: &MapValue,
1369 def_region_kind: DefRegionKind,
1370 ) -> Option<MutateResult>
1371 where
1372 Driver: MutateContextDriver<State>,
1373 {
1374 let mut mutator = MutateContext::<State, dyn MutateContextDriver<State>> {
1375 driver,
1376 current: MapValue::from_raw(value.raw()),
1377 def_region_kind,
1378 _state: PhantomData,
1379 _not_send_sync: PhantomData,
1380 };
1381 unsafe { (&*callback_ptr).try_mutate(value, &mut mutator) }
1384 }
1385}
1386
1387#[inline(always)]
1388fn try_mutate_callbacks<State, Link, Marker, Driver>(
1389 driver: &mut Driver,
1390 callback_ptr: *const Link,
1391 value: &MapValue,
1392 def_region_kind: DefRegionKind,
1393) -> Option<MutateResult>
1394where
1395 Link: MutateChainLink<State, Marker>,
1396 Link::Strategy: MutateCallbackStrategy<State, Link, Marker>,
1397 Driver: MutateContextDriver<State>,
1398{
1399 <Link::Strategy as MutateCallbackStrategy<State, Link, Marker>>::try_mutate(
1400 driver,
1401 callback_ptr,
1402 value,
1403 def_region_kind,
1404 )
1405}
1406
1407impl<State, Link, Marker> StructuralMutator for MutateCallbacks<State, Link, Marker>
1408where
1409 Link: MutateChainLink<State, Marker>,
1410 Link::Strategy: MutateCallbackStrategy<State, Link, Marker>,
1411{
1412 #[inline(always)]
1413 fn dispatch_mutate(&mut self, value: &MapValue, def_region_kind: DefRegionKind) -> Result<Any> {
1414 let callback_ptr = Rc::as_ptr(&self.callbacks);
1415 match try_mutate_callbacks::<State, Link, Marker, _>(
1416 self,
1417 callback_ptr,
1418 value,
1419 def_region_kind,
1420 ) {
1421 Some(result) => result,
1422 None => user_default_mutate(self, value.raw(), def_region_kind, Permit::Copy),
1423 }
1424 }
1425
1426 #[inline(always)]
1427 fn dispatch_maybe_inplace_mutate(
1428 &mut self,
1429 value: InplaceValue<'_>,
1430 def_region_kind: DefRegionKind,
1431 ) -> Result<Any> {
1432 let callback_ptr = Rc::as_ptr(&self.callbacks);
1433 match try_mutate_callbacks::<State, Link, Marker, _>(
1434 self,
1435 callback_ptr,
1436 value.as_value(),
1437 def_region_kind,
1438 ) {
1439 Some(result) => result,
1440 None => self
1441 .default_maybe_inplace_mutate_result(value, def_region_kind)
1442 .map(Any::from),
1443 }
1444 }
1445}
1446
1447impl<Link, Marker> StructuralMutator for DirectMutateCallbacks<'_, Link, Marker>
1448where
1449 Link: MutateChainLink<(), Marker>,
1450 Link::Strategy: MutateCallbackStrategy<(), Link, Marker>,
1451{
1452 #[inline(always)]
1453 fn dispatch_mutate(&mut self, value: &MapValue, def_region_kind: DefRegionKind) -> Result<Any> {
1454 let callback_ptr = std::ptr::from_ref(self.callbacks);
1455 match try_mutate_callbacks::<(), Link, Marker, _>(
1456 self,
1457 callback_ptr,
1458 value,
1459 def_region_kind,
1460 ) {
1461 Some(result) => result,
1462 None => user_default_mutate(self, value.raw(), def_region_kind, Permit::Copy),
1463 }
1464 }
1465
1466 #[inline(always)]
1467 fn dispatch_maybe_inplace_mutate(
1468 &mut self,
1469 value: InplaceValue<'_>,
1470 def_region_kind: DefRegionKind,
1471 ) -> Result<Any> {
1472 let callback_ptr = std::ptr::from_ref(self.callbacks);
1473 match try_mutate_callbacks::<(), Link, Marker, _>(
1474 self,
1475 callback_ptr,
1476 value.as_value(),
1477 def_region_kind,
1478 ) {
1479 Some(result) => result,
1480 None => self
1481 .default_maybe_inplace_mutate_result(value, def_region_kind)
1482 .map(Any::from),
1483 }
1484 }
1485}
1486
1487impl<State, Driver> MutateContextDriver<State> for Driver
1488where
1489 Driver: StructuralMutator + MutateCallbackState<State>,
1490{
1491 #[inline(always)]
1492 fn state(&self) -> &State {
1493 self.callback_state()
1494 }
1495
1496 #[inline(always)]
1497 fn state_mut(&mut self) -> &mut State {
1498 self.callback_state_mut()
1499 }
1500
1501 #[inline(always)]
1502 fn mutate_raw(
1503 &mut self,
1504 raw: TVMFFIAny,
1505 def_region_kind: DefRegionKind,
1506 permit: Permit,
1507 ) -> Result<Any> {
1508 dispatch_user_raw(self, raw, def_region_kind, permit)
1509 }
1510
1511 #[inline(always)]
1512 fn default_mutate_raw(
1513 &mut self,
1514 raw: TVMFFIAny,
1515 def_region_kind: DefRegionKind,
1516 ) -> Result<Any> {
1517 default_mutate_driver(self, raw, def_region_kind, Permit::Copy)
1518 }
1519
1520 #[inline(always)]
1521 fn var_remap_get_raw(&mut self, raw: TVMFFIAny) -> Result<Option<Any>> {
1522 <Self as StructuralMutator>::var_remap_get(self, &MapValue::from_raw(raw))
1523 }
1524
1525 #[inline(always)]
1526 fn var_remap_set_raw(&mut self, raw: TVMFFIAny, mutated_value: &Any) -> Result<()> {
1527 <Self as StructuralMutator>::var_remap_set(self, &MapValue::from_raw(raw), mutated_value)
1528 }
1529}
1530
1531#[doc(hidden)]
1532#[derive(Clone, Copy, PartialEq, Eq)]
1533pub enum Permit {
1534 Copy,
1535 MaybeInPlace,
1536}
1537
1538struct MemoEntry {
1539 _original: Any,
1542 result: Any,
1543}
1544
1545struct NativeMapper<D> {
1546 dispatch: D,
1547 order: WalkOrder,
1548 remap: StructuralVarRemap,
1549}
1550
1551impl<D: MapDispatch> NativeMapper<D> {
1552 fn map_raw(
1553 &mut self,
1554 raw: TVMFFIAny,
1555 def_region_kind: DefRegionKind,
1556 permit: Permit,
1557 ) -> Result<Any> {
1558 if is_plain_inline(raw.type_index) {
1565 let value = MapValue::from_raw(raw);
1566 return match self.dispatch.dispatch_map(&value, def_region_kind) {
1567 Some(result) => {
1568 let mapped = result?;
1569 if self.order == WalkOrder::PreOrder && !is_plain_inline(mapped.type_index()) {
1571 let descended =
1572 self.map_default_root(&mapped, def_region_kind, Permit::MaybeInPlace)?;
1573 Ok(if is_unchanged(&descended) {
1574 mapped
1575 } else {
1576 descended
1577 })
1578 } else {
1579 Ok(mapped)
1580 }
1581 }
1582 None => Ok(unsafe { Any::from_raw_ffi_any(raw) }),
1587 };
1588 }
1589
1590 self.map_current_raw(raw, def_region_kind, permit)
1591 .map_err(|error| with_value_context(error, raw))
1592 }
1593
1594 fn map_current_raw(
1595 &mut self,
1596 raw: TVMFFIAny,
1597 def_region_kind: DefRegionKind,
1598 permit: Permit,
1599 ) -> Result<Any> {
1600 match self.order {
1601 WalkOrder::PreOrder => {
1602 let value = MapValue::from_raw(raw);
1603 let Some(callback_result) = self.dispatch.dispatch_map(&value, def_region_kind)
1604 else {
1605 return self.default_map_current_raw(raw, def_region_kind, permit);
1606 };
1607 let mapped = callback_result?;
1608 let mapped_raw = *mapped.as_raw_ffi_any();
1609 if is_unchanged(&mapped) || same_shallow(raw, mapped_raw) {
1610 drop(mapped);
1613 self.default_map_current_raw(raw, def_region_kind, permit)
1614 } else {
1615 let descended =
1616 self.map_default_root(&mapped, def_region_kind, Permit::MaybeInPlace)?;
1617 Ok(if is_unchanged(&descended) {
1618 mapped
1619 } else {
1620 descended
1621 })
1622 }
1623 }
1624 WalkOrder::PostOrder => {
1625 let mapped = self.default_map_current_raw(raw, def_region_kind, permit)?;
1626 let mapped_raw = if is_unchanged(&mapped) {
1627 raw
1628 } else {
1629 *mapped.as_raw_ffi_any()
1630 };
1631 let value = MapValue::from_raw(mapped_raw);
1632 match self.dispatch.dispatch_map(&value, def_region_kind) {
1633 Some(result) => result,
1634 None => Ok(mapped),
1635 }
1636 }
1637 }
1638 }
1639
1640 fn map_default_root(
1642 &mut self,
1643 mapped: &Any,
1644 def_region_kind: DefRegionKind,
1645 permit: Permit,
1646 ) -> Result<Any> {
1647 let raw = *mapped.as_raw_ffi_any();
1648 self.default_map_current_raw(raw, def_region_kind, permit)
1649 .map_err(|error| with_value_context(error, raw))
1650 }
1651}
1652
1653trait MutationDriver: Sized {
1656 fn dispatch_raw(
1657 &mut self,
1658 raw: TVMFFIAny,
1659 def_region_kind: DefRegionKind,
1660 permit: Permit,
1661 ) -> Result<Any>;
1662
1663 fn var_remap_get_raw(&mut self, raw: TVMFFIAny) -> Result<Option<Any>>;
1664
1665 fn var_remap_set_raw(&mut self, raw: TVMFFIAny, replacement: &Any) -> Result<()>;
1666
1667 fn call_registered_hook(
1668 &mut self,
1669 raw: TVMFFIAny,
1670 def_region_kind: DefRegionKind,
1671 permit: Permit,
1672 ) -> Result<Option<Any>> {
1673 let mutator = active_mutator()?;
1674 with_current_driver_context(mutator, self, || {
1675 call_registered_structural_mutate(mutator, raw, def_region_kind, permit)
1676 })
1677 }
1678
1679 fn default_map_current_raw(
1680 &mut self,
1681 raw: TVMFFIAny,
1682 def_region_kind: DefRegionKind,
1683 permit: Permit,
1684 ) -> Result<Any> {
1685 default_mutate_driver(self, raw, def_region_kind, permit)
1686 }
1687
1688 fn map_reflected(&mut self, raw: TVMFFIAny, def_region_kind: DefRegionKind) -> Result<Any> {
1689 let type_info = checked_type_info(raw.type_index)?;
1690 let seq_hash_kind = unsafe {
1691 if (*type_info).metadata.is_null() {
1692 TVMFFISEqHashKind::kTVMFFISEqHashKindUnsupported as i32
1693 } else {
1694 (*(*type_info).metadata).structural_eq_hash_kind
1695 }
1696 };
1697 let inherited_region = free_var_child_region(def_region_kind, seq_hash_kind);
1698 let output = shallow_copy(raw)?;
1703 let output_raw = *output.as_raw_ffi_any();
1704 let output_object = unsafe { output_raw.data_union.v_obj.cast::<u8>() };
1705 if output_object.is_null() {
1706 return Err(runtime_error(
1707 "native structural map: shallow copy has a null object pointer",
1708 ));
1709 }
1710
1711 let mut field_changed = false;
1712 let mut failure: Option<Error> = None;
1713 unsafe {
1714 for_each_field_info(type_info, &mut |field| {
1715 if field.flags & FLAG_SEQ_HASH_IGNORE != 0 {
1716 return ControlFlow::Continue(());
1717 }
1718 match self.map_reflected_field(
1719 output_object,
1720 field,
1721 inherited_region,
1722 &mut field_changed,
1723 ) {
1724 Ok(()) => ControlFlow::Continue(()),
1725 Err(error) => {
1726 failure = Some(error);
1727 ControlFlow::Break(())
1728 }
1729 }
1730 });
1731 }
1732 if let Some(error) = failure {
1733 return Err(error);
1734 }
1735 if field_changed {
1736 Ok(output)
1737 } else {
1738 Ok(Unchanged.into())
1739 }
1740 }
1741
1742 unsafe fn map_reflected_field(
1743 &mut self,
1744 output_object: *mut u8,
1745 field: &TVMFFIFieldInfo,
1746 inherited_region: DefRegionKind,
1747 field_changed: &mut bool,
1748 ) -> Result<()> {
1749 let Some(getter) = field.getter else {
1750 return Err(runtime_error(&format!(
1751 "native structural map: reflected field `{}` has no getter",
1752 field.name.as_str()
1753 )));
1754 };
1755 let field_offset = usize::try_from(field.offset).map_err(|_| {
1758 runtime_error(&format!(
1759 "native structural map: reflected field `{}` has an invalid offset",
1760 field.name.as_str()
1761 ))
1762 })?;
1763 let source_address = output_object.add(field_offset).cast::<c_void>();
1767 let mut child = Any::new();
1770 if getter(source_address, Any::as_data_ptr(&mut child)) != 0 {
1771 return Err(with_error_context(
1772 Error::from_raised(),
1773 &format!("field `{}`", field.name.as_str()),
1774 ));
1775 }
1776 let child_raw = *child.as_raw_ffi_any();
1779 let child_region = field_def_region(field, inherited_region);
1780 let mapped = self
1781 .dispatch_raw(child_raw, child_region, Permit::Copy)
1782 .map_err(|error| {
1783 with_error_context(error, &format!("field `{}`", field.name.as_str()))
1784 })?;
1785 if is_unchanged(&mapped) || same_shallow(child_raw, *mapped.as_raw_ffi_any()) {
1786 return Ok(());
1787 }
1788
1789 call_field_setter(field, source_address, mapped.as_raw_ffi_any()).map_err(|error| {
1790 with_error_context(error, &format!("field `{}`", field.name.as_str()))
1791 })?;
1792 *field_changed = true;
1793 Ok(())
1794 }
1795}
1796
1797type StructuralMutatorHandle = *mut RuntimeStructuralMutatorObj;
1798
1799type FStructuralMutate =
1800 unsafe extern "C" fn(StructuralMutatorHandle, AnyView<'static>) -> TVMFFIAny;
1801type FStructuralVarRemapGet =
1802 unsafe extern "C" fn(StructuralMutatorHandle, AnyView<'static>) -> TVMFFIAny;
1803type FStructuralVarRemapSet =
1804 unsafe extern "C" fn(StructuralMutatorHandle, AnyView<'static>, AnyView<'static>) -> TVMFFIAny;
1805
1806#[repr(C)]
1808struct StructuralMutatorVTable {
1809 mutate: FStructuralMutate,
1810 maybe_inplace_mutate: FStructuralMutate,
1811 var_remap_get: FStructuralVarRemapGet,
1812 var_remap_set: FStructuralVarRemapSet,
1813}
1814
1815type RuntimeDispatchMutateCallback =
1816 unsafe fn(*mut c_void, TVMFFIAny, DefRegionKind, Permit) -> Result<Any>;
1817type RuntimeVarRemapGetCallback = unsafe fn(*mut c_void, TVMFFIAny) -> Result<Option<Any>>;
1818type RuntimeVarRemapSetCallback = unsafe fn(*mut c_void, TVMFFIAny, &Any) -> Result<()>;
1819
1820struct RuntimeMutatorCallbacks {
1821 dispatch_mutate: RuntimeDispatchMutateCallback,
1822 var_remap_get: RuntimeVarRemapGetCallback,
1823 var_remap_set: RuntimeVarRemapSetCallback,
1824}
1825
1826#[repr(C)]
1831struct RuntimeStructuralMutatorObj {
1832 base: Object,
1833 vtable: *const StructuralMutatorVTable,
1834 def_region_mode: i32,
1835 context: *mut c_void,
1839 context_identity: *mut c_void,
1840 owner_thread: std::thread::ThreadId,
1841 callbacks: RuntimeMutatorCallbacks,
1842 remap: RefCell<StructuralVarRemap>,
1844 panic: Option<Box<dyn std::any::Any + Send>>,
1845}
1846
1847const _: () = {
1848 assert!(
1849 std::mem::offset_of!(RuntimeStructuralMutatorObj, vtable)
1850 == std::mem::size_of::<TVMFFIObject>()
1851 );
1852 assert!(
1853 std::mem::offset_of!(RuntimeStructuralMutatorObj, def_region_mode)
1854 == std::mem::size_of::<TVMFFIObject>() + std::mem::size_of::<*const c_void>()
1855 );
1856};
1857
1858unsafe impl ObjectCore for RuntimeStructuralMutatorObj {
1863 const TYPE_KEY: &'static str = "ffi.StructuralMutator";
1864 const TYPE_DEPTH: i32 = Object::TYPE_DEPTH + 1;
1865
1866 fn type_index() -> i32 {
1867 static TYPE_INDEX: LazyLock<i32> = LazyLock::new(|| unsafe {
1868 let key = TVMFFIByteArray::from_str(RuntimeStructuralMutatorObj::TYPE_KEY);
1869 let mut type_index = 0;
1870 let return_code = TVMFFITypeKeyToIndex(&key, &mut type_index);
1871 if return_code != 0 {
1872 panic!(
1873 "ffi.StructuralMutator is not registered: {}",
1874 Error::from_raised()
1875 );
1876 }
1877 type_index
1878 });
1879 *TYPE_INDEX
1880 }
1881
1882 unsafe fn object_header_mut(this: &mut Self) -> &mut TVMFFIObject {
1883 Object::object_header_mut(&mut this.base)
1884 }
1885}
1886
1887static RUST_STRUCTURAL_MUTATOR_VTABLE: StructuralMutatorVTable = StructuralMutatorVTable {
1888 mutate: rust_vtable_mutate,
1889 maybe_inplace_mutate: rust_vtable_maybe_inplace_mutate,
1890 var_remap_get: rust_vtable_var_remap_get,
1891 var_remap_set: rust_vtable_var_remap_set,
1892};
1893
1894struct RuntimeContextGuard {
1895 mutator: StructuralMutatorHandle,
1896 context: *mut c_void,
1897}
1898
1899impl Drop for RuntimeContextGuard {
1900 fn drop(&mut self) {
1901 unsafe { (*self.mutator).context = self.context };
1905 }
1906}
1907
1908unsafe fn take_runtime_context(mutator: StructuralMutatorHandle) -> Result<RuntimeContextGuard> {
1917 if !is_active_mutator(mutator) {
1918 return Err(inactive_mutator_error(mutator, "callback"));
1919 }
1920 let context = (*mutator).context;
1921 if context.is_null() {
1922 let message = if (*mutator).context_identity.is_null() {
1923 "structural mutator was retained after its active call"
1924 } else {
1925 "structural mutator may only be called by its active registered hook"
1926 };
1927 return Err(runtime_error(message));
1928 }
1929 (*mutator).context = std::ptr::null_mut();
1932 Ok(RuntimeContextGuard { mutator, context })
1933}
1934
1935unsafe extern "C" fn rust_vtable_mutate(
1936 mutator: StructuralMutatorHandle,
1937 value: AnyView<'static>,
1938) -> TVMFFIAny {
1939 rust_vtable_mutate_impl(mutator, value, Permit::Copy)
1942}
1943
1944unsafe extern "C" fn rust_vtable_maybe_inplace_mutate(
1945 mutator: StructuralMutatorHandle,
1946 value: AnyView<'static>,
1947) -> TVMFFIAny {
1948 rust_vtable_mutate_impl(mutator, value, Permit::MaybeInPlace)
1951}
1952
1953unsafe fn rust_vtable_mutate_impl(
1960 mutator: StructuralMutatorHandle,
1961 value: AnyView<'static>,
1962 permit: Permit,
1963) -> TVMFFIAny {
1964 let context_guard = match take_runtime_context(mutator) {
1965 Ok(guard) => guard,
1966 Err(error) => return result_into_raw(Err(error)),
1967 };
1968 let context = context_guard.context;
1969 let callback = (*mutator).callbacks.dispatch_mutate;
1970 let raw = *value.as_raw_ffi_any();
1971 let outcome = catch_unwind(AssertUnwindSafe(|| {
1972 let kind = def_region_from_raw((*mutator).def_region_mode)?;
1973 with_active_mutator(mutator, || callback(context, raw, kind, permit))
1974 }));
1975 match outcome {
1976 Ok(result) => result_into_raw(result),
1977 Err(payload) => {
1978 (*mutator).panic = Some(payload);
1979 result_into_raw(Err(runtime_error("panic in structural mutator callback")))
1980 }
1981 }
1982}
1983
1984unsafe extern "C" fn rust_vtable_var_remap_get(
1985 mutator: StructuralMutatorHandle,
1986 var: AnyView<'static>,
1987) -> TVMFFIAny {
1988 let context_guard = match take_runtime_context(mutator) {
1989 Ok(guard) => guard,
1990 Err(error) => return result_into_raw(Err(error)),
1991 };
1992 let callback = (*mutator).callbacks.var_remap_get;
1993 let context = context_guard.context;
1994 let raw = *var.as_raw_ffi_any();
1995 match catch_unwind(AssertUnwindSafe(|| callback(context, raw))) {
1996 Ok(Ok(Some(replacement))) => Any::into_raw_ffi_any(replacement),
1997 Ok(Ok(None)) => TVMFFIAny::new(),
1998 Ok(Err(error)) => result_into_raw(Err(error)),
1999 Err(payload) => {
2000 (*mutator).panic = Some(payload);
2001 result_into_raw(Err(runtime_error("panic in structural var-remap lookup")))
2002 }
2003 }
2004}
2005
2006unsafe extern "C" fn rust_vtable_var_remap_set(
2007 mutator: StructuralMutatorHandle,
2008 var: AnyView<'static>,
2009 replacement: AnyView<'static>,
2010) -> TVMFFIAny {
2011 let context_guard = match take_runtime_context(mutator) {
2012 Ok(guard) => guard,
2013 Err(error) => return result_into_raw(Err(error)),
2014 };
2015 let callback = (*mutator).callbacks.var_remap_set;
2016 let context = context_guard.context;
2017 let var_raw = *var.as_raw_ffi_any();
2018 let replacement_raw = *replacement.as_raw_ffi_any();
2019 match catch_unwind(AssertUnwindSafe(|| {
2020 let replacement = owned_from_raw(replacement_raw)?;
2021 callback(context, var_raw, &replacement)
2022 })) {
2023 Ok(Ok(())) => TVMFFIAny::new(),
2024 Ok(Err(error)) => result_into_raw(Err(error)),
2025 Err(payload) => {
2026 (*mutator).panic = Some(payload);
2027 result_into_raw(Err(runtime_error(
2028 "panic in structural var-remap insertion",
2029 )))
2030 }
2031 }
2032}
2033
2034thread_local! {
2035 static ACTIVE_MUTATOR: Cell<StructuralMutatorHandle> = const {
2036 Cell::new(std::ptr::null_mut())
2037 };
2038}
2039
2040fn with_active_mutator<T>(handle: StructuralMutatorHandle, callback: impl FnOnce() -> T) -> T {
2041 ACTIVE_MUTATOR.with(|active| {
2042 let previous = active.replace(handle);
2043 struct Restore<'a> {
2044 active: &'a Cell<StructuralMutatorHandle>,
2045 previous: StructuralMutatorHandle,
2046 }
2047 impl Drop for Restore<'_> {
2048 fn drop(&mut self) {
2049 self.active.set(self.previous);
2050 }
2051 }
2052 let _restore = Restore { active, previous };
2053 callback()
2054 })
2055}
2056
2057fn active_mutator() -> Result<StructuralMutatorHandle> {
2058 ACTIVE_MUTATOR.with(|active| {
2059 let handle = active.get();
2060 if handle.is_null() {
2061 Err(runtime_error(
2062 "structural mutator helper called outside structural_mutate",
2063 ))
2064 } else {
2065 Ok(handle)
2066 }
2067 })
2068}
2069
2070fn invocation_var_remap_get<U: Sized>(mutator: &mut U, var: &MapValue) -> Result<Option<Any>> {
2071 let active = active_mutator()?;
2072 let context = std::ptr::from_mut(mutator).cast::<c_void>();
2073 unsafe {
2074 if (*active).context_identity != context {
2075 return Err(runtime_error(
2076 "default structural var-remap used by a non-active mutator",
2077 ));
2078 }
2079 (*active).remap.borrow().get(var)
2080 }
2081}
2082
2083fn invocation_var_remap_set<U: Sized>(
2084 mutator: &mut U,
2085 var: &MapValue,
2086 mutated_value: &Any,
2087) -> Result<()> {
2088 let active = active_mutator()?;
2089 let context = std::ptr::from_mut(mutator).cast::<c_void>();
2090 unsafe {
2091 if (*active).context_identity != context {
2092 return Err(runtime_error(
2093 "default structural var-remap used by a non-active mutator",
2094 ));
2095 }
2096 (*active).remap.borrow_mut().set(var, mutated_value)
2097 }
2098}
2099
2100#[inline]
2101fn is_active_mutator(handle: StructuralMutatorHandle) -> bool {
2102 !handle.is_null() && ACTIVE_MUTATOR.with(|active| active.get() == handle)
2103}
2104
2105#[cold]
2106fn inactive_mutator_error(mutator: StructuralMutatorHandle, operation: &str) -> Error {
2107 if mutator.is_null() {
2108 return runtime_error("null active structural mutator");
2109 }
2110 unsafe {
2113 if (*mutator).owner_thread != std::thread::current().id() {
2114 return runtime_error(&format!(
2115 "structural mutator {operation} invoked from a different thread"
2116 ));
2117 }
2118 if (*mutator).context_identity.is_null() {
2119 runtime_error("structural mutator was retained after its active call")
2120 } else {
2121 runtime_error(&format!(
2122 "structural mutator {operation} may only be used by its active registered hook"
2123 ))
2124 }
2125 }
2126}
2127
2128fn with_current_driver_context<D, T>(
2132 mutator: StructuralMutatorHandle,
2133 driver: &mut D,
2134 callback: impl FnOnce() -> Result<T>,
2135) -> Result<T> {
2136 let context = std::ptr::from_mut(driver).cast::<c_void>();
2137 if !is_active_mutator(mutator) {
2138 return Err(inactive_mutator_error(mutator, "helper"));
2139 }
2140 unsafe {
2141 if (*mutator).context_identity != context {
2142 return Err(runtime_error(
2143 "structural mutator helper called on a non-active mutator",
2144 ));
2145 }
2146 if !(*mutator).context.is_null() {
2147 return Err(runtime_error(
2148 "structural mutator driver context is already exposed",
2149 ));
2150 }
2151
2152 (*mutator).context = context;
2153 struct HideContext {
2154 mutator: StructuralMutatorHandle,
2155 }
2156 impl Drop for HideContext {
2157 fn drop(&mut self) {
2158 unsafe { (*self.mutator).context = std::ptr::null_mut() };
2161 }
2162 }
2163 let _hide = HideContext { mutator };
2164 callback()
2165 }
2166}
2167
2168fn def_region_from_raw(kind: i32) -> Result<DefRegionKind> {
2169 match kind {
2170 x if x == DefRegionKind::None as i32 => Ok(DefRegionKind::None),
2171 x if x == DefRegionKind::Pattern as i32 => Ok(DefRegionKind::Pattern),
2172 x if x == DefRegionKind::Simple as i32 => Ok(DefRegionKind::Simple),
2173 _ => Err(runtime_error("invalid structural definition-region kind")),
2174 }
2175}
2176
2177impl<D: MapDispatch> MutationDriver for NativeMapper<D> {
2178 fn dispatch_raw(
2179 &mut self,
2180 raw: TVMFFIAny,
2181 def_region_kind: DefRegionKind,
2182 permit: Permit,
2183 ) -> Result<Any> {
2184 self.map_raw(raw, def_region_kind, permit)
2185 }
2186
2187 fn var_remap_get_raw(&mut self, raw: TVMFFIAny) -> Result<Option<Any>> {
2188 self.remap.get(&MapValue::from_raw(raw))
2189 }
2190
2191 fn var_remap_set_raw(&mut self, raw: TVMFFIAny, replacement: &Any) -> Result<()> {
2192 self.remap.set(&MapValue::from_raw(raw), replacement)
2193 }
2194}
2195
2196impl<U: StructuralMutator> MutationDriver for U {
2197 fn dispatch_raw(
2198 &mut self,
2199 raw: TVMFFIAny,
2200 def_region_kind: DefRegionKind,
2201 permit: Permit,
2202 ) -> Result<Any> {
2203 dispatch_user_raw(self, raw, def_region_kind, permit)
2204 }
2205
2206 fn var_remap_get_raw(&mut self, raw: TVMFFIAny) -> Result<Option<Any>> {
2207 self.var_remap_get(&MapValue::from_raw(raw))
2208 }
2209
2210 fn var_remap_set_raw(&mut self, raw: TVMFFIAny, replacement: &Any) -> Result<()> {
2211 self.var_remap_set(&MapValue::from_raw(raw), replacement)
2212 }
2213}
2214
2215unsafe fn runtime_dispatch_mutate<D: MutationDriver>(
2222 context: *mut c_void,
2223 raw: TVMFFIAny,
2224 def_region_kind: DefRegionKind,
2225 permit: Permit,
2226) -> Result<Any> {
2227 (&mut *context.cast::<D>()).dispatch_raw(raw, def_region_kind, permit)
2228}
2229
2230unsafe fn runtime_var_remap_get<D: MutationDriver>(
2236 context: *mut c_void,
2237 raw: TVMFFIAny,
2238) -> Result<Option<Any>> {
2239 (&mut *context.cast::<D>()).var_remap_get_raw(raw)
2240}
2241
2242unsafe fn runtime_var_remap_set<D: MutationDriver>(
2249 context: *mut c_void,
2250 raw: TVMFFIAny,
2251 replacement: &Any,
2252) -> Result<()> {
2253 (&mut *context.cast::<D>()).var_remap_set_raw(raw, replacement)
2254}
2255
2256fn run_structural_mutator<D: MutationDriver>(root: Any, driver: &mut D) -> Result<Any> {
2257 let context = std::ptr::from_mut(driver).cast::<c_void>();
2258 let callbacks = RuntimeMutatorCallbacks {
2259 dispatch_mutate: runtime_dispatch_mutate::<D>,
2260 var_remap_get: runtime_var_remap_get::<D>,
2261 var_remap_set: runtime_var_remap_set::<D>,
2262 };
2263 run_structural_mutator_with_context(root, context, callbacks)
2264}
2265
2266fn run_structural_mutator_with_context(
2267 root: Any,
2268 context: *mut c_void,
2269 callbacks: RuntimeMutatorCallbacks,
2270) -> Result<Any> {
2271 let mut active = ObjectArc::new(RuntimeStructuralMutatorObj {
2272 base: Object::new(),
2273 vtable: &RUST_STRUCTURAL_MUTATOR_VTABLE,
2274 def_region_mode: DefRegionKind::None as i32,
2275 context,
2276 context_identity: context,
2277 owner_thread: std::thread::current().id(),
2278 callbacks,
2279 remap: RefCell::new(StructuralVarRemap::default()),
2280 panic: None,
2281 });
2282 let handle = unsafe { ObjectArc::as_raw_mut(&mut active) };
2283 let result = with_active_mutator(handle, || {
2284 call_mutator(
2285 handle,
2286 *root.as_raw_ffi_any(),
2287 DefRegionKind::None,
2288 Permit::MaybeInPlace,
2289 )
2290 });
2291 unsafe {
2296 (*handle).remap.get_mut().clear();
2297 (*handle).context = std::ptr::null_mut();
2298 (*handle).context_identity = std::ptr::null_mut();
2299 }
2300 let panic = unsafe { (*handle).panic.take() };
2301 if let Some(payload) = panic {
2302 drop(result);
2303 resume_unwind(payload);
2304 }
2305 result.map(|result| if is_unchanged(&result) { root } else { result })
2306}
2307
2308fn call_mutator(
2309 mutator: StructuralMutatorHandle,
2310 raw: TVMFFIAny,
2311 def_region_kind: DefRegionKind,
2312 permit: Permit,
2313) -> Result<Any> {
2314 if mutator.is_null() {
2315 return Err(runtime_error("no active structural mutator"));
2316 }
2317 let use_inplace = permit == Permit::MaybeInPlace && object_is_unique(raw);
2318 let callback = unsafe {
2319 if use_inplace {
2320 (*(*mutator).vtable).maybe_inplace_mutate
2321 } else {
2322 (*(*mutator).vtable).mutate
2323 }
2324 };
2325 with_mutator_def_region(mutator, def_region_kind, || unsafe {
2326 let view = AnyView::from_raw_ffi_any(raw);
2327 result_from_raw(callback(mutator, view))
2328 })
2329}
2330
2331fn call_registered_structural_mutate(
2332 mutator: StructuralMutatorHandle,
2333 raw: TVMFFIAny,
2334 def_region_kind: DefRegionKind,
2335 permit: Permit,
2336) -> Result<Option<Any>> {
2337 let use_inplace = permit == Permit::MaybeInPlace && object_is_unique(raw);
2338 if use_inplace {
2339 if let Some(attr) = structural_maybe_inplace_mutate_column()
2340 .and_then(|column| column.get_raw(raw.type_index))
2341 {
2342 if attr.type_index == TVMFFITypeIndex::kTVMFFIOpaquePtr as i32
2343 || attr.type_index == TVMFFITypeIndex::kTVMFFIFunction as i32
2344 {
2345 return call_structural_mutate_hook(mutator, raw, def_region_kind, attr).map(Some);
2346 }
2347 }
2348 }
2349
2350 let Some(attr) = structural_mutate_column().and_then(|column| column.get_raw(raw.type_index))
2351 else {
2352 return Ok(None);
2353 };
2354 if attr.type_index == TVMFFITypeIndex::kTVMFFINone as i32 {
2355 return Ok(None);
2356 }
2357 call_structural_mutate_hook(mutator, raw, def_region_kind, attr).map(Some)
2358}
2359
2360fn call_structural_mutate_hook(
2361 mutator: StructuralMutatorHandle,
2362 raw: TVMFFIAny,
2363 def_region_kind: DefRegionKind,
2364 attr: TVMFFIAny,
2365) -> Result<Any> {
2366 with_mutator_def_region(mutator, def_region_kind, || unsafe {
2367 match attr.type_index {
2368 x if x == TVMFFITypeIndex::kTVMFFIOpaquePtr as i32 => {
2369 let pointer = attr.data_union.v_ptr;
2370 if pointer.is_null() {
2371 return Err(runtime_error("structural mutation hook is null"));
2372 }
2373 let hook: FStructuralMutate = std::mem::transmute(pointer);
2377 let value = AnyView::from_raw_ffi_any(raw);
2378 result_from_raw(hook(mutator, value))
2379 }
2380 x if x == TVMFFITypeIndex::kTVMFFIFunction as i32 => {
2381 let function = Function::try_from(AnyView::from_raw_ffi_any(attr))?;
2382 let mutator_value = borrowed_mutator_view(mutator);
2383 let value = AnyView::from_raw_ffi_any(raw);
2384 function.call_packed(&[mutator_value, value])
2385 }
2386 _ => Err(Error::new(
2387 TYPE_ERROR,
2388 "__s_mutate__ must be an opaque function pointer or ffi.Function",
2389 "",
2390 )),
2391 }
2392 })
2393}
2394
2395unsafe fn borrowed_mutator_view<'a>(mutator: StructuralMutatorHandle) -> AnyView<'a> {
2402 let object = mutator.cast::<TVMFFIObject>();
2403 let mut raw = TVMFFIAny::new();
2404 raw.type_index = (*object).type_index;
2405 raw.small_str_len = 0;
2406 raw.data_union.v_obj = object;
2407 AnyView::from_raw_ffi_any(raw)
2408}
2409
2410fn result_into_raw(result: Result<Any>) -> TVMFFIAny {
2411 unsafe {
2412 match result {
2413 Ok(value) => Any::into_raw_ffi_any(value),
2414 Err(error) => Any::into_raw_ffi_any(Any::from(error)),
2415 }
2416 }
2417}
2418
2419fn resolve_result(result: Any, original: TVMFFIAny) -> Result<Any> {
2422 if is_unchanged(&result) {
2423 owned_from_raw(original)
2424 } else {
2425 Ok(result)
2426 }
2427}
2428
2429unsafe fn result_from_raw(raw: TVMFFIAny) -> Result<Any> {
2436 let value = Any::from_raw_ffi_any(raw);
2437 if value.type_index() != TVMFFITypeIndex::kTVMFFIError as i32 {
2438 return Ok(value);
2439 }
2440 match Error::try_from(value) {
2441 Ok(error) | Err(error) => Err(error),
2442 }
2443}
2444
2445fn with_mutator_def_region<T>(
2446 mutator: StructuralMutatorHandle,
2447 kind: DefRegionKind,
2448 callback: impl FnOnce() -> T,
2449) -> T {
2450 unsafe {
2451 let previous = (*mutator).def_region_mode;
2452 if previous == DefRegionKind::Pattern as i32 {
2454 return callback();
2455 }
2456 (*mutator).def_region_mode = kind as i32;
2457 struct Restore {
2458 mutator: StructuralMutatorHandle,
2459 previous: i32,
2460 }
2461 impl Drop for Restore {
2462 fn drop(&mut self) {
2463 unsafe { (*self.mutator).def_region_mode = self.previous };
2464 }
2465 }
2466 let _restore = Restore { mutator, previous };
2467 callback()
2468 }
2469}
2470
2471#[inline(always)]
2472fn dispatch_user_raw<U: StructuralMutator>(
2473 mutator: &mut U,
2474 raw: TVMFFIAny,
2475 def_region_kind: DefRegionKind,
2476 permit: Permit,
2477) -> Result<Any> {
2478 let result = if permit == Permit::MaybeInPlace && object_is_unique(raw) {
2479 let mut scoped_raw = raw;
2480 mutator
2481 .dispatch_maybe_inplace_mutate(InplaceValue::from_raw(&mut scoped_raw), def_region_kind)
2482 } else {
2483 mutator.dispatch_mutate(&MapValue::from_raw(raw), def_region_kind)
2484 };
2485 result.map_err(|error| with_value_context(error, raw))
2486}
2487
2488fn user_default_mutate<U: StructuralMutator>(
2489 mutator: &mut U,
2490 raw: TVMFFIAny,
2491 def_region_kind: DefRegionKind,
2492 permit: Permit,
2493) -> Result<Any> {
2494 default_mutate_driver(mutator, raw, def_region_kind, permit)
2495}
2496
2497fn default_mutate_driver<D: MutationDriver>(
2498 driver: &mut D,
2499 raw: TVMFFIAny,
2500 def_region_kind: DefRegionKind,
2501 permit: Permit,
2502) -> Result<Any> {
2503 if let Some(mutated) = driver.call_registered_hook(raw, def_region_kind, permit)? {
2507 return Ok(mutated);
2508 }
2509 if raw.type_index < TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 {
2510 return owned_from_raw(raw);
2511 }
2512
2513 let kind = structural_hash_kind(raw)?;
2514 let is_free_var = kind == Some(TVMFFISEqHashKind::kTVMFFISEqHashKindFreeVar as i32);
2515 let is_dag_node = kind == Some(TVMFFISEqHashKind::kTVMFFISEqHashKindDAGNode as i32);
2516 if is_free_var || is_dag_node {
2517 if let Some(mutated) = driver.var_remap_get_raw(raw)? {
2518 if mutated.type_index() != TVMFFITypeIndex::kTVMFFINone as i32 {
2520 return Ok(mutated);
2521 }
2522 }
2523 }
2524 if is_free_var && def_region_kind == DefRegionKind::None {
2526 return Ok(Unchanged.into());
2527 }
2528
2529 let result = driver.map_reflected(raw, def_region_kind)?;
2530 if is_dag_node
2531 || (is_free_var && (def_region_kind == DefRegionKind::Pattern || !is_unchanged(&result)))
2532 {
2533 driver.var_remap_set_raw(raw, &result)?;
2536 }
2537 Ok(result)
2538}
2539
2540pub fn structural_mutate<R, M>(root: R, mutator: impl IntoMutator<M>) -> Result<Any>
2546where
2547 R: Into<Any>,
2548{
2549 mutator.mutate_root(root.into())
2550}
2551
2552pub fn structural_map<R, M, H>(root: R, mapper: H, order: WalkOrder) -> Result<Any>
2567where
2568 R: Into<Any>,
2569 H: IntoMapper<M>,
2570{
2571 let root = root.into();
2572 let mut native = NativeMapper {
2573 dispatch: mapper.into_mapper(),
2574 order,
2575 remap: StructuralVarRemap::default(),
2576 };
2577 run_structural_mutator(root, &mut native)
2578}
2579
2580fn shallow_copy(raw: TVMFFIAny) -> Result<Any> {
2581 let Some(attr) = shallow_copy_column().and_then(|column| column.get_raw(raw.type_index)) else {
2582 return Err(Error::new(
2583 TYPE_ERROR,
2584 &format!(
2585 "type `{}` cannot use reflected structural mutation because it does not define `{SHALLOW_COPY_ATTR}`",
2586 type_key_of(raw.type_index)
2587 ),
2588 "",
2589 ));
2590 };
2591 if attr.type_index != TVMFFITypeIndex::kTVMFFIFunction as i32 {
2592 return Err(Error::new(
2593 TYPE_ERROR,
2594 &format!("{SHALLOW_COPY_ATTR} must be an ffi.Function"),
2595 "",
2596 ));
2597 }
2598 let function = Function::try_from(unsafe { AnyView::from_raw_ffi_any(attr) })?;
2599 let source = unsafe { AnyView::from_raw_ffi_any(raw) };
2603 let result = function.call_packed(&[source])?;
2604 let result_raw = *result.as_raw_ffi_any();
2605 let result_pointer = unsafe { result_raw.data_union.v_obj };
2606 let source_pointer = unsafe { raw.data_union.v_obj };
2607 if result_raw.type_index != raw.type_index
2608 || result_pointer.is_null()
2609 || result_pointer == source_pointer
2610 {
2611 return Err(Error::new(
2612 TYPE_ERROR,
2613 "shallow copy callback must return a distinct object with the same type as its input",
2614 "",
2615 ));
2616 }
2617 Ok(result)
2618}
2619
2620fn call_field_setter(
2621 field: &TVMFFIFieldInfo,
2622 field_address: *mut c_void,
2623 value: &TVMFFIAny,
2624) -> Result<()> {
2625 if field.setter.is_null() {
2626 return Err(Error::new(
2627 TYPE_ERROR,
2628 &format!(
2629 "cannot structurally mutate field `{}` because it does not define a setter",
2630 field.name.as_str()
2631 ),
2632 "",
2633 ));
2634 }
2635 let return_code = unsafe {
2636 if field.flags & FLAG_SETTER_IS_FUNCTION == 0 {
2637 let setter: TVMFFIFieldSetter = std::mem::transmute(field.setter);
2640 setter(field_address, value)
2641 } else {
2642 let mut args = [TVMFFIAny::new(), *value];
2643 args[0].type_index = TVMFFITypeIndex::kTVMFFIOpaquePtr as i32;
2644 args[0].data_union.v_ptr = field_address;
2645 let mut result = Any::new();
2648 TVMFFIFunctionCall(
2649 field.setter as TVMFFIObjectHandle,
2650 args.as_ptr(),
2651 2,
2652 Any::as_data_ptr(&mut result),
2653 )
2654 }
2655 };
2656 if return_code == 0 {
2657 Ok(())
2658 } else {
2659 Err(Error::from_raised())
2660 }
2661}
2662
2663fn structural_hash_kind(raw: TVMFFIAny) -> Result<Option<i32>> {
2664 if raw.type_index < TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 {
2665 return Ok(None);
2666 }
2667 let type_info = checked_type_info(raw.type_index)?;
2668 unsafe {
2669 if (*type_info).metadata.is_null() {
2670 Ok(None)
2671 } else {
2672 Ok(Some((*(*type_info).metadata).structural_eq_hash_kind))
2673 }
2674 }
2675}
2676
2677fn object_identity_key(raw: TVMFFIAny) -> Result<NonNull<TVMFFIObject>> {
2678 if raw.type_index < TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 {
2679 return Err(Error::new(
2680 TYPE_ERROR,
2681 "variable-remap keys must be object-backed values",
2682 "",
2683 ));
2684 }
2685 let pointer = unsafe { raw.data_union.v_obj };
2686 NonNull::new(pointer)
2687 .ok_or_else(|| runtime_error("native structural map: identity object has a null pointer"))
2688}
2689
2690fn checked_type_info(type_index: i32) -> Result<*const crate::tvm_ffi_sys::TVMFFITypeInfo> {
2691 let info = unsafe { TVMFFIGetTypeInfo(type_index) };
2692 if info.is_null() {
2693 Err(runtime_error(&format!(
2694 "native structural map: unregistered type index {type_index}"
2695 )))
2696 } else {
2697 Ok(info)
2698 }
2699}
2700
2701#[inline]
2702fn object_is_unique(raw: TVMFFIAny) -> bool {
2703 if raw.type_index < TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 {
2704 return false;
2705 }
2706 let pointer = unsafe { raw.data_union.v_obj };
2707 !pointer.is_null() && unsafe { object::unsafe_::strong_count(pointer) == 1 }
2708}
2709
2710fn owned_from_raw(raw: TVMFFIAny) -> Result<Any> {
2711 if let Some(owned) = try_to_owned_without_normalization(raw) {
2712 return Ok(owned);
2713 }
2714 if raw.type_index >= TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 {
2715 return Err(runtime_error(
2716 "native structural map: object-backed value has a null pointer",
2717 ));
2718 }
2719
2720 let mut owned = Any::new();
2724 let return_code = unsafe { TVMFFIAnyViewToOwnedAny(&raw, Any::as_data_ptr(&mut owned)) };
2725 if return_code == 0 {
2726 Ok(owned)
2727 } else {
2728 Err(Error::from_raised())
2729 }
2730}
2731
2732fn with_value_context(error: Error, raw: TVMFFIAny) -> Error {
2733 if raw.type_index < TVMFFITypeIndex::kTVMFFIStaticObjectBegin as i32 {
2734 error
2735 } else {
2736 with_error_context(error, &format!("object `{}`", type_key_of(raw.type_index)))
2737 }
2738}
2739
2740fn with_error_context(error: Error, frame: &str) -> Error {
2741 with_structural_error_context(error, "map", frame)
2742}
2743
2744fn runtime_error(message: &str) -> Error {
2745 Error::new(RUNTIME_ERROR, message, "")
2746}
2747
2748fn cached_column(cache: &'static AtomicUsize, name: &'static str) -> Option<TypeAttrColumn> {
2749 let cached = cache.load(Ordering::Relaxed);
2750 if cached != 0 {
2751 let pointer = cached as *mut TVMFFITypeAttrColumn;
2752 return Some(unsafe { TypeAttrColumn::from_non_null(NonNull::new_unchecked(pointer)) });
2753 }
2754 let column = type_attr_column(name)?;
2755 cache.store(column.as_ptr() as usize, Ordering::Relaxed);
2758 Some(column)
2759}
2760
2761static STRUCTURAL_MUTATE_COLUMN: AtomicUsize = AtomicUsize::new(0);
2762static STRUCTURAL_MAYBE_INPLACE_MUTATE_COLUMN: AtomicUsize = AtomicUsize::new(0);
2763static SHALLOW_COPY_COLUMN: AtomicUsize = AtomicUsize::new(0);
2764
2765fn structural_mutate_column() -> Option<TypeAttrColumn> {
2766 cached_column(&STRUCTURAL_MUTATE_COLUMN, STRUCTURAL_MUTATE_ATTR)
2767}
2768
2769fn structural_maybe_inplace_mutate_column() -> Option<TypeAttrColumn> {
2770 cached_column(
2771 &STRUCTURAL_MAYBE_INPLACE_MUTATE_COLUMN,
2772 STRUCTURAL_MAYBE_INPLACE_MUTATE_ATTR,
2773 )
2774}
2775
2776fn shallow_copy_column() -> Option<TypeAttrColumn> {
2777 cached_column(&SHALLOW_COPY_COLUMN, SHALLOW_COPY_ATTR)
2778}