You've already forked comprehensive-rust
mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-06-17 14:47:35 +02:00
Rework example to compare to UB in C
This commit is contained in:
@ -20,14 +20,19 @@ fn main() {
|
|||||||
We can also look at a case where these rules prevent incorrect optimizations:
|
We can also look at a case where these rules prevent incorrect optimizations:
|
||||||
|
|
||||||
```rust,editable,compile_fail
|
```rust,editable,compile_fail
|
||||||
fn sum_and_zero(a: &mut i32, b: &mut i32) {
|
fn swap_and_increment(a: &mut i32, b: &mut i32) {
|
||||||
*a = *a + *b;
|
*a = *a + 1;
|
||||||
*b = 0;
|
|
||||||
|
let tmp = *a;
|
||||||
|
*a = *b;
|
||||||
|
*b = tmp;
|
||||||
|
|
||||||
|
*b = *a + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut x = 5;
|
let mut x = 1;
|
||||||
sum_and_zero(&mut x, &mut x);
|
swap_and_increment(&mut x, &mut x);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -37,16 +42,28 @@ fn main() {
|
|||||||
can potentially invalidate existing references to the collection's elements if
|
can potentially invalidate existing references to the collection's elements if
|
||||||
the collection has to reallocate.
|
the collection has to reallocate.
|
||||||
|
|
||||||
- In the second case, the aliasing rule prevents mis-compilation: The output of
|
- In the second case, the aliasing rule prevents mis-compilation: In the C
|
||||||
`sum_and_zero` depends on the ordering of the two operations, which means if
|
equivalent of this function, the program produces different results when
|
||||||
the compiler swaps the order of these operations (which it's allowed to do) it
|
compiled with optimzations enabled.
|
||||||
changes the result.
|
|
||||||
|
|
||||||
- The equivalent code in C exhibits undefined behavior, which may result in
|
- Show students [the C version of this on Godbolt][unoptimized]. By default,
|
||||||
mis-compilation and unexpected behavior, even if it doesn't cause a crash.
|
with no optimizations enabled it will print `x = 3`. But
|
||||||
|
[enabling optimizations][optimized] causes it to instead print `x = 2`.
|
||||||
|
|
||||||
|
- Note the use of the `restrict` keyword in the C example. This tells the
|
||||||
|
compiler that `a` and `b` cannot alias, but nothing prevents you from
|
||||||
|
violating that requirement. The compiler will silently produce the wrong
|
||||||
|
behavior.
|
||||||
|
|
||||||
|
- In the Rust version, using `&mut` automatically implies the same
|
||||||
|
restriction, and the compiler statically prevents violations of this
|
||||||
|
requirement.
|
||||||
|
|
||||||
- Rust's aliasing rules provide strong guarantees about how references can
|
- Rust's aliasing rules provide strong guarantees about how references can
|
||||||
alias, allowing the compiler to apply optimizations without breaking the
|
alias, allowing the compiler to apply optimizations without breaking the
|
||||||
semantics of your program.
|
semantics of your program.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
[unoptimized]: https://godbolt.org/z/9EGh6eMxE
|
||||||
|
[optimized]: https://godbolt.org/z/Kxsf8sahT
|
||||||
|
Reference in New Issue
Block a user