Skip to content

Commit

Permalink
Merge pull request #499 from camelid/input-mut
Browse files Browse the repository at this point in the history
book: Creating inputs no longer requires `&mut dyn Db`
  • Loading branch information
nikomatsakis authored Jun 18, 2024
2 parents 56eb9c2 + 5b99535 commit 2c7cda5
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 10 deletions.
11 changes: 7 additions & 4 deletions book/src/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,18 @@ pub struct ProgramFile {
```

You create an input by using the `new` method.
Because the values of input fields are stored in the database, you also give an `&mut`-reference to the database:
Because the values of input fields are stored in the database, you also give an `&`-reference to the database:

```rust
let file: ProgramFile = ProgramFile::new(
&mut db,
&db,
PathBuf::from("some_path.txt"),
String::from("fn foo() { }"),
);
```

Mutable access is not needed since creating a new input cannot affect existing tracked data in the database.

### Salsa structs are just integers

The `ProgramFile` struct generated by the `salsa::input` macro doesn't actually store any data. It's just a newtyped integer id:
Expand Down Expand Up @@ -111,7 +113,8 @@ file.data(&db)
### Writing input fields

Finally, you can also modify the value of an input field by using the setter method.
Since this is modifying the input, the setter takes an `&mut`-reference to the database:
Since this is modifying the input, and potentially invalidating data derived from it,
the setter takes an `&mut`-reference to the database:

```rust
file.set_contents(&mut db).to(String::from("fn foo() { /* add a comment */ }"));
Expand Down Expand Up @@ -140,7 +143,7 @@ The algorithm Salsa uses to decide when a tracked function needs to be re-execut
Tracked functions have to follow a particular structure:

- They must take a `&`-reference to the database as their first argument.
- Note that because this is an `&`-reference, it is not possible to create or modify inputs during a tracked function!
- Note that because this is an `&`-reference, it is not possible to modify inputs during a tracked function!
- They must take a "Salsa struct" as the second argument -- in our example, this is an input struct, but there are other kinds of Salsa structs we'll describe shortly.
- They _can_ take additional arguments, but it's faster and better if they don't.

Expand Down
4 changes: 2 additions & 2 deletions book/src/plumbing/db_lifetime.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ The reason we use a raw pointer in the struct is because instances of this struc

```rust
let mut db = MyDatabase::default();
let input = MyInput::new(&mut db, ...);
let input = MyInput::new(&db, ...);

// Revision 1:
let result1 = tracked_fn(&db, input);
Expand Down Expand Up @@ -235,4 +235,4 @@ However in some later revision R2, how
### Freeing the memory while a tracked struct remains live


### Aliases of a tracked struct
### Aliases of a tracked struct
8 changes: 4 additions & 4 deletions book/src/tutorial/ir.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ pub struct SourceProgram(salsa::Id);
```

It will also generate a method `new` that lets you create a `SourceProgram` in the database.
For an input, a `&mut db` reference is required, along with the values for each field:
For an input, a `&db` reference is required, along with the values for each field:

```rust
let source = SourceProgram::new(&mut db, "print 11 + 11".to_string());
let source = SourceProgram::new(&db, "print 11 + 11".to_string());
```

You can read the value of the field with `source.text(&db)`,
Expand Down Expand Up @@ -90,7 +90,7 @@ then subsequent parts of the computation won't need to re-execute.

Apart from the fields being immutable, the API for working with a tracked struct is quite similar to an input:

* You can create a new value by using `new`, but with a tracked struct, you only need an `&dyn` database, not `&mut` (e.g., `Program::new(&db, some_staements)`)
* You can create a new value by using `new`: e.g., `Program::new(&db, some_statements)`
* You use a getter to read the value of a field, just like with an input (e.g., `my_func.statements(db)` to read the `statements` field).
* In this case, the field is tagged as `#[return_ref]`, which means that the getter will return a `&Vec<Statement>`, instead of cloning the vector.

Expand Down Expand Up @@ -123,7 +123,7 @@ This would mean that we have to re-execute those parts of the code that depended

Apart from the fields being immutable, the API for working with a tracked struct is quite similar to an input:

* You can create a new value by using `new`, but with a tracked struct, you only need an `&dyn` database, not `&mut` (e.g., `Function::new(&db, some_name, some_args, some_body)`)
* You can create a new value by using `new`: e.g., `Function::new(&db, some_name, some_args, some_body)`
* You use a getter to read the value of a field, just like with an input (e.g., `my_func.args(db)` to read the `args` field).

### id fields
Expand Down

0 comments on commit 2c7cda5

Please sign in to comment.