turbo_tasks/
value.rs

1use std::{fmt::Debug, marker::PhantomData, ops::Deref};
2
3use anyhow::Result;
4
5use crate::{
6    SharedReference,
7    trace::{TraceRawVcs, TraceRawVcsContext},
8};
9
10/// Pass a value by value (`Value<Xxx>`) instead of by reference (`Vc<Xxx>`).
11///
12/// Doesn't require serialization, and won't be stored in the persistent cache
13/// in the future.
14#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
15pub struct TransientValue<T> {
16    inner: T,
17}
18
19impl<T> TransientValue<T> {
20    pub fn new(value: T) -> Self {
21        Self { inner: value }
22    }
23
24    pub fn into_value(self) -> T {
25        self.inner
26    }
27}
28
29impl<T> Deref for TransientValue<T> {
30    type Target = T;
31
32    fn deref(&self) -> &Self::Target {
33        &self.inner
34    }
35}
36
37impl<T: TraceRawVcs> TraceRawVcs for TransientValue<T> {
38    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
39        self.inner.trace_raw_vcs(trace_context)
40    }
41}
42
43/// Pass a reference to an instance to a turbo-tasks function.
44///
45/// Equality and hash is implemented as pointer comparison.
46///
47/// Doesn't require serialization, and won't be stored in the persistent cache
48/// in the future, so we don't include the `ValueTypeId` in the
49/// `SharedReference`.
50pub struct TransientInstance<T> {
51    inner: SharedReference,
52    phantom: PhantomData<T>,
53}
54
55impl<T> Debug for TransientInstance<T> {
56    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57        f.debug_tuple("TransientInstance").finish()
58    }
59}
60
61impl<T> Clone for TransientInstance<T> {
62    fn clone(&self) -> Self {
63        Self {
64            inner: self.inner.clone(),
65            phantom: self.phantom,
66        }
67    }
68}
69
70impl<T> Eq for TransientInstance<T> {}
71
72impl<T> PartialEq for TransientInstance<T> {
73    fn eq(&self, other: &Self) -> bool {
74        self.inner == other.inner
75    }
76}
77
78impl<T> std::hash::Hash for TransientInstance<T> {
79    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
80        self.inner.hash(state);
81    }
82}
83
84impl<T: Send + Sync + 'static> From<TransientInstance<T>> for triomphe::Arc<T> {
85    fn from(instance: TransientInstance<T>) -> Self {
86        // we know this downcast must work because we have type T
87        instance.inner.downcast().unwrap()
88    }
89}
90
91impl<T: Send + Sync + 'static> From<TransientInstance<T>> for SharedReference {
92    fn from(instance: TransientInstance<T>) -> Self {
93        instance.inner
94    }
95}
96
97impl<T: Send + Sync + 'static> From<triomphe::Arc<T>> for TransientInstance<T> {
98    fn from(arc: triomphe::Arc<T>) -> Self {
99        Self {
100            inner: SharedReference::new(arc),
101            phantom: PhantomData,
102        }
103    }
104}
105
106impl<T: Send + Sync + 'static> TryFrom<SharedReference> for TransientInstance<T> {
107    type Error = ();
108
109    fn try_from(inner: SharedReference) -> Result<Self, Self::Error> {
110        if inner.0.downcast_ref::<T>().is_some() {
111            Ok(Self {
112                inner,
113                phantom: PhantomData,
114            })
115        } else {
116            Err(())
117        }
118    }
119}
120
121impl<T: Send + Sync + 'static> TransientInstance<T> {
122    pub fn new(value: T) -> Self {
123        Self {
124            inner: SharedReference::new(triomphe::Arc::new(value)),
125            phantom: PhantomData,
126        }
127    }
128}
129
130impl<T: 'static> Deref for TransientInstance<T> {
131    type Target = T;
132
133    fn deref(&self) -> &Self::Target {
134        self.inner.0.downcast_ref().unwrap()
135    }
136}
137
138impl<T: TraceRawVcs + 'static> TraceRawVcs for TransientInstance<T> {
139    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
140        self.inner.downcast_ref::<T>().trace_raw_vcs(trace_context)
141    }
142}