turbo_tasks/task/
local_task.rs

1use std::{fmt, sync::Arc};
2
3use anyhow::{Result, anyhow};
4
5use crate::{
6    MagicAny, OutputContent, RawVc, TaskPersistence, TraitMethod, TurboTasksBackendApi,
7    ValueTypeId,
8    backend::{Backend, TypedCellContent},
9    event::Event,
10    macro_helpers::NativeFunction,
11    registry,
12};
13
14/// A potentially in-flight local task stored in `CurrentGlobalTaskState::local_tasks`.
15pub enum LocalTask {
16    Scheduled { done_event: Event },
17    Done { output: OutputContent },
18}
19
20pub struct LocalTaskSpec {
21    /// The self value, will always be present for `ResolveTrait` tasks and is optional otherwise
22    pub(crate) this: Option<RawVc>,
23    /// Function arguments
24    pub(crate) arg: Box<dyn MagicAny>,
25    pub(crate) task_type: LocalTaskType,
26}
27
28#[derive(Copy, Clone)]
29pub enum LocalTaskType {
30    /// A resolve task, which resolves arguments and calls the function with resolve arguments. The
31    /// inner function call will be a `PersistentTaskType`.
32    ResolveNative { native_fn: &'static NativeFunction },
33
34    /// A trait method resolve task. It resolves the first (`self`) argument and looks up the trait
35    /// method on that value. Then it calls that method. The method call will do a cache lookup and
36    /// might resolve arguments before.
37    ResolveTrait { trait_method: &'static TraitMethod },
38}
39
40impl fmt::Display for LocalTaskType {
41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42        match self {
43            LocalTaskType::ResolveNative { native_fn } => write!(f, "*{}", native_fn.name),
44            LocalTaskType::ResolveTrait { trait_method } => write!(
45                f,
46                "*{}::{}",
47                trait_method.trait_name, trait_method.method_name
48            ),
49        }
50    }
51}
52
53impl LocalTaskType {
54    /// Implementation of the LocalTaskType::ResolveNative task.
55    /// Resolves all the task inputs and then calls the given function.
56    pub(crate) async fn run_resolve_native<B: Backend + 'static>(
57        native_fn: &'static NativeFunction,
58        mut this: Option<RawVc>,
59        arg: &dyn MagicAny,
60        persistence: TaskPersistence,
61        turbo_tasks: Arc<dyn TurboTasksBackendApi<B>>,
62    ) -> Result<RawVc> {
63        if let Some(this) = this.as_mut() {
64            *this = this.resolve().await?;
65        }
66        let arg = native_fn.arg_meta.resolve(arg).await?;
67        Ok(turbo_tasks.native_call(native_fn, this, arg, persistence))
68    }
69    /// Implementation of the LocalTaskType::ResolveTrait task.
70    pub(crate) async fn run_resolve_trait<B: Backend + 'static>(
71        trait_method: &'static TraitMethod,
72        this: RawVc,
73        arg: &dyn MagicAny,
74        persistence: TaskPersistence,
75        turbo_tasks: Arc<dyn TurboTasksBackendApi<B>>,
76    ) -> Result<RawVc> {
77        let this = this.resolve().await?;
78        let TypedCellContent(this_ty, _) = this.into_read().await?;
79
80        let native_fn = Self::resolve_trait_method_from_value(trait_method, this_ty)?;
81        let arg = native_fn.arg_meta.filter_and_resolve(arg).await?;
82        Ok(turbo_tasks.native_call(native_fn, Some(this), arg, persistence))
83    }
84
85    fn resolve_trait_method_from_value(
86        trait_method: &'static TraitMethod,
87        value_type: ValueTypeId,
88    ) -> Result<&'static NativeFunction> {
89        match registry::get_value_type(value_type).get_trait_method(trait_method) {
90            Some(native_fn) => Ok(native_fn),
91            None => Err(anyhow!(
92                "{} doesn't implement the trait for {:?}, the compiler should have flagged this",
93                registry::get_value_type(value_type),
94                trait_method
95            )),
96        }
97    }
98}
99
100#[cfg(test)]
101pub(crate) mod tests {
102    use super::*;
103    use crate::{self as turbo_tasks, Vc};
104
105    #[turbo_tasks::function]
106    fn mock_func_task() -> Vc<()> {
107        Vc::cell(())
108    }
109
110    #[turbo_tasks::value_trait]
111    trait MockTrait {
112        #[turbo_tasks::function]
113        fn mock_method_task() -> Vc<()>;
114    }
115
116    #[test]
117    fn test_fmt() {
118        assert_eq!(
119            LocalTaskType::ResolveNative {
120                native_fn: &MOCK_FUNC_TASK_FUNCTION,
121            }
122            .to_string(),
123            "*mock_func_task",
124        );
125        assert_eq!(
126            LocalTaskType::ResolveTrait {
127                trait_method: MOCKTRAIT_TRAIT_TYPE.get("mock_method_task"),
128            }
129            .to_string(),
130            "*MockTrait::mock_method_task",
131        );
132    }
133}