Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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 always Vc<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 a TraitRef<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();