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