Traits
#[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_impl]
pub trait OtherTrait: MyTrait + ValueToString {
// ...
}
#[turbo_tasks::value_trait]
annotation is required to define traits in Turbo-Engine.- All items annotated with
#[turbo_tasks::function]
are Turbo-Engine functions.self
argument is alwaysVc<Self>
.
- Default implementation are supported and behave similarly to defining Turbo-Engine functions.
Vc<Box<dyn MyTrait>>
is a Vc to a trait.- A
Vc<Box<dyn MyTrait>>
can be turned into aTraitRef<Box<dyn MyTrait>>
to call non-turbotask functions. See reading below.
Implementing traits
#[turbo_tasks::value_impl]
impl MyTrait for Something {
#[turbo_tasks::function]
fn method(self: Vc<Self>, a: i32) -> Vc<Something> {
// Implementation
}
#[turbo_tasks::function]
fn method2(&self, a: i32) -> Vc<Something> {
// Implementation
}
fn normal(&self) -> SomethingElse {
// Implementation
}
}
Upcasting
Vcs can be upcasted to a trait Vc:
let something_vc: Vc<Something> = ...;
let trait_vc: Vc<Box<dyn MyTrait>> = Vc::upcast(something_vc);
Downcasting
Vcs can also be downcasted to a concrete type of a subtrait:
let trait_vc: Vc<Box<dyn MyTrait>> = ...;
if let Some(something_vc) = Vc::try_downcast_type::<Something>(trait_vc).await? {
// ...
}
let trait_vc: Vc<Box<dyn MyTrait>> = ...;
if let Some(something_vc) = Vc::try_downcast::<Box<dyn OtherTrait>>(trait_vc).await? {
// ...
}
There is a compile-time check that the source trait is implemented by the target trait/type.
Note: This will resolve the Vc and have similar implications as .to_resolved().await?
.
Sidecasting
let trait_vc: Vc<Box<dyn MyTrait>> = ...;
if let Some(something_vc) = Vc::try_sidecast::<Box<dyn UnrelatedTrait>>(trait_vc).await? {
// ...
}
This won't do any compile-time checks, so downcasting should be preferred if possible.
Note: This will resolve the Vc and have similar implications as .to_resolved().await?
.
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.
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();