move content from rfc into book,d ocs

This commit is contained in:
Niko Matsakis 2021-11-06 05:29:31 -04:00
parent cc2f8870c1
commit b9d748a2ae
4 changed files with 42 additions and 2 deletions

View file

@ -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

3
book/src/cycles.md Normal file
View file

@ -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.

View file

@ -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.

View file

@ -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,