diff --git a/turbopack/crates/turbo-tasks-macros/src/func.rs b/turbopack/crates/turbo-tasks-macros/src/func.rs index e79a811173a95..2855b3977438b 100644 --- a/turbopack/crates/turbo-tasks-macros/src/func.rs +++ b/turbopack/crates/turbo-tasks-macros/src/func.rs @@ -1,7 +1,7 @@ use std::collections::HashSet; use proc_macro2::{Ident, Span, TokenStream}; -use quote::{quote, quote_spanned}; +use quote::{quote, quote_spanned, ToTokens}; use syn::{ parenthesized, parse::{Parse, ParseStream}, @@ -24,6 +24,8 @@ pub struct TurboFn { inputs: Vec, /// Should we check that the return type contains a `ResolvedValue`? resolved: Option, + /// Should this function use `TaskPersistence::LocalCells`? + local_cells: bool, } #[derive(Debug)] @@ -257,6 +259,7 @@ impl TurboFn { this, inputs, resolved: args.resolved, + local_cells: args.local_cells.is_some(), }) } @@ -301,17 +304,26 @@ impl TurboFn { } } - fn inputs(&self) -> Vec<&Ident> { - self.inputs - .iter() - .map(|Input { ident, .. }| ident) - .collect() + fn input_idents(&self) -> impl Iterator { + self.inputs.iter().map(|Input { ident, .. }| ident) } pub fn input_types(&self) -> Vec<&Type> { self.inputs.iter().map(|Input { ty, .. }| ty).collect() } + pub fn persistence(&self) -> impl ToTokens { + if self.local_cells { + quote! { + turbo_tasks::TaskPersistence::LocalCells + } + } else { + quote! { + turbo_tasks::macro_helpers::get_non_local_persistence_from_inputs(&*inputs) + } + } + } + fn converted_this(&self) -> Option { self.this.as_ref().map(|Input { ty: _, ident }| { parse_quote! { @@ -344,31 +356,33 @@ impl TurboFn { /// The block of the exposed function for a dynamic dispatch call to the /// given trait. pub fn dynamic_block(&self, trait_type_id_ident: &Ident) -> Block { + let Some(converted_this) = self.converted_this() else { + return parse_quote! { + { + unimplemented!("trait methods without self are not yet supported") + } + }; + }; + let ident = &self.ident; let output = &self.output; let assertions = self.get_assertions(); - if let Some(converted_this) = self.converted_this() { - let inputs = self.inputs(); - parse_quote! { - { - #assertions - let turbo_tasks_transient = #( turbo_tasks::TaskInput::is_transient(&#inputs) ||)* false; - <#output as turbo_tasks::task::TaskOutput>::try_from_raw_vc( - turbo_tasks::trait_call( - *#trait_type_id_ident, - std::borrow::Cow::Borrowed(stringify!(#ident)), - #converted_this, - Box::new((#(#inputs,)*)) as Box, - turbo_tasks_transient, - ) + let inputs = self.input_idents(); + let persistence = self.persistence(); + parse_quote! { + { + #assertions + let inputs = std::boxed::Box::new((#(#inputs,)*)); + let persistence = #persistence; + <#output as turbo_tasks::task::TaskOutput>::try_from_raw_vc( + turbo_tasks::trait_call( + *#trait_type_id_ident, + std::borrow::Cow::Borrowed(stringify!(#ident)), + #converted_this, + inputs as std::boxed::Box, + persistence, ) - } - } - } else { - parse_quote! { - { - unimplemented!("trait methods without self are not yet supported") - } + ) } } } @@ -377,19 +391,21 @@ impl TurboFn { /// given native function. pub fn static_block(&self, native_function_id_ident: &Ident) -> Block { let output = &self.output; - let inputs = self.inputs(); + let inputs = self.input_idents(); + let persistence = self.persistence(); let assertions = self.get_assertions(); if let Some(converted_this) = self.converted_this() { parse_quote! { { #assertions - let turbo_tasks_transient = #( turbo_tasks::TaskInput::is_transient(&#inputs) ||)* false; + let inputs = std::boxed::Box::new((#(#inputs,)*)); + let persistence = #persistence; <#output as turbo_tasks::task::TaskOutput>::try_from_raw_vc( turbo_tasks::dynamic_this_call( *#native_function_id_ident, #converted_this, - Box::new((#(#inputs,)*)) as Box, - turbo_tasks_transient + inputs as std::boxed::Box, + persistence, ) ) } @@ -398,12 +414,13 @@ impl TurboFn { parse_quote! { { #assertions - let turbo_tasks_transient = #( turbo_tasks::TaskInput::is_transient(&#inputs) ||)* false; + let inputs = std::boxed::Box::new((#(#inputs,)*)); + let persistence = #persistence; <#output as turbo_tasks::task::TaskOutput>::try_from_raw_vc( turbo_tasks::dynamic_call( *#native_function_id_ident, - Box::new((#(#inputs,)*)) as Box, - turbo_tasks_transient, + inputs as std::boxed::Box, + persistence, ) ) } diff --git a/turbopack/crates/turbo-tasks-memory/src/task.rs b/turbopack/crates/turbo-tasks-memory/src/task.rs index 4b7cd70953455..64e664ac2a9fd 100644 --- a/turbopack/crates/turbo-tasks-memory/src/task.rs +++ b/turbopack/crates/turbo-tasks-memory/src/task.rs @@ -810,7 +810,7 @@ impl Task { native_fn_id, *this, &**arg, - self.id.is_transient(), + self.id.persistence(), turbo_tasks, )); drop(entered); @@ -833,7 +833,7 @@ impl Task { name, *this, &**arg, - self.id.is_transient(), + self.id.persistence(), turbo_tasks, )); drop(entered); diff --git a/turbopack/crates/turbo-tasks-memory/tests/local_cell.rs b/turbopack/crates/turbo-tasks-memory/tests/local_cell.rs new file mode 120000 index 0000000000000..9249e3399052e --- /dev/null +++ b/turbopack/crates/turbo-tasks-memory/tests/local_cell.rs @@ -0,0 +1 @@ +../../turbo-tasks-testing/tests/local_cell.rs \ No newline at end of file diff --git a/turbopack/crates/turbo-tasks-testing/src/lib.rs b/turbopack/crates/turbo-tasks-testing/src/lib.rs index 62116f98444d4..f66bf93c53252 100644 --- a/turbopack/crates/turbo-tasks-testing/src/lib.rs +++ b/turbopack/crates/turbo-tasks-testing/src/lib.rs @@ -20,8 +20,8 @@ use turbo_tasks::{ registry, test_helpers::with_turbo_tasks_for_testing, util::{SharedError, StaticOrArc}, - CellId, ExecutionId, InvalidationReason, MagicAny, RawVc, TaskId, TraitTypeId, TurboTasksApi, - TurboTasksCallApi, + CellId, ExecutionId, InvalidationReason, MagicAny, RawVc, TaskId, TaskPersistence, TraitTypeId, + TurboTasksApi, TurboTasksCallApi, }; pub use crate::run::{run, run_without_cache_check, Registration}; @@ -92,7 +92,7 @@ impl TurboTasksCallApi for VcStorage { &self, func: turbo_tasks::FunctionId, arg: Box, - _is_transient: bool, + _persistence: TaskPersistence, ) -> RawVc { self.dynamic_call(func, None, arg) } @@ -102,7 +102,7 @@ impl TurboTasksCallApi for VcStorage { func: turbo_tasks::FunctionId, this_arg: RawVc, arg: Box, - _is_transient: bool, + _persistence: TaskPersistence, ) -> RawVc { self.dynamic_call(func, Some(this_arg), arg) } @@ -111,7 +111,7 @@ impl TurboTasksCallApi for VcStorage { &self, _func: turbo_tasks::FunctionId, _arg: Box, - _is_transient: bool, + _persistence: TaskPersistence, ) -> RawVc { unreachable!() } @@ -121,7 +121,7 @@ impl TurboTasksCallApi for VcStorage { _func: turbo_tasks::FunctionId, _this: RawVc, _arg: Box, - _is_transient: bool, + _persistence: TaskPersistence, ) -> RawVc { unreachable!() } @@ -132,7 +132,7 @@ impl TurboTasksCallApi for VcStorage { _trait_fn_name: Cow<'static, str>, _this: RawVc, _arg: Box, - _is_transient: bool, + _persistence: TaskPersistence, ) -> RawVc { unreachable!() } diff --git a/turbopack/crates/turbo-tasks-testing/tests/local_cell.rs b/turbopack/crates/turbo-tasks-testing/tests/local_cell.rs index 78325b251740d..009081fbe70ff 100644 --- a/turbopack/crates/turbo-tasks-testing/tests/local_cell.rs +++ b/turbopack/crates/turbo-tasks-testing/tests/local_cell.rs @@ -1,5 +1,6 @@ #![feature(arbitrary_self_types)] +use anyhow::Result; use turbo_tasks::{ debug::ValueDebug, test_helpers::current_task_for_testing, ResolvedValue, ValueDefault, Vc, }; @@ -14,8 +15,8 @@ struct Wrapper(u32); struct TransparentWrapper(u32); #[tokio::test] -async fn test_store_and_read() { - run(®ISTRATION, async { +async fn test_store_and_read() -> Result<()> { + run(®ISTRATION, || async { let a: Vc = Vc::local_cell(42); assert_eq!(*a.await.unwrap(), 42); @@ -24,13 +25,15 @@ async fn test_store_and_read() { let c = TransparentWrapper(42).local_cell(); assert_eq!(*c.await.unwrap(), 42); + + Ok(()) }) .await } #[tokio::test] -async fn test_store_and_read_generic() { - run(®ISTRATION, async { +async fn test_store_and_read_generic() -> Result<()> { + run(®ISTRATION, || async { // `Vc>>` is stored as `Vc>>` and requires special // transmute handling let cells: Vc>> = @@ -42,6 +45,8 @@ async fn test_store_and_read_generic() { } assert_eq!(output, vec![1, 2, 3]); + + Ok(()) }) .await } @@ -53,10 +58,12 @@ async fn returns_resolved_local_vc() -> Vc { cell.resolve().await.unwrap() } +#[ignore] #[tokio::test] -async fn test_return_resolved() { - run(®ISTRATION, async { +async fn test_return_resolved() -> Result<()> { + run(®ISTRATION, || async { assert_eq!(*returns_resolved_local_vc().await.unwrap(), 42); + Ok(()) }) .await } @@ -65,8 +72,8 @@ async fn test_return_resolved() { trait UnimplementedTrait {} #[tokio::test] -async fn test_try_resolve_sidecast() { - run(®ISTRATION, async { +async fn test_try_resolve_sidecast() -> Result<()> { + run(®ISTRATION, || async { let trait_vc: Vc> = Vc::upcast(Vc::::local_cell(42)); // `u32` is both a `ValueDebug` and a `ValueDefault`, so this sidecast is valid @@ -80,13 +87,15 @@ async fn test_try_resolve_sidecast() { .await .unwrap(); assert!(wrongly_sidecast_vc.is_none()); + + Ok(()) }) .await } #[tokio::test] -async fn test_try_resolve_downcast_type() { - run(®ISTRATION, async { +async fn test_try_resolve_downcast_type() -> Result<()> { + run(®ISTRATION, || async { let trait_vc: Vc> = Vc::upcast(Vc::::local_cell(42)); let downcast_vc: Vc = Vc::try_resolve_downcast_type(trait_vc) @@ -98,16 +107,19 @@ async fn test_try_resolve_downcast_type() { let wrongly_downcast_vc: Option> = Vc::try_resolve_downcast_type(trait_vc).await.unwrap(); assert!(wrongly_downcast_vc.is_none()); + + Ok(()) }) .await } #[tokio::test] -async fn test_get_task_id() { - run(®ISTRATION, async { +async fn test_get_task_id() -> Result<()> { + run(®ISTRATION, || async { // the task id as reported by the RawVc let vc_task_id = Vc::into_raw(Vc::<()>::local_cell(())).get_task_id(); assert_eq!(vc_task_id, current_task_for_testing()); + Ok(()) }) .await } @@ -139,25 +151,31 @@ async fn get_untracked_local_cell() -> Vc { .unwrap() } +#[ignore] #[tokio::test] #[should_panic(expected = "Local Vcs must only be accessed within their own task")] async fn test_panics_on_local_cell_escape_read() { - run(®ISTRATION, async { + run(®ISTRATION, || async { get_untracked_local_cell() .await .unwrap() .cell .await .unwrap(); + Ok(()) }) .await + .unwrap() } +#[ignore] #[tokio::test] #[should_panic(expected = "Local Vcs must only be accessed within their own task")] async fn test_panics_on_local_cell_escape_get_task_id() { - run(®ISTRATION, async { + run(®ISTRATION, || async { Vc::into_raw(get_untracked_local_cell().await.unwrap().cell).get_task_id(); + Ok(()) }) .await + .unwrap() } diff --git a/turbopack/crates/turbo-tasks/src/backend.rs b/turbopack/crates/turbo-tasks/src/backend.rs index 8dc9fa2f60188..87ea0ce121839 100644 --- a/turbopack/crates/turbo-tasks/src/backend.rs +++ b/turbopack/crates/turbo-tasks/src/backend.rs @@ -23,8 +23,8 @@ use crate::{ task::shared_reference::TypedSharedReference, trait_helpers::{get_trait_method, has_trait, traits}, triomphe_utils::unchecked_sidecast_triomphe_arc, - FunctionId, RawVc, ReadRef, SharedReference, TaskId, TaskIdSet, TraitRef, TraitTypeId, - ValueTypeId, VcRead, VcValueTrait, VcValueType, + FunctionId, RawVc, ReadRef, SharedReference, TaskId, TaskIdSet, TaskPersistence, TraitRef, + TraitTypeId, ValueTypeId, VcRead, VcValueTrait, VcValueType, }; type TransientTaskRoot = @@ -608,7 +608,7 @@ impl CachedTaskType { fn_id: FunctionId, mut this: Option, arg: &dyn MagicAny, - is_transient: bool, + persistence: TaskPersistence, turbo_tasks: Arc>, ) -> Result { if let Some(this) = this.as_mut() { @@ -616,9 +616,9 @@ impl CachedTaskType { } let arg = registry::get_function(fn_id).arg_meta.resolve(arg).await?; Ok(if let Some(this) = this { - turbo_tasks.this_call(fn_id, this, arg, is_transient) + turbo_tasks.this_call(fn_id, this, arg, persistence) } else { - turbo_tasks.native_call(fn_id, arg, is_transient) + turbo_tasks.native_call(fn_id, arg, persistence) }) } @@ -636,7 +636,7 @@ impl CachedTaskType { name: Cow<'static, str>, this: RawVc, arg: &dyn MagicAny, - is_transient: bool, + persistence: TaskPersistence, turbo_tasks: Arc>, ) -> Result { let this = this.resolve().await?; @@ -647,7 +647,7 @@ impl CachedTaskType { .arg_meta .resolve(arg) .await?; - Ok(turbo_tasks.dynamic_this_call(native_fn, this, arg, is_transient)) + Ok(turbo_tasks.dynamic_this_call(native_fn, this, arg, persistence)) } /// Shared helper used by [`Self::resolve_trait_method`] and diff --git a/turbopack/crates/turbo-tasks/src/id.rs b/turbopack/crates/turbo-tasks/src/id.rs index d851e0114d861..26f1f712c0ebc 100644 --- a/turbopack/crates/turbo-tasks/src/id.rs +++ b/turbopack/crates/turbo-tasks/src/id.rs @@ -7,7 +7,7 @@ use std::{ use serde::{de::Visitor, Deserialize, Serialize}; -use crate::registry; +use crate::{registry, TaskPersistence}; macro_rules! define_id { ($name:ident : $primitive:ty $(,derive($($derive:ty),*))?) => { @@ -84,6 +84,14 @@ impl TaskId { pub fn is_transient(&self) -> bool { **self & TRANSIENT_TASK_BIT != 0 } + pub fn persistence(&self) -> TaskPersistence { + // tasks with `TaskPersistence::LocalCells` have no `TaskId`, so we can ignore that case + if self.is_transient() { + TaskPersistence::Transient + } else { + TaskPersistence::Persistent + } + } } macro_rules! make_serializable { diff --git a/turbopack/crates/turbo-tasks/src/lib.rs b/turbopack/crates/turbo-tasks/src/lib.rs index b0f17aff7678e..42590944842e9 100644 --- a/turbopack/crates/turbo-tasks/src/lib.rs +++ b/turbopack/crates/turbo-tasks/src/lib.rs @@ -90,8 +90,8 @@ pub use magic_any::MagicAny; pub use manager::{ dynamic_call, dynamic_this_call, emit, get_invalidator, mark_finished, mark_stateful, prevent_gc, run_once, run_once_with_reason, spawn_blocking, spawn_thread, trait_call, - turbo_tasks, CurrentCellRef, Invalidator, TurboTasks, TurboTasksApi, TurboTasksBackendApi, - TurboTasksCallApi, Unused, UpdateInfo, + turbo_tasks, CurrentCellRef, Invalidator, TaskPersistence, TurboTasks, TurboTasksApi, + TurboTasksBackendApi, TurboTasksCallApi, Unused, UpdateInfo, }; pub use native_function::{FunctionMeta, NativeFunction}; pub use raw_vc::{CellId, RawVc, ReadRawVcFuture, ResolveTypeError}; diff --git a/turbopack/crates/turbo-tasks/src/macro_helpers.rs b/turbopack/crates/turbo-tasks/src/macro_helpers.rs index 692e4cfa6f143..e4e3e47016dfc 100644 --- a/turbopack/crates/turbo-tasks/src/macro_helpers.rs +++ b/turbopack/crates/turbo-tasks/src/macro_helpers.rs @@ -8,7 +8,7 @@ pub use super::{ magic_any::MagicAny, manager::{find_cell_by_type, notify_scheduled_tasks, spawn_detached_for_testing}, }; -use crate::debug::ValueDebugFormatString; +use crate::{debug::ValueDebugFormatString, TaskInput, TaskPersistence}; #[inline(never)] pub async fn value_debug_format_field(value: ValueDebugFormatString<'_>) -> String { @@ -21,6 +21,14 @@ pub async fn value_debug_format_field(value: ValueDebugFormatString<'_>) -> Stri } } +pub fn get_non_local_persistence_from_inputs(inputs: &impl TaskInput) -> TaskPersistence { + if inputs.is_transient() { + TaskPersistence::Transient + } else { + TaskPersistence::Persistent + } +} + #[macro_export] macro_rules! stringify_path { ($path:path) => { diff --git a/turbopack/crates/turbo-tasks/src/manager.rs b/turbopack/crates/turbo-tasks/src/manager.rs index 99f0241a5dbd0..6c183ffca5c40 100644 --- a/turbopack/crates/turbo-tasks/src/manager.rs +++ b/turbopack/crates/turbo-tasks/src/manager.rs @@ -47,7 +47,12 @@ use crate::{ pub trait TurboTasksCallApi: Sync + Send { /// Calls a native function with arguments. Resolves arguments when needed /// with a wrapper task. - fn dynamic_call(&self, func: FunctionId, arg: Box, is_transient: bool) -> RawVc; + fn dynamic_call( + &self, + func: FunctionId, + arg: Box, + persistence: TaskPersistence, + ) -> RawVc; /// Calls a native function with arguments. Resolves arguments when needed /// with a wrapper task. fn dynamic_this_call( @@ -55,11 +60,16 @@ pub trait TurboTasksCallApi: Sync + Send { func: FunctionId, this: RawVc, arg: Box, - is_transient: bool, + persistence: TaskPersistence, ) -> RawVc; /// Call a native function with arguments. /// All inputs must be resolved. - fn native_call(&self, func: FunctionId, arg: Box, is_transient: bool) -> RawVc; + fn native_call( + &self, + func: FunctionId, + arg: Box, + persistence: TaskPersistence, + ) -> RawVc; /// Call a native function with arguments. /// All inputs must be resolved. fn this_call( @@ -67,7 +77,7 @@ pub trait TurboTasksCallApi: Sync + Send { func: FunctionId, this: RawVc, arg: Box, - is_transient: bool, + persistence: TaskPersistence, ) -> RawVc; /// Calls a trait method with arguments. First input is the `self` object. /// Uses a wrapper task to resolve @@ -77,7 +87,7 @@ pub trait TurboTasksCallApi: Sync + Send { trait_fn_name: Cow<'static, str>, this: RawVc, arg: Box, - is_transient: bool, + persistence: TaskPersistence, ) -> RawVc; fn run_once( @@ -239,6 +249,34 @@ pub struct UpdateInfo { placeholder_for_future_fields: (), } +#[derive(Clone, Copy)] +pub enum TaskPersistence { + /// Tasks that may be persisted across sessions using serialization. + Persistent, + + /// Tasks that will be persisted in memory for the life of this session, but won't persist + /// between sessions. + /// + /// This is used for [root tasks][TurboTasks::spawn_root_task] and tasks with an argument of + /// type [`TransientValue`][crate::value::TransientValue] or + /// [`TransientInstance`][crate::value::TransientInstance]. + Transient, + + /// Tasks that are persisted only for the lifetime of the nearest non-`LocalCells` parent + /// caller. + /// + /// This task does not have a unique task id, and is not shared with the backend. Instead it + /// uses the parent task's id. + /// + /// Cells are allocated onto a temporary arena by default. Resolved cells inside a local task + /// are allocated into the parent task's cells. + /// + /// This is useful for functions that have a low cache hit rate. Those functions could be + /// converted to non-task functions, but that would break their function signature. This + /// provides a mechanism for skipping caching without changing the function signature. + LocalCells, +} + pub struct TurboTasks { this: Weak, backend: B, @@ -416,25 +454,31 @@ impl TurboTasks { &self, func: FunctionId, arg: Box, - is_transient: bool, + persistence: TaskPersistence, ) -> RawVc { let task_type = CachedTaskType::Native { fn_type: func, this: None, arg, }; - if is_transient { - RawVc::TaskOutput(self.backend.get_or_create_transient_task( - task_type, - current_task("turbo_function calls"), - self, - )) - } else { - RawVc::TaskOutput(self.backend.get_or_create_persistent_task( - task_type, - current_task("turbo_function calls"), - self, - )) + match persistence { + TaskPersistence::LocalCells => { + todo!("bgw: local tasks"); + } + TaskPersistence::Transient => { + RawVc::TaskOutput(self.backend.get_or_create_transient_task( + task_type, + current_task("turbo_function calls"), + self, + )) + } + TaskPersistence::Persistent => { + RawVc::TaskOutput(self.backend.get_or_create_persistent_task( + task_type, + current_task("turbo_function calls"), + self, + )) + } } } @@ -443,25 +487,31 @@ impl TurboTasks { func: FunctionId, this: RawVc, arg: Box, - is_transient: bool, + persistence: TaskPersistence, ) -> RawVc { let task_type = CachedTaskType::Native { fn_type: func, this: Some(this), arg, }; - if is_transient { - RawVc::TaskOutput(self.backend.get_or_create_transient_task( - task_type, - current_task("turbo_function calls"), - self, - )) - } else { - RawVc::TaskOutput(self.backend.get_or_create_persistent_task( - task_type, - current_task("turbo_function calls"), - self, - )) + match persistence { + TaskPersistence::LocalCells => { + todo!("bgw: local tasks"); + } + TaskPersistence::Transient => { + RawVc::TaskOutput(self.backend.get_or_create_transient_task( + task_type, + current_task("turbo_function calls"), + self, + )) + } + TaskPersistence::Persistent => { + RawVc::TaskOutput(self.backend.get_or_create_persistent_task( + task_type, + current_task("turbo_function calls"), + self, + )) + } } } @@ -469,31 +519,38 @@ impl TurboTasks { &self, func: FunctionId, arg: Box, - is_transient: bool, + persistence: TaskPersistence, ) -> RawVc { // TODO(bgw): Don't create a full turbo task if this is a function using local_cells if registry::get_function(func).arg_meta.is_resolved(&*arg) { - self.native_call(func, arg, is_transient) - } else if is_transient { - RawVc::TaskOutput(self.backend.get_or_create_transient_task( - CachedTaskType::ResolveNative { - fn_type: func, - this: None, - arg, - }, - current_task("turbo_function calls"), - self, - )) - } else { - RawVc::TaskOutput(self.backend.get_or_create_persistent_task( - CachedTaskType::ResolveNative { - fn_type: func, - this: None, - arg, - }, - current_task("turbo_function calls"), - self, - )) + return self.native_call(func, arg, persistence); + } + match persistence { + TaskPersistence::LocalCells => { + todo!("bgw: local tasks"); + } + TaskPersistence::Transient => { + RawVc::TaskOutput(self.backend.get_or_create_transient_task( + CachedTaskType::ResolveNative { + fn_type: func, + this: None, + arg, + }, + current_task("turbo_function calls"), + self, + )) + } + TaskPersistence::Persistent => { + RawVc::TaskOutput(self.backend.get_or_create_persistent_task( + CachedTaskType::ResolveNative { + fn_type: func, + this: None, + arg, + }, + current_task("turbo_function calls"), + self, + )) + } } } @@ -502,23 +559,28 @@ impl TurboTasks { func: FunctionId, this: RawVc, arg: Box, - is_transient: bool, + persistence: TaskPersistence, ) -> RawVc { if this.is_resolved() && registry::get_function(func).arg_meta.is_resolved(&*arg) { - self.this_call(func, this, arg, is_transient) - } else { - let task_type = CachedTaskType::ResolveNative { - fn_type: func, - this: Some(this), - arg, - }; - if is_transient { + return self.this_call(func, this, arg, persistence); + } + let task_type = CachedTaskType::ResolveNative { + fn_type: func, + this: Some(this), + arg, + }; + match persistence { + TaskPersistence::LocalCells => { + todo!("bgw: local tasks"); + } + TaskPersistence::Transient => { RawVc::TaskOutput(self.backend.get_or_create_transient_task( task_type, current_task("turbo_function calls"), self, )) - } else { + } + TaskPersistence::Persistent => { RawVc::TaskOutput(self.backend.get_or_create_persistent_task( task_type, current_task("turbo_function calls"), @@ -534,7 +596,7 @@ impl TurboTasks { mut trait_fn_name: Cow<'static, str>, this: RawVc, arg: Box, - is_transient: bool, + persistence: TaskPersistence, ) -> RawVc { // avoid creating a wrapper task if self is already resolved // for resolved cells we already know the value type so we can lookup the @@ -542,7 +604,7 @@ impl TurboTasks { if let RawVc::TaskCell(_, CellId { type_id, .. }) = this { match get_trait_method(trait_type, type_id, trait_fn_name) { Ok(native_fn) => { - return self.dynamic_this_call(native_fn, this, arg, is_transient); + return self.dynamic_this_call(native_fn, this, arg, persistence); } Err(name) => { trait_fn_name = name; @@ -557,18 +619,24 @@ impl TurboTasks { this, arg, }; - if is_transient { - RawVc::TaskOutput(self.backend.get_or_create_transient_task( - task_type, - current_task("turbo_function calls"), - self, - )) - } else { - RawVc::TaskOutput(self.backend.get_or_create_persistent_task( - task_type, - current_task("turbo_function calls"), - self, - )) + match persistence { + TaskPersistence::LocalCells => { + todo!("bgw: local tasks"); + } + TaskPersistence::Transient => { + RawVc::TaskOutput(self.backend.get_or_create_transient_task( + task_type, + current_task("turbo_function calls"), + self, + )) + } + TaskPersistence::Persistent => { + RawVc::TaskOutput(self.backend.get_or_create_persistent_task( + task_type, + current_task("turbo_function calls"), + self, + )) + } } } @@ -951,29 +1019,39 @@ impl TurboTasks { } impl TurboTasksCallApi for TurboTasks { - fn dynamic_call(&self, func: FunctionId, arg: Box, is_transient: bool) -> RawVc { - self.dynamic_call(func, arg, is_transient) + fn dynamic_call( + &self, + func: FunctionId, + arg: Box, + persistence: TaskPersistence, + ) -> RawVc { + self.dynamic_call(func, arg, persistence) } fn dynamic_this_call( &self, func: FunctionId, this: RawVc, arg: Box, - is_transient: bool, + persistence: TaskPersistence, ) -> RawVc { - self.dynamic_this_call(func, this, arg, is_transient) + self.dynamic_this_call(func, this, arg, persistence) } - fn native_call(&self, func: FunctionId, arg: Box, is_transient: bool) -> RawVc { - self.native_call(func, arg, is_transient) + fn native_call( + &self, + func: FunctionId, + arg: Box, + persistence: TaskPersistence, + ) -> RawVc { + self.native_call(func, arg, persistence) } fn this_call( &self, func: FunctionId, this: RawVc, arg: Box, - is_transient: bool, + persistence: TaskPersistence, ) -> RawVc { - self.this_call(func, this, arg, is_transient) + self.this_call(func, this, arg, persistence) } fn trait_call( &self, @@ -981,9 +1059,9 @@ impl TurboTasksCallApi for TurboTasks { trait_fn_name: Cow<'static, str>, this: RawVc, arg: Box, - is_transient: bool, + persistence: TaskPersistence, ) -> RawVc { - self.trait_call(trait_type, trait_fn_name, this, arg, is_transient) + self.trait_call(trait_type, trait_fn_name, this, arg, persistence) } #[track_caller] @@ -1475,8 +1553,12 @@ pub async fn run_once_with_reason( } /// Calls [`TurboTasks::dynamic_call`] for the current turbo tasks instance. -pub fn dynamic_call(func: FunctionId, arg: Box, is_transient: bool) -> RawVc { - with_turbo_tasks(|tt| tt.dynamic_call(func, arg, is_transient)) +pub fn dynamic_call( + func: FunctionId, + arg: Box, + persistence: TaskPersistence, +) -> RawVc { + with_turbo_tasks(|tt| tt.dynamic_call(func, arg, persistence)) } /// Calls [`TurboTasks::dynamic_this_call`] for the current turbo tasks @@ -1485,9 +1567,9 @@ pub fn dynamic_this_call( func: FunctionId, this: RawVc, arg: Box, - is_transient: bool, + persistence: TaskPersistence, ) -> RawVc { - with_turbo_tasks(|tt| tt.dynamic_this_call(func, this, arg, is_transient)) + with_turbo_tasks(|tt| tt.dynamic_this_call(func, this, arg, persistence)) } /// Calls [`TurboTasks::trait_call`] for the current turbo tasks instance. @@ -1496,9 +1578,9 @@ pub fn trait_call( trait_fn_name: Cow<'static, str>, this: RawVc, arg: Box, - is_transient: bool, + persistence: TaskPersistence, ) -> RawVc { - with_turbo_tasks(|tt| tt.trait_call(trait_type, trait_fn_name, this, arg, is_transient)) + with_turbo_tasks(|tt| tt.trait_call(trait_type, trait_fn_name, this, arg, persistence)) } pub fn turbo_tasks() -> Arc {