|
| 1 | +- Feature Name: `unsafe_expr` |
| 2 | +- Start Date: 2015-10-29 |
| 3 | +- RFC PR: (leave this empty) |
| 4 | +- Rust Issue: (leave this empty) |
| 5 | + |
| 6 | +# Summary |
| 7 | + |
| 8 | +Proposal to extend the syntax of the `unsafe` keyword to be followed by an expression |
| 9 | +rather than a block as it is currently defined. |
| 10 | + |
| 11 | + |
| 12 | +# Motivation |
| 13 | + |
| 14 | +`unsafe` is often used for single method calls, and requires one to wrap the expression |
| 15 | +in curly braces. It looks ugly, makes for strange-looking inline blocks, causes code |
| 16 | +to drift rightward in block indenting, and in general just doesn't feel very ergonomic. |
| 17 | + |
| 18 | + |
| 19 | +# Detailed design |
| 20 | + |
| 21 | +Let's take a look at a trivial example that makes use of unsafe: |
| 22 | + |
| 23 | +```rust |
| 24 | +match senders.len() { |
| 25 | + 1 => if unsafe { senders.get_unchecked(0) }.send(value).is_err() { |
| 26 | + // ... |
| 27 | + }, |
| 28 | + _ => {}, |
| 29 | +} |
| 30 | +``` |
| 31 | + |
| 32 | +The inline braces are awkward and feel strange from a formatting perspective. |
| 33 | +Now, suppose `unsafe` accepted an expression rather than a block. |
| 34 | + |
| 35 | +```rust |
| 36 | +match senders.len() { |
| 37 | + 1 => if unsafe senders.get_unchecked(0).send(value).is_err() { |
| 38 | + // ... |
| 39 | + }, |
| 40 | + _ => {}, |
| 41 | +} |
| 42 | +``` |
| 43 | + |
| 44 | +We've removed the strange punctuation, and all works as usual. This change |
| 45 | +would be backwards-compatible, as it will allow all existing Rust code to compile. |
| 46 | + |
| 47 | + |
| 48 | +# Drawbacks |
| 49 | + |
| 50 | +Less friction to the ergonomics of using `unsafe` is not necessarily a good thing, |
| 51 | +we certainly don't want to encourage its use. I believe this change would still |
| 52 | +be beneficial in general, however. |
| 53 | + |
| 54 | +This encourages `unsafe` to be more coarse-grained, rather than wrapping the |
| 55 | +single function call in its own block. However, I've found this style to not |
| 56 | +be common in the greater rust ecosystem, which more often means the example |
| 57 | +is written as such: |
| 58 | + |
| 59 | +```rust |
| 60 | +match senders.len() { |
| 61 | + 1 => if unsafe { senders.get_unchecked(0).send(value).is_err() } { |
| 62 | + // ... |
| 63 | + }, |
| 64 | + _ => {}, |
| 65 | +} |
| 66 | +``` |
| 67 | + |
| 68 | +or worse, like so: |
| 69 | + |
| 70 | +```rust |
| 71 | +unsafe { |
| 72 | + match senders.len() { |
| 73 | + 1 => if senders.get_unchecked(0).send(value).is_err() { |
| 74 | + // ... |
| 75 | + }, |
| 76 | + _ => {}, |
| 77 | + } |
| 78 | +} |
| 79 | +``` |
| 80 | + |
| 81 | +Note that this issue exists in other contexts as well, such as `unsafe` functions |
| 82 | +themselves. |
| 83 | + |
| 84 | + |
| 85 | +# Unresolved questions |
| 86 | + |
| 87 | +- Is there any reason this proposal will not work from a grammar or syntax perspective? |
| 88 | +- Are there any strange interactions with the language here that haven't been addressed? |
| 89 | +- Does this conflict with or complicate parsing due to the `unsafe fn x()` declaration syntax? |
0 commit comments