summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_transform/src/check_unsafety.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs115
1 files changed, 27 insertions, 88 deletions
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index d564f4801..f8f04214a 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -1,17 +1,16 @@
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::FxHashSet;
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::hir_id::HirId;
use rustc_hir::intravisit;
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
+use rustc_middle::mir::*;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt};
-use rustc_middle::{lint, mir::*};
use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
use rustc_session::lint::Level;
-use std::collections::hash_map;
use std::ops::Bound;
pub struct UnsafetyChecker<'a, 'tcx> {
@@ -23,10 +22,7 @@ pub struct UnsafetyChecker<'a, 'tcx> {
param_env: ty::ParamEnv<'tcx>,
/// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint.
- ///
- /// The keys are the used `unsafe` blocks, the UnusedUnsafeKind indicates whether
- /// or not any of the usages happen at a place that doesn't allow `unsafe_op_in_unsafe_fn`.
- used_unsafe_blocks: FxHashMap<HirId, UsedUnsafeBlockData>,
+ used_unsafe_blocks: FxHashSet<HirId>,
}
impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
@@ -109,7 +105,8 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
// safe (at least as emitted during MIR construction)
}
- StatementKind::CopyNonOverlapping(..) => unreachable!(),
+ // Move to above list once mir construction uses it.
+ StatementKind::Intrinsic(..) => unreachable!(),
}
self.super_statement(statement, location);
}
@@ -130,10 +127,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
&AggregateKind::Closure(def_id, _) | &AggregateKind::Generator(def_id, _, _) => {
let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
self.tcx.unsafety_check_result(def_id);
- self.register_violations(
- violations,
- used_unsafe_blocks.iter().map(|(&h, &d)| (h, d)),
- );
+ self.register_violations(violations, used_unsafe_blocks.iter().copied());
}
},
_ => {}
@@ -257,22 +251,8 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
fn register_violations<'a>(
&mut self,
violations: impl IntoIterator<Item = &'a UnsafetyViolation>,
- new_used_unsafe_blocks: impl IntoIterator<Item = (HirId, UsedUnsafeBlockData)>,
+ new_used_unsafe_blocks: impl IntoIterator<Item = HirId>,
) {
- use UsedUnsafeBlockData::{AllAllowedInUnsafeFn, SomeDisallowedInUnsafeFn};
-
- let update_entry = |this: &mut Self, hir_id, new_usage| {
- match this.used_unsafe_blocks.entry(hir_id) {
- hash_map::Entry::Occupied(mut entry) => {
- if new_usage == SomeDisallowedInUnsafeFn {
- *entry.get_mut() = SomeDisallowedInUnsafeFn;
- }
- }
- hash_map::Entry::Vacant(entry) => {
- entry.insert(new_usage);
- }
- };
- };
let safety = self.body.source_scopes[self.source_info.scope]
.local_data
.as_ref()
@@ -299,22 +279,14 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
}
}),
Safety::BuiltinUnsafe => {}
- Safety::ExplicitUnsafe(hir_id) => violations.into_iter().for_each(|violation| {
- update_entry(
- self,
- hir_id,
- match self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, violation.lint_root).0
- {
- Level::Allow => AllAllowedInUnsafeFn(violation.lint_root),
- _ => SomeDisallowedInUnsafeFn,
- },
- )
+ Safety::ExplicitUnsafe(hir_id) => violations.into_iter().for_each(|_violation| {
+ self.used_unsafe_blocks.insert(hir_id);
}),
};
- new_used_unsafe_blocks
- .into_iter()
- .for_each(|(hir_id, usage_data)| update_entry(self, hir_id, usage_data));
+ new_used_unsafe_blocks.into_iter().for_each(|hir_id| {
+ self.used_unsafe_blocks.insert(hir_id);
+ });
}
fn check_mut_borrowing_layout_constrained_field(
&mut self,
@@ -340,7 +312,7 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
} else if !place
.ty(self.body, self.tcx)
.ty
- .is_freeze(self.tcx.at(self.source_info.span), self.param_env)
+ .is_freeze(self.tcx, self.param_env)
{
UnsafetyViolationDetails::BorrowOfLayoutConstrainedField
} else {
@@ -411,34 +383,28 @@ enum Context {
struct UnusedUnsafeVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- used_unsafe_blocks: &'a FxHashMap<HirId, UsedUnsafeBlockData>,
+ used_unsafe_blocks: &'a FxHashSet<HirId>,
context: Context,
unused_unsafes: &'a mut Vec<(HirId, UnusedUnsafe)>,
}
impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_, 'tcx> {
fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) {
- use UsedUnsafeBlockData::{AllAllowedInUnsafeFn, SomeDisallowedInUnsafeFn};
-
if let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = block.rules {
let used = match self.tcx.lint_level_at_node(UNUSED_UNSAFE, block.hir_id) {
- (Level::Allow, _) => Some(SomeDisallowedInUnsafeFn),
- _ => self.used_unsafe_blocks.get(&block.hir_id).copied(),
+ (Level::Allow, _) => true,
+ _ => self.used_unsafe_blocks.contains(&block.hir_id),
};
let unused_unsafe = match (self.context, used) {
- (_, None) => UnusedUnsafe::Unused,
- (Context::Safe, Some(_))
- | (Context::UnsafeFn(_), Some(SomeDisallowedInUnsafeFn)) => {
+ (_, false) => UnusedUnsafe::Unused,
+ (Context::Safe, true) | (Context::UnsafeFn(_), true) => {
let previous_context = self.context;
self.context = Context::UnsafeBlock(block.hir_id);
intravisit::walk_block(self, block);
self.context = previous_context;
return;
}
- (Context::UnsafeFn(hir_id), Some(AllAllowedInUnsafeFn(lint_root))) => {
- UnusedUnsafe::InUnsafeFn(hir_id, lint_root)
- }
- (Context::UnsafeBlock(hir_id), Some(_)) => UnusedUnsafe::InUnsafeBlock(hir_id),
+ (Context::UnsafeBlock(hir_id), true) => UnusedUnsafe::InUnsafeBlock(hir_id),
};
self.unused_unsafes.push((block.hir_id, unused_unsafe));
}
@@ -462,7 +428,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_, 'tcx> {
fn check_unused_unsafe(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
- used_unsafe_blocks: &FxHashMap<HirId, UsedUnsafeBlockData>,
+ used_unsafe_blocks: &FxHashSet<HirId>,
) -> Vec<(HirId, UnusedUnsafe)> {
let body_id = tcx.hir().maybe_body_owned_by(def_id);
@@ -523,40 +489,20 @@ fn unsafety_check_result<'tcx>(
fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) {
let span = tcx.sess.source_map().guess_head_span(tcx.hir().span(id));
- tcx.struct_span_lint_hir(UNUSED_UNSAFE, id, span, |lint| {
- let msg = "unnecessary `unsafe` block";
- let mut db = lint.build(msg);
- db.span_label(span, msg);
+ 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) => {
- db.span_label(
+ lint.span_label(
tcx.sess.source_map().guess_head_span(tcx.hir().span(id)),
"because it's nested under this `unsafe` block",
);
}
- UnusedUnsafe::InUnsafeFn(id, usage_lint_root) => {
- db.span_label(
- tcx.sess.source_map().guess_head_span(tcx.hir().span(id)),
- "because it's nested under this `unsafe` fn",
- )
- .note(
- "this `unsafe` block does contain unsafe operations, \
- but those are already allowed in an `unsafe fn`",
- );
- let (level, source) =
- tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, usage_lint_root);
- assert_eq!(level, Level::Allow);
- lint::explain_lint_level_source(
- UNSAFE_OP_IN_UNSAFE_FN,
- Level::Allow,
- source,
- &mut db,
- );
- }
}
- db.emit();
+ lint
});
}
@@ -596,15 +542,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
UNSAFE_OP_IN_UNSAFE_FN,
lint_root,
source_info.span,
- |lint| {
- lint.build(&format!(
- "{} is unsafe and requires unsafe block (error E0133)",
- description,
- ))
- .span_label(source_info.span, description)
- .note(note)
- .emit();
- },
+ format!("{} is unsafe and requires unsafe block (error E0133)", description,),
+ |lint| lint.span_label(source_info.span, description).note(note),
),
}
}