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