From 4195b60323046c86d9431e82665de6d2f71a2289 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 8 Nov 2019 21:53:36 +0000 Subject: [PATCH 1/5] Rename `cmt_` to `Place` --- src/librustc/middle/expr_use_visitor.rs | 14 ++--- src/librustc/middle/mem_categorization.rs | 66 +++++++++++------------ src/librustc_typeck/check/regionck.rs | 10 ++-- src/librustc_typeck/check/upvar.rs | 14 ++--- 4 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 00bddf50c293e..2b18ecb169ecd 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -25,13 +25,13 @@ use syntax_pos::Span; pub trait Delegate<'tcx> { // The value found at `cmt` is either copied or moved, depending // on mode. - fn consume(&mut self, cmt: &mc::cmt_<'tcx>, mode: ConsumeMode); + fn consume(&mut self, cmt: &mc::Place<'tcx>, mode: ConsumeMode); // The value found at `cmt` is being borrowed with kind `bk`. - fn borrow(&mut self, cmt: &mc::cmt_<'tcx>, bk: ty::BorrowKind); + fn borrow(&mut self, cmt: &mc::Place<'tcx>, bk: ty::BorrowKind); // The path at `cmt` is being assigned to. - fn mutate(&mut self, assignee_cmt: &mc::cmt_<'tcx>); + fn mutate(&mut self, assignee_cmt: &mc::Place<'tcx>); } #[derive(Copy, Clone, PartialEq, Debug)] @@ -180,7 +180,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.mc.tcx } - fn delegate_consume(&mut self, cmt: &mc::cmt_<'tcx>) { + fn delegate_consume(&mut self, cmt: &mc::Place<'tcx>) { debug!("delegate_consume(cmt={:?})", cmt); let mode = copy_or_move(&self.mc, self.param_env, cmt); @@ -528,7 +528,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { /// after all relevant autoderefs have occurred. fn walk_autoref(&mut self, expr: &hir::Expr, - cmt_base: &mc::cmt_<'tcx>, + cmt_base: &mc::Place<'tcx>, autoref: &adjustment::AutoBorrow<'tcx>) { debug!("walk_autoref(expr.hir_id={} cmt_base={:?} autoref={:?})", expr.hir_id, @@ -645,7 +645,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { closure_hir_id: hir::HirId, closure_span: Span, var_id: hir::HirId) - -> mc::McResult> { + -> mc::McResult> { // Create the cmt for the variable being borrowed, from the // perspective of the creator (parent) of the closure. let var_ty = self.mc.node_ty(var_id)?; @@ -656,7 +656,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { fn copy_or_move<'a, 'tcx>( mc: &mc::MemCategorizationContext<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, - cmt: &mc::cmt_<'tcx>, + cmt: &mc::Place<'tcx>, ) -> ConsumeMode { if !mc.type_is_copy_modulo_regions(param_env, cmt.ty, cmt.span) { Move diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 3510fe4d12359..1b641cba770a8 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -184,7 +184,7 @@ pub enum Note { // dereference (`@T`). So use `cmt.ty` to find the type of the value in // a consistent fashion. For more details, see the method `cat_pattern` #[derive(Clone, Debug, PartialEq)] -pub struct cmt_<'tcx> { +pub struct Place<'tcx> { pub hir_id: hir::HirId, // HIR id of expr/pat producing this value pub span: Span, // span of same expr/pat pub cat: Categorization<'tcx>, // categorization of expr @@ -193,7 +193,7 @@ pub struct cmt_<'tcx> { pub note: Note, // Note about the provenance of this cmt } -pub type cmt<'tcx> = Rc>; +pub type cmt<'tcx> = Rc>; pub trait HirNode { fn hir_id(&self) -> hir::HirId; @@ -504,14 +504,14 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { Ok(ret_ty) } - pub fn cat_expr(&self, expr: &hir::Expr) -> McResult> { + pub fn cat_expr(&self, expr: &hir::Expr) -> McResult> { // This recursion helper avoids going through *too many* // adjustments, since *only* non-overloaded deref recurses. fn helper<'a, 'tcx>( mc: &MemCategorizationContext<'a, 'tcx>, expr: &hir::Expr, adjustments: &[adjustment::Adjustment<'tcx>], - ) -> McResult> { + ) -> McResult> { match adjustments.split_last() { None => mc.cat_expr_unadjusted(expr), Some((adjustment, previous)) => { @@ -524,17 +524,17 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } pub fn cat_expr_adjusted(&self, expr: &hir::Expr, - previous: cmt_<'tcx>, + previous: Place<'tcx>, adjustment: &adjustment::Adjustment<'tcx>) - -> McResult> { + -> McResult> { self.cat_expr_adjusted_with(expr, || Ok(previous), adjustment) } fn cat_expr_adjusted_with(&self, expr: &hir::Expr, previous: F, adjustment: &adjustment::Adjustment<'tcx>) - -> McResult> - where F: FnOnce() -> McResult> + -> McResult> + where F: FnOnce() -> McResult> { debug!("cat_expr_adjusted_with({:?}): {:?}", adjustment, expr); let target = self.resolve_vars_if_possible(&adjustment.target); @@ -562,7 +562,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } } - pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult> { + pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult> { debug!("cat_expr: id={} expr={:?}", expr.hir_id, expr); let expr_ty = self.expr_ty(expr)?; @@ -630,7 +630,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { span: Span, expr_ty: Ty<'tcx>, res: Res) - -> McResult> { + -> McResult> { debug!("cat_res: id={:?} expr={:?} def={:?}", hir_id, expr_ty, res); @@ -658,7 +658,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { Categorization::StaticItem }; - Ok(cmt_ { + Ok(Place { hir_id, span, cat, @@ -675,7 +675,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { if self.upvars.map_or(false, |upvars| upvars.contains_key(&var_id)) { self.cat_upvar(hir_id, span, var_id) } else { - Ok(cmt_ { + Ok(Place { hir_id, span, cat: Categorization::Local(var_id), @@ -697,7 +697,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { hir_id: hir::HirId, span: Span, var_id: hir::HirId, - ) -> McResult> { + ) -> 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 // field from the environment. @@ -758,7 +758,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // Construct the upvar. This represents access to the field // from the environment (perhaps we should eventually desugar // this field further, but it will do for now). - let cmt_result = cmt_ { + let cmt_result = Place { hir_id, span, cat: Categorization::Upvar(Upvar {id: upvar_id, kind: kind}), @@ -792,7 +792,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } ty::UpvarCapture::ByRef(upvar_borrow) => { let ptr = BorrowedPtr(upvar_borrow.kind, upvar_borrow.region); - cmt_ { + Place { hir_id, span, cat: Categorization::Deref(Rc::new(cmt_result), ptr), @@ -814,8 +814,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { upvar_id: ty::UpvarId, upvar_mutbl: MutabilityCategory, env_borrow_kind: ty::BorrowKind, - cmt_result: cmt_<'tcx>) - -> cmt_<'tcx> + cmt_result: Place<'tcx>) + -> Place<'tcx> { // Region of environment pointer let env_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion { @@ -837,7 +837,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // away with stuffing a `Error` in there // instead of bothering to construct a proper // one. - let cmt_result = cmt_ { + let cmt_result = Place { mutbl: McImmutable, ty: self.tcx.types.err, ..cmt_result @@ -852,7 +852,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { McDeclared | McInherited => { } } - let ret = cmt_ { + let ret = Place { hir_id, span, cat: Categorization::Deref(Rc::new(cmt_result), env_ptr), @@ -870,7 +870,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { hir_id: hir::HirId, span: Span, expr_ty: Ty<'tcx>) - -> cmt_<'tcx> { + -> Place<'tcx> { debug!("cat_rvalue_node(id={:?}, span={:?}, expr_ty={:?})", hir_id, span, expr_ty); @@ -882,8 +882,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { pub fn cat_rvalue(&self, cmt_hir_id: hir::HirId, span: Span, - expr_ty: Ty<'tcx>) -> cmt_<'tcx> { - let ret = cmt_ { + expr_ty: Ty<'tcx>) -> Place<'tcx> { + let ret = Place { hir_id: cmt_hir_id, span:span, cat:Categorization::Rvalue, @@ -901,8 +901,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { f_index: usize, f_ident: ast::Ident, f_ty: Ty<'tcx>) - -> cmt_<'tcx> { - let ret = cmt_ { + -> Place<'tcx> { + let ret = Place { hir_id: node.hir_id(), span: node.span(), mutbl: base_cmt.mutbl.inherit(), @@ -920,7 +920,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { expr: &hir::Expr, base: &hir::Expr, note: Note, - ) -> McResult> { + ) -> McResult> { debug!("cat_overloaded_place(expr={:?}, base={:?}, note={:?})", expr, base, @@ -950,7 +950,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { node: &impl HirNode, base_cmt: cmt<'tcx>, note: Note, - ) -> McResult> { + ) -> McResult> { debug!("cat_deref: base_cmt={:?}", base_cmt); let base_cmt_ty = base_cmt.ty; @@ -971,7 +971,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } _ => bug!("unexpected type in cat_deref: {:?}", base_cmt.ty) }; - let ret = cmt_ { + let ret = Place { hir_id: node.hir_id(), span: node.span(), // For unique ptrs, we inherit mutability from the owning reference. @@ -989,7 +989,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { base_cmt: cmt<'tcx>, element_ty: Ty<'tcx>, context: InteriorOffsetKind) - -> McResult> { + -> McResult> { //! Creates a cmt for an indexing operation (`[]`). //! //! One subtle aspect of indexing that may not be @@ -1018,8 +1018,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { base_cmt: cmt<'tcx>, interior_ty: Ty<'tcx>, interior: InteriorKind) - -> cmt_<'tcx> { - let ret = cmt_ { + -> Place<'tcx> { + let ret = Place { hir_id: node.hir_id(), span: node.span(), mutbl: base_cmt.mutbl.inherit(), @@ -1040,7 +1040,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { let base_did = self.tcx.parent(variant_did).unwrap(); if self.tcx.adt_def(base_did).variants.len() != 1 { let base_ty = base_cmt.ty; - let ret = Rc::new(cmt_ { + let ret = Rc::new(Place { hir_id: node.hir_id(), span: node.span(), mutbl: base_cmt.mutbl.inherit(), @@ -1327,8 +1327,8 @@ pub enum AliasableReason { AliasableStaticMut, } -impl<'tcx> cmt_<'tcx> { - pub fn guarantor(&self) -> cmt_<'tcx> { +impl<'tcx> Place<'tcx> { + pub fn guarantor(&self) -> Place<'tcx> { //! Returns `self` after stripping away any derefs or //! interior content. The return value is basically the `cmt` which //! determines how long the value in `self` remains live. diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index f4fdc2882e702..170c4acad8b40 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -825,7 +825,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { /// Invoked on any adjustments that occur. Checks that if this is a region pointer being /// dereferenced, the lifetime of the pointer includes the deref expr. - fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult> { + fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult> { debug!("constrain_adjustments(expr={:?})", expr); let mut cmt = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?; @@ -921,7 +921,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { ) } - fn check_safety_of_rvalue_destructor_if_necessary(&mut self, cmt: &mc::cmt_<'tcx>, span: Span) { + fn check_safety_of_rvalue_destructor_if_necessary(&mut self, cmt: &mc::Place<'tcx>, span: Span) { if let Categorization::Rvalue = cmt.cat { let typ = self.resolve_type(cmt.ty); let body_id = self.body_id; @@ -1100,7 +1100,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { fn link_autoref( &self, expr: &hir::Expr, - expr_cmt: &mc::cmt_<'tcx>, + expr_cmt: &mc::Place<'tcx>, autoref: &adjustment::AutoBorrow<'tcx>, ) { debug!( @@ -1130,7 +1130,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { span: Span, id: hir::HirId, mutbl: hir::Mutability, - cmt_borrowed: &mc::cmt_<'tcx>, + cmt_borrowed: &mc::Place<'tcx>, ) { debug!( "link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={:?})", @@ -1153,7 +1153,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { span: Span, borrow_region: ty::Region<'tcx>, borrow_kind: ty::BorrowKind, - borrow_cmt: &mc::cmt_<'tcx>, + borrow_cmt: &mc::Place<'tcx>, ) { let origin = infer::DataBorrowed(borrow_cmt.ty, span); self.type_must_outlive(origin, borrow_cmt.ty, borrow_region); diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 390ee0d0f8380..5d17074e65e4e 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -312,7 +312,7 @@ struct InferBorrowKind<'a, 'tcx> { impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { fn adjust_upvar_borrow_kind_for_consume( &mut self, - cmt: &mc::cmt_<'tcx>, + cmt: &mc::Place<'tcx>, mode: euv::ConsumeMode, ) { debug!( @@ -388,7 +388,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { /// Indicates that `cmt` is being directly mutated (e.g., assigned /// to). If cmt contains any by-ref upvars, this implies that /// those upvars must be borrowed using an `&mut` borrow. - fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: &mc::cmt_<'tcx>) { + fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: &mc::Place<'tcx>) { debug!("adjust_upvar_borrow_kind_for_mut(cmt={:?})", cmt); match cmt.cat.clone() { @@ -421,7 +421,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { } } - fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: &mc::cmt_<'tcx>) { + fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: &mc::Place<'tcx>) { debug!("adjust_upvar_borrow_kind_for_unique(cmt={:?})", cmt); match cmt.cat.clone() { @@ -452,7 +452,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { fn try_adjust_upvar_deref( &mut self, - cmt: &mc::cmt_<'tcx>, + cmt: &mc::Place<'tcx>, borrow_kind: ty::BorrowKind, ) -> bool { assert!(match borrow_kind { @@ -586,12 +586,12 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { } impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { - fn consume(&mut self, cmt: &mc::cmt_<'tcx>,mode: euv::ConsumeMode) { + fn consume(&mut self, cmt: &mc::Place<'tcx>,mode: euv::ConsumeMode) { debug!("consume(cmt={:?},mode={:?})", cmt, mode); self.adjust_upvar_borrow_kind_for_consume(cmt, mode); } - fn borrow(&mut self, cmt: &mc::cmt_<'tcx>, bk: ty::BorrowKind) { + fn borrow(&mut self, cmt: &mc::Place<'tcx>, bk: ty::BorrowKind) { debug!("borrow(cmt={:?}, bk={:?})", cmt, bk); match bk { @@ -605,7 +605,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { } } - fn mutate(&mut self, assignee_cmt: &mc::cmt_<'tcx>) { + fn mutate(&mut self, assignee_cmt: &mc::Place<'tcx>) { debug!("mutate(assignee_cmt={:?})", assignee_cmt); self.adjust_upvar_borrow_kind_for_mut(assignee_cmt); From a5b8a3088a61a564fb2e4de97d4d26e321eb66bd Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 8 Nov 2019 22:11:03 +0000 Subject: [PATCH 2/5] Simplify fields of `MemCategorizationContext` --- src/librustc/middle/expr_use_visitor.rs | 52 ++------ src/librustc/middle/mem_categorization.rs | 139 +++++++--------------- src/librustc_typeck/check/regionck.rs | 3 +- src/librustc_typeck/check/upvar.rs | 6 +- 4 files changed, 57 insertions(+), 143 deletions(-) diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 2b18ecb169ecd..214f435351f00 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -10,7 +10,6 @@ use crate::hir::def_id::DefId; use crate::hir::ptr::P; use crate::infer::InferCtxt; use crate::middle::mem_categorization as mc; -use crate::middle::region; use crate::ty::{self, TyCtxt, adjustment}; use crate::hir::{self, PatKind}; @@ -85,7 +84,6 @@ impl OverloadedCallType { pub struct ExprUseVisitor<'a, 'tcx> { mc: mc::MemCategorizationContext<'a, 'tcx>, delegate: &'a mut dyn Delegate<'tcx>, - param_env: ty::ParamEnv<'tcx>, } // If the MC results in an error, it's because the type check @@ -112,49 +110,22 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { /// /// - `delegate` -- who receives the callbacks /// - `param_env` --- parameter environment for trait lookups (esp. pertaining to `Copy`) - /// - `region_scope_tree` --- region scope tree for the code being analyzed /// - `tables` --- typeck results for the code being analyzed - /// - /// See also `with_infer`, which is used *during* typeck. pub fn new( - delegate: &'a mut (dyn Delegate<'tcx> + 'a), - tcx: TyCtxt<'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::new(tcx, - param_env, - body_owner, - region_scope_tree, - tables), - delegate, - param_env, - } - } -} - -impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { - pub fn with_infer( delegate: &'a mut (dyn Delegate<'tcx> + 'a), infcx: &'a InferCtxt<'a, '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( + mc: mc::MemCategorizationContext::new( infcx, param_env, body_owner, - region_scope_tree, tables, ), delegate, - param_env, } } @@ -177,14 +148,14 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } fn tcx(&self) -> TyCtxt<'tcx> { - self.mc.tcx + self.mc.tcx() } - fn delegate_consume(&mut self, cmt: &mc::Place<'tcx>) { - debug!("delegate_consume(cmt={:?})", cmt); + fn delegate_consume(&mut self, place: &mc::Place<'tcx>) { + debug!("delegate_consume(place={:?})", place); - let mode = copy_or_move(&self.mc, self.param_env, cmt); - self.delegate.consume(cmt, mode); + let mode = copy_or_move(&self.mc, place); + self.delegate.consume(place, mode); } fn consume_exprs(&mut self, exprs: &[hir::Expr]) { @@ -573,7 +544,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { debug!("walk_pat(cmt_discr={:?}, pat={:?})", cmt_discr, pat); let tcx = self.tcx(); - let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self; + let ExprUseVisitor { ref mc, ref mut delegate } = *self; return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| { if let PatKind::Binding(_, canonical_id, ..) = pat.kind { debug!( @@ -602,7 +573,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { delegate.borrow(&cmt_pat, bk); } ty::BindByValue(..) => { - let mode = copy_or_move(mc, param_env, &cmt_pat); + let mode = copy_or_move(mc, &cmt_pat); debug!("walk_pat binding consuming pat"); delegate.consume(&cmt_pat, mode); } @@ -630,7 +601,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { var_id)); match upvar_capture { ty::UpvarCapture::ByValue => { - let mode = copy_or_move(&self.mc, self.param_env, &cmt_var); + let mode = copy_or_move(&self.mc, &cmt_var); self.delegate.consume(&cmt_var, mode); } ty::UpvarCapture::ByRef(upvar_borrow) => { @@ -655,10 +626,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { fn copy_or_move<'a, 'tcx>( mc: &mc::MemCategorizationContext<'a, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - cmt: &mc::Place<'tcx>, + place: &mc::Place<'tcx>, ) -> ConsumeMode { - if !mc.type_is_copy_modulo_regions(param_env, cmt.ty, cmt.span) { + if !mc.type_is_copy_modulo_regions(place.ty, place.span) { Move } else { Copy diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 1b641cba770a8..f6ce052f96be5 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -58,7 +58,6 @@ pub use self::Note::*; use self::Aliasability::*; -use crate::middle::region; use crate::hir::def_id::{DefId, LocalDefId}; use crate::hir::Node; use crate::infer::InferCtxt; @@ -212,13 +211,11 @@ impl HirNode for hir::Pat { #[derive(Clone)] pub struct MemCategorizationContext<'a, 'tcx> { - pub tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - pub body_owner: DefId, - pub upvars: Option<&'tcx FxIndexMap>, - pub region_scope_tree: &'a region::ScopeTree, pub tables: &'a ty::TypeckTables<'tcx>, - infcx: Option<&'a InferCtxt<'a, 'tcx>>, + infcx: &'a InferCtxt<'a, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + body_owner: DefId, + upvars: Option<&'tcx FxIndexMap>, } pub type McResult = Result; @@ -327,81 +324,42 @@ impl MutabilityCategory { } impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { + /// Creates a `MemCategorizationContext`. pub fn new( - tcx: TyCtxt<'tcx>, + infcx: &'a InferCtxt<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, body_owner: DefId, - region_scope_tree: &'a region::ScopeTree, tables: &'a ty::TypeckTables<'tcx>, ) -> MemCategorizationContext<'a, 'tcx> { MemCategorizationContext { - tcx, - body_owner, - upvars: tcx.upvars(body_owner), - region_scope_tree, tables, - infcx: None, + infcx, param_env, + body_owner, + upvars: infcx.tcx.upvars(body_owner), } } -} -impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { - /// Creates a `MemCategorizationContext` during type inference. - /// This is used during upvar analysis and a few other places. - /// Because the typeck tables are not yet complete, the results - /// from the analysis must be used with caution: - /// - /// - rvalue promotions are not known, so the lifetimes of - /// temporaries may be overly conservative; - /// - 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, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - body_owner: DefId, - region_scope_tree: &'a region::ScopeTree, - tables: &'a ty::TypeckTables<'tcx>, - ) -> MemCategorizationContext<'a, 'tcx> { - let tcx = infcx.tcx; - - MemCategorizationContext { - tcx, - body_owner, - upvars: tcx.upvars(body_owner), - region_scope_tree, - tables, - infcx: Some(infcx), - param_env, - } + crate fn tcx(&self) -> TyCtxt<'tcx> { + self.infcx.tcx } - pub fn type_is_copy_modulo_regions( + crate fn type_is_copy_modulo_regions( &self, - param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, span: Span, ) -> bool { - self.infcx.map(|infcx| infcx.type_is_copy_modulo_regions(param_env, ty, span)) - .or_else(|| { - if (param_env, ty).has_local_value() { - None - } else { - Some(ty.is_copy_modulo_regions(self.tcx, param_env, span)) - } - }) - .unwrap_or(true) + self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) } fn resolve_vars_if_possible(&self, value: &T) -> T where T: TypeFoldable<'tcx> { - self.infcx.map(|infcx| infcx.resolve_vars_if_possible(value)) - .unwrap_or_else(|| value.clone()) + self.infcx.resolve_vars_if_possible(value) } fn is_tainted_by_errors(&self) -> bool { - self.infcx.map_or(false, |infcx| infcx.is_tainted_by_errors()) + self.infcx.is_tainted_by_errors() } fn resolve_type_vars_or_error(&self, @@ -422,23 +380,20 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { None if self.is_tainted_by_errors() => Err(()), None => { bug!("no type for node {}: {} in mem_categorization", - id, self.tcx.hir().node_to_string(id)); + id, self.tcx().hir().node_to_string(id)); } } } - pub fn node_ty(&self, - hir_id: hir::HirId) - -> McResult> { - self.resolve_type_vars_or_error(hir_id, - self.tables.node_type_opt(hir_id)) + crate fn node_ty(&self, hir_id: hir::HirId) -> McResult> { + self.resolve_type_vars_or_error(hir_id, self.tables.node_type_opt(hir_id)) } - pub fn expr_ty(&self, expr: &hir::Expr) -> McResult> { + fn expr_ty(&self, expr: &hir::Expr) -> McResult> { self.resolve_type_vars_or_error(expr.hir_id, self.tables.expr_ty_opt(expr)) } - pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult> { + crate fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult> { self.resolve_type_vars_or_error(expr.hir_id, self.tables.expr_ty_adjusted_opt(expr)) } @@ -452,7 +407,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { /// implicit deref patterns attached (e.g., it is really /// `&Some(x)`). In that case, we return the "outermost" type /// (e.g., `&Option). - pub fn pat_ty_adjusted(&self, pat: &hir::Pat) -> McResult> { + pub(super) fn pat_ty_adjusted(&self, pat: &hir::Pat) -> McResult> { // Check for implicit `&` types wrapping the pattern; note // that these are never attached to binding patterns, so // actually this is somewhat "disjoint" from the code below @@ -542,7 +497,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { adjustment::Adjust::Deref(overloaded) => { // Equivalent to *expr or something similar. let base = Rc::new(if let Some(deref) = overloaded { - let ref_ty = self.tcx.mk_ref(deref.region, ty::TypeAndMut { + let ref_ty = self.tcx().mk_ref(deref.region, ty::TypeAndMut { ty: target, mutbl: deref.mutbl, }); @@ -582,7 +537,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { expr.hir_id, expr, base_cmt); - let f_index = self.tcx.field_index(expr.hir_id, self.tables); + let f_index = self.tcx().field_index(expr.hir_id, self.tables); Ok(self.cat_field(expr, base_cmt, f_index, f_ident, expr_ty)) } @@ -648,7 +603,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { Res::Def(DefKind::Static, def_id) => { // `#[thread_local]` statics may not outlive the current function, but // they also cannot be moved out of. - let is_thread_local = self.tcx.get_attrs(def_id)[..] + let is_thread_local = self.tcx().get_attrs(def_id)[..] .iter() .any(|attr| attr.check_name(sym::thread_local)); @@ -662,7 +617,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { hir_id, span, cat, - mutbl: match self.tcx.static_mutability(def_id).unwrap() { + mutbl: match self.tcx().static_mutability(def_id).unwrap() { Mutability::Immutable => McImmutable, Mutability::Mutable => McDeclared, }, @@ -679,7 +634,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { hir_id, span, cat: Categorization::Local(var_id), - mutbl: MutabilityCategory::from_local(self.tcx, self.tables, var_id), + mutbl: MutabilityCategory::from_local(self.tcx(), self.tables, var_id), ty: expr_ty, note: NoteNone }) @@ -722,25 +677,17 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // 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( + let fn_hir_id = self.tcx().hir().local_def_id_to_hir_id( LocalDefId::from_def_id(closure_expr_def_id), ); let ty = self.node_ty(fn_hir_id)?; let kind = match ty.kind { ty::Generator(..) => ty::ClosureKind::FnOnce, ty::Closure(closure_def_id, substs) => { - match self.infcx { - // During upvar inference we may not know the - // closure kind, just use the LATTICE_BOTTOM value. - Some(infcx) => - infcx.closure_kind( - closure_def_id, - substs - ).unwrap_or(ty::ClosureKind::LATTICE_BOTTOM), - - None => - substs.as_closure().kind(closure_def_id, self.tcx), - } + self.infcx.closure_kind( + closure_def_id, + substs + ).unwrap_or(ty::ClosureKind::LATTICE_BOTTOM) } _ => span_bug!(span, "unexpected type for fn in mem_categorization: {:?}", ty), }; @@ -753,7 +700,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { let var_ty = self.node_ty(var_id)?; // Mutability of original variable itself - let var_mutbl = MutabilityCategory::from_local(self.tcx, self.tables, var_id); + let var_mutbl = MutabilityCategory::from_local(self.tcx(), self.tables, var_id); // Construct the upvar. This represents access to the field // from the environment (perhaps we should eventually desugar @@ -818,7 +765,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { -> Place<'tcx> { // Region of environment pointer - let env_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion { + let env_region = self.tcx().mk_region(ty::ReFree(ty::FreeRegion { // The environment of a closure is guaranteed to // outlive any bindings introduced in the body of the // closure itself. @@ -839,7 +786,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // one. let cmt_result = Place { mutbl: McImmutable, - ty: self.tcx.types.err, + ty: self.tcx().types.err, ..cmt_result }; @@ -936,7 +883,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { ty::Ref(region, _, mutbl) => (region, mutbl), _ => span_bug!(expr.span, "cat_overloaded_place: base is not a reference") }; - let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut { + let ref_ty = self.tcx().mk_ref(region, ty::TypeAndMut { ty: place_ty, mutbl, }); @@ -1037,8 +984,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { variant_did: DefId) -> cmt<'tcx> { // univariant enums do not need downcasts - let base_did = self.tcx.parent(variant_did).unwrap(); - if self.tcx.adt_def(base_did).variants.len() != 1 { + let base_did = self.tcx().parent(variant_did).unwrap(); + if self.tcx().adt_def(base_did).variants.len() != 1 { let base_ty = base_cmt.ty; let ret = Rc::new(Place { hir_id: node.hir_id(), @@ -1179,10 +1126,10 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { return Err(()) } Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), variant_ctor_did) => { - let variant_did = self.tcx.parent(variant_ctor_did).unwrap(); - let enum_did = self.tcx.parent(variant_did).unwrap(); + let variant_did = self.tcx().parent(variant_ctor_did).unwrap(); + let enum_did = self.tcx().parent(variant_did).unwrap(); (self.cat_downcast_if_needed(pat, cmt, variant_did), - self.tcx.adt_def(enum_did) + self.tcx().adt_def(enum_did) .variant_with_ctor_id(variant_ctor_did).fields.len()) } Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), _) @@ -1204,7 +1151,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { def, pat.span, ); - self.tcx.sess.delay_span_bug(pat.span, &format!( + self.tcx().sess.delay_span_bug(pat.span, &format!( "tuple struct pattern didn't resolve to variant or struct {:?}", def, )); @@ -1230,7 +1177,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { return Err(()) } Res::Def(DefKind::Ctor(CtorOf::Variant, _), variant_ctor_did) => { - let variant_did = self.tcx.parent(variant_ctor_did).unwrap(); + let variant_did = self.tcx().parent(variant_ctor_did).unwrap(); self.cat_downcast_if_needed(pat, cmt, variant_did) } Res::Def(DefKind::Variant, variant_did) => { @@ -1241,7 +1188,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { for fp in field_pats { let field_ty = self.pat_ty_adjusted(&fp.pat)?; // see (*2) - let f_index = self.tcx.field_index(fp.hir_id, self.tables); + let f_index = self.tcx().field_index(fp.hir_id, self.tables); let cmt_field = Rc::new(self.cat_field(pat, cmt.clone(), f_index, fp.ident, field_ty)); self.cat_pattern_(cmt_field, &fp.pat, op)?; diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 170c4acad8b40..b1813f5046840 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -814,11 +814,10 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { where F: for<'b> FnOnce(mc::MemCategorizationContext<'b, 'tcx>) -> R, { - f(mc::MemCategorizationContext::with_infer( + f(mc::MemCategorizationContext::new( &self.infcx, self.outlives_environment.param_env, 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 5d17074e65e4e..185902142c748 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -171,20 +171,18 @@ impl<'a, 'tcx> FnCtxt<'a, '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, - closure_def_id: closure_def_id, + closure_def_id, current_closure_kind: ty::ClosureKind::LATTICE_BOTTOM, current_origin: None, adjust_upvar_captures: ty::UpvarCaptureMap::default(), }; - euv::ExprUseVisitor::with_infer( + euv::ExprUseVisitor::new( &mut delegate, &self.infcx, body_owner_def_id, self.param_env, - region_scope_tree, &self.tables.borrow(), ) .consume_body(body); From 1d53e437442b44b5c530c45cf9fdfd595ad715b1 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 8 Nov 2019 22:54:00 +0000 Subject: [PATCH 3/5] Simplify `mem_categorization` * `Place` is no longer recursive. * The `cmt` type alias is removed * `Upvar` places no longer include the dereferences of the environment closure or of by reference captures. * All non-dereference projections are combined to a single variant. * Various unnecessary types and methods have been removed. --- src/librustc/middle/expr_use_visitor.rs | 54 +- src/librustc/middle/mem_categorization.rs | 1066 +++-------------- src/librustc_typeck/check/regionck.rs | 258 ++-- src/librustc_typeck/check/upvar.rs | 225 ++-- src/test/ui/issues/issue-4335.rs | 3 +- src/test/ui/issues/issue-4335.stderr | 23 +- .../regions/regions-addr-of-upvar-self.stderr | 2 +- ...-infer-fn-once-move-from-projection.stderr | 2 +- 8 files changed, 374 insertions(+), 1259 deletions(-) diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 214f435351f00..201ae6597f4dd 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -13,7 +13,6 @@ use crate::middle::mem_categorization as mc; use crate::ty::{self, TyCtxt, adjustment}; use crate::hir::{self, PatKind}; -use std::rc::Rc; use syntax_pos::Span; /////////////////////////////////////////////////////////////////////////// @@ -136,12 +135,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { let param_ty = return_if_err!(self.mc.pat_ty_adjusted(¶m.pat)); debug!("consume_body: param_ty = {:?}", param_ty); - let param_cmt = Rc::new(self.mc.cat_rvalue( - param.hir_id, - param.pat.span, - param_ty)); + let param_place = self.mc.cat_rvalue(param.hir_id, param.pat.span, param_ty); - self.walk_irrefutable_pat(param_cmt, ¶m.pat); + self.walk_irrefutable_pat(¶m_place, ¶m.pat); } self.consume_expr(&body.value); @@ -234,12 +230,12 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } hir::ExprKind::Match(ref discr, ref arms, _) => { - let discr_cmt = Rc::new(return_if_err!(self.mc.cat_expr(&discr))); + let discr_cmt = return_if_err!(self.mc.cat_expr(&discr)); self.borrow_expr(&discr, ty::ImmBorrow); // treatment of the discriminant is handled while walking the arms. for arm in arms { - self.walk_arm(discr_cmt.clone(), arm); + self.walk_arm(&discr_cmt, arm); } } @@ -385,8 +381,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // "assigns", which is handled by // `walk_pat`: self.walk_expr(&expr); - let init_cmt = Rc::new(return_if_err!(self.mc.cat_expr(&expr))); - self.walk_irrefutable_pat(init_cmt, &local.pat); + let init_cmt = return_if_err!(self.mc.cat_expr(&expr)); + self.walk_irrefutable_pat(&init_cmt, &local.pat); } } @@ -417,11 +413,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { None => { return; } }; - let with_cmt = Rc::new(return_if_err!(self.mc.cat_expr(&with_expr))); + let with_place = return_if_err!(self.mc.cat_expr(&with_expr)); // Select just those fields of the `with` // expression that will actually be used - match with_cmt.ty.kind { + match with_place.ty.kind { ty::Adt(adt, substs) if adt.is_struct() => { // Consume those fields of the with expression that are needed. for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() { @@ -429,14 +425,12 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.tcx().field_index(f.hir_id, self.mc.tables) == f_index }); if !is_mentioned { - let cmt_field = self.mc.cat_field( + let field_place = self.mc.cat_projection( &*with_expr, - with_cmt.clone(), - f_index, - with_field.ident, - with_field.ty(self.tcx(), substs) + with_place.clone(), + with_field.ty(self.tcx(), substs), ); - self.delegate_consume(&cmt_field); + self.delegate_consume(&field_place); } } } @@ -522,8 +516,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } } - fn walk_arm(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &hir::Arm) { - self.walk_pat(discr_cmt.clone(), &arm.pat); + fn walk_arm(&mut self, discr_place: &mc::Place<'tcx>, arm: &hir::Arm) { + self.walk_pat(discr_place, &arm.pat); if let Some(hir::Guard::If(ref e)) = arm.guard { self.consume_expr(e) @@ -534,22 +528,22 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { /// Walks a pat that occurs in isolation (i.e., top-level of fn argument or /// let binding, and *not* a match arm or nested pat.) - fn walk_irrefutable_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat) { - self.walk_pat(cmt_discr, pat); + fn walk_irrefutable_pat(&mut self, discr_place: &mc::Place<'tcx>, pat: &hir::Pat) { + self.walk_pat(discr_place, pat); } /// The core driver for walking a pattern - fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat) { - debug!("walk_pat(cmt_discr={:?}, pat={:?})", cmt_discr, pat); + fn walk_pat(&mut self, discr_place: &mc::Place<'tcx>, pat: &hir::Pat) { + debug!("walk_pat(discr_place={:?}, pat={:?})", discr_place, pat); let tcx = self.tcx(); let ExprUseVisitor { ref mc, ref mut delegate } = *self; - return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| { + return_if_err!(mc.cat_pattern(discr_place.clone(), pat, |place, pat| { if let PatKind::Binding(_, canonical_id, ..) = pat.kind { debug!( - "walk_pat: binding cmt_pat={:?} pat={:?}", - cmt_pat, + "walk_pat: binding place={:?} pat={:?}", + place, pat, ); if let Some(&bm) = mc.tables.pat_binding_modes().get(pat.hir_id) { @@ -570,12 +564,12 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { match bm { ty::BindByReference(m) => { let bk = ty::BorrowKind::from_mutbl(m); - delegate.borrow(&cmt_pat, bk); + delegate.borrow(place, bk); } ty::BindByValue(..) => { - let mode = copy_or_move(mc, &cmt_pat); + let mode = copy_or_move(mc, place); debug!("walk_pat binding consuming pat"); - delegate.consume(&cmt_pat, mode); + delegate.consume(place, mode); } } } else { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index f6ce052f96be5..50a70ebc515ca 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -48,152 +48,72 @@ //! result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference //! tied to `x`. The type of `x'` will be a borrowed pointer. -#![allow(non_camel_case_types)] - -pub use self::PointerKind::*; -pub use self::InteriorKind::*; -pub use self::MutabilityCategory::*; -pub use self::AliasableReason::*; -pub use self::Note::*; - -use self::Aliasability::*; - -use crate::hir::def_id::{DefId, LocalDefId}; -use crate::hir::Node; +use crate::hir::def_id::DefId; use crate::infer::InferCtxt; -use crate::hir::def::{CtorOf, Res, DefKind, CtorKind}; +use crate::hir::def::{Res, DefKind}; use crate::ty::adjustment; -use crate::ty::{self, DefIdTree, Ty, TyCtxt}; +use crate::ty::{self, Ty, TyCtxt}; use crate::ty::fold::TypeFoldable; -use crate::hir::{Mutability, PatKind}; -use crate::hir::pat_util::EnumerateAndAdjustIterator; +use crate::hir::PatKind; use crate::hir; -use syntax::ast::{self, Name}; -use syntax::symbol::sym; use syntax_pos::Span; -use std::borrow::Cow; -use std::fmt; -use std::hash::{Hash, Hasher}; use rustc_data_structures::fx::FxIndexMap; -use std::rc::Rc; -#[derive(Clone, Debug, PartialEq)] -pub enum Categorization<'tcx> { - Rvalue, // temporary val - ThreadLocal, // value that cannot move, but still restricted in scope +#[derive(Clone, Debug)] +pub enum PlaceBase { + /// A temporary variable + Rvalue, + /// A named `static` item StaticItem, - Upvar(Upvar), // upvar referenced by closure env - Local(hir::HirId), // local variable - Deref(cmt<'tcx>, PointerKind<'tcx>), // deref of a ptr - Interior(cmt<'tcx>, InteriorKind), // something interior: field, tuple, etc - Downcast(cmt<'tcx>, DefId), // selects a particular enum variant (*1) - - // (*1) downcast is only required if the enum has more than one variant -} - -// Represents any kind of upvar -#[derive(Clone, Copy, PartialEq)] -pub struct Upvar { - pub id: ty::UpvarId, - pub kind: ty::ClosureKind + /// A named local variable + Local(hir::HirId), + /// An upvar referenced by closure env + Upvar(ty::UpvarId), } -// different kinds of pointers: -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum PointerKind<'tcx> { - /// `Box` - Unique, - - /// `&T` - BorrowedPtr(ty::BorrowKind, ty::Region<'tcx>), - - /// `*T` - UnsafePtr(hir::Mutability), -} - -// We use the term "interior" to mean "something reachable from the -// base without a pointer dereference", e.g., a field -#[derive(Clone, PartialEq)] -pub enum InteriorKind { - InteriorField(FieldIndex), - InteriorElement(InteriorOffsetKind), +#[derive(Clone, Debug)] +pub enum Projection<'tcx> { + /// A dereference of a pointer, reference or `Box` of the given type + Deref(Ty<'tcx>), + /// An index or a field + Other, } -// Contains index of a field that is actually used for loan path comparisons and -// string representation of the field that should be used only for diagnostics. -#[derive(Clone, Copy, Eq)] -pub struct FieldIndex(pub usize, pub Name); - -impl PartialEq for FieldIndex { - fn eq(&self, rhs: &Self) -> bool { - self.0 == rhs.0 - } +/// A `Place` represents how a value is located in memory. +/// +/// This is an HIR version of `mir::Place` +#[derive(Clone, Debug)] +pub struct Place<'tcx> { + /// `HirId` of the expression or pattern producing this value. + pub hir_id: hir::HirId, + /// The `Span` of the expression or pattern producing this value. + pub span: Span, + /// The type of the `Place` + pub ty: Ty<'tcx>, + /// The "outermost" place that holds this value. + pub base: PlaceBase, + /// How this place is derived from the base place. + pub projections: Vec>, } -impl Hash for FieldIndex { - fn hash(&self, h: &mut H) { - self.0.hash(h) +impl<'tcx> Place<'tcx> { + /// Returns an iterator of the types that have to be dereferenced to access + /// the `Place`. + /// + /// The types are in the reverse order that they are applied. So if + /// `x: &*const u32` and the `Place` is `**x`, then the types returned are + ///`*const u32` then `&*const u32`. + pub fn deref_tys(&self) -> impl Iterator> + '_ { + self.projections.iter().rev().filter_map(|proj| if let Projection::Deref(deref_ty) = *proj { + Some(deref_ty) + } else { + None + }) } } -#[derive(Clone, PartialEq)] -pub enum InteriorOffsetKind { - Index, // e.g., `array_expr[index_expr]` - Pattern, // e.g., `fn foo([_, a, _, _]: [A; 4]) { ... }` -} - -#[derive(Clone, Copy, PartialEq, Debug)] -pub enum MutabilityCategory { - McImmutable, // Immutable. - McDeclared, // Directly declared as mutable. - McInherited, // Inherited from the fact that owner is mutable. -} - -// A note about the provenance of a `cmt`. This is used for -// special-case handling of upvars such as mutability inference. -// Upvar categorization can generate a variable number of nested -// derefs. The note allows detecting them without deep pattern -// matching on the categorization. -#[derive(Clone, Copy, PartialEq, Debug)] -pub enum Note { - NoteClosureEnv(ty::UpvarId), // Deref through closure env - NoteUpvarRef(ty::UpvarId), // Deref through by-ref upvar - NoteIndex, // Deref as part of desugaring `x[]` into its two components - NoteNone // Nothing special -} - -// `cmt`: "Category, Mutability, and Type". -// -// a complete categorization of a value indicating where it originated -// and how it is located, as well as the mutability of the memory in -// which the value is stored. -// -// *WARNING* The field `cmt.type` is NOT necessarily the same as the -// result of `node_type(cmt.id)`. -// -// (FIXME: rewrite the following comment given that `@x` managed -// pointers have been obsolete for quite some time.) -// -// This is because the `id` is always the `id` of the node producing the -// type; in an expression like `*x`, the type of this deref node is the -// deref'd type (`T`), but in a pattern like `@x`, the `@x` pattern is -// again a dereference, but its type is the type *before* the -// dereference (`@T`). So use `cmt.ty` to find the type of the value in -// a consistent fashion. For more details, see the method `cat_pattern` -#[derive(Clone, Debug, PartialEq)] -pub struct Place<'tcx> { - pub hir_id: hir::HirId, // HIR id of expr/pat producing this value - pub span: Span, // span of same expr/pat - pub cat: Categorization<'tcx>, // categorization of expr - pub mutbl: MutabilityCategory, // mutability of expr as place - pub ty: Ty<'tcx>, // type of the expr (*see WARNING above*) - pub note: Note, // Note about the provenance of this cmt -} - -pub type cmt<'tcx> = Rc>; - pub trait HirNode { fn hir_id(&self) -> hir::HirId; fn span(&self) -> Span; @@ -220,109 +140,6 @@ pub struct MemCategorizationContext<'a, 'tcx> { pub type McResult = Result; -impl MutabilityCategory { - pub fn from_mutbl(m: hir::Mutability) -> MutabilityCategory { - let ret = match m { - Mutability::Immutable => McImmutable, - Mutability::Mutable => McDeclared - }; - debug!("MutabilityCategory::{}({:?}) => {:?}", - "from_mutbl", m, ret); - ret - } - - pub fn from_borrow_kind(borrow_kind: ty::BorrowKind) -> MutabilityCategory { - let ret = match borrow_kind { - ty::ImmBorrow => McImmutable, - ty::UniqueImmBorrow => McImmutable, - ty::MutBorrow => McDeclared, - }; - debug!("MutabilityCategory::{}({:?}) => {:?}", - "from_borrow_kind", borrow_kind, ret); - ret - } - - fn from_pointer_kind(base_mutbl: MutabilityCategory, - ptr: PointerKind<'_>) -> MutabilityCategory { - let ret = match ptr { - Unique => { - base_mutbl.inherit() - } - BorrowedPtr(borrow_kind, _) => { - MutabilityCategory::from_borrow_kind(borrow_kind) - } - UnsafePtr(m) => { - MutabilityCategory::from_mutbl(m) - } - }; - debug!("MutabilityCategory::{}({:?}, {:?}) => {:?}", - "from_pointer_kind", base_mutbl, ptr, ret); - ret - } - - fn from_local( - tcx: TyCtxt<'_>, - tables: &ty::TypeckTables<'_>, - id: hir::HirId, - ) -> MutabilityCategory { - let ret = match tcx.hir().get(id) { - Node::Binding(p) => match p.kind { - PatKind::Binding(..) => { - let bm = *tables.pat_binding_modes() - .get(p.hir_id) - .expect("missing binding mode"); - if bm == ty::BindByValue(Mutability::Mutable) { - McDeclared - } else { - McImmutable - } - } - _ => span_bug!(p.span, "expected identifier pattern") - }, - _ => span_bug!(tcx.hir().span(id), "expected identifier pattern") - }; - debug!("MutabilityCategory::{}(tcx, id={:?}) => {:?}", - "from_local", id, ret); - ret - } - - pub fn inherit(&self) -> MutabilityCategory { - let ret = match *self { - McImmutable => McImmutable, - McDeclared => McInherited, - McInherited => McInherited, - }; - debug!("{:?}.inherit() => {:?}", self, ret); - ret - } - - pub fn is_mutable(&self) -> bool { - let ret = match *self { - McImmutable => false, - McInherited => true, - McDeclared => true, - }; - debug!("{:?}.is_mutable() => {:?}", self, ret); - ret - } - - pub fn is_immutable(&self) -> bool { - let ret = match *self { - McImmutable => true, - McDeclared | McInherited => false - }; - debug!("{:?}.is_immutable() => {:?}", self, ret); - ret - } - - pub fn to_user_str(&self) -> &'static str { - match *self { - McDeclared | McInherited => "mutable", - McImmutable => "immutable", - } - } -} - impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { /// Creates a `MemCategorizationContext`. pub fn new( @@ -407,7 +224,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { /// implicit deref patterns attached (e.g., it is really /// `&Some(x)`). In that case, we return the "outermost" type /// (e.g., `&Option). - pub(super) fn pat_ty_adjusted(&self, pat: &hir::Pat) -> McResult> { + crate fn pat_ty_adjusted(&self, pat: &hir::Pat) -> McResult> { // Check for implicit `&` types wrapping the pattern; note // that these are never attached to binding patterns, so // actually this is somewhat "disjoint" from the code below @@ -496,23 +313,23 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { match adjustment.kind { adjustment::Adjust::Deref(overloaded) => { // Equivalent to *expr or something similar. - let base = Rc::new(if let Some(deref) = overloaded { + let base = if let Some(deref) = overloaded { let ref_ty = self.tcx().mk_ref(deref.region, ty::TypeAndMut { ty: target, mutbl: deref.mutbl, }); - self.cat_rvalue_node(expr.hir_id, expr.span, ref_ty) + self.cat_rvalue(expr.hir_id, expr.span, ref_ty) } else { previous()? - }); - self.cat_deref(expr, base, NoteNone) + }; + self.cat_deref(expr, base) } adjustment::Adjust::NeverToAny | adjustment::Adjust::Pointer(_) | adjustment::Adjust::Borrow(_) => { // Result is an rvalue. - Ok(self.cat_rvalue_node(expr.hir_id, expr.span, target)) + Ok(self.cat_rvalue(expr.hir_id, expr.span, target)) } } } @@ -524,21 +341,20 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { match expr.kind { hir::ExprKind::Unary(hir::UnDeref, ref e_base) => { if self.tables.is_method_call(expr) { - self.cat_overloaded_place(expr, e_base, NoteNone) + self.cat_overloaded_place(expr, e_base) } else { - let base_cmt = Rc::new(self.cat_expr(&e_base)?); - self.cat_deref(expr, base_cmt, NoteNone) + let base = self.cat_expr(&e_base)?; + self.cat_deref(expr, base) } } - hir::ExprKind::Field(ref base, f_ident) => { - let base_cmt = Rc::new(self.cat_expr(&base)?); + hir::ExprKind::Field(ref base, _) => { + let base = self.cat_expr(&base)?; debug!("cat_expr(cat_field): id={} expr={:?} base={:?}", expr.hir_id, expr, - base_cmt); - let f_index = self.tcx().field_index(expr.hir_id, self.tables); - Ok(self.cat_field(expr, base_cmt, f_index, f_ident, expr_ty)) + base); + Ok(self.cat_projection(expr, base, expr_ty)) } hir::ExprKind::Index(ref base, _) => { @@ -548,10 +364,10 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // The call to index() returns a `&T` value, which // is an rvalue. That is what we will be // dereferencing. - self.cat_overloaded_place(expr, base, NoteIndex) + self.cat_overloaded_place(expr, base) } else { - let base_cmt = Rc::new(self.cat_expr(&base)?); - self.cat_index(expr, base_cmt, expr_ty, InteriorOffsetKind::Index) + let base = self.cat_expr(&base)?; + Ok(self.cat_projection(expr, base, expr_ty)) } } @@ -575,12 +391,12 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { hir::ExprKind::Lit(..) | hir::ExprKind::Break(..) | hir::ExprKind::Continue(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) | hir::ExprKind::InlineAsm(..) | hir::ExprKind::Box(..) | hir::ExprKind::Err => { - Ok(self.cat_rvalue_node(expr.hir_id, expr.span, expr_ty)) + Ok(self.cat_rvalue(expr.hir_id, expr.span, expr_ty)) } } } - pub fn cat_res(&self, + crate fn cat_res(&self, hir_id: hir::HirId, span: Span, expr_ty: Ty<'tcx>, @@ -597,32 +413,16 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { | Res::Def(DefKind::Fn, _) | Res::Def(DefKind::Method, _) | Res::SelfCtor(..) => { - Ok(self.cat_rvalue_node(hir_id, span, expr_ty)) + Ok(self.cat_rvalue(hir_id, span, expr_ty)) } - Res::Def(DefKind::Static, def_id) => { - // `#[thread_local]` statics may not outlive the current function, but - // they also cannot be moved out of. - let is_thread_local = self.tcx().get_attrs(def_id)[..] - .iter() - .any(|attr| attr.check_name(sym::thread_local)); - - let cat = if is_thread_local { - Categorization::ThreadLocal - } else { - Categorization::StaticItem - }; - + Res::Def(DefKind::Static, _) => { Ok(Place { hir_id, span, - cat, - mutbl: match self.tcx().static_mutability(def_id).unwrap() { - Mutability::Immutable => McImmutable, - Mutability::Mutable => McDeclared, - }, - ty:expr_ty, - note: NoteNone + ty: expr_ty, + base: PlaceBase::StaticItem, + projections: Vec::new(), }) } @@ -633,10 +433,9 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { Ok(Place { hir_id, span, - cat: Categorization::Local(var_id), - mutbl: MutabilityCategory::from_local(self.tcx(), self.tables, var_id), ty: expr_ty, - note: NoteNone + base: PlaceBase::Local(var_id), + projections: Vec::new(), }) } } @@ -645,218 +444,64 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } } - // Categorize an upvar, complete with invisible derefs of closure - // environment and upvar reference as appropriate. + /// Categorize an upvar. + /// + /// Note: the actual upvar access contains invisible derefs of closure + /// environment and upvar reference as appropriate. Only regionck cares + /// about these dereferences, so we let it compute them as needed. fn cat_upvar( &self, hir_id: hir::HirId, span: Span, var_id: hir::HirId, ) -> 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 - // field from the environment. - // - // `Categorization::Upvar`. Next, we add a deref through the implicit - // environment pointer with an anonymous free region 'env and - // appropriate borrow kind for closure kinds that take self by - // reference. Finally, if the upvar was captured - // by-reference, we add a deref through that reference. The - // region of this reference is an inference variable 'up that - // was previously generated and recorded in the upvar borrow - // map. The borrow kind bk is inferred by based on how the - // upvar is used. - // - // This results in the following table for concrete closure - // types: - // - // | move | ref - // ---------------+----------------------+------------------------------- - // Fn | copied -> &'env | upvar -> &'env -> &'up bk - // 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), - ); - let ty = self.node_ty(fn_hir_id)?; - let kind = match ty.kind { - ty::Generator(..) => ty::ClosureKind::FnOnce, - ty::Closure(closure_def_id, substs) => { - self.infcx.closure_kind( - closure_def_id, - substs - ).unwrap_or(ty::ClosureKind::LATTICE_BOTTOM) - } - _ => span_bug!(span, "unexpected type for fn in mem_categorization: {:?}", ty), - }; let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_id }, closure_expr_id: closure_expr_def_id.to_local(), }; - let var_ty = self.node_ty(var_id)?; - // Mutability of original variable itself - let var_mutbl = MutabilityCategory::from_local(self.tcx(), self.tables, var_id); - - // Construct the upvar. This represents access to the field - // from the environment (perhaps we should eventually desugar - // this field further, but it will do for now). - let cmt_result = Place { + let ret = Place { hir_id, span, - cat: Categorization::Upvar(Upvar {id: upvar_id, kind: kind}), - mutbl: var_mutbl, ty: var_ty, - note: NoteNone - }; - - // If this is a `FnMut` or `Fn` closure, then the above is - // conceptually a `&mut` or `&` reference, so we have to add a - // deref. - let cmt_result = match kind { - ty::ClosureKind::FnOnce => { - cmt_result - } - ty::ClosureKind::FnMut => { - self.env_deref(hir_id, span, upvar_id, var_mutbl, ty::MutBorrow, cmt_result) - } - ty::ClosureKind::Fn => { - self.env_deref(hir_id, span, upvar_id, var_mutbl, ty::ImmBorrow, cmt_result) - } - }; - - // If this is a by-ref capture, then the upvar we loaded is - // actually a reference, so we have to add an implicit deref - // for that. - let upvar_capture = self.tables.upvar_capture(upvar_id); - let cmt_result = match upvar_capture { - ty::UpvarCapture::ByValue => { - cmt_result - } - ty::UpvarCapture::ByRef(upvar_borrow) => { - let ptr = BorrowedPtr(upvar_borrow.kind, upvar_borrow.region); - Place { - hir_id, - span, - cat: Categorization::Deref(Rc::new(cmt_result), ptr), - mutbl: MutabilityCategory::from_borrow_kind(upvar_borrow.kind), - ty: var_ty, - note: NoteUpvarRef(upvar_id) - } - } + base: PlaceBase::Upvar(upvar_id), + projections: Vec::new(), }; - let ret = cmt_result; debug!("cat_upvar ret={:?}", ret); Ok(ret) } - fn env_deref(&self, - hir_id: hir::HirId, - span: Span, - upvar_id: ty::UpvarId, - upvar_mutbl: MutabilityCategory, - env_borrow_kind: ty::BorrowKind, - cmt_result: Place<'tcx>) - -> Place<'tcx> - { - // Region of environment pointer - let env_region = self.tcx().mk_region(ty::ReFree(ty::FreeRegion { - // The environment of a closure is guaranteed to - // outlive any bindings introduced in the body of the - // closure itself. - scope: upvar_id.closure_expr_id.to_def_id(), - bound_region: ty::BrEnv - })); - - let env_ptr = BorrowedPtr(env_borrow_kind, env_region); - - let var_ty = cmt_result.ty; - - // We need to add the env deref. This means - // that the above is actually immutable and - // has a ref type. However, nothing should - // actually look at the type, so we can get - // away with stuffing a `Error` in there - // instead of bothering to construct a proper - // one. - let cmt_result = Place { - mutbl: McImmutable, - ty: self.tcx().types.err, - ..cmt_result - }; - - let mut deref_mutbl = MutabilityCategory::from_borrow_kind(env_borrow_kind); - - // Issue #18335. If variable is declared as immutable, override the - // mutability from the environment and substitute an `&T` anyway. - match upvar_mutbl { - McImmutable => { deref_mutbl = McImmutable; } - McDeclared | McInherited => { } - } - + pub fn cat_rvalue(&self, hir_id: hir::HirId, span: Span, expr_ty: Ty<'tcx>) -> Place<'tcx> { + debug!("cat_rvalue hir_id={:?}, expr_ty={:?}, span={:?}", hir_id, expr_ty, span); let ret = Place { hir_id, span, - cat: Categorization::Deref(Rc::new(cmt_result), env_ptr), - mutbl: deref_mutbl, - ty: var_ty, - note: NoteClosureEnv(upvar_id) - }; - - debug!("env_deref ret {:?}", ret); - - ret - } - - pub fn cat_rvalue_node(&self, - hir_id: hir::HirId, - span: Span, - expr_ty: Ty<'tcx>) - -> Place<'tcx> { - debug!("cat_rvalue_node(id={:?}, span={:?}, expr_ty={:?})", - hir_id, span, expr_ty); - - let ret = self.cat_rvalue(hir_id, span, expr_ty); - debug!("cat_rvalue_node ret {:?}", ret); - ret - } - - pub fn cat_rvalue(&self, - cmt_hir_id: hir::HirId, - span: Span, - expr_ty: Ty<'tcx>) -> Place<'tcx> { - let ret = Place { - hir_id: cmt_hir_id, - span:span, - cat:Categorization::Rvalue, - mutbl:McDeclared, - ty:expr_ty, - note: NoteNone + base: PlaceBase::Rvalue, + projections: Vec::new(), + ty: expr_ty, }; - debug!("cat_rvalue ret {:?}", ret); + debug!("cat_rvalue ret={:?}", ret); ret } - pub fn cat_field(&self, - node: &N, - base_cmt: cmt<'tcx>, - f_index: usize, - f_ident: ast::Ident, - f_ty: Ty<'tcx>) - -> Place<'tcx> { + crate fn cat_projection( + &self, + node: &N, + base_place: Place<'tcx>, + ty: Ty<'tcx>, + ) -> Place<'tcx> { + let mut projections = base_place.projections; + projections.push(Projection::Other); let ret = Place { hir_id: node.hir_id(), span: node.span(), - mutbl: base_cmt.mutbl.inherit(), - cat: Categorization::Interior(base_cmt, - InteriorField(FieldIndex(f_index, f_ident.name))), - ty: f_ty, - note: NoteNone + ty, + base: base_place.base, + projections, }; debug!("cat_field ret {:?}", ret); ret @@ -866,12 +511,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { &self, expr: &hir::Expr, base: &hir::Expr, - note: Note, ) -> McResult> { - debug!("cat_overloaded_place(expr={:?}, base={:?}, note={:?})", - expr, - base, - note); + debug!("cat_overloaded_place(expr={:?}, base={:?})", expr, base); // Reconstruct the output assuming it's a reference with the // same region and mutability as the receiver. This holds for @@ -888,182 +529,60 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { mutbl, }); - let base_cmt = Rc::new(self.cat_rvalue_node(expr.hir_id, expr.span, ref_ty)); - self.cat_deref(expr, base_cmt, note) + let base_cmt = self.cat_rvalue(expr.hir_id, expr.span, ref_ty); + self.cat_deref(expr, base_cmt) } - pub fn cat_deref( + fn cat_deref( &self, node: &impl HirNode, - base_cmt: cmt<'tcx>, - note: Note, + base_place: Place<'tcx>, ) -> McResult> { - debug!("cat_deref: base_cmt={:?}", base_cmt); + debug!("cat_deref: base_cmt={:?}", base_place); - let base_cmt_ty = base_cmt.ty; - let deref_ty = match base_cmt_ty.builtin_deref(true) { + let base_ty = base_place.ty; + let deref_ty = match base_ty.builtin_deref(true) { Some(mt) => mt.ty, None => { - debug!("explicit deref of non-derefable type: {:?}", base_cmt_ty); + debug!("explicit deref of non-derefable type: {:?}", base_ty); return Err(()); } }; + let mut projections = base_place.projections; + projections.push(Projection::Deref(base_ty)); - let ptr = match base_cmt.ty.kind { - ty::Adt(def, ..) if def.is_box() => Unique, - ty::RawPtr(ref mt) => UnsafePtr(mt.mutbl), - ty::Ref(r, _, mutbl) => { - let bk = ty::BorrowKind::from_mutbl(mutbl); - BorrowedPtr(bk, r) - } - _ => bug!("unexpected type in cat_deref: {:?}", base_cmt.ty) - }; let ret = Place { hir_id: node.hir_id(), span: node.span(), - // For unique ptrs, we inherit mutability from the owning reference. - mutbl: MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr), - cat: Categorization::Deref(base_cmt, ptr), ty: deref_ty, - note: note, + base: base_place.base, + projections, }; debug!("cat_deref ret {:?}", ret); Ok(ret) } - fn cat_index(&self, - elt: &N, - base_cmt: cmt<'tcx>, - element_ty: Ty<'tcx>, - context: InteriorOffsetKind) - -> McResult> { - //! Creates a cmt for an indexing operation (`[]`). - //! - //! One subtle aspect of indexing that may not be - //! immediately obvious: for anything other than a fixed-length - //! vector, an operation like `x[y]` actually consists of two - //! disjoint (from the point of view of borrowck) operations. - //! The first is a deref of `x` to create a pointer `p` that points - //! at the first element in the array. The second operation is - //! an index which adds `y*sizeof(T)` to `p` to obtain the - //! pointer to `x[y]`. `cat_index` will produce a resulting - //! cmt containing both this deref and the indexing, - //! presuming that `base_cmt` is not of fixed-length type. - //! - //! # Parameters - //! - `elt`: the HIR node being indexed - //! - `base_cmt`: the cmt of `elt` - - let interior_elem = InteriorElement(context); - let ret = self.cat_imm_interior(elt, base_cmt, element_ty, interior_elem); - debug!("cat_index ret {:?}", ret); - return Ok(ret); - } - - pub fn cat_imm_interior(&self, - node: &N, - base_cmt: cmt<'tcx>, - interior_ty: Ty<'tcx>, - interior: InteriorKind) - -> Place<'tcx> { - let ret = Place { - hir_id: node.hir_id(), - span: node.span(), - mutbl: base_cmt.mutbl.inherit(), - cat: Categorization::Interior(base_cmt, interior), - ty: interior_ty, - note: NoteNone - }; - debug!("cat_imm_interior ret={:?}", ret); - ret - } - - pub fn cat_downcast_if_needed(&self, - node: &N, - base_cmt: cmt<'tcx>, - variant_did: DefId) - -> cmt<'tcx> { - // univariant enums do not need downcasts - let base_did = self.tcx().parent(variant_did).unwrap(); - if self.tcx().adt_def(base_did).variants.len() != 1 { - let base_ty = base_cmt.ty; - let ret = Rc::new(Place { - hir_id: node.hir_id(), - span: node.span(), - mutbl: base_cmt.mutbl.inherit(), - cat: Categorization::Downcast(base_cmt, variant_did), - ty: base_ty, - note: NoteNone - }); - debug!("cat_downcast ret={:?}", ret); - ret - } else { - debug!("cat_downcast univariant={:?}", base_cmt); - base_cmt - } - } - - pub fn cat_pattern(&self, cmt: cmt<'tcx>, pat: &hir::Pat, mut op: F) -> McResult<()> - where F: FnMut(cmt<'tcx>, &hir::Pat), + pub fn cat_pattern(&self, place: Place<'tcx>, pat: &hir::Pat, mut op: F) -> McResult<()> + where F: FnMut(&Place<'tcx>, &hir::Pat), { - self.cat_pattern_(cmt, pat, &mut op) + self.cat_pattern_(place, pat, &mut op) } // FIXME(#19596) This is a workaround, but there should be a better way to do this - fn cat_pattern_(&self, mut cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McResult<()> - where F : FnMut(cmt<'tcx>, &hir::Pat) + fn cat_pattern_(&self, mut place: Place<'tcx>, pat: &hir::Pat, op: &mut F) -> McResult<()> + where F: FnMut(&Place<'tcx>, &hir::Pat) { - // Here, `cmt` is the categorization for the value being - // matched and pat is the pattern it is being matched against. - // - // In general, the way that this works is that we walk down - // the pattern, constructing a cmt that represents the path - // that will be taken to reach the value being matched. - // - // When we encounter named bindings, we take the cmt that has - // been built up and pass it off to guarantee_valid() so that - // we can be sure that the binding will remain valid for the - // duration of the arm. - // - // (*2) There is subtlety concerning the correspondence between - // pattern ids and types as compared to *expression* ids and - // types. This is explained briefly. on the definition of the - // type `cmt`, so go off and read what it says there, then - // come back and I'll dive into a bit more detail here. :) OK, - // back? - // - // In general, the id of the cmt should be the node that - // "produces" the value---patterns aren't executable code - // exactly, but I consider them to "execute" when they match a - // value, and I consider them to produce the value that was - // matched. So if you have something like: - // - // (FIXME: `@@3` is not legal code anymore!) - // - // let x = @@3; - // match x { - // @@y { ... } - // } - // - // In this case, the cmt and the relevant ids would be: - // - // CMT Id Type of Id Type of cmt + // Here, `place` is the `Place` being matched and pat is the pattern it + // is being matched against. // - // local(x)->@->@ - // ^~~~~~~^ `x` from discr @@int @@int - // ^~~~~~~~~~^ `@@y` pattern node @@int @int - // ^~~~~~~~~~~~~^ `@y` pattern node @int int - // - // You can see that the types of the id and the cmt are in - // sync in the first line, because that id is actually the id - // of an expression. But once we get to pattern ids, the types - // step out of sync again. So you'll see below that we always - // get the type of the *subpattern* and use that. + // In general, the way that this works is that we walk down the pattern, + // constructing a `Place` that represents the path that will be taken + // to reach the value being matched. - debug!("cat_pattern(pat={:?}, cmt={:?})", pat, cmt); + debug!("cat_pattern(pat={:?}, place={:?})", pat, place); - // If (pattern) adjustments are active for this pattern, adjust the `cmt` correspondingly. - // `cmt`s are constructed differently from patterns. For example, in + // If (pattern) adjustments are active for this pattern, adjust the `Place` correspondingly. + // `Place`s are constructed differently from patterns. For example, in // // ``` // match foo { @@ -1073,13 +592,13 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // ``` // // the pattern `&&Some(x,)` is represented as `Ref { Ref { TupleStruct }}`. To build the - // corresponding `cmt` we start with a `cmt` for `foo`, and then, by traversing the + // corresponding `Place` we start with the `Place` for `foo`, and then, by traversing the // pattern, try to answer the question: given the address of `foo`, how is `x` reached? // - // `&&Some(x,)` `cmt_foo` - // `&Some(x,)` `deref { cmt_foo}` - // `Some(x,)` `deref { deref { cmt_foo }}` - // (x,)` `field0 { deref { deref { cmt_foo }}}` <- resulting cmt + // `&&Some(x,)` `place_foo` + // `&Some(x,)` `deref { place_foo}` + // `Some(x,)` `deref { deref { place_foo }}` + // (x,)` `field0 { deref { deref { place_foo }}}` <- resulting cmt // // The above example has no adjustments. If the code were instead the (after adjustments, // equivalent) version @@ -1091,20 +610,20 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // } // ``` // - // Then we see that to get the same result, we must start with `deref { deref { cmt_foo }}` - // instead of `cmt_foo` since the pattern is now `Some(x,)` and not `&&Some(x,)`, even - // though its assigned type is that of `&&Some(x,)`. + // Then we see that to get the same result, we must start with + // `deref { deref { place_foo }}` instead of `place_foo` since the pattern is now `Some(x,)` + // and not `&&Some(x,)`, even though its assigned type is that of `&&Some(x,)`. for _ in 0..self.tables .pat_adjustments() .get(pat.hir_id) .map(|v| v.len()) .unwrap_or(0) { - debug!("cat_pattern: applying adjustment to cmt={:?}", cmt); - cmt = Rc::new(self.cat_deref(pat, cmt, NoteNone)?); + debug!("cat_pattern: applying adjustment to place={:?}", place); + place = self.cat_deref(pat, place)?; } - let cmt = cmt; // lose mutability - debug!("cat_pattern: applied adjustment derefs to get cmt={:?}", cmt); + let place = place; // lose mutability + debug!("cat_pattern: applied adjustment derefs to get place={:?}", place); // Invoke the callback, but only now, after the `cmt` has adjusted. // @@ -1115,138 +634,65 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // `Some(x)` (which matches). Recursing once more, `*&Some(3)` and the pattern `Some(x)` // result in the cmt `Downcast(*&Some(3)).0` associated to `x` and invoke `op` with // that (where the `ref` on `x` is implied). - op(cmt.clone(), pat); + op(&place, pat); match pat.kind { - PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => { - let res = self.tables.qpath_res(qpath, pat.hir_id); - let (cmt, expected_len) = match res { - Res::Err => { - debug!("access to unresolvable pattern {:?}", pat); - return Err(()) - } - Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), variant_ctor_did) => { - let variant_did = self.tcx().parent(variant_ctor_did).unwrap(); - let enum_did = self.tcx().parent(variant_did).unwrap(); - (self.cat_downcast_if_needed(pat, cmt, variant_did), - self.tcx().adt_def(enum_did) - .variant_with_ctor_id(variant_ctor_did).fields.len()) - } - Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), _) - | Res::SelfCtor(..) => { - let ty = self.pat_ty_unadjusted(&pat)?; - match ty.kind { - ty::Adt(adt_def, _) => { - (cmt, adt_def.non_enum_variant().fields.len()) - } - _ => { - span_bug!(pat.span, - "tuple struct pattern unexpected type {:?}", ty); - } - } - } - def => { - debug!( - "tuple struct pattern didn't resolve to variant or struct {:?} at {:?}", - def, - pat.span, - ); - self.tcx().sess.delay_span_bug(pat.span, &format!( - "tuple struct pattern didn't resolve to variant or struct {:?}", - def, - )); - return Err(()); - } - }; - - for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) { - let subpat_ty = self.pat_ty_adjusted(&subpat)?; // see (*2) - let interior = InteriorField(FieldIndex(i, sym::integer(i))); - let subcmt = Rc::new( - self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior)); - self.cat_pattern_(subcmt, &subpat, op)?; + PatKind::TupleStruct(_, ref subpats, _) + | PatKind::Tuple(ref subpats, _) => { + // S(p1, ..., pN) or (p1, ..., pN) + for subpat in subpats.iter() { + let subpat_ty = self.pat_ty_adjusted(&subpat)?; + let sub_place = self.cat_projection(pat, place.clone(), subpat_ty); + self.cat_pattern_(sub_place, &subpat, op)?; } } - PatKind::Struct(ref qpath, ref field_pats, _) => { - // {f1: p1, ..., fN: pN} - let res = self.tables.qpath_res(qpath, pat.hir_id); - let cmt = match res { - Res::Err => { - debug!("access to unresolvable pattern {:?}", pat); - return Err(()) - } - Res::Def(DefKind::Ctor(CtorOf::Variant, _), variant_ctor_did) => { - let variant_did = self.tcx().parent(variant_ctor_did).unwrap(); - self.cat_downcast_if_needed(pat, cmt, variant_did) - } - Res::Def(DefKind::Variant, variant_did) => { - self.cat_downcast_if_needed(pat, cmt, variant_did) - } - _ => cmt, - }; - + PatKind::Struct(_, ref field_pats, _) => { + // S { f1: p1, ..., fN: pN } for fp in field_pats { - let field_ty = self.pat_ty_adjusted(&fp.pat)?; // see (*2) - let f_index = self.tcx().field_index(fp.hir_id, self.tables); - let cmt_field = Rc::new(self.cat_field(pat, cmt.clone(), f_index, - fp.ident, field_ty)); + let field_ty = self.pat_ty_adjusted(&fp.pat)?; + let cmt_field = self.cat_projection(pat, place.clone(), field_ty); self.cat_pattern_(cmt_field, &fp.pat, op)?; } } PatKind::Or(ref pats) => { for pat in pats { - self.cat_pattern_(cmt.clone(), &pat, op)?; + self.cat_pattern_(place.clone(), &pat, op)?; } } PatKind::Binding(.., Some(ref subpat)) => { - self.cat_pattern_(cmt, &subpat, op)?; - } - - PatKind::Tuple(ref subpats, ddpos) => { - // (p1, ..., pN) - let ty = self.pat_ty_unadjusted(&pat)?; - let expected_len = match ty.kind { - ty::Tuple(ref tys) => tys.len(), - _ => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty), - }; - for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) { - let subpat_ty = self.pat_ty_adjusted(&subpat)?; // see (*2) - let interior = InteriorField(FieldIndex(i, sym::integer(i))); - let subcmt = Rc::new( - self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior)); - self.cat_pattern_(subcmt, &subpat, op)?; - } + self.cat_pattern_(place, &subpat, op)?; } PatKind::Box(ref subpat) | PatKind::Ref(ref subpat, _) => { // box p1, &p1, &mut p1. we can ignore the mutability of // PatKind::Ref since that information is already contained // in the type. - let subcmt = Rc::new(self.cat_deref(pat, cmt, NoteNone)?); - self.cat_pattern_(subcmt, &subpat, op)?; + let subplace = self.cat_deref(pat, place)?; + self.cat_pattern_(subplace, &subpat, op)?; } PatKind::Slice(ref before, ref slice, ref after) => { - let element_ty = match cmt.ty.builtin_index() { + let element_ty = match place.ty.builtin_index() { Some(ty) => ty, None => { - debug!("explicit index of non-indexable type {:?}", cmt); + debug!("explicit index of non-indexable type {:?}", place); return Err(()); } }; - let context = InteriorOffsetKind::Pattern; - let elt_cmt = Rc::new(self.cat_index(pat, cmt, element_ty, context)?); + let elt_place = self.cat_projection(pat, place.clone(), element_ty); for before_pat in before { - self.cat_pattern_(elt_cmt.clone(), &before_pat, op)?; + self.cat_pattern_(elt_place.clone(), &before_pat, op)?; } if let Some(ref slice_pat) = *slice { - self.cat_pattern_(elt_cmt.clone(), &slice_pat, op)?; + let slice_pat_ty = self.pat_ty_adjusted(&slice_pat)?; + let slice_place = self.cat_projection(pat, place, slice_pat_ty); + self.cat_pattern_(slice_place, &slice_pat, op)?; } for after_pat in after { - self.cat_pattern_(elt_cmt.clone(), &after_pat, op)?; + self.cat_pattern_(elt_place.clone(), &after_pat, op)?; } } @@ -1259,197 +705,3 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { Ok(()) } } - -#[derive(Clone, Debug)] -pub enum Aliasability { - FreelyAliasable(AliasableReason), - NonAliasable, - ImmutableUnique(Box), -} - -#[derive(Copy, Clone, Debug)] -pub enum AliasableReason { - AliasableBorrowed, - AliasableStatic, - AliasableStaticMut, -} - -impl<'tcx> Place<'tcx> { - pub fn guarantor(&self) -> Place<'tcx> { - //! Returns `self` after stripping away any derefs or - //! interior content. The return value is basically the `cmt` which - //! determines how long the value in `self` remains live. - - match self.cat { - Categorization::Rvalue | - Categorization::StaticItem | - Categorization::ThreadLocal | - Categorization::Local(..) | - Categorization::Deref(_, UnsafePtr(..)) | - Categorization::Deref(_, BorrowedPtr(..)) | - Categorization::Upvar(..) => { - (*self).clone() - } - Categorization::Downcast(ref b, _) | - Categorization::Interior(ref b, _) | - Categorization::Deref(ref b, Unique) => { - b.guarantor() - } - } - } - - /// Returns `FreelyAliasable(_)` if this place represents a freely aliasable pointer type. - pub fn freely_aliasable(&self) -> Aliasability { - // Maybe non-obvious: copied upvars can only be considered - // non-aliasable in once closures, since any other kind can be - // aliased and eventually recused. - - match self.cat { - Categorization::Deref(ref b, BorrowedPtr(ty::MutBorrow, _)) | - Categorization::Deref(ref b, BorrowedPtr(ty::UniqueImmBorrow, _)) | - Categorization::Deref(ref b, Unique) | - Categorization::Downcast(ref b, _) | - Categorization::Interior(ref b, _) => { - // Aliasability depends on base cmt - b.freely_aliasable() - } - - Categorization::Rvalue | - Categorization::ThreadLocal | - Categorization::Local(..) | - Categorization::Upvar(..) | - Categorization::Deref(_, UnsafePtr(..)) => { // yes, it's aliasable, but... - NonAliasable - } - - Categorization::StaticItem => { - if self.mutbl.is_mutable() { - FreelyAliasable(AliasableStaticMut) - } else { - FreelyAliasable(AliasableStatic) - } - } - - Categorization::Deref(_, BorrowedPtr(ty::ImmBorrow, _)) => { - FreelyAliasable(AliasableBorrowed) - } - } - } - - // Digs down through one or two layers of deref and grabs the - // Categorization of the cmt for the upvar if a note indicates there is - // one. - pub fn upvar_cat(&self) -> Option<&Categorization<'tcx>> { - match self.note { - NoteClosureEnv(..) | NoteUpvarRef(..) => { - Some(match self.cat { - Categorization::Deref(ref inner, _) => { - match inner.cat { - Categorization::Deref(ref inner, _) => &inner.cat, - Categorization::Upvar(..) => &inner.cat, - _ => bug!() - } - } - _ => bug!() - }) - } - NoteIndex | NoteNone => None - } - } - - pub fn descriptive_string(&self, tcx: TyCtxt<'_>) -> Cow<'static, str> { - match self.cat { - Categorization::StaticItem => { - "static item".into() - } - Categorization::ThreadLocal => { - "thread-local static item".into() - } - Categorization::Rvalue => { - "non-place".into() - } - Categorization::Local(vid) => { - if tcx.hir().is_argument(vid) { - "argument" - } else { - "local variable" - }.into() - } - Categorization::Deref(_, pk) => { - match self.upvar_cat() { - Some(&Categorization::Upvar(ref var)) => { - var.to_string().into() - } - Some(_) => bug!(), - None => { - match pk { - Unique => { - "`Box` content" - } - UnsafePtr(..) => { - "dereference of raw pointer" - } - BorrowedPtr(..) => { - match self.note { - NoteIndex => "indexed content", - _ => "borrowed content" - } - } - }.into() - } - } - } - Categorization::Interior(_, InteriorField(..)) => { - "field".into() - } - Categorization::Interior(_, InteriorElement(InteriorOffsetKind::Index)) => { - "indexed content".into() - } - Categorization::Interior(_, InteriorElement(InteriorOffsetKind::Pattern)) => { - "pattern-bound indexed content".into() - } - Categorization::Upvar(ref var) => { - var.to_string().into() - } - Categorization::Downcast(ref cmt, _) => { - cmt.descriptive_string(tcx).into() - } - } - } -} - -pub fn ptr_sigil(ptr: PointerKind<'_>) -> &'static str { - match ptr { - Unique => "Box", - BorrowedPtr(ty::ImmBorrow, _) => "&", - BorrowedPtr(ty::MutBorrow, _) => "&mut", - BorrowedPtr(ty::UniqueImmBorrow, _) => "&unique", - UnsafePtr(_) => "*", - } -} - -impl fmt::Debug for InteriorKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - InteriorField(FieldIndex(_, info)) => write!(f, "{}", info), - InteriorElement(..) => write!(f, "[]"), - } - } -} - -impl fmt::Debug for Upvar { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:?}/{:?}", self.id, self.kind) - } -} - -impl fmt::Display for Upvar { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let kind = match self.kind { - ty::ClosureKind::Fn => "Fn", - ty::ClosureKind::FnMut => "FnMut", - ty::ClosureKind::FnOnce => "FnOnce", - }; - write!(f, "captured outer variable in an `{}` closure", kind) - } -} diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index b1813f5046840..7666db3ecd0d1 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -75,7 +75,6 @@ use crate::check::dropck; use crate::check::FnCtxt; use crate::middle::mem_categorization as mc; -use crate::middle::mem_categorization::Categorization; use crate::middle::region; use rustc::hir::def_id::DefId; use rustc::infer::outlives::env::OutlivesEnvironment; @@ -88,7 +87,6 @@ use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::hir::{self, PatKind}; use std::mem; use std::ops::Deref; -use std::rc::Rc; use syntax_pos::Span; // a variation on try that just returns unit @@ -898,10 +896,6 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { } cmt = self.with_mc(|mc| mc.cat_expr_adjusted(expr, cmt, &adjustment))?; - - if let Categorization::Deref(_, mc::BorrowedPtr(_, r_ptr)) = cmt.cat { - self.mk_subregion_due_to_dereference(expr.span, expr_region, r_ptr); - } } Ok(cmt) @@ -920,16 +914,22 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { ) } - fn check_safety_of_rvalue_destructor_if_necessary(&mut self, cmt: &mc::Place<'tcx>, span: Span) { - if let Categorization::Rvalue = cmt.cat { - let typ = self.resolve_type(cmt.ty); - let body_id = self.body_id; - let _ = dropck::check_drop_obligations( - self, - typ, - span, - body_id, - ); + fn check_safety_of_rvalue_destructor_if_necessary( + &mut self, + place: &mc::Place<'tcx>, + span: Span, + ) { + if let mc::PlaceBase::Rvalue = place.base { + if place.projections.is_empty() { + let typ = self.resolve_type(place.ty); + let body_id = self.body_id; + let _ = dropck::check_drop_obligations( + self, + typ, + span, + body_id, + ); + } } } @@ -1034,7 +1034,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { } Some(ref expr) => &**expr, }; - let discr_cmt = Rc::new(ignore_err!(self.with_mc(|mc| mc.cat_expr(init_expr)))); + let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(init_expr))); self.link_pattern(discr_cmt, &local.pat); } @@ -1043,7 +1043,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { /// linked to the lifetime of its guarantor (if any). fn link_match(&self, discr: &hir::Expr, arms: &[hir::Arm]) { debug!("regionck::for_match()"); - let discr_cmt = Rc::new(ignore_err!(self.with_mc(|mc| mc.cat_expr(discr)))); + let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(discr))); debug!("discr_cmt={:?}", discr_cmt); for arm in arms { self.link_pattern(discr_cmt.clone(), &arm.pat); @@ -1057,7 +1057,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { for param in params { let param_ty = self.node_ty(param.hir_id); let param_cmt = self.with_mc(|mc| { - Rc::new(mc.cat_rvalue(param.hir_id, param.pat.span, param_ty)) + mc.cat_rvalue(param.hir_id, param.pat.span, param_ty) }); debug!("param_ty={:?} param_cmt={:?} param={:?}", param_ty, param_cmt, param); self.link_pattern(param_cmt, ¶m.pat); @@ -1066,7 +1066,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { /// Link lifetimes of any ref bindings in `root_pat` to the pointers found /// in the discriminant, if needed. - fn link_pattern(&self, discr_cmt: mc::cmt<'tcx>, root_pat: &hir::Pat) { + fn link_pattern(&self, discr_cmt: mc::Place<'tcx>, root_pat: &hir::Pat) { debug!( "link_pattern(discr_cmt={:?}, root_pat={:?})", discr_cmt, root_pat @@ -1152,61 +1152,35 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { span: Span, borrow_region: ty::Region<'tcx>, borrow_kind: ty::BorrowKind, - borrow_cmt: &mc::Place<'tcx>, + borrow_place: &mc::Place<'tcx>, ) { - let origin = infer::DataBorrowed(borrow_cmt.ty, span); - self.type_must_outlive(origin, borrow_cmt.ty, borrow_region); - - let mut borrow_kind = borrow_kind; - let mut borrow_cmt_cat = borrow_cmt.cat.clone(); + let origin = infer::DataBorrowed(borrow_place.ty, span); + self.type_must_outlive(origin, borrow_place.ty, borrow_region); - loop { + for pointer_ty in borrow_place.deref_tys() { debug!( - "link_region(borrow_region={:?}, borrow_kind={:?}, borrow_cmt={:?})", - borrow_region, borrow_kind, borrow_cmt + "link_region(borrow_region={:?}, borrow_kind={:?}, pointer_ty={:?})", + borrow_region, borrow_kind, borrow_place ); - match borrow_cmt_cat { - Categorization::Deref(ref_cmt, mc::BorrowedPtr(ref_kind, ref_region)) => { - match self.link_reborrowed_region( + match pointer_ty.kind { + ty::RawPtr(_) => return, + ty::Ref(ref_region, _, ref_mutability) => { + if self.link_reborrowed_region( span, borrow_region, - borrow_kind, - ref_cmt, ref_region, - ref_kind, - borrow_cmt.note, + ref_mutability, ) { - Some((c, k)) => { - borrow_cmt_cat = c.cat.clone(); - borrow_kind = k; - } - None => { - return; - } + return; } - } - Categorization::Downcast(cmt_base, _) - | Categorization::Deref(cmt_base, mc::Unique) - | Categorization::Interior(cmt_base, _) => { - // Borrowing interior or owned data requires the base - // to be valid and borrowable in the same fashion. - borrow_cmt_cat = cmt_base.cat.clone(); - borrow_kind = borrow_kind; - } - - Categorization::Deref(_, mc::UnsafePtr(..)) - | Categorization::StaticItem - | Categorization::Upvar(..) - | Categorization::Local(..) - | Categorization::ThreadLocal - | Categorization::Rvalue => { - // These are all "base cases" with independent lifetimes - // that are not subject to inference - return; } + _ => assert!(pointer_ty.is_box(), "unexpected built-in deref type {}", pointer_ty) } } + if let mc::PlaceBase::Upvar(upvar_id) = borrow_place.base { + self.link_upvar_region(span, borrow_region, upvar_id); + } } /// This is the most complicated case: the path being borrowed is @@ -1230,83 +1204,28 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { /// /// Here `bk` stands for some borrow-kind (e.g., `mut`, `uniq`, etc). /// - /// Unfortunately, there are some complications beyond the simple - /// scenario I just painted: + /// There is a complication beyond the simple scenario I just painted: there + /// may in fact be more levels of reborrowing. In the example, I said the + /// borrow was like `&'z *r`, but it might in fact be a borrow like + /// `&'z **q` where `q` has type `&'a &'b mut T`. In that case, we want to + /// ensure that `'z <= 'a` and `'z <= 'b`. /// - /// 1. The reference `r` might in fact be a "by-ref" upvar. In that - /// case, we have two jobs. First, we are inferring whether this reference - /// should be an `&T`, `&mut T`, or `&uniq T` reference, and we must - /// adjust that based on this borrow (e.g., if this is an `&mut` borrow, - /// then `r` must be an `&mut` reference). Second, whenever we link - /// two regions (here, `'z <= 'a`), we supply a *cause*, and in this - /// case we adjust the cause to indicate that the reference being - /// "reborrowed" is itself an upvar. This provides a nicer error message - /// should something go wrong. + /// The return value of this function indicates whether we *don't* need to + /// the recurse to the next reference up. /// - /// 2. There may in fact be more levels of reborrowing. In the - /// example, I said the borrow was like `&'z *r`, but it might - /// in fact be a borrow like `&'z **q` where `q` has type `&'a - /// &'b mut T`. In that case, we want to ensure that `'z <= 'a` - /// and `'z <= 'b`. This is explained more below. - /// - /// The return value of this function indicates whether we need to - /// recurse and process `ref_cmt` (see case 2 above). + /// This is explained more below. fn link_reborrowed_region( &self, span: Span, borrow_region: ty::Region<'tcx>, - borrow_kind: ty::BorrowKind, - ref_cmt: mc::cmt<'tcx>, ref_region: ty::Region<'tcx>, - mut ref_kind: ty::BorrowKind, - note: mc::Note, - ) -> Option<(mc::cmt<'tcx>, ty::BorrowKind)> { - // Possible upvar ID we may need later to create an entry in the - // maybe link map. - - // Detect by-ref upvar `x`: - let cause = match note { - mc::NoteUpvarRef(ref upvar_id) => { - match self.tables.borrow().upvar_capture_map.get(upvar_id) { - Some(&ty::UpvarCapture::ByRef(ref upvar_borrow)) => { - // The mutability of the upvar may have been modified - // by the above adjustment, so update our local variable. - ref_kind = upvar_borrow.kind; - - infer::ReborrowUpvar(span, *upvar_id) - } - _ => { - span_bug!(span, "Illegal upvar id: {:?}", upvar_id); - } - } - } - mc::NoteClosureEnv(ref upvar_id) => { - // We don't have any mutability changes to propagate, but - // we do want to note that an upvar reborrow caused this - // link - infer::ReborrowUpvar(span, *upvar_id) - } - _ => infer::Reborrow(span), - }; - + ref_mutability: hir::Mutability, + ) -> bool { debug!( "link_reborrowed_region: {:?} <= {:?}", borrow_region, ref_region ); - self.sub_regions(cause, borrow_region, ref_region); - - // If we end up needing to recurse and establish a region link - // with `ref_cmt`, calculate what borrow kind we will end up - // needing. This will be used below. - // - // One interesting twist is that we can weaken the borrow kind - // when we recurse: to reborrow an `&mut` referent as mutable, - // borrowck requires a unique path to the `&mut` reference but not - // necessarily a *mutable* path. - let new_borrow_kind = match borrow_kind { - ty::ImmBorrow => ty::ImmBorrow, - ty::MutBorrow | ty::UniqueImmBorrow => ty::UniqueImmBorrow, - }; + self.sub_regions(infer::Reborrow(span), borrow_region, ref_region); // Decide whether we need to recurse and link any regions within // the `ref_cmt`. This is concerned for the case where the value @@ -1335,24 +1254,83 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { // (Note that since we have not examined `ref_cmt.cat`, we don't // know whether this scenario has occurred; but I wanted to show // how all the types get adjusted.) - match ref_kind { - ty::ImmBorrow => { + match ref_mutability { + hir::Mutability::Immutable => { // The reference being reborrowed is a shareable ref of // type `&'a T`. In this case, it doesn't matter where we // *found* the `&T` pointer, the memory it references will // be valid and immutable for `'a`. So we can stop here. - // - // (Note that the `borrow_kind` must also be ImmBorrow or - // else the user is borrowed imm memory as mut memory, - // which means they'll get an error downstream in borrowck - // anyhow.) - return None; + true } - ty::MutBorrow | ty::UniqueImmBorrow => { - // The reference being reborrowed is either an `&mut T` or - // `&uniq T`. This is the case where recursion is needed. - return Some((ref_cmt, new_borrow_kind)); + hir::Mutability::Mutable => { + // The reference being reborrowed is either an `&mut T`. This is + // the case where recursion is needed. + false + } + } + } + + /// An upvar may be behind up to 2 references: + /// + /// * One can come from the reference to a "by-reference" upvar. + /// * Another one can come from the reference to the closure itself if it's + /// a `FnMut` or `Fn` closure. + /// + /// This function links the lifetimes of those references to the lifetime + /// of the borrow that's provided. See [link_reborrowed_region] for some + /// more explanation of this in the general case. + /// + /// We also supply a *cause*, and in this case we set the cause to + /// indicate that the reference being "reborrowed" is itself an upvar. This + /// provides a nicer error message should something go wrong. + fn link_upvar_region( + &self, + span: Span, + borrow_region: ty::Region<'tcx>, + upvar_id: ty::UpvarId, + ) { + debug!("link_upvar_region(borrorw_region={:?}, upvar_id={:?}", borrow_region, upvar_id); + // A by-reference upvar can't be borrowed for longer than the + // upvar is borrowed from the environment. + match self.tables.borrow().upvar_capture(upvar_id) { + ty::UpvarCapture::ByRef(upvar_borrow) => { + self.sub_regions( + infer::ReborrowUpvar(span, upvar_id), + borrow_region, + upvar_borrow.region, + ); + if let ty::ImmBorrow = upvar_borrow.kind { + debug!("link_upvar_region: capture by shared ref"); + return; + } + } + ty::UpvarCapture::ByValue => {} + } + let fn_hir_id = self.tcx.hir().local_def_id_to_hir_id(upvar_id.closure_expr_id); + let ty = self.resolve_node_type(fn_hir_id); + debug!("link_upvar_region: ty={:?}", ty); + + // A closure capture can't be borrowed for longer than the + // reference to the closure. + if let ty::Closure(closure_def_id, substs) = ty.kind { + match self.infcx.closure_kind(closure_def_id, substs) { + Some(ty::ClosureKind::Fn) | Some(ty::ClosureKind::FnMut) => { + // Region of environment pointer + let env_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion { + scope: upvar_id.closure_expr_id.to_def_id(), + bound_region: ty::BrEnv + })); + self.sub_regions( + infer::ReborrowUpvar(span, upvar_id), + borrow_region, + env_region, + ); + } + Some(ty::ClosureKind::FnOnce) => {} + None => { + span_bug!(span, "Have not inferred closure kind before regionck"); + } } } } diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 185902142c748..d58a513dcde62 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -34,7 +34,7 @@ use super::FnCtxt; use crate::middle::expr_use_visitor as euv; use crate::middle::mem_categorization as mc; -use crate::middle::mem_categorization::Categorization; +use crate::middle::mem_categorization::PlaceBase; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::hir::def_id::LocalDefId; @@ -76,6 +76,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> { } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { + /// Analysis starting point. fn analyze_closure( &self, closure_hir_id: hir::HirId, @@ -83,9 +84,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { body: &hir::Body, capture_clause: hir::CaptureBy, ) { - /*! - * Analysis starting point. - */ debug!( "analyze_closure(id={:?}, body.id={:?})", @@ -310,13 +308,10 @@ struct InferBorrowKind<'a, 'tcx> { impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { fn adjust_upvar_borrow_kind_for_consume( &mut self, - cmt: &mc::Place<'tcx>, + place: &mc::Place<'tcx>, mode: euv::ConsumeMode, ) { - debug!( - "adjust_upvar_borrow_kind_for_consume(cmt={:?}, mode={:?})", - cmt, mode - ); + debug!("adjust_upvar_borrow_kind_for_consume(place={:?}, mode={:?})", place, mode); // we only care about moves match mode { @@ -327,132 +322,68 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { } let tcx = self.fcx.tcx; + let upvar_id = if let PlaceBase::Upvar(upvar_id) = place.base { + upvar_id + } else { + return; + }; - // watch out for a move of the deref of a borrowed pointer; - // for that to be legal, the upvar would have to be borrowed - // by value instead - let guarantor = cmt.guarantor(); - debug!( - "adjust_upvar_borrow_kind_for_consume: guarantor={:?}", - guarantor - ); - debug!( - "adjust_upvar_borrow_kind_for_consume: guarantor.cat={:?}", - guarantor.cat - ); - if let Categorization::Deref(_, mc::BorrowedPtr(..)) = guarantor.cat { - debug!( - "adjust_upvar_borrow_kind_for_consume: found deref with note {:?}", - cmt.note - ); - match guarantor.note { - mc::NoteUpvarRef(upvar_id) => { - debug!( - "adjust_upvar_borrow_kind_for_consume: \ - setting upvar_id={:?} to by value", - upvar_id - ); + debug!("adjust_upvar_borrow_kind_for_consume: upvar={:?}", upvar_id); - // to move out of an upvar, this must be a FnOnce closure - self.adjust_closure_kind( - upvar_id.closure_expr_id, - ty::ClosureKind::FnOnce, - guarantor.span, - var_name(tcx, upvar_id.var_path.hir_id), - ); + // To move out of an upvar, this must be a FnOnce closure + self.adjust_closure_kind( + upvar_id.closure_expr_id, + ty::ClosureKind::FnOnce, + place.span, + var_name(tcx, upvar_id.var_path.hir_id), + ); - self.adjust_upvar_captures - .insert(upvar_id, ty::UpvarCapture::ByValue); - } - mc::NoteClosureEnv(upvar_id) => { - // we get just a closureenv ref if this is a - // `move` closure, or if the upvar has already - // been inferred to by-value. In any case, we - // must still adjust the kind of the closure - // to be a FnOnce closure to permit moves out - // of the environment. - self.adjust_closure_kind( - upvar_id.closure_expr_id, - ty::ClosureKind::FnOnce, - guarantor.span, - var_name(tcx, upvar_id.var_path.hir_id), - ); - } - mc::NoteIndex | mc::NoteNone => {} - } - } + self.adjust_upvar_captures.insert(upvar_id, ty::UpvarCapture::ByValue); } /// Indicates that `cmt` is being directly mutated (e.g., assigned - /// to). If cmt contains any by-ref upvars, this implies that - /// those upvars must be borrowed using an `&mut` borrow. - fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: &mc::Place<'tcx>) { - debug!("adjust_upvar_borrow_kind_for_mut(cmt={:?})", cmt); - - match cmt.cat.clone() { - Categorization::Deref(base, mc::Unique) - | Categorization::Interior(base, _) - | Categorization::Downcast(base, _) => { - // Interior or owned data is mutable if base is - // mutable, so iterate to the base. - self.adjust_upvar_borrow_kind_for_mut(&base); - } - - Categorization::Deref(base, mc::BorrowedPtr(..)) => { - if !self.try_adjust_upvar_deref(cmt, ty::MutBorrow) { + /// to). If the place is based on a by-ref upvar, this implies that + /// the upvar must be borrowed using an `&mut` borrow. + fn adjust_upvar_borrow_kind_for_mut(&mut self, place: &mc::Place<'tcx>) { + debug!("adjust_upvar_borrow_kind_for_mut(place={:?})", place); + + if let PlaceBase::Upvar(upvar_id) = place.base { + let mut borrow_kind = ty::MutBorrow; + for pointer_ty in place.deref_tys() { + match pointer_ty.kind { + // Raw pointers don't inherit mutability. + ty::RawPtr(_) => return, // assignment to deref of an `&mut` // borrowed pointer implies that the // pointer itself must be unique, but not // necessarily *mutable* - self.adjust_upvar_borrow_kind_for_unique(&base); + ty::Ref(.., hir::Mutability::Mutable) => borrow_kind = ty::UniqueImmBorrow, + _ => (), } } - - Categorization::Deref(_, mc::UnsafePtr(..)) - | Categorization::StaticItem - | Categorization::ThreadLocal - | Categorization::Rvalue - | Categorization::Local(_) - | Categorization::Upvar(..) => { - return; - } + self.adjust_upvar_deref(upvar_id, place.span, borrow_kind); } } - fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: &mc::Place<'tcx>) { - debug!("adjust_upvar_borrow_kind_for_unique(cmt={:?})", cmt); + fn adjust_upvar_borrow_kind_for_unique(&mut self, place: &mc::Place<'tcx>) { + debug!("adjust_upvar_borrow_kind_for_unique(place={:?})", place); - match cmt.cat.clone() { - Categorization::Deref(base, mc::Unique) - | Categorization::Interior(base, _) - | Categorization::Downcast(base, _) => { - // Interior or owned data is unique if base is - // unique. - self.adjust_upvar_borrow_kind_for_unique(&base); - } - - Categorization::Deref(base, mc::BorrowedPtr(..)) => { - if !self.try_adjust_upvar_deref(cmt, ty::UniqueImmBorrow) { - // for a borrowed pointer to be unique, its - // base must be unique - self.adjust_upvar_borrow_kind_for_unique(&base); - } + if let PlaceBase::Upvar(upvar_id) = place.base { + if place.deref_tys().any(ty::TyS::is_unsafe_ptr) { + // Raw pointers don't inherit mutability. + return; } - - Categorization::Deref(_, mc::UnsafePtr(..)) - | Categorization::StaticItem - | Categorization::ThreadLocal - | Categorization::Rvalue - | Categorization::Local(_) - | Categorization::Upvar(..) => {} + // for a borrowed pointer to be unique, its base must be unique + self.adjust_upvar_deref(upvar_id, place.span, ty::UniqueImmBorrow); } } - fn try_adjust_upvar_deref( + fn adjust_upvar_deref( &mut self, - cmt: &mc::Place<'tcx>, + upvar_id: ty::UpvarId, + place_span: Span, borrow_kind: ty::BorrowKind, - ) -> bool { + ) { assert!(match borrow_kind { ty::MutBorrow => true, ty::UniqueImmBorrow => true, @@ -463,39 +394,19 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { let tcx = self.fcx.tcx; - match cmt.note { - mc::NoteUpvarRef(upvar_id) => { - // if this is an implicit deref of an - // upvar, then we need to modify the - // borrow_kind of the upvar to make sure it - // is inferred to mutable if necessary - self.adjust_upvar_borrow_kind(upvar_id, borrow_kind); - - // also need to be in an FnMut closure since this is not an ImmBorrow - self.adjust_closure_kind( - upvar_id.closure_expr_id, - ty::ClosureKind::FnMut, - cmt.span, - var_name(tcx, upvar_id.var_path.hir_id), - ); - - true - } - mc::NoteClosureEnv(upvar_id) => { - // this kind of deref occurs in a `move` closure, or - // for a by-value upvar; in either case, to mutate an - // upvar, we need to be an FnMut closure - self.adjust_closure_kind( - upvar_id.closure_expr_id, - ty::ClosureKind::FnMut, - cmt.span, - var_name(tcx, upvar_id.var_path.hir_id), - ); - - true - } - mc::NoteIndex | mc::NoteNone => false, - } + // if this is an implicit deref of an + // upvar, then we need to modify the + // borrow_kind of the upvar to make sure it + // is inferred to mutable if necessary + self.adjust_upvar_borrow_kind(upvar_id, borrow_kind); + + // also need to be in an FnMut closure since this is not an ImmBorrow + self.adjust_closure_kind( + upvar_id.closure_expr_id, + ty::ClosureKind::FnMut, + place_span, + var_name(tcx, upvar_id.var_path.hir_id), + ); } /// We infer the borrow_kind with which to borrow upvars in a stack closure. @@ -507,7 +418,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { let upvar_capture = self .adjust_upvar_captures .get(&upvar_id) - .cloned() + .copied() .unwrap_or_else(|| self.fcx.tables.borrow().upvar_capture(upvar_id)); debug!( "adjust_upvar_borrow_kind(upvar_id={:?}, upvar_capture={:?}, kind={:?})", @@ -584,29 +495,29 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { } impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { - fn consume(&mut self, cmt: &mc::Place<'tcx>,mode: euv::ConsumeMode) { - debug!("consume(cmt={:?},mode={:?})", cmt, mode); - self.adjust_upvar_borrow_kind_for_consume(cmt, mode); + fn consume(&mut self, place: &mc::Place<'tcx>,mode: euv::ConsumeMode) { + debug!("consume(place={:?},mode={:?})", place, mode); + self.adjust_upvar_borrow_kind_for_consume(place, mode); } - fn borrow(&mut self, cmt: &mc::Place<'tcx>, bk: ty::BorrowKind) { - debug!("borrow(cmt={:?}, bk={:?})", cmt, bk); + fn borrow(&mut self, place: &mc::Place<'tcx>, bk: ty::BorrowKind) { + debug!("borrow(place={:?}, bk={:?})", place, bk); match bk { ty::ImmBorrow => {} ty::UniqueImmBorrow => { - self.adjust_upvar_borrow_kind_for_unique(cmt); + self.adjust_upvar_borrow_kind_for_unique(place); } ty::MutBorrow => { - self.adjust_upvar_borrow_kind_for_mut(cmt); + self.adjust_upvar_borrow_kind_for_mut(place); } } } - fn mutate(&mut self, assignee_cmt: &mc::Place<'tcx>) { - debug!("mutate(assignee_cmt={:?})", assignee_cmt); + fn mutate(&mut self, assignee_place: &mc::Place<'tcx>) { + debug!("mutate(assignee_place={:?})", assignee_place); - self.adjust_upvar_borrow_kind_for_mut(assignee_cmt); + self.adjust_upvar_borrow_kind_for_mut(assignee_place); } } diff --git a/src/test/ui/issues/issue-4335.rs b/src/test/ui/issues/issue-4335.rs index a10ae9a1243a2..c5914a17cf924 100644 --- a/src/test/ui/issues/issue-4335.rs +++ b/src/test/ui/issues/issue-4335.rs @@ -4,8 +4,7 @@ fn id(t: T) -> T { t } fn f<'r, T>(v: &'r T) -> Box T + 'r> { id(Box::new(|| *v)) - //~^ ERROR E0373 - //~| ERROR E0507 + //~^ ERROR E0507 } fn main() { diff --git a/src/test/ui/issues/issue-4335.stderr b/src/test/ui/issues/issue-4335.stderr index ca1c0b68d2a5f..f187969ff4e86 100644 --- a/src/test/ui/issues/issue-4335.stderr +++ b/src/test/ui/issues/issue-4335.stderr @@ -6,25 +6,6 @@ LL | fn f<'r, T>(v: &'r T) -> Box T + 'r> { LL | id(Box::new(|| *v)) | ^^ move occurs because `*v` has type `T`, which does not implement the `Copy` trait -error[E0373]: closure may outlive the current function, but it borrows `v`, which is owned by the current function - --> $DIR/issue-4335.rs:6:17 - | -LL | id(Box::new(|| *v)) - | ^^ - `v` is borrowed here - | | - | may outlive borrowed value `v` - | -note: closure is returned here - --> $DIR/issue-4335.rs:6:5 - | -LL | id(Box::new(|| *v)) - | ^^^^^^^^^^^^^^^^^^^ -help: to force the closure to take ownership of `v` (and any other referenced variables), use the `move` keyword - | -LL | id(Box::new(move || *v)) - | ^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0373, E0507. -For more information about an error, try `rustc --explain E0373`. +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/regions/regions-addr-of-upvar-self.stderr b/src/test/ui/regions/regions-addr-of-upvar-self.stderr index 7a051b8ac835d..005800d50a457 100644 --- a/src/test/ui/regions/regions-addr-of-upvar-self.stderr +++ b/src/test/ui/regions/regions-addr-of-upvar-self.stderr @@ -9,7 +9,7 @@ note: first, the lifetime cannot outlive the lifetime `'_` as defined on the bod | LL | let _f = || { | ^^ -note: ...so that reference does not outlive borrowed content +note: ...so that closure can access `self` --> $DIR/regions-addr-of-upvar-self.rs:10:41 | LL | let p: &'static mut usize = &mut self.food; diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr index 9287353245e98..68ec8d2ba8287 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr @@ -2,7 +2,7 @@ error[E0525]: expected a closure that implements the `Fn` trait, but this closur --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:14:13 | LL | let c = || drop(y.0); - | ^^^^^^^^-^^^ + | ^^^^^^^^---^ | | | | | closure is `FnOnce` because it moves the variable `y` out of its environment | this closure implements `FnOnce`, not `Fn` From c87de41f99f0523490e826222edb21d6cc361415 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 9 Nov 2019 10:21:33 +0000 Subject: [PATCH 4/5] Remove remaining uses of "cmt" --- src/librustc/middle/expr_use_visitor.rs | 78 ++++++++++++----------- src/librustc/middle/mem_categorization.rs | 20 +++--- src/librustc_typeck/check/upvar.rs | 2 +- 3 files changed, 51 insertions(+), 49 deletions(-) diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 201ae6597f4dd..5ad381ef6b272 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -21,15 +21,15 @@ use syntax_pos::Span; /// This trait defines the callbacks you can expect to receive when /// employing the ExprUseVisitor. pub trait Delegate<'tcx> { - // The value found at `cmt` is either copied or moved, depending + // The value found at `place` is either copied or moved, depending // on mode. - fn consume(&mut self, cmt: &mc::Place<'tcx>, mode: ConsumeMode); + fn consume(&mut self, place: &mc::Place<'tcx>, mode: ConsumeMode); - // The value found at `cmt` is being borrowed with kind `bk`. - fn borrow(&mut self, cmt: &mc::Place<'tcx>, bk: ty::BorrowKind); + // The value found at `place` is being borrowed with kind `bk`. + fn borrow(&mut self, place: &mc::Place<'tcx>, bk: ty::BorrowKind); - // The path at `cmt` is being assigned to. - fn mutate(&mut self, assignee_cmt: &mc::Place<'tcx>); + // The path at `place` is being assigned to. + fn mutate(&mut self, assignee_place: &mc::Place<'tcx>); } #[derive(Copy, Clone, PartialEq, Debug)] @@ -163,22 +163,22 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { pub fn consume_expr(&mut self, expr: &hir::Expr) { debug!("consume_expr(expr={:?})", expr); - let cmt = return_if_err!(self.mc.cat_expr(expr)); - self.delegate_consume(&cmt); + let place = return_if_err!(self.mc.cat_expr(expr)); + self.delegate_consume(&place); self.walk_expr(expr); } fn mutate_expr(&mut self, expr: &hir::Expr) { - let cmt = return_if_err!(self.mc.cat_expr(expr)); - self.delegate.mutate(&cmt); + let place = return_if_err!(self.mc.cat_expr(expr)); + self.delegate.mutate(&place); self.walk_expr(expr); } fn borrow_expr(&mut self, expr: &hir::Expr, bk: ty::BorrowKind) { debug!("borrow_expr(expr={:?}, bk={:?})", expr, bk); - let cmt = return_if_err!(self.mc.cat_expr(expr)); - self.delegate.borrow(&cmt, bk); + let place = return_if_err!(self.mc.cat_expr(expr)); + self.delegate.borrow(&place, bk); self.walk_expr(expr) } @@ -230,12 +230,12 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } hir::ExprKind::Match(ref discr, ref arms, _) => { - let discr_cmt = return_if_err!(self.mc.cat_expr(&discr)); + let discr_place = return_if_err!(self.mc.cat_expr(&discr)); self.borrow_expr(&discr, ty::ImmBorrow); // treatment of the discriminant is handled while walking the arms. for arm in arms { - self.walk_arm(&discr_cmt, arm); + self.walk_arm(&discr_place, arm); } } @@ -381,8 +381,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // "assigns", which is handled by // `walk_pat`: self.walk_expr(&expr); - let init_cmt = return_if_err!(self.mc.cat_expr(&expr)); - self.walk_irrefutable_pat(&init_cmt, &local.pat); + let init_place = return_if_err!(self.mc.cat_expr(&expr)); + self.walk_irrefutable_pat(&init_place, &local.pat); } } @@ -457,7 +457,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // process. fn walk_adjustment(&mut self, expr: &hir::Expr) { let adjustments = self.mc.tables.expr_adjustments(expr); - let mut cmt = return_if_err!(self.mc.cat_expr_unadjusted(expr)); + let mut place = return_if_err!(self.mc.cat_expr_unadjusted(expr)); for adjustment in adjustments { debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment); match adjustment.kind { @@ -465,7 +465,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { adjustment::Adjust::Pointer(_) => { // Creating a closure/fn-pointer or unsizing consumes // the input and stores it into the resulting rvalue. - self.delegate_consume(&cmt); + self.delegate_consume(&place); } adjustment::Adjust::Deref(None) => {} @@ -477,41 +477,41 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // this is an autoref of `x`. adjustment::Adjust::Deref(Some(ref deref)) => { let bk = ty::BorrowKind::from_mutbl(deref.mutbl); - self.delegate.borrow(&cmt, bk); + self.delegate.borrow(&place, bk); } adjustment::Adjust::Borrow(ref autoref) => { - self.walk_autoref(expr, &cmt, autoref); + self.walk_autoref(expr, &place, autoref); } } - cmt = return_if_err!(self.mc.cat_expr_adjusted(expr, cmt, &adjustment)); + place = return_if_err!(self.mc.cat_expr_adjusted(expr, place, &adjustment)); } } /// Walks the autoref `autoref` applied to the autoderef'd - /// `expr`. `cmt_base` is the mem-categorized form of `expr` + /// `expr`. `base_place` is the mem-categorized form of `expr` /// after all relevant autoderefs have occurred. fn walk_autoref(&mut self, expr: &hir::Expr, - cmt_base: &mc::Place<'tcx>, + base_place: &mc::Place<'tcx>, autoref: &adjustment::AutoBorrow<'tcx>) { - debug!("walk_autoref(expr.hir_id={} cmt_base={:?} autoref={:?})", + debug!("walk_autoref(expr.hir_id={} base_place={:?} autoref={:?})", expr.hir_id, - cmt_base, + base_place, autoref); match *autoref { adjustment::AutoBorrow::Ref(_, m) => { - self.delegate.borrow(cmt_base, ty::BorrowKind::from_mutbl(m.into())); + self.delegate.borrow(base_place, ty::BorrowKind::from_mutbl(m.into())); } adjustment::AutoBorrow::RawPtr(m) => { - debug!("walk_autoref: expr.hir_id={} cmt_base={:?}", + debug!("walk_autoref: expr.hir_id={} base_place={:?}", expr.hir_id, - cmt_base); + base_place); - self.delegate.borrow(cmt_base, ty::BorrowKind::from_mutbl(m)); + self.delegate.borrow(base_place, ty::BorrowKind::from_mutbl(m)); } } } @@ -556,8 +556,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // Each match binding is effectively an assignment to the // binding being produced. let def = Res::Local(canonical_id); - if let Ok(ref binding_cmt) = mc.cat_res(pat.hir_id, pat.span, pat_ty, def) { - delegate.mutate(binding_cmt); + if let Ok(ref binding_place) = mc.cat_res(pat.hir_id, pat.span, pat_ty, def) { + delegate.mutate(binding_place); } // It is also a borrow or copy/move of the value being matched. @@ -590,16 +590,18 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { closure_expr_id: closure_def_id.to_local(), }; let upvar_capture = self.mc.tables.upvar_capture(upvar_id); - let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.hir_id, - fn_decl_span, - var_id)); + let captured_place = return_if_err!(self.cat_captured_var( + closure_expr.hir_id, + fn_decl_span, + var_id, + )); match upvar_capture { ty::UpvarCapture::ByValue => { - let mode = copy_or_move(&self.mc, &cmt_var); - self.delegate.consume(&cmt_var, mode); + let mode = copy_or_move(&self.mc, &captured_place); + self.delegate.consume(&captured_place, mode); } ty::UpvarCapture::ByRef(upvar_borrow) => { - self.delegate.borrow(&cmt_var, upvar_borrow.kind); + self.delegate.borrow(&captured_place, upvar_borrow.kind); } } } @@ -611,7 +613,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { closure_span: Span, var_id: hir::HirId) -> mc::McResult> { - // Create the cmt for the variable being borrowed, from the + // Create the place for the variable being borrowed, from the // perspective of the creator (parent) of the closure. 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 50a70ebc515ca..9b0a12234a7ef 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -529,8 +529,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { mutbl, }); - let base_cmt = self.cat_rvalue(expr.hir_id, expr.span, ref_ty); - self.cat_deref(expr, base_cmt) + let base = self.cat_rvalue(expr.hir_id, expr.span, ref_ty); + self.cat_deref(expr, base) } fn cat_deref( @@ -538,7 +538,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { node: &impl HirNode, base_place: Place<'tcx>, ) -> McResult> { - debug!("cat_deref: base_cmt={:?}", base_place); + debug!("cat_deref: base_place={:?}", base_place); let base_ty = base_place.ty; let deref_ty = match base_ty.builtin_deref(true) { @@ -598,7 +598,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // `&&Some(x,)` `place_foo` // `&Some(x,)` `deref { place_foo}` // `Some(x,)` `deref { deref { place_foo }}` - // (x,)` `field0 { deref { deref { place_foo }}}` <- resulting cmt + // (x,)` `field0 { deref { deref { place_foo }}}` <- resulting place // // The above example has no adjustments. If the code were instead the (after adjustments, // equivalent) version @@ -625,14 +625,14 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { let place = place; // lose mutability debug!("cat_pattern: applied adjustment derefs to get place={:?}", place); - // Invoke the callback, but only now, after the `cmt` has adjusted. + // Invoke the callback, but only now, after the `place` has adjusted. // // To see that this makes sense, consider `match &Some(3) { Some(x) => { ... }}`. In that - // case, the initial `cmt` will be that for `&Some(3)` and the pattern is `Some(x)`. We + // case, the initial `place` will be that for `&Some(3)` and the pattern is `Some(x)`. We // don't want to call `op` with these incompatible values. As written, what happens instead - // is that `op` is called with the adjusted cmt (that for `*&Some(3)`) and the pattern + // is that `op` is called with the adjusted place (that for `*&Some(3)`) and the pattern // `Some(x)` (which matches). Recursing once more, `*&Some(3)` and the pattern `Some(x)` - // result in the cmt `Downcast(*&Some(3)).0` associated to `x` and invoke `op` with + // result in the place `Downcast(*&Some(3)).0` associated to `x` and invoke `op` with // that (where the `ref` on `x` is implied). op(&place, pat); @@ -651,8 +651,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // S { f1: p1, ..., fN: pN } for fp in field_pats { let field_ty = self.pat_ty_adjusted(&fp.pat)?; - let cmt_field = self.cat_projection(pat, place.clone(), field_ty); - self.cat_pattern_(cmt_field, &fp.pat, op)?; + let field_place = self.cat_projection(pat, place.clone(), field_ty); + self.cat_pattern_(field_place, &fp.pat, op)?; } } diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index d58a513dcde62..daaa21202ac21 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -341,7 +341,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { self.adjust_upvar_captures.insert(upvar_id, ty::UpvarCapture::ByValue); } - /// Indicates that `cmt` is being directly mutated (e.g., assigned + /// Indicates that `place` is being directly mutated (e.g., assigned /// to). If the place is based on a by-ref upvar, this implies that /// the upvar must be borrowed using an `&mut` borrow. fn adjust_upvar_borrow_kind_for_mut(&mut self, place: &mc::Place<'tcx>) { From 5bc15866d752d4ba4a02e9ab130b08cb8186d8f9 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 9 Nov 2019 10:38:06 +0000 Subject: [PATCH 5/5] Move ExprUseVisitor and mem_categorization to rustc_typeck `MemCategorizationContext` is now private, the remaining types and traits remain public for Clippy. --- src/librustc/lib.rs | 2 - src/librustc_typeck/check/regionck.rs | 2 +- src/librustc_typeck/check/upvar.rs | 6 +-- .../expr_use_visitor.rs | 29 ++++++++------ src/librustc_typeck/lib.rs | 4 ++ .../mem_categorization.rs | 40 +++++++++---------- 6 files changed, 44 insertions(+), 39 deletions(-) rename src/{librustc/middle => librustc_typeck}/expr_use_visitor.rs (97%) rename src/{librustc/middle => librustc_typeck}/mem_categorization.rs (96%) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 1fc157eca3e89..481ae3b93291e 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -96,7 +96,6 @@ pub mod infer; pub mod lint; pub mod middle { - pub mod expr_use_visitor; pub mod cstore; pub mod dependency_format; pub mod diagnostic_items; @@ -104,7 +103,6 @@ pub mod middle { pub mod free_region; pub mod lib_features; pub mod lang_items; - pub mod mem_categorization; pub mod privacy; pub mod reachable; pub mod region; diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 7666db3ecd0d1..8ceb21748520e 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -74,7 +74,7 @@ use crate::check::dropck; use crate::check::FnCtxt; -use crate::middle::mem_categorization as mc; +use crate::mem_categorization as mc; use crate::middle::region; use rustc::hir::def_id::DefId; use rustc::infer::outlives::env::OutlivesEnvironment; diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index daaa21202ac21..3002459d56f3c 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -32,9 +32,9 @@ use super::FnCtxt; -use crate::middle::expr_use_visitor as euv; -use crate::middle::mem_categorization as mc; -use crate::middle::mem_categorization::PlaceBase; +use crate::expr_use_visitor as euv; +use crate::mem_categorization as mc; +use crate::mem_categorization::PlaceBase; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::hir::def_id::LocalDefId; diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc_typeck/expr_use_visitor.rs similarity index 97% rename from src/librustc/middle/expr_use_visitor.rs rename to src/librustc_typeck/expr_use_visitor.rs index 5ad381ef6b272..03d7ab2d63377 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc_typeck/expr_use_visitor.rs @@ -5,14 +5,17 @@ pub use self::ConsumeMode::*; use self::OverloadedCallType::*; -use crate::hir::def::Res; -use crate::hir::def_id::DefId; -use crate::hir::ptr::P; -use crate::infer::InferCtxt; -use crate::middle::mem_categorization as mc; -use crate::ty::{self, TyCtxt, adjustment}; - -use crate::hir::{self, PatKind}; +// Export these here so that Clippy can use them. +pub use mc::{PlaceBase, Place, Projection}; + +use rustc::hir::{self, PatKind}; +use rustc::hir::def::Res; +use rustc::hir::def_id::DefId; +use rustc::hir::ptr::P; +use rustc::infer::InferCtxt; +use rustc::ty::{self, TyCtxt, adjustment}; + +use crate::mem_categorization as mc; use syntax_pos::Span; /////////////////////////////////////////////////////////////////////////// @@ -147,7 +150,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.mc.tcx() } - fn delegate_consume(&mut self, place: &mc::Place<'tcx>) { + fn delegate_consume(&mut self, place: &Place<'tcx>) { debug!("delegate_consume(place={:?})", place); let mode = copy_or_move(&self.mc, place); @@ -516,7 +519,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } } - fn walk_arm(&mut self, discr_place: &mc::Place<'tcx>, arm: &hir::Arm) { + fn walk_arm(&mut self, discr_place: &Place<'tcx>, arm: &hir::Arm) { self.walk_pat(discr_place, &arm.pat); if let Some(hir::Guard::If(ref e)) = arm.guard { @@ -528,13 +531,13 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { /// Walks a pat that occurs in isolation (i.e., top-level of fn argument or /// let binding, and *not* a match arm or nested pat.) - fn walk_irrefutable_pat(&mut self, discr_place: &mc::Place<'tcx>, pat: &hir::Pat) { + fn walk_irrefutable_pat(&mut self, discr_place: &Place<'tcx>, pat: &hir::Pat) { self.walk_pat(discr_place, pat); } /// The core driver for walking a pattern - fn walk_pat(&mut self, discr_place: &mc::Place<'tcx>, pat: &hir::Pat) { + fn walk_pat(&mut self, discr_place: &Place<'tcx>, pat: &hir::Pat) { debug!("walk_pat(discr_place={:?}, pat={:?})", discr_place, pat); let tcx = self.tcx(); @@ -622,7 +625,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { fn copy_or_move<'a, 'tcx>( mc: &mc::MemCategorizationContext<'a, 'tcx>, - place: &mc::Place<'tcx>, + place: &Place<'tcx>, ) -> ConsumeMode { if !mc.type_is_copy_modulo_regions(place.ty, place.span) { Move diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 0f147f92b5f7e..c606feab08727 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -75,6 +75,9 @@ This API is completely unstable and subject to change. #[macro_use] extern crate rustc; +// This is used by Clippy. +pub mod expr_use_visitor; + mod astconv; mod check; mod check_unused; @@ -83,6 +86,7 @@ mod collect; mod constrained_generic_params; mod structured_errors; mod impl_wf_check; +mod mem_categorization; mod namespace; mod outlives; mod variance; diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc_typeck/mem_categorization.rs similarity index 96% rename from src/librustc/middle/mem_categorization.rs rename to src/librustc_typeck/mem_categorization.rs index 9b0a12234a7ef..84e5d234da9d7 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc_typeck/mem_categorization.rs @@ -48,15 +48,15 @@ //! result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference //! tied to `x`. The type of `x'` will be a borrowed pointer. -use crate::hir::def_id::DefId; -use crate::infer::InferCtxt; -use crate::hir::def::{Res, DefKind}; -use crate::ty::adjustment; -use crate::ty::{self, Ty, TyCtxt}; -use crate::ty::fold::TypeFoldable; - -use crate::hir::PatKind; -use crate::hir; +use rustc::hir; +use rustc::hir::PatKind; +use rustc::hir::def_id::DefId; +use rustc::hir::def::{Res, DefKind}; +use rustc::infer::InferCtxt; +use rustc::ty::adjustment; +use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::fold::TypeFoldable; + use syntax_pos::Span; use rustc_data_structures::fx::FxIndexMap; @@ -105,7 +105,7 @@ impl<'tcx> Place<'tcx> { /// The types are in the reverse order that they are applied. So if /// `x: &*const u32` and the `Place` is `**x`, then the types returned are ///`*const u32` then `&*const u32`. - pub fn deref_tys(&self) -> impl Iterator> + '_ { + crate fn deref_tys(&self) -> impl Iterator> + '_ { self.projections.iter().rev().filter_map(|proj| if let Projection::Deref(deref_ty) = *proj { Some(deref_ty) } else { @@ -114,7 +114,7 @@ impl<'tcx> Place<'tcx> { } } -pub trait HirNode { +crate trait HirNode { fn hir_id(&self) -> hir::HirId; fn span(&self) -> Span; } @@ -130,19 +130,19 @@ impl HirNode for hir::Pat { } #[derive(Clone)] -pub struct MemCategorizationContext<'a, 'tcx> { - pub tables: &'a ty::TypeckTables<'tcx>, +crate struct MemCategorizationContext<'a, 'tcx> { + crate tables: &'a ty::TypeckTables<'tcx>, infcx: &'a InferCtxt<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, body_owner: DefId, upvars: Option<&'tcx FxIndexMap>, } -pub type McResult = Result; +crate type McResult = Result; impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { /// Creates a `MemCategorizationContext`. - pub fn new( + crate fn new( infcx: &'a InferCtxt<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, body_owner: DefId, @@ -276,7 +276,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { Ok(ret_ty) } - pub fn cat_expr(&self, expr: &hir::Expr) -> McResult> { + crate fn cat_expr(&self, expr: &hir::Expr) -> McResult> { // This recursion helper avoids going through *too many* // adjustments, since *only* non-overloaded deref recurses. fn helper<'a, 'tcx>( @@ -295,7 +295,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { helper(self, expr, self.tables.expr_adjustments(expr)) } - pub fn cat_expr_adjusted(&self, expr: &hir::Expr, + crate fn cat_expr_adjusted(&self, expr: &hir::Expr, previous: Place<'tcx>, adjustment: &adjustment::Adjustment<'tcx>) -> McResult> { @@ -334,7 +334,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } } - pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult> { + crate fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult> { debug!("cat_expr: id={} expr={:?}", expr.hir_id, expr); let expr_ty = self.expr_ty(expr)?; @@ -475,7 +475,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { Ok(ret) } - pub fn cat_rvalue(&self, hir_id: hir::HirId, span: Span, expr_ty: Ty<'tcx>) -> Place<'tcx> { + crate fn cat_rvalue(&self, hir_id: hir::HirId, span: Span, expr_ty: Ty<'tcx>) -> Place<'tcx> { debug!("cat_rvalue hir_id={:?}, expr_ty={:?}, span={:?}", hir_id, expr_ty, span); let ret = Place { hir_id, @@ -562,7 +562,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { Ok(ret) } - pub fn cat_pattern(&self, place: Place<'tcx>, pat: &hir::Pat, mut op: F) -> McResult<()> + crate fn cat_pattern(&self, place: Place<'tcx>, pat: &hir::Pat, mut op: F) -> McResult<()> where F: FnMut(&Place<'tcx>, &hir::Pat), { self.cat_pattern_(place, pat, &mut op)