diff --git a/src/librustc_middle/hir/mod.rs b/src/librustc_middle/hir/mod.rs index e152d11c081a1..2214c31020969 100644 --- a/src/librustc_middle/hir/mod.rs +++ b/src/librustc_middle/hir/mod.rs @@ -4,6 +4,7 @@ pub mod exports; pub mod map; +pub mod place; use crate::ich::StableHashingContext; use crate::ty::query::Providers; diff --git a/src/librustc_middle/hir/place.rs b/src/librustc_middle/hir/place.rs new file mode 100644 index 0000000000000..1a7870adf9c8d --- /dev/null +++ b/src/librustc_middle/hir/place.rs @@ -0,0 +1,117 @@ +use crate::ty; +use crate::ty::Ty; + +use rustc_hir::HirId; + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +pub enum PlaceBase { + /// A temporary variable + Rvalue, + /// A named `static` item + StaticItem, + /// A named local variable + Local(HirId), + /// An upvar referenced by closure env + Upvar(ty::UpvarId), +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +pub enum ProjectionKind { + /// A dereference of a pointer, reference or `Box` of the given type + Deref, + + /// `B.F` where `B` is the base expression and `F` is + /// the field. The field is identified by which variant + /// it appears in along with a field index. The variant + /// is used for enums. + Field(u32, VariantIdx), + + /// Some index like `B[x]`, where `B` is the base + /// expression. We don't preserve the index `x` because + /// we won't need it. + Index, + + /// A subslice covering a range of values like `B[x..y]`. + Subslice, + + /// Other + Other, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +pub struct Projection<'tcx> { + /// Type after the projection is being applied. + pub ty: Ty<'tcx>, + + /// Defines the type of access + pub kind: ProjectionKind, +} + +/// A `Place` represents how a value is located in memory. +/// +/// This is an HIR version of `mir::Place` +#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +pub struct Place<'tcx> { + /// The type of the `PlaceBase` + pub base_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>, +} + +/// A `PlaceWithHirId` represents how a value is located in memory. +/// +/// This is an HIR version of `mir::Place` +#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] +pub struct PlaceWithHirId<'tcx> { + /// `HirId` of the expression or pattern producing this value. + pub hir_id: HirId, + + /// Information about the `Place` + pub place: Place<'tcx>, +} + +impl<'tcx> PlaceWithHirId<'tcx> { + pub fn new( + hir_id: HirId, + base_ty: Ty<'tcx>, + base: PlaceBase, + projections: Vec>, + ) -> PlaceWithHirId<'tcx> { + PlaceWithHirId { + hir_id: hir_id, + place: Place { base_ty: base_ty, base: base, projections: projections }, + } + } +} + +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().enumerate().rev().filter_map(move |(index, proj)| { + if ProjectionKind::Deref == proj.kind { + Some(self.ty_before_projection(index)) + } else { + None + } + }) + } + + /// Returns the type of this `Place` after all projections have been applied. + pub fn ty(&self) -> Ty<'tcx> { + self.projections.last().map_or_else(|| self.base_ty, |proj| proj.ty) + } + + /// Returns the type of this `Place` immediately before `projection_index`th projection + /// is applied. + pub fn ty_before_projection(&self, projection_index: usize) -> Ty<'tcx> { + assert!(projection_index < self.projections.len()); + if projection_index == 0 { self.base_ty } else { self.projections[projection_index - 1].ty } + } +} diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 199f49ca323e0..06557fcb0e7a2 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -82,6 +82,7 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::PatKind; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, RegionObligation, RegionckMode}; +use rustc_middle::hir::place::{PlaceBase, PlaceWithHirId}; use rustc_middle::ty::adjustment; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; @@ -442,7 +443,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { fn constrain_adjustments( &mut self, expr: &hir::Expr<'_>, - ) -> mc::McResult> { + ) -> mc::McResult> { debug!("constrain_adjustments(expr={:?})", expr); let mut place = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?; @@ -483,10 +484,10 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { fn check_safety_of_rvalue_destructor_if_necessary( &mut self, - place_with_id: &mc::PlaceWithHirId<'tcx>, + place_with_id: &PlaceWithHirId<'tcx>, span: Span, ) { - if let mc::PlaceBase::Rvalue = place_with_id.place.base { + if let 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; @@ -573,7 +574,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::PlaceWithHirId<'tcx>, root_pat: &hir::Pat<'_>) { + fn link_pattern(&self, discr_cmt: 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 }| { @@ -594,7 +595,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { fn link_autoref( &self, expr: &hir::Expr<'_>, - expr_cmt: &mc::PlaceWithHirId<'tcx>, + expr_cmt: &PlaceWithHirId<'tcx>, autoref: &adjustment::AutoBorrow<'tcx>, ) { debug!("link_autoref(autoref={:?}, expr_cmt={:?})", autoref, expr_cmt); @@ -615,7 +616,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { span: Span, id: hir::HirId, mutbl: hir::Mutability, - cmt_borrowed: &mc::PlaceWithHirId<'tcx>, + cmt_borrowed: &PlaceWithHirId<'tcx>, ) { debug!( "link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={:?})", @@ -638,7 +639,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { span: Span, borrow_region: ty::Region<'tcx>, borrow_kind: ty::BorrowKind, - borrow_place: &mc::PlaceWithHirId<'tcx>, + borrow_place: &PlaceWithHirId<'tcx>, ) { let origin = infer::DataBorrowed(borrow_place.place.ty(), span); self.type_must_outlive(origin, borrow_place.place.ty(), borrow_region); @@ -659,7 +660,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.place.base { + if let 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 0f3133e0695f1..3bc5696bf70e8 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -33,14 +33,13 @@ use super::FnCtxt; use crate::expr_use_visitor as euv; -use crate::mem_categorization as mc; -use crate::mem_categorization::PlaceBase; use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_infer::infer::UpvarRegion; +use rustc_middle::hir::place::{PlaceBase, PlaceWithHirId}; use rustc_middle::ty::{self, Ty, TyCtxt, UpvarSubsts}; use rustc_span::{Span, Symbol}; @@ -270,7 +269,7 @@ struct InferBorrowKind<'a, 'tcx> { impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { fn adjust_upvar_borrow_kind_for_consume( &mut self, - place_with_id: &mc::PlaceWithHirId<'tcx>, + place_with_id: &PlaceWithHirId<'tcx>, mode: euv::ConsumeMode, ) { debug!( @@ -309,7 +308,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { /// 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_with_id: &mc::PlaceWithHirId<'tcx>) { + fn adjust_upvar_borrow_kind_for_mut(&mut self, place_with_id: &PlaceWithHirId<'tcx>) { debug!("adjust_upvar_borrow_kind_for_mut(place_with_id={:?})", place_with_id); if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base { @@ -334,7 +333,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { } } - fn adjust_upvar_borrow_kind_for_unique(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>) { + fn adjust_upvar_borrow_kind_for_unique(&mut self, place_with_id: &PlaceWithHirId<'tcx>) { debug!("adjust_upvar_borrow_kind_for_unique(place_with_id={:?})", place_with_id); if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base { @@ -464,12 +463,12 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> { } impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { - fn consume(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>, mode: euv::ConsumeMode) { + fn consume(&mut self, place_with_id: &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_with_id: &mc::PlaceWithHirId<'tcx>, bk: ty::BorrowKind) { + fn borrow(&mut self, place_with_id: &PlaceWithHirId<'tcx>, bk: ty::BorrowKind) { debug!("borrow(place_with_id={:?}, bk={:?})", place_with_id, bk); match bk { @@ -483,7 +482,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> { } } - fn mutate(&mut self, assignee_place: &mc::PlaceWithHirId<'tcx>) { + fn mutate(&mut self, assignee_place: &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 1be32729b1ee5..ff24cbe7b699b 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::{PlaceBase, PlaceWithHirId, Projection}; +pub use rustc_middle::hir::place::{PlaceBase, PlaceWithHirId, Projection}; use rustc_hir as hir; use rustc_hir::def::Res; @@ -13,6 +13,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_hir::PatKind; use rustc_index::vec::Idx; use rustc_infer::infer::InferCtxt; +use rustc_middle::hir::place::ProjectionKind; use rustc_middle::ty::{self, adjustment, TyCtxt}; use rustc_target::abi::VariantIdx; @@ -27,13 +28,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_with_id: &mc::PlaceWithHirId<'tcx>, mode: ConsumeMode); + fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, mode: ConsumeMode); // The value found at `place` is being borrowed with kind `bk`. - fn borrow(&mut self, place_with_id: &mc::PlaceWithHirId<'tcx>, bk: ty::BorrowKind); + fn borrow(&mut self, place_with_id: &PlaceWithHirId<'tcx>, bk: ty::BorrowKind); // The path at `place_with_id` is being assigned to. - fn mutate(&mut self, assignee_place: &mc::PlaceWithHirId<'tcx>); + fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>); } #[derive(Copy, Clone, PartialEq, Debug)] @@ -398,7 +399,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { &*with_expr, with_place.clone(), with_field.ty(self.tcx(), substs), - mc::ProjectionKind::Field(f_index as u32, VariantIdx::new(0)), + ProjectionKind::Field(f_index as u32, VariantIdx::new(0)), ); self.delegate_consume(&field_place); } @@ -462,7 +463,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { fn walk_autoref( &mut self, expr: &hir::Expr<'_>, - base_place: &mc::PlaceWithHirId<'tcx>, + base_place: &PlaceWithHirId<'tcx>, autoref: &adjustment::AutoBorrow<'tcx>, ) { debug!( @@ -573,7 +574,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)?; diff --git a/src/librustc_typeck/mem_categorization.rs b/src/librustc_typeck/mem_categorization.rs index 76f0182a8a45d..f0e1e954c9406 100644 --- a/src/librustc_typeck/mem_categorization.rs +++ b/src/librustc_typeck/mem_categorization.rs @@ -48,6 +48,7 @@ //! result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference //! tied to `x`. The type of `x'` will be a borrowed pointer. +use rustc_middle::hir::place::*; use rustc_middle::ty::adjustment; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -63,119 +64,6 @@ use rustc_span::Span; use rustc_target::abi::VariantIdx; use rustc_trait_selection::infer::InferCtxtExt; -#[derive(Clone, Debug)] -pub enum PlaceBase { - /// A temporary variable - Rvalue, - /// A named `static` item - StaticItem, - /// A named local variable - Local(hir::HirId), - /// An upvar referenced by closure env - Upvar(ty::UpvarId), -} - -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum ProjectionKind { - /// A dereference of a pointer, reference or `Box` of the given type - Deref, - - /// `B.F` where `B` is the base expression and `F` is - /// the field. The field is identified by which variant - /// it appears in along with a field index. The variant - /// is used for enums. - Field(u32, VariantIdx), - - /// Some index like `B[x]`, where `B` is the base - /// expression. We don't preserve the index `x` because - /// we won't need it. - Index, - - /// A subslice covering a range of values like `B[x..y]`. - Subslice, - - /// Other - Other, -} - -#[derive(Clone, Debug)] -pub struct Projection<'tcx> { - // Type after the projection is being applied. - ty: Ty<'tcx>, - - /// Defines the type of access - kind: ProjectionKind, -} - -/// 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> { - /// The type of the `PlaceBase` - pub base_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>, -} - -/// 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, - base_ty: Ty<'tcx>, - base: PlaceBase, - projections: Vec>, - ) -> PlaceWithHirId<'tcx> { - PlaceWithHirId { - hir_id: hir_id, - place: Place { base_ty: base_ty, base: base, projections: projections }, - } - } -} - -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`. - crate fn deref_tys(&self) -> impl Iterator> + '_ { - self.projections.iter().enumerate().rev().filter_map(move |(index, proj)| { - if ProjectionKind::Deref == proj.kind { - Some(self.ty_before_projection(index)) - } else { - None - } - }) - } - - // Returns the type of this `Place` after all projections have been applied. - pub fn ty(&self) -> Ty<'tcx> { - self.projections.last().map_or_else(|| self.base_ty, |proj| proj.ty) - } - - // Returns the type of this `Place` immediately before `projection_index`th projection - // is applied. - crate fn ty_before_projection(&self, projection_index: usize) -> Ty<'tcx> { - assert!(projection_index < self.projections.len()); - if projection_index == 0 { self.base_ty } else { self.projections[projection_index - 1].ty } - } -} - crate trait HirNode { fn hir_id(&self) -> hir::HirId; fn span(&self) -> Span;