diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 90ba15aa08988..d3bccaaa3e4b9 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -439,7 +439,10 @@ 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 place = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?; @@ -480,12 +483,12 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { fn check_safety_of_rvalue_destructor_if_necessary( &mut self, - place: &mc::Place<'tcx>, + place_with_id: &mc::PlaceWithHirId<'tcx>, span: Span, ) { - if let mc::PlaceBase::Rvalue = place.base { - if place.projections.is_empty() { - let typ = self.resolve_type(place.ty); + if let mc::PlaceBase::Rvalue = place_with_id.place.base { + if place_with_id.place.projections.is_empty() { + let typ = self.resolve_type(place_with_id.place.ty); let body_id = self.body_id; let _ = dropck::check_drop_obligations(self, typ, span, body_id); } @@ -570,7 +573,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::Place<'tcx>, root_pat: &hir::Pat<'_>) { + fn link_pattern(&self, discr_cmt: mc::PlaceWithHirId<'tcx>, root_pat: &hir::Pat<'_>) { debug!("link_pattern(discr_cmt={:?}, root_pat={:?})", discr_cmt, root_pat); ignore_err!(self.with_mc(|mc| { mc.cat_pattern(discr_cmt, root_pat, |sub_cmt, hir::Pat { kind, span, hir_id }| { @@ -591,7 +594,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { fn link_autoref( &self, expr: &hir::Expr<'_>, - expr_cmt: &mc::Place<'tcx>, + expr_cmt: &mc::PlaceWithHirId<'tcx>, autoref: &adjustment::AutoBorrow<'tcx>, ) { debug!("link_autoref(autoref={:?}, expr_cmt={:?})", autoref, expr_cmt); @@ -612,7 +615,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { span: Span, id: hir::HirId, mutbl: hir::Mutability, - cmt_borrowed: &mc::Place<'tcx>, + cmt_borrowed: &mc::PlaceWithHirId<'tcx>, ) { debug!( "link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={:?})", @@ -635,12 +638,12 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { span: Span, borrow_region: ty::Region<'tcx>, borrow_kind: ty::BorrowKind, - borrow_place: &mc::Place<'tcx>, + borrow_place: &mc::PlaceWithHirId<'tcx>, ) { - let origin = infer::DataBorrowed(borrow_place.ty, span); - self.type_must_outlive(origin, borrow_place.ty, borrow_region); + let origin = infer::DataBorrowed(borrow_place.place.ty, span); + self.type_must_outlive(origin, borrow_place.place.ty, borrow_region); - for pointer_ty in borrow_place.deref_tys() { + for pointer_ty in borrow_place.place.deref_tys() { debug!( "link_region(borrow_region={:?}, borrow_kind={:?}, pointer_ty={:?})", borrow_region, borrow_kind, borrow_place @@ -656,7 +659,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { _ => assert!(pointer_ty.is_box(), "unexpected built-in deref type {}", pointer_ty), } } - if let mc::PlaceBase::Upvar(upvar_id) = borrow_place.base { + if let mc::PlaceBase::Upvar(upvar_id) = borrow_place.place.base { self.link_upvar_region(span, borrow_region, upvar_id); } } diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 8403c99f01bb5..0f3133e0695f1 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -270,10 +270,13 @@ struct InferBorrowKind<'a, 'tcx> { impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { fn adjust_upvar_borrow_kind_for_consume( &mut self, - place: &mc::Place<'tcx>, + place_with_id: &mc::PlaceWithHirId<'tcx>, mode: euv::ConsumeMode, ) { - debug!("adjust_upvar_borrow_kind_for_consume(place={:?}, mode={:?})", place, mode); + debug!( + "adjust_upvar_borrow_kind_for_consume(place_with_id={:?}, mode={:?})", + place_with_id, mode + ); // we only care about moves match mode { @@ -284,7 +287,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { } let tcx = self.fcx.tcx; - let upvar_id = if let PlaceBase::Upvar(upvar_id) = place.base { + let upvar_id = if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base { upvar_id } else { return; @@ -296,22 +299,22 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { self.adjust_closure_kind( upvar_id.closure_expr_id, ty::ClosureKind::FnOnce, - place.span, + tcx.hir().span(place_with_id.hir_id), var_name(tcx, upvar_id.var_path.hir_id), ); self.adjust_upvar_captures.insert(upvar_id, ty::UpvarCapture::ByValue); } - /// Indicates that `place` is being directly mutated (e.g., assigned + /// Indicates that `place_with_id` 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>) { - debug!("adjust_upvar_borrow_kind_for_mut(place={:?})", place); + fn adjust_upvar_borrow_kind_for_mut(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>) { + debug!("adjust_upvar_borrow_kind_for_mut(place_with_id={:?})", place_with_id); - if let PlaceBase::Upvar(upvar_id) = place.base { + if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base { let mut borrow_kind = ty::MutBorrow; - for pointer_ty in place.deref_tys() { + for pointer_ty in place_with_id.place.deref_tys() { match pointer_ty.kind { // Raw pointers don't inherit mutability. ty::RawPtr(_) => return, @@ -323,20 +326,28 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { _ => (), } } - self.adjust_upvar_deref(upvar_id, place.span, borrow_kind); + self.adjust_upvar_deref( + upvar_id, + self.fcx.tcx.hir().span(place_with_id.hir_id), + borrow_kind, + ); } } - fn adjust_upvar_borrow_kind_for_unique(&mut self, place: &mc::Place<'tcx>) { - debug!("adjust_upvar_borrow_kind_for_unique(place={:?})", place); + fn adjust_upvar_borrow_kind_for_unique(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>) { + debug!("adjust_upvar_borrow_kind_for_unique(place_with_id={:?})", place_with_id); - if let PlaceBase::Upvar(upvar_id) = place.base { - if place.deref_tys().any(ty::TyS::is_unsafe_ptr) { + if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base { + if place_with_id.place.deref_tys().any(ty::TyS::is_unsafe_ptr) { // Raw pointers don't inherit mutability. return; } // for a borrowed pointer to be unique, its base must be unique - self.adjust_upvar_deref(upvar_id, place.span, ty::UniqueImmBorrow); + self.adjust_upvar_deref( + upvar_id, + self.fcx.tcx.hir().span(place_with_id.hir_id), + ty::UniqueImmBorrow, + ); } } @@ -453,26 +464,26 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { } impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { - 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 consume(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>, mode: euv::ConsumeMode) { + debug!("consume(place_with_id={:?},mode={:?})", place_with_id, mode); + self.adjust_upvar_borrow_kind_for_consume(place_with_id, mode); } - fn borrow(&mut self, place: &mc::Place<'tcx>, bk: ty::BorrowKind) { - debug!("borrow(place={:?}, bk={:?})", place, bk); + fn borrow(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>, bk: ty::BorrowKind) { + debug!("borrow(place_with_id={:?}, bk={:?})", place_with_id, bk); match bk { ty::ImmBorrow => {} ty::UniqueImmBorrow => { - self.adjust_upvar_borrow_kind_for_unique(place); + self.adjust_upvar_borrow_kind_for_unique(place_with_id); } ty::MutBorrow => { - self.adjust_upvar_borrow_kind_for_mut(place); + self.adjust_upvar_borrow_kind_for_mut(place_with_id); } } } - fn mutate(&mut self, assignee_place: &mc::Place<'tcx>) { + fn mutate(&mut self, assignee_place: &mc::PlaceWithHirId<'tcx>) { debug!("mutate(assignee_place={:?})", assignee_place); self.adjust_upvar_borrow_kind_for_mut(assignee_place); diff --git a/src/librustc_typeck/expr_use_visitor.rs b/src/librustc_typeck/expr_use_visitor.rs index 6baadb8febd36..b72fae96e4ca0 100644 --- a/src/librustc_typeck/expr_use_visitor.rs +++ b/src/librustc_typeck/expr_use_visitor.rs @@ -5,7 +5,7 @@ pub use self::ConsumeMode::*; // Export these here so that Clippy can use them. -pub use mc::{Place, PlaceBase, Projection}; +pub use mc::{PlaceBase, PlaceWithHirId, Projection}; use rustc_hir as hir; use rustc_hir::def::Res; @@ -25,13 +25,13 @@ use rustc_span::Span; pub trait Delegate<'tcx> { // The value found at `place` is either copied or moved, depending // on mode. - fn consume(&mut self, place: &mc::Place<'tcx>, mode: ConsumeMode); + fn consume(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>, mode: ConsumeMode); // The value found at `place` is being borrowed with kind `bk`. - fn borrow(&mut self, place: &mc::Place<'tcx>, bk: ty::BorrowKind); + fn borrow(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>, bk: ty::BorrowKind); - // The path at `place` is being assigned to. - fn mutate(&mut self, assignee_place: &mc::Place<'tcx>); + // The path at `place_with_id` is being assigned to. + fn mutate(&mut self, assignee_place: &mc::PlaceWithHirId<'tcx>); } #[derive(Copy, Clone, PartialEq, Debug)] @@ -113,11 +113,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { self.mc.tcx() } - fn delegate_consume(&mut self, place: &Place<'tcx>) { - debug!("delegate_consume(place={:?})", place); + fn delegate_consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>) { + debug!("delegate_consume(place_with_id={:?})", place_with_id); - let mode = copy_or_move(&self.mc, place); - self.delegate.consume(place, mode); + let mode = copy_or_move(&self.mc, place_with_id); + self.delegate.consume(place_with_id, mode); } fn consume_exprs(&mut self, exprs: &[hir::Expr<'_>]) { @@ -129,22 +129,22 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { pub fn consume_expr(&mut self, expr: &hir::Expr<'_>) { debug!("consume_expr(expr={:?})", expr); - let place = return_if_err!(self.mc.cat_expr(expr)); - self.delegate_consume(&place); + let place_with_id = return_if_err!(self.mc.cat_expr(expr)); + self.delegate_consume(&place_with_id); self.walk_expr(expr); } fn mutate_expr(&mut self, expr: &hir::Expr<'_>) { - let place = return_if_err!(self.mc.cat_expr(expr)); - self.delegate.mutate(&place); + let place_with_id = return_if_err!(self.mc.cat_expr(expr)); + self.delegate.mutate(&place_with_id); self.walk_expr(expr); } fn borrow_expr(&mut self, expr: &hir::Expr<'_>, bk: ty::BorrowKind) { debug!("borrow_expr(expr={:?}, bk={:?})", expr, bk); - let place = return_if_err!(self.mc.cat_expr(expr)); - self.delegate.borrow(&place, bk); + let place_with_id = return_if_err!(self.mc.cat_expr(expr)); + self.delegate.borrow(&place_with_id, bk); self.walk_expr(expr) } @@ -384,7 +384,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // Select just those fields of the `with` // expression that will actually be used - match with_place.ty.kind { + match with_place.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() { @@ -422,14 +422,14 @@ 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 place = return_if_err!(self.mc.cat_expr_unadjusted(expr)); + let mut place_with_id = return_if_err!(self.mc.cat_expr_unadjusted(expr)); for adjustment in adjustments { debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment); match adjustment.kind { adjustment::Adjust::NeverToAny | adjustment::Adjust::Pointer(_) => { // Creating a closure/fn-pointer or unsizing consumes // the input and stores it into the resulting rvalue. - self.delegate_consume(&place); + self.delegate_consume(&place_with_id); } adjustment::Adjust::Deref(None) => {} @@ -441,14 +441,15 @@ 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(&place, bk); + self.delegate.borrow(&place_with_id, bk); } adjustment::Adjust::Borrow(ref autoref) => { - self.walk_autoref(expr, &place, autoref); + self.walk_autoref(expr, &place_with_id, autoref); } } - place = return_if_err!(self.mc.cat_expr_adjusted(expr, place, &adjustment)); + place_with_id = + return_if_err!(self.mc.cat_expr_adjusted(expr, place_with_id, &adjustment)); } } @@ -458,7 +459,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { fn walk_autoref( &mut self, expr: &hir::Expr<'_>, - base_place: &mc::Place<'tcx>, + base_place: &mc::PlaceWithHirId<'tcx>, autoref: &adjustment::AutoBorrow<'tcx>, ) { debug!( @@ -479,7 +480,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } } - fn walk_arm(&mut self, discr_place: &Place<'tcx>, arm: &hir::Arm<'_>) { + fn walk_arm(&mut self, discr_place: &PlaceWithHirId<'tcx>, arm: &hir::Arm<'_>) { self.walk_pat(discr_place, &arm.pat); if let Some(hir::Guard::If(ref e)) = arm.guard { @@ -491,12 +492,12 @@ 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: &Place<'tcx>, pat: &hir::Pat<'_>) { + fn walk_irrefutable_pat(&mut self, discr_place: &PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>) { self.walk_pat(discr_place, pat); } /// The core driver for walking a pattern - fn walk_pat(&mut self, discr_place: &Place<'tcx>, pat: &hir::Pat<'_>) { + fn walk_pat(&mut self, discr_place: &PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>) { debug!("walk_pat(discr_place={:?}, pat={:?})", discr_place, pat); let tcx = self.tcx(); @@ -569,7 +570,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 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)?; @@ -579,7 +580,14 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { fn copy_or_move<'a, 'tcx>( mc: &mc::MemCategorizationContext<'a, 'tcx>, - place: &Place<'tcx>, + place_with_id: &PlaceWithHirId<'tcx>, ) -> ConsumeMode { - if !mc.type_is_copy_modulo_regions(place.ty, place.span) { Move } else { Copy } + if !mc.type_is_copy_modulo_regions( + place_with_id.place.ty, + mc.tcx().hir().span(place_with_id.hir_id), + ) { + Move + } else { + Copy + } } diff --git a/src/librustc_typeck/mem_categorization.rs b/src/librustc_typeck/mem_categorization.rs index 93d01ccd66f1e..d619d37be2d7b 100644 --- a/src/librustc_typeck/mem_categorization.rs +++ b/src/librustc_typeck/mem_categorization.rs @@ -74,22 +74,24 @@ pub enum PlaceBase { } #[derive(Clone, Debug)] -pub enum Projection<'tcx> { +pub enum ProjectionKind<'tcx> { /// A dereference of a pointer, reference or `Box` of the given type Deref(Ty<'tcx>), /// An index or a field Other, } +#[derive(Clone, Debug)] +pub struct Projection<'tcx> { + /// Defines the type of access + kind: ProjectionKind<'tcx>, +} + /// 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. @@ -98,6 +100,32 @@ pub struct Place<'tcx> { pub projections: Vec>, } +/// A `PlaceWithHirId` represents how a value is located in memory. +/// +/// This is an HIR version of `mir::Place` +#[derive(Clone, Debug)] +pub struct PlaceWithHirId<'tcx> { + /// `HirId` of the expression or pattern producing this value. + pub hir_id: hir::HirId, + + /// Information about the `Place` + pub place: Place<'tcx>, +} + +impl<'tcx> PlaceWithHirId<'tcx> { + crate fn new( + hir_id: hir::HirId, + ty: Ty<'tcx>, + base: PlaceBase, + projections: Vec>, + ) -> PlaceWithHirId<'tcx> { + PlaceWithHirId { + hir_id: hir_id, + place: Place { ty: ty, base: base, projections: projections }, + } + } +} + impl<'tcx> Place<'tcx> { /// Returns an iterator of the types that have to be dereferenced to access /// the `Place`. @@ -107,7 +135,7 @@ impl<'tcx> Place<'tcx> { ///`*const u32` then `&*const u32`. 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 { None } + if let ProjectionKind::Deref(deref_ty) = proj.kind { Some(deref_ty) } else { None } }) } } @@ -280,14 +308,14 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { Ok(ret_ty) } - crate 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>( 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)) => { @@ -302,9 +330,9 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { crate fn cat_expr_adjusted( &self, expr: &hir::Expr<'_>, - previous: Place<'tcx>, + previous: PlaceWithHirId<'tcx>, adjustment: &adjustment::Adjustment<'tcx>, - ) -> McResult> { + ) -> McResult> { self.cat_expr_adjusted_with(expr, || Ok(previous), adjustment) } @@ -313,9 +341,9 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { expr: &hir::Expr<'_>, previous: F, adjustment: &adjustment::Adjustment<'tcx>, - ) -> McResult> + ) -> McResult> where - F: FnOnce() -> McResult>, + F: FnOnce() -> McResult>, { debug!("cat_expr_adjusted_with({:?}): {:?}", adjustment, expr); let target = self.resolve_vars_if_possible(&adjustment.target); @@ -342,7 +370,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } } - crate 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)?; @@ -418,7 +446,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); match res { @@ -433,25 +461,15 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { ) | Res::SelfCtor(..) => Ok(self.cat_rvalue(hir_id, span, expr_ty)), - Res::Def(DefKind::Static, _) => Ok(Place { - hir_id, - span, - ty: expr_ty, - base: PlaceBase::StaticItem, - projections: Vec::new(), - }), + Res::Def(DefKind::Static, _) => { + Ok(PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::StaticItem, Vec::new())) + } Res::Local(var_id) => { if self.upvars.map_or(false, |upvars| upvars.contains_key(&var_id)) { - self.cat_upvar(hir_id, span, var_id) + self.cat_upvar(hir_id, var_id) } else { - Ok(Place { - hir_id, - span, - ty: expr_ty, - base: PlaceBase::Local(var_id), - projections: Vec::new(), - }) + Ok(PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Local(var_id), Vec::new())) } } @@ -464,12 +482,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { /// 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> { + fn cat_upvar(&self, hir_id: hir::HirId, var_id: hir::HirId) -> McResult> { let closure_expr_def_id = self.body_owner; let upvar_id = ty::UpvarId { @@ -478,22 +491,20 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { }; let var_ty = self.node_ty(var_id)?; - let ret = Place { - hir_id, - span, - ty: var_ty, - base: PlaceBase::Upvar(upvar_id), - projections: Vec::new(), - }; + let ret = PlaceWithHirId::new(hir_id, var_ty, PlaceBase::Upvar(upvar_id), Vec::new()); debug!("cat_upvar ret={:?}", ret); Ok(ret) } - crate 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>, + ) -> PlaceWithHirId<'tcx> { debug!("cat_rvalue hir_id={:?}, expr_ty={:?}, span={:?}", hir_id, expr_ty, span); - let ret = - Place { hir_id, span, base: PlaceBase::Rvalue, projections: Vec::new(), ty: expr_ty }; + let ret = PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new()); debug!("cat_rvalue ret={:?}", ret); ret } @@ -501,18 +512,12 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { crate fn cat_projection( &self, node: &N, - base_place: Place<'tcx>, + base_place: PlaceWithHirId<'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(), - ty, - base: base_place.base, - projections, - }; + ) -> PlaceWithHirId<'tcx> { + let mut projections = base_place.place.projections; + projections.push(Projection { kind: ProjectionKind::Other }); + let ret = PlaceWithHirId::new(node.hir_id(), ty, base_place.place.base, projections); debug!("cat_field ret {:?}", ret); ret } @@ -521,7 +526,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { &self, expr: &hir::Expr<'_>, base: &hir::Expr<'_>, - ) -> McResult> { + ) -> McResult> { debug!("cat_overloaded_place(expr={:?}, base={:?})", expr, base); // Reconstruct the output assuming it's a reference with the @@ -540,10 +545,14 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { self.cat_deref(expr, base) } - fn cat_deref(&self, node: &impl HirNode, base_place: Place<'tcx>) -> McResult> { + fn cat_deref( + &self, + node: &impl HirNode, + base_place: PlaceWithHirId<'tcx>, + ) -> McResult> { debug!("cat_deref: base_place={:?}", base_place); - let base_ty = base_place.ty; + let base_ty = base_place.place.ty; let deref_ty = match base_ty.builtin_deref(true) { Some(mt) => mt.ty, None => { @@ -551,28 +560,22 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { return Err(()); } }; - let mut projections = base_place.projections; - projections.push(Projection::Deref(base_ty)); - - let ret = Place { - hir_id: node.hir_id(), - span: node.span(), - ty: deref_ty, - base: base_place.base, - projections, - }; + let mut projections = base_place.place.projections; + projections.push(Projection { kind: ProjectionKind::Deref(base_ty) }); + + let ret = PlaceWithHirId::new(node.hir_id(), deref_ty, base_place.place.base, projections); debug!("cat_deref ret {:?}", ret); Ok(ret) } crate fn cat_pattern( &self, - place: Place<'tcx>, + place: PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>, mut op: F, ) -> McResult<()> where - F: FnMut(&Place<'tcx>, &hir::Pat<'_>), + F: FnMut(&PlaceWithHirId<'tcx>, &hir::Pat<'_>), { self.cat_pattern_(place, pat, &mut op) } @@ -580,24 +583,24 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // FIXME(#19596) This is a workaround, but there should be a better way to do this fn cat_pattern_( &self, - mut place: Place<'tcx>, + mut place_with_id: PlaceWithHirId<'tcx>, pat: &hir::Pat<'_>, op: &mut F, ) -> McResult<()> where - F: FnMut(&Place<'tcx>, &hir::Pat<'_>), + F: FnMut(&PlaceWithHirId<'tcx>, &hir::Pat<'_>), { - // Here, `place` is the `Place` being matched and pat is the pattern it + // Here, `place` is the `PlaceWithHirId` 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 `Place` that represents the path that will be taken + // constructing a `PlaceWithHirId` that represents the path that will be taken // to reach the value being matched. - debug!("cat_pattern(pat={:?}, place={:?})", pat, place); + debug!("cat_pattern(pat={:?}, place_with_id={:?})", pat, place_with_id); - // If (pattern) adjustments are active for this pattern, adjust the `Place` correspondingly. - // `Place`s are constructed differently from patterns. For example, in + // If (pattern) adjustments are active for this pattern, adjust the `PlaceWithHirId` correspondingly. + // `PlaceWithHirId`s are constructed differently from patterns. For example, in // // ``` // match foo { @@ -607,7 +610,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // ``` // // the pattern `&&Some(x,)` is represented as `Ref { Ref { TupleStruct }}`. To build the - // corresponding `Place` we start with the `Place` for `foo`, and then, by traversing the + // corresponding `PlaceWithHirId` we start with the `PlaceWithHirId` for `foo`, and then, by traversing the // pattern, try to answer the question: given the address of `foo`, how is `x` reached? // // `&&Some(x,)` `place_foo` @@ -629,29 +632,29 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // `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 place={:?}", place); - place = self.cat_deref(pat, place)?; + debug!("cat_pattern: applying adjustment to place_with_id={:?}", place_with_id); + place_with_id = self.cat_deref(pat, place_with_id)?; } - let place = place; // lose mutability - debug!("cat_pattern: applied adjustment derefs to get place={:?}", place); + let place_with_id = place_with_id; // lose mutability + debug!("cat_pattern: applied adjustment derefs to get place_with_id={:?}", place_with_id); - // Invoke the callback, but only now, after the `place` has adjusted. + // Invoke the callback, but only now, after the `place_with_id` has adjusted. // // To see that this makes sense, consider `match &Some(3) { Some(x) => { ... }}`. In that - // case, the initial `place` will be that for `&Some(3)` and the pattern is `Some(x)`. We + // case, the initial `place_with_id` 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 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 place `Downcast(*&Some(3)).0` associated to `x` and invoke `op` with // that (where the `ref` on `x` is implied). - op(&place, pat); + op(&place_with_id, pat); match pat.kind { 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); + let sub_place = self.cat_projection(pat, place_with_id.clone(), subpat_ty); self.cat_pattern_(sub_place, &subpat, op)?; } } @@ -660,44 +663,44 @@ 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 field_place = self.cat_projection(pat, place.clone(), field_ty); + let field_place = self.cat_projection(pat, place_with_id.clone(), field_ty); self.cat_pattern_(field_place, &fp.pat, op)?; } } PatKind::Or(pats) => { for pat in pats { - self.cat_pattern_(place.clone(), &pat, op)?; + self.cat_pattern_(place_with_id.clone(), &pat, op)?; } } PatKind::Binding(.., Some(ref subpat)) => { - self.cat_pattern_(place, &subpat, op)?; + self.cat_pattern_(place_with_id, &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 subplace = self.cat_deref(pat, place)?; + let subplace = self.cat_deref(pat, place_with_id)?; self.cat_pattern_(subplace, &subpat, op)?; } PatKind::Slice(before, ref slice, after) => { - let element_ty = match place.ty.builtin_index() { + let element_ty = match place_with_id.place.ty.builtin_index() { Some(ty) => ty, None => { - debug!("explicit index of non-indexable type {:?}", place); + debug!("explicit index of non-indexable type {:?}", place_with_id); return Err(()); } }; - let elt_place = self.cat_projection(pat, place.clone(), element_ty); + let elt_place = self.cat_projection(pat, place_with_id.clone(), element_ty); for before_pat in before { self.cat_pattern_(elt_place.clone(), &before_pat, op)?; } if let Some(ref slice_pat) = *slice { let slice_pat_ty = self.pat_ty_adjusted(&slice_pat)?; - let slice_place = self.cat_projection(pat, place, slice_pat_ty); + let slice_place = self.cat_projection(pat, place_with_id, slice_pat_ty); self.cat_pattern_(slice_place, &slice_pat, op)?; } for after_pat in after { diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index 7227683aa5ac2..59af475af175e 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -6,7 +6,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_target::abi::LayoutOf; -use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; +use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceWithHirId, PlaceBase}; use crate::utils::span_lint; @@ -112,9 +112,9 @@ fn is_argument(map: rustc_middle::hir::map::Map<'_>, id: HirId) -> bool { } impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { - fn consume(&mut self, cmt: &Place<'tcx>, mode: ConsumeMode) { - if cmt.projections.is_empty() { - if let PlaceBase::Local(lid) = cmt.base { + fn consume(&mut self, cmt: &PlaceWithHirId<'tcx>, mode: ConsumeMode) { + if cmt.place.projections.is_empty() { + if let PlaceBase::Local(lid) = cmt.place.base { if let ConsumeMode::Move = mode { // moved out or in. clearly can't be localized self.set.remove(&lid); @@ -132,16 +132,16 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } } - fn borrow(&mut self, cmt: &Place<'tcx>, _: ty::BorrowKind) { - if cmt.projections.is_empty() { - if let PlaceBase::Local(lid) = cmt.base { + fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: ty::BorrowKind) { + if cmt.place.projections.is_empty() { + if let PlaceBase::Local(lid) = cmt.place.base { self.set.remove(&lid); } } } - fn mutate(&mut self, cmt: &Place<'tcx>) { - if cmt.projections.is_empty() { + fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>) { + if cmt.place.projections.is_empty() { let map = &self.cx.tcx.hir(); if is_argument(*map, cmt.hir_id) { // Skip closure arguments @@ -150,7 +150,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { return; } - if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) { + if is_non_trait_box(cmt.place.ty) && !self.is_large_box(cmt.place.ty) { self.set.insert(cmt.hir_id); } return; diff --git a/src/tools/clippy/clippy_lints/src/loops.rs b/src/tools/clippy/clippy_lints/src/loops.rs index 771bc8d055825..83093ec51bd90 100644 --- a/src/tools/clippy/clippy_lints/src/loops.rs +++ b/src/tools/clippy/clippy_lints/src/loops.rs @@ -28,7 +28,7 @@ use rustc_middle::ty::{self, Ty, TyS}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; -use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; +use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceWithHirId, PlaceBase}; use std::iter::{once, Iterator}; use std::mem; @@ -1489,42 +1489,43 @@ fn check_for_loop_over_map_kv<'a, 'tcx>( } } -struct MutatePairDelegate { +struct MutatePairDelegate<'a, 'tcx> { + cx: &'a LateContext<'a, 'tcx>, hir_id_low: Option, hir_id_high: Option, span_low: Option, span_high: Option, } -impl<'tcx> Delegate<'tcx> for MutatePairDelegate { - fn consume(&mut self, _: &Place<'tcx>, _: ConsumeMode) {} +impl<'a, 'tcx> Delegate<'tcx> for MutatePairDelegate<'a, 'tcx> { + fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: ConsumeMode) {} - fn borrow(&mut self, cmt: &Place<'tcx>, bk: ty::BorrowKind) { + fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, bk: ty::BorrowKind) { if let ty::BorrowKind::MutBorrow = bk { - if let PlaceBase::Local(id) = cmt.base { + if let PlaceBase::Local(id) = cmt.place.base { if Some(id) == self.hir_id_low { - self.span_low = Some(cmt.span) + self.span_low = Some(self.cx.tcx.hir().span(cmt.hir_id)) } if Some(id) == self.hir_id_high { - self.span_high = Some(cmt.span) + self.span_high = Some(self.cx.tcx.hir().span(cmt.hir_id)) } } } } - fn mutate(&mut self, cmt: &Place<'tcx>) { - if let PlaceBase::Local(id) = cmt.base { + fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>) { + if let PlaceBase::Local(id) = cmt.place.base { if Some(id) == self.hir_id_low { - self.span_low = Some(cmt.span) + self.span_low = Some(self.cx.tcx.hir().span(cmt.hir_id)) } if Some(id) == self.hir_id_high { - self.span_high = Some(cmt.span) + self.span_high = Some(self.cx.tcx.hir().span(cmt.hir_id)) } } } } -impl<'tcx> MutatePairDelegate { +impl<'a, 'tcx> MutatePairDelegate<'a, 'tcx> { fn mutation_span(&self) -> (Option, Option) { (self.span_low, self.span_high) } @@ -1579,12 +1580,13 @@ fn check_for_mutability(cx: &LateContext<'_, '_>, bound: &Expr<'_>) -> Option, +fn check_for_mutation<'a, 'tcx> ( + cx: &LateContext<'a, 'tcx>, body: &Expr<'_>, bound_ids: &[Option], ) -> (Option, Option) { let mut delegate = MutatePairDelegate { + cx: cx, hir_id_low: bound_ids[0], hir_id_high: bound_ids[1], span_low: None, diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 218b0d27f7486..ca87deac9891c 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -326,21 +326,21 @@ struct MovedVariablesCtxt { } impl MovedVariablesCtxt { - fn move_common(&mut self, cmt: &euv::Place<'_>) { - if let euv::PlaceBase::Local(vid) = cmt.base { + fn move_common(&mut self, cmt: &euv::PlaceWithHirId<'_>) { + if let euv::PlaceBase::Local(vid) = cmt.place.base { self.moved_vars.insert(vid); } } } impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt { - fn consume(&mut self, cmt: &euv::Place<'tcx>, mode: euv::ConsumeMode) { + fn consume(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, mode: euv::ConsumeMode) { if let euv::ConsumeMode::Move = mode { self.move_common(cmt); } } - fn borrow(&mut self, _: &euv::Place<'tcx>, _: ty::BorrowKind) {} + fn borrow(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: ty::BorrowKind) {} - fn mutate(&mut self, _: &euv::Place<'tcx>) {} + fn mutate(&mut self, _: &euv::PlaceWithHirId<'tcx>) {} } diff --git a/src/tools/clippy/clippy_lints/src/utils/usage.rs b/src/tools/clippy/clippy_lints/src/utils/usage.rs index 904d948ad29ed..6a7a1f1ceaaef 100644 --- a/src/tools/clippy/clippy_lints/src/utils/usage.rs +++ b/src/tools/clippy/clippy_lints/src/utils/usage.rs @@ -8,7 +8,7 @@ use rustc_lint::LateContext; use rustc_middle::hir::map::Map; use rustc_middle::ty; use rustc_span::symbol::{Ident, Symbol}; -use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; +use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, PlaceWithHirId, PlaceBase}; /// Returns a set of mutated local variable IDs, or `None` if mutations could not be determined. pub fn mutated_variables<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &'a LateContext<'a, 'tcx>) -> Option> { @@ -46,8 +46,8 @@ struct MutVarsDelegate { impl<'tcx> MutVarsDelegate { #[allow(clippy::similar_names)] - fn update(&mut self, cat: &Place<'tcx>) { - match cat.base { + fn update(&mut self, cat: &PlaceWithHirId<'tcx>) { + match cat.place.base { PlaceBase::Local(id) => { self.used_mutably.insert(id); }, @@ -63,15 +63,15 @@ impl<'tcx> MutVarsDelegate { } impl<'tcx> Delegate<'tcx> for MutVarsDelegate { - fn consume(&mut self, _: &Place<'tcx>, _: ConsumeMode) {} + fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: ConsumeMode) {} - fn borrow(&mut self, cmt: &Place<'tcx>, bk: ty::BorrowKind) { + fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, bk: ty::BorrowKind) { if let ty::BorrowKind::MutBorrow = bk { self.update(&cmt) } } - fn mutate(&mut self, cmt: &Place<'tcx>) { + fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>) { self.update(&cmt) } }