diff --git a/crates/turbo-tasks/src/lib.rs b/crates/turbo-tasks/src/lib.rs index 9eb8d7d7fcb0b..9d8c955d498f1 100644 --- a/crates/turbo-tasks/src/lib.rs +++ b/crates/turbo-tasks/src/lib.rs @@ -107,9 +107,9 @@ pub use turbo_tasks_macros::{function, value, value_impl, value_trait, TaskInput pub use value::{TransientInstance, TransientValue, Value}; pub use value_type::{TraitMethod, TraitType, ValueType}; pub use vc::{ - Dynamic, TypedForInput, Upcast, ValueDefault, Vc, VcCast, VcCellNewMode, VcCellSharedMode, - VcDefaultRead, VcRead, VcTransparentRead, VcValueTrait, VcValueTraitCast, VcValueType, - VcValueTypeCast, + Dynamic, ResolvedVc, TypedForInput, Upcast, ValueDefault, Vc, VcCast, VcCellNewMode, + VcCellSharedMode, VcDefaultRead, VcRead, VcTransparentRead, VcValueTrait, VcValueTraitCast, + VcValueType, VcValueTypeCast, }; pub use crate::rcstr::RcStr; diff --git a/crates/turbo-tasks/src/vc/mod.rs b/crates/turbo-tasks/src/vc/mod.rs index 3dbe3ec895d42..836d6fc29243f 100644 --- a/crates/turbo-tasks/src/vc/mod.rs +++ b/crates/turbo-tasks/src/vc/mod.rs @@ -2,9 +2,15 @@ pub(crate) mod cast; mod cell_mode; pub(crate) mod default; mod read; +pub(crate) mod resolved; mod traits; -use std::{any::Any, marker::PhantomData, ops::Deref}; +use std::{ + any::Any, + hash::{Hash, Hasher}, + marker::PhantomData, + ops::Deref, +}; use anyhow::Result; use auto_hash_map::AutoSet; @@ -16,6 +22,7 @@ pub use self::{ cell_mode::{VcCellNewMode, VcCellSharedMode}, default::ValueDefault, read::{ReadVcFuture, VcDefaultRead, VcRead, VcTransparentRead}, + resolved::ResolvedVc, traits::{Dynamic, TypedForInput, Upcast, VcValueTrait, VcValueType}, }; use crate::{ @@ -205,11 +212,11 @@ where } } -impl core::hash::Hash for Vc +impl Hash for Vc where T: ?Sized + Send, { - fn hash(&self, state: &mut H) { + fn hash(&self, state: &mut H) { self.node.hash(state); } } @@ -363,13 +370,22 @@ where /// /// This is async and will rethrow any fatal error that happened during task /// execution. - pub async fn resolve(self) -> Result { + pub async fn resolve(self) -> Result> { Ok(Self { node: self.node.resolve().await?, _t: PhantomData, }) } + /// Resolve the reference until it points to a cell directly, and wrap the + /// result in a [`ResolvedVc`], which strongly guarantees that the + /// [`Vc`] was resolved. + pub async fn to_resolved(self) -> Result> { + Ok(ResolvedVc { + node: self.resolve().await?, + }) + } + /// Resolve the reference until it points to a cell directly in a strongly /// consistent way. /// diff --git a/crates/turbo-tasks/src/vc/resolved.rs b/crates/turbo-tasks/src/vc/resolved.rs new file mode 100644 index 0000000000000..64913b997f380 --- /dev/null +++ b/crates/turbo-tasks/src/vc/resolved.rs @@ -0,0 +1,34 @@ +use std::{ + hash::{Hash, Hasher}, + ops::Deref, +}; + +use crate::vc::Vc; + +#[derive(Copy, Clone)] +pub struct ResolvedVc +where + T: ?Sized + Send, +{ + pub(crate) node: Vc, +} + +impl Deref for ResolvedVc +where + T: ?Sized + Send, +{ + type Target = Vc; + + fn deref(&self) -> &Self::Target { + &self.node + } +} + +impl Hash for ResolvedVc +where + T: ?Sized + Send, +{ + fn hash(&self, state: &mut H) { + self.node.hash(state); + } +}