Skip to content

Commit

Permalink
Rollup merge of rust-lang#79208 - LeSeulArtichaut:stable-unsafe_op_in…
Browse files Browse the repository at this point in the history
…_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 rust-lang#71668 (comment).

Tracking issue: rust-lang#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();
    }
}
```
  • Loading branch information
Dylan-DPC committed Mar 9, 2021
2 parents 3a5d45f + ec20993 commit d157bdb
Show file tree
Hide file tree
Showing 13 changed files with 26 additions and 74 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/accepted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),

Expand Down
9 changes: 1 addition & 8 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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() {}
Expand Down Expand Up @@ -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! {
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_middle/src/mir/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_mir/src/transform/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,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;

Expand All @@ -355,8 +355,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() {
Expand Down
2 changes: 1 addition & 1 deletion library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
4 changes: 2 additions & 2 deletions library/core/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,16 @@
#![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)]
#![feature(const_option)]
#![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;

Expand Down
2 changes: 1 addition & 1 deletion library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down

This file was deleted.

This file was deleted.

1 change: 0 additions & 1 deletion src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#![feature(unsafe_block_in_unsafe_fn)]
#![deny(unsafe_op_in_unsafe_fn)]
#![deny(unused_unsafe)]

Expand Down
32 changes: 16 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
@@ -1,90 +1,90 @@
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
|
= 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
|
= 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)]
| ^^^^^^^^
= 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:27:5
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26: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:29:5
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:28: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: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
| |
| 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
Expand All @@ -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
Expand All @@ -102,15 +102,15 @@ 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
|
= 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
Expand Down

0 comments on commit d157bdb

Please sign in to comment.