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, 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
68pub 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#[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#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
114pub enum InplaceMode {
115 #[default]
117 Disallow,
118 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
139pub 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 pub fn borrowed(value: &'a StructuralView) -> Self {
192 Self::new(value, InplaceMode::Disallow)
193 }
194}
195
196impl<'a, T> MutateValue<'a, T> {
197 pub fn inplace_mode(&self) -> InplaceMode {
199 self.mode
200 }
201
202 pub fn as_value(&self) -> &StructuralView {
204 &self.value
205 }
206
207 pub fn try_cast<U: crate::type_traits::ContainerElement>(
209 self,
210 ) -> std::result::Result<MutateValue<'a, U>, Self> {
211 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 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 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
254pub 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
267pub struct Mutator {
274 def_region_kind: DefRegionKind,
275 inplace_mode: InplaceMode,
276 _not_send_sync: PhantomData<Rc<()>>,
277}
278
279impl Mutator {
280 pub fn inplace_mode(&self) -> InplaceMode {
285 self.inplace_mode
286 }
287
288 #[inline(always)]
290 pub fn def_region_kind(&self) -> DefRegionKind {
291 self.def_region_kind
292 }
293
294 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 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 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 #[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 #[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
483trait 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 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 #[inline(always)]
509 pub fn state(&self) -> &State {
510 self.driver.state()
511 }
512
513 #[inline(always)]
515 pub fn state_mut(&mut self) -> &mut State {
516 self.driver.state_mut()
517 }
518
519 pub fn inplace_mode(&self) -> InplaceMode {
524 self.inplace_mode
525 }
526
527 #[inline(always)]
529 pub fn def_region_kind(&self) -> DefRegionKind {
530 self.def_region_kind
531 }
532
533 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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 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 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 #[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 #[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#[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
735pub 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
745pub trait MutateDispatch: Sized {
755 fn dispatch_mutate(
756 &mut self,
757 value: &StructuralView,
758 mutator: &mut Mutator,
759 ) -> Option<Result<Any>>;
760
761 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
977pub 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 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 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 pub fn state(&self) -> &State {
1016 &self.state
1017 }
1018
1019 pub fn state_mut(&mut self) -> &mut State {
1021 &mut self.state
1022 }
1023
1024 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
1082pub 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#[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#[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
1141pub 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#[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
1468pub 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 #[inline]
1487 pub fn as_value(&self) -> &StructuralView {
1488 &self.value
1489 }
1490
1491 #[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#[derive(Default)]
1514pub struct StructuralVarRemap {
1515 entries: HashMap<NonNull<TVMFFIObject>, MemoEntry>,
1516}
1517
1518impl StructuralVarRemap {
1519 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 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 pub fn clear(&mut self) {
1540 self.entries.clear();
1541 }
1542}
1543
1544pub trait StructuralMutator: Sized {
1550 fn dispatch_mutate(
1554 &mut self,
1555 value: &StructuralView,
1556 def_region_kind: DefRegionKind,
1557 ) -> Result<Any>;
1558
1559 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 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 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 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 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 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 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 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 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 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 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 fn var_remap_get(&mut self, var: &StructuralView) -> Result<Option<Any>> {
1721 invocation_var_remap_get(self, var)
1722 }
1723
1724 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#[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 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 _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 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 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 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 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 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 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 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
2148trait 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 #[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 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 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 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 let source_address = output_object.add(field_offset).cast::<c_void>();
2285 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 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#[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#[repr(C)]
2346struct RuntimeStructuralMutatorObj {
2347 base: Object,
2348 vtable: *const StructuralMutatorVTable,
2349 def_region_mode: i32,
2350 context: *mut c_void,
2354 context_identity: *mut c_void,
2355 owner_thread: std::thread::ThreadId,
2356 callbacks: RuntimeMutatorCallbacks,
2357 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
2373unsafe 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 unsafe { (*self.mutator).context = self.context };
2424 }
2425}
2426
2427unsafe 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 (*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 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 rust_vtable_mutate_impl::<D, true>(mutator, value)
2470}
2471
2472#[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 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 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
2662fn with_current_driver_context<T>(
2666 mutator: StructuralMutatorHandle,
2667 context: *mut c_void,
2668 callback: impl FnOnce() -> Result<T>,
2669) -> Result<T> {
2670 unsafe {
2673 (*mutator).context = context;
2674 struct HideContext {
2675 mutator: StructuralMutatorHandle,
2676 }
2677 impl Drop for HideContext {
2678 fn drop(&mut self) {
2679 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#[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
2828unsafe 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
2840unsafe 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 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 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
2987unsafe 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#[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#[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 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 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 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 if mutated.type_index() != TVMFFITypeIndex::kTVMFFINone as i32 {
3164 return Ok(mutated);
3165 }
3166 }
3167 }
3168 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 driver.var_remap_set_raw(raw, &result)?;
3180 }
3181 Ok(result)
3182}
3183
3184pub 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
3196pub 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 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 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 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 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 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}