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