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