turbo_tasks/vc/
read.rs

1use std::{any::Any, marker::PhantomData, mem::ManuallyDrop, pin::Pin, task::Poll};
2
3use anyhow::Result;
4use futures::Future;
5
6use super::traits::VcValueType;
7use crate::{ReadRawVcFuture, ReadRef, VcCast, VcValueTrait, VcValueTraitCast, VcValueTypeCast};
8
9type VcReadTarget<T> = <<T as VcValueType>::Read as VcRead<T>>::Target;
10
11/// Trait that controls [`crate::Vc`]'s read representation.
12///
13/// Has two implementations:
14/// * [`VcDefaultRead`]
15/// * [`VcTransparentRead`]
16///
17/// This trait must remain sealed within this crate.
18pub trait VcRead<T>
19where
20    T: VcValueType,
21{
22    /// The read target type. This is the type that will be returned when
23    /// `.await`ing a `Vc` of a value type.
24    ///
25    /// For instance, the target of `.await`ing a `Vc<Completion>` will be a
26    /// `Completion`. When using `#[turbo_tasks::value(transparent)]`, the
27    /// target will be different than the value type.
28    type Target;
29
30    /// The representation type. This is what will be used to
31    /// serialize/deserialize the value, and this determines the
32    /// type that the value will be upcasted to for storage.
33    ///
34    /// For instance, when storing generic collection types such as
35    /// `Vec<Vc<ValueType>>`, we first cast them to a shared `Vec<Vc<()>>`
36    /// type instead, which has an equivalent memory representation to any
37    /// `Vec<Vc<T>>` type. This allows sharing implementations of methods and
38    /// traits between all `Vec<Vc<T>>`.
39    type Repr: VcValueType;
40
41    /// Convert a reference to a value to a reference to the target type.
42    fn value_to_target_ref(value: &T) -> &Self::Target;
43
44    /// Convert a value to the target type.
45    fn value_to_target(value: T) -> Self::Target;
46
47    /// Convert the value type to the repr.
48    fn value_to_repr(value: T) -> Self::Repr;
49
50    /// Convert the target type to the value.
51    fn target_to_value(target: Self::Target) -> T;
52
53    /// Convert a reference to a target type to a reference to a value.
54    fn target_to_value_ref(target: &Self::Target) -> &T;
55
56    /// Convert a mutable reference to a target type to a reference to a value.
57    fn target_to_value_mut_ref(target: &mut Self::Target) -> &mut T;
58
59    /// Convert the target type to the repr.
60    fn target_to_repr(target: Self::Target) -> Self::Repr;
61
62    /// Convert a reference to a repr type to a reference to a value.
63    fn repr_to_value_ref(repr: &Self::Repr) -> &T;
64}
65
66/// Representation for standard `#[turbo_tasks::value]`, where a read return a
67/// reference to the value type[]
68pub struct VcDefaultRead<T> {
69    _phantom: PhantomData<T>,
70}
71
72impl<T> VcRead<T> for VcDefaultRead<T>
73where
74    T: VcValueType,
75{
76    type Target = T;
77    type Repr = T;
78
79    fn value_to_target_ref(value: &T) -> &Self::Target {
80        value
81    }
82
83    fn value_to_target(value: T) -> Self::Target {
84        value
85    }
86
87    fn value_to_repr(value: T) -> Self::Repr {
88        value
89    }
90
91    fn target_to_value(target: Self::Target) -> T {
92        target
93    }
94
95    fn target_to_value_ref(target: &Self::Target) -> &T {
96        target
97    }
98
99    fn target_to_value_mut_ref(target: &mut Self::Target) -> &mut T {
100        target
101    }
102
103    fn target_to_repr(target: Self::Target) -> Self::Repr {
104        target
105    }
106
107    fn repr_to_value_ref(repr: &Self::Repr) -> &T {
108        repr
109    }
110}
111
112/// Representation for `#[turbo_tasks::value(transparent)]` types, where reads
113/// return a reference to the target type.
114pub struct VcTransparentRead<T, Target, Repr> {
115    _phantom: PhantomData<(T, Target, Repr)>,
116}
117
118impl<T, Target, Repr> VcRead<T> for VcTransparentRead<T, Target, Repr>
119where
120    T: VcValueType,
121    Target: Any + Send + Sync,
122    Repr: VcValueType,
123{
124    type Target = Target;
125    type Repr = Repr;
126
127    fn value_to_target_ref(value: &T) -> &Self::Target {
128        // Safety: the `VcValueType` implementor must guarantee that both `T` and
129        // `Target` are #[repr(transparent)]. This is guaranteed by the
130        // `#[turbo_tasks::value(transparent)]` macro.
131        // We can't use `std::mem::transmute` here as it doesn't support generic types.
132        // See https://users.rust-lang.org/t/transmute-doesnt-work-on-generic-types/87272/9
133        unsafe {
134            std::mem::transmute_copy::<ManuallyDrop<&T>, &Self::Target>(&ManuallyDrop::new(value))
135        }
136    }
137
138    fn value_to_target(value: T) -> Self::Target {
139        // Safety: see `Self::value_to_target_ref` above.
140        unsafe {
141            std::mem::transmute_copy::<ManuallyDrop<T>, Self::Target>(&ManuallyDrop::new(value))
142        }
143    }
144
145    fn value_to_repr(value: T) -> Self::Repr {
146        // Safety: see `Self::value_to_target_ref` above.
147        unsafe {
148            std::mem::transmute_copy::<ManuallyDrop<T>, Self::Repr>(&ManuallyDrop::new(value))
149        }
150    }
151
152    fn target_to_value(target: Self::Target) -> T {
153        // Safety: see `Self::value_to_target_ref` above.
154        unsafe {
155            std::mem::transmute_copy::<ManuallyDrop<Self::Target>, T>(&ManuallyDrop::new(target))
156        }
157    }
158
159    fn target_to_value_ref(target: &Self::Target) -> &T {
160        // Safety: see `Self::value_to_target_ref` above.
161        unsafe {
162            std::mem::transmute_copy::<ManuallyDrop<&Self::Target>, &T>(&ManuallyDrop::new(target))
163        }
164    }
165
166    fn target_to_value_mut_ref(target: &mut Self::Target) -> &mut T {
167        // Safety: see `Self::value_to_target_ref` above.
168        unsafe {
169            std::mem::transmute_copy::<ManuallyDrop<&mut Self::Target>, &mut T>(&ManuallyDrop::new(
170                target,
171            ))
172        }
173    }
174
175    fn target_to_repr(target: Self::Target) -> Self::Repr {
176        // Safety: see `Self::value_to_target_ref` above.
177        unsafe {
178            std::mem::transmute_copy::<ManuallyDrop<Self::Target>, Self::Repr>(&ManuallyDrop::new(
179                target,
180            ))
181        }
182    }
183
184    fn repr_to_value_ref(repr: &Self::Repr) -> &T {
185        // Safety: see `Self::value_to_target_ref` above.
186        unsafe {
187            std::mem::transmute_copy::<ManuallyDrop<&Self::Repr>, &T>(&ManuallyDrop::new(repr))
188        }
189    }
190}
191
192pub struct ReadVcFuture<T, Cast = VcValueTypeCast<T>>
193where
194    T: ?Sized,
195    Cast: VcCast,
196{
197    raw: ReadRawVcFuture,
198    _phantom_t: PhantomData<T>,
199    _phantom_cast: PhantomData<Cast>,
200}
201
202impl<T, Cast> ReadVcFuture<T, Cast>
203where
204    T: ?Sized,
205    Cast: VcCast,
206{
207    pub fn strongly_consistent(mut self) -> Self {
208        self.raw = self.raw.strongly_consistent();
209        self
210    }
211
212    pub fn untracked(mut self) -> Self {
213        self.raw = self.raw.untracked();
214        self
215    }
216
217    pub fn final_read_hint(mut self) -> Self {
218        self.raw = self.raw.final_read_hint();
219        self
220    }
221}
222
223impl<T> ReadVcFuture<T, VcValueTypeCast<T>>
224where
225    T: VcValueType,
226    VcReadTarget<T>: Clone,
227{
228    pub fn owned(self) -> ReadOwnedVcFuture<T> {
229        ReadOwnedVcFuture { future: self }
230    }
231}
232
233impl<T> From<ReadRawVcFuture> for ReadVcFuture<T, VcValueTypeCast<T>>
234where
235    T: VcValueType,
236{
237    fn from(raw: ReadRawVcFuture) -> Self {
238        Self {
239            raw,
240            _phantom_t: PhantomData,
241            _phantom_cast: PhantomData,
242        }
243    }
244}
245
246impl<T> From<ReadRawVcFuture> for ReadVcFuture<T, VcValueTraitCast<T>>
247where
248    T: VcValueTrait + ?Sized,
249{
250    fn from(raw: ReadRawVcFuture) -> Self {
251        Self {
252            raw,
253            _phantom_t: PhantomData,
254            _phantom_cast: PhantomData,
255        }
256    }
257}
258
259impl<T, Cast> Future for ReadVcFuture<T, Cast>
260where
261    T: ?Sized,
262    Cast: VcCast,
263{
264    type Output = Result<Cast::Output>;
265
266    fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
267        // Safety: We never move the contents of `self`
268        let raw = unsafe { self.map_unchecked_mut(|this| &mut this.raw) };
269        Poll::Ready(std::task::ready!(raw.poll(cx)).and_then(Cast::cast))
270    }
271}
272
273pub struct ReadOwnedVcFuture<T>
274where
275    T: VcValueType,
276    VcReadTarget<T>: Clone,
277{
278    future: ReadVcFuture<T, VcValueTypeCast<T>>,
279}
280
281impl<T> Future for ReadOwnedVcFuture<T>
282where
283    T: VcValueType,
284    VcReadTarget<T>: Clone,
285{
286    type Output = Result<VcReadTarget<T>>;
287
288    fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
289        // Safety: We never move the contents of `self`
290        let future = unsafe { self.map_unchecked_mut(|this| &mut this.future) };
291        match future.poll(cx) {
292            Poll::Ready(Ok(result)) => Poll::Ready(Ok(ReadRef::into_owned(result))),
293            Poll::Ready(Err(err)) => Poll::Ready(Err(err)),
294            Poll::Pending => Poll::Pending,
295        }
296    }
297}