zng_var/
var_impl.rs

1use std::{
2    any::{Any, TypeId},
3    fmt,
4    marker::PhantomData,
5    ops,
6    sync::{Arc, atomic::AtomicBool},
7};
8
9use crate::{
10    AnyVarHookArgs, AnyVarValue, BoxAnyVarValue, VarInstanceTag, VarUpdateId, VarValue,
11    animation::{AnimationStopFn, ModifyInfo},
12    read_only_var::ReadOnlyImpl,
13};
14use bitflags::bitflags;
15use smallbox::{SmallBox, smallbox};
16
17pub(crate) mod shared_var;
18pub use shared_var::{any_var, any_var_derived, var, var_derived, var_getter, var_state};
19
20pub(crate) mod const_var;
21pub(crate) mod cow_var;
22pub use const_var::IntoVar;
23pub(crate) mod flat_map_var;
24pub(crate) mod read_only_var;
25
26pub(crate) mod contextual_var;
27pub use contextual_var::{ContextInitHandle, WeakContextInitHandle, any_contextual_var, contextual_var};
28
29pub(crate) mod context_var;
30pub use context_var::{__context_var_local, ContextVar, context_var_init};
31
32pub(crate) mod merge_var;
33pub use merge_var::{
34    __merge_var, MergeInput, MergeVarBuilder, VarMergeInputs, merge_var, merge_var_input, merge_var_output, merge_var_with,
35};
36
37pub(crate) mod response_var;
38pub use response_var::{ResponderVar, Response, ResponseVar, response_done_var, response_var};
39
40pub(crate) mod when_var;
41pub use when_var::{__when_var, AnyWhenVarBuilder, WhenVarBuilder};
42
43pub(crate) mod expr_var;
44pub use expr_var::{__expr_var, expr_var_as, expr_var_into, expr_var_map};
45
46pub(crate) enum DynAnyVar {
47    Const(const_var::ConstVar),
48    Merge(merge_var::MergeVar),
49    When(when_var::WhenVar),
50
51    Shared(shared_var::SharedVar),
52    Context(context_var::ContextVarImpl),
53    FlatMap(flat_map_var::FlatMapVar),
54    Cow(cow_var::CowVar),
55    Contextual(contextual_var::ContextualVar),
56
57    ReadOnlyShared(ReadOnlyImpl<shared_var::SharedVar>),
58    ReadOnlyFlatMap(ReadOnlyImpl<flat_map_var::FlatMapVar>),
59    ReadOnlyContext(ReadOnlyImpl<context_var::ContextVarImpl>),
60    ReadOnlyCow(ReadOnlyImpl<cow_var::CowVar>),
61    ReadOnlyContextual(ReadOnlyImpl<contextual_var::ContextualVar>),
62}
63macro_rules! dispatch {
64    ($self:ident, $var:ident => $($tt:tt)+) => {
65        match $self {
66            DynAnyVar::Const($var) => $($tt)+,
67            DynAnyVar::Merge($var) => $($tt)+,
68            DynAnyVar::FlatMap($var) => $($tt)+,
69            DynAnyVar::When($var) => $($tt)+,
70
71            DynAnyVar::Shared($var) => $($tt)+,
72            DynAnyVar::Context($var) => $($tt)+,
73            DynAnyVar::Cow($var) => $($tt)+,
74            DynAnyVar::Contextual($var) => $($tt)+,
75
76            DynAnyVar::ReadOnlyShared($var) => $($tt)+,
77            DynAnyVar::ReadOnlyFlatMap($var) => $($tt)+,
78            DynAnyVar::ReadOnlyContext($var) => $($tt)+,
79            DynAnyVar::ReadOnlyCow($var) => $($tt)+,
80            DynAnyVar::ReadOnlyContextual($var) => $($tt)+,
81        }
82    };
83}
84impl fmt::Debug for DynAnyVar {
85    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86        dispatch!(self, v => fmt::Debug::fmt(v, f))
87    }
88}
89
90pub(crate) enum DynWeakAnyVar {
91    Const(const_var::WeakConstVar),
92    Merge(merge_var::WeakMergeVar),
93    When(when_var::WeakWhenVar),
94
95    Shared(shared_var::WeakSharedVar),
96    Context(context_var::ContextVarImpl),
97    FlatMap(flat_map_var::WeakFlatMapVar),
98    Cow(cow_var::WeakCowVar),
99    Contextual(contextual_var::WeakContextualVar),
100
101    ReadOnlyShared(ReadOnlyImpl<shared_var::WeakSharedVar>),
102    ReadOnlyContext(ReadOnlyImpl<context_var::ContextVarImpl>),
103    ReadOnlyCow(ReadOnlyImpl<cow_var::WeakCowVar>),
104    ReadOnlyContextual(ReadOnlyImpl<contextual_var::WeakContextualVar>),
105    ReadOnlyFlatMap(ReadOnlyImpl<flat_map_var::WeakFlatMapVar>),
106}
107macro_rules! dispatch_weak {
108    ($self:ident, $var:ident => $($tt:tt)+) => {
109        match $self {
110            DynWeakAnyVar::Const($var) => $($tt)+,
111            DynWeakAnyVar::Shared($var) => $($tt)+,
112            DynWeakAnyVar::Context($var) => $($tt)+,
113            DynWeakAnyVar::Cow($var) => $($tt)+,
114            DynWeakAnyVar::Contextual($var) => $($tt)+,
115            DynWeakAnyVar::FlatMap($var) => $($tt)+,
116            DynWeakAnyVar::Merge($var) => $($tt)+,
117            DynWeakAnyVar::When($var) => $($tt)+,
118            DynWeakAnyVar::ReadOnlyShared($var) => $($tt)+,
119            DynWeakAnyVar::ReadOnlyContext($var) => $($tt)+,
120            DynWeakAnyVar::ReadOnlyCow($var) => $($tt)+,
121            DynWeakAnyVar::ReadOnlyContextual($var) => $($tt)+,
122            DynWeakAnyVar::ReadOnlyFlatMap($var) => $($tt)+,
123
124        }
125    };
126}
127impl fmt::Debug for DynWeakAnyVar {
128    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129        dispatch_weak!(self, v => fmt::Debug::fmt(v, f))
130    }
131}
132
133macro_rules! declare {
134    ($(
135        $(#[$meta:meta])*
136        fn $method:ident(&self $(, $arg:ident : $Input:ty)*) $(-> $Output:ty)?;
137    )+) => {
138        pub(crate) trait VarImpl: fmt::Debug + Any + Send + Sync {
139            $(
140                $(#[$meta])*
141                fn $method(&self $(, $arg: $Input)*) $(-> $Output)?;
142            )+
143        }
144
145        impl VarImpl for DynAnyVar {
146            $(
147                $(#[$meta])*
148                fn $method(&self $(, $arg: $Input)*) $(-> $Output)? {
149                    dispatch!(self, v => VarImpl::$method(v$(, $arg)*))
150                }
151            )+
152        }
153    };
154}
155declare! {
156    fn clone_dyn(&self) -> DynAnyVar;
157    fn value_type(&self) -> TypeId;
158    #[cfg(feature = "type_names")]
159    fn value_type_name(&self) -> &'static str;
160    fn strong_count(&self) -> usize;
161    fn var_eq(&self, other: &DynAnyVar) -> bool;
162    fn var_instance_tag(&self) -> VarInstanceTag;
163    fn downgrade(&self) -> DynWeakAnyVar;
164    fn capabilities(&self) -> VarCapability;
165    fn with(&self, visitor: &mut dyn FnMut(&dyn AnyVarValue));
166    fn get(&self) -> BoxAnyVarValue;
167    fn set(&self, new_value: BoxAnyVarValue) -> bool;
168    fn update(&self) -> bool;
169    fn modify(&self, modify: SmallBox<dyn FnMut(&mut AnyVarModify) + Send + 'static, smallbox::space::S4>) -> bool;
170    fn hook(&self, on_new: SmallBox<dyn FnMut(&AnyVarHookArgs) -> bool + Send + 'static, smallbox::space::S4>) -> VarHandle;
171    fn last_update(&self) -> VarUpdateId;
172    fn modify_importance(&self) -> usize;
173    fn is_animating(&self) -> bool;
174    fn hook_animation_stop(&self, handler: AnimationStopFn) -> VarHandle;
175    fn current_context(&self) -> DynAnyVar;
176    fn modify_info(&self) -> ModifyInfo;
177}
178
179macro_rules! declare_weak {
180        ($(
181        fn $method:ident(&self $(, $arg:ident : $Input:ty)*) $(-> $Output:ty)?;
182    )+) => {
183        pub(crate) trait WeakVarImpl: fmt::Debug + Any + Send + Sync {
184            $(
185                fn $method(&self $(, $arg: $Input)*) $(-> $Output)?;
186            )+
187        }
188
189        impl WeakVarImpl for DynWeakAnyVar {
190            $(
191                fn $method(&self $(, $arg: $Input)*) $(-> $Output)? {
192                    dispatch_weak!(self, v => WeakVarImpl::$method(v$(, $arg)*))
193                }
194            )+
195        }
196    };
197}
198declare_weak! {
199    fn clone_dyn(&self) -> DynWeakAnyVar;
200    fn strong_count(&self) -> usize;
201    fn upgrade(&self) -> Option<DynAnyVar>;
202}
203
204/// Error when an attempt to modify a variable without the [`MODIFY`] capability is made.
205///
206/// [`MODIFY`]: VarCapability::MODIFY
207#[derive(Debug, Clone, Copy)]
208#[non_exhaustive]
209pub struct VarIsReadOnlyError {}
210impl fmt::Display for VarIsReadOnlyError {
211    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
212        write!(f, "cannot modify read-only variable")
213    }
214}
215impl std::error::Error for VarIsReadOnlyError {}
216
217bitflags! {
218    /// Kinds of interactions allowed by a [`Var<T>`] in the current update.
219    ///
220    /// You can get the current capabilities of a var by using the [`AnyVar::capabilities`] method.
221    ///
222    /// [`Var<T>`]: crate::Var
223    /// [`AnyVar::capabilities`]: crate::AnyVar::capabilities
224    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
225    pub struct VarCapability: u8 {
226        /// Variable value can change.
227        ///
228        /// If this is set the [`AnyVar::is_new`] can be `true` in some updates, a variable can `NEW`
229        /// even if it cannot `MODIFY`, in this case the variable is a read-only wrapper on a read-write variable.
230        ///
231        /// [`AnyVar::is_new`]: crate::AnyVar::is_new
232        const NEW = 0b0000_0010;
233
234        /// Variable can be modified.
235        ///
236        /// If this is set [`Var::try_modify`] always returns `Ok`, if this is set `NEW` is also set.
237        ///
238        /// Note that modify requests from inside overridden animations can still be ignored, see [`AnyVar::modify_importance`].
239        ///
240        /// [`AnyVar::modify_importance`]: crate::AnyVar::modify_importance
241        /// [`Var::try_modify`]: crate::Var::try_modify
242        const MODIFY = 0b0000_0011;
243
244        /// Var represents different inner variables depending on the context it is used.
245        const CONTEXT = 0b1000_0000;
246
247        /// Variable capabilities can change to sometimes have the `MODIFY` capability.
248        const MODIFY_CHANGES = 0b0100_0000;
249        /// Variable capabilities can change to sometimes have the `CONTEXT` capability.
250        const CONTEXT_CHANGES = 0b0010_0000;
251
252        /// Var is an *arc* reference to the value and variable state, cloning the variable only clones a
253        /// reference to the variable, all references modify and notify the same state.
254        const SHARE = 0b0001_0000;
255    }
256}
257impl VarCapability {
258    /// If cannot `NEW` and is not `MODIFY_CHANGES`.
259    pub fn is_const(self) -> bool {
260        self.is_empty()
261    }
262
263    /// If does not have `MODIFY` capability and is not `MODIFY_CHANGES`.
264    pub fn is_always_read_only(&self) -> bool {
265        !self.contains(Self::MODIFY) && !self.contains(Self::MODIFY_CHANGES)
266    }
267
268    /// If does not have `MODIFY` capability.
269    pub fn is_read_only(self) -> bool {
270        !self.can_modify()
271    }
272
273    /// Has the `MODIFY` capability.
274    pub fn can_modify(self) -> bool {
275        self.contains(Self::MODIFY)
276    }
277
278    /// Has the `CONTEXT` capability.
279    pub fn is_contextual(self) -> bool {
280        self.contains(Self::CONTEXT)
281    }
282
283    /// Has the `CONTEXT` capability and does not have `CONTEXT_CHANGES`.
284    pub fn is_always_contextual(self) -> bool {
285        self.contains(Self::CONTEXT) && !self.contains(Self::CONTEXT_CHANGES)
286    }
287
288    /// Has the `SHARE` capability.
289    pub fn is_share(&self) -> bool {
290        self.contains(Self::SHARE)
291    }
292
293    /// Does not have the `SHARE` capability.
294    ///
295    /// Cloning this variable clones the value.
296    pub fn is_local(&self) -> bool {
297        !self.is_share()
298    }
299}
300impl VarCapability {
301    pub(crate) fn as_always_read_only(self) -> Self {
302        let mut out = self;
303
304        // can be new, but not modify
305        out.remove(Self::MODIFY & !Self::NEW);
306        // never will allow modify
307        out.remove(Self::MODIFY_CHANGES);
308
309        out
310    }
311}
312
313bitflags! {
314    #[derive(Clone, Copy)]
315    pub(crate) struct VarModifyUpdate: u8 {
316        /// Value was deref_mut or update was called
317        const UPDATE = 0b001;
318        /// Method update was called
319        const REQUESTED = 0b011;
320        /// Value was deref_mut
321        const TOUCHED = 0b101;
322    }
323}
324
325/// Mutable reference to a variable value.
326///
327/// The variable will notify an update only on `deref_mut`.
328pub struct AnyVarModify<'a> {
329    pub(crate) value: &'a mut BoxAnyVarValue,
330    pub(crate) update: VarModifyUpdate,
331    pub(crate) tags: Vec<BoxAnyVarValue>,
332    pub(crate) custom_importance: Option<usize>,
333}
334impl<'a> AnyVarModify<'a> {
335    /// Replace the value if not equal.
336    ///
337    /// Note that you can also deref_mut to modify the value.
338    pub fn set(&mut self, mut new_value: BoxAnyVarValue) -> bool {
339        if **self.value != *new_value {
340            if !self.value.try_swap(&mut *new_value) {
341                #[cfg(feature = "type_names")]
342                panic!(
343                    "cannot AnyVarModify::set `{}` on variable of type `{}`",
344                    new_value.type_name(),
345                    self.value.type_name()
346                );
347                #[cfg(not(feature = "type_names"))]
348                panic!("cannot modify set, type mismatch");
349            }
350            self.update |= VarModifyUpdate::TOUCHED;
351            true
352        } else {
353            false
354        }
355    }
356
357    /// Notify an update, even if the value does not actually change.
358    pub fn update(&mut self) {
359        self.update |= VarModifyUpdate::REQUESTED;
360    }
361
362    /// Custom tags that will be shared with the var hooks if the value updates.
363    ///
364    /// The tags where set by previous modify closures or this one during this update cycle, so
365    /// tags can also be used to communicate between modify closures.
366    pub fn tags(&self) -> &[BoxAnyVarValue] {
367        &self.tags
368    }
369
370    /// Add a custom tag object that will be shared with the var hooks if the value updates.
371    pub fn push_tag(&mut self, tag: impl AnyVarValue) {
372        self.tags.push(BoxAnyVarValue::new(tag));
373    }
374
375    /// Sets a custom [`AnyVar::modify_importance`] value.
376    ///
377    /// Note that the modify info is already automatically set, using a custom value here
378    /// can easily break all future modify requests for this variable. The importance is set even if the
379    /// variable does not update (no actual value change or update request).
380    ///
381    /// [`AnyVar::modify_importance`]: crate::AnyVar::modify_importance
382    pub fn set_modify_importance(&mut self, importance: usize) {
383        self.custom_importance = Some(importance);
384    }
385
386    /// Strongly typed reference, if it is of the same type.
387    pub fn downcast<'s, T: VarValue>(&'s mut self) -> Option<VarModify<'s, 'a, T>> {
388        if self.value.is::<T>() {
389            Some(VarModify {
390                inner: self,
391                _t: PhantomData,
392            })
393        } else {
394            None
395        }
396    }
397
398    /// Immutable reference to the value.
399    ///
400    /// Note that you can also simply deref to the value.
401    pub fn value(&self) -> &dyn AnyVarValue {
402        &**self
403    }
404
405    /// Mutable reference to the value.
406    ///
407    /// Getting a mutable reference to the value flags the variable to notify update.
408    ///
409    /// Note that you can also simply deref to the value.
410    pub fn value_mut(&mut self) -> &mut dyn AnyVarValue {
411        &mut **self
412    }
413}
414impl<'a> ops::Deref for AnyVarModify<'a> {
415    type Target = dyn AnyVarValue;
416
417    fn deref(&self) -> &Self::Target {
418        &**self.value
419    }
420}
421impl<'a> ops::DerefMut for AnyVarModify<'a> {
422    fn deref_mut(&mut self) -> &mut Self::Target {
423        self.update |= VarModifyUpdate::TOUCHED;
424        self.value.deref_mut()
425    }
426}
427
428/// Mutable reference to a variable value.
429///
430/// The variable will notify an update only on `deref_mut`.
431pub struct VarModify<'s, 'a, T: VarValue> {
432    inner: &'s mut AnyVarModify<'a>,
433    _t: PhantomData<fn() -> &'a T>,
434}
435impl<'s, 'a, T: VarValue> VarModify<'s, 'a, T> {
436    /// Replace the value if not equal.
437    ///
438    /// Note that you can also deref_mut to modify the value.
439    pub fn set(&mut self, new_value: impl Into<T>) -> bool {
440        let new_value = new_value.into();
441        if **self != new_value {
442            **self = new_value;
443            true
444        } else {
445            false
446        }
447    }
448
449    /// Notify an update, even if the value does not actually change.
450    pub fn update(&mut self) {
451        self.inner.update();
452    }
453
454    /// Custom tags that will be shared with the var hooks if the value updates.
455    ///
456    /// The tags where set by previous modify closures or this one during this update cycle, so
457    /// tags can also be used to communicate between modify closures.
458    pub fn tags(&self) -> &[BoxAnyVarValue] {
459        self.inner.tags()
460    }
461
462    /// Add a custom tag object that will be shared with the var hooks if the value updates.
463    pub fn push_tag(&mut self, tag: impl AnyVarValue) {
464        self.inner.push_tag(tag);
465    }
466
467    /// Sets a custom [`AnyVar::modify_importance`] value.
468    ///
469    /// Note that the modify info is already automatically set, using a custom value here
470    /// can easily break all future modify requests for this variable. The importance is set even if the
471    /// variable does not update (no actual value change or update request).
472    ///
473    /// [`AnyVar::modify_importance`]: crate::AnyVar::modify_importance
474    pub fn set_modify_importance(&mut self, importance: usize) {
475        self.inner.set_modify_importance(importance);
476    }
477
478    /// Type erased reference.
479    pub fn as_any(&mut self) -> &mut AnyVarModify<'a> {
480        self.inner
481    }
482
483    /// Immutable reference to the value.
484    ///
485    /// Note that you can also simply deref to the value.
486    pub fn value(&self) -> &T {
487        self
488    }
489
490    /// Mutable reference to the value.
491    ///
492    /// Getting a mutable reference to the value flags the variable to notify update.
493    ///
494    /// Note that you can also simply deref to the value.
495    pub fn value_mut(&mut self) -> &mut T {
496        self
497    }
498}
499impl<'s, 'a, T: VarValue> ops::Deref for VarModify<'s, 'a, T> {
500    type Target = T;
501
502    fn deref(&self) -> &Self::Target {
503        self.inner.downcast_ref().unwrap()
504    }
505}
506impl<'s, 'a, T: VarValue> ops::DerefMut for VarModify<'s, 'a, T> {
507    fn deref_mut(&mut self) -> &mut Self::Target {
508        self.inner.downcast_mut().unwrap()
509    }
510}
511
512/// Handle to a variable or animation hook.
513///
514/// This can represent a widget subscriber, a var binding, var app handler or animation, dropping the handler stops
515/// the behavior it represents.
516///
517/// Note that the hook closure is not dropped immediately when the handle is dropped, usually it will drop only the next
518/// time it would have been called.
519#[derive(Clone, Default)]
520#[must_use = "var handle stops the behavior it represents on drop"]
521pub struct VarHandle(Option<Arc<AtomicBool>>);
522impl PartialEq for VarHandle {
523    fn eq(&self, other: &Self) -> bool {
524        if let Some(a) = &self.0
525            && let Some(b) = &other.0
526        {
527            Arc::ptr_eq(a, b)
528        } else {
529            false
530        }
531    }
532}
533impl fmt::Debug for VarHandle {
534    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
535        if self.is_dummy() {
536            write!(f, "VarHandle(<dummy>)")
537        } else {
538            f.debug_tuple("VarHandle").finish_non_exhaustive()
539        }
540    }
541}
542impl VarHandle {
543    /// Handle to no variable.
544    pub const fn dummy() -> Self {
545        VarHandle(None)
546    }
547
548    pub(crate) fn new() -> (VarHandlerOwner, Self) {
549        let h = Arc::new(AtomicBool::new(false));
550        (VarHandlerOwner(h.clone()), Self(Some(h)))
551    }
552
553    /// Returns `true` if the handle is a [`dummy`].
554    ///
555    /// [`dummy`]: VarHandle::dummy
556    pub fn is_dummy(&self) -> bool {
557        self.0.is_none()
558    }
559
560    /// Drop the handle without stopping the behavior it represents.
561    ///
562    /// Note that the behavior can still be stopped by dropping the involved variables.
563    pub fn perm(self) {
564        if let Some(c) = &self.0 {
565            c.store(true, std::sync::atomic::Ordering::Relaxed);
566        }
567    }
568
569    /// Create a [`VarHandles`] collection with `self` and `other`.
570    pub fn chain(self, other: Self) -> VarHandles {
571        VarHandles(smallvec::smallvec![self, other])
572    }
573}
574pub(crate) struct VarHandlerOwner(Arc<AtomicBool>);
575impl fmt::Debug for VarHandlerOwner {
576    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
577        write!(f, "{}", Arc::strong_count(&self.0) - 1)?;
578        if self.0.load(std::sync::atomic::Ordering::Relaxed) {
579            write!(f, " perm")
580        } else {
581            Ok(())
582        }
583    }
584}
585impl VarHandlerOwner {
586    pub fn is_alive(&self) -> bool {
587        Arc::strong_count(&self.0) > 1 || self.0.load(std::sync::atomic::Ordering::Relaxed)
588    }
589}
590
591/// Represents a collection of var handles.
592#[must_use = "var handles stops the behavior they represents on drop"]
593#[derive(Clone, Default)]
594pub struct VarHandles(smallvec::SmallVec<[VarHandle; 2]>);
595impl VarHandles {
596    /// Empty collection.
597    pub const fn dummy() -> Self {
598        VarHandles(smallvec::SmallVec::new_const())
599    }
600
601    /// Returns `true` if empty or all handles are dummy.
602    pub fn is_dummy(&self) -> bool {
603        self.0.is_empty() || self.0.iter().all(VarHandle::is_dummy)
604    }
605
606    /// Drop all handles without stopping their behavior.
607    pub fn perm(self) {
608        for handle in self.0 {
609            handle.perm()
610        }
611    }
612
613    /// Add the `other` handle to the collection, if it is not dummy.
614    pub fn push(&mut self, other: VarHandle) -> &mut Self {
615        if !other.is_dummy() {
616            self.0.push(other);
617        }
618        self
619    }
620
621    /// Drop all handles.
622    pub fn clear(&mut self) {
623        self.0.clear()
624    }
625}
626impl FromIterator<VarHandle> for VarHandles {
627    fn from_iter<T: IntoIterator<Item = VarHandle>>(iter: T) -> Self {
628        VarHandles(iter.into_iter().filter(|h| !h.is_dummy()).collect())
629    }
630}
631impl<const N: usize> From<[VarHandle; N]> for VarHandles {
632    fn from(handles: [VarHandle; N]) -> Self {
633        handles.into_iter().collect()
634    }
635}
636impl Extend<VarHandle> for VarHandles {
637    fn extend<T: IntoIterator<Item = VarHandle>>(&mut self, iter: T) {
638        for handle in iter {
639            self.push(handle);
640        }
641    }
642}
643impl IntoIterator for VarHandles {
644    type Item = VarHandle;
645
646    type IntoIter = smallvec::IntoIter<[VarHandle; 2]>;
647
648    fn into_iter(self) -> Self::IntoIter {
649        self.0.into_iter()
650    }
651}
652impl ops::Deref for VarHandles {
653    type Target = smallvec::SmallVec<[VarHandle; 2]>;
654
655    fn deref(&self) -> &Self::Target {
656        &self.0
657    }
658}
659impl ops::DerefMut for VarHandles {
660    fn deref_mut(&mut self) -> &mut Self::Target {
661        &mut self.0
662    }
663}
664impl From<VarHandle> for VarHandles {
665    fn from(value: VarHandle) -> Self {
666        let mut r = VarHandles::dummy();
667        r.push(value);
668        r
669    }
670}
671
672#[cfg(feature = "type_names")]
673fn value_type_name(var: &dyn VarImpl) -> &'static str {
674    var.value_type_name()
675}
676#[cfg(not(feature = "type_names"))]
677#[inline(always)]
678fn value_type_name(_: &dyn VarImpl) -> &'static str {
679    ""
680}