turbo_tasks/lib.rs
1//! A task scheduling and caching system that is focused on incremental
2//! execution.
3//!
4//! It defines 4 primitives:
5//! - **[Functions][macro@crate::function]:** Units of execution, invalidation, and reexecution.
6//! - **[Values][macro@crate::value]:** Data created, stored, and returned by functions.
7//! - **[Traits][macro@crate::value_trait]:** Traits that define a set of functions on values.
8//! - **[Collectibles][crate::TurboTasks::emit_collectible]:** Values emitted in functions that
9//! bubble up the call graph and can be collected in parent functions.
10//!
11//! It also defines some derived elements from that:
12//! - **[Tasks][book-tasks]:** An instance of a function together with its arguments.
13//! - **[Cells][book-cells]:** The locations associated with tasks where values are stored. The
14//! contents of a cell can change after the reexecution of a function.
15//! - **[`Vc`s ("Value Cells")][Vc]:** A reference to a cell or a return value of a function.
16//!
17//! A [`Vc`] can be read to get [a read-only reference][ReadRef] to the stored data, representing a
18//! snapshot of that cell at that point in time.
19//!
20//! On execution of functions, `turbo-tasks` will track which [`Vc`]s are read. Once any of these
21//! change, `turbo-tasks` will invalidate the task created from the function's execution and it will
22//! eventually be scheduled and reexecuted.
23//!
24//! Collectibles go through a similar process.
25//!
26//! [book-cells]: https://turbopack-rust-docs.vercel.sh/turbo-engine/cells.html
27//! [book-tasks]: https://turbopack-rust-docs.vercel.sh/turbo-engine/tasks.html
28
29#![feature(trivial_bounds)]
30#![feature(min_specialization)]
31#![feature(try_trait_v2)]
32#![deny(unsafe_op_in_unsafe_fn)]
33#![feature(error_generic_member_access)]
34#![feature(arbitrary_self_types)]
35#![feature(arbitrary_self_types_pointers)]
36#![feature(new_zeroed_alloc)]
37#![feature(never_type)]
38#![feature(downcast_unchecked)]
39#![feature(ptr_metadata)]
40#![feature(sync_unsafe_cell)]
41#![feature(vec_into_raw_parts)]
42
43pub mod backend;
44mod capture_future;
45mod collectibles;
46mod completion;
47pub mod debug;
48mod display;
49pub mod duration_span;
50mod effect;
51pub mod event;
52pub mod graph;
53mod id;
54mod id_factory;
55mod invalidation;
56mod join_iter_ext;
57mod key_value_pair;
58#[doc(hidden)]
59pub mod macro_helpers;
60mod magic_any;
61mod manager;
62mod marker_trait;
63pub mod message_queue;
64mod native_function;
65mod no_move_vec;
66mod once_map;
67mod output;
68pub mod panic_hooks;
69pub mod parallel;
70pub mod persisted_graph;
71pub mod primitives;
72mod raw_vc;
73mod read_options;
74mod read_ref;
75pub mod registry;
76pub mod scope;
77mod serialization_invalidation;
78pub mod small_duration;
79mod spawn;
80mod state;
81pub mod task;
82mod task_execution_reason;
83pub mod task_statistics;
84pub mod trace;
85mod trait_ref;
86mod triomphe_utils;
87pub mod util;
88mod value;
89mod value_type;
90mod vc;
91
92use std::hash::BuildHasherDefault;
93
94pub use anyhow::{Error, Result};
95use auto_hash_map::AutoSet;
96pub use capture_future::TurboTasksPanic;
97pub use collectibles::CollectiblesSource;
98pub use completion::{Completion, Completions};
99pub use display::ValueToString;
100pub use effect::{ApplyEffectsContext, Effects, apply_effects, effect, get_effects};
101pub use id::{
102 ExecutionId, LocalTaskId, SessionId, TRANSIENT_TASK_BIT, TaskId, TraitTypeId, ValueTypeId,
103};
104pub use invalidation::{
105 InvalidationReason, InvalidationReasonKind, InvalidationReasonSet, Invalidator, get_invalidator,
106};
107pub use join_iter_ext::{JoinIterExt, TryFlatJoinIterExt, TryJoinIterExt};
108pub use key_value_pair::KeyValuePair;
109pub use magic_any::MagicAny;
110pub use manager::{
111 CurrentCellRef, ReadConsistency, TaskPersistence, TurboTasks, TurboTasksApi,
112 TurboTasksBackendApi, TurboTasksBackendApiExt, TurboTasksCallApi, Unused, UpdateInfo,
113 dynamic_call, emit, mark_finished, mark_root, mark_session_dependent, mark_stateful,
114 prevent_gc, run_once, run_once_with_reason, trait_call, turbo_tasks, turbo_tasks_scope,
115};
116pub use output::OutputContent;
117pub use raw_vc::{CellId, RawVc, ReadRawVcFuture, ResolveTypeError};
118pub use read_options::ReadCellOptions;
119pub use read_ref::ReadRef;
120use rustc_hash::FxHasher;
121pub use serialization_invalidation::SerializationInvalidator;
122pub use shrink_to_fit::ShrinkToFit;
123pub use spawn::{
124 JoinHandle, block_for_future, block_in_place, spawn, spawn_blocking, spawn_thread,
125};
126pub use state::{State, TransientState};
127pub use task::{SharedReference, TypedSharedReference, task_input::TaskInput};
128pub use task_execution_reason::TaskExecutionReason;
129pub use trait_ref::{IntoTraitRef, TraitRef};
130pub use turbo_tasks_macros::{TaskInput, function, value_impl};
131pub use value::{TransientInstance, TransientValue};
132pub use value_type::{TraitMethod, TraitType, ValueType};
133pub use vc::{
134 Dynamic, NonLocalValue, OperationValue, OperationVc, OptionVcExt, ReadVcFuture, ResolvedVc,
135 Upcast, ValueDefault, Vc, VcCast, VcCellNewMode, VcCellSharedMode, VcDefaultRead, VcRead,
136 VcTransparentRead, VcValueTrait, VcValueTraitCast, VcValueType, VcValueTypeCast,
137};
138
139pub type SliceMap<K, V> = Box<[(K, V)]>;
140
141pub type FxIndexSet<T> = indexmap::IndexSet<T, BuildHasherDefault<FxHasher>>;
142pub type FxIndexMap<K, V> = indexmap::IndexMap<K, V, BuildHasherDefault<FxHasher>>;
143pub type FxDashMap<K, V> = dashmap::DashMap<K, V, BuildHasherDefault<FxHasher>>;
144
145// Copied from indexmap! and indexset!
146#[macro_export]
147macro_rules! fxindexmap {
148 (@single $($x:tt)*) => (());
149 (@count $($rest:expr),*) => (<[()]>::len(&[$($crate::fxindexmap!(@single $rest)),*]));
150
151 ($($key:expr => $value:expr,)+) => { $crate::fxindexmap!($($key => $value),+) };
152 ($($key:expr => $value:expr),*) => {
153 {
154 let _cap = $crate::fxindexmap!(@count $($key),*);
155 let mut _map = $crate::FxIndexMap::with_capacity_and_hasher(_cap, Default::default());
156 $(
157 _map.insert($key, $value);
158 )*
159 _map
160 }
161 };
162}
163#[macro_export]
164macro_rules! fxindexset {
165 (@single $($x:tt)*) => (());
166 (@count $($rest:expr),*) => (<[()]>::len(&[$($crate::fxindexset!(@single $rest)),*]));
167
168 ($($value:expr,)+) => { $crate::fxindexset!($($value),+) };
169 ($($value:expr),*) => {
170 {
171 let _cap = $crate::fxindexset!(@count $($value),*);
172 let mut _set = $crate::FxIndexSet::with_capacity_and_hasher(_cap, Default::default());
173 $(
174 _set.insert($value);
175 )*
176 _set
177 }
178 };
179}
180
181/// Implements [`VcValueType`] for the given `struct` or `enum`. These value types can be used
182/// inside of a "value cell" as [`Vc<...>`][Vc].
183///
184/// A [`Vc`] represents a (potentially lazy) memoized computation. Each [`Vc`]'s value is placed
185/// into a cell associated with the current [`TaskId`]. That [`Vc`] object can be `await`ed to get
186/// [a read-only reference to the value contained in the cell][ReadRef].
187///
188/// This macro accepts multiple comma-separated arguments. For example:
189///
190/// ```
191/// # #![feature(arbitrary_self_types)]
192// # #![feature(arbitrary_self_types_pointers)]
193/// #[turbo_tasks::value(transparent, into = "shared")]
194/// struct Foo(Vec<u32>);
195/// ```
196///
197/// ## `cell = "..."`
198///
199/// Controls when a cell is invalidated upon recomputation of a task. Internally, this is performed
200/// by setting the [`VcValueType::CellMode`] associated type.
201///
202/// - **`"new"`:** Always overrides the value in the cell, invalidating all dependent tasks.
203/// - **`"shared"` *(default)*:** Compares with the existing value in the cell, before overriding it.
204/// Requires the value to implement [`Eq`].
205///
206/// Avoiding unnecessary invalidation is important to reduce downstream recomputation of tasks that
207/// depend on this cell's value.
208///
209/// Use `"new"` only if a correct implementation of [`Eq`] is not possible, would be expensive (e.g.
210/// would require comparing a large collection), or if you're implementing a low-level primitive
211/// that intentionally forces recomputation.
212///
213/// ## `eq = "..."`
214///
215/// By default, we `#[derive(PartialEq, Eq)]`. [`Eq`] is required by `cell = "shared"`. This
216/// argument allows overriding that default implementation behavior.
217///
218/// - **`"manual"`:** Prevents deriving [`Eq`] and [`PartialEq`] so you can do it manually.
219///
220/// ## `into = "..."`
221///
222/// This macro always implements a `.cell()` method on your type with the signature:
223///
224/// ```ignore
225/// /// Wraps the value in a cell.
226/// fn cell(self) -> Vc<Self>;
227/// ```
228///
229/// This argument controls the visibility of the `.cell()` method, as well as whether a
230/// [`From<T> for Vc<T>`][From] implementation is generated.
231///
232/// - **`"new"` or `"shared"`:** Exposes both `.cell()` and [`From`]/[`Into`] implementations. Both
233/// of these values (`"new"` or `"shared"`) do the same thing (for legacy reasons).
234/// - **`"none"` *(default)*:** Makes `.cell()` private and prevents implementing [`From`]/[`Into`].
235///
236/// You should use the default value of `"none"` when providing your own public constructor methods.
237///
238/// The naming of this field and it's values are due to legacy reasons.
239///
240/// ## `serialization = "..."`
241///
242/// Affects serialization via [`serde::Serialize`] and [`serde::Deserialize`]. Serialization is
243/// required for persistent caching of tasks to disk.
244///
245/// - **`"auto"` *(default)*:** Derives the serialization traits and enables serialization.
246/// - **`"custom"`:** Prevents deriving the serialization traits, but still enables serialization
247/// (you must manually implement [`serde::Serialize`] and [`serde::Deserialize`]).
248/// - **`"none"`:** Disables serialization and prevents deriving the traits.
249///
250/// ## `shared`
251///
252/// Sets both `cell = "shared"` *(already the default)* and `into = "shared"`, exposing the
253/// `.cell()` method and adding a [`From`]/[`Into`] implementation.
254///
255/// ## `transparent`
256///
257/// This attribute is only valid on single-element unit structs. When this value is set:
258///
259/// 1. The struct will use [`#[repr(transparent)]`][repr-transparent].
260/// 1. Read operations (`vc.await?`) return a [`ReadRef`] containing the inner type, rather than the
261/// outer struct. Internally, this is accomplished using [`VcTransparentRead`] for the
262/// [`VcValueType::Read`] associated type.
263/// 1. Construction of the type must be performed using [`Vc::cell(inner)`][Vc::cell], rather than
264/// using the `.cell()` method on the outer type (`outer.cell()`).
265/// 1. The [`ValueDebug`][crate::debug::ValueDebug] implementation will defer to the inner type.
266///
267/// This is commonly used to create [`VcValueType`] wrappers for foreign or generic types, such as
268/// [`Vec`] or [`Option`].
269///
270/// [repr-transparent]: https://doc.rust-lang.org/nomicon/other-reprs.html#reprtransparent
271///
272/// ## `local`
273///
274/// Skip the implementation of [`NonLocalValue`] for this type.
275///
276/// If not specified, we apply the [`#[derive(NonLocalValue)]`][macro@NonLocalValue] macro, which
277/// asserts that this struct has no fields containing [`Vc`] by implementing the [`NonLocalValue`]
278/// marker trait. Compile-time assertions are generated on every field, checking that they are also
279/// [`NonLocalValue`]s.
280#[rustfmt::skip]
281pub use turbo_tasks_macros::value;
282
283/// Allows this trait to be used as part of a trait object inside of a value
284/// cell, in the form of `Vc<dyn MyTrait>`.
285///
286/// ## Arguments
287///
288/// Example: `#[turbo_tasks::value_trait(no_debug, resolved)]`
289///
290/// ### 'no_debug`
291///
292/// Disables the automatic implementation of [`ValueDebug`][crate::debug::ValueDebug].
293///
294/// Example: `#[turbo_tasks::value_trait(no_debug)]`
295///
296/// ### 'resolved`
297///
298/// Adds [`NonLocalValue`] as a supertrait of this trait.
299///
300/// Example: `#[turbo_tasks::value_trait(resolved)]`
301#[rustfmt::skip]
302pub use turbo_tasks_macros::value_trait;
303
304pub type TaskIdSet = AutoSet<TaskId, BuildHasherDefault<FxHasher>, 2>;
305
306pub mod test_helpers {
307 pub use super::manager::{current_task_for_testing, with_turbo_tasks_for_testing};
308}
309
310pub fn register() {
311 include!(concat!(env!("OUT_DIR"), "/register.rs"));
312}