Mercurial > public > mercurial-scm > hg
annotate rust/rhg/src/commands/debugrequirements.rs @ 49000:dd6b67d5c256 stable
rust: fix unsound `OwningDirstateMap`
As per the previous patch, `OwningDirstateMap` is unsound. Self-referential
structs are difficult to implement correctly in Rust since the compiler is
free to move structs around as much as it wants to. They are also very rarely
needed in practice, so the state-of-the-art on how they should be done within
the Rust rules is still a bit new.
The crate `ouroboros` is an attempt at providing a safe way (in the Rust sense)
of declaring self-referential structs. It is getting a lot attention and was
improved very quickly when soundness issues were found in the past: rather than
relying on our own (limited) review circle, we might as well use the de-facto
common crate to fix this problem. This will give us a much better chance of
finding issues should any new ones be discovered as well as the benefit of
fewer `unsafe` APIs of our own.
I was starting to think about how I would present a safe API to the old struct
but soon realized that the callback-based approach was already done in
`ouroboros`, along with a lot more care towards refusing incorrect structs.
In short: we don't return a mutable reference to the `DirstateMap` anymore, we
expect users of its API to pass a `FnOnce` that takes the map as an argument.
This allows our `OwningDirstateMap` to control the input and output lifetimes
of the code that modifies it to prevent such issues.
Changing to `ouroboros` meant changing every API with it, but it is relatively
low churn in the end. It correctly identified the example buggy modification of
`copy_map_insert` outlined in the previous patch as violating the borrow rules.
Differential Revision: https://phab.mercurial-scm.org/D12429
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Tue, 05 Apr 2022 10:55:28 +0200 |
parents | 5ce2aa7c2ad5 |
children | 37bc3edef76f |
rev | line source |
---|---|
45924
a2eda1ff22aa
requirements: move loading to hg-core and add parsing
Simon Sapin <simon-commits@exyr.org>
parents:
45923
diff
changeset
|
1 use crate::error::CommandError; |
45923
ead435aa5294
rhg: add a `debugrequirements` subcommand
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
2 |
ead435aa5294
rhg: add a `debugrequirements` subcommand
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
3 pub const HELP_TEXT: &str = " |
ead435aa5294
rhg: add a `debugrequirements` subcommand
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
4 Print the current repo requirements. |
ead435aa5294
rhg: add a `debugrequirements` subcommand
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
5 "; |
ead435aa5294
rhg: add a `debugrequirements` subcommand
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
6 |
46501
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
7 pub fn args() -> clap::App<'static, 'static> { |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
8 clap::SubCommand::with_name("debugrequirements").about(HELP_TEXT) |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
9 } |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
10 |
46592
80840b651721
rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
11 pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> { |
46593
5ce2aa7c2ad5
rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents:
46592
diff
changeset
|
12 let repo = invocation.repo?; |
46500
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
13 let mut output = String::new(); |
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
14 let mut requirements: Vec<_> = repo.requirements().iter().collect(); |
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
15 requirements.sort(); |
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
16 for req in requirements { |
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
17 output.push_str(req); |
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
18 output.push('\n'); |
45923
ead435aa5294
rhg: add a `debugrequirements` subcommand
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
19 } |
46592
80840b651721
rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
20 invocation.ui.write_stdout(output.as_bytes())?; |
46500
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
21 Ok(()) |
45923
ead435aa5294
rhg: add a `debugrequirements` subcommand
Simon Sapin <simon-commits@exyr.org>
parents:
diff
changeset
|
22 } |