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 serde::{Deserialize, Serialize};
21use shrink_to_fit::ShrinkToFit;
22
23pub use self::{
24    cast::{VcCast, VcValueTraitCast, VcValueTypeCast},
25    cell_mode::{VcCellMode, VcCellNewMode, VcCellSharedMode},
26    default::ValueDefault,
27    local::NonLocalValue,
28    operation::{OperationValue, OperationVc},
29    read::{ReadOwnedVcFuture, ReadVcFuture, VcDefaultRead, VcRead, VcTransparentRead},
30    resolved::ResolvedVc,
31    traits::{Dynamic, Upcast, UpcastStrict, VcValueTrait, VcValueType},
32};
33use crate::{
34    CellId, RawVc, ResolveTypeError,
35    debug::{ValueDebug, ValueDebugFormat, ValueDebugFormatString},
36    registry,
37    trace::{TraceRawVcs, TraceRawVcsContext},
38};
39
40type VcReadTarget<T> = <<T as VcValueType>::Read as VcRead<T>>::Target;
41
42/// A "Value Cell" (`Vc` for short) is a reference to a memoized computation result stored on the
43/// heap or in filesystem cache, depending on the Turbo Engine backend implementation.
44///
45/// In order to get a reference to the pointed value, you need to `.await` the [`Vc<T>`] to get a
46/// [`ReadRef<T>`][`ReadRef`]:
47///
48/// ```
49/// let some_vc: Vc<T>;
50/// let some_ref: ReadRef<T> = some_vc.await?;
51/// some_ref.some_method_on_t();
52/// ```
53///
54/// `Vc`s are similar to a [`Future`] or a Promise with a few key differences:
55///
56/// - The value pointed to by a `Vc` can be invalidated by changing dependencies or cache evicted,
57///   meaning that `await`ing a `Vc` multiple times can give different results. A [`ReadRef`] is
58///   snapshot of the underlying cell at a point in time.
59///
60/// - Reading (`await`ing) `Vc`s causes the current task to be tracked a dependent of the `Vc`'s
61///   task or task cell. When the read task or task cell changes, the current task may be
62///   re-executed.
63///
64/// - `Vc` types are always [`Copy`]. Most [`Future`]s are not. This works because `Vc`s are
65///   represented as a few ids or indices into data structures managed by the `turbo-tasks`
66///   framework. `Vc` types are not reference counted, but do support [tracing] for a hypothetical
67///   (unimplemented) garbage collector.
68///
69/// - Unlike futures (but like promises), the work that a `Vc` represents [begins execution even if
70///   the `Vc` is not `await`ed](#execution-model).
71///
72/// For a more in-depth explanation of the concepts behind value cells, [refer to the Turbopack
73/// book][book-cells].
74///
75///
76/// ## Subtypes
77///
78/// There are a couple of explicit "subtypes" of `Vc`. These can both be cheaply converted back into
79/// a `Vc`.
80///
81/// - **[`ResolvedVc`]:** *(aka [`RawVc::TaskCell`])* A reference to a cell constructed within a
82///   task, as part of a [`Vc::cell`] or `value_type.cell()` constructor. As the cell has been
83///   constructed at least once, the concrete type of the cell is known (allowing
84///   [downcasting][ResolvedVc::try_downcast]). This is stored as a combination of a task id, a type
85///   id, and a cell id.
86///
87/// - **[`OperationVc`]:** *(aka [`RawVc::TaskOutput`])* The synchronous return value of a
88///   [`turbo_tasks::function`]. Internally, this is stored using a task id. Exact type information
89///   of trait types (i.e. `Vc<Box<dyn Trait>>`) is not known because the function may not have
90///   finished execution yet. [`OperationVc`]s must first be [`connect`][OperationVc::connect]ed
91///   before being read.
92///
93/// [`ResolvedVc`] is almost always preferred over the more awkward [`OperationVc`] API, but
94/// [`OperationVc`] can be useful when dealing with [collectibles], when you need to [read the
95/// result of a function with strong consistency][OperationVc::read_strongly_consistent], or with
96/// [`State`].
97///
98/// These many representations are stored internally using a type-erased [`RawVc`]. Type erasure
99/// reduces the [monomorphization] (and therefore binary size and compilation time) required to
100/// support `Vc` and its subtypes.
101///
102/// |                 | Representation                     | Equality        | Downcasting                | Strong Consistency     | Collectibles      | [Non-Local]  |
103/// |-----------------|------------------------------------|-----------------|----------------------------|------------------------|-------------------|--------------|
104/// | [`Vc`]          | [One of many][RawVc]               | ❌ [Broken][eq] | ⚠️  After resolution        | ❌ Eventual            | ❌ No             | ❌ [No][loc] |
105/// | [`ResolvedVc`]  | [Task Id + Type Id + Cell Id][rtc] | ✅ Yes\*        | ✅ [Yes, cheaply][resolve] | ❌ Eventual            | ❌ No             | ✅ Yes       |
106/// | [`OperationVc`] | [Task Id][rto]                     | ✅ Yes\*        | ⚠️  After resolution        | ✅ [Supported][strong] | ✅ [Yes][collect] | ✅ Yes       |
107///
108/// *\* see the type's documentation for details*
109///
110/// [Non-Local]: NonLocalValue
111/// [rtc]: RawVc::TaskCell
112/// [rto]: RawVc::TaskOutput
113/// [loc]: #optimization-local-outputs
114/// [eq]: #equality--hashing
115/// [resolve]: ResolvedVc::try_downcast
116/// [strong]: OperationVc::read_strongly_consistent
117/// [collect]: crate::CollectiblesSource
118///
119///
120/// ## Execution Model
121///
122/// While task functions are expected to be side-effect free, their execution behavior is still
123/// important for performance reasons, or to code using [collectibles] to represent issues or
124/// side-effects.
125///
126/// Function calls are neither "eager", nor "lazy". Even if not awaited, they are guaranteed to
127/// execute (potentially emitting collectibles) before the root task finishes or before the
128/// completion of any strongly consistent read containing their call. However, the exact point when
129/// that execution begins is an implementation detail. Functions may execute more than once due to
130/// dirty task invalidation.
131///
132///
133/// ## Equality & Hashing
134///
135/// Because `Vc`s can be equivalent but have different representation, it's not recommended to
136/// compare `Vc`s by equality. Instead, you should convert a `Vc` to an explicit subtype first
137/// (likely [`ResolvedVc`]). Future versions of `Vc` may not implement [`Eq`], [`PartialEq`], or
138/// [`Hash`].
139///
140///
141/// ## Optimization: Local Outputs
142///
143/// In addition to the potentially-explicit "resolved" and "operation" representations of a `Vc`,
144/// there's another internal representation of a `Vc`, known as a "Local `Vc`", or
145/// [`RawVc::LocalOutput`].
146///
147/// This is a special case of the synchronous return value of a [`turbo_tasks::function`] when some
148/// of its arguments have not yet been resolved. These are stored in task-local state that is freed
149/// after their parent non-local task exits.
150///
151/// We prevent potentially-local `Vc`s from escaping the lifetime of a function using the
152/// [`NonLocalValue`] marker trait alongside some fallback runtime checks. We do this to avoid some
153/// ergonomic challenges that would come from using lifetime annotations with `Vc`.
154///
155///
156/// [tracing]: crate::trace::TraceRawVcs
157/// [`ReadRef`]: crate::ReadRef
158/// [`turbo_tasks::function`]: crate::function
159/// [monomorphization]: https://doc.rust-lang.org/book/ch10-01-syntax.html#performance-of-code-using-generics
160/// [`State`]: crate::State
161/// [book-cells]: https://turbopack-rust-docs.vercel.sh/turbo-engine/cells.html
162/// [collectibles]: crate::CollectiblesSource
163#[must_use]
164#[derive(Serialize, Deserialize)]
165#[serde(transparent, bound = "")]
166#[repr(transparent)]
167pub struct Vc<T>
168where
169    T: ?Sized,
170{
171    pub(crate) node: RawVc,
172    #[doc(hidden)]
173    pub(crate) _t: PhantomData<T>,
174}
175
176/// This only exists to satisfy the Rust type system. However, this struct can
177/// never actually be instantiated, as dereferencing a `Vc<T>` will result in a
178/// linker error. See the implementation of `Deref` for `Vc<T>`.
179pub struct VcDeref<T>
180where
181    T: ?Sized,
182{
183    _t: PhantomData<T>,
184}
185
186macro_rules! do_not_use_or_you_will_be_fired {
187    ($($name:ident)*) => {
188        impl<T> VcDeref<T>
189        where
190            T: ?Sized,
191        {
192            $(
193                #[doc(hidden)]
194                #[allow(unused)]
195                #[allow(clippy::wrong_self_convention)]
196                #[deprecated = "This is not the method you are looking for."]
197                pub fn $name(self) {}
198            )*
199        }
200    };
201}
202
203// Hide raw pointer methods on `Vc<T>`. This is an artifact of having
204// implement `Deref<Target = *const T>` on `Vc<T>` for `arbitrary_self_types` to
205// do its thing. This can be removed once the `Receiver` trait no longer depends
206// on `Deref`.
207do_not_use_or_you_will_be_fired!(
208    add
209    addr
210    align_offset
211    as_mut
212    as_mut_ptr
213    as_ptr
214    as_ref
215    as_uninit_mut
216    as_uninit_ref
217    as_uninit_slice
218    as_uninit_slice_mut
219    byte_add
220    byte_offset
221    byte_offset_from
222    byte_sub
223    cast
224    cast_const
225    cast_mut
226    copy_from
227    copy_from_nonoverlapping
228    copy_to
229    copy_to_nonoverlapping
230    drop_in_place
231    expose_addr
232    from_bits
233    get_unchecked
234    get_unchecked_mut
235    guaranteed_eq
236    guaranteed_ne
237    is_aligned
238    is_aligned_to
239    is_empty
240    is_null
241    len
242    map_addr
243    mask
244    offset
245    offset_from
246    read
247    read_unaligned
248    read_volatile
249    replace
250    split_at_mut
251    split_at_mut_unchecked
252    sub
253    sub_ptr
254    swap
255    to_bits
256    to_raw_parts
257    with_addr
258    with_metadata_of
259    wrapping_add
260    wrapping_byte_add
261    wrapping_byte_offset
262    wrapping_byte_sub
263    wrapping_offset
264    wrapping_sub
265    write
266    write_bytes
267    write_unaligned
268    write_volatile
269);
270
271// Call this macro for all the applicable methods above:
272
273#[doc(hidden)]
274impl<T> Deref for VcDeref<T>
275where
276    T: ?Sized,
277{
278    // `*const T` or `*mut T` would be enough here, but from an abundance of
279    // caution, we use `*const *mut *const T` to make sure there will never be an
280    // applicable method.
281    type Target = *const *mut *const T;
282
283    fn deref(&self) -> &Self::Target {
284        unsafe extern "C" {
285            #[link_name = "\n\nERROR: you tried to dereference a `Vc<T>`\n"]
286            fn trigger() -> !;
287        }
288
289        unsafe { trigger() };
290    }
291}
292
293// This is the magic that makes `Vc<T>` accept `self: Vc<Self>` methods through
294// `arbitrary_self_types`, while not allowing any other receiver type:
295// * `Vc<T>` dereferences to `*const *mut *const T`, which means that it is valid under the
296//   `arbitrary_self_types` rules.
297// * `*const *mut *const T` is not a valid receiver for any attribute access on `T`, which means
298//   that the only applicable items will be the methods declared on `self: Vc<Self>`.
299//
300// If we had used `type Target = T` instead, `vc_t.some_attr_defined_on_t` would
301// have been accepted by the compiler.
302#[doc(hidden)]
303impl<T> Deref for Vc<T>
304where
305    T: ?Sized,
306{
307    type Target = VcDeref<T>;
308
309    fn deref(&self) -> &Self::Target {
310        unsafe extern "C" {
311            #[link_name = "\n\nERROR: you tried to dereference a `Vc<T>`\n"]
312            fn trigger() -> !;
313        }
314
315        unsafe { trigger() };
316    }
317}
318
319impl<T> Copy for Vc<T> where T: ?Sized {}
320
321impl<T> Clone for Vc<T>
322where
323    T: ?Sized,
324{
325    fn clone(&self) -> Self {
326        *self
327    }
328}
329
330impl<T> Hash for Vc<T>
331where
332    T: ?Sized,
333{
334    fn hash<H: Hasher>(&self, state: &mut H) {
335        self.node.hash(state);
336    }
337}
338
339impl<T> PartialEq<Vc<T>> for Vc<T>
340where
341    T: ?Sized,
342{
343    fn eq(&self, other: &Self) -> bool {
344        self.node == other.node
345    }
346}
347
348impl<T> Eq for Vc<T> where T: ?Sized {}
349
350/// Generates an opaque debug representation of the [`Vc`] itself, but not the data inside of it.
351///
352/// This is implemented to allow types containing [`Vc`] to implement the synchronous [`Debug`]
353/// trait, but in most cases users should use the [`ValueDebug`] implementation to get a string
354/// representation of the contents of the cell.
355impl<T> Debug for Vc<T>
356where
357    T: ?Sized,
358{
359    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
360        f.debug_tuple("Vc").field(&self.node).finish()
361    }
362}
363
364impl<T> Vc<T>
365where
366    T: VcValueType,
367{
368    // called by the `.cell()` method generated by the `#[turbo_tasks::value]` macro
369    #[doc(hidden)]
370    pub fn cell_private(mut inner: <T::Read as VcRead<T>>::Target) -> Self {
371        // cell contents are immutable, so go ahead and shrink the cell's contents
372        ShrinkToFit::shrink_to_fit(<T::Read as VcRead<T>>::target_to_value_mut_ref(&mut inner));
373        <T::CellMode as VcCellMode<T>>::cell(inner)
374    }
375}
376
377impl<T, Inner, Repr> Vc<T>
378where
379    T: VcValueType<Read = VcTransparentRead<T, Inner, Repr>>,
380    Inner: Any + Send + Sync,
381    Repr: VcValueType,
382{
383    pub fn cell(inner: Inner) -> Self {
384        Self::cell_private(inner)
385    }
386}
387
388impl<T> Vc<T>
389where
390    T: ?Sized,
391{
392    /// Returns a debug identifier for this `Vc`.
393    pub async fn debug_identifier(vc: Self) -> Result<String> {
394        let resolved = vc.resolve().await?;
395        let raw_vc: RawVc = resolved.node;
396        if let RawVc::TaskCell(task_id, CellId { type_id, index }) = raw_vc {
397            let value_ty = registry::get_value_type(type_id);
398            Ok(format!("{}#{}: {}", value_ty.name, index, task_id))
399        } else {
400            unreachable!()
401        }
402    }
403
404    /// Returns the `RawVc` corresponding to this `Vc`.
405    pub fn into_raw(vc: Self) -> RawVc {
406        vc.node
407    }
408
409    /// Upcasts the given `Vc<T>` to a `Vc<Box<dyn K>>`.
410    ///
411    /// This is also available as an `Into`/`From` conversion.
412    #[inline(always)]
413    pub fn upcast<K>(vc: Self) -> Vc<K>
414    where
415        T: UpcastStrict<K>,
416        K: VcValueTrait + ?Sized,
417    {
418        Self::upcast_non_strict(vc)
419    }
420
421    /// Upcasts the given `Vc<T>` to a `Vc<Box<dyn K>>`
422    ///
423    /// This has a loose type constraint which would allow upcasting to the same type, prefer using
424    /// [`Vc::upcast`] when possible.  This is useful for extension traits and other more generic
425    /// usecases.
426    ///
427    /// # Example
428    /// ```rust
429    /// // In generic code where T might be the same as K
430    /// fn process_foo(vc: ResolvedVc<impl Upcast<Box<dyn MyTrait>>>) -> Vc<Foo> {
431    ///    let my_trait: ResolvedVc<Box<dyn MyTrait>> = Vc::upcast_non_strict(vc);
432    ///    my_trait.do_something()
433    /// }
434    /// ```
435    /// Using generics you could allow users to pass any compatible type, but if you specified
436    /// `UpcastStrict<...>` instead of `Upcast<...>` you would disallow calling this function if you
437    /// already had a `ResolvedVc<Box<dyn MyTrait>>.  So this function has a looser type constraint
438    /// to make these functions easier to write and use.
439    #[inline(always)]
440    pub fn upcast_non_strict<K>(vc: Self) -> Vc<K>
441    where
442        T: Upcast<K>,
443        K: VcValueTrait + ?Sized,
444    {
445        Vc {
446            node: vc.node,
447            _t: PhantomData,
448        }
449    }
450    /// Runs the operation, but ignores the returned Vc. Use that when only interested in running
451    /// the task for side effects.
452    pub async fn as_side_effect(self) -> Result<()> {
453        self.node.resolve().await?;
454        Ok(())
455    }
456
457    /// Do not use this: Use [`Vc::to_resolved`] instead. If you must have a resolved [`Vc`] type
458    /// and not a [`ResolvedVc`] type, simply deref the result of [`Vc::to_resolved`].
459    pub async fn resolve(self) -> Result<Vc<T>> {
460        Ok(Self {
461            node: self.node.resolve().await?,
462            _t: PhantomData,
463        })
464    }
465
466    /// Resolve the reference until it points to a cell directly, and wrap the
467    /// result in a [`ResolvedVc`], which statically guarantees that the
468    /// [`Vc`] was resolved.
469    pub async fn to_resolved(self) -> Result<ResolvedVc<T>> {
470        Ok(ResolvedVc {
471            node: self.resolve().await?,
472        })
473    }
474
475    /// Returns `true` if the reference is resolved, meaning the underlying [`RawVc`] uses the
476    /// [`RawVc::TaskCell`] representation.
477    ///
478    /// If you need resolved [`Vc`] value, it's typically better to use the [`ResolvedVc`] type to
479    /// enforce your requirements statically instead of dynamically at runtime.
480    ///
481    /// See also [`ResolvedVc::to_resolved`] and [`RawVc::is_resolved`].
482    pub fn is_resolved(self) -> bool {
483        self.node.is_resolved()
484    }
485
486    /// Returns `true` if the `Vc` was by a local function call (e.g. one who's arguments were not
487    /// fully resolved) and has not yet been resolved.
488    ///
489    /// Aside from differences in caching, a function's behavior should not be changed by using
490    /// local or non-local cells, so this function is mostly useful inside tests and internally in
491    /// turbo-tasks.
492    pub fn is_local(self) -> bool {
493        self.node.is_local()
494    }
495
496    /// Do not use this: Use [`OperationVc::resolve_strongly_consistent`] instead.
497    #[cfg(feature = "non_operation_vc_strongly_consistent")]
498    pub async fn resolve_strongly_consistent(self) -> Result<Self> {
499        Ok(Self {
500            node: self.node.resolve_strongly_consistent().await?,
501            _t: PhantomData,
502        })
503    }
504}
505
506impl<T> Vc<T>
507where
508    T: VcValueTrait + ?Sized,
509{
510    /// Attempts to sidecast the given `Vc<Box<dyn T>>` to a `Vc<Box<dyn K>>`.
511    /// This operation also resolves the `Vc`.
512    ///
513    /// Returns `None` if the underlying value type does not implement `K`.
514    ///
515    /// **Note:** if the trait T is required to implement K, use
516    /// `Vc::upcast(vc).resolve()` instead. This provides stronger guarantees,
517    /// removing the need for a `Result` return type.
518    pub async fn try_resolve_sidecast<K>(vc: Self) -> Result<Option<Vc<K>>, ResolveTypeError>
519    where
520        K: VcValueTrait + ?Sized,
521    {
522        debug_assert!(
523            <K as VcValueTrait>::get_trait_type_id() != <T as VcValueTrait>::get_trait_type_id(),
524            "Attempted to cast a type {} to itself, which is pointless. Use the value directly \
525             instead.",
526            crate::registry::get_trait(<T as VcValueTrait>::get_trait_type_id()).global_name
527        );
528        let raw_vc: RawVc = vc.node;
529        let raw_vc = raw_vc
530            .resolve_trait(<K as VcValueTrait>::get_trait_type_id())
531            .await?;
532        Ok(raw_vc.map(|raw_vc| Vc {
533            node: raw_vc,
534            _t: PhantomData,
535        }))
536    }
537
538    /// Attempts to downcast the given `Vc<Box<dyn T>>` to a `Vc<K>`, where `K`
539    /// is of the form `Box<dyn L>`, and `L` is a value trait.
540    /// This operation also resolves the `Vc`.
541    ///
542    /// Returns `None` if the underlying value type is not a `K`.
543    pub async fn try_resolve_downcast<K>(vc: Self) -> Result<Option<Vc<K>>, ResolveTypeError>
544    where
545        K: UpcastStrict<T> + VcValueTrait + ?Sized,
546    {
547        Self::try_resolve_sidecast(vc).await
548    }
549
550    /// Attempts to downcast the given `Vc<Box<dyn T>>` to a `Vc<K>`, where `K`
551    /// is a value type.
552    /// This operation also resolves the `Vc`.
553    ///
554    /// Returns `None` if the underlying value type is not a `K`.
555    pub async fn try_resolve_downcast_type<K>(vc: Self) -> Result<Option<Vc<K>>, ResolveTypeError>
556    where
557        K: UpcastStrict<T> + VcValueType,
558    {
559        let raw_vc: RawVc = vc.node;
560        let raw_vc = raw_vc
561            .resolve_value(<K as VcValueType>::get_value_type_id())
562            .await?;
563        Ok(raw_vc.map(|raw_vc| Vc {
564            node: raw_vc,
565            _t: PhantomData,
566        }))
567    }
568}
569
570impl<T> From<RawVc> for Vc<T>
571where
572    T: ?Sized,
573{
574    fn from(node: RawVc) -> Self {
575        Self {
576            node,
577            _t: PhantomData,
578        }
579    }
580}
581
582impl<T> TraceRawVcs for Vc<T>
583where
584    T: ?Sized,
585{
586    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
587        TraceRawVcs::trace_raw_vcs(&self.node, trace_context);
588    }
589}
590
591impl<T> ValueDebugFormat for Vc<T>
592where
593    T: UpcastStrict<Box<dyn ValueDebug>> + Send + Sync + ?Sized,
594{
595    fn value_debug_format(&self, depth: usize) -> ValueDebugFormatString<'_> {
596        ValueDebugFormatString::Async(Box::pin(async move {
597            Ok({
598                let vc_value_debug = Vc::upcast::<Box<dyn ValueDebug>>(*self);
599                vc_value_debug.dbg_depth(depth).await?.to_string()
600            })
601        }))
602    }
603}
604
605macro_rules! into_future {
606    ($ty:ty) => {
607        impl<T> IntoFuture for $ty
608        where
609            T: VcValueType,
610        {
611            type Output = <ReadVcFuture<T> as Future>::Output;
612            type IntoFuture = ReadVcFuture<T>;
613            fn into_future(self) -> Self::IntoFuture {
614                self.node.into_read().into()
615            }
616        }
617    };
618}
619
620into_future!(Vc<T>);
621into_future!(&Vc<T>);
622into_future!(&mut Vc<T>);
623
624impl<T> Vc<T>
625where
626    T: VcValueType,
627{
628    /// Do not use this: Use [`OperationVc::read_strongly_consistent`] instead.
629    #[cfg(feature = "non_operation_vc_strongly_consistent")]
630    #[must_use]
631    pub fn strongly_consistent(self) -> ReadVcFuture<T> {
632        self.node.into_read().strongly_consistent().into()
633    }
634
635    /// Returns a untracked read of the value. This will not invalidate the current function when
636    /// the read value changed.
637    #[must_use]
638    pub fn untracked(self) -> ReadVcFuture<T> {
639        self.node.into_read().untracked().into()
640    }
641
642    /// Read the value with the hint that this is the final read of the value. This might drop the
643    /// cell content. Future reads might need to recompute the value.
644    #[must_use]
645    pub fn final_read_hint(self) -> ReadVcFuture<T> {
646        self.node.into_read().final_read_hint().into()
647    }
648}
649
650impl<T> Vc<T>
651where
652    T: VcValueType,
653    VcReadTarget<T>: Clone,
654{
655    /// Read the value and returns a owned version of it. It might clone the value.
656    pub fn owned(self) -> ReadOwnedVcFuture<T> {
657        let future: ReadVcFuture<T> = self.node.into_read().into();
658        future.owned()
659    }
660}
661
662impl<T> Unpin for Vc<T> where T: ?Sized {}
663
664impl<T> Default for Vc<T>
665where
666    T: ValueDefault,
667{
668    fn default() -> Self {
669        T::value_default()
670    }
671}
672
673pub trait OptionVcExt<T>
674where
675    T: VcValueType,
676{
677    fn to_resolved(self) -> impl Future<Output = Result<Option<ResolvedVc<T>>>> + Send;
678}
679
680impl<T> OptionVcExt<T> for Option<Vc<T>>
681where
682    T: VcValueType,
683{
684    async fn to_resolved(self) -> Result<Option<ResolvedVc<T>>> {
685        if let Some(vc) = self {
686            Ok(Some(vc.to_resolved().await?))
687        } else {
688            Ok(None)
689        }
690    }
691}