Skip to content

Commit a977df3

Browse files
Implement RFC 2585
1 parent 2873165 commit a977df3

File tree

7 files changed

+75
-10
lines changed

7 files changed

+75
-10
lines changed

src/librustc_feature/active.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,9 @@ declare_features! (
571571
/// Allows the use of `#[ffi_const]` on foreign functions.
572572
(active, ffi_const, "1.45.0", Some(58328), None),
573573

574+
/// No longer treat an unsafe function as an unsafe block.
575+
(active, unsafe_block_in_unsafe_fn, "1.45.0", Some(71668), None),
576+
574577
// -------------------------------------------------------------------------
575578
// feature-group-end: actual feature gates
576579
// -------------------------------------------------------------------------

src/librustc_middle/mir/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ impl<'tcx> Body<'tcx> {
408408
}
409409
}
410410

411-
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
411+
#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable, HashStable)]
412412
pub enum Safety {
413413
Safe,
414414
/// Unsafe because of a PushUnsafeBlock

src/librustc_middle/mir/query.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,17 @@ use super::{Field, SourceInfo};
1515

1616
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
1717
pub enum UnsafetyViolationKind {
18+
/// Only permitted in regular `fn`s, prohibitted in `const fn`s.
1819
General,
1920
/// Permitted both in `const fn`s and regular `fn`s.
2021
GeneralAndConstFn,
22+
/// Borrow of packed field.
23+
/// Has to be handled as a lint for backwards compatibility.
2124
BorrowPacked(hir::HirId),
25+
/// Unsafe operation in an `unsafe fn` but outside an `unsafe` block.
26+
/// Has to be handled as a lint for backwards compatibility.
27+
/// Should stay gated under `#![feature(unsafe_block_in_unsafe_fn)]`.
28+
UnsafeFn(hir::HirId),
2229
}
2330

2431
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]

src/librustc_mir/transform/check_unsafety.rs

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_middle::mir::*;
99
use rustc_middle::ty::cast::CastTy;
1010
use rustc_middle::ty::query::Providers;
1111
use rustc_middle::ty::{self, TyCtxt};
12-
use rustc_session::lint::builtin::{SAFE_PACKED_BORROWS, UNUSED_UNSAFE};
12+
use rustc_session::lint::builtin::{SAFE_PACKED_BORROWS, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
1313
use rustc_span::symbol::{sym, Symbol};
1414

1515
use std::ops::Bound;
@@ -351,14 +351,35 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
351351
violation.kind = UnsafetyViolationKind::General;
352352
}
353353
}
354+
UnsafetyViolationKind::UnsafeFn(_) => {
355+
bug!("`UnsafetyViolationKind::UnsafeFn` in an `Safe` context")
356+
}
357+
}
358+
if !self.violations.contains(&violation) {
359+
self.violations.push(violation)
354360
}
361+
}
362+
false
363+
}
364+
// With the RFC 2585, no longer allow `unsafe` operations in `unsafe fn`s
365+
Safety::FnUnsafe if self.tcx.features().unsafe_block_in_unsafe_fn => {
366+
for violation in violations {
367+
let mut violation = *violation;
368+
let lint_root = self.body.source_scopes[self.source_info.scope]
369+
.local_data
370+
.as_ref()
371+
.assert_crate_local()
372+
.lint_root;
373+
374+
// FIXME(LeSeulArtichaut): what to do with `UnsafetyViolationKind::BorrowPacked`?
375+
violation.kind = UnsafetyViolationKind::UnsafeFn(lint_root);
355376
if !self.violations.contains(&violation) {
356377
self.violations.push(violation)
357378
}
358379
}
359380
false
360381
}
361-
// `unsafe` function bodies allow unsafe without additional unsafe blocks
382+
// `unsafe` function bodies allow unsafe without additional unsafe blocks (before RFC 2585)
362383
Safety::BuiltinUnsafe | Safety::FnUnsafe => true,
363384
Safety::ExplicitUnsafe(hir_id) => {
364385
// mark unsafe block as used if there are any unsafe operations inside
@@ -383,6 +404,9 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
383404
self.violations.push(violation)
384405
}
385406
}
407+
UnsafetyViolationKind::UnsafeFn(_) => bug!(
408+
"`UnsafetyViolationKind::UnsafeFn` in an `ExplicitUnsafe` context"
409+
),
386410
}
387411
}
388412
}
@@ -575,9 +599,12 @@ fn is_enclosed(
575599
kind: hir::ItemKind::Fn(ref sig, _, _), ..
576600
})) = tcx.hir().find(parent_id)
577601
{
578-
match sig.header.unsafety {
579-
hir::Unsafety::Unsafe => Some(("fn".to_string(), parent_id)),
580-
hir::Unsafety::Normal => None,
602+
if sig.header.unsafety == hir::Unsafety::Unsafe
603+
&& !tcx.features().unsafe_block_in_unsafe_fn
604+
{
605+
Some(("fn".to_string(), parent_id))
606+
} else {
607+
None
581608
}
582609
} else {
583610
is_enclosed(tcx, used_unsafe, parent_id)
@@ -630,16 +657,20 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: DefId) {
630657
let UnsafetyCheckResult { violations, unsafe_blocks } =
631658
tcx.unsafety_check_result(def_id.expect_local());
632659

660+
let or_block_msg = if tcx.features().unsafe_block_in_unsafe_fn { "" } else { " or block" };
661+
633662
for &UnsafetyViolation { source_info, description, details, kind } in violations.iter() {
634663
// Report an error.
635664
match kind {
636665
UnsafetyViolationKind::GeneralAndConstFn | UnsafetyViolationKind::General => {
666+
// once
637667
struct_span_err!(
638668
tcx.sess,
639669
source_info.span,
640670
E0133,
641-
"{} is unsafe and requires unsafe function or block",
642-
description
671+
"{} is unsafe and requires unsafe function{}",
672+
description,
673+
or_block_msg,
643674
)
644675
.span_label(source_info.span, &*description.as_str())
645676
.note(&details.as_str())
@@ -655,15 +686,29 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: DefId) {
655686
source_info.span,
656687
|lint| {
657688
lint.build(&format!(
658-
"{} is unsafe and requires unsafe function or block (error E0133)",
659-
description
689+
"{} is unsafe and requires unsafe function{} (error E0133)",
690+
description, or_block_msg,
660691
))
661692
.note(&details.as_str())
662693
.emit()
663694
},
664695
)
665696
}
666697
}
698+
UnsafetyViolationKind::UnsafeFn(lint_hir_id) => tcx.struct_span_lint_hir(
699+
UNSAFE_OP_IN_UNSAFE_FN,
700+
lint_hir_id,
701+
source_info.span,
702+
|lint| {
703+
lint.build(&format!(
704+
"{} is unsafe and requires unsafe block (error E0133)",
705+
description
706+
))
707+
.span_label(source_info.span, &*description.as_str())
708+
.note(&details.as_str())
709+
.emit();
710+
},
711+
),
667712
}
668713
}
669714

src/librustc_mir_build/build/block.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
217217
assert_eq!(self.push_unsafe_count, 0);
218218
match self.unpushed_unsafe {
219219
Safety::Safe => {}
220+
// no longer treat `unsafe fn`s as `unsafe` contexts (see RFC #2585)
221+
Safety::FnUnsafe if self.hir.tcx().features().unsafe_block_in_unsafe_fn => {}
220222
_ => return,
221223
}
222224
self.unpushed_unsafe = Safety::ExplicitUnsafe(hir_id);

src/librustc_session/lint/builtin.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,12 @@ declare_lint! {
526526
"using only a subset of a register for inline asm inputs",
527527
}
528528

529+
declare_lint! {
530+
pub UNSAFE_OP_IN_UNSAFE_FN,
531+
Allow,
532+
"unsafe operations in unsafe functions without an explicit unsafe block are deprecated",
533+
}
534+
529535
declare_lint_pass! {
530536
/// Does nothing as a lint pass, but registers some `Lint`s
531537
/// that are used by other parts of the compiler.
@@ -597,6 +603,7 @@ declare_lint_pass! {
597603
SOFT_UNSTABLE,
598604
INLINE_NO_SANITIZE,
599605
ASM_SUB_REGISTER,
606+
UNSAFE_OP_IN_UNSAFE_FN,
600607
]
601608
}
602609

src/librustc_span/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,7 @@ symbols! {
806806
unmarked_api,
807807
unreachable_code,
808808
unrestricted_attribute_tokens,
809+
unsafe_block_in_unsafe_fn,
809810
unsafe_no_drop_flag,
810811
unsized_locals,
811812
unsized_tuple_coercion,

0 commit comments

Comments
 (0)