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