From b9d748a2ae0a89e29d5b576988f2a16a94f358fd Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 6 Nov 2021 05:29:31 -0400 Subject: [PATCH] move content from rfc into book,d ocs --- book/src/SUMMARY.md | 2 ++ book/src/cycles.md | 3 +++ book/src/cycles/fallback.md | 22 ++++++++++++++++++++++ src/lib.rs | 17 +++++++++++++++-- 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 book/src/cycles.md create mode 100644 book/src/cycles/fallback.md diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index ca85cf25..10c21589 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -8,6 +8,8 @@ - [Common patterns](./common_patterns.md) - [Selection](./common_patterns/selection.md) - [On-demand (Lazy) inputs](./common_patterns/on_demand_inputs.md) +- [Cycle handling](./cycles.md) + - [Recovering via fallback](./cycles/fallback.md) # How Salsa works internally diff --git a/book/src/cycles.md b/book/src/cycles.md new file mode 100644 index 00000000..64ea5e73 --- /dev/null +++ b/book/src/cycles.md @@ -0,0 +1,3 @@ +# Cycle handling + +By default, when Salsa detects a cycle in the computation graph, Salsa will panic with a [`salsa::Cycle`] as the panic value. The [`salsa::Cycle`] structure that describes the cycle, which can be useful for diagnosing what went wrong. diff --git a/book/src/cycles/fallback.md b/book/src/cycles/fallback.md new file mode 100644 index 00000000..51afcf58 --- /dev/null +++ b/book/src/cycles/fallback.md @@ -0,0 +1,22 @@ +# Recovering via fallback + +Panicking when a cycle occurs is ok for situations where you believe a cycle is impossible. But sometimes cycles can result from illegal user input and cannot be statically prevented. In these cases, you might prefer to gracefully recover from a cycle rather than panicking the entire query. Salsa supports that with the idea of *cycle recovery*. + +To use cycle recovery, you annotate every potential participant in the cycle with a `#[salsa::recover(my_recover_fn)]` attribute. When a cycle occurs, if **all** participants have recovery information, then no panic will result. Instead, salsa will abort the execution of the cycle participants and invoke the recovery function `my_recover_fn` instead. The result of this recovery will be returned as the query result. + +The recovery function has a similar signature to a query function. It is given a reference to your database along with a `salsa::Cycle` describing the cycle that occurred; it returns the result of the query. Example: + +```rust +fn my_recover_fn( + db: &dyn MyDatabase, + cycle: &salsa::Cycle, +) -> MyResultValue +``` + +The `db` and `cycle` argument can be used to prepare a useful error message for your users. + +**Important:** Although the recovery function is given a `db` handle, you should be careful to avoid creating a cycle from within recovery or invoking queries that may be participating in the current cycle. Attempting to do so can result in inconsistent results. + +## Figuring out why recovery did not work + +If a cycle occurs and *some* of the participant queries have `#[salsa::recover]` annotations and others do not, then the query will be treated as irrecoverable and will simply panic. You can use the `Cycle::unexpected_participants` method to figure out why recovery did not succeed and add the appropriate `#[salsa::recover]` annotations. diff --git a/src/lib.rs b/src/lib.rs index f95d46f2..84fbe9b3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -645,8 +645,21 @@ impl std::fmt::Display for Cancelled { impl std::error::Error for Cancelled {} -/// Information about an "unexpected" cycle, meaning one where some of the -/// participants lacked cycle recovery annotations. +/// Captuers the participants of a cycle that occurred when executing a query. +/// +/// This type is meant to be used to help give meaningful error messages to the +/// user or to help salsa developers figure out why their program is resulting +/// in a computation cycle. +/// +/// It is used in a few ways: +/// +/// * During [cycle recovery](https://https://salsa-rs.github.io/salsa/cycles/fallback.html), +/// where it is given to the fallback function. +/// * As the panic value when an unexpected cycle (i.e., a cycle where one or more participants +/// lacks cycle recovery information) occurs. +/// +/// You can read more about cycle handling in +/// the [salsa book](https://https://salsa-rs.github.io/salsa/cycles.html). #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Cycle { participants: plumbing::CycleParticipants,