Skip to main content

turbo_tasks/vc/
mod.rs

1pub(crate) mod cast;
2mod cell_mode;
3pub(crate) mod default;
4mod local;
5pub(crate) mod operation;
6mod read;
7pub(crate) mod resolved;
8mod traits;
9
10use std::{
11    any::Any,
12    fmt::Debug,
13    future::{Future, IntoFuture},
14    hash::{Hash, Hasher},
15    marker::PhantomData,
16    ops::Deref,
17    pin::Pin,
18    task::{Context, Poll},
19};
20
21use anyhow::Result;
22use bincode::{Decode, Encode};
23use serde::{Deserialize, Serialize};
24use shrink_to_fit::ShrinkToFit;
25
26pub use self::{
27    cast::{VcCast, VcValueTraitCast, VcValueTypeCast},
28    cell_mode::{
29        VcCellCompareMode, VcCellHashedCompareMode, VcCellKeyedCompareMode, VcCellMode,
30        VcCellNewMode,
31    },
32    default::ValueDefault,
33    local::NonLocalValue,
34    operation::{OperationValue, OperationVc, ResolveOperationVcFuture},
35    read::{ReadOwnedVcFuture, ReadVcFuture, VcDefaultRead, VcRead, VcTransparentRead},
36    resolved::ResolvedVc,
37    traits::{Dynamic, Upcast, UpcastStrict, VcValueTrait, VcValueType},
38};
39#[cfg(debug_assertions)]
40use crate::debug::{ValueDebug, ValueDebugFormat, ValueDebugFormatString};
41use crate::{
42    CellId, RawVc, ResolveRawVcFuture,
43    keyed::{KeyedAccess, KeyedEq},
44    registry,
45    trace::{TraceRawVcs, TraceRawVcsContext},
46    vc::read::{ReadContainsKeyedVcFuture, ReadKeyedVcFuture},
47};
48
49/// A future returned by [`Vc::resolve`] that resolves a [`Vc<T>`] to a cell.
50///
51/// To opt into strong consistency, use [`OperationVc::resolve`] which returns a
52/// [`ResolveOperationVcFuture`] with a
53/// [`.strongly_consistent()`][ResolveOperationVcFuture::strongly_consistent] method.
54#[must_use]
55pub struct ResolveVcFuture<T>
56where
57    T: ?Sized,
58{
59    pub(crate) inner: ResolveRawVcFuture,
60    pub(crate) _t: PhantomData<T>,
61}
62
63impl<T: ?Sized> Future for ResolveVcFuture<T> {
64    type Output = Result<Vc<T>>;
65
66    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
67        // SAFETY: we are not moving self
68        let this = unsafe { self.get_unchecked_mut() };
69        // ResolveRawVcFuture: Unpin, so Pin::new is safe
70        Pin::new(&mut this.inner).poll(cx).map(|r| {
71            r.map(|node| Vc {
72                node,
73                _t: PhantomData,
74            })
75        })
76    }
77}
78
79impl<T: ?Sized> Unpin for ResolveVcFuture<T> {}
80
81/// A future returned by [`Vc::to_resolved`] that resolves a [`Vc<T>`] to a [`ResolvedVc<T>`].
82///
83/// Use [`.strongly_consistent()`][Self::strongly_consistent] to opt into strong consistency.
84#[must_use]
85pub struct ToResolvedVcFuture<T>
86where
87    T: ?Sized,
88{
89    inner: ResolveRawVcFuture,
90    _t: PhantomData<T>,
91}
92
93impl<T: ?Sized> ToResolvedVcFuture<T> {
94    /// Make the resolution strongly consistent.
95    pub fn strongly_consistent(mut self) -> Self {
96        self.inner = self.inner.strongly_consistent();
97        self
98    }
99}
100
101impl<T: ?Sized> Future for ToResolvedVcFuture<T> {
102    type Output = Result<ResolvedVc<T>>;
103
104    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
105        // SAFETY: we are not moving self
106        let this = unsafe { self.get_unchecked_mut() };
107        // ResolveRawVcFuture: Unpin, so Pin::new is safe
108        Pin::new(&mut this.inner).poll(cx).map(|r| {
109            r.map(|node| ResolvedVc {
110                node: Vc {
111                    node,
112                    _t: PhantomData,
113                },
114            })
115        })
116    }
117}
118
119impl<T: ?Sized> Unpin for ToResolvedVcFuture<T> {}
120
121type VcReadTarget<T> = <<T as VcValueType>::Read as VcRead<T>>::Target;
122
123#[doc = include_str!("README.md")]
124#[must_use]
125#[derive(Serialize, Deserialize, Encode, Decode)]
126#[serde(transparent, bound = "")]
127#[bincode(bounds = "T: ?Sized")]
128#[repr(transparent)]
129pub struct Vc<T>
130where
131    T: ?Sized,
132{
133    pub(crate) node: RawVc,
134    #[doc(hidden)]
135    pub(crate) _t: PhantomData<T>,
136}
137
138/// This only exists to satisfy the Rust type system. However, this struct can
139/// never actually be instantiated, as dereferencing a `Vc<T>` will result in a
140/// linker error. See the implementation of `Deref` for `Vc<T>`.
141pub struct VcDeref<T>
142where
143    T: ?Sized,
144{
145    _t: PhantomData<T>,
146}
147
148macro_rules! do_not_use_or_you_will_be_fired {
149    ($($name:ident)*) => {
150        impl<T> VcDeref<T>
151        where
152            T: ?Sized,
153        {
154            $(
155                #[doc(hidden)]
156                #[allow(unused)]
157                #[allow(clippy::wrong_self_convention)]
158                #[deprecated = "This is not the method you are looking for."]
159                pub fn $name(self) {}
160            )*
161        }
162    };
163}
164
165// Hide raw pointer methods on `Vc<T>`. This is an artifact of having
166// implement `Deref<Target = *const T>` on `Vc<T>` for `arbitrary_self_types` to
167// do its thing. This can be removed once the `Receiver` trait no longer depends
168// on `Deref`.
169do_not_use_or_you_will_be_fired!(
170    add
171    addr
172    align_offset
173    as_mut
174    as_mut_ptr
175    as_ptr
176    as_ref
177    as_uninit_mut
178    as_uninit_ref
179    as_uninit_slice
180    as_uninit_slice_mut
181    byte_add
182    byte_offset
183    byte_offset_from
184    byte_sub
185    cast
186    cast_const
187    cast_mut
188    copy_from
189    copy_from_nonoverlapping
190    copy_to
191    copy_to_nonoverlapping
192    drop_in_place
193    expose_addr
194    from_bits
195    get_unchecked
196    get_unchecked_mut
197    guaranteed_eq
198    guaranteed_ne
199    is_aligned
200    is_aligned_to
201    is_empty
202    is_null
203    len
204    map_addr
205    mask
206    offset
207    offset_from
208    read
209    read_unaligned
210    read_volatile
211    replace
212    split_at_mut
213    split_at_mut_unchecked
214    sub
215    sub_ptr
216    swap
217    to_bits
218    to_raw_parts
219    with_addr
220    with_metadata_of
221    wrapping_add
222    wrapping_byte_add
223    wrapping_byte_offset
224    wrapping_byte_sub
225    wrapping_offset
226    wrapping_sub
227    write
228    write_bytes
229    write_unaligned
230    write_volatile
231);
232
233// Call this macro for all the applicable methods above:
234
235#[doc(hidden)]
236impl<T> Deref for VcDeref<T>
237where
238    T: ?Sized,
239{
240    // `*const T` or `*mut T` would be enough here, but from an abundance of
241    // caution, we use `*const *mut *const T` to make sure there will never be an
242    // applicable method.
243    type Target = *const *mut *const T;
244
245    fn deref(&self) -> &Self::Target {
246        unsafe extern "C" {
247            #[link_name = "\n\nERROR: you tried to dereference a `Vc<T>`\n"]
248            fn trigger() -> !;
249        }
250
251        unsafe { trigger() };
252    }
253}
254
255// This is the magic that makes `Vc<T>` accept `self: Vc<Self>` methods through
256// `arbitrary_self_types`, while not allowing any other receiver type:
257// * `Vc<T>` dereferences to `*const *mut *const T`, which means that it is valid under the
258//   `arbitrary_self_types` rules.
259// * `*const *mut *const T` is not a valid receiver for any attribute access on `T`, which means
260//   that the only applicable items will be the methods declared on `self: Vc<Self>`.
261//
262// If we had used `type Target = T` instead, `vc_t.some_attr_defined_on_t` would
263// have been accepted by the compiler.
264#[doc(hidden)]
265impl<T> Deref for Vc<T>
266where
267    T: ?Sized,
268{
269    type Target = VcDeref<T>;
270
271    fn deref(&self) -> &Self::Target {
272        unsafe extern "C" {
273            #[link_name = "\n\nERROR: you tried to dereference a `Vc<T>`\n"]
274            fn trigger() -> !;
275        }
276
277        unsafe { trigger() };
278    }
279}
280
281impl<T> Copy for Vc<T> where T: ?Sized {}
282
283impl<T> Clone for Vc<T>
284where
285    T: ?Sized,
286{
287    fn clone(&self) -> Self {
288        *self
289    }
290}
291
292impl<T> Hash for Vc<T>
293where
294    T: ?Sized,
295{
296    fn hash<H: Hasher>(&self, state: &mut H) {
297        self.node.hash(state);
298    }
299}
300
301impl<T> PartialEq<Vc<T>> for Vc<T>
302where
303    T: ?Sized,
304{
305    fn eq(&self, other: &Self) -> bool {
306        self.node == other.node
307    }
308}
309
310impl<T> Eq for Vc<T> where T: ?Sized {}
311
312/// Generates an opaque debug representation of the [`Vc`] itself, but not the data inside of it.
313///
314/// This is implemented to allow types containing [`Vc`] to implement the synchronous [`Debug`]
315/// trait, but in most cases users should use the [`ValueDebug`] implementation to get a string
316/// representation of the contents of the cell.
317impl<T> Debug for Vc<T>
318where
319    T: ?Sized,
320{
321    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
322        f.debug_tuple("Vc").field(&self.node).finish()
323    }
324}
325
326impl<T> Vc<T>
327where
328    T: VcValueType,
329{
330    // called by the `.cell()` method generated by the `#[turbo_tasks::value]` macro
331    #[doc(hidden)]
332    pub fn cell_private(mut inner: <T::Read as VcRead<T>>::Target) -> Self {
333        // cell contents are immutable, so go ahead and shrink the cell's contents
334        ShrinkToFit::shrink_to_fit(<T::Read as VcRead<T>>::target_to_value_mut_ref(&mut inner));
335        <T::CellMode as VcCellMode<T>>::cell(inner)
336    }
337}
338
339impl<T, Inner> Vc<T>
340where
341    T: VcValueType<Read = VcTransparentRead<T, Inner>>,
342    Inner: Any + Send + Sync,
343{
344    pub fn cell(inner: Inner) -> Self {
345        Self::cell_private(inner)
346    }
347}
348
349impl<T> Vc<T>
350where
351    T: ?Sized,
352{
353    /// Returns a debug identifier for this `Vc`.
354    pub async fn debug_identifier(vc: Self) -> Result<String> {
355        let resolved = vc.to_resolved().await?;
356        let raw_vc: RawVc = resolved.node.node;
357        if let RawVc::TaskCell(task_id, CellId { type_id, index }) = raw_vc {
358            let value_ty = registry::get_value_type(type_id);
359            Ok(format!("{}#{}: {}", value_ty.ty.name, index, task_id))
360        } else {
361            unreachable!()
362        }
363    }
364
365    /// Returns the `RawVc` corresponding to this `Vc`.
366    pub fn into_raw(vc: Self) -> RawVc {
367        vc.node
368    }
369
370    /// Upcasts the given `Vc<T>` to a `Vc<Box<dyn K>>`.
371    ///
372    /// This is also available as an `Into`/`From` conversion.
373    #[inline(always)]
374    pub fn upcast<K>(vc: Self) -> Vc<K>
375    where
376        T: UpcastStrict<K>,
377        K: VcValueTrait + ?Sized,
378    {
379        Self::upcast_non_strict(vc)
380    }
381
382    /// Upcasts the given `Vc<T>` to a `Vc<Box<dyn K>>`
383    ///
384    /// This has a loose type constraint which would allow upcasting to the same type, prefer using
385    /// [`Vc::upcast`] when possible.  This is useful for extension traits and other more generic
386    /// usecases.
387    ///
388    /// # Example
389    /// ```rust
390    /// // In generic code where T might be the same as K
391    /// fn process_foo(vc: ResolvedVc<impl Upcast<Box<dyn MyTrait>>>) -> Vc<Foo> {
392    ///    let my_trait: ResolvedVc<Box<dyn MyTrait>> = Vc::upcast_non_strict(vc);
393    ///    my_trait.do_something()
394    /// }
395    /// ```
396    /// Using generics you could allow users to pass any compatible type, but if you specified
397    /// `UpcastStrict<...>` instead of `Upcast<...>` you would disallow calling this function if you
398    /// already had a `ResolvedVc<Box<dyn MyTrait>>`. So this function has a looser type constraint
399    /// to make these functions easier to write and use.
400    #[inline(always)]
401    pub fn upcast_non_strict<K>(vc: Self) -> Vc<K>
402    where
403        T: Upcast<K>,
404        K: VcValueTrait + ?Sized,
405    {
406        Vc {
407            node: vc.node,
408            _t: PhantomData,
409        }
410    }
411    /// Runs the operation, but ignores the returned Vc. Use that when only interested in running
412    /// the task for side effects.
413    pub async fn as_side_effect(self) -> Result<()> {
414        self.node.resolve().await?;
415        Ok(())
416    }
417
418    /// Do not use this: Use [`Vc::to_resolved`] instead. If you must have a resolved [`Vc`] type
419    /// and not a [`ResolvedVc`] type, simply deref the result of [`Vc::to_resolved`].
420    pub fn resolve(self) -> ResolveVcFuture<T> {
421        ResolveVcFuture {
422            inner: self.node.resolve(),
423            _t: PhantomData,
424        }
425    }
426
427    /// Resolve the reference until it points to a cell directly, and wrap the
428    /// result in a [`ResolvedVc`], which statically guarantees that the
429    /// [`Vc`] was resolved.
430    pub fn to_resolved(self) -> ToResolvedVcFuture<T> {
431        ToResolvedVcFuture {
432            inner: self.node.resolve(),
433            _t: PhantomData,
434        }
435    }
436
437    /// Returns `true` if the reference is resolved, meaning the underlying [`RawVc`] uses the
438    /// [`RawVc::TaskCell`] representation.
439    ///
440    /// If you need resolved [`Vc`] value, it's typically better to use the [`ResolvedVc`] type to
441    /// enforce your requirements statically instead of dynamically at runtime.
442    ///
443    /// See also [`ResolvedVc::to_resolved`] and [`RawVc::is_resolved`].
444    pub fn is_resolved(self) -> bool {
445        self.node.is_resolved()
446    }
447
448    /// Returns `true` if the `Vc` was by a local function call (e.g. one who's arguments were not
449    /// fully resolved) and has not yet been resolved.
450    ///
451    /// Aside from differences in caching, a function's behavior should not be changed by using
452    /// local or non-local cells, so this function is mostly useful inside tests and internally in
453    /// turbo-tasks.
454    pub fn is_local(self) -> bool {
455        self.node.is_local()
456    }
457}
458
459impl<T> From<RawVc> for Vc<T>
460where
461    T: ?Sized,
462{
463    fn from(node: RawVc) -> Self {
464        Self {
465            node,
466            _t: PhantomData,
467        }
468    }
469}
470
471impl<T> TraceRawVcs for Vc<T>
472where
473    T: ?Sized,
474{
475    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
476        TraceRawVcs::trace_raw_vcs(&self.node, trace_context);
477    }
478}
479
480#[cfg(debug_assertions)]
481impl<T> ValueDebugFormat for Vc<T>
482where
483    T: UpcastStrict<Box<dyn ValueDebug>> + Send + Sync + ?Sized,
484{
485    fn value_debug_format(&self, depth: usize) -> ValueDebugFormatString<'_> {
486        ValueDebugFormatString::Async(Box::pin(async move {
487            let vc_value_debug = Vc::upcast::<Box<dyn ValueDebug>>(*self);
488            let trait_ref = vc_value_debug.into_trait_ref().await?;
489            trait_ref.dbg_depth(depth).await
490        }))
491    }
492}
493
494macro_rules! into_future {
495    ($ty:ty) => {
496        impl<T> IntoFuture for $ty
497        where
498            T: VcValueType,
499        {
500            type Output = <ReadVcFuture<T> as Future>::Output;
501            type IntoFuture = ReadVcFuture<T>;
502            fn into_future(self) -> Self::IntoFuture {
503                self.node.into_read().into()
504            }
505        }
506    };
507}
508
509into_future!(Vc<T>);
510into_future!(&Vc<T>);
511into_future!(&mut Vc<T>);
512
513impl<T> Vc<T>
514where
515    T: VcValueType,
516{
517    /// Do not use this: Use [`OperationVc::read_strongly_consistent`] instead.
518    #[cfg(feature = "non_operation_vc_strongly_consistent")]
519    pub fn strongly_consistent(self) -> ReadVcFuture<T> {
520        self.node.into_read().strongly_consistent().into()
521    }
522
523    /// Returns a untracked read of the value. This will not invalidate the current function when
524    /// the read value changed.
525    pub fn untracked(self) -> ReadVcFuture<T> {
526        self.node.into_read().untracked().into()
527    }
528
529    /// Read the value with the hint that this is the final read of the value. This might drop the
530    /// cell content. Future reads might need to recompute the value.
531    pub fn final_read_hint(self) -> ReadVcFuture<T> {
532        self.node.into_read().final_read_hint().into()
533    }
534}
535
536impl<T> Vc<T>
537where
538    T: VcValueType,
539    VcReadTarget<T>: Clone,
540{
541    /// Read the value and returns a owned version of it. It might clone the value.
542    pub fn owned(self) -> ReadOwnedVcFuture<T> {
543        let future: ReadVcFuture<T> = self.node.into_read().into();
544        future.owned()
545    }
546}
547
548impl<T> Vc<T>
549where
550    T: VcValueType,
551    VcReadTarget<T>: KeyedEq,
552{
553    /// Read the value and selects a keyed value from it. Only depends on the used key instead of
554    /// the full value.
555    pub fn get<'l, Q>(self, key: &'l Q) -> ReadKeyedVcFuture<'l, T, Q>
556    where
557        Q: Hash + ?Sized,
558        VcReadTarget<T>: KeyedAccess<Q>,
559    {
560        let future: ReadVcFuture<T> = self.node.into_read().into();
561        future.get(key)
562    }
563
564    /// Read the value and checks if it contains the given key. Only depends on the used key instead
565    /// of the full value.
566    pub fn contains_key<'l, Q>(self, key: &'l Q) -> ReadContainsKeyedVcFuture<'l, T, Q>
567    where
568        Q: Hash + ?Sized,
569        VcReadTarget<T>: KeyedAccess<Q>,
570    {
571        let future: ReadVcFuture<T> = self.node.into_read().into();
572        future.contains_key(key)
573    }
574}
575
576impl<T> Unpin for Vc<T> where T: ?Sized {}
577
578impl<T> Vc<T>
579where
580    T: VcValueTrait + ?Sized,
581{
582    /// Converts this trait vc into a trait reference.
583    ///
584    /// The signature is similar to [`IntoFuture::into_future`], but we don't want trait vcs to
585    /// have the same future-like semantics as value vcs when it comes to producing refs. This
586    /// behavior is rarely needed, so in most cases, `.await`ing a trait vc is a mistake.
587    pub fn into_trait_ref(self) -> ReadVcFuture<T, VcValueTraitCast<T>> {
588        self.node.into_read().into()
589    }
590}
591
592impl<T> Default for Vc<T>
593where
594    T: ValueDefault,
595{
596    fn default() -> Self {
597        T::value_default()
598    }
599}
600
601pub trait OptionVcExt<T>
602where
603    T: VcValueType,
604{
605    fn to_resolved(self) -> impl Future<Output = Result<Option<ResolvedVc<T>>>> + Send;
606}
607
608impl<T> OptionVcExt<T> for Option<Vc<T>>
609where
610    T: VcValueType,
611{
612    async fn to_resolved(self) -> Result<Option<ResolvedVc<T>>> {
613        if let Some(vc) = self {
614            Ok(Some(vc.to_resolved().await?))
615        } else {
616            Ok(None)
617        }
618    }
619}