Skip to main content

turbo_tasks/
read_ref.rs

1use std::{
2    cmp::Ordering,
3    fmt::{self, Debug, Display},
4    hash::{Hash, Hasher},
5    marker::PhantomData,
6    mem::transmute_copy,
7    ops::Deref,
8};
9
10use bincode::{
11    Decode, Encode,
12    de::Decoder,
13    enc::Encoder,
14    error::{DecodeError, EncodeError},
15    impl_borrow_decode_with_context,
16};
17use serde::{Deserialize, Serialize};
18use turbo_tasks_hash::DeterministicHash;
19
20#[cfg(debug_assertions)]
21use crate::debug::{ValueDebugFormat, ValueDebugFormatString};
22use crate::{
23    ResolvedVc, SharedReference, Vc, VcRead, VcValueType,
24    trace::{TraceRawVcs, TraceRawVcsContext},
25    vc::VcCellMode,
26};
27
28type VcReadTarget<T> = <<T as VcValueType>::Read as VcRead<T>>::Target;
29
30/// The read value of a value cell. The read value is immutable, while the cell
31/// itself might change over time. It's basically a snapshot of a value at a
32/// certain point in time.
33///
34/// Internally it stores a reference counted reference to a value on the heap.
35pub struct ReadRef<T>(pub(crate) triomphe::Arc<T>);
36
37impl<T> Clone for ReadRef<T> {
38    fn clone(&self) -> Self {
39        Self(self.0.clone())
40    }
41}
42
43impl<T> Deref for ReadRef<T>
44where
45    T: VcValueType,
46{
47    type Target = VcReadTarget<T>;
48
49    fn deref(&self) -> &Self::Target {
50        T::Read::value_to_target_ref(&self.0)
51    }
52}
53
54impl<T> Display for ReadRef<T>
55where
56    T: VcValueType,
57    VcReadTarget<T>: Display,
58{
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        Display::fmt(&**self, f)
61    }
62}
63
64impl<T> Debug for ReadRef<T>
65where
66    T: Debug,
67{
68    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69        Self::as_raw_ref(self).fmt(f)
70    }
71}
72
73impl<T> TraceRawVcs for ReadRef<T>
74where
75    T: TraceRawVcs,
76{
77    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
78        Self::as_raw_ref(self).trace_raw_vcs(trace_context);
79    }
80}
81
82#[cfg(debug_assertions)]
83impl<T> ValueDebugFormat for ReadRef<T>
84where
85    T: VcValueType,
86    VcReadTarget<T>: ValueDebugFormat + 'static,
87{
88    fn value_debug_format(&self, depth: usize) -> ValueDebugFormatString<'_> {
89        let value = &**self;
90        value.value_debug_format(depth)
91    }
92}
93
94impl<T> PartialEq for ReadRef<T>
95where
96    T: Eq,
97{
98    fn eq(&self, other: &Self) -> bool {
99        // Fast path: if both point to the same allocation, they're equal.
100        Self::ptr_eq(self, other) || Self::as_raw_ref(self).eq(Self::as_raw_ref(other))
101    }
102}
103
104impl<T> Eq for ReadRef<T> where T: Eq {}
105
106impl<T> PartialOrd for ReadRef<T>
107where
108    T: PartialOrd + Eq,
109{
110    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
111        Self::as_raw_ref(self).partial_cmp(Self::as_raw_ref(other))
112    }
113}
114
115impl<T> Ord for ReadRef<T>
116where
117    T: Ord + Eq,
118{
119    fn cmp(&self, other: &Self) -> Ordering {
120        Self::as_raw_ref(self).cmp(Self::as_raw_ref(other))
121    }
122}
123
124impl<T> Hash for ReadRef<T>
125where
126    T: Hash,
127{
128    fn hash<H: Hasher>(&self, state: &mut H) {
129        Self::as_raw_ref(self).hash(state)
130    }
131}
132
133impl<T> DeterministicHash for ReadRef<T>
134where
135    T: VcValueType,
136    VcReadTarget<T>: DeterministicHash,
137{
138    fn deterministic_hash<H: turbo_tasks_hash::DeterministicHasher>(&self, state: &mut H) {
139        let p = &**self;
140        p.deterministic_hash(state);
141    }
142}
143
144impl<'a, T, I, J: Iterator<Item = I>> IntoIterator for &'a ReadRef<T>
145where
146    T: VcValueType,
147    &'a VcReadTarget<T>: IntoIterator<Item = I, IntoIter = J>,
148{
149    type Item = I;
150
151    type IntoIter = J;
152
153    fn into_iter(self) -> Self::IntoIter {
154        (&**self).into_iter()
155    }
156}
157
158impl<T, I: 'static, J: Iterator<Item = I>> IntoIterator for ReadRef<T>
159where
160    T: VcValueType,
161    &'static VcReadTarget<T>: IntoIterator<Item = I, IntoIter = J>,
162{
163    type Item = I;
164
165    type IntoIter = ReadRefIter<T, I, J>;
166
167    fn into_iter(self) -> Self::IntoIter {
168        let r = &*self;
169        // # Safety
170        // The reference will we valid as long as the ReadRef is valid.
171        let r = unsafe { transmute_copy::<&'_ VcReadTarget<T>, &'static VcReadTarget<T>>(&r) };
172        ReadRefIter {
173            read_ref: self,
174            iter: r.into_iter(),
175        }
176    }
177}
178
179pub struct ReadRefIter<T, I: 'static, J: Iterator<Item = I>>
180where
181    T: VcValueType,
182{
183    iter: J,
184    #[allow(dead_code)]
185    read_ref: ReadRef<T>,
186}
187
188impl<T, I: 'static, J: Iterator<Item = I>> Iterator for ReadRefIter<T, I, J>
189where
190    T: VcValueType,
191{
192    type Item = I;
193
194    fn next(&mut self) -> Option<Self::Item> {
195        self.iter.next()
196    }
197}
198
199impl<T> Serialize for ReadRef<T>
200where
201    T: Serialize,
202{
203    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
204    where
205        S: serde::Serializer,
206    {
207        Self::as_raw_ref(self).serialize(serializer)
208    }
209}
210
211impl<'de, T> Deserialize<'de> for ReadRef<T>
212where
213    T: Deserialize<'de>,
214{
215    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
216    where
217        D: serde::Deserializer<'de>,
218    {
219        let value = T::deserialize(deserializer)?;
220        Ok(Self(triomphe::Arc::new(value)))
221    }
222}
223
224impl<T> Encode for ReadRef<T>
225where
226    T: Encode,
227{
228    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
229        Self::as_raw_ref(self).encode(encoder)
230    }
231}
232
233impl<Context, T> Decode<Context> for ReadRef<T>
234where
235    T: Decode<Context>,
236{
237    fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
238        let value = T::decode(decoder)?;
239        Ok(Self(triomphe::Arc::new(value)))
240    }
241}
242
243impl_borrow_decode_with_context!(ReadRef<T>, Context, Context, T: Decode<Context>);
244
245impl<T> ReadRef<T> {
246    pub fn new_owned(value: T) -> Self {
247        Self(triomphe::Arc::new(value))
248    }
249
250    pub fn new_arc(arc: triomphe::Arc<T>) -> Self {
251        Self(arc)
252    }
253
254    /// Returns the reference to `&T`, rather than `<<T as VcValueType>::Read as VcRead<T>>::Target`
255    /// (the behavior of [`Deref`]).
256    pub fn as_raw_ref(this: &ReadRef<T>) -> &T {
257        &this.0
258    }
259
260    /// Returns the inner `Arc<T>`.
261    pub fn into_raw_arc(self) -> triomphe::Arc<T> {
262        self.0
263    }
264
265    pub fn ptr_eq(&self, other: &ReadRef<T>) -> bool {
266        triomphe::Arc::ptr_eq(&self.0, &other.0)
267    }
268
269    pub fn ptr(&self) -> *const T {
270        &*self.0 as *const T
271    }
272}
273
274impl<T> ReadRef<T>
275where
276    T: VcValueType,
277{
278    /// Returns a new [`Vc`] that points to the same value as the given reference.
279    pub fn cell(read_ref: ReadRef<T>) -> Vc<T> {
280        let type_id = T::get_value_type_id();
281        Vc {
282            node: <T::CellMode as VcCellMode<T>>::raw_cell(
283                SharedReference::new(read_ref.0).into_typed(type_id),
284            ),
285            _t: PhantomData,
286        }
287    }
288
289    /// Returns a new [`ResolvedVc`] that points to the same value as the given reference.
290    pub fn resolved_cell(read_ref: ReadRef<T>) -> ResolvedVc<T> {
291        ResolvedVc {
292            node: ReadRef::cell(read_ref),
293        }
294    }
295}
296
297impl<T> ReadRef<T>
298where
299    T: VcValueType,
300{
301    /// Returns the inner value, if this [`ReadRef`] has exactly one strong reference.
302    ///
303    /// Otherwise, an [`Err`] is returned with the same [`ReadRef`] that was passed in.
304    pub fn try_unwrap(this: Self) -> Result<VcReadTarget<T>, Self> {
305        match triomphe::Arc::try_unwrap(this.0) {
306            Ok(value) => Ok(T::Read::value_to_target(value)),
307            Err(arc) => Err(Self(arc)),
308        }
309    }
310}
311
312impl<T> ReadRef<T>
313where
314    T: VcValueType,
315    VcReadTarget<T>: Clone,
316{
317    /// This is return a owned version of the value. It potentially clones the value.
318    /// The clone might be expensive. Prefer Deref to get a reference to the value.
319    pub fn into_owned(this: Self) -> VcReadTarget<T> {
320        Self::try_unwrap(this).unwrap_or_else(|this| (*this).clone())
321    }
322}