Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 71 additions & 9 deletions turbopack/crates/turbo-tasks/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ pub use anyhow::{Error, Result};
use auto_hash_map::AutoSet;
use rustc_hash::FxHasher;
pub use shrink_to_fit::ShrinkToFit;
pub use turbo_tasks_macros::{turbobail, turbofmt, value_impl};
pub use turbo_tasks_macros::{turbobail, turbofmt};

pub use crate::{
capture_future::TurboTasksPanic,
Expand Down Expand Up @@ -249,27 +249,89 @@ pub use turbo_tasks_macros::function;
#[rustfmt::skip]
pub use turbo_tasks_macros::value;

/// Allows this trait to be used as part of a trait object inside of a value
/// cell, in the form of `Vc<dyn MyTrait>`.
/// Allows this trait to be used as part of a trait object inside of a value cell, in the form of
/// `Vc<Box<dyn MyTrait>>`. The annotated trait is made into a subtrait of [`VcValueTrait`].
///
/// ```ignore
/// #[turbo_tasks::value_trait]
/// pub trait MyTrait {
///
/// #[turbo_tasks::function]
/// fn method(self: Vc<Self>, a: i32) -> Vc<Something>;
///
/// // External signature: fn method(self: Vc<Self>, a: i32) -> Vc<Something>
/// #[turbo_tasks::function]
/// async fn method2(&self, a: i32) -> Result<Vc<Something>> {
/// // Default implementation
/// }
///
/// // A normal trait item, not a turbo-task
/// fn normal(&self) -> SomethingElse;
/// }
///
/// #[turbo_tasks::value_trait]
/// pub trait OtherTrait: MyTrait + ValueToString {
/// // ...
/// }
///
/// #[turbo_tasks::value_impl]
/// impl MyTrait for MyValue {
/// // only the external signature must match (see the docs for #[turbo_tasks::function])
/// #[turbo_tasks::function]
/// fn method(&self, a: i32) -> Vc<Something> {
/// todo!()
/// }
///
/// fn normal(&self) -> SomethingElse {
/// todo!()
/// }
/// }
/// ```
///
/// The `#[turbo_tasks::value_trait]` annotation derives [`VcValueTrait`] and registers the trait
/// and its methods.
///
/// All methods annotated with [`#[turbo_tasks::function]`][function] are cached, and
/// the external signature rewriting rules defined on that macro are applied.
///
/// Default implementation are supported.
///
/// ## Arguments
///
/// Example: `#[turbo_tasks::value_trait(no_debug, resolved)]`
/// Example: `#[turbo_tasks::value_trait(no_debug, operation)]`
///
/// ### 'no_debug`
/// ### `no_debug`
///
/// Disables the automatic implementation of [`ValueDebug`][crate::debug::ValueDebug].
/// Disables the automatic implementation of [`ValueDebug`][debug::ValueDebug].
///
/// Example: `#[turbo_tasks::value_trait(no_debug)]`
///
/// ### 'resolved`
/// ### `Operation`
///
/// Adds [`NonLocalValue`] as a supertrait of this trait.
/// Adds [`OperationValue`] as a supertrait of this trait.
///
/// Example: `#[turbo_tasks::value_trait(resolved)]`
/// Example: `#[turbo_tasks::value_trait(operation)]`
#[rustfmt::skip]
pub use turbo_tasks_macros::value_trait;

/// A macro used on any `impl` block for a [`VcValueType`]. This can either be an inherent
/// implementation or a trait implementation (see [`turbo_tasks::value_trait`][value_trait] and
/// [`VcValueTrait`]).
///
/// Methods should be annotated with the [`#[turbo_tasks::function]`][function] macro.
///
/// ```ignore
/// #[turbo_tasks::value_impl]
/// impl MyTrait for MyValue {
/// #[turbo_tasks::function]
/// fn method(&self, a: i32) -> Vc<Something> {
/// todo!()
/// }
/// }
/// ```
#[rustfmt::skip]
pub use turbo_tasks_macros::value_impl;

/// Derives the TaskStorage struct and generates optimized storage structures.
///
/// This macro analyzes `field` annotations and generates:
Expand Down
9 changes: 4 additions & 5 deletions turbopack/crates/turbo-tasks/src/trait_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ use crate::{
vc::{ReadVcFuture, VcValueTraitCast, cast::VcCast},
};

/// Similar to a [`ReadRef<T>`][crate::ReadRef], but contains a value trait
/// object instead.
/// Similar to a [`ReadRef<T>`][crate::ReadRef], but contains a value trait object instead.
///
/// The only way to interact with a `TraitRef<T>` is by passing
/// it around or turning it back into a value trait vc by calling
/// [`ReadRef::cell`][crate::ReadRef::cell].
/// Non-turbo-task methods with a `&self` receiver can be called on this reference.
///
/// A `TraitRef<T>` can be turned back into a value trait vc by calling [`TraitRef::cell`].
///
/// Internally it stores a reference counted reference to a value on the heap.
pub struct TraitRef<T>
Expand Down
123 changes: 111 additions & 12 deletions turbopack/crates/turbo-tasks/src/vc/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ use crate::{
vc::cell_mode::VcCellMode,
};

/// A trait implemented on all values types that can be put into a Value Cell
/// ([`Vc<T>`][crate::Vc]).
/// A trait implemented on all values types that can be put into a value cell ([`Vc`][crate::Vc]).
///
/// # Safety
/// Custom traits for `VcValueType`s should be subtraits of [`VcValueTrait`].
///
/// You should not implement this trait directly, but instead use the
/// [`#[turbo_tasks::value]`][crate::value] macro instead.
///
/// ## Safety
///
/// The implementor of this trait must ensure that the read and cell mode
/// implementations are correct for the value type. Otherwise, it is possible to
/// generate invalid reads, for instance by using
/// [`VcTransparentRead`][crate::VcTransparentRead] for a value type that is not
/// The implementor of this trait must ensure that the read and cell mode implementations are
/// correct for the value type. Otherwise, it is possible to generate invalid reads, for instance by
/// using [`VcTransparentRead`][crate::VcTransparentRead] for a value type that is not
/// `#[repr(transparent)]`.
pub unsafe trait VcValueType: ShrinkToFit + Sized + Send + Sync + 'static {
/// How to read the value.
Expand All @@ -26,8 +29,100 @@ pub unsafe trait VcValueType: ShrinkToFit + Sized + Send + Sync + 'static {
fn has_serialization() -> bool;
}

/// A trait implemented on all values trait object references that can be put
/// into a Value Cell ([`Vc<Box<dyn Trait>>`][crate::Vc]).
/// A trait implemented on all values trait object references that can be used with a value cell
/// ([`Vc<Box<dyn Trait>>`][crate::Vc]).
///
/// You should not create subtraits of this trait manually, but instead use the
/// [`#[turbo_tasks::value_trait]`][crate::value_trait] macro. Implementations of `VcValueTrait`s
/// should use the [`#[turbo_tasks::value_impl]`][crate::value_impl] macro.
///
/// [`Vc`]: crate::Vc
///
///
/// ## Upcasting
///
/// A concrete [`Vc`] of a [`VcValueType`] can be converted to a [`Vc`] of a `VcValueTrait` with an
/// upcast:
///
/// ```ignore
/// let something_vc: Vc<ConcreteType> = ...;
/// let trait_vc: Vc<Box<dyn MyTrait>> = Vc::upcast(something_vc);
///
/// // there is an equivalent API for ResolvedVc
/// let something_resolved_vc: ResolvedVc<ConcreteType> = ...;
/// let trait_resolved_vc: ResolvedVc<Box<dyn MyTrait>> = ResolvedVc::upcast(something_resolved_vc);
/// ```
///
/// Upcast safety is enforced at compile-time with the [`Upcast`] and [`UpcastStrict`] traits.
/// Upcasts always succeed.
///
///
/// ## Downcasting
///
/// A [`ResolvedVc`] containing a `VcValueTrait` subtrait can be downcast to a concrete type with
/// [`ResolvedVc::try_downcast_type`]:
///
/// ```ignore
/// let trait_vc: Vc<Box<dyn MyTrait>> = ...;
/// if let Some(something_vc) = ResolvedVc::try_downcast_type::<Something>(trait_vc) {
/// // ...
/// }
/// ```
///
/// A supertrait can be cast to a subtrait with [`ResolvedVc::try_downcast`]:
///
/// ```ignore
/// let trait_vc: Vc<Box<dyn SubTrait>> = ...;
/// if let Some(something_vc) = ResolvedVc::try_downcast::<Box<dyn SuperTrait>>(trait_vc) {
/// // ...
/// }
/// ```
///
/// If you have an unresolved [`Vc`] that you'd like to downcast, you should [resolve it first].
///
/// A compile-time check using the [`Upcast`] and [`UpcastStrict`] traits ensures that a downcast is
/// possible (the target type or trait implements the source trait), but it may still return
/// `None` at runtime if the concrete value does not implement the trait.
///
/// [`ResolvedVc`]: crate::ResolvedVc
/// [`ResolvedVc::try_downcast_type`]: crate::ResolvedVc::try_downcast_type
/// [`ResolvedVc::try_downcast`]: crate::ResolvedVc::try_downcast
/// [resolve it first]: crate::Vc::to_resolved
///
///
/// ## Sidecasting
///
/// In some cases, you may want to convert between two traits that do not have a supertrait/subtrait
/// relationship:
///
/// ```ignore
/// let trait_vc: Vc<Box<dyn MyTrait>> = ...;
/// if let Some(something_vc) = ResolvedVc::try_sidecast::<Box<dyn UnrelatedTrait>>(trait_vc) {
/// // ...
/// }
/// ```
///
/// If you have an unresolved [`Vc`] that you'd like to sidecast, you should [resolve it first].
///
/// This won't do any compile-time checks, so downcasting should be preferred if possible. It will
/// return `None` at runtime if the cast fails.
///
///
/// ## Reading
///
/// Trait object Vcs can be read by converting them to a [`TraitRef`], which allows non-turbo-tasks
/// functions defined on the trait to be called.
///
/// ```ignore
/// use turbo_tasks::IntoTraitRef;
///
/// let trait_vc: Vc<Box<dyn MyTrait>> = ...;
/// let trait_ref: TraitRef<Box<dyn MyTrait>> = trait_vc.into_trait_ref().await?;
///
/// trait_ref.non_turbo_tasks_function();
/// ```
///
/// [`TraitRef`]: crate::TraitRef
pub trait VcValueTrait: NonLocalValue + Send + Sync + 'static {
// The concrete type of the value_trait implementing VcValueTrait
type ValueTrait: ?Sized;
Expand All @@ -40,8 +135,10 @@ pub trait VcValueTrait: NonLocalValue + Send + Sync + 'static {
fn get_impl_vtables() -> &'static VTableRegistry<Self::ValueTrait>;
}

/// Marker trait that indicates that a [`Vc<Self>`][crate::Vc] can be upcasted
/// to a [`Vc<T>`][crate::Vc].
/// Marker trait that indicates that a [`Vc<Self>`][crate::Vc] can be upcasted to a
/// [`Vc<T>`][crate::Vc].
///
/// See [`VcValueTrait`] for example usage.
///
/// # Safety
///
Expand All @@ -53,7 +150,9 @@ where
{
}

/// A speialization of [`Upcast`] that ensures that the upcast is strict meaning that T !== Self
/// A specialization of [`Upcast`] that ensures that the upcast is strict meaning that `T !== Self`.
///
/// See [`VcValueTrait`] for example usage.
///
/// # Safety
///
Expand Down
Loading