Skip to content

Commit

Permalink
Auto merge of #81110 - LeSeulArtichaut:fix-unused-unsafe-label, r=Ral…
Browse files Browse the repository at this point in the history
…fJung

Fix `unused_unsafe` label with `unsafe_block_in_unsafe_fn

Previously, the following code:

```rust
#![feature(unsafe_block_in_unsafe_fn)]

unsafe fn foo() {
    unsafe { unsf() }
}

unsafe fn unsf() {}
```

Would give the following warning:

```
warning: unnecessary `unsafe` block
 --> src/lib.rs:4:5
  |
4 |     unsafe { unsf() }
  |     ^^^^^^ unnecessary `unsafe` block
  |
  = note: `#[warn(unused_unsafe)]` on by default
```
which doesn't point out that the block is in an `unsafe fn`.

Tracking issue: #71668
cc #79208
  • Loading branch information
bors committed Jan 19, 2021
2 parents 7d7b22d + 2136a5c commit 47121d6
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 24 deletions.
17 changes: 9 additions & 8 deletions compiler/rustc_mir/src/transform/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,24 +568,23 @@ fn is_enclosed(
tcx: TyCtxt<'_>,
used_unsafe: &FxHashSet<hir::HirId>,
id: hir::HirId,
) -> Option<(String, hir::HirId)> {
unsafe_op_in_unsafe_fn_allowed: bool,
) -> Option<(&'static str, hir::HirId)> {
let parent_id = tcx.hir().get_parent_node(id);
if parent_id != id {
if used_unsafe.contains(&parent_id) {
Some(("block".to_string(), parent_id))
Some(("block", parent_id))
} else if let Some(Node::Item(&hir::Item {
kind: hir::ItemKind::Fn(ref sig, _, _), ..
})) = tcx.hir().find(parent_id)
{
if sig.header.unsafety == hir::Unsafety::Unsafe
&& !tcx.features().unsafe_block_in_unsafe_fn
{
Some(("fn".to_string(), parent_id))
if sig.header.unsafety == hir::Unsafety::Unsafe && unsafe_op_in_unsafe_fn_allowed {
Some(("fn", parent_id))
} else {
None
}
} else {
is_enclosed(tcx, used_unsafe, parent_id)
is_enclosed(tcx, used_unsafe, parent_id, unsafe_op_in_unsafe_fn_allowed)
}
} else {
None
Expand All @@ -598,7 +597,9 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, used_unsafe: &FxHashSet<hir::HirId>, id
let msg = "unnecessary `unsafe` block";
let mut db = lint.build(msg);
db.span_label(span, msg);
if let Some((kind, id)) = is_enclosed(tcx, used_unsafe, id) {
if let Some((kind, id)) =
is_enclosed(tcx, used_unsafe, id, unsafe_op_in_unsafe_fn_allowed(tcx, id))
{
db.span_label(
tcx.sess.source_map().guess_head_span(tcx.hir().span(id)),
format!("because it's nested under this `unsafe` {}", kind),
Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ unsafe fn deny_level() {
//~^ ERROR dereference of raw pointer is unsafe and requires unsafe block
VOID = ();
//~^ ERROR use of mutable static is unsafe and requires unsafe block

unsafe {}
//~^ ERROR unnecessary `unsafe` block
}

// Check that `unsafe_op_in_unsafe_fn` works starting from the `warn` level.
Expand All @@ -25,6 +28,8 @@ unsafe fn warning_level() {
//~^ ERROR dereference of raw pointer is unsafe and requires unsafe block
VOID = ();
//~^ ERROR use of mutable static is unsafe and requires unsafe block
unsafe {}
//~^ ERROR unnecessary `unsafe` block
}

unsafe fn explicit_block() {
Expand Down
50 changes: 34 additions & 16 deletions src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -27,78 +27,96 @@ LL | VOID = ();
|
= note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior

error: unnecessary `unsafe` block
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:17:5
|
LL | unsafe {}
| ^^^^^^ unnecessary `unsafe` block
|
note: the lint level is defined here
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:3:9
|
LL | #![deny(unused_unsafe)]
| ^^^^^^^^^^^^^

error: call to unsafe function is unsafe and requires unsafe block (error E0133)
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:22:5
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:25:5
|
LL | unsf();
| ^^^^^^ call to unsafe function
|
note: the lint level is defined here
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:20:8
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:23:8
|
LL | #[deny(warnings)]
| ^^^^^^^^
= note: `#[deny(unsafe_op_in_unsafe_fn)]` implied by `#[deny(warnings)]`
= note: consult the function's documentation for information on how to avoid undefined behavior

error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:24:5
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:27:5
|
LL | *PTR;
| ^^^^ dereference of raw pointer
|
= note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior

error: use of mutable static is unsafe and requires unsafe block (error E0133)
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26:5
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:29:5
|
LL | VOID = ();
| ^^^^^^^^^ use of mutable static
|
= note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior

error: unnecessary `unsafe` block
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:40:14
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:31:5
|
LL | unsafe {}
| ^^^^^^ unnecessary `unsafe` block

error: unnecessary `unsafe` block
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:45:14
|
LL | unsafe { unsafe { unsf() } }
| ------ ^^^^^^ unnecessary `unsafe` block
| |
| because it's nested under this `unsafe` block
|
note: the lint level is defined here
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:3:9
|
LL | #![deny(unused_unsafe)]
| ^^^^^^^^^^^^^

error: unnecessary `unsafe` block
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:51:5
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:56:5
|
LL | unsafe fn allow_level() {
| ----------------------- because it's nested under this `unsafe` fn
...
LL | unsafe { unsf() }
| ^^^^^^ unnecessary `unsafe` block

error: unnecessary `unsafe` block
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:63:9
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:68:9
|
LL | unsafe fn nested_allow_level() {
| ------------------------------ because it's nested under this `unsafe` fn
...
LL | unsafe { unsf() }
| ^^^^^^ unnecessary `unsafe` block

error[E0133]: call to unsafe function is unsafe and requires unsafe block
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:69:5
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:74:5
|
LL | unsf();
| ^^^^^^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior

error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:73:9
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:78:9
|
LL | unsf();
| ^^^^^^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior

error: aborting due to 11 previous errors
error: aborting due to 13 previous errors

For more information about this error, try `rustc --explain E0133`.

0 comments on commit 47121d6

Please sign in to comment.