diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 11faaa4df18..2d94874105a 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -268,6 +268,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> { /// See also `with_infer`, which is used *during* typeck. pub fn new(delegate: &'a mut (dyn Delegate<'tcx>+'a), tcx: TyCtxt<'a, 'tcx, 'tcx>, + body_owner: DefId, param_env: ty::ParamEnv<'tcx>, region_scope_tree: &'a region::ScopeTree, tables: &'a ty::TypeckTables<'tcx>, @@ -276,6 +277,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> { { ExprUseVisitor { mc: mc::MemCategorizationContext::new(tcx, + body_owner, region_scope_tree, tables, rvalue_promotable_map), @@ -288,13 +290,19 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> { impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { pub fn with_infer(delegate: &'a mut (dyn Delegate<'tcx>+'a), infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + body_owner: DefId, param_env: ty::ParamEnv<'tcx>, region_scope_tree: &'a region::ScopeTree, tables: &'a ty::TypeckTables<'tcx>) -> Self { ExprUseVisitor { - mc: mc::MemCategorizationContext::with_infer(infcx, region_scope_tree, tables), + mc: mc::MemCategorizationContext::with_infer( + infcx, + body_owner, + region_scope_tree, + tables, + ), delegate, param_env, } @@ -965,10 +973,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // caller's perspective if upvar.has_parent { let closure_def_id = self.tcx().hir().local_def_id_from_hir_id(closure_hir_id); - let parent_def_id = self.tcx().parent(closure_def_id).unwrap(); - assert!(self.tcx().is_closure(parent_def_id)); + assert_eq!(self.mc.body_owner, self.tcx().parent(closure_def_id).unwrap()); let var_nid = self.tcx().hir().hir_to_node_id(var_id); - self.mc.cat_upvar(closure_hir_id, closure_span, var_nid, parent_def_id) + self.mc.cat_upvar(closure_hir_id, closure_span, var_nid) } else { let var_ty = self.mc.node_ty(var_id)?; self.mc.cat_res(closure_hir_id, closure_span, var_ty, Res::Local(var_id)) diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 7ce729bb715..2022169dbf1 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -288,6 +288,7 @@ impl HirNode for hir::Pat { #[derive(Clone)] pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, + pub body_owner: DefId, pub region_scope_tree: &'a region::ScopeTree, pub tables: &'a ty::TypeckTables<'tcx>, rvalue_promotable_map: Option<&'tcx ItemLocalSet>, @@ -398,12 +399,14 @@ impl MutabilityCategory { impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, + body_owner: DefId, region_scope_tree: &'a region::ScopeTree, tables: &'a ty::TypeckTables<'tcx>, rvalue_promotable_map: Option<&'tcx ItemLocalSet>) -> MemCategorizationContext<'a, 'tcx, 'tcx> { MemCategorizationContext { tcx, + body_owner, region_scope_tree, tables, rvalue_promotable_map, @@ -423,6 +426,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { /// - similarly, as the results of upvar analysis are not yet /// known, the results around upvar accesses may be incorrect. pub fn with_infer(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + body_owner: DefId, region_scope_tree: &'a region::ScopeTree, tables: &'a ty::TypeckTables<'tcx>) -> MemCategorizationContext<'a, 'gcx, 'tcx> { @@ -436,6 +440,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { MemCategorizationContext { tcx, + body_owner, region_scope_tree, tables, rvalue_promotable_map, @@ -739,8 +744,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { Res::Upvar(var_id, closure_node_id) => { let var_nid = self.tcx.hir().hir_to_node_id(var_id); - let closure_expr_def_id = self.tcx.hir().local_def_id(closure_node_id); - self.cat_upvar(hir_id, span, var_nid, closure_expr_def_id) + let closure_def_id = self.tcx.hir().local_def_id(closure_node_id); + assert_eq!(self.body_owner, closure_def_id); + + self.cat_upvar(hir_id, span, var_nid) } Res::Local(vid) => { @@ -766,7 +773,6 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { hir_id: hir::HirId, span: Span, var_id: ast::NodeId, - closure_expr_def_id: DefId, ) -> McResult> { // An upvar can have up to 3 components. We translate first to a // `Categorization::Upvar`, which is itself a fiction -- it represents the reference to the @@ -791,6 +797,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // FnMut | copied -> &'env mut | upvar -> &'env mut -> &'up bk // FnOnce | copied | upvar -> &'up bk + let closure_expr_def_id = self.body_owner; let fn_hir_id = self.tcx.hir().local_def_id_to_hir_id( LocalDefId::from_def_id(closure_expr_def_id), ); diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index d2d5c4fe85c..35e6c1c5bf5 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -208,6 +208,7 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, let rvalue_promotable_map = bccx.tcx.rvalue_promotable_map(def_id); euv::ExprUseVisitor::new(&mut clcx, bccx.tcx, + def_id, param_env, &bccx.region_scope_tree, bccx.tables, diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 3892a18b140..e437c08c956 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -44,6 +44,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, let rvalue_promotable_map = bccx.tcx.rvalue_promotable_map(def_id); euv::ExprUseVisitor::new(&mut glcx, bccx.tcx, + def_id, param_env, &bccx.region_scope_tree, bccx.tables, diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 0edf32d3a30..215faee9532 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -35,6 +35,7 @@ pub(crate) fn check_match<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) MatchVisitor { tcx, + body_owner: def_id, tables: tcx.body_tables(body_id), region_scope_tree: &tcx.region_scope_tree(def_id), param_env: tcx.param_env(def_id), @@ -48,6 +49,7 @@ fn create_e0004<'a>(sess: &'a Session, sp: Span, error_message: String) -> Diagn struct MatchVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, + body_owner: DefId, tables: &'a ty::TypeckTables<'tcx>, param_env: ty::ParamEnv<'tcx>, identity_substs: SubstsRef<'tcx>, @@ -632,6 +634,7 @@ fn check_for_mutation_in_guard(cx: &MatchVisitor<'_, '_>, guard: &hir::Guard) { hir::Guard::If(expr) => ExprUseVisitor::new(&mut checker, cx.tcx, + cx.body_owner, cx.param_env, cx.region_scope_tree, cx.tables, diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 85cd602db59..869cae3d3a8 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -199,8 +199,15 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { let param_env = self.param_env; let region_scope_tree = self.tcx.region_scope_tree(item_def_id); let tables = self.tables; - euv::ExprUseVisitor::new(self, tcx, param_env, ®ion_scope_tree, tables, None) - .consume_body(body); + euv::ExprUseVisitor::new( + self, + tcx, + item_def_id, + param_env, + ®ion_scope_tree, + tables, + None, + ).consume_body(body); let body_promotable = self.check_expr(&body.value); self.in_fn = outer_in_fn; diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 62c9c7c8b1c..21d7e483e9d 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -200,6 +200,7 @@ pub struct RegionCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { // id of innermost fn body id body_id: hir::HirId, + body_owner: DefId, // call_site scope of innermost fn call_site_scope: Option, @@ -236,6 +237,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { region_scope_tree, repeating_scope: initial_repeating_scope, body_id: initial_body_id, + body_owner: subject, call_site_scope: None, subject_def_id: subject, outlives_environment, @@ -308,6 +310,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let body_id = body.id(); self.body_id = body_id.hir_id; + self.body_owner = self.tcx.hir().body_owner_def_id(body_id); let call_site = region::Scope { id: body.value.hir_id.local_id, @@ -466,6 +469,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> { // Save state of current function before invoking // `visit_fn_body`. We will restore afterwards. let old_body_id = self.body_id; + let old_body_owner = self.body_owner; let old_call_site_scope = self.call_site_scope; let env_snapshot = self.outlives_environment.push_snapshot_pre_closure(); @@ -477,6 +481,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> { .pop_snapshot_post_closure(env_snapshot); self.call_site_scope = old_call_site_scope; self.body_id = old_body_id; + self.body_owner = old_body_owner; } //visit_pat: visit_pat, // (..) see above @@ -829,6 +834,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { { f(mc::MemCategorizationContext::with_infer( &self.infcx, + self.body_owner, &self.region_scope_tree, &self.tables.borrow(), )) diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 8ceca20eb07..82c173a6f7a 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -167,6 +167,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } let body_owner_def_id = self.tcx.hir().body_owner_def_id(body.id()); + assert_eq!(body_owner_def_id, closure_def_id); let region_scope_tree = &self.tcx.region_scope_tree(body_owner_def_id); let mut delegate = InferBorrowKind { fcx: self, @@ -178,6 +179,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { euv::ExprUseVisitor::with_infer( &mut delegate, &self.infcx, + body_owner_def_id, self.param_env, region_scope_tree, &self.tables.borrow(),