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