From 7c74e109328ecee00e270409dddfccc011b0172b Mon Sep 17 00:00:00 2001 From: arcnmx Date: Thu, 29 Oct 2015 17:16:36 -0400 Subject: [PATCH 1/3] Unsafe expressions --- text/0000-unsafe-expressions.md | 89 +++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 text/0000-unsafe-expressions.md diff --git a/text/0000-unsafe-expressions.md b/text/0000-unsafe-expressions.md new file mode 100644 index 00000000000..60f37619bb5 --- /dev/null +++ b/text/0000-unsafe-expressions.md @@ -0,0 +1,89 @@ +- Feature Name: `unsafe_expr` +- Start Date: 2015-10-29 +- RFC PR: (leave this empty) +- Rust Issue: (leave this empty) + +# Summary + +Proposal to extend the syntax of the `unsafe` keyword to be followed by an expression +rather than a block as it is currently defined. + + +# Motivation + +`unsafe` is often used for single method calls, and requires one to wrap the expression +in curly braces. It looks ugly, makes for strange-looking inline blocks, causes code +to drift rightward in block indenting, and in general just doesn't feel very ergonomic. + + +# Detailed design + +Let's take a look at a trivial example that makes use of unsafe: + +```rust +match senders.len() { + 1 => if unsafe { senders.get_unchecked(0) }.send(value).is_err() { + // ... + }, + _ => {}, +} +``` + +The inline braces are awkward and feel strange from a formatting perspective. +Now, suppose `unsafe` accepted an expression rather than a block. + +```rust +match senders.len() { + 1 => if unsafe senders.get_unchecked(0).send(value).is_err() { + // ... + }, + _ => {}, +} +``` + +We've removed the strange punctuation, and all works as usual. This change +would be backwards-compatible, as it will allow all existing Rust code to compile. + + +# Drawbacks + +Less friction to the ergonomics of using `unsafe` is not necessarily a good thing, +we certainly don't want to encourage its use. I believe this change would still +be beneficial in general, however. + +This encourages `unsafe` to be more coarse-grained, rather than wrapping the +single function call in its own block. However, I've found this style to not +be common in the greater rust ecosystem, which more often means the example +is written as such: + +```rust +match senders.len() { + 1 => if unsafe { senders.get_unchecked(0).send(value).is_err() } { + // ... + }, + _ => {}, +} +``` + +or worse, like so: + +```rust +unsafe { + match senders.len() { + 1 => if senders.get_unchecked(0).send(value).is_err() { + // ... + }, + _ => {}, + } +} +``` + +Note that this issue exists in other contexts as well, such as `unsafe` functions +themselves. + + +# Unresolved questions + +- Is there any reason this proposal will not work from a grammar or syntax perspective? +- Are there any strange interactions with the language here that haven't been addressed? +- Does this conflict with or complicate parsing due to the `unsafe fn x()` declaration syntax? From 141384d87a5af8fd783e334cac40d124c3f30ede Mon Sep 17 00:00:00 2001 From: arcnmx Date: Wed, 11 Nov 2015 10:28:22 -0500 Subject: [PATCH 2/3] Clarify unsafe keyword precedence --- text/0000-unsafe-expressions.md | 45 ++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/text/0000-unsafe-expressions.md b/text/0000-unsafe-expressions.md index 60f37619bb5..fec78c29fbe 100644 --- a/text/0000-unsafe-expressions.md +++ b/text/0000-unsafe-expressions.md @@ -22,7 +22,7 @@ Let's take a look at a trivial example that makes use of unsafe: ```rust match senders.len() { - 1 => if unsafe { senders.get_unchecked(0) }.send(value).is_err() { + 1 => if unsafe { senders.get_unchecked(0).send(value).is_err() } { // ... }, _ => {}, @@ -44,6 +44,23 @@ match senders.len() { We've removed the strange punctuation, and all works as usual. This change would be backwards-compatible, as it will allow all existing Rust code to compile. +## Operator Precedence + +The `unsafe` keyword would have similar precedence to any other prefix unary operator. +As a demonstration, consider the following expressions equivalent... + +`unsafe a.m().n()` => `unsafe { a.m().n() }` +`unsafe a[i].foo()` => `unsafe { a[i].foo() }` +`unsafe a[i].foo() + 1` => `unsafe { a[i].foo() } + 1` +`(unsafe a.()).n()` => `unsafe { a.m() }.n()` + +We have another similar (unstable) keyword in the language already: `box`. It would +make sense to tie these two together with the same precedence in the language. + +One modification to the above may be to give it the precedence of the `||` closure +operator, which would make it more greedy: + +`unsafe a[i].foo() + 1` => `unsafe { a[i].foo() + 1 }` # Drawbacks @@ -51,21 +68,11 @@ Less friction to the ergonomics of using `unsafe` is not necessarily a good thin we certainly don't want to encourage its use. I believe this change would still be beneficial in general, however. -This encourages `unsafe` to be more coarse-grained, rather than wrapping the -single function call in its own block. However, I've found this style to not +This may encourage `unsafe` to be more coarse-grained or greedy, rather than +making the scope of the `unsafe` explicit, one needs to be aware of its operator +precedence as discussed above. However, I've found the "minimal unsafe" style to not be common in the greater rust ecosystem, which more often means the example -is written as such: - -```rust -match senders.len() { - 1 => if unsafe { senders.get_unchecked(0).send(value).is_err() } { - // ... - }, - _ => {}, -} -``` - -or worse, like so: +may be written as such: ```rust unsafe { @@ -78,8 +85,10 @@ unsafe { } ``` -Note that this issue exists in other contexts as well, such as `unsafe` functions -themselves. +... where much more of the code than is necessary is covered by `unsafe` while the +unrelated `_ => {}` block would normally not want it at all. Note that this issue +exists in other contexts as well, such as `unsafe` functions themselves having their +body implicitly be `unsafe`. # Unresolved questions @@ -87,3 +96,5 @@ themselves. - Is there any reason this proposal will not work from a grammar or syntax perspective? - Are there any strange interactions with the language here that haven't been addressed? - Does this conflict with or complicate parsing due to the `unsafe fn x()` declaration syntax? +- See the discussion at [rust-lang/rust#21192](https://github.com/rust-lang/rust/issues/21192) + for opinions on the exact precedence of keyword unary operators. From ee6076e9efeb0ed386bfac5e76743e66f90263b1 Mon Sep 17 00:00:00 2001 From: arcnmx Date: Sat, 12 Mar 2016 14:24:45 -0500 Subject: [PATCH 3/3] Formatting --- text/0000-unsafe-expressions.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/text/0000-unsafe-expressions.md b/text/0000-unsafe-expressions.md index fec78c29fbe..9425800b2ed 100644 --- a/text/0000-unsafe-expressions.md +++ b/text/0000-unsafe-expressions.md @@ -49,10 +49,10 @@ would be backwards-compatible, as it will allow all existing Rust code to compil The `unsafe` keyword would have similar precedence to any other prefix unary operator. As a demonstration, consider the following expressions equivalent... -`unsafe a.m().n()` => `unsafe { a.m().n() }` -`unsafe a[i].foo()` => `unsafe { a[i].foo() }` -`unsafe a[i].foo() + 1` => `unsafe { a[i].foo() } + 1` -`(unsafe a.()).n()` => `unsafe { a.m() }.n()` +- `unsafe a.m().n()` => `unsafe { a.m().n() }` +- `unsafe a[i].foo()` => `unsafe { a[i].foo() }` +- `unsafe a[i].foo() + 1` => `unsafe { a[i].foo() } + 1` +- `(unsafe a.()).n()` => `unsafe { a.m() }.n()` We have another similar (unstable) keyword in the language already: `box`. It would make sense to tie these two together with the same precedence in the language.