Remove old match guard pattern tracking code
This is subsumed by the new changes that count pattern variables as bound for the whole guard expression.
This commit is contained in:
parent
d08efdec1c
commit
fce4c7998b
|
@ -17,7 +17,6 @@ use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use smallvec::SmallVec;
|
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
mod drop_ranges;
|
mod drop_ranges;
|
||||||
|
@ -29,13 +28,6 @@ struct InteriorVisitor<'a, 'tcx> {
|
||||||
expr_count: usize,
|
expr_count: usize,
|
||||||
kind: hir::GeneratorKind,
|
kind: hir::GeneratorKind,
|
||||||
prev_unresolved_span: Option<Span>,
|
prev_unresolved_span: Option<Span>,
|
||||||
/// Match arm guards have temporary borrows from the pattern bindings.
|
|
||||||
/// In case there is a yield point in a guard with a reference to such bindings,
|
|
||||||
/// such borrows can span across this yield point.
|
|
||||||
/// As such, we need to track these borrows and record them despite of the fact
|
|
||||||
/// that they may succeed the said yield point in the post-order.
|
|
||||||
guard_bindings: SmallVec<[SmallVec<[HirId; 4]>; 1]>,
|
|
||||||
guard_bindings_set: HirIdSet,
|
|
||||||
linted_values: HirIdSet,
|
linted_values: HirIdSet,
|
||||||
drop_ranges: DropRanges,
|
drop_ranges: DropRanges,
|
||||||
}
|
}
|
||||||
|
@ -48,7 +40,6 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
|
||||||
scope: Option<region::Scope>,
|
scope: Option<region::Scope>,
|
||||||
expr: Option<&'tcx Expr<'tcx>>,
|
expr: Option<&'tcx Expr<'tcx>>,
|
||||||
source_span: Span,
|
source_span: Span,
|
||||||
guard_borrowing_from_pattern: bool,
|
|
||||||
) {
|
) {
|
||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::DUMMY_SP;
|
||||||
|
|
||||||
|
@ -89,8 +80,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
|
||||||
// If it is a borrowing happening in the guard,
|
// If it is a borrowing happening in the guard,
|
||||||
// it needs to be recorded regardless because they
|
// it needs to be recorded regardless because they
|
||||||
// do live across this yield point.
|
// do live across this yield point.
|
||||||
guard_borrowing_from_pattern
|
yield_data.expr_and_pat_count >= self.expr_count
|
||||||
|| yield_data.expr_and_pat_count >= self.expr_count
|
|
||||||
})
|
})
|
||||||
.cloned()
|
.cloned()
|
||||||
})
|
})
|
||||||
|
@ -196,8 +186,6 @@ pub fn resolve_interior<'a, 'tcx>(
|
||||||
expr_count: 0,
|
expr_count: 0,
|
||||||
kind,
|
kind,
|
||||||
prev_unresolved_span: None,
|
prev_unresolved_span: None,
|
||||||
guard_bindings: <_>::default(),
|
|
||||||
guard_bindings_set: <_>::default(),
|
|
||||||
linted_values: <_>::default(),
|
linted_values: <_>::default(),
|
||||||
drop_ranges: drop_ranges::compute_drop_ranges(fcx, def_id, body),
|
drop_ranges: drop_ranges::compute_drop_ranges(fcx, def_id, body),
|
||||||
};
|
};
|
||||||
|
@ -284,8 +272,41 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
|
||||||
let Arm { guard, pat, body, .. } = arm;
|
let Arm { guard, pat, body, .. } = arm;
|
||||||
self.visit_pat(pat);
|
self.visit_pat(pat);
|
||||||
if let Some(ref g) = guard {
|
if let Some(ref g) = guard {
|
||||||
self.guard_bindings.push(<_>::default());
|
|
||||||
{
|
{
|
||||||
|
// If there is a guard, we need to count all variables bound in the pattern as
|
||||||
|
// borrowed for the entire guard body, regardless of whether they are accessed.
|
||||||
|
// We do this by walking the pattern bindings and recording `&T` for any `x: T`
|
||||||
|
// that is bound.
|
||||||
|
|
||||||
|
struct ArmPatCollector<'a, 'b, 'tcx> {
|
||||||
|
interior_visitor: &'a mut InteriorVisitor<'b, 'tcx>,
|
||||||
|
scope: Scope,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'tcx> Visitor<'tcx> for ArmPatCollector<'a, 'b, 'tcx> {
|
||||||
|
fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) {
|
||||||
|
intravisit::walk_pat(self, pat);
|
||||||
|
if let PatKind::Binding(_, id, ident, ..) = pat.kind {
|
||||||
|
let ty =
|
||||||
|
self.interior_visitor.fcx.typeck_results.borrow().node_type(id);
|
||||||
|
let tcx = self.interior_visitor.fcx.tcx;
|
||||||
|
let ty = tcx.mk_ref(
|
||||||
|
// Use `ReErased` as `resolve_interior` is going to replace all the
|
||||||
|
// regions anyway.
|
||||||
|
tcx.mk_region(ty::ReErased),
|
||||||
|
ty::TypeAndMut { ty, mutbl: hir::Mutability::Not },
|
||||||
|
);
|
||||||
|
self.interior_visitor.record(
|
||||||
|
ty,
|
||||||
|
id,
|
||||||
|
Some(self.scope),
|
||||||
|
None,
|
||||||
|
ident.span,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ArmPatCollector {
|
ArmPatCollector {
|
||||||
interior_visitor: self,
|
interior_visitor: self,
|
||||||
scope: Scope { id: g.body().hir_id.local_id, data: ScopeData::Node },
|
scope: Scope { id: g.body().hir_id.local_id, data: ScopeData::Node },
|
||||||
|
@ -301,12 +322,6 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
|
||||||
self.visit_let_expr(l);
|
self.visit_let_expr(l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut scope_var_ids =
|
|
||||||
self.guard_bindings.pop().expect("should have pushed at least one earlier");
|
|
||||||
for var_id in scope_var_ids.drain(..) {
|
|
||||||
self.guard_bindings_set.remove(&var_id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
self.visit_expr(body);
|
self.visit_expr(body);
|
||||||
}
|
}
|
||||||
|
@ -319,13 +334,11 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
|
||||||
if let PatKind::Binding(..) = pat.kind {
|
if let PatKind::Binding(..) = pat.kind {
|
||||||
let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id).unwrap();
|
let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id).unwrap();
|
||||||
let ty = self.fcx.typeck_results.borrow().pat_ty(pat);
|
let ty = self.fcx.typeck_results.borrow().pat_ty(pat);
|
||||||
self.record(ty, pat.hir_id, Some(scope), None, pat.span, false);
|
self.record(ty, pat.hir_id, Some(scope), None, pat.span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
|
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
|
||||||
let mut guard_borrowing_from_pattern = false;
|
|
||||||
|
|
||||||
match &expr.kind {
|
match &expr.kind {
|
||||||
ExprKind::Call(callee, args) => match &callee.kind {
|
ExprKind::Call(callee, args) => match &callee.kind {
|
||||||
ExprKind::Path(qpath) => {
|
ExprKind::Path(qpath) => {
|
||||||
|
@ -352,16 +365,6 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
_ => intravisit::walk_expr(self, expr),
|
_ => intravisit::walk_expr(self, expr),
|
||||||
},
|
},
|
||||||
ExprKind::Path(qpath) => {
|
|
||||||
intravisit::walk_expr(self, expr);
|
|
||||||
let res = self.fcx.typeck_results.borrow().qpath_res(qpath, expr.hir_id);
|
|
||||||
match res {
|
|
||||||
Res::Local(id) if self.guard_bindings_set.contains(&id) => {
|
|
||||||
guard_borrowing_from_pattern = true;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => intravisit::walk_expr(self, expr),
|
_ => intravisit::walk_expr(self, expr),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,14 +393,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
|
||||||
// If there are adjustments, then record the final type --
|
// If there are adjustments, then record the final type --
|
||||||
// this is the actual value that is being produced.
|
// this is the actual value that is being produced.
|
||||||
if let Some(adjusted_ty) = self.fcx.typeck_results.borrow().expr_ty_adjusted_opt(expr) {
|
if let Some(adjusted_ty) = self.fcx.typeck_results.borrow().expr_ty_adjusted_opt(expr) {
|
||||||
self.record(
|
self.record(adjusted_ty, expr.hir_id, scope, Some(expr), expr.span);
|
||||||
adjusted_ty,
|
|
||||||
expr.hir_id,
|
|
||||||
scope,
|
|
||||||
Some(expr),
|
|
||||||
expr.span,
|
|
||||||
guard_borrowing_from_pattern,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also record the unadjusted type (which is the only type if
|
// Also record the unadjusted type (which is the only type if
|
||||||
|
@ -425,68 +421,13 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
|
||||||
// The type table might not have information for this expression
|
// The type table might not have information for this expression
|
||||||
// if it is in a malformed scope. (#66387)
|
// if it is in a malformed scope. (#66387)
|
||||||
if let Some(ty) = self.fcx.typeck_results.borrow().expr_ty_opt(expr) {
|
if let Some(ty) = self.fcx.typeck_results.borrow().expr_ty_opt(expr) {
|
||||||
if guard_borrowing_from_pattern {
|
self.record(ty, expr.hir_id, scope, Some(expr), expr.span);
|
||||||
// Match guards create references to all the bindings in the pattern that are used
|
|
||||||
// in the guard, e.g. `y if is_even(y) => ...` becomes `is_even(*r_y)` where `r_y`
|
|
||||||
// is a reference to `y`, so we must record a reference to the type of the binding.
|
|
||||||
let tcx = self.fcx.tcx;
|
|
||||||
let ref_ty = tcx.mk_ref(
|
|
||||||
// Use `ReErased` as `resolve_interior` is going to replace all the regions anyway.
|
|
||||||
tcx.mk_region(ty::ReErased),
|
|
||||||
ty::TypeAndMut { ty, mutbl: hir::Mutability::Not },
|
|
||||||
);
|
|
||||||
self.record(
|
|
||||||
ref_ty,
|
|
||||||
expr.hir_id,
|
|
||||||
scope,
|
|
||||||
Some(expr),
|
|
||||||
expr.span,
|
|
||||||
guard_borrowing_from_pattern,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
self.record(
|
|
||||||
ty,
|
|
||||||
expr.hir_id,
|
|
||||||
scope,
|
|
||||||
Some(expr),
|
|
||||||
expr.span,
|
|
||||||
guard_borrowing_from_pattern,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
self.fcx.tcx.sess.delay_span_bug(expr.span, "no type for node");
|
self.fcx.tcx.sess.delay_span_bug(expr.span, "no type for node");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ArmPatCollector<'a, 'b, 'tcx> {
|
|
||||||
interior_visitor: &'a mut InteriorVisitor<'b, 'tcx>,
|
|
||||||
scope: Scope,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'b, 'tcx> Visitor<'tcx> for ArmPatCollector<'a, 'b, 'tcx> {
|
|
||||||
fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) {
|
|
||||||
intravisit::walk_pat(self, pat);
|
|
||||||
if let PatKind::Binding(_, id, ..) = pat.kind {
|
|
||||||
self.interior_visitor
|
|
||||||
.guard_bindings
|
|
||||||
.last_mut()
|
|
||||||
.expect("should have pushed at least one earlier")
|
|
||||||
.push(id);
|
|
||||||
self.interior_visitor.guard_bindings_set.insert(id);
|
|
||||||
|
|
||||||
let ty = self.interior_visitor.fcx.typeck_results.borrow().node_type(id);
|
|
||||||
let ty = self.interior_visitor.fcx.tcx.mk_ref(
|
|
||||||
// Use `ReErased` as `resolve_interior` is going to replace all the regions anyway.
|
|
||||||
self.interior_visitor.fcx.tcx.mk_region(ty::ReErased),
|
|
||||||
ty::TypeAndMut { ty, mutbl: hir::Mutability::Not },
|
|
||||||
);
|
|
||||||
// FIXME: use the right span
|
|
||||||
let span = rustc_span::DUMMY_SP;
|
|
||||||
self.interior_visitor.record(ty, id, Some(self.scope), None, span, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct SuspendCheckData<'a, 'tcx> {
|
pub struct SuspendCheckData<'a, 'tcx> {
|
||||||
expr: Option<&'tcx Expr<'tcx>>,
|
expr: Option<&'tcx Expr<'tcx>>,
|
||||||
|
|
Loading…
Reference in a new issue