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(thread_local)]
32#![feature(try_trait_v2)]
33#![deny(unsafe_op_in_unsafe_fn)]
34#![feature(result_flattening)]
35#![feature(error_generic_member_access)]
36#![feature(arbitrary_self_types)]
37#![feature(arbitrary_self_types_pointers)]
38#![feature(new_zeroed_alloc)]
39#![feature(never_type)]
40#![feature(downcast_unchecked)]
41
42pub mod backend;
43mod capture_future;
44mod collectibles;
45mod completion;
46pub mod debug;
47mod display;
48pub mod duration_span;
49mod effect;
50pub mod event;
51pub mod graph;
52mod id;
53mod id_factory;
54mod invalidation;
55mod join_iter_ext;
56mod key_value_pair;
57#[doc(hidden)]
58pub mod macro_helpers;
59mod magic_any;
60mod manager;
61mod marker_trait;
62pub mod message_queue;
63mod native_function;
64mod no_move_vec;
65mod once_map;
66mod output;
67pub mod persisted_graph;
68pub mod primitives;
69mod raw_vc;
70mod read_options;
71mod read_ref;
72pub mod registry;
73mod scope;
74mod serialization_invalidation;
75pub mod small_duration;
76mod state;
77pub mod task;
78pub mod task_statistics;
79pub mod trace;
80mod trait_helpers;
81mod trait_ref;
82mod triomphe_utils;
83pub mod util;
84mod value;
85mod value_type;
86mod vc;
87
88use std::{cell::RefCell, hash::BuildHasherDefault, panic};
89
90pub use anyhow::{Error, Result};
91use auto_hash_map::AutoSet;
92pub use capture_future::TurboTasksPanic;
93pub use collectibles::CollectiblesSource;
94pub use completion::{Completion, Completions};
95pub use display::ValueToString;
96pub use effect::{ApplyEffectsContext, Effects, apply_effects, effect, get_effects};
97pub use id::{
98    ExecutionId, FunctionId, LocalTaskId, SessionId, TRANSIENT_TASK_BIT, TaskId, TraitTypeId,
99    ValueTypeId,
100};
101pub use invalidation::{
102    DynamicEqHash, InvalidationReason, InvalidationReasonKind, InvalidationReasonSet, Invalidator,
103    get_invalidator,
104};
105pub use join_iter_ext::{JoinIterExt, TryFlatJoinIterExt, TryJoinIterExt};
106pub use key_value_pair::KeyValuePair;
107pub use magic_any::MagicAny;
108pub use manager::{
109    CurrentCellRef, ReadConsistency, TaskPersistence, TurboTasks, TurboTasksApi,
110    TurboTasksBackendApi, TurboTasksBackendApiExt, TurboTasksCallApi, Unused, UpdateInfo,
111    dynamic_call, emit, mark_finished, mark_root, mark_session_dependent, mark_stateful,
112    prevent_gc, run_once, run_once_with_reason, spawn_blocking, spawn_thread, trait_call,
113    turbo_tasks, turbo_tasks_scope,
114};
115pub use output::OutputContent;
116pub use raw_vc::{CellId, RawVc, ReadRawVcFuture, ResolveTypeError};
117pub use read_options::ReadCellOptions;
118pub use read_ref::ReadRef;
119use rustc_hash::FxHasher;
120pub use scope::scope;
121pub use serialization_invalidation::SerializationInvalidator;
122pub use shrink_to_fit::ShrinkToFit;
123pub use state::{State, TransientState};
124pub use task::{SharedReference, TypedSharedReference, task_input::TaskInput};
125pub use trait_ref::{IntoTraitRef, TraitRef};
126pub use turbo_tasks_macros::{TaskInput, function, value_impl};
127pub use value::{TransientInstance, TransientValue, Value};
128pub use value_type::{TraitMethod, TraitType, ValueType};
129pub use vc::{
130    Dynamic, NonLocalValue, OperationValue, OperationVc, OptionVcExt, ReadVcFuture, ResolvedVc,
131    TypedForInput, Upcast, ValueDefault, Vc, VcCast, VcCellNewMode, VcCellSharedMode,
132    VcDefaultRead, VcRead, VcTransparentRead, VcValueTrait, VcValueTraitCast, VcValueType,
133    VcValueTypeCast,
134};
135
136pub type SliceMap<K, V> = Box<[(K, V)]>;
137
138pub type FxIndexSet<T> = indexmap::IndexSet<T, BuildHasherDefault<FxHasher>>;
139pub type FxIndexMap<K, V> = indexmap::IndexMap<K, V, BuildHasherDefault<FxHasher>>;
140pub type FxDashMap<K, V> = dashmap::DashMap<K, V, BuildHasherDefault<FxHasher>>;
141
142// Copied from indexmap! and indexset!
143#[macro_export]
144macro_rules! fxindexmap {
145    (@single $($x:tt)*) => (());
146    (@count $($rest:expr),*) => (<[()]>::len(&[$($crate::fxindexmap!(@single $rest)),*]));
147
148    ($($key:expr => $value:expr,)+) => { $crate::fxindexmap!($($key => $value),+) };
149    ($($key:expr => $value:expr),*) => {
150        {
151            let _cap = $crate::fxindexmap!(@count $($key),*);
152            let mut _map = $crate::FxIndexMap::with_capacity_and_hasher(_cap, Default::default());
153            $(
154                _map.insert($key, $value);
155            )*
156            _map
157        }
158    };
159}
160#[macro_export]
161macro_rules! fxindexset {
162    (@single $($x:tt)*) => (());
163    (@count $($rest:expr),*) => (<[()]>::len(&[$($crate::fxindexset!(@single $rest)),*]));
164
165    ($($value:expr,)+) => { $crate::fxindexset!($($value),+) };
166    ($($value:expr),*) => {
167        {
168            let _cap = $crate::fxindexset!(@count $($value),*);
169            let mut _set = $crate::FxIndexSet::with_capacity_and_hasher(_cap, Default::default());
170            $(
171                _set.insert($value);
172            )*
173            _set
174        }
175    };
176}
177
178/// Implements [`VcValueType`] for the given `struct` or `enum`. These value types can be used
179/// inside of a "value cell" as [`Vc<...>`][Vc].
180///
181/// A [`Vc`] represents a (potentially lazy) memoized computation. Each [`Vc`]'s value is placed
182/// into a cell associated with the current [`TaskId`]. That [`Vc`] object can be `await`ed to get
183/// [a read-only reference to the value contained in the cell][ReadRef].
184///
185/// This macro accepts multiple comma-separated arguments. For example:
186///
187/// ```
188/// # #![feature(arbitrary_self_types)]
189//  # #![feature(arbitrary_self_types_pointers)]
190/// #[turbo_tasks::value(transparent, into = "shared")]
191/// struct Foo(Vec<u32>);
192/// ```
193///
194/// ## `cell = "..."`
195///
196/// Controls when a cell is invalidated upon recomputation of a task. Internally, this is performed
197/// by setting the [`VcValueType::CellMode`] associated type.
198///
199/// - **`"new"`:** Always overrides the value in the cell, invalidating all dependent tasks.
200/// - **`"shared"` *(default)*:** Compares with the existing value in the cell, before overriding it.
201///   Requires the value to implement [`Eq`].
202///
203/// Avoiding unnecessary invalidation is important to reduce downstream recomputation of tasks that
204/// depend on this cell's value.
205///
206/// Use `"new"` only if a correct implementation of [`Eq`] is not possible, would be expensive (e.g.
207/// would require comparing a large collection), or if you're implementing a low-level primitive
208/// that intentionally forces recomputation.
209///
210/// ## `eq = "..."`
211///
212/// By default, we `#[derive(PartialEq, Eq)]`. [`Eq`] is required by `cell = "shared"`. This
213/// argument allows overriding that default implementation behavior.
214///
215/// - **`"manual"`:** Prevents deriving [`Eq`] and [`PartialEq`] so you can do it manually.
216///
217/// ## `into = "..."`
218///
219/// This macro always implements a `.cell()` method on your type with the signature:
220///
221/// ```ignore
222/// /// Wraps the value in a cell.
223/// fn cell(self) -> Vc<Self>;
224/// ```
225///
226/// This argument controls the visibility of the `.cell()` method, as well as whether a
227/// [`From<T> for Vc<T>`][From] implementation is generated.
228///
229/// - **`"new"` or `"shared"`:** Exposes both `.cell()` and [`From`]/[`Into`] implementations. Both
230///   of these values (`"new"` or `"shared"`) do the same thing (for legacy reasons).
231/// - **`"none"` *(default)*:** Makes `.cell()` private and prevents implementing [`From`]/[`Into`].
232///
233/// You should use the default value of `"none"` when providing your own public constructor methods.
234///
235/// The naming of this field and it's values are due to legacy reasons.
236///
237/// ## `serialization = "..."`
238///
239/// Affects serialization via [`serde::Serialize`] and [`serde::Deserialize`]. Serialization is
240/// required for persistent caching of tasks to disk.
241///
242/// - **`"auto"` *(default)*:** Derives the serialization traits and enables serialization.
243/// - **`"auto_for_input"`:** Same as `"auto"`, but also adds the marker trait [`TypedForInput`].
244/// - **`"custom"`:** Prevents deriving the serialization traits, but still enables serialization
245///   (you must manually implement [`serde::Serialize`] and [`serde::Deserialize`]).
246/// - **`"custom_for_input"`:** Same as `"custom"`, but also adds the marker trait
247///   [`TypedForInput`].
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
310thread_local! {
311    /// The location of the last error that occurred in the current thread.
312    ///
313    /// Used for debugging when errors are sent to telemetry
314    pub(crate) static LAST_ERROR_LOCATION: RefCell<Option<String>> = const { RefCell::new(None) };
315}
316
317pub fn handle_panic(info: &panic::PanicHookInfo<'_>) {
318    LAST_ERROR_LOCATION.with_borrow_mut(|loc| {
319        *loc = info.location().map(|l| l.to_string());
320    });
321}
322
323pub fn register() {
324    include!(concat!(env!("OUT_DIR"), "/register.rs"));
325}