1
Fork 0

Add helper for switching safety contexts

This commit is contained in:
LeSeulArtichaut 2021-04-03 22:45:33 +02:00
parent d5ea294114
commit 985fb4caa0
3 changed files with 74 additions and 51 deletions

View file

@ -21,6 +21,36 @@ struct UnsafetyVisitor<'tcx> {
} }
impl<'tcx> UnsafetyVisitor<'tcx> { impl<'tcx> UnsafetyVisitor<'tcx> {
fn in_safety_context<R>(
&mut self,
safety_context: SafetyContext,
f: impl FnOnce(&mut Self) -> R,
) {
if let (
SafetyContext::UnsafeBlock { span: enclosing_span, .. },
SafetyContext::UnsafeBlock { span: block_span, hir_id, .. },
) = (self.safety_context, safety_context)
{
self.warn_unused_unsafe(
hir_id,
block_span,
Some(self.tcx.sess.source_map().guess_head_span(enclosing_span)),
);
f(self);
} else {
let prev_context = self.safety_context;
self.safety_context = safety_context;
f(self);
if let SafetyContext::UnsafeBlock { used: false, span, hir_id } = self.safety_context {
self.warn_unused_unsafe(hir_id, span, self.body_unsafety.unsafe_fn_sig_span());
}
self.safety_context = prev_context;
return;
}
}
fn requires_unsafe(&mut self, span: Span, kind: UnsafeOpKind) { fn requires_unsafe(&mut self, span: Span, kind: UnsafeOpKind) {
let (description, note) = kind.description_and_note(); let (description, note) = kind.description_and_note();
let unsafe_op_in_unsafe_fn_allowed = self.unsafe_op_in_unsafe_fn_allowed(); let unsafe_op_in_unsafe_fn_allowed = self.unsafe_op_in_unsafe_fn_allowed();
@ -100,40 +130,25 @@ impl<'tcx> UnsafetyVisitor<'tcx> {
impl<'thir, 'tcx> Visitor<'thir, 'tcx> for UnsafetyVisitor<'tcx> { impl<'thir, 'tcx> Visitor<'thir, 'tcx> for UnsafetyVisitor<'tcx> {
fn visit_block(&mut self, block: &Block<'thir, 'tcx>) { fn visit_block(&mut self, block: &Block<'thir, 'tcx>) {
if let BlockSafety::ExplicitUnsafe(hir_id) = block.safety_mode { if let BlockSafety::ExplicitUnsafe(hir_id) = block.safety_mode {
if let SafetyContext::UnsafeBlock { span: enclosing_span, .. } = self.safety_context { self.in_safety_context(
self.warn_unused_unsafe( SafetyContext::UnsafeBlock { span: block.span, hir_id, used: false },
hir_id, |this| visit::walk_block(this, block),
block.span,
Some(self.tcx.sess.source_map().guess_head_span(enclosing_span)),
); );
} else { } else {
let prev_context = self.safety_context;
self.safety_context =
SafetyContext::UnsafeBlock { span: block.span, hir_id, used: false };
visit::walk_block(self, block); visit::walk_block(self, block);
if let SafetyContext::UnsafeBlock { used: false, span, hir_id } =
self.safety_context
{
self.warn_unused_unsafe(hir_id, span, self.body_unsafety.unsafe_fn_sig_span());
} }
self.safety_context = prev_context;
return;
}
}
visit::walk_block(self, block);
} }
fn visit_expr(&mut self, expr: &'thir Expr<'thir, 'tcx>) { fn visit_expr(&mut self, expr: &'thir Expr<'thir, 'tcx>) {
match expr.kind { match expr.kind {
ExprKind::Scope { value, lint_level: LintLevel::Explicit(hir_id), .. } => { ExprKind::Scope { value, lint_level: LintLevel::Explicit(hir_id), region_scope: _ } => {
let prev_id = self.hir_context; let prev_id = self.hir_context;
self.hir_context = hir_id; self.hir_context = hir_id;
self.visit_expr(value); self.visit_expr(value);
self.hir_context = prev_id; self.hir_context = prev_id;
return; return;
} }
ExprKind::Call { fun, .. } => { ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => {
if fun.ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe { if fun.ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
self.requires_unsafe(expr.span, CallToUnsafeFunction); self.requires_unsafe(expr.span, CallToUnsafeFunction);
} }

View file

@ -26,7 +26,7 @@ pub fn walk_expr<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
) { ) {
use ExprKind::*; use ExprKind::*;
match expr.kind { match expr.kind {
Scope { value, .. } => visitor.visit_expr(value), Scope { value, region_scope: _, lint_level: _ } => visitor.visit_expr(value),
Box { value } => visitor.visit_expr(value), Box { value } => visitor.visit_expr(value),
If { cond, then, else_opt } => { If { cond, then, else_opt } => {
visitor.visit_expr(cond); visitor.visit_expr(cond);
@ -35,22 +35,22 @@ pub fn walk_expr<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
visitor.visit_expr(else_expr); visitor.visit_expr(else_expr);
} }
} }
Call { fun, args, .. } => { Call { fun, args, ty: _, from_hir_call: _, fn_span: _ } => {
visitor.visit_expr(fun); visitor.visit_expr(fun);
for arg in args { for arg in args {
visitor.visit_expr(arg); visitor.visit_expr(arg);
} }
} }
Deref { arg } => visitor.visit_expr(arg), Deref { arg } => visitor.visit_expr(arg),
Binary { lhs, rhs, .. } | LogicalOp { lhs, rhs, .. } => { Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => {
visitor.visit_expr(lhs); visitor.visit_expr(lhs);
visitor.visit_expr(rhs); visitor.visit_expr(rhs);
} }
Unary { arg, .. } => visitor.visit_expr(arg), Unary { arg, op: _ } => visitor.visit_expr(arg),
Cast { source } => visitor.visit_expr(source), Cast { source } => visitor.visit_expr(source),
Use { source } => visitor.visit_expr(source), Use { source } => visitor.visit_expr(source),
NeverToAny { source } => visitor.visit_expr(source), NeverToAny { source } => visitor.visit_expr(source),
Pointer { source, .. } => visitor.visit_expr(source), Pointer { source, cast: _ } => visitor.visit_expr(source),
Loop { body } => visitor.visit_expr(body), Loop { body } => visitor.visit_expr(body),
Match { scrutinee, arms } => { Match { scrutinee, arms } => {
visitor.visit_expr(scrutinee); visitor.visit_expr(scrutinee);
@ -59,24 +59,24 @@ pub fn walk_expr<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
} }
} }
Block { ref body } => visitor.visit_block(body), Block { ref body } => visitor.visit_block(body),
Assign { lhs, rhs } | AssignOp { lhs, rhs, .. } => { Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => {
visitor.visit_expr(lhs); visitor.visit_expr(lhs);
visitor.visit_expr(rhs); visitor.visit_expr(rhs);
} }
Field { lhs, .. } => visitor.visit_expr(lhs), Field { lhs, name: _ } => visitor.visit_expr(lhs),
Index { lhs, index } => { Index { lhs, index } => {
visitor.visit_expr(lhs); visitor.visit_expr(lhs);
visitor.visit_expr(index); visitor.visit_expr(index);
} }
VarRef { .. } | UpvarRef { .. } => {} VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {}
Borrow { arg, .. } => visitor.visit_expr(arg), Borrow { arg, borrow_kind: _ } => visitor.visit_expr(arg),
AddressOf { arg, .. } => visitor.visit_expr(arg), AddressOf { arg, mutability: _ } => visitor.visit_expr(arg),
Break { value, .. } => { Break { value, label: _ } => {
if let Some(value) = value { if let Some(value) = value {
visitor.visit_expr(value) visitor.visit_expr(value)
} }
} }
Continue { .. } => {} Continue { label: _ } => {}
Return { value } => { Return { value } => {
if let Some(value) = value { if let Some(value) = value {
visitor.visit_expr(value) visitor.visit_expr(value)
@ -92,7 +92,7 @@ pub fn walk_expr<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
visitor.visit_expr(field); visitor.visit_expr(field);
} }
} }
Adt { fields, ref base, .. } => { Adt { fields, ref base, adt_def: _, variant_index: _, substs: _, user_ty: _ } => {
for field in fields { for field in fields {
visitor.visit_expr(field.expr); visitor.visit_expr(field.expr);
} }
@ -100,32 +100,34 @@ pub fn walk_expr<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
visitor.visit_expr(base.base); visitor.visit_expr(base.base);
} }
} }
PlaceTypeAscription { source, .. } | ValueTypeAscription { source, .. } => { PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => {
visitor.visit_expr(source) visitor.visit_expr(source)
} }
Closure { .. } => {} Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {}
Literal { literal, .. } => visitor.visit_const(literal), Literal { literal, user_ty: _, const_id: _ } => visitor.visit_const(literal),
StaticRef { literal, .. } => visitor.visit_const(literal), StaticRef { literal, def_id: _ } => visitor.visit_const(literal),
InlineAsm { operands, .. } => { InlineAsm { operands, template: _, options: _, line_spans: _ } => {
for op in operands { for op in operands {
use InlineAsmOperand::*; use InlineAsmOperand::*;
match op { match op {
In { expr, .. } In { expr, reg: _ }
| Out { expr: Some(expr), .. } | Out { expr: Some(expr), reg: _, late: _ }
| InOut { expr, .. } | InOut { expr, reg: _, late: _ }
| SymFn { expr } => visitor.visit_expr(expr), | SymFn { expr } => visitor.visit_expr(expr),
SplitInOut { in_expr, out_expr, .. } => { SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
visitor.visit_expr(in_expr); visitor.visit_expr(in_expr);
if let Some(out_expr) = out_expr { if let Some(out_expr) = out_expr {
visitor.visit_expr(out_expr); visitor.visit_expr(out_expr);
} }
} }
Out { .. } | Const { .. } | SymStatic { .. } => {} Out { expr: None, reg: _, late: _ }
| Const { value: _, span: _ }
| SymStatic { def_id: _ } => {}
} }
} }
} }
ThreadLocalRef(_) => {} ThreadLocalRef(_) => {}
LlvmInlineAsm { outputs, inputs, .. } => { LlvmInlineAsm { outputs, inputs, asm: _ } => {
for out_expr in outputs { for out_expr in outputs {
visitor.visit_expr(out_expr); visitor.visit_expr(out_expr);
} }
@ -142,8 +144,14 @@ pub fn walk_stmt<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
stmt: &'thir Stmt<'thir, 'tcx>, stmt: &'thir Stmt<'thir, 'tcx>,
) { ) {
match stmt.kind { match stmt.kind {
StmtKind::Expr { expr, .. } => visitor.visit_expr(expr), StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(expr),
StmtKind::Let { pattern: _, initializer, .. } => { StmtKind::Let {
initializer,
remainder_scope: _,
init_scope: _,
pattern: _,
lint_level: _,
} => {
if let Some(init) = initializer { if let Some(init) = initializer {
visitor.visit_expr(init); visitor.visit_expr(init);
} }

View file

@ -7,8 +7,8 @@ use std::path::Path;
const ENTRY_LIMIT: usize = 1000; const ENTRY_LIMIT: usize = 1000;
// FIXME: The following limits should be reduced eventually. // FIXME: The following limits should be reduced eventually.
const ROOT_ENTRY_LIMIT: usize = 1369; const ROOT_ENTRY_LIMIT: usize = 1370;
const ISSUES_ENTRY_LIMIT: usize = 2551; const ISSUES_ENTRY_LIMIT: usize = 2555;
fn check_entries(path: &Path, bad: &mut bool) { fn check_entries(path: &Path, bad: &mut bool) {
let dirs = walkdir::WalkDir::new(&path.join("test/ui")) let dirs = walkdir::WalkDir::new(&path.join("test/ui"))