mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Rollup merge of #73489 - sexxi-goose:init_place_refactor, r=nikomatsakis
Refactor hir::Place For the following code ```rust let c = || bar(foo.x, foo.x) ``` We generate two different `hir::Place`s for both `foo.x`. Handling this adds overhead for analysis we need to do for RFC 2229. We also want to store type information at each Projection to support analysis as part of the RFC. This resembles what we have for `mir::Place` This commit modifies the Place as follows: - Rename to `PlaceWithHirId`, where there `hir_id` is that of the expressioin. - Move any other information that describes the access out to another struct now called `Place`. - Removed `Span`, it can be accessed using the [hir API](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.span) - Modify `Projection` to be a strucutre of its own, that currently only contains the `ProjectionKind`. Adding type information to projections wil be completed as part of https://github.com/rust-lang/project-rfc-2229/issues/5 Closes https://github.com/rust-lang/project-rfc-2229/issues/3
This commit is contained in:
commit
a88182f94b
@ -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<mc::Place<'tcx>> {
|
||||
fn constrain_adjustments(
|
||||
&mut self,
|
||||
expr: &hir::Expr<'_>,
|
||||
) -> mc::McResult<mc::PlaceWithHirId<'tcx>> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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::Place<'tcx>> {
|
||||
) -> mc::McResult<mc::PlaceWithHirId<'tcx>> {
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
@ -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<T>` 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<Projection<'tcx>>,
|
||||
}
|
||||
|
||||
/// 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<Projection<'tcx>>,
|
||||
) -> 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<Item = Ty<'tcx>> + '_ {
|
||||
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<Place<'tcx>> {
|
||||
crate fn cat_expr(&self, expr: &hir::Expr<'_>) -> McResult<PlaceWithHirId<'tcx>> {
|
||||
// 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<Place<'tcx>> {
|
||||
) -> McResult<PlaceWithHirId<'tcx>> {
|
||||
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<Place<'tcx>> {
|
||||
) -> McResult<PlaceWithHirId<'tcx>> {
|
||||
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<Place<'tcx>>
|
||||
) -> McResult<PlaceWithHirId<'tcx>>
|
||||
where
|
||||
F: FnOnce() -> McResult<Place<'tcx>>,
|
||||
F: FnOnce() -> McResult<PlaceWithHirId<'tcx>>,
|
||||
{
|
||||
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<Place<'tcx>> {
|
||||
crate fn cat_expr_unadjusted(&self, expr: &hir::Expr<'_>) -> McResult<PlaceWithHirId<'tcx>> {
|
||||
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<Place<'tcx>> {
|
||||
) -> McResult<PlaceWithHirId<'tcx>> {
|
||||
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<Place<'tcx>> {
|
||||
fn cat_upvar(&self, hir_id: hir::HirId, var_id: hir::HirId) -> McResult<PlaceWithHirId<'tcx>> {
|
||||
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<N: HirNode>(
|
||||
&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<Place<'tcx>> {
|
||||
) -> McResult<PlaceWithHirId<'tcx>> {
|
||||
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<Place<'tcx>> {
|
||||
fn cat_deref(
|
||||
&self,
|
||||
node: &impl HirNode,
|
||||
base_place: PlaceWithHirId<'tcx>,
|
||||
) -> McResult<PlaceWithHirId<'tcx>> {
|
||||
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 mut projections = base_place.place.projections;
|
||||
projections.push(Projection { kind: ProjectionKind::Deref(base_ty) });
|
||||
|
||||
let ret = Place {
|
||||
hir_id: node.hir_id(),
|
||||
span: node.span(),
|
||||
ty: deref_ty,
|
||||
base: base_place.base,
|
||||
projections,
|
||||
};
|
||||
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<F>(
|
||||
&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_<F>(
|
||||
&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>(*&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 {
|
||||
|
@ -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;
|
||||
|
@ -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<HirId>,
|
||||
hir_id_high: Option<HirId>,
|
||||
span_low: Option<Span>,
|
||||
span_high: Option<Span>,
|
||||
}
|
||||
|
||||
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<Span>, Option<Span>) {
|
||||
(self.span_low, self.span_high)
|
||||
}
|
||||
@ -1579,12 +1580,13 @@ fn check_for_mutability(cx: &LateContext<'_, '_>, bound: &Expr<'_>) -> Option<Hi
|
||||
None
|
||||
}
|
||||
|
||||
fn check_for_mutation(
|
||||
cx: &LateContext<'_, '_>,
|
||||
fn check_for_mutation<'a, 'tcx> (
|
||||
cx: &LateContext<'a, 'tcx>,
|
||||
body: &Expr<'_>,
|
||||
bound_ids: &[Option<HirId>],
|
||||
) -> (Option<Span>, Option<Span>) {
|
||||
let mut delegate = MutatePairDelegate {
|
||||
cx: cx,
|
||||
hir_id_low: bound_ids[0],
|
||||
hir_id_high: bound_ids[1],
|
||||
span_low: None,
|
||||
|
@ -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>) {}
|
||||
}
|
||||
|
@ -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<FxHashSet<HirId>> {
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user