Skip to content

Commit

Permalink
Introduce basic usage of Miri in the unsafe chapter
Browse files Browse the repository at this point in the history
  • Loading branch information
chriskrycho committed Oct 4, 2024
1 parent 2be08c8 commit 5ab364f
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 0 deletions.
14 changes: 14 additions & 0 deletions listings/ch20-advanced-features/listing-20-10/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
$ cargo +nightly miri run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01s
Running `/Users/chris/.rustup/toolchains/nightly-aarch64-apple-darwin/bin/cargo-miri runner target/miri/aarch64-apple-darwin/debug/unsafe-example`
warning: creating a shared reference to mutable static is discouraged
--> src/main.rs:14:33
|
14 | println!("COUNTER: {}", COUNTER);
| ^^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: `#[warn(static_mut_refs)]` on by default

COUNTER: 3
45 changes: 45 additions & 0 deletions src/ch20-01-unsafe-rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -451,13 +451,56 @@ interface with unions in C code. Accessing union fields is unsafe because Rust
cant guarantee the type of the data currently being stored in the union
instance. You can learn more about unions in [the Rust Reference][reference].
### Using Miri to check unsafe code
When writing unsafe code, you might want to check that what you have written
actually is safe and correct. One of the best ways to do that is to use
[Miri][miri], an official Rust tool for detecting undefined behavior. Whereas
the borrow checker is a *static* tool which works at compile time, Miri is a
*dynamic* tool which works at runtime. It checks your code by running your
program, or its test suite, and detecting when you violate the rules its
understands about how Rust should work.
Using Miri requires a nightly build of Rust (which we talk about more in
[Appendix G: How Rust is Made and “Nightly Rust”][nightly]). You can install
both a nightly version of Rust and the Miri tool by typing `rustup +nightly
component add miri`. This does not change what version of Rust your project
uses; it only adds the tool to your system so you can use it when you want to.
You can run Miri on a project by typing `cargo +nightly miri run` or `cargo
+nightly miri test`.
For an example of how helpful this can be, consider what happens when we run it
against Listing 20-10:
```console
{{#include ../listings/ch20-advanced-features/listing-20-10/output.txt}}
```
It helpfully and correctly notices that we have shared references to mutable
data, and warns about it. In this case, it does not tell us how to fix the
problem, but it means that we know there is a possible issue and can think about
how to make sure it is safe. In other cases, it can actually tell us that some
code is *sure* to be wrong and make recommendations about how to fix it.
Miri doesn’t catch *everything* you might get wrong when writing unsafe code.
For one thing, since it is a dynamic check, it only catches problems with code
that actually gets run. That means you will need to use it in conjunction with
good testing techniques to increase your confidence about the unsafe code you
have written. For another thing, it does not cover every possible way your code
can be unsound. If Miri *does* catch a problem, you know there’s a bug, but just
because Miri *doesn’t* catch a bug doesn’t mean there isn’t a problem! Miri can
catch a lot, though. Try running it on the other examples of unsafe code in this
chapter and see what it says.
### When to Use Unsafe Code
Using `unsafe` to take one of the five actions (superpowers) just discussed
isn’t wrong or even frowned upon. But it is trickier to get `unsafe` code
correct because the compiler can’t help uphold memory safety. When you have a
reason to use `unsafe` code, you can do so, and having the explicit `unsafe`
annotation makes it easier to track down the source of problems when they occur.
Whenever you write unsafe code, you can use Miri to help you be more confident
that the code you have written upholds Rust’s rules.
[dangling-references]:
ch04-02-references-and-borrowing.html#dangling-references
Expand All @@ -467,3 +510,5 @@ ch03-01-variables-and-mutability.html#constants
ch16-04-extensible-concurrency-sync-and-send.html#extensible-concurrency-with-the-sync-and-send-traits
[the-slice-type]: ch04-03-slices.html#the-slice-type
[reference]: ../reference/items/unions.html
[miri]: https://github.com/rust-lang/miri
[nightly]: appendix-07-nightly-rust.html

0 comments on commit 5ab364f

Please sign in to comment.