8000 add extended example from doener · sarvex/rust-memory-model@f0daa52 · GitHub
[go: up one dir, main page]

Skip to content

Commit f0daa52

Browse files
committed
add extended example from doener
1 parent 2c459c1 commit f0daa52

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

litmus_tests/usize_transfer.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
### Example
2+
3+
```rust
4+
fn foo(x: &i32) -> usize {
5+
x as *const _ as usize
6+
}
7+
8+
fn bar(x: usize) -> i32 {
9+
let y: &i32 = unsafe { std::mem::transmute(x as *const i32) };
10+
*y
11+
}
12+
13+
fn main() {
14+
let x = 2;
15+
println!("{}", bar(foo(&x)));
16+
}
17+
```
18+
19+
### Explanation
20+
21+
In this example, the value `x` is cast to a `usize` and then
22+
transmitted to `bar`, which then casts back to a pointer. `bar` is
23+
declared as a safe function: strictly speaking, this seems
24+
semantically incorrect, because in fact it cannot accept any `usize`
25+
as argument. Rather, its inputs must meet very specific criteria (it
26+
must be a valid pointer that can be dereferenced). Nonetheless, the
27+
user has incorrectly put an unsafe block in the body, rather than in
28+
the signature, and so the compiler accepts this code.
29+
30+
Either something in this example must be UB or else we have to be
31+
**very** limited in our ability to add "nocapture" annotations. See
32+
the ["nocapture by safe fn"][nocap] example for further thoughts.
33+
34+
[nocap]: ../optimizations/nocapture_by_safe_fn.md
35+
36+
### Source
37+
38+
doener on IRC

optimizations/nocapture_by_safe_fn.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,18 @@ can always assume that.
5050
- `escape_as_vec` -- variant on the previous case where it seems like
5151
we should be able to assume nocapture, even though the return type
5252
contains a `*const i32`.
53+
54+
nmatsakis notes: One possibility is that all of these examples *can
55+
be* legal, depending on the caller. That is, looking specifically as
56+
`escape_as_usize`, if the caller gets back a `usize` and transmutes it
57+
to a pointer which is then dereferenced, perhaps we can simply have
58+
very conservative rules on the caller because they have created a
59+
pointer with no known origin. However, this gets complicated if the
60+
caller passes the `usize` elsewhere without adding proper unsafe
61+
blocks; see the ["usize transfer"][ut] litmus test for an example of
62+
why.
63+
64+
[ut]: ../litmus_tests/usize_transfer.md
5365

5466
### Source
5567

0 commit comments

Comments
 (0)
0