Skip to content

Commit

Permalink
Fix unused_unsafe with compiler-generated unsafe
Browse files Browse the repository at this point in the history
  • Loading branch information
camsteffen committed Jun 21, 2021
1 parent 39260f6 commit b07bb6d
Show file tree
Hide file tree
Showing 9 changed files with 43 additions and 25 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,8 @@ impl<'tcx> Body<'tcx> {
#[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum Safety {
Safe,
/// Unsafe because of compiler-generated unsafe code, like `await` desugaring
BuiltinUnsafe,
/// Unsafe because of an unsafe fn
FnUnsafe,
/// Unsafe because of an `unsafe` block
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/thir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ pub struct Adt<'tcx> {
#[derive(Copy, Clone, Debug, HashStable)]
pub enum BlockSafety {
Safe,
BuiltinUnsafe,
ExplicitUnsafe(hir::HirId),
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir/src/transform/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
}
false
}
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
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/build/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
debug!("update_source_scope_for({:?}, {:?})", span, safety_mode);
let new_unsafety = match safety_mode {
BlockSafety::Safe => None,
BlockSafety::BuiltinUnsafe => Some(Safety::BuiltinUnsafe),
BlockSafety::ExplicitUnsafe(hir_id) => {
match self.in_scope_unsafe {
Safety::Safe => {}
Expand Down
33 changes: 20 additions & 13 deletions compiler/rustc_mir_build/src/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,7 @@ struct UnsafetyVisitor<'a, 'tcx> {
}

impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
fn in_safety_context<R>(
&mut self,
safety_context: SafetyContext,
f: impl FnOnce(&mut Self) -> R,
) {
fn in_safety_context(&mut self, safety_context: SafetyContext, f: impl FnOnce(&mut Self)) {
if let (
SafetyContext::UnsafeBlock { span: enclosing_span, .. },
SafetyContext::UnsafeBlock { span: block_span, hir_id, .. },
Expand Down Expand Up @@ -63,14 +59,14 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
);
}
self.safety_context = prev_context;
return;
}
}

fn requires_unsafe(&mut self, span: Span, kind: UnsafeOpKind) {
let (description, note) = kind.description_and_note();
let unsafe_op_in_unsafe_fn_allowed = self.unsafe_op_in_unsafe_fn_allowed();
match self.safety_context {
SafetyContext::BuiltinUnsafeBlock => {}
SafetyContext::UnsafeBlock { ref mut used, .. } => {
if !self.body_unsafety.is_unsafe() || !unsafe_op_in_unsafe_fn_allowed {
// Mark this block as useful
Expand Down Expand Up @@ -142,13 +138,23 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
}

fn visit_block(&mut self, block: &Block) {
if let BlockSafety::ExplicitUnsafe(hir_id) = block.safety_mode {
self.in_safety_context(
SafetyContext::UnsafeBlock { span: block.span, hir_id, used: false },
|this| visit::walk_block(this, block),
);
} else {
visit::walk_block(self, block);
match block.safety_mode {
// compiler-generated unsafe code should not count towards the usefulness of
// an outer unsafe block
BlockSafety::BuiltinUnsafe => {
self.in_safety_context(SafetyContext::BuiltinUnsafeBlock, |this| {
visit::walk_block(this, block)
});
}
BlockSafety::ExplicitUnsafe(hir_id) => {
self.in_safety_context(
SafetyContext::UnsafeBlock { span: block.span, hir_id, used: false },
|this| visit::walk_block(this, block),
);
}
BlockSafety::Safe => {
visit::walk_block(self, block);
}
}
}

Expand Down Expand Up @@ -250,6 +256,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
#[derive(Clone, Copy)]
enum SafetyContext {
Safe,
BuiltinUnsafeBlock,
UnsafeFn,
UnsafeBlock { span: Span, hir_id: hir::HirId, used: bool },
}
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_mir_build/src/thir/cx/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ impl<'tcx> Cx<'tcx> {
expr: block.expr.map(|expr| self.mirror_expr(expr)),
safety_mode: match block.rules {
hir::BlockCheckMode::DefaultBlock => BlockSafety::Safe,
hir::BlockCheckMode::UnsafeBlock(..) => BlockSafety::ExplicitUnsafe(block.hir_id),
hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated) => {
BlockSafety::BuiltinUnsafe
}
hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) => {
BlockSafety::ExplicitUnsafe(block.hir_id)
}
},
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: unnecessary `unsafe` block
--> $DIR/unsafe-around-compiler-generated-unsafe.rs:9:5
--> $DIR/unsafe-around-compiler-generated-unsafe.rs:9:9
|
LL | unsafe { println!("foo"); }
| ^^^^^^ unnecessary `unsafe` block
LL | unsafe { async {}.await; }
| ^^^^^^ unnecessary `unsafe` block
|
note: the lint level is defined here
--> $DIR/unsafe-around-compiler-generated-unsafe.rs:6:9
--> $DIR/unsafe-around-compiler-generated-unsafe.rs:5:9
|
LL | #![deny(unused_unsafe)]
| ^^^^^^^^^^^^^
Expand Down
7 changes: 4 additions & 3 deletions src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// issue #12418

// edition:2018
// revisions: mir thir
// [thir]compile-flags: -Z thir-unsafeck

#![deny(unused_unsafe)]

fn main() {
unsafe { println!("foo"); } //~ ERROR unnecessary `unsafe`
let _ = async {
unsafe { async {}.await; } //~ ERROR unnecessary `unsafe`
};
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: unnecessary `unsafe` block
--> $DIR/unsafe-around-compiler-generated-unsafe.rs:9:5
--> $DIR/unsafe-around-compiler-generated-unsafe.rs:9:9
|
LL | unsafe { println!("foo"); }
| ^^^^^^ unnecessary `unsafe` block
LL | unsafe { async {}.await; }
| ^^^^^^ unnecessary `unsafe` block
|
note: the lint level is defined here
--> $DIR/unsafe-around-compiler-generated-unsafe.rs:6:9
--> $DIR/unsafe-around-compiler-generated-unsafe.rs:5:9
|
LL | #![deny(unused_unsafe)]
| ^^^^^^^^^^^^^
Expand Down

0 comments on commit b07bb6d

Please sign in to comment.