minor edits
This commit is contained in:
parent
4e34e79914
commit
e7e1a20983
|
|
@ -4,14 +4,14 @@
|
||||||
|
|
||||||
This chapter is based on the explanation given by Niko Matsakis in this
|
This chapter is based on the explanation given by Niko Matsakis in this
|
||||||
[video](https://www.youtube.com/watch?v=_muY4HjSqVw) about
|
[video](https://www.youtube.com/watch?v=_muY4HjSqVw) about
|
||||||
[`Salsa`](https://github.com/salsa-rs/salsa). To find out more you may
|
[Salsa](https://github.com/salsa-rs/salsa). To find out more you may
|
||||||
want to watch [`Salsa` In More
|
want to watch [Salsa In More
|
||||||
Depth](https://www.youtube.com/watch?v=i_IhACacPRY), also by Niko
|
Depth](https://www.youtube.com/watch?v=i_IhACacPRY), also by Niko
|
||||||
Matsakis.
|
Matsakis.
|
||||||
|
|
||||||
> As of <!-- date-check --> November 2022, although `Salsa` is inspired by (among
|
> As of <!-- date-check --> November 2022, although Salsa is inspired by (among
|
||||||
> other things) `rustc`'s query system, it is not used directly in `rustc`. It
|
> other things) rustc's query system, it is not used directly in rustc. It
|
||||||
> _is_ used in [chalk], an implementation of Rust's `trait` system, and
|
> _is_ used in [chalk], an implementation of Rust's trait system, and
|
||||||
> extensively in [`rust-analyzer`], the official implementation of the language
|
> extensively in [`rust-analyzer`], the official implementation of the language
|
||||||
> server protocol for Rust, but there are no medium or long-term concrete
|
> server protocol for Rust, but there are no medium or long-term concrete
|
||||||
> plans to integrate it into the compiler.
|
> plans to integrate it into the compiler.
|
||||||
|
|
@ -21,18 +21,18 @@ Matsakis.
|
||||||
|
|
||||||
## What is Salsa?
|
## What is Salsa?
|
||||||
|
|
||||||
`Salsa` is a library for incremental recomputation. This means it allows reusing
|
Salsa is a library for incremental recomputation. This means it allows reusing
|
||||||
computations that were already done in the past to increase the efficiency
|
computations that were already done in the past to increase the efficiency
|
||||||
of future computations.
|
of future computations.
|
||||||
|
|
||||||
The objectives of `Salsa` are:
|
The objectives of Salsa are:
|
||||||
* Provide that functionality in an automatic way, so reusing old computations
|
* Provide that functionality in an automatic way, so reusing old computations
|
||||||
is done automatically by the library.
|
is done automatically by the library.
|
||||||
* Doing so in a "sound", or "correct", way, therefore leading to the same
|
* Doing so in a "sound", or "correct", way, therefore leading to the same
|
||||||
results as if it had been done from scratch.
|
results as if it had been done from scratch.
|
||||||
|
|
||||||
`Salsa`'s actual model is much richer, allowing many kinds of inputs and many
|
Salsa's actual model is much richer, allowing many kinds of inputs and many different outputs.
|
||||||
different outputs. For example, integrating `Salsa` with an IDE could mean that
|
For example, integrating Salsa with an IDE could mean that
|
||||||
the inputs could be manifests (`Cargo.toml`, `rust-toolchain.toml`), entire
|
the inputs could be manifests (`Cargo.toml`, `rust-toolchain.toml`), entire
|
||||||
source files (`foo.rs`), snippets and so on. The outputs of such an integration
|
source files (`foo.rs`), snippets and so on. The outputs of such an integration
|
||||||
could range from a binary executable, to lints, types (for example, if a user
|
could range from a binary executable, to lints, types (for example, if a user
|
||||||
|
|
@ -40,10 +40,10 @@ selects a certain variable and wishes to see its type), completions, etc.
|
||||||
|
|
||||||
## How does it work?
|
## How does it work?
|
||||||
|
|
||||||
The first thing that `Salsa` has to do is identify the "base inputs" that
|
The first thing that Salsa has to do is identify the "base inputs" that
|
||||||
are not something computed but given as input.
|
are not something computed but given as input.
|
||||||
|
|
||||||
Then `Salsa` has to also identify intermediate, "derived" values, which are
|
Then Salsa has to also identify intermediate, "derived" values, which are
|
||||||
something that the library produces, but, for each derived value there's a
|
something that the library produces, but, for each derived value there's a
|
||||||
"pure" function that computes the derived value.
|
"pure" function that computes the derived value.
|
||||||
|
|
||||||
|
|
@ -51,16 +51,16 @@ For example, there might be a function `ast(x: Path) -> AST`. The produced
|
||||||
Abstract Syntax Tree (`AST`) isn't a final value, it's an intermediate value
|
Abstract Syntax Tree (`AST`) isn't a final value, it's an intermediate value
|
||||||
that the library would use for the computation.
|
that the library would use for the computation.
|
||||||
|
|
||||||
This means that when you try to compute with the library, `Salsa` is going to
|
This means that when you try to compute with the library, Salsa is going to
|
||||||
compute various derived values, and eventually read the input and produce the
|
compute various derived values, and eventually read the input and produce the
|
||||||
result for the asked computation.
|
result for the asked computation.
|
||||||
|
|
||||||
In the course of computing, `Salsa` tracks which inputs were accessed and which
|
In the course of computing, Salsa tracks which inputs were accessed and which
|
||||||
values are derived. This information is used to determine what's going to
|
values are derived. This information is used to determine what's going to
|
||||||
happen when the inputs change: are the derived values still valid?
|
happen when the inputs change: are the derived values still valid?
|
||||||
|
|
||||||
This doesn't necessarily mean that each computation downstream from the input
|
This doesn't necessarily mean that each computation downstream from the input
|
||||||
is going to be checked, which could be costly. `Salsa` only needs to check each
|
is going to be checked, which could be costly. Salsa only needs to check each
|
||||||
downstream computation until it finds one that isn't changed. At that point, it
|
downstream computation until it finds one that isn't changed. At that point, it
|
||||||
won't check other derived computations since they wouldn't need to change.
|
won't check other derived computations since they wouldn't need to change.
|
||||||
|
|
||||||
|
|
@ -76,7 +76,7 @@ J <- B <--+
|
||||||
|
|
||||||
When an input `I` changes, the derived value `A` could change. The derived
|
When an input `I` changes, the derived value `A` could change. The derived
|
||||||
value `B`, which does not depend on `I`, `A`, or any value derived from `A` or
|
value `B`, which does not depend on `I`, `A`, or any value derived from `A` or
|
||||||
`I`, is not subject to change. Therefore, `Salsa` can reuse the computation done
|
`I`, is not subject to change. Therefore, Salsa can reuse the computation done
|
||||||
for `B` in the past, without having to compute it again.
|
for `B` in the past, without having to compute it again.
|
||||||
|
|
||||||
The computation could also terminate early. Keeping the same graph as before,
|
The computation could also terminate early. Keeping the same graph as before,
|
||||||
|
|
@ -86,18 +86,18 @@ computation. This leads to an "early termination", because there's no need to
|
||||||
check if `C` needs to change, since both `C` direct inputs, `A` and `B`,
|
check if `C` needs to change, since both `C` direct inputs, `A` and `B`,
|
||||||
haven't changed.
|
haven't changed.
|
||||||
|
|
||||||
## Key `Salsa` concepts
|
## Key Salsa concepts
|
||||||
|
|
||||||
### Query
|
### Query
|
||||||
|
|
||||||
A query is some value that `Salsa` can access in the course of computation. Each
|
A query is some value that Salsa can access in the course of computation. Each
|
||||||
query can have a number of keys (from 0 to many), and all queries have a
|
query can have a number of keys (from 0 to many), and all queries have a
|
||||||
result, akin to functions. `0-key` queries are called "input" queries.
|
result, akin to functions. `0-key` queries are called "input" queries.
|
||||||
|
|
||||||
### Database
|
### Database
|
||||||
|
|
||||||
The database is basically the context for the entire computation, it's meant to
|
The database is basically the context for the entire computation, it's meant to
|
||||||
store `Salsa`'s internal state, all intermediate values for each query, and
|
store Salsa's internal state, all intermediate values for each query, and
|
||||||
anything else that the computation might need. The database must know all the
|
anything else that the computation might need. The database must know all the
|
||||||
queries the library is going to do before it can be built, but they don't need
|
queries the library is going to do before it can be built, but they don't need
|
||||||
to be specified in the same place.
|
to be specified in the same place.
|
||||||
|
|
@ -116,14 +116,14 @@ potentially invalidated.
|
||||||
|
|
||||||
A query group is a set of queries which have been defined together as a unit.
|
A query group is a set of queries which have been defined together as a unit.
|
||||||
The database is formed by combining query groups. Query groups are akin to
|
The database is formed by combining query groups. Query groups are akin to
|
||||||
"`Salsa` modules".
|
"Salsa modules".
|
||||||
|
|
||||||
A set of queries in a query group are just a set of methods in a `trait`.
|
A set of queries in a query group are just a set of methods in a trait.
|
||||||
|
|
||||||
To create a query group a `trait` annotated with a specific attribute
|
To create a query group a trait annotated with a specific attribute
|
||||||
(`#[salsa::query_group(...)]`) has to be created.
|
(`#[salsa::query_group(...)]`) has to be created.
|
||||||
|
|
||||||
An argument must also be provided to said attribute as it will be used by `Salsa`
|
An argument must also be provided to said attribute as it will be used by Salsa
|
||||||
to create a `struct` to be used later when the database is created.
|
to create a `struct` to be used later when the database is created.
|
||||||
|
|
||||||
Example input query group:
|
Example input query group:
|
||||||
|
|
@ -166,7 +166,7 @@ pub trait Parser: Inputs {
|
||||||
|
|
||||||
When creating a derived query the implementation of said query must be defined
|
When creating a derived query the implementation of said query must be defined
|
||||||
outside the trait. The definition must take a database parameter as an `impl
|
outside the trait. The definition must take a database parameter as an `impl
|
||||||
Trait` (or `dyn Trait`), where `Trait` is the query group that the definition
|
Trait` (or `dyn Trait`), where trait is the query group that the definition
|
||||||
belongs to, in addition to the other keys.
|
belongs to, in addition to the other keys.
|
||||||
|
|
||||||
```rust,ignore
|
```rust,ignore
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue