summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_transform/src/check_unsafety.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_transform/src/check_unsafety.rs')
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs55
1 files changed, 43 insertions, 12 deletions
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index f8f04214a..e783d1891 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -4,6 +4,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::hir_id::HirId;
use rustc_hir::intravisit;
+use rustc_hir::{BlockCheckMode, ExprKind, Node};
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::query::Providers;
@@ -101,12 +102,10 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
| StatementKind::Retag { .. }
| StatementKind::AscribeUserType(..)
| StatementKind::Coverage(..)
+ | StatementKind::Intrinsic(..)
| StatementKind::Nop => {
// safe (at least as emitted during MIR construction)
}
-
- // Move to above list once mir construction uses it.
- StatementKind::Intrinsic(..) => unreachable!(),
}
self.super_statement(statement, location);
}
@@ -472,6 +471,14 @@ fn unsafety_check_result<'tcx>(
// `mir_built` force this.
let body = &tcx.mir_built(def).borrow();
+ if body.should_skip() {
+ return tcx.arena.alloc(UnsafetyCheckResult {
+ violations: Vec::new(),
+ used_unsafe_blocks: FxHashSet::default(),
+ unused_unsafes: Some(Vec::new()),
+ });
+ }
+
let param_env = tcx.param_env(def.did);
let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env);
@@ -519,24 +526,48 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
for &UnsafetyViolation { source_info, lint_root, kind, details } in violations.iter() {
let (description, note) = details.description_and_note();
- // Report an error.
- let unsafe_fn_msg =
- if unsafe_op_in_unsafe_fn_allowed(tcx, lint_root) { " function or" } else { "" };
-
match kind {
UnsafetyViolationKind::General => {
// once
- struct_span_err!(
+ let unsafe_fn_msg = if unsafe_op_in_unsafe_fn_allowed(tcx, lint_root) {
+ " function or"
+ } else {
+ ""
+ };
+
+ let mut err = struct_span_err!(
tcx.sess,
source_info.span,
E0133,
"{} is unsafe and requires unsafe{} block",
description,
unsafe_fn_msg,
- )
- .span_label(source_info.span, description)
- .note(note)
- .emit();
+ );
+ err.span_label(source_info.span, description).note(note);
+ let note_non_inherited = tcx.hir().parent_iter(lint_root).find(|(id, node)| {
+ if let Node::Expr(block) = node
+ && let ExprKind::Block(block, _) = block.kind
+ && let BlockCheckMode::UnsafeBlock(_) = block.rules
+ {
+ true
+ }
+ else if let Some(sig) = tcx.hir().fn_sig_by_hir_id(*id)
+ && sig.header.is_unsafe()
+ {
+ true
+ } else {
+ false
+ }
+ });
+ if let Some((id, _)) = note_non_inherited {
+ let span = tcx.hir().span(id);
+ err.span_label(
+ tcx.sess.source_map().guess_head_span(span),
+ "items do not inherit unsafety from separate enclosing items",
+ );
+ }
+
+ err.emit();
}
UnsafetyViolationKind::UnsafeFn => tcx.struct_span_lint_hir(
UNSAFE_OP_IN_UNSAFE_FN,