Rollup merge of #79208 - LeSeulArtichaut:stable-unsafe_op_in_unsafe_fn, r=nikomatsakis

Stabilize `unsafe_op_in_unsafe_fn` lint

This makes it possible to override the level of the `unsafe_op_in_unsafe_fn`, as proposed in https://github.com/rust-lang/rust/issues/71668#issuecomment-729770896.

Tracking issue: #71668
r? ```@nikomatsakis``` cc ```@SimonSapin``` ```@RalfJung```

# Stabilization report

This is a stabilization report for `#![feature(unsafe_block_in_unsafe_fn)]`.

## Summary

Currently, the body of unsafe functions is an unsafe block, i.e. you can perform unsafe operations inside.

The `unsafe_op_in_unsafe_fn` lint, stabilized here, can be used to change this behavior, so performing unsafe operations in unsafe functions requires an unsafe block.

For now, the lint is allow-by-default, which means that this PR does not change anything without overriding the lint level.

For more information, see [RFC 2585](https://github.com/rust-lang/rfcs/blob/master/text/2585-unsafe-block-in-unsafe-fn.md)

### Example

```rust
// An `unsafe fn` for demonstration purposes.
// Calling this is an unsafe operation.
unsafe fn unsf() {}

// #[allow(unsafe_op_in_unsafe_fn)] by default,
// the behavior of `unsafe fn` is unchanged
unsafe fn allowed() {
    // Here, no `unsafe` block is needed to
    // perform unsafe operations...
    unsf();

    // ...and any `unsafe` block is considered
    // unused and is warned on by the compiler.
    unsafe {
        unsf();
    }
}

#[warn(unsafe_op_in_unsafe_fn)]
unsafe fn warned() {
    // Removing this `unsafe` block will
    // cause the compiler to emit a warning.
    // (Also, no "unused unsafe" warning will be emitted here.)
    unsafe {
        unsf();
    }
}

#[deny(unsafe_op_in_unsafe_fn)]
unsafe fn denied() {
    // Removing this `unsafe` block will
    // cause a compilation error.
    // (Also, no "unused unsafe" warning will be emitted here.)
    unsafe {
        unsf();
    }
}
```
This commit is contained in:
Yuki Okushi 2021-03-10 08:01:25 +09:00 committed by GitHub
commit c46f948a80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 26 additions and 74 deletions

View File

@ -275,6 +275,8 @@ declare_features! (
(accepted, move_ref_pattern, "1.49.0", Some(68354), None),
/// The smallest useful subset of `const_generics`.
(accepted, min_const_generics, "1.51.0", Some(74878), None),
/// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block.
(accepted, unsafe_block_in_unsafe_fn, "1.51.0", Some(71668), None),
// -------------------------------------------------------------------------
// feature-group-end: accepted features

View File

@ -557,9 +557,6 @@ declare_features! (
/// Allows the use of `#[ffi_const]` on foreign functions.
(active, ffi_const, "1.45.0", Some(58328), None),
/// No longer treat an unsafe function as an unsafe block.
(active, unsafe_block_in_unsafe_fn, "1.45.0", Some(71668), None),
/// Allows `extern "avr-interrupt" fn()` and `extern "avr-non-blocking-interrupt" fn()`.
(active, abi_avr_interrupt, "1.45.0", Some(69664), None),

View File

@ -8,7 +8,6 @@
use crate::{declare_lint, declare_lint_pass};
use rustc_span::edition::Edition;
use rustc_span::symbol::sym;
declare_lint! {
/// The `forbidden_lint_groups` lint detects violations of
@ -2489,16 +2488,11 @@ declare_lint! {
declare_lint! {
/// The `unsafe_op_in_unsafe_fn` lint detects unsafe operations in unsafe
/// functions without an explicit unsafe block. This lint only works on
/// the [**nightly channel**] with the
/// `#![feature(unsafe_block_in_unsafe_fn)]` feature.
///
/// [**nightly channel**]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html
/// functions without an explicit unsafe block.
///
/// ### Example
///
/// ```rust,compile_fail
/// #![feature(unsafe_block_in_unsafe_fn)]
/// #![deny(unsafe_op_in_unsafe_fn)]
///
/// unsafe fn foo() {}
@ -2536,7 +2530,6 @@ declare_lint! {
pub UNSAFE_OP_IN_UNSAFE_FN,
Allow,
"unsafe operations in unsafe functions without an explicit unsafe block are deprecated",
@feature_gate = sym::unsafe_block_in_unsafe_fn;
}
declare_lint! {

View File

@ -28,11 +28,9 @@ pub enum UnsafetyViolationKind {
BorrowPacked,
/// Unsafe operation in an `unsafe fn` but outside an `unsafe` block.
/// Has to be handled as a lint for backwards compatibility.
/// Should stay gated under `#![feature(unsafe_block_in_unsafe_fn)]`.
UnsafeFn,
/// Borrow of packed field in an `unsafe fn` but outside an `unsafe` block.
/// Has to be handled as a lint for backwards compatibility.
/// Should stay gated under `#![feature(unsafe_block_in_unsafe_fn)]`.
UnsafeFnBorrowPacked,
}

View File

@ -341,7 +341,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
false
}
// With the RFC 2585, no longer allow `unsafe` operations in `unsafe fn`s
Safety::FnUnsafe if self.tcx.features().unsafe_block_in_unsafe_fn => {
Safety::FnUnsafe => {
for violation in violations {
let mut violation = *violation;
@ -356,8 +356,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
}
false
}
// `unsafe` function bodies allow unsafe without additional unsafe blocks (before RFC 2585)
Safety::BuiltinUnsafe | Safety::FnUnsafe => true,
Safety::BuiltinUnsafe => true,
Safety::ExplicitUnsafe(hir_id) => {
// mark unsafe block as used if there are any unsafe operations inside
if !violations.is_empty() {

View File

@ -133,7 +133,7 @@
#![feature(trusted_len)]
#![feature(unboxed_closures)]
#![feature(unicode_internals)]
#![feature(unsafe_block_in_unsafe_fn)]
#![cfg_attr(bootstrap, feature(unsafe_block_in_unsafe_fn))]
#![feature(unsize)]
#![feature(unsized_fn_params)]
#![feature(allocator_internals)]

View File

@ -164,8 +164,8 @@
#![feature(const_caller_location)]
#![feature(slice_ptr_get)]
#![feature(no_niche)] // rust-lang/rust#68303
#![feature(unsafe_block_in_unsafe_fn)]
#![feature(int_error_matching)]
#![cfg_attr(bootstrap, feature(unsafe_block_in_unsafe_fn))]
#![deny(unsafe_op_in_unsafe_fn)]
#[prelude_import]

View File

@ -72,7 +72,6 @@
#![feature(peekable_peek_mut)]
#![cfg_attr(not(bootstrap), feature(ptr_metadata))]
#![feature(once_cell)]
#![feature(unsafe_block_in_unsafe_fn)]
#![feature(unsized_tuple_coercion)]
#![feature(int_bits_const)]
#![feature(nonzero_leading_trailing_zeros)]
@ -80,8 +79,9 @@
#![feature(integer_atomics)]
#![feature(slice_group_by)]
#![feature(trusted_random_access)]
#![deny(unsafe_op_in_unsafe_fn)]
#![cfg_attr(bootstrap, feature(unsafe_block_in_unsafe_fn))]
#![cfg_attr(not(bootstrap), feature(unsize))]
#![deny(unsafe_op_in_unsafe_fn)]
extern crate test;

View File

@ -327,7 +327,7 @@
#![feature(try_blocks)]
#![feature(try_reserve)]
#![feature(unboxed_closures)]
#![feature(unsafe_block_in_unsafe_fn)]
#![cfg_attr(bootstrap, feature(unsafe_block_in_unsafe_fn))]
#![feature(unsafe_cell_raw_get)]
#![feature(unwind_attributes)]
#![feature(vec_into_raw_parts)]

View File

@ -1,6 +0,0 @@
#![deny(unsafe_op_in_unsafe_fn)]
//~^ ERROR the `unsafe_op_in_unsafe_fn` lint is unstable
//~| ERROR the `unsafe_op_in_unsafe_fn` lint is unstable
//~| ERROR the `unsafe_op_in_unsafe_fn` lint is unstable
fn main() {}

View File

@ -1,30 +0,0 @@
error[E0658]: the `unsafe_op_in_unsafe_fn` lint is unstable
--> $DIR/feature-gate-unsafe_block_in_unsafe_fn.rs:1:1
|
LL | #![deny(unsafe_op_in_unsafe_fn)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #71668 <https://github.com/rust-lang/rust/issues/71668> for more information
= help: add `#![feature(unsafe_block_in_unsafe_fn)]` to the crate attributes to enable
error[E0658]: the `unsafe_op_in_unsafe_fn` lint is unstable
--> $DIR/feature-gate-unsafe_block_in_unsafe_fn.rs:1:1
|
LL | #![deny(unsafe_op_in_unsafe_fn)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #71668 <https://github.com/rust-lang/rust/issues/71668> for more information
= help: add `#![feature(unsafe_block_in_unsafe_fn)]` to the crate attributes to enable
error[E0658]: the `unsafe_op_in_unsafe_fn` lint is unstable
--> $DIR/feature-gate-unsafe_block_in_unsafe_fn.rs:1:1
|
LL | #![deny(unsafe_op_in_unsafe_fn)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #71668 <https://github.com/rust-lang/rust/issues/71668> for more information
= help: add `#![feature(unsafe_block_in_unsafe_fn)]` to the crate attributes to enable
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -1,4 +1,3 @@
#![feature(unsafe_block_in_unsafe_fn)]
#![deny(unsafe_op_in_unsafe_fn)]
#![deny(unused_unsafe)]

View File

@ -1,18 +1,18 @@
error: call to unsafe function is unsafe and requires unsafe block (error E0133)
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:10:5
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:9:5
|
LL | unsf();
| ^^^^^^ call to unsafe function
|
note: the lint level is defined here
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:2:9
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:1:9
|
LL | #![deny(unsafe_op_in_unsafe_fn)]
| ^^^^^^^^^^^^^^^^^^^^^^
= 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:12:5
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:11:5
|
LL | *PTR;
| ^^^^ dereference of raw pointer
@ -20,7 +20,7 @@ LL | *PTR;
= 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:14:5
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:13:5
|
LL | VOID = ();
| ^^^^^^^^^ use of mutable static
@ -28,25 +28,25 @@ 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
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:16:5
|
LL | unsafe {}
| ^^^^^^ unnecessary `unsafe` block
|
note: the lint level is defined here
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:3:9
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:2: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:25:5
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:24:5
|
LL | unsf();
| ^^^^^^ call to unsafe function
|
note: the lint level is defined here
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:23:8
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:22:8
|
LL | #[deny(warnings)]
| ^^^^^^^^
@ -54,7 +54,7 @@ LL | #[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:27:5
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26:5
|
LL | *PTR;
| ^^^^ dereference of raw pointer
@ -62,7 +62,7 @@ LL | *PTR;
= 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:29:5
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:28:5
|
LL | VOID = ();
| ^^^^^^^^^ use of mutable static
@ -70,13 +70,13 @@ 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:31:5
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:30:5
|
LL | unsafe {}
| ^^^^^^ unnecessary `unsafe` block
error: unnecessary `unsafe` block
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:45:14
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:44:14
|
LL | unsafe { unsafe { unsf() } }
| ------ ^^^^^^ unnecessary `unsafe` block
@ -84,7 +84,7 @@ LL | unsafe { unsafe { unsf() } }
| because it's nested under this `unsafe` block
error: unnecessary `unsafe` block
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:56:5
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:55:5
|
LL | unsafe fn allow_level() {
| ----------------------- because it's nested under this `unsafe` fn
@ -93,7 +93,7 @@ LL | unsafe { unsf() }
| ^^^^^^ unnecessary `unsafe` block
error: unnecessary `unsafe` block
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:68:9
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:67:9
|
LL | unsafe fn nested_allow_level() {
| ------------------------------ because it's nested under this `unsafe` fn
@ -102,7 +102,7 @@ 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:74:5
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:73:5
|
LL | unsf();
| ^^^^^^ call to unsafe function
@ -110,7 +110,7 @@ LL | unsf();
= 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:78:9
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:77:9
|
LL | unsf();
| ^^^^^^ call to unsafe function