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.rs102
1 files changed, 31 insertions, 71 deletions
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index d908f6b3a..069514d8a 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -1,5 +1,4 @@
use rustc_data_structures::unord::{UnordItems, UnordSet};
-use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
@@ -8,13 +7,15 @@ 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;
+use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
use rustc_session::lint::Level;
use std::ops::Bound;
+use crate::errors;
+
pub struct UnsafetyChecker<'a, 'tcx> {
body: &'a Body<'tcx>,
body_did: LocalDefId,
@@ -148,7 +149,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
if let Some(uv) = maybe_uneval {
if uv.promoted.is_none() {
- let def_id = uv.def.def_id_for_type_of();
+ let def_id = uv.def;
if self.tcx.def_kind(def_id) == DefKind::InlineConst {
let local_def_id = def_id.expect_local();
let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
@@ -375,22 +376,7 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
}
pub(crate) fn provide(providers: &mut Providers) {
- *providers = Providers {
- unsafety_check_result: |tcx, def_id| {
- if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
- tcx.unsafety_check_result_for_const_arg(def)
- } else {
- unsafety_check_result(tcx, ty::WithOptConstParam::unknown(def_id))
- }
- },
- unsafety_check_result_for_const_arg: |tcx, (did, param_did)| {
- unsafety_check_result(
- tcx,
- ty::WithOptConstParam { did, const_param_did: Some(param_did) },
- )
- },
- ..*providers
- };
+ *providers = Providers { unsafety_check_result, ..*providers };
}
/// Context information for [`UnusedUnsafeVisitor`] traversal,
@@ -492,10 +478,7 @@ fn check_unused_unsafe(
unused_unsafes
}
-fn unsafety_check_result(
- tcx: TyCtxt<'_>,
- def: ty::WithOptConstParam<LocalDefId>,
-) -> &UnsafetyCheckResult {
+fn unsafety_check_result(tcx: TyCtxt<'_>, def: LocalDefId) -> &UnsafetyCheckResult {
debug!("unsafety_violations({:?})", def);
// N.B., this borrow is valid because all the consumers of
@@ -510,13 +493,13 @@ fn unsafety_check_result(
});
}
- let param_env = tcx.param_env(def.did);
+ let param_env = tcx.param_env(def);
- let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env);
+ let mut checker = UnsafetyChecker::new(body, def, tcx, param_env);
checker.visit_body(&body);
- let unused_unsafes = (!tcx.is_typeck_child(def.did.to_def_id()))
- .then(|| check_unused_unsafe(tcx, def.did, &checker.used_unsafe_blocks));
+ let unused_unsafes = (!tcx.is_typeck_child(def.to_def_id()))
+ .then(|| check_unused_unsafe(tcx, def, &checker.used_unsafe_blocks));
tcx.arena.alloc(UnsafetyCheckResult {
violations: checker.violations,
@@ -527,21 +510,12 @@ fn unsafety_check_result(
fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) {
let span = tcx.sess.source_map().guess_head_span(tcx.hir().span(id));
- let msg = "unnecessary `unsafe` block";
- tcx.struct_span_lint_hir(UNUSED_UNSAFE, id, span, msg, |lint| {
- lint.span_label(span, msg);
- match kind {
- UnusedUnsafe::Unused => {}
- UnusedUnsafe::InUnsafeBlock(id) => {
- lint.span_label(
- tcx.sess.source_map().guess_head_span(tcx.hir().span(id)),
- "because it's nested under this `unsafe` block",
- );
- }
- }
-
- lint
- });
+ let nested_parent = if let UnusedUnsafe::InUnsafeBlock(id) = kind {
+ Some(tcx.sess.source_map().guess_head_span(tcx.hir().span(id)))
+ } else {
+ None
+ };
+ tcx.emit_spanned_lint(UNUSED_UNSAFE, id, span, errors::UnusedUnsafe { span, nested_parent });
}
pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
@@ -555,26 +529,11 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let UnsafetyCheckResult { violations, unused_unsafes, .. } = tcx.unsafety_check_result(def_id);
for &UnsafetyViolation { source_info, lint_root, kind, details } in violations.iter() {
- let (description, note) = details.description_and_note();
+ let details = errors::RequiresUnsafeDetail { violation: details, span: source_info.span };
match kind {
UnsafetyViolationKind::General => {
- // once
- 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,
- );
- err.span_label(source_info.span, description).note(note);
+ let op_in_unsafe_fn_allowed = unsafe_op_in_unsafe_fn_allowed(tcx, lint_root);
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
@@ -590,22 +549,23 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
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();
+ let enclosing = if let Some((id, _)) = note_non_inherited {
+ Some(tcx.sess.source_map().guess_head_span(tcx.hir().span(id)))
+ } else {
+ None
+ };
+ tcx.sess.emit_err(errors::RequiresUnsafe {
+ span: source_info.span,
+ enclosing,
+ details,
+ op_in_unsafe_fn_allowed,
+ });
}
- UnsafetyViolationKind::UnsafeFn => tcx.struct_span_lint_hir(
+ UnsafetyViolationKind::UnsafeFn => tcx.emit_spanned_lint(
UNSAFE_OP_IN_UNSAFE_FN,
lint_root,
source_info.span,
- format!("{} is unsafe and requires unsafe block (error E0133)", description,),
- |lint| lint.span_label(source_info.span, description).note(note),
+ errors::UnsafeOpInUnsafeFn { details },
),
}
}