Rust: Nightly: unsafe code is allowed outside `unsafe` blocks when the code is unreachable

Created on 7 Oct 2017  路  8Comments  路  Source: rust-lang/rust

I'm not sure if this is a feature or a bug, but the compiler behaves differently for the following program on stable, beta, and nightly:

fn main() {
    return;
    let _ = ();
    *(&true as *const bool);
}

On stable:

error[E0133]: dereference of raw pointer requires unsafe function or block
 --> src/main.rs:4:5
  |
4 |     *(&true as *const bool);
  |     ^^^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer

error: aborting due to previous error

On beta:

warning: unreachable statement
 --> src/main.rs:3:5
  |
3 |     let _ = ();
  |     ^^^^^^^^^^^
  |
  = note: #[warn(unreachable_code)] on by default

error[E0133]: dereference of raw pointer requires unsafe function or block
 --> src/main.rs:4:5
  |
4 |     *(&true as *const bool);
  |     ^^^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer

error: aborting due to previous error

On nightly:

warning: unreachable statement
 --> src/main.rs:3:5
  |
3 |     let _ = ();
  |     ^^^^^^^^^^^
  |
  = note: #[warn(unreachable_code)] on by default

Note that wrapping the final statement in an unsafe block will allow the program to compile on all three versions, but on nightly the compiler will complain:

warning: unnecessary `unsafe` block
 --> src/main.rs:4:5
  |
4 |     unsafe { *(&true as *const bool); }
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unnecessary `unsafe` block
  |
  = note: #[warn(unused_unsafe)] on by default

I suppose that the compiler is technically correct, because dead code ~tells no tales~ cannot cause memory unsafety, so no unsafe block is needed... but the current situation does seem like an accident, as the compiler does perform other checks on dead code (typechecking, borrow-checking, ...).

C-bug P-high T-compiler regression-from-stable-to-beta

Most helpful comment

I think it's entirely wrong to fail to issue the warning, here. Even if code is unreachable, we shouldn't allow incorrect usage/non-usage of unsafe.

Among other things, that might also break code in if cfg!(...) blocks.

All 8 comments

Probably due to #44700, cc @arielb1

cc @rust-lang/lang as well

This is clearly a result of doing unsafe checking on MIR. My preference would be to continue issuing the error, but we have sometimes decided to let errors in unreachable code slide -- but that was primarily around the borrow check, i.e., checks that are very flow-sensitive. Effect check doesn't seem to fall into that category. Probably if we just perform the unsafe check before we remove dead code, it'd be fine? But @arielb1 can correct.

triage: P-high

We have to reach a decision of some kind.

I think it's entirely wrong to fail to issue the warning, here. Even if code is unreachable, we shouldn't allow incorrect usage/non-usage of unsafe.

Among other things, that might also break code in if cfg!(...) blocks.

I think the problem is not so much that the compiler dosen't mind unreachable unsafe code outside of unsafe blocks (although that is a bit silly), but that it gives "unnecessary unsafe block" warnings for correct unsafe{ ... } blocks that happen to be unreachable.

Probably if we just perform the unsafe check before we remove dead code, it'd be fine?

Yeah it shouldn't be a problem to fix this

Affects 1.22 beta too.

Fix is in queue, nice work @arielb1.

Was this page helpful?
0 / 5 - 0 ratings