mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-28 01:34:21 +00:00
Add helper for switching safety contexts
This commit is contained in:
parent
d5ea294114
commit
985fb4caa0
@ -21,6 +21,36 @@ struct 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) {
|
||||
let (description, note) = kind.description_and_note();
|
||||
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> {
|
||||
fn visit_block(&mut self, block: &Block<'thir, 'tcx>) {
|
||||
if let BlockSafety::ExplicitUnsafe(hir_id) = block.safety_mode {
|
||||
if let SafetyContext::UnsafeBlock { span: enclosing_span, .. } = self.safety_context {
|
||||
self.warn_unused_unsafe(
|
||||
hir_id,
|
||||
block.span,
|
||||
Some(self.tcx.sess.source_map().guess_head_span(enclosing_span)),
|
||||
);
|
||||
} else {
|
||||
let prev_context = self.safety_context;
|
||||
self.safety_context =
|
||||
SafetyContext::UnsafeBlock { span: block.span, hir_id, used: false };
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
visit::walk_block(self, block);
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'thir Expr<'thir, 'tcx>) {
|
||||
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;
|
||||
self.hir_context = hir_id;
|
||||
self.visit_expr(value);
|
||||
self.hir_context = prev_id;
|
||||
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 {
|
||||
self.requires_unsafe(expr.span, CallToUnsafeFunction);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ pub fn walk_expr<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
|
||||
) {
|
||||
use ExprKind::*;
|
||||
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),
|
||||
If { cond, then, else_opt } => {
|
||||
visitor.visit_expr(cond);
|
||||
@ -35,22 +35,22 @@ pub fn walk_expr<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
|
||||
visitor.visit_expr(else_expr);
|
||||
}
|
||||
}
|
||||
Call { fun, args, .. } => {
|
||||
Call { fun, args, ty: _, from_hir_call: _, fn_span: _ } => {
|
||||
visitor.visit_expr(fun);
|
||||
for arg in args {
|
||||
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(rhs);
|
||||
}
|
||||
Unary { arg, .. } => visitor.visit_expr(arg),
|
||||
Unary { arg, op: _ } => visitor.visit_expr(arg),
|
||||
Cast { source } => visitor.visit_expr(source),
|
||||
Use { 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),
|
||||
Match { scrutinee, arms } => {
|
||||
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),
|
||||
Assign { lhs, rhs } | AssignOp { lhs, rhs, .. } => {
|
||||
Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => {
|
||||
visitor.visit_expr(lhs);
|
||||
visitor.visit_expr(rhs);
|
||||
}
|
||||
Field { lhs, .. } => visitor.visit_expr(lhs),
|
||||
Field { lhs, name: _ } => visitor.visit_expr(lhs),
|
||||
Index { lhs, index } => {
|
||||
visitor.visit_expr(lhs);
|
||||
visitor.visit_expr(index);
|
||||
}
|
||||
VarRef { .. } | UpvarRef { .. } => {}
|
||||
Borrow { arg, .. } => visitor.visit_expr(arg),
|
||||
AddressOf { arg, .. } => visitor.visit_expr(arg),
|
||||
Break { value, .. } => {
|
||||
VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {}
|
||||
Borrow { arg, borrow_kind: _ } => visitor.visit_expr(arg),
|
||||
AddressOf { arg, mutability: _ } => visitor.visit_expr(arg),
|
||||
Break { value, label: _ } => {
|
||||
if let Some(value) = value {
|
||||
visitor.visit_expr(value)
|
||||
}
|
||||
}
|
||||
Continue { .. } => {}
|
||||
Continue { label: _ } => {}
|
||||
Return { value } => {
|
||||
if let Some(value) = value {
|
||||
visitor.visit_expr(value)
|
||||
@ -92,7 +92,7 @@ pub fn walk_expr<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
|
||||
visitor.visit_expr(field);
|
||||
}
|
||||
}
|
||||
Adt { fields, ref base, .. } => {
|
||||
Adt { fields, ref base, adt_def: _, variant_index: _, substs: _, user_ty: _ } => {
|
||||
for field in fields {
|
||||
visitor.visit_expr(field.expr);
|
||||
}
|
||||
@ -100,32 +100,34 @@ pub fn walk_expr<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
|
||||
visitor.visit_expr(base.base);
|
||||
}
|
||||
}
|
||||
PlaceTypeAscription { source, .. } | ValueTypeAscription { source, .. } => {
|
||||
PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => {
|
||||
visitor.visit_expr(source)
|
||||
}
|
||||
Closure { .. } => {}
|
||||
Literal { literal, .. } => visitor.visit_const(literal),
|
||||
StaticRef { literal, .. } => visitor.visit_const(literal),
|
||||
InlineAsm { operands, .. } => {
|
||||
Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {}
|
||||
Literal { literal, user_ty: _, const_id: _ } => visitor.visit_const(literal),
|
||||
StaticRef { literal, def_id: _ } => visitor.visit_const(literal),
|
||||
InlineAsm { operands, template: _, options: _, line_spans: _ } => {
|
||||
for op in operands {
|
||||
use InlineAsmOperand::*;
|
||||
match op {
|
||||
In { expr, .. }
|
||||
| Out { expr: Some(expr), .. }
|
||||
| InOut { expr, .. }
|
||||
In { expr, reg: _ }
|
||||
| Out { expr: Some(expr), reg: _, late: _ }
|
||||
| InOut { expr, reg: _, late: _ }
|
||||
| SymFn { expr } => visitor.visit_expr(expr),
|
||||
SplitInOut { in_expr, out_expr, .. } => {
|
||||
SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
|
||||
visitor.visit_expr(in_expr);
|
||||
if let Some(out_expr) = out_expr {
|
||||
visitor.visit_expr(out_expr);
|
||||
}
|
||||
}
|
||||
Out { .. } | Const { .. } | SymStatic { .. } => {}
|
||||
Out { expr: None, reg: _, late: _ }
|
||||
| Const { value: _, span: _ }
|
||||
| SymStatic { def_id: _ } => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
ThreadLocalRef(_) => {}
|
||||
LlvmInlineAsm { outputs, inputs, .. } => {
|
||||
LlvmInlineAsm { outputs, inputs, asm: _ } => {
|
||||
for out_expr in outputs {
|
||||
visitor.visit_expr(out_expr);
|
||||
}
|
||||
@ -142,8 +144,14 @@ pub fn walk_stmt<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
|
||||
stmt: &'thir Stmt<'thir, 'tcx>,
|
||||
) {
|
||||
match stmt.kind {
|
||||
StmtKind::Expr { expr, .. } => visitor.visit_expr(expr),
|
||||
StmtKind::Let { pattern: _, initializer, .. } => {
|
||||
StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(expr),
|
||||
StmtKind::Let {
|
||||
initializer,
|
||||
remainder_scope: _,
|
||||
init_scope: _,
|
||||
pattern: _,
|
||||
lint_level: _,
|
||||
} => {
|
||||
if let Some(init) = initializer {
|
||||
visitor.visit_expr(init);
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ use std::path::Path;
|
||||
|
||||
const ENTRY_LIMIT: usize = 1000;
|
||||
// FIXME: The following limits should be reduced eventually.
|
||||
const ROOT_ENTRY_LIMIT: usize = 1369;
|
||||
const ISSUES_ENTRY_LIMIT: usize = 2551;
|
||||
const ROOT_ENTRY_LIMIT: usize = 1370;
|
||||
const ISSUES_ENTRY_LIMIT: usize = 2555;
|
||||
|
||||
fn check_entries(path: &Path, bad: &mut bool) {
|
||||
let dirs = walkdir::WalkDir::new(&path.join("test/ui"))
|
||||
|
Loading…
Reference in New Issue
Block a user