Adapt the THIR visitor to the vec-stored THIR
This commit is contained in:
parent
dc3eabd487
commit
7093a21e27
@ -9,8 +9,9 @@ use rustc_session::lint::Level;
|
||||
use rustc_span::def_id::{DefId, LocalDefId};
|
||||
use rustc_span::Span;
|
||||
|
||||
struct UnsafetyVisitor<'tcx> {
|
||||
struct UnsafetyVisitor<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
thir: &'a Thir<'tcx>,
|
||||
/// The `HirId` of the current scope, which would be the `HirId`
|
||||
/// of the current HIR node, modulo adjustments. Used for lint levels.
|
||||
hir_context: hir::HirId,
|
||||
@ -20,7 +21,7 @@ struct UnsafetyVisitor<'tcx> {
|
||||
body_unsafety: BodyUnsafety,
|
||||
}
|
||||
|
||||
impl<'tcx> UnsafetyVisitor<'tcx> {
|
||||
impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
|
||||
fn in_safety_context<R>(
|
||||
&mut self,
|
||||
safety_context: SafetyContext,
|
||||
@ -127,8 +128,12 @@ impl<'tcx> UnsafetyVisitor<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'thir, 'tcx> Visitor<'thir, 'tcx> for UnsafetyVisitor<'tcx> {
|
||||
fn visit_block(&mut self, block: &Block<'thir, 'tcx>) {
|
||||
impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
||||
fn thir(&self) -> &'a Thir<'tcx> {
|
||||
&self.thir
|
||||
}
|
||||
|
||||
fn visit_block(&mut self, block: &Block) {
|
||||
if let BlockSafety::ExplicitUnsafe(hir_id) = block.safety_mode {
|
||||
self.in_safety_context(
|
||||
SafetyContext::UnsafeBlock { span: block.span, hir_id, used: false },
|
||||
@ -139,17 +144,17 @@ impl<'thir, 'tcx> Visitor<'thir, 'tcx> for UnsafetyVisitor<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'thir Expr<'thir, 'tcx>) {
|
||||
fn visit_expr(&mut self, expr: &Expr<'tcx>) {
|
||||
match expr.kind {
|
||||
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.visit_expr(&self.thir[value]);
|
||||
self.hir_context = prev_id;
|
||||
return;
|
||||
}
|
||||
ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => {
|
||||
if fun.ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
|
||||
if self.thir[fun].ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
|
||||
self.requires_unsafe(expr.span, CallToUnsafeFunction);
|
||||
}
|
||||
}
|
||||
@ -293,7 +298,12 @@ impl UnsafeOpKind {
|
||||
|
||||
// FIXME: checking unsafety for closures should be handled by their parent body,
|
||||
// as they inherit their "safety context" from their declaration site.
|
||||
pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, thir: &Expr<'_, 'tcx>, hir_id: hir::HirId) {
|
||||
pub fn check_unsafety<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
thir: &Thir<'tcx>,
|
||||
expr: ExprId,
|
||||
hir_id: hir::HirId,
|
||||
) {
|
||||
let body_unsafety = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(BodyUnsafety::Safe, |fn_sig| {
|
||||
if fn_sig.header.unsafety == hir::Unsafety::Unsafe {
|
||||
BodyUnsafety::Unsafe(fn_sig.span)
|
||||
@ -303,8 +313,9 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, thir: &Expr<'_, 'tcx>, hir_id: hi
|
||||
});
|
||||
let safety_context =
|
||||
if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe };
|
||||
let mut visitor = UnsafetyVisitor { tcx, safety_context, hir_context: hir_id, body_unsafety };
|
||||
visitor.visit_expr(thir);
|
||||
let mut visitor =
|
||||
UnsafetyVisitor { tcx, thir, safety_context, hir_context: hir_id, body_unsafety };
|
||||
visitor.visit_expr(&thir[expr]);
|
||||
}
|
||||
|
||||
crate fn thir_check_unsafety_inner<'tcx>(
|
||||
@ -314,10 +325,8 @@ crate fn thir_check_unsafety_inner<'tcx>(
|
||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
|
||||
let body_id = tcx.hir().body_owned_by(hir_id);
|
||||
let body = tcx.hir().body(body_id);
|
||||
|
||||
let arena = Arena::default();
|
||||
let thir = cx::build_thir(tcx, def, &arena, &body.value);
|
||||
check_unsafety(tcx, thir, hir_id);
|
||||
let (thir, expr) = cx::build_thir(tcx, def, &body.value);
|
||||
check_unsafety(tcx, &thir, expr, hir_id);
|
||||
}
|
||||
|
||||
crate fn thir_check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
|
||||
|
@ -1,123 +1,124 @@
|
||||
use crate::thir::*;
|
||||
|
||||
pub trait Visitor<'thir, 'tcx>: Sized {
|
||||
fn visit_expr(&mut self, expr: &'thir Expr<'thir, 'tcx>) {
|
||||
pub trait Visitor<'a, 'tcx: 'a>: Sized {
|
||||
fn thir(&self) -> &'a Thir<'tcx>;
|
||||
|
||||
fn visit_expr(&mut self, expr: &Expr<'tcx>) {
|
||||
walk_expr(self, expr);
|
||||
}
|
||||
|
||||
fn visit_stmt(&mut self, stmt: &'thir Stmt<'thir, 'tcx>) {
|
||||
fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) {
|
||||
walk_stmt(self, stmt);
|
||||
}
|
||||
|
||||
fn visit_block(&mut self, block: &Block<'thir, 'tcx>) {
|
||||
fn visit_block(&mut self, block: &Block) {
|
||||
walk_block(self, block);
|
||||
}
|
||||
|
||||
fn visit_arm(&mut self, arm: &'thir Arm<'thir, 'tcx>) {
|
||||
fn visit_arm(&mut self, arm: &Arm<'tcx>) {
|
||||
walk_arm(self, arm);
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {}
|
||||
}
|
||||
|
||||
pub fn walk_expr<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
|
||||
visitor: &mut V,
|
||||
expr: &'thir Expr<'thir, 'tcx>,
|
||||
) {
|
||||
pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) {
|
||||
use ExprKind::*;
|
||||
match expr.kind {
|
||||
Scope { value, region_scope: _, lint_level: _ } => visitor.visit_expr(value),
|
||||
Box { value } => visitor.visit_expr(value),
|
||||
Scope { value, region_scope: _, lint_level: _ } => {
|
||||
visitor.visit_expr(&visitor.thir()[value])
|
||||
}
|
||||
Box { value } => visitor.visit_expr(&visitor.thir()[value]),
|
||||
If { cond, then, else_opt } => {
|
||||
visitor.visit_expr(cond);
|
||||
visitor.visit_expr(then);
|
||||
visitor.visit_expr(&visitor.thir()[cond]);
|
||||
visitor.visit_expr(&visitor.thir()[then]);
|
||||
if let Some(else_expr) = else_opt {
|
||||
visitor.visit_expr(else_expr);
|
||||
visitor.visit_expr(&visitor.thir()[else_expr]);
|
||||
}
|
||||
}
|
||||
Call { fun, args, ty: _, from_hir_call: _, fn_span: _ } => {
|
||||
visitor.visit_expr(fun);
|
||||
for arg in args {
|
||||
visitor.visit_expr(arg);
|
||||
Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ } => {
|
||||
visitor.visit_expr(&visitor.thir()[fun]);
|
||||
for &arg in &**args {
|
||||
visitor.visit_expr(&visitor.thir()[arg]);
|
||||
}
|
||||
}
|
||||
Deref { arg } => visitor.visit_expr(arg),
|
||||
Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]),
|
||||
Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => {
|
||||
visitor.visit_expr(lhs);
|
||||
visitor.visit_expr(rhs);
|
||||
visitor.visit_expr(&visitor.thir()[lhs]);
|
||||
visitor.visit_expr(&visitor.thir()[rhs]);
|
||||
}
|
||||
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, cast: _ } => visitor.visit_expr(source),
|
||||
Loop { body } => visitor.visit_expr(body),
|
||||
Match { scrutinee, arms } => {
|
||||
visitor.visit_expr(scrutinee);
|
||||
for arm in arms {
|
||||
visitor.visit_arm(arm);
|
||||
Unary { arg, op: _ } => visitor.visit_expr(&visitor.thir()[arg]),
|
||||
Cast { source } => visitor.visit_expr(&visitor.thir()[source]),
|
||||
Use { source } => visitor.visit_expr(&visitor.thir()[source]),
|
||||
NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]),
|
||||
Pointer { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]),
|
||||
Loop { body } => visitor.visit_expr(&visitor.thir()[body]),
|
||||
Match { scrutinee, ref arms } => {
|
||||
visitor.visit_expr(&visitor.thir()[scrutinee]);
|
||||
for &arm in &**arms {
|
||||
visitor.visit_arm(&visitor.thir()[arm]);
|
||||
}
|
||||
}
|
||||
Block { ref body } => visitor.visit_block(body),
|
||||
Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => {
|
||||
visitor.visit_expr(lhs);
|
||||
visitor.visit_expr(rhs);
|
||||
visitor.visit_expr(&visitor.thir()[lhs]);
|
||||
visitor.visit_expr(&visitor.thir()[rhs]);
|
||||
}
|
||||
Field { lhs, name: _ } => visitor.visit_expr(lhs),
|
||||
Field { lhs, name: _ } => visitor.visit_expr(&visitor.thir()[lhs]),
|
||||
Index { lhs, index } => {
|
||||
visitor.visit_expr(lhs);
|
||||
visitor.visit_expr(index);
|
||||
visitor.visit_expr(&visitor.thir()[lhs]);
|
||||
visitor.visit_expr(&visitor.thir()[index]);
|
||||
}
|
||||
VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {}
|
||||
Borrow { arg, borrow_kind: _ } => visitor.visit_expr(arg),
|
||||
AddressOf { arg, mutability: _ } => visitor.visit_expr(arg),
|
||||
Borrow { arg, borrow_kind: _ } => visitor.visit_expr(&visitor.thir()[arg]),
|
||||
AddressOf { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]),
|
||||
Break { value, label: _ } => {
|
||||
if let Some(value) = value {
|
||||
visitor.visit_expr(value)
|
||||
visitor.visit_expr(&visitor.thir()[value])
|
||||
}
|
||||
}
|
||||
Continue { label: _ } => {}
|
||||
Return { value } => {
|
||||
if let Some(value) = value {
|
||||
visitor.visit_expr(value)
|
||||
visitor.visit_expr(&visitor.thir()[value])
|
||||
}
|
||||
}
|
||||
ConstBlock { value } => visitor.visit_const(value),
|
||||
Repeat { value, count } => {
|
||||
visitor.visit_expr(value);
|
||||
visitor.visit_expr(&visitor.thir()[value]);
|
||||
visitor.visit_const(count);
|
||||
}
|
||||
Array { fields } | Tuple { fields } => {
|
||||
for field in fields {
|
||||
visitor.visit_expr(field);
|
||||
Array { ref fields } | Tuple { ref fields } => {
|
||||
for &field in &**fields {
|
||||
visitor.visit_expr(&visitor.thir()[field]);
|
||||
}
|
||||
}
|
||||
Adt { fields, ref base, adt_def: _, variant_index: _, substs: _, user_ty: _ } => {
|
||||
for field in fields {
|
||||
visitor.visit_expr(field.expr);
|
||||
Adt { ref fields, ref base, adt_def: _, variant_index: _, substs: _, user_ty: _ } => {
|
||||
for field in &**fields {
|
||||
visitor.visit_expr(&visitor.thir()[field.expr]);
|
||||
}
|
||||
if let Some(base) = base {
|
||||
visitor.visit_expr(base.base);
|
||||
visitor.visit_expr(&visitor.thir()[base.base]);
|
||||
}
|
||||
}
|
||||
PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => {
|
||||
visitor.visit_expr(source)
|
||||
visitor.visit_expr(&visitor.thir()[source])
|
||||
}
|
||||
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 {
|
||||
InlineAsm { ref operands, template: _, options: _, line_spans: _ } => {
|
||||
for op in &**operands {
|
||||
use InlineAsmOperand::*;
|
||||
match op {
|
||||
In { expr, reg: _ }
|
||||
| Out { expr: Some(expr), reg: _, late: _ }
|
||||
| InOut { expr, reg: _, late: _ }
|
||||
| SymFn { expr } => visitor.visit_expr(expr),
|
||||
| SymFn { expr } => visitor.visit_expr(&visitor.thir()[*expr]),
|
||||
SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
|
||||
visitor.visit_expr(in_expr);
|
||||
visitor.visit_expr(&visitor.thir()[*in_expr]);
|
||||
if let Some(out_expr) = out_expr {
|
||||
visitor.visit_expr(out_expr);
|
||||
visitor.visit_expr(&visitor.thir()[*out_expr]);
|
||||
}
|
||||
}
|
||||
Out { expr: None, reg: _, late: _ }
|
||||
@ -127,24 +128,21 @@ pub fn walk_expr<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
|
||||
}
|
||||
}
|
||||
ThreadLocalRef(_) => {}
|
||||
LlvmInlineAsm { outputs, inputs, asm: _ } => {
|
||||
for out_expr in outputs {
|
||||
visitor.visit_expr(out_expr);
|
||||
LlvmInlineAsm { ref outputs, ref inputs, asm: _ } => {
|
||||
for &out_expr in &**outputs {
|
||||
visitor.visit_expr(&visitor.thir()[out_expr]);
|
||||
}
|
||||
for in_expr in inputs {
|
||||
visitor.visit_expr(in_expr);
|
||||
for &in_expr in &**inputs {
|
||||
visitor.visit_expr(&visitor.thir()[in_expr]);
|
||||
}
|
||||
}
|
||||
Yield { value } => visitor.visit_expr(value),
|
||||
Yield { value } => visitor.visit_expr(&visitor.thir()[value]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_stmt<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
|
||||
visitor: &mut V,
|
||||
stmt: &'thir Stmt<'thir, 'tcx>,
|
||||
) {
|
||||
pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) {
|
||||
match stmt.kind {
|
||||
StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(expr),
|
||||
StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[expr]),
|
||||
StmtKind::Let {
|
||||
initializer,
|
||||
remainder_scope: _,
|
||||
@ -153,34 +151,28 @@ pub fn walk_stmt<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
|
||||
lint_level: _,
|
||||
} => {
|
||||
if let Some(init) = initializer {
|
||||
visitor.visit_expr(init);
|
||||
visitor.visit_expr(&visitor.thir()[init]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_block<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
|
||||
visitor: &mut V,
|
||||
block: &Block<'thir, 'tcx>,
|
||||
) {
|
||||
for stmt in block.stmts {
|
||||
visitor.visit_stmt(stmt);
|
||||
pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &Block) {
|
||||
for &stmt in &*block.stmts {
|
||||
visitor.visit_stmt(&visitor.thir()[stmt]);
|
||||
}
|
||||
if let Some(expr) = block.expr {
|
||||
visitor.visit_expr(expr);
|
||||
visitor.visit_expr(&visitor.thir()[expr]);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_arm<'thir, 'tcx, V: Visitor<'thir, 'tcx>>(
|
||||
visitor: &mut V,
|
||||
arm: &'thir Arm<'thir, 'tcx>,
|
||||
) {
|
||||
pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) {
|
||||
match arm.guard {
|
||||
Some(Guard::If(expr)) => visitor.visit_expr(expr),
|
||||
Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]),
|
||||
Some(Guard::IfLet(ref _pat, expr)) => {
|
||||
visitor.visit_expr(expr);
|
||||
visitor.visit_expr(&visitor.thir()[expr]);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
visitor.visit_expr(arm.body);
|
||||
visitor.visit_expr(&visitor.thir()[arm.body]);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user