1
Fork 0

Avoid many cmt allocations.

`cmt` is a ref-counted wrapper around `cmt_` The use of refcounting
keeps `cmt` handling simple, but a lot of `cmt` instances are very
short-lived, and heap-allocating the short-lived ones takes up time.

This patch changes things in the following ways.

- Most of the functions that produced `cmt` instances now produce `cmt_`
  instances. The `Rc::new` calls that occurred within those functions
  now occur at their call sites (but only when necessary, which isn't
  that often).

- Many of the functions that took `cmt` arguments now take `&cmt_`
  arguments. This includes all the methods in the `Delegate` trait.

As a result, the vast majority of the heap allocations are avoided. In
an extreme case, the number of calls to malloc in tuple-stress drops
from 9.9M to 7.9M, a drop of 20%. And the compile times for many runs of
coercions, deep-vector, and tuple-stress drop by 1--2%.
This commit is contained in:
Nicholas Nethercote 2018-05-02 10:28:37 +10:00
parent f76f6fbdea
commit 7cf142f78b
12 changed files with 208 additions and 209 deletions

View file

@ -28,6 +28,7 @@ use ty::{self, TyCtxt, adjustment};
use hir::{self, PatKind}; use hir::{self, PatKind};
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use std::rc::Rc;
use syntax::ast; use syntax::ast;
use syntax::ptr::P; use syntax::ptr::P;
use syntax_pos::Span; use syntax_pos::Span;
@ -44,7 +45,7 @@ pub trait Delegate<'tcx> {
fn consume(&mut self, fn consume(&mut self,
consume_id: ast::NodeId, consume_id: ast::NodeId,
consume_span: Span, consume_span: Span,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
mode: ConsumeMode); mode: ConsumeMode);
// The value found at `cmt` has been determined to match the // The value found at `cmt` has been determined to match the
@ -61,14 +62,14 @@ pub trait Delegate<'tcx> {
// called on a subpart of an input passed to `matched_pat). // called on a subpart of an input passed to `matched_pat).
fn matched_pat(&mut self, fn matched_pat(&mut self,
matched_pat: &hir::Pat, matched_pat: &hir::Pat,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
mode: MatchMode); mode: MatchMode);
// The value found at `cmt` is either copied or moved via the // The value found at `cmt` is either copied or moved via the
// pattern binding `consume_pat`, depending on mode. // pattern binding `consume_pat`, depending on mode.
fn consume_pat(&mut self, fn consume_pat(&mut self,
consume_pat: &hir::Pat, consume_pat: &hir::Pat,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
mode: ConsumeMode); mode: ConsumeMode);
// The value found at `borrow` is being borrowed at the point // The value found at `borrow` is being borrowed at the point
@ -76,7 +77,7 @@ pub trait Delegate<'tcx> {
fn borrow(&mut self, fn borrow(&mut self,
borrow_id: ast::NodeId, borrow_id: ast::NodeId,
borrow_span: Span, borrow_span: Span,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
loan_region: ty::Region<'tcx>, loan_region: ty::Region<'tcx>,
bk: ty::BorrowKind, bk: ty::BorrowKind,
loan_cause: LoanCause); loan_cause: LoanCause);
@ -90,7 +91,7 @@ pub trait Delegate<'tcx> {
fn mutate(&mut self, fn mutate(&mut self,
assignment_id: ast::NodeId, assignment_id: ast::NodeId,
assignment_span: Span, assignment_span: Span,
assignee_cmt: mc::cmt<'tcx>, assignee_cmt: &mc::cmt_<'tcx>,
mode: MutateMode); mode: MutateMode);
} }
@ -316,11 +317,11 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
let fn_body_scope_r = let fn_body_scope_r =
self.tcx().mk_region(ty::ReScope(region::Scope::Node(body.value.hir_id.local_id))); self.tcx().mk_region(ty::ReScope(region::Scope::Node(body.value.hir_id.local_id)));
let arg_cmt = self.mc.cat_rvalue( let arg_cmt = Rc::new(self.mc.cat_rvalue(
arg.id, arg.id,
arg.pat.span, arg.pat.span,
fn_body_scope_r, // Args live only as long as the fn body. fn_body_scope_r, // Args live only as long as the fn body.
arg_ty); arg_ty));
self.walk_irrefutable_pat(arg_cmt, &arg.pat); self.walk_irrefutable_pat(arg_cmt, &arg.pat);
} }
@ -335,11 +336,11 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
fn delegate_consume(&mut self, fn delegate_consume(&mut self,
consume_id: ast::NodeId, consume_id: ast::NodeId,
consume_span: Span, consume_span: Span,
cmt: mc::cmt<'tcx>) { cmt: &mc::cmt_<'tcx>) {
debug!("delegate_consume(consume_id={}, cmt={:?})", debug!("delegate_consume(consume_id={}, cmt={:?})",
consume_id, cmt); consume_id, cmt);
let mode = copy_or_move(&self.mc, self.param_env, &cmt, DirectRefMove); let mode = copy_or_move(&self.mc, self.param_env, cmt, DirectRefMove);
self.delegate.consume(consume_id, consume_span, cmt, mode); self.delegate.consume(consume_id, consume_span, cmt, mode);
} }
@ -353,7 +354,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
debug!("consume_expr(expr={:?})", expr); debug!("consume_expr(expr={:?})", expr);
let cmt = return_if_err!(self.mc.cat_expr(expr)); let cmt = return_if_err!(self.mc.cat_expr(expr));
self.delegate_consume(expr.id, expr.span, cmt); self.delegate_consume(expr.id, expr.span, &cmt);
self.walk_expr(expr); self.walk_expr(expr);
} }
@ -362,7 +363,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
expr: &hir::Expr, expr: &hir::Expr,
mode: MutateMode) { mode: MutateMode) {
let cmt = return_if_err!(self.mc.cat_expr(expr)); let cmt = return_if_err!(self.mc.cat_expr(expr));
self.delegate.mutate(assignment_expr.id, assignment_expr.span, cmt, mode); self.delegate.mutate(assignment_expr.id, assignment_expr.span, &cmt, mode);
self.walk_expr(expr); self.walk_expr(expr);
} }
@ -375,7 +376,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
expr, r, bk); expr, r, bk);
let cmt = return_if_err!(self.mc.cat_expr(expr)); let cmt = return_if_err!(self.mc.cat_expr(expr));
self.delegate.borrow(expr.id, expr.span, cmt, r, bk, cause); self.delegate.borrow(expr.id, expr.span, &cmt, r, bk, cause);
self.walk_expr(expr) self.walk_expr(expr)
} }
@ -435,7 +436,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
} }
hir::ExprMatch(ref discr, ref arms, _) => { hir::ExprMatch(ref discr, ref arms, _) => {
let discr_cmt = return_if_err!(self.mc.cat_expr(&discr)); let discr_cmt = Rc::new(return_if_err!(self.mc.cat_expr(&discr)));
let r = self.tcx().types.re_empty; let r = self.tcx().types.re_empty;
self.borrow_expr(&discr, r, ty::ImmBorrow, MatchDiscriminant); self.borrow_expr(&discr, r, ty::ImmBorrow, MatchDiscriminant);
@ -619,7 +620,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
// "assigns", which is handled by // "assigns", which is handled by
// `walk_pat`: // `walk_pat`:
self.walk_expr(&expr); self.walk_expr(&expr);
let init_cmt = return_if_err!(self.mc.cat_expr(&expr)); let init_cmt = Rc::new(return_if_err!(self.mc.cat_expr(&expr)));
self.walk_irrefutable_pat(init_cmt, &local.pat); self.walk_irrefutable_pat(init_cmt, &local.pat);
} }
} }
@ -652,7 +653,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
None => { return; } None => { return; }
}; };
let with_cmt = return_if_err!(self.mc.cat_expr(&with_expr)); let with_cmt = Rc::new(return_if_err!(self.mc.cat_expr(&with_expr)));
// Select just those fields of the `with` // Select just those fields of the `with`
// expression that will actually be used // expression that will actually be used
@ -671,7 +672,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
with_field.name, with_field.name,
with_field.ty(self.tcx(), substs) with_field.ty(self.tcx(), substs)
); );
self.delegate_consume(with_expr.id, with_expr.span, cmt_field); self.delegate_consume(with_expr.id, with_expr.span, &cmt_field);
} }
} }
} }
@ -710,7 +711,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
adjustment::Adjust::Unsize => { adjustment::Adjust::Unsize => {
// Creating a closure/fn-pointer or unsizing consumes // Creating a closure/fn-pointer or unsizing consumes
// the input and stores it into the resulting rvalue. // the input and stores it into the resulting rvalue.
self.delegate_consume(expr.id, expr.span, cmt.clone()); self.delegate_consume(expr.id, expr.span, &cmt);
} }
adjustment::Adjust::Deref(None) => {} adjustment::Adjust::Deref(None) => {}
@ -722,12 +723,11 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
// this is an autoref of `x`. // this is an autoref of `x`.
adjustment::Adjust::Deref(Some(ref deref)) => { adjustment::Adjust::Deref(Some(ref deref)) => {
let bk = ty::BorrowKind::from_mutbl(deref.mutbl); let bk = ty::BorrowKind::from_mutbl(deref.mutbl);
self.delegate.borrow(expr.id, expr.span, cmt.clone(), self.delegate.borrow(expr.id, expr.span, &cmt, deref.region, bk, AutoRef);
deref.region, bk, AutoRef);
} }
adjustment::Adjust::Borrow(ref autoref) => { adjustment::Adjust::Borrow(ref autoref) => {
self.walk_autoref(expr, cmt.clone(), autoref); self.walk_autoref(expr, &cmt, autoref);
} }
} }
cmt = return_if_err!(self.mc.cat_expr_adjusted(expr, cmt, &adjustment)); cmt = return_if_err!(self.mc.cat_expr_adjusted(expr, cmt, &adjustment));
@ -739,7 +739,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
/// after all relevant autoderefs have occurred. /// after all relevant autoderefs have occurred.
fn walk_autoref(&mut self, fn walk_autoref(&mut self,
expr: &hir::Expr, expr: &hir::Expr,
cmt_base: mc::cmt<'tcx>, cmt_base: &mc::cmt_<'tcx>,
autoref: &adjustment::AutoBorrow<'tcx>) { autoref: &adjustment::AutoBorrow<'tcx>) {
debug!("walk_autoref(expr.id={} cmt_base={:?} autoref={:?})", debug!("walk_autoref(expr.id={} cmt_base={:?} autoref={:?})",
expr.id, expr.id,
@ -852,7 +852,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
// Each match binding is effectively an assignment to the // Each match binding is effectively an assignment to the
// binding being produced. // binding being produced.
let def = Def::Local(canonical_id); let def = Def::Local(canonical_id);
if let Ok(binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty, def) { if let Ok(ref binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty, def) {
delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init); delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init);
} }
@ -861,13 +861,13 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
ty::BindByReference(m) => { ty::BindByReference(m) => {
if let ty::TyRef(r, _) = pat_ty.sty { if let ty::TyRef(r, _) = pat_ty.sty {
let bk = ty::BorrowKind::from_mutbl(m); let bk = ty::BorrowKind::from_mutbl(m);
delegate.borrow(pat.id, pat.span, cmt_pat, r, bk, RefBinding); delegate.borrow(pat.id, pat.span, &cmt_pat, r, bk, RefBinding);
} }
} }
ty::BindByValue(..) => { ty::BindByValue(..) => {
let mode = copy_or_move(mc, param_env, &cmt_pat, PatBindingMove); let mode = copy_or_move(mc, param_env, &cmt_pat, PatBindingMove);
debug!("walk_pat binding consuming pat"); debug!("walk_pat binding consuming pat");
delegate.consume_pat(pat, cmt_pat, mode); delegate.consume_pat(pat, &cmt_pat, mode);
} }
} }
} }
@ -891,12 +891,12 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did); let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did);
debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat); debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat);
delegate.matched_pat(pat, downcast_cmt, match_mode); delegate.matched_pat(pat, &downcast_cmt, match_mode);
} }
Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) | Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => { Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => {
debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat); debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat);
delegate.matched_pat(pat, cmt_pat, match_mode); delegate.matched_pat(pat, &cmt_pat, match_mode);
} }
_ => {} _ => {}
} }
@ -924,12 +924,12 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
self.param_env, self.param_env,
&cmt_var, &cmt_var,
CaptureMove); CaptureMove);
self.delegate.consume(closure_expr.id, freevar.span, cmt_var, mode); self.delegate.consume(closure_expr.id, freevar.span, &cmt_var, mode);
} }
ty::UpvarCapture::ByRef(upvar_borrow) => { ty::UpvarCapture::ByRef(upvar_borrow) => {
self.delegate.borrow(closure_expr.id, self.delegate.borrow(closure_expr.id,
fn_decl_span, fn_decl_span,
cmt_var, &cmt_var,
upvar_borrow.region, upvar_borrow.region,
upvar_borrow.kind, upvar_borrow.kind,
ClosureCapture(freevar.span)); ClosureCapture(freevar.span));
@ -943,7 +943,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
closure_id: ast::NodeId, closure_id: ast::NodeId,
closure_span: Span, closure_span: Span,
upvar: &hir::Freevar) upvar: &hir::Freevar)
-> mc::McResult<mc::cmt<'tcx>> { -> mc::McResult<mc::cmt_<'tcx>> {
// Create the cmt for the variable being borrowed, from the // Create the cmt for the variable being borrowed, from the
// caller's perspective // caller's perspective
let var_hir_id = self.tcx().hir.node_to_hir_id(upvar.var_id()); let var_hir_id = self.tcx().hir.node_to_hir_id(upvar.var_id());
@ -954,7 +954,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
fn copy_or_move<'a, 'gcx, 'tcx>(mc: &mc::MemCategorizationContext<'a, 'gcx, 'tcx>, fn copy_or_move<'a, 'gcx, 'tcx>(mc: &mc::MemCategorizationContext<'a, 'gcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
cmt: &mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
move_reason: MoveReason) move_reason: MoveReason)
-> ConsumeMode -> ConsumeMode
{ {

View file

@ -572,13 +572,13 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
Ok(ret_ty) Ok(ret_ty)
} }
pub fn cat_expr(&self, expr: &hir::Expr) -> McResult<cmt<'tcx>> { pub fn cat_expr(&self, expr: &hir::Expr) -> McResult<cmt_<'tcx>> {
// This recursion helper avoids going through *too many* // This recursion helper avoids going through *too many*
// adjustments, since *only* non-overloaded deref recurses. // adjustments, since *only* non-overloaded deref recurses.
fn helper<'a, 'gcx, 'tcx>(mc: &MemCategorizationContext<'a, 'gcx, 'tcx>, fn helper<'a, 'gcx, 'tcx>(mc: &MemCategorizationContext<'a, 'gcx, 'tcx>,
expr: &hir::Expr, expr: &hir::Expr,
adjustments: &[adjustment::Adjustment<'tcx>]) adjustments: &[adjustment::Adjustment<'tcx>])
-> McResult<cmt<'tcx>> { -> McResult<cmt_<'tcx>> {
match adjustments.split_last() { match adjustments.split_last() {
None => mc.cat_expr_unadjusted(expr), None => mc.cat_expr_unadjusted(expr),
Some((adjustment, previous)) => { Some((adjustment, previous)) => {
@ -591,24 +591,24 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
} }
pub fn cat_expr_adjusted(&self, expr: &hir::Expr, pub fn cat_expr_adjusted(&self, expr: &hir::Expr,
previous: cmt<'tcx>, previous: cmt_<'tcx>,
adjustment: &adjustment::Adjustment<'tcx>) adjustment: &adjustment::Adjustment<'tcx>)
-> McResult<cmt<'tcx>> { -> McResult<cmt_<'tcx>> {
self.cat_expr_adjusted_with(expr, || Ok(previous), adjustment) self.cat_expr_adjusted_with(expr, || Ok(previous), adjustment)
} }
fn cat_expr_adjusted_with<F>(&self, expr: &hir::Expr, fn cat_expr_adjusted_with<F>(&self, expr: &hir::Expr,
previous: F, previous: F,
adjustment: &adjustment::Adjustment<'tcx>) adjustment: &adjustment::Adjustment<'tcx>)
-> McResult<cmt<'tcx>> -> McResult<cmt_<'tcx>>
where F: FnOnce() -> McResult<cmt<'tcx>> where F: FnOnce() -> McResult<cmt_<'tcx>>
{ {
debug!("cat_expr_adjusted_with({:?}): {:?}", adjustment, expr); debug!("cat_expr_adjusted_with({:?}): {:?}", adjustment, expr);
let target = self.resolve_type_vars_if_possible(&adjustment.target); let target = self.resolve_type_vars_if_possible(&adjustment.target);
match adjustment.kind { match adjustment.kind {
adjustment::Adjust::Deref(overloaded) => { adjustment::Adjust::Deref(overloaded) => {
// Equivalent to *expr or something similar. // Equivalent to *expr or something similar.
let base = if let Some(deref) = overloaded { let base = Rc::new(if let Some(deref) = overloaded {
let ref_ty = self.tcx.mk_ref(deref.region, ty::TypeAndMut { let ref_ty = self.tcx.mk_ref(deref.region, ty::TypeAndMut {
ty: target, ty: target,
mutbl: deref.mutbl, mutbl: deref.mutbl,
@ -616,7 +616,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
self.cat_rvalue_node(expr.id, expr.span, ref_ty) self.cat_rvalue_node(expr.id, expr.span, ref_ty)
} else { } else {
previous()? previous()?
}; });
self.cat_deref(expr, base, false) self.cat_deref(expr, base, false)
} }
@ -633,7 +633,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
} }
} }
pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult<cmt<'tcx>> { pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult<cmt_<'tcx>> {
debug!("cat_expr: id={} expr={:?}", expr.id, expr); debug!("cat_expr: id={} expr={:?}", expr.id, expr);
let expr_ty = self.expr_ty(expr)?; let expr_ty = self.expr_ty(expr)?;
@ -642,13 +642,13 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
if self.tables.is_method_call(expr) { if self.tables.is_method_call(expr) {
self.cat_overloaded_place(expr, e_base, false) self.cat_overloaded_place(expr, e_base, false)
} else { } else {
let base_cmt = self.cat_expr(&e_base)?; let base_cmt = Rc::new(self.cat_expr(&e_base)?);
self.cat_deref(expr, base_cmt, false) self.cat_deref(expr, base_cmt, false)
} }
} }
hir::ExprField(ref base, f_name) => { hir::ExprField(ref base, f_name) => {
let base_cmt = self.cat_expr(&base)?; let base_cmt = Rc::new(self.cat_expr(&base)?);
debug!("cat_expr(cat_field): id={} expr={:?} base={:?}", debug!("cat_expr(cat_field): id={} expr={:?} base={:?}",
expr.id, expr.id,
expr, expr,
@ -666,7 +666,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
// dereferencing. // dereferencing.
self.cat_overloaded_place(expr, base, true) self.cat_overloaded_place(expr, base, true)
} else { } else {
let base_cmt = self.cat_expr(&base)?; let base_cmt = Rc::new(self.cat_expr(&base)?);
self.cat_index(expr, base_cmt, expr_ty, InteriorOffsetKind::Index) self.cat_index(expr, base_cmt, expr_ty, InteriorOffsetKind::Index)
} }
} }
@ -701,7 +701,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
span: Span, span: Span,
expr_ty: Ty<'tcx>, expr_ty: Ty<'tcx>,
def: Def) def: Def)
-> McResult<cmt<'tcx>> { -> McResult<cmt_<'tcx>> {
debug!("cat_def: id={} expr={:?} def={:?}", debug!("cat_def: id={} expr={:?} def={:?}",
id, expr_ty, def); id, expr_ty, def);
@ -718,14 +718,14 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
return Ok(self.cat_rvalue_node(id, span, expr_ty)); return Ok(self.cat_rvalue_node(id, span, expr_ty));
} }
} }
Ok(Rc::new(cmt_ { Ok(cmt_ {
id:id, id:id,
span:span, span:span,
cat:Categorization::StaticItem, cat:Categorization::StaticItem,
mutbl: if mutbl { McDeclared } else { McImmutable}, mutbl: if mutbl { McDeclared } else { McImmutable},
ty:expr_ty, ty:expr_ty,
note: NoteNone note: NoteNone
})) })
} }
Def::Upvar(var_id, _, fn_node_id) => { Def::Upvar(var_id, _, fn_node_id) => {
@ -733,14 +733,14 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
} }
Def::Local(vid) => { Def::Local(vid) => {
Ok(Rc::new(cmt_ { Ok(cmt_ {
id, id,
span, span,
cat: Categorization::Local(vid), cat: Categorization::Local(vid),
mutbl: MutabilityCategory::from_local(self.tcx, self.tables, vid), mutbl: MutabilityCategory::from_local(self.tcx, self.tables, vid),
ty: expr_ty, ty: expr_ty,
note: NoteNone note: NoteNone
})) })
} }
def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def) def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def)
@ -754,7 +754,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
span: Span, span: Span,
var_id: ast::NodeId, var_id: ast::NodeId,
fn_node_id: ast::NodeId) fn_node_id: ast::NodeId)
-> McResult<cmt<'tcx>> -> McResult<cmt_<'tcx>>
{ {
let fn_hir_id = self.tcx.hir.node_to_hir_id(fn_node_id); let fn_hir_id = self.tcx.hir.node_to_hir_id(fn_node_id);
@ -861,7 +861,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
} }
}; };
let ret = Rc::new(cmt_result); let ret = cmt_result;
debug!("cat_upvar ret={:?}", ret); debug!("cat_upvar ret={:?}", ret);
Ok(ret) Ok(ret)
} }
@ -938,7 +938,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
id: ast::NodeId, id: ast::NodeId,
span: Span, span: Span,
expr_ty: Ty<'tcx>) expr_ty: Ty<'tcx>)
-> cmt<'tcx> { -> cmt_<'tcx> {
let hir_id = self.tcx.hir.node_to_hir_id(id); let hir_id = self.tcx.hir.node_to_hir_id(id);
let promotable = self.rvalue_promotable_map.as_ref().map(|m| m.contains(&hir_id.local_id)) let promotable = self.rvalue_promotable_map.as_ref().map(|m| m.contains(&hir_id.local_id))
.unwrap_or(false); .unwrap_or(false);
@ -966,15 +966,15 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
cmt_id: ast::NodeId, cmt_id: ast::NodeId,
span: Span, span: Span,
temp_scope: ty::Region<'tcx>, temp_scope: ty::Region<'tcx>,
expr_ty: Ty<'tcx>) -> cmt<'tcx> { expr_ty: Ty<'tcx>) -> cmt_<'tcx> {
let ret = Rc::new(cmt_ { let ret = cmt_ {
id:cmt_id, id:cmt_id,
span:span, span:span,
cat:Categorization::Rvalue(temp_scope), cat:Categorization::Rvalue(temp_scope),
mutbl:McDeclared, mutbl:McDeclared,
ty:expr_ty, ty:expr_ty,
note: NoteNone note: NoteNone
}); };
debug!("cat_rvalue ret {:?}", ret); debug!("cat_rvalue ret {:?}", ret);
ret ret
} }
@ -985,15 +985,15 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
f_index: usize, f_index: usize,
f_name: Name, f_name: Name,
f_ty: Ty<'tcx>) f_ty: Ty<'tcx>)
-> cmt<'tcx> { -> cmt_<'tcx> {
let ret = Rc::new(cmt_ { let ret = cmt_ {
id: node.id(), id: node.id(),
span: node.span(), span: node.span(),
mutbl: base_cmt.mutbl.inherit(), mutbl: base_cmt.mutbl.inherit(),
cat: Categorization::Interior(base_cmt, InteriorField(FieldIndex(f_index, f_name))), cat: Categorization::Interior(base_cmt, InteriorField(FieldIndex(f_index, f_name))),
ty: f_ty, ty: f_ty,
note: NoteNone note: NoteNone
}); };
debug!("cat_field ret {:?}", ret); debug!("cat_field ret {:?}", ret);
ret ret
} }
@ -1002,7 +1002,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
expr: &hir::Expr, expr: &hir::Expr,
base: &hir::Expr, base: &hir::Expr,
implicit: bool) implicit: bool)
-> McResult<cmt<'tcx>> { -> McResult<cmt_<'tcx>> {
debug!("cat_overloaded_place: implicit={}", implicit); debug!("cat_overloaded_place: implicit={}", implicit);
// Reconstruct the output assuming it's a reference with the // Reconstruct the output assuming it's a reference with the
@ -1022,7 +1022,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
mutbl, mutbl,
}); });
let base_cmt = self.cat_rvalue_node(expr.id, expr.span, ref_ty); let base_cmt = Rc::new(self.cat_rvalue_node(expr.id, expr.span, ref_ty));
self.cat_deref(expr, base_cmt, implicit) self.cat_deref(expr, base_cmt, implicit)
} }
@ -1030,7 +1030,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
node: &N, node: &N,
base_cmt: cmt<'tcx>, base_cmt: cmt<'tcx>,
implicit: bool) implicit: bool)
-> McResult<cmt<'tcx>> { -> McResult<cmt_<'tcx>> {
debug!("cat_deref: base_cmt={:?}", base_cmt); debug!("cat_deref: base_cmt={:?}", base_cmt);
let base_cmt_ty = base_cmt.ty; let base_cmt_ty = base_cmt.ty;
@ -1052,7 +1052,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
} }
ref ty => bug!("unexpected type in cat_deref: {:?}", ty) ref ty => bug!("unexpected type in cat_deref: {:?}", ty)
}; };
let ret = Rc::new(cmt_ { let ret = cmt_ {
id: node.id(), id: node.id(),
span: node.span(), span: node.span(),
// For unique ptrs, we inherit mutability from the owning reference. // For unique ptrs, we inherit mutability from the owning reference.
@ -1060,7 +1060,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
cat: Categorization::Deref(base_cmt, ptr), cat: Categorization::Deref(base_cmt, ptr),
ty: deref_ty, ty: deref_ty,
note: NoteNone note: NoteNone
}); };
debug!("cat_deref ret {:?}", ret); debug!("cat_deref ret {:?}", ret);
Ok(ret) Ok(ret)
} }
@ -1070,7 +1070,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
base_cmt: cmt<'tcx>, base_cmt: cmt<'tcx>,
element_ty: Ty<'tcx>, element_ty: Ty<'tcx>,
context: InteriorOffsetKind) context: InteriorOffsetKind)
-> McResult<cmt<'tcx>> { -> McResult<cmt_<'tcx>> {
//! Creates a cmt for an indexing operation (`[]`). //! Creates a cmt for an indexing operation (`[]`).
//! //!
//! One subtle aspect of indexing that may not be //! One subtle aspect of indexing that may not be
@ -1089,8 +1089,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
//! - `base_cmt`: the cmt of `elt` //! - `base_cmt`: the cmt of `elt`
let interior_elem = InteriorElement(context); let interior_elem = InteriorElement(context);
let ret = let ret = self.cat_imm_interior(elt, base_cmt, element_ty, interior_elem);
self.cat_imm_interior(elt, base_cmt, element_ty, interior_elem);
debug!("cat_index ret {:?}", ret); debug!("cat_index ret {:?}", ret);
return Ok(ret); return Ok(ret);
} }
@ -1100,15 +1099,15 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
base_cmt: cmt<'tcx>, base_cmt: cmt<'tcx>,
interior_ty: Ty<'tcx>, interior_ty: Ty<'tcx>,
interior: InteriorKind) interior: InteriorKind)
-> cmt<'tcx> { -> cmt_<'tcx> {
let ret = Rc::new(cmt_ { let ret = cmt_ {
id: node.id(), id: node.id(),
span: node.span(), span: node.span(),
mutbl: base_cmt.mutbl.inherit(), mutbl: base_cmt.mutbl.inherit(),
cat: Categorization::Interior(base_cmt, interior), cat: Categorization::Interior(base_cmt, interior),
ty: interior_ty, ty: interior_ty,
note: NoteNone note: NoteNone
}); };
debug!("cat_imm_interior ret={:?}", ret); debug!("cat_imm_interior ret={:?}", ret);
ret ret
} }
@ -1232,7 +1231,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
.get(pat.hir_id) .get(pat.hir_id)
.map(|v| v.len()) .map(|v| v.len())
.unwrap_or(0) { .unwrap_or(0) {
cmt = self.cat_deref(pat, cmt, true /* implicit */)?; cmt = Rc::new(self.cat_deref(pat, cmt, true /* implicit */)?);
} }
let cmt = cmt; // lose mutability let cmt = cmt; // lose mutability
@ -1279,7 +1278,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) { for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
let subpat_ty = self.pat_ty(&subpat)?; // see (*2) let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string()))); let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string())));
let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior); let subcmt = Rc::new(self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior));
self.cat_pattern_(subcmt, &subpat, op)?; self.cat_pattern_(subcmt, &subpat, op)?;
} }
} }
@ -1302,7 +1301,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
for fp in field_pats { for fp in field_pats {
let field_ty = self.pat_ty(&fp.node.pat)?; // see (*2) let field_ty = self.pat_ty(&fp.node.pat)?; // see (*2)
let f_index = self.tcx.field_index(fp.node.id, self.tables); let f_index = self.tcx.field_index(fp.node.id, self.tables);
let cmt_field = self.cat_field(pat, cmt.clone(), f_index, fp.node.name, field_ty); let cmt_field =
Rc::new(self.cat_field(pat, cmt.clone(), f_index, fp.node.name, field_ty));
self.cat_pattern_(cmt_field, &fp.node.pat, op)?; self.cat_pattern_(cmt_field, &fp.node.pat, op)?;
} }
} }
@ -1320,7 +1320,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) { for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
let subpat_ty = self.pat_ty(&subpat)?; // see (*2) let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string()))); let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string())));
let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior); let subcmt = Rc::new(self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior));
self.cat_pattern_(subcmt, &subpat, op)?; self.cat_pattern_(subcmt, &subpat, op)?;
} }
} }
@ -1329,7 +1329,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
// box p1, &p1, &mut p1. we can ignore the mutability of // box p1, &p1, &mut p1. we can ignore the mutability of
// PatKind::Ref since that information is already contained // PatKind::Ref since that information is already contained
// in the type. // in the type.
let subcmt = self.cat_deref(pat, cmt, false)?; let subcmt = Rc::new(self.cat_deref(pat, cmt, false)?);
self.cat_pattern_(subcmt, &subpat, op)?; self.cat_pattern_(subcmt, &subpat, op)?;
} }
@ -1342,7 +1342,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
} }
}; };
let context = InteriorOffsetKind::Pattern; let context = InteriorOffsetKind::Pattern;
let elt_cmt = self.cat_index(pat, cmt, element_ty, context)?; let elt_cmt = Rc::new(self.cat_index(pat, cmt, element_ty, context)?);
for before_pat in before { for before_pat in before {
self.cat_pattern_(elt_cmt.clone(), &before_pat, op)?; self.cat_pattern_(elt_cmt.clone(), &before_pat, op)?;
} }
@ -1379,7 +1379,7 @@ pub enum AliasableReason {
} }
impl<'tcx> cmt_<'tcx> { impl<'tcx> cmt_<'tcx> {
pub fn guarantor(&self) -> cmt<'tcx> { pub fn guarantor(&self) -> cmt_<'tcx> {
//! Returns `self` after stripping away any derefs or //! Returns `self` after stripping away any derefs or
//! interior content. The return value is basically the `cmt` which //! interior content. The return value is basically the `cmt` which
//! determines how long the value in `self` remains live. //! determines how long the value in `self` remains live.
@ -1392,7 +1392,7 @@ impl<'tcx> cmt_<'tcx> {
Categorization::Deref(_, BorrowedPtr(..)) | Categorization::Deref(_, BorrowedPtr(..)) |
Categorization::Deref(_, Implicit(..)) | Categorization::Deref(_, Implicit(..)) |
Categorization::Upvar(..) => { Categorization::Upvar(..) => {
Rc::new((*self).clone()) (*self).clone()
} }
Categorization::Downcast(ref b, _) | Categorization::Downcast(ref b, _) |
Categorization::Interior(ref b, _) | Categorization::Interior(ref b, _) |
@ -1442,16 +1442,17 @@ impl<'tcx> cmt_<'tcx> {
} }
} }
// Digs down through one or two layers of deref and grabs the cmt // Digs down through one or two layers of deref and grabs the
// for the upvar if a note indicates there is one. // Categorization of the cmt for the upvar if a note indicates there is
pub fn upvar(&self) -> Option<cmt<'tcx>> { // one.
pub fn upvar_cat(&self) -> Option<&Categorization<'tcx>> {
match self.note { match self.note {
NoteClosureEnv(..) | NoteUpvarRef(..) => { NoteClosureEnv(..) | NoteUpvarRef(..) => {
Some(match self.cat { Some(match self.cat {
Categorization::Deref(ref inner, _) => { Categorization::Deref(ref inner, _) => {
match inner.cat { match inner.cat {
Categorization::Deref(ref inner, _) => inner.clone(), Categorization::Deref(ref inner, _) => &inner.cat,
Categorization::Upvar(..) => inner.clone(), Categorization::Upvar(..) => &inner.cat,
_ => bug!() _ => bug!()
} }
} }
@ -1462,7 +1463,6 @@ impl<'tcx> cmt_<'tcx> {
} }
} }
pub fn descriptive_string(&self, tcx: TyCtxt) -> String { pub fn descriptive_string(&self, tcx: TyCtxt) -> String {
match self.cat { match self.cat {
Categorization::StaticItem => { Categorization::StaticItem => {
@ -1479,8 +1479,7 @@ impl<'tcx> cmt_<'tcx> {
} }
} }
Categorization::Deref(_, pk) => { Categorization::Deref(_, pk) => {
let upvar = self.upvar(); match self.upvar_cat() {
match upvar.as_ref().map(|i| &i.cat) {
Some(&Categorization::Upvar(ref var)) => { Some(&Categorization::Upvar(ref var)) => {
var.to_string() var.to_string()
} }

View file

@ -99,7 +99,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
fn consume(&mut self, fn consume(&mut self,
consume_id: ast::NodeId, consume_id: ast::NodeId,
consume_span: Span, consume_span: Span,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
mode: euv::ConsumeMode) { mode: euv::ConsumeMode) {
debug!("consume(consume_id={}, cmt={:?}, mode={:?})", debug!("consume(consume_id={}, cmt={:?}, mode={:?})",
consume_id, cmt, mode); consume_id, cmt, mode);
@ -110,12 +110,12 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
fn matched_pat(&mut self, fn matched_pat(&mut self,
_matched_pat: &hir::Pat, _matched_pat: &hir::Pat,
_cmt: mc::cmt, _cmt: &mc::cmt_,
_mode: euv::MatchMode) { } _mode: euv::MatchMode) { }
fn consume_pat(&mut self, fn consume_pat(&mut self,
consume_pat: &hir::Pat, consume_pat: &hir::Pat,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
mode: euv::ConsumeMode) { mode: euv::ConsumeMode) {
debug!("consume_pat(consume_pat={:?}, cmt={:?}, mode={:?})", debug!("consume_pat(consume_pat={:?}, cmt={:?}, mode={:?})",
consume_pat, consume_pat,
@ -128,7 +128,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
fn borrow(&mut self, fn borrow(&mut self,
borrow_id: ast::NodeId, borrow_id: ast::NodeId,
borrow_span: Span, borrow_span: Span,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
loan_region: ty::Region<'tcx>, loan_region: ty::Region<'tcx>,
bk: ty::BorrowKind, bk: ty::BorrowKind,
loan_cause: euv::LoanCause) loan_cause: euv::LoanCause)
@ -139,7 +139,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
bk, loan_cause); bk, loan_cause);
let hir_id = self.tcx().hir.node_to_hir_id(borrow_id); let hir_id = self.tcx().hir.node_to_hir_id(borrow_id);
if let Some(lp) = opt_loan_path(&cmt) { if let Some(lp) = opt_loan_path(cmt) {
let moved_value_use_kind = match loan_cause { let moved_value_use_kind = match loan_cause {
euv::ClosureCapture(_) => MovedInCapture, euv::ClosureCapture(_) => MovedInCapture,
_ => MovedInUse, _ => MovedInUse,
@ -155,13 +155,13 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
fn mutate(&mut self, fn mutate(&mut self,
assignment_id: ast::NodeId, assignment_id: ast::NodeId,
assignment_span: Span, assignment_span: Span,
assignee_cmt: mc::cmt<'tcx>, assignee_cmt: &mc::cmt_<'tcx>,
mode: euv::MutateMode) mode: euv::MutateMode)
{ {
debug!("mutate(assignment_id={}, assignee_cmt={:?})", debug!("mutate(assignment_id={}, assignee_cmt={:?})",
assignment_id, assignee_cmt); assignment_id, assignee_cmt);
if let Some(lp) = opt_loan_path(&assignee_cmt) { if let Some(lp) = opt_loan_path(assignee_cmt) {
match mode { match mode {
MutateMode::Init | MutateMode::JustWrite => { MutateMode::Init | MutateMode::JustWrite => {
// In a case like `path = 1`, then path does not // In a case like `path = 1`, then path does not
@ -363,10 +363,10 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
} }
pub fn check_for_loans_across_yields(&self, pub fn check_for_loans_across_yields(&self,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
loan_region: ty::Region<'tcx>, loan_region: ty::Region<'tcx>,
borrow_span: Span) { borrow_span: Span) {
pub fn borrow_of_local_data<'tcx>(cmt: &mc::cmt<'tcx>) -> bool { pub fn borrow_of_local_data<'tcx>(cmt: &mc::cmt_<'tcx>) -> bool {
match cmt.cat { match cmt.cat {
// Borrows of static items is allowed // Borrows of static items is allowed
Categorization::StaticItem => false, Categorization::StaticItem => false,
@ -401,7 +401,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
return; return;
} }
if !borrow_of_local_data(&cmt) { if !borrow_of_local_data(cmt) {
return; return;
} }
@ -649,9 +649,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
fn consume_common(&self, fn consume_common(&self,
id: hir::ItemLocalId, id: hir::ItemLocalId,
span: Span, span: Span,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
mode: euv::ConsumeMode) { mode: euv::ConsumeMode) {
if let Some(lp) = opt_loan_path(&cmt) { if let Some(lp) = opt_loan_path(cmt) {
let moved_value_use_kind = match mode { let moved_value_use_kind = match mode {
euv::Copy => { euv::Copy => {
self.check_for_copy_of_frozen_path(id, span, &lp); self.check_for_copy_of_frozen_path(id, span, &lp);
@ -876,11 +876,11 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
fn check_assignment(&self, fn check_assignment(&self,
assignment_id: hir::ItemLocalId, assignment_id: hir::ItemLocalId,
assignment_span: Span, assignment_span: Span,
assignee_cmt: mc::cmt<'tcx>) { assignee_cmt: &mc::cmt_<'tcx>) {
debug!("check_assignment(assignee_cmt={:?})", assignee_cmt); debug!("check_assignment(assignee_cmt={:?})", assignee_cmt);
// Check that we don't invalidate any outstanding loans // Check that we don't invalidate any outstanding loans
if let Some(loan_path) = opt_loan_path(&assignee_cmt) { if let Some(loan_path) = opt_loan_path(assignee_cmt) {
let scope = region::Scope::Node(assignment_id); let scope = region::Scope::Node(assignment_id);
self.each_in_scope_loan_affecting_path(scope, &loan_path, |loan| { self.each_in_scope_loan_affecting_path(scope, &loan_path, |loan| {
self.report_illegal_mutation(assignment_span, &loan_path, loan); self.report_illegal_mutation(assignment_span, &loan_path, loan);
@ -892,7 +892,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
// needs to be done here instead of in check_loans because we // needs to be done here instead of in check_loans because we
// depend on move data. // depend on move data.
if let Categorization::Local(local_id) = assignee_cmt.cat { if let Categorization::Local(local_id) = assignee_cmt.cat {
let lp = opt_loan_path(&assignee_cmt).unwrap(); let lp = opt_loan_path(assignee_cmt).unwrap();
self.move_data.each_assignment_of(assignment_id, &lp, |assign| { self.move_data.each_assignment_of(assignment_id, &lp, |assign| {
if assignee_cmt.mutbl.is_mutable() { if assignee_cmt.mutbl.is_mutable() {
let hir_id = self.bccx.tcx.hir.node_to_hir_id(local_id); let hir_id = self.bccx.tcx.hir.node_to_hir_id(local_id);

View file

@ -26,10 +26,10 @@ use syntax_pos::Span;
use rustc::hir::*; use rustc::hir::*;
use rustc::hir::map::Node::*; use rustc::hir::map::Node::*;
struct GatherMoveInfo<'tcx> { struct GatherMoveInfo<'c, 'tcx: 'c> {
id: hir::ItemLocalId, id: hir::ItemLocalId,
kind: MoveKind, kind: MoveKind,
cmt: mc::cmt<'tcx>, cmt: &'c mc::cmt_<'tcx>,
span_path_opt: Option<MovePlace<'tcx>> span_path_opt: Option<MovePlace<'tcx>>
} }
@ -87,7 +87,7 @@ pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
move_error_collector: &mut MoveErrorCollector<'tcx>, move_error_collector: &mut MoveErrorCollector<'tcx>,
move_expr_id: hir::ItemLocalId, move_expr_id: hir::ItemLocalId,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
move_reason: euv::MoveReason) { move_reason: euv::MoveReason) {
let kind = match move_reason { let kind = match move_reason {
euv::DirectRefMove | euv::PatBindingMove => MoveExpr, euv::DirectRefMove | euv::PatBindingMove => MoveExpr,
@ -102,11 +102,11 @@ pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
gather_move(bccx, move_data, move_error_collector, move_info); gather_move(bccx, move_data, move_error_collector, move_info);
} }
pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, pub fn gather_move_from_pat<'a, 'c, 'tcx: 'c>(bccx: &BorrowckCtxt<'a, 'tcx>,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
move_error_collector: &mut MoveErrorCollector<'tcx>, move_error_collector: &mut MoveErrorCollector<'tcx>,
move_pat: &hir::Pat, move_pat: &hir::Pat,
cmt: mc::cmt<'tcx>) { cmt: &'c mc::cmt_<'tcx>) {
let source = get_pattern_source(bccx.tcx,move_pat); let source = get_pattern_source(bccx.tcx,move_pat);
let pat_span_path_opt = match move_pat.node { let pat_span_path_opt = match move_pat.node {
PatKind::Binding(_, _, ref path1, _) => { PatKind::Binding(_, _, ref path1, _) => {
@ -132,18 +132,17 @@ pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
gather_move(bccx, move_data, move_error_collector, move_info); gather_move(bccx, move_data, move_error_collector, move_info);
} }
fn gather_move<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, fn gather_move<'a, 'c, 'tcx: 'c>(bccx: &BorrowckCtxt<'a, 'tcx>,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
move_error_collector: &mut MoveErrorCollector<'tcx>, move_error_collector: &mut MoveErrorCollector<'tcx>,
move_info: GatherMoveInfo<'tcx>) { move_info: GatherMoveInfo<'c, 'tcx>) {
debug!("gather_move(move_id={:?}, cmt={:?})", debug!("gather_move(move_id={:?}, cmt={:?})",
move_info.id, move_info.cmt); move_info.id, move_info.cmt);
let potentially_illegal_move = let potentially_illegal_move = check_and_get_illegal_move_origin(bccx, move_info.cmt);
check_and_get_illegal_move_origin(bccx, &move_info.cmt);
if let Some(illegal_move_origin) = potentially_illegal_move { if let Some(illegal_move_origin) = potentially_illegal_move {
debug!("illegal_move_origin={:?}", illegal_move_origin); debug!("illegal_move_origin={:?}", illegal_move_origin);
let error = MoveError::with_move_info(illegal_move_origin, let error = MoveError::with_move_info(Rc::new(illegal_move_origin),
move_info.span_path_opt); move_info.span_path_opt);
move_error_collector.add_error(error); move_error_collector.add_error(error);
return; return;
@ -177,8 +176,8 @@ pub fn gather_assignment<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
// (keep in sync with move_error::report_cannot_move_out_of ) // (keep in sync with move_error::report_cannot_move_out_of )
fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
cmt: &mc::cmt<'tcx>) cmt: &mc::cmt_<'tcx>)
-> Option<mc::cmt<'tcx>> { -> Option<mc::cmt_<'tcx>> {
match cmt.cat { match cmt.cat {
Categorization::Deref(_, mc::BorrowedPtr(..)) | Categorization::Deref(_, mc::BorrowedPtr(..)) |
Categorization::Deref(_, mc::Implicit(..)) | Categorization::Deref(_, mc::Implicit(..)) |

View file

@ -27,7 +27,7 @@ pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
item_scope: region::Scope, item_scope: region::Scope,
span: Span, span: Span,
cause: euv::LoanCause, cause: euv::LoanCause,
cmt: mc::cmt<'tcx>, cmt: &'a mc::cmt_<'tcx>,
loan_region: ty::Region<'tcx>, loan_region: ty::Region<'tcx>,
_: ty::BorrowKind) _: ty::BorrowKind)
-> Result<(),()> { -> Result<(),()> {
@ -41,8 +41,8 @@ pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
span, span,
cause, cause,
loan_region, loan_region,
cmt_original: cmt.clone()}; cmt_original: cmt};
ctxt.check(&cmt, None) ctxt.check(cmt, None)
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -57,12 +57,11 @@ struct GuaranteeLifetimeContext<'a, 'tcx: 'a> {
span: Span, span: Span,
cause: euv::LoanCause, cause: euv::LoanCause,
loan_region: ty::Region<'tcx>, loan_region: ty::Region<'tcx>,
cmt_original: mc::cmt<'tcx> cmt_original: &'a mc::cmt_<'tcx>
} }
impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
fn check(&self, cmt: &mc::cmt_<'tcx>, discr_scope: Option<ast::NodeId>) -> R {
fn check(&self, cmt: &mc::cmt<'tcx>, discr_scope: Option<ast::NodeId>) -> R {
//! Main routine. Walks down `cmt` until we find the //! Main routine. Walks down `cmt` until we find the
//! "guarantor". Reports an error if `self.loan_region` is //! "guarantor". Reports an error if `self.loan_region` is
//! larger than scope of `cmt`. //! larger than scope of `cmt`.
@ -102,7 +101,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
} }
} }
fn scope(&self, cmt: &mc::cmt<'tcx>) -> ty::Region<'tcx> { fn scope(&self, cmt: &mc::cmt_<'tcx>) -> ty::Region<'tcx> {
//! Returns the maximal region scope for the which the //! Returns the maximal region scope for the which the
//! place `cmt` is guaranteed to be valid without any //! place `cmt` is guaranteed to be valid without any
//! rooting etc, and presuming `cmt` is not mutated. //! rooting etc, and presuming `cmt` is not mutated.
@ -136,7 +135,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
} }
fn report_error(&self, code: bckerr_code<'tcx>) { fn report_error(&self, code: bckerr_code<'tcx>) {
self.bccx.report(BckError { cmt: self.cmt_original.clone(), self.bccx.report(BckError { cmt: self.cmt_original,
span: self.span, span: self.span,
cause: BorrowViolation(self.cause), cause: BorrowViolation(self.cause),
code: code }); code: code });

View file

@ -76,7 +76,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
fn consume(&mut self, fn consume(&mut self,
consume_id: ast::NodeId, consume_id: ast::NodeId,
_consume_span: Span, _consume_span: Span,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
mode: euv::ConsumeMode) { mode: euv::ConsumeMode) {
debug!("consume(consume_id={}, cmt={:?}, mode={:?})", debug!("consume(consume_id={}, cmt={:?}, mode={:?})",
consume_id, cmt, mode); consume_id, cmt, mode);
@ -93,7 +93,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
fn matched_pat(&mut self, fn matched_pat(&mut self,
matched_pat: &hir::Pat, matched_pat: &hir::Pat,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
mode: euv::MatchMode) { mode: euv::MatchMode) {
debug!("matched_pat(matched_pat={:?}, cmt={:?}, mode={:?})", debug!("matched_pat(matched_pat={:?}, cmt={:?}, mode={:?})",
matched_pat, matched_pat,
@ -103,7 +103,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
fn consume_pat(&mut self, fn consume_pat(&mut self,
consume_pat: &hir::Pat, consume_pat: &hir::Pat,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
mode: euv::ConsumeMode) { mode: euv::ConsumeMode) {
debug!("consume_pat(consume_pat={:?}, cmt={:?}, mode={:?})", debug!("consume_pat(consume_pat={:?}, cmt={:?}, mode={:?})",
consume_pat, consume_pat,
@ -123,7 +123,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
fn borrow(&mut self, fn borrow(&mut self,
borrow_id: ast::NodeId, borrow_id: ast::NodeId,
borrow_span: Span, borrow_span: Span,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
loan_region: ty::Region<'tcx>, loan_region: ty::Region<'tcx>,
bk: ty::BorrowKind, bk: ty::BorrowKind,
loan_cause: euv::LoanCause) loan_cause: euv::LoanCause)
@ -144,7 +144,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
fn mutate(&mut self, fn mutate(&mut self,
assignment_id: ast::NodeId, assignment_id: ast::NodeId,
assignment_span: Span, assignment_span: Span,
assignee_cmt: mc::cmt<'tcx>, assignee_cmt: &mc::cmt_<'tcx>,
mode: euv::MutateMode) mode: euv::MutateMode)
{ {
self.guarantee_assignment_valid(assignment_id, self.guarantee_assignment_valid(assignment_id,
@ -165,7 +165,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
borrow_span: Span, borrow_span: Span,
loan_cause: AliasableViolationKind, loan_cause: AliasableViolationKind,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
req_kind: ty::BorrowKind) req_kind: ty::BorrowKind)
-> Result<(),()> { -> Result<(),()> {
@ -206,7 +206,7 @@ fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
fn check_mutability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, fn check_mutability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
borrow_span: Span, borrow_span: Span,
cause: AliasableViolationKind, cause: AliasableViolationKind,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
req_kind: ty::BorrowKind) req_kind: ty::BorrowKind)
-> Result<(),()> { -> Result<(),()> {
debug!("check_mutability(cause={:?} cmt={:?} req_kind={:?}", debug!("check_mutability(cause={:?} cmt={:?} req_kind={:?}",
@ -246,10 +246,10 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
fn guarantee_assignment_valid(&mut self, fn guarantee_assignment_valid(&mut self,
assignment_id: ast::NodeId, assignment_id: ast::NodeId,
assignment_span: Span, assignment_span: Span,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
mode: euv::MutateMode) { mode: euv::MutateMode) {
let opt_lp = opt_loan_path(&cmt); let opt_lp = opt_loan_path(cmt);
debug!("guarantee_assignment_valid(assignment_id={}, cmt={:?}) opt_lp={:?}", debug!("guarantee_assignment_valid(assignment_id={}, cmt={:?}) opt_lp={:?}",
assignment_id, cmt, opt_lp); assignment_id, cmt, opt_lp);
@ -259,14 +259,14 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
} else { } else {
// Check that we don't allow assignments to non-mutable data. // Check that we don't allow assignments to non-mutable data.
if check_mutability(self.bccx, assignment_span, MutabilityViolation, if check_mutability(self.bccx, assignment_span, MutabilityViolation,
cmt.clone(), ty::MutBorrow).is_err() { cmt, ty::MutBorrow).is_err() {
return; // reported an error, no sense in reporting more. return; // reported an error, no sense in reporting more.
} }
} }
// Check that we don't allow assignments to aliasable data // Check that we don't allow assignments to aliasable data
if check_aliasability(self.bccx, assignment_span, MutabilityViolation, if check_aliasability(self.bccx, assignment_span, MutabilityViolation,
cmt.clone(), ty::MutBorrow).is_err() { cmt, ty::MutBorrow).is_err() {
return; // reported an error, no sense in reporting more. return; // reported an error, no sense in reporting more.
} }
@ -300,7 +300,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
fn guarantee_valid(&mut self, fn guarantee_valid(&mut self,
borrow_id: hir::ItemLocalId, borrow_id: hir::ItemLocalId,
borrow_span: Span, borrow_span: Span,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
req_kind: ty::BorrowKind, req_kind: ty::BorrowKind,
loan_region: ty::Region<'tcx>, loan_region: ty::Region<'tcx>,
cause: euv::LoanCause) { cause: euv::LoanCause) {
@ -320,28 +320,26 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
// Check that the lifetime of the borrow does not exceed // Check that the lifetime of the borrow does not exceed
// the lifetime of the data being borrowed. // the lifetime of the data being borrowed.
if lifetime::guarantee_lifetime(self.bccx, self.item_ub, if lifetime::guarantee_lifetime(self.bccx, self.item_ub,
borrow_span, cause, cmt.clone(), loan_region, borrow_span, cause, cmt, loan_region, req_kind).is_err() {
req_kind).is_err() {
return; // reported an error, no sense in reporting more. return; // reported an error, no sense in reporting more.
} }
// Check that we don't allow mutable borrows of non-mutable data. // Check that we don't allow mutable borrows of non-mutable data.
if check_mutability(self.bccx, borrow_span, BorrowViolation(cause), if check_mutability(self.bccx, borrow_span, BorrowViolation(cause),
cmt.clone(), req_kind).is_err() { cmt, req_kind).is_err() {
return; // reported an error, no sense in reporting more. return; // reported an error, no sense in reporting more.
} }
// Check that we don't allow mutable borrows of aliasable data. // Check that we don't allow mutable borrows of aliasable data.
if check_aliasability(self.bccx, borrow_span, BorrowViolation(cause), if check_aliasability(self.bccx, borrow_span, BorrowViolation(cause),
cmt.clone(), req_kind).is_err() { cmt, req_kind).is_err() {
return; // reported an error, no sense in reporting more. return; // reported an error, no sense in reporting more.
} }
// Compute the restrictions that are required to enforce the // Compute the restrictions that are required to enforce the
// loan is safe. // loan is safe.
let restr = restrictions::compute_restrictions( let restr = restrictions::compute_restrictions(
self.bccx, borrow_span, cause, self.bccx, borrow_span, cause, &cmt, loan_region);
cmt.clone(), loan_region);
debug!("guarantee_valid(): restrictions={:?}", restr); debug!("guarantee_valid(): restrictions={:?}", restr);

View file

@ -30,7 +30,7 @@ pub enum RestrictionResult<'tcx> {
pub fn compute_restrictions<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, pub fn compute_restrictions<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
span: Span, span: Span,
cause: euv::LoanCause, cause: euv::LoanCause,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
loan_region: ty::Region<'tcx>) loan_region: ty::Region<'tcx>)
-> RestrictionResult<'tcx> { -> RestrictionResult<'tcx> {
let ctxt = RestrictionsContext { let ctxt = RestrictionsContext {
@ -55,7 +55,7 @@ struct RestrictionsContext<'a, 'tcx: 'a> {
impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
fn restrict(&self, fn restrict(&self,
cmt: mc::cmt<'tcx>) -> RestrictionResult<'tcx> { cmt: &mc::cmt_<'tcx>) -> RestrictionResult<'tcx> {
debug!("restrict(cmt={:?})", cmt); debug!("restrict(cmt={:?})", cmt);
let new_lp = |v: LoanPathKind<'tcx>| Rc::new(LoanPath::new(v, cmt.ty)); let new_lp = |v: LoanPathKind<'tcx>| Rc::new(LoanPath::new(v, cmt.ty));
@ -86,7 +86,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
// When we borrow the interior of an enum, we have to // When we borrow the interior of an enum, we have to
// ensure the enum itself is not mutated, because that // ensure the enum itself is not mutated, because that
// could cause the type of the memory to change. // could cause the type of the memory to change.
self.restrict(cmt_base) self.restrict(&cmt_base)
} }
Categorization::Interior(cmt_base, interior) => { Categorization::Interior(cmt_base, interior) => {
@ -101,7 +101,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
}; };
let interior = interior.cleaned(); let interior = interior.cleaned();
let base_ty = cmt_base.ty; let base_ty = cmt_base.ty;
let result = self.restrict(cmt_base); let result = self.restrict(&cmt_base);
// Borrowing one union field automatically borrows all its fields. // Borrowing one union field automatically borrows all its fields.
match base_ty.sty { match base_ty.sty {
ty::TyAdt(adt_def, _) if adt_def.is_union() => match result { ty::TyAdt(adt_def, _) if adt_def.is_union() => match result {
@ -145,7 +145,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
// //
// Eventually we should make these non-special and // Eventually we should make these non-special and
// just rely on Deref<T> implementation. // just rely on Deref<T> implementation.
let result = self.restrict(cmt_base); let result = self.restrict(&cmt_base);
self.extend(result, &cmt, LpDeref(pk)) self.extend(result, &cmt, LpDeref(pk))
} }
mc::Implicit(bk, lt) | mc::BorrowedPtr(bk, lt) => { mc::Implicit(bk, lt) | mc::BorrowedPtr(bk, lt) => {
@ -155,7 +155,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
BckError { BckError {
span: self.span, span: self.span,
cause: BorrowViolation(self.cause), cause: BorrowViolation(self.cause),
cmt: cmt_base, cmt: &cmt_base,
code: err_borrowed_pointer_too_short( code: err_borrowed_pointer_too_short(
self.loan_region, lt)}); self.loan_region, lt)});
return RestrictionResult::Safe; return RestrictionResult::Safe;
@ -169,7 +169,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
// The referent can be aliased after the // The referent can be aliased after the
// references lifetime ends (by a newly-unfrozen // references lifetime ends (by a newly-unfrozen
// borrow). // borrow).
let result = self.restrict(cmt_base); let result = self.restrict(&cmt_base);
self.extend(result, &cmt, LpDeref(pk)) self.extend(result, &cmt, LpDeref(pk))
} }
} }
@ -183,7 +183,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
fn extend(&self, fn extend(&self,
result: RestrictionResult<'tcx>, result: RestrictionResult<'tcx>,
cmt: &mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
elem: LoanPathElem<'tcx>) -> RestrictionResult<'tcx> { elem: LoanPathElem<'tcx>) -> RestrictionResult<'tcx> {
match result { match result {
RestrictionResult::Safe => RestrictionResult::Safe, RestrictionResult::Safe => RestrictionResult::Safe,

View file

@ -497,7 +497,7 @@ impl<'a, 'tcx> LoanPath<'tcx> {
// Avoid "cannot borrow immutable field `self.x` as mutable" as that implies that a field *can* be // Avoid "cannot borrow immutable field `self.x` as mutable" as that implies that a field *can* be
// mutable independently of the struct it belongs to. (#35937) // mutable independently of the struct it belongs to. (#35937)
pub fn opt_loan_path_is_field<'tcx>(cmt: &mc::cmt<'tcx>) -> (Option<Rc<LoanPath<'tcx>>>, bool) { pub fn opt_loan_path_is_field<'tcx>(cmt: &mc::cmt_<'tcx>) -> (Option<Rc<LoanPath<'tcx>>>, bool) {
let new_lp = |v: LoanPathKind<'tcx>| Rc::new(LoanPath::new(v, cmt.ty)); let new_lp = |v: LoanPathKind<'tcx>| Rc::new(LoanPath::new(v, cmt.ty));
match cmt.cat { match cmt.cat {
@ -545,7 +545,7 @@ pub fn opt_loan_path_is_field<'tcx>(cmt: &mc::cmt<'tcx>) -> (Option<Rc<LoanPath<
/// the method `compute()` found in `gather_loans::restrictions`, /// the method `compute()` found in `gather_loans::restrictions`,
/// which allows it to share common loan path pieces as it /// which allows it to share common loan path pieces as it
/// traverses the CMT. /// traverses the CMT.
pub fn opt_loan_path<'tcx>(cmt: &mc::cmt<'tcx>) -> Option<Rc<LoanPath<'tcx>>> { pub fn opt_loan_path<'tcx>(cmt: &mc::cmt_<'tcx>) -> Option<Rc<LoanPath<'tcx>>> {
opt_loan_path_is_field(cmt).0 opt_loan_path_is_field(cmt).0
} }
@ -564,10 +564,10 @@ pub enum bckerr_code<'tcx> {
// Combination of an error code and the categorization of the expression // Combination of an error code and the categorization of the expression
// that caused it // that caused it
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct BckError<'tcx> { pub struct BckError<'c, 'tcx: 'c> {
span: Span, span: Span,
cause: AliasableViolationKind, cause: AliasableViolationKind,
cmt: mc::cmt<'tcx>, cmt: &'c mc::cmt_<'tcx>,
code: bckerr_code<'tcx> code: bckerr_code<'tcx>
} }
@ -599,7 +599,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
region_rels.is_subregion_of(r_sub, r_sup) region_rels.is_subregion_of(r_sub, r_sup)
} }
pub fn report(&self, err: BckError<'tcx>) { pub fn report(&self, err: BckError<'a, 'tcx>) {
// Catch and handle some particular cases. // Catch and handle some particular cases.
match (&err.code, &err.cause) { match (&err.code, &err.cause) {
(&err_out_of_scope(&ty::ReScope(_), &ty::ReStatic, _), (&err_out_of_scope(&ty::ReScope(_), &ty::ReStatic, _),
@ -800,7 +800,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
self.tcx.sess.span_err_with_code(s, msg, code); self.tcx.sess.span_err_with_code(s, msg, code);
} }
fn report_bckerr(&self, err: &BckError<'tcx>) { fn report_bckerr(&self, err: &BckError<'a, 'tcx>) {
let error_span = err.span.clone(); let error_span = err.span.clone();
match err.code { match err.code {
@ -1011,7 +1011,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
db.emit(); db.emit();
} }
err_borrowed_pointer_too_short(loan_scope, ptr_scope) => { err_borrowed_pointer_too_short(loan_scope, ptr_scope) => {
let descr = self.cmt_to_path_or_string(&err.cmt); let descr = self.cmt_to_path_or_string(err.cmt);
let mut db = self.lifetime_too_short_for_reborrow(error_span, &descr, Origin::Ast); let mut db = self.lifetime_too_short_for_reborrow(error_span, &descr, Origin::Ast);
let descr = match opt_loan_path(&err.cmt) { let descr = match opt_loan_path(&err.cmt) {
Some(lp) => { Some(lp) => {
@ -1042,7 +1042,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
span: Span, span: Span,
kind: AliasableViolationKind, kind: AliasableViolationKind,
cause: mc::AliasableReason, cause: mc::AliasableReason,
cmt: mc::cmt<'tcx>) { cmt: &mc::cmt_<'tcx>) {
let mut is_closure = false; let mut is_closure = false;
let prefix = match kind { let prefix = match kind {
MutabilityViolation => { MutabilityViolation => {
@ -1240,7 +1240,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
} }
fn report_out_of_scope_escaping_closure_capture(&self, fn report_out_of_scope_escaping_closure_capture(&self,
err: &BckError<'tcx>, err: &BckError<'a, 'tcx>,
capture_span: Span) capture_span: Span)
{ {
let cmt_path_or_string = self.cmt_to_path_or_string(&err.cmt); let cmt_path_or_string = self.cmt_to_path_or_string(&err.cmt);
@ -1274,18 +1274,18 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
} }
} }
fn note_and_explain_mutbl_error(&self, db: &mut DiagnosticBuilder, err: &BckError<'tcx>, fn note_and_explain_mutbl_error(&self, db: &mut DiagnosticBuilder, err: &BckError<'a, 'tcx>,
error_span: &Span) { error_span: &Span) {
match err.cmt.note { match err.cmt.note {
mc::NoteClosureEnv(upvar_id) | mc::NoteUpvarRef(upvar_id) => { mc::NoteClosureEnv(upvar_id) | mc::NoteUpvarRef(upvar_id) => {
// If this is an `Fn` closure, it simply can't mutate upvars. // If this is an `Fn` closure, it simply can't mutate upvars.
// If it's an `FnMut` closure, the original variable was declared immutable. // If it's an `FnMut` closure, the original variable was declared immutable.
// We need to determine which is the case here. // We need to determine which is the case here.
let kind = match err.cmt.upvar().unwrap().cat { let kind = match err.cmt.upvar_cat().unwrap() {
Categorization::Upvar(mc::Upvar { kind, .. }) => kind, Categorization::Upvar(mc::Upvar { kind, .. }) => kind,
_ => bug!() _ => bug!()
}; };
if kind == ty::ClosureKind::Fn { if *kind == ty::ClosureKind::Fn {
let closure_node_id = let closure_node_id =
self.tcx.hir.local_def_id_to_node_id(upvar_id.closure_expr_id); self.tcx.hir.local_def_id_to_node_id(upvar_id.closure_expr_id);
db.span_help(self.tcx.hir.span(closure_node_id), db.span_help(self.tcx.hir.span(closure_node_id),
@ -1389,7 +1389,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
cmt.descriptive_string(self.tcx) cmt.descriptive_string(self.tcx)
} }
pub fn cmt_to_path_or_string(&self, cmt: &mc::cmt<'tcx>) -> String { pub fn cmt_to_path_or_string(&self, cmt: &mc::cmt_<'tcx>) -> String {
match opt_loan_path(cmt) { match opt_loan_path(cmt) {
Some(lp) => format!("`{}`", self.loan_path_to_string(&lp)), Some(lp) => format!("`{}`", self.loan_path_to_string(&lp)),
None => self.cmt_to_string(cmt), None => self.cmt_to_string(cmt),

View file

@ -17,7 +17,7 @@ use super::{Pattern, PatternContext, PatternError, PatternKind};
use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor}; use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
use rustc::middle::expr_use_visitor::{LoanCause, MutateMode}; use rustc::middle::expr_use_visitor::{LoanCause, MutateMode};
use rustc::middle::expr_use_visitor as euv; use rustc::middle::expr_use_visitor as euv;
use rustc::middle::mem_categorization::{cmt}; use rustc::middle::mem_categorization::cmt_;
use rustc::middle::region; use rustc::middle::region;
use rustc::session::Session; use rustc::session::Session;
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
@ -573,13 +573,13 @@ struct MutationChecker<'a, 'tcx: 'a> {
} }
impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> { impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> {
fn matched_pat(&mut self, _: &Pat, _: cmt, _: euv::MatchMode) {} fn matched_pat(&mut self, _: &Pat, _: &cmt_, _: euv::MatchMode) {}
fn consume(&mut self, _: ast::NodeId, _: Span, _: cmt, _: ConsumeMode) {} fn consume(&mut self, _: ast::NodeId, _: Span, _: &cmt_, _: ConsumeMode) {}
fn consume_pat(&mut self, _: &Pat, _: cmt, _: ConsumeMode) {} fn consume_pat(&mut self, _: &Pat, _: &cmt_, _: ConsumeMode) {}
fn borrow(&mut self, fn borrow(&mut self,
_: ast::NodeId, _: ast::NodeId,
span: Span, span: Span,
_: cmt, _: &cmt_,
_: ty::Region<'tcx>, _: ty::Region<'tcx>,
kind:ty:: BorrowKind, kind:ty:: BorrowKind,
_: LoanCause) { _: LoanCause) {
@ -594,7 +594,7 @@ impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> {
} }
} }
fn decl_without_init(&mut self, _: ast::NodeId, _: Span) {} fn decl_without_init(&mut self, _: ast::NodeId, _: Span) {}
fn mutate(&mut self, _: ast::NodeId, span: Span, _: cmt, mode: MutateMode) { fn mutate(&mut self, _: ast::NodeId, span: Span, _: &cmt_, mode: MutateMode) {
match mode { match mode {
MutateMode::JustWrite | MutateMode::WriteAndRead => { MutateMode::JustWrite | MutateMode::WriteAndRead => {
struct_span_err!(self.cx.tcx.sess, span, E0302, "cannot assign in a pattern guard") struct_span_err!(self.cx.tcx.sess, span, E0302, "cannot assign in a pattern guard")

View file

@ -468,13 +468,13 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> {
fn consume(&mut self, fn consume(&mut self,
_consume_id: ast::NodeId, _consume_id: ast::NodeId,
_consume_span: Span, _consume_span: Span,
_cmt: mc::cmt, _cmt: &mc::cmt_,
_mode: euv::ConsumeMode) {} _mode: euv::ConsumeMode) {}
fn borrow(&mut self, fn borrow(&mut self,
borrow_id: ast::NodeId, borrow_id: ast::NodeId,
_borrow_span: Span, _borrow_span: Span,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
_loan_region: ty::Region<'tcx>, _loan_region: ty::Region<'tcx>,
bk: ty::BorrowKind, bk: ty::BorrowKind,
loan_cause: euv::LoanCause) { loan_cause: euv::LoanCause) {
@ -489,7 +489,7 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> {
_ => {} _ => {}
} }
let mut cur = &cmt; let mut cur = cmt;
loop { loop {
match cur.cat { match cur.cat {
Categorization::Rvalue(..) => { Categorization::Rvalue(..) => {
@ -521,11 +521,11 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> {
fn mutate(&mut self, fn mutate(&mut self,
_assignment_id: ast::NodeId, _assignment_id: ast::NodeId,
_assignment_span: Span, _assignment_span: Span,
_assignee_cmt: mc::cmt, _assignee_cmt: &mc::cmt_,
_mode: euv::MutateMode) { _mode: euv::MutateMode) {
} }
fn matched_pat(&mut self, _: &hir::Pat, _: mc::cmt, _: euv::MatchMode) {} fn matched_pat(&mut self, _: &hir::Pat, _: &mc::cmt_, _: euv::MatchMode) {}
fn consume_pat(&mut self, _consume_pat: &hir::Pat, _cmt: mc::cmt, _mode: euv::ConsumeMode) {} fn consume_pat(&mut self, _consume_pat: &hir::Pat, _cmt: &mc::cmt_, _mode: euv::ConsumeMode) {}
} }

View file

@ -96,6 +96,7 @@ use rustc::ty::adjustment;
use std::mem; use std::mem;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use syntax::ast; use syntax::ast;
use syntax_pos::Span; use syntax_pos::Span;
@ -513,7 +514,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
// the adjusted form if there is an adjustment. // the adjusted form if there is an adjustment.
match cmt_result { match cmt_result {
Ok(head_cmt) => { Ok(head_cmt) => {
self.check_safety_of_rvalue_destructor_if_necessary(head_cmt, expr.span); self.check_safety_of_rvalue_destructor_if_necessary(&head_cmt, expr.span);
} }
Err(..) => { Err(..) => {
self.tcx.sess.delay_span_bug(expr.span, "cat_expr Errd"); self.tcx.sess.delay_span_bug(expr.span, "cat_expr Errd");
@ -799,7 +800,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
/// Invoked on any adjustments that occur. Checks that if this is a region pointer being /// 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. /// dereferenced, the lifetime of the pointer includes the deref expr.
fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult<mc::cmt<'tcx>> { fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult<mc::cmt_<'tcx>> {
debug!("constrain_adjustments(expr={:?})", expr); debug!("constrain_adjustments(expr={:?})", expr);
let mut cmt = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?; let mut cmt = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?;
@ -814,7 +815,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
// If necessary, constrain destructors in the unadjusted form of this // If necessary, constrain destructors in the unadjusted form of this
// expression. // expression.
self.check_safety_of_rvalue_destructor_if_necessary(cmt.clone(), expr.span); self.check_safety_of_rvalue_destructor_if_necessary(&cmt, expr.span);
let expr_region = self.tcx.mk_region(ty::ReScope( let expr_region = self.tcx.mk_region(ty::ReScope(
region::Scope::Node(expr.hir_id.local_id))); region::Scope::Node(expr.hir_id.local_id)));
@ -837,7 +838,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
}); });
self.link_region(expr.span, deref.region, self.link_region(expr.span, deref.region,
ty::BorrowKind::from_mutbl(deref.mutbl), cmt.clone()); ty::BorrowKind::from_mutbl(deref.mutbl), &cmt);
// Specialized version of constrain_call. // Specialized version of constrain_call.
self.type_must_outlive(infer::CallRcvr(expr.span), self.type_must_outlive(infer::CallRcvr(expr.span),
@ -847,7 +848,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
} }
if let adjustment::Adjust::Borrow(ref autoref) = adjustment.kind { if let adjustment::Adjust::Borrow(ref autoref) = adjustment.kind {
self.link_autoref(expr, cmt.clone(), autoref); self.link_autoref(expr, &cmt, autoref);
// Require that the resulting region encompasses // Require that the resulting region encompasses
// the current node. // the current node.
@ -878,7 +879,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
} }
fn check_safety_of_rvalue_destructor_if_necessary(&mut self, fn check_safety_of_rvalue_destructor_if_necessary(&mut self,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
span: Span) { span: Span) {
match cmt.cat { match cmt.cat {
Categorization::Rvalue(region) => { Categorization::Rvalue(region) => {
@ -980,7 +981,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
debug!("link_addr_of: cmt={:?}", cmt); debug!("link_addr_of: cmt={:?}", cmt);
self.link_region_from_node_type(expr.span, expr.hir_id, mutability, cmt); self.link_region_from_node_type(expr.span, expr.hir_id, mutability, &cmt);
} }
/// Computes the guarantors for any ref bindings in a `let` and /// Computes the guarantors for any ref bindings in a `let` and
@ -992,7 +993,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
None => { return; } None => { return; }
Some(ref expr) => &**expr, Some(ref expr) => &**expr,
}; };
let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(init_expr))); let discr_cmt = Rc::new(ignore_err!(self.with_mc(|mc| mc.cat_expr(init_expr))));
self.link_pattern(discr_cmt, &local.pat); self.link_pattern(discr_cmt, &local.pat);
} }
@ -1001,7 +1002,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
/// linked to the lifetime of its guarantor (if any). /// linked to the lifetime of its guarantor (if any).
fn link_match(&self, discr: &hir::Expr, arms: &[hir::Arm]) { fn link_match(&self, discr: &hir::Expr, arms: &[hir::Arm]) {
debug!("regionck::for_match()"); debug!("regionck::for_match()");
let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(discr))); let discr_cmt = Rc::new(ignore_err!(self.with_mc(|mc| mc.cat_expr(discr))));
debug!("discr_cmt={:?}", discr_cmt); debug!("discr_cmt={:?}", discr_cmt);
for arm in arms { for arm in arms {
for root_pat in &arm.pats { for root_pat in &arm.pats {
@ -1019,7 +1020,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
let arg_ty = self.node_ty(arg.hir_id); let arg_ty = self.node_ty(arg.hir_id);
let re_scope = self.tcx.mk_region(ty::ReScope(body_scope)); let re_scope = self.tcx.mk_region(ty::ReScope(body_scope));
let arg_cmt = self.with_mc(|mc| { let arg_cmt = self.with_mc(|mc| {
mc.cat_rvalue(arg.id, arg.pat.span, re_scope, arg_ty) Rc::new(mc.cat_rvalue(arg.id, arg.pat.span, re_scope, arg_ty))
}); });
debug!("arg_ty={:?} arg_cmt={:?} arg={:?}", debug!("arg_ty={:?} arg_cmt={:?} arg={:?}",
arg_ty, arg_ty,
@ -1044,7 +1045,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
.expect("missing binding mode"); .expect("missing binding mode");
if let ty::BindByReference(mutbl) = bm { if let ty::BindByReference(mutbl) = bm {
self.link_region_from_node_type(sub_pat.span, sub_pat.hir_id, self.link_region_from_node_type(sub_pat.span, sub_pat.hir_id,
mutbl, sub_cmt); mutbl, &sub_cmt);
} }
} }
_ => {} _ => {}
@ -1057,15 +1058,14 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
/// autoref'd. /// autoref'd.
fn link_autoref(&self, fn link_autoref(&self,
expr: &hir::Expr, expr: &hir::Expr,
expr_cmt: mc::cmt<'tcx>, expr_cmt: &mc::cmt_<'tcx>,
autoref: &adjustment::AutoBorrow<'tcx>) autoref: &adjustment::AutoBorrow<'tcx>)
{ {
debug!("link_autoref(autoref={:?}, expr_cmt={:?})", autoref, expr_cmt); debug!("link_autoref(autoref={:?}, expr_cmt={:?})", autoref, expr_cmt);
match *autoref { match *autoref {
adjustment::AutoBorrow::Ref(r, m) => { adjustment::AutoBorrow::Ref(r, m) => {
self.link_region(expr.span, r, self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m.into()), expr_cmt);
ty::BorrowKind::from_mutbl(m.into()), expr_cmt);
} }
adjustment::AutoBorrow::RawPtr(m) => { adjustment::AutoBorrow::RawPtr(m) => {
@ -1081,15 +1081,14 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
span: Span, span: Span,
id: hir::HirId, id: hir::HirId,
mutbl: hir::Mutability, mutbl: hir::Mutability,
cmt_borrowed: mc::cmt<'tcx>) { cmt_borrowed: &mc::cmt_<'tcx>) {
debug!("link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={:?})", debug!("link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={:?})",
id, mutbl, cmt_borrowed); id, mutbl, cmt_borrowed);
let rptr_ty = self.resolve_node_type(id); let rptr_ty = self.resolve_node_type(id);
if let ty::TyRef(r, _) = rptr_ty.sty { if let ty::TyRef(r, _) = rptr_ty.sty {
debug!("rptr_ty={}", rptr_ty); debug!("rptr_ty={}", rptr_ty);
self.link_region(span, r, ty::BorrowKind::from_mutbl(mutbl), self.link_region(span, r, ty::BorrowKind::from_mutbl(mutbl), cmt_borrowed);
cmt_borrowed);
} }
} }
@ -1101,19 +1100,19 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
span: Span, span: Span,
borrow_region: ty::Region<'tcx>, borrow_region: ty::Region<'tcx>,
borrow_kind: ty::BorrowKind, borrow_kind: ty::BorrowKind,
borrow_cmt: mc::cmt<'tcx>) { borrow_cmt: &mc::cmt_<'tcx>) {
let mut borrow_cmt = borrow_cmt;
let mut borrow_kind = borrow_kind;
let origin = infer::DataBorrowed(borrow_cmt.ty, span); let origin = infer::DataBorrowed(borrow_cmt.ty, span);
self.type_must_outlive(origin, borrow_cmt.ty, borrow_region); self.type_must_outlive(origin, borrow_cmt.ty, borrow_region);
let mut borrow_kind = borrow_kind;
let mut borrow_cmt_cat = borrow_cmt.cat.clone();
loop { loop {
debug!("link_region(borrow_region={:?}, borrow_kind={:?}, borrow_cmt={:?})", debug!("link_region(borrow_region={:?}, borrow_kind={:?}, borrow_cmt={:?})",
borrow_region, borrow_region,
borrow_kind, borrow_kind,
borrow_cmt); borrow_cmt);
match borrow_cmt.cat.clone() { match borrow_cmt_cat {
Categorization::Deref(ref_cmt, mc::Implicit(ref_kind, ref_region)) | Categorization::Deref(ref_cmt, mc::Implicit(ref_kind, ref_region)) |
Categorization::Deref(ref_cmt, mc::BorrowedPtr(ref_kind, ref_region)) => { Categorization::Deref(ref_cmt, mc::BorrowedPtr(ref_kind, ref_region)) => {
match self.link_reborrowed_region(span, match self.link_reborrowed_region(span,
@ -1121,7 +1120,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
ref_cmt, ref_region, ref_kind, ref_cmt, ref_region, ref_kind,
borrow_cmt.note) { borrow_cmt.note) {
Some((c, k)) => { Some((c, k)) => {
borrow_cmt = c; borrow_cmt_cat = c.cat.clone();
borrow_kind = k; borrow_kind = k;
} }
None => { None => {
@ -1135,7 +1134,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
Categorization::Interior(cmt_base, _) => { Categorization::Interior(cmt_base, _) => {
// Borrowing interior or owned data requires the base // Borrowing interior or owned data requires the base
// to be valid and borrowable in the same fashion. // to be valid and borrowable in the same fashion.
borrow_cmt = cmt_base; borrow_cmt_cat = cmt_base.cat.clone();
borrow_kind = borrow_kind; borrow_kind = borrow_kind;
} }

View file

@ -298,7 +298,8 @@ struct InferBorrowKind<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
} }
impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
fn adjust_upvar_borrow_kind_for_consume(&mut self, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) { fn adjust_upvar_borrow_kind_for_consume(&mut self, cmt: &mc::cmt_<'tcx>,
mode: euv::ConsumeMode) {
debug!( debug!(
"adjust_upvar_borrow_kind_for_consume(cmt={:?}, mode={:?})", "adjust_upvar_borrow_kind_for_consume(cmt={:?}, mode={:?})",
cmt, cmt,
@ -377,7 +378,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
/// Indicates that `cmt` is being directly mutated (e.g., assigned /// Indicates that `cmt` is being directly mutated (e.g., assigned
/// to). If cmt contains any by-ref upvars, this implies that /// to). If cmt contains any by-ref upvars, this implies that
/// those upvars must be borrowed using an `&mut` borrow. /// those upvars must be borrowed using an `&mut` borrow.
fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: mc::cmt<'tcx>) { fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: &mc::cmt_<'tcx>) {
debug!("adjust_upvar_borrow_kind_for_mut(cmt={:?})", cmt); debug!("adjust_upvar_borrow_kind_for_mut(cmt={:?})", cmt);
match cmt.cat.clone() { match cmt.cat.clone() {
@ -386,7 +387,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
Categorization::Downcast(base, _) => { Categorization::Downcast(base, _) => {
// Interior or owned data is mutable if base is // Interior or owned data is mutable if base is
// mutable, so iterate to the base. // mutable, so iterate to the base.
self.adjust_upvar_borrow_kind_for_mut(base); self.adjust_upvar_borrow_kind_for_mut(&base);
} }
Categorization::Deref(base, mc::BorrowedPtr(..)) | Categorization::Deref(base, mc::BorrowedPtr(..)) |
@ -396,7 +397,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
// borrowed pointer implies that the // borrowed pointer implies that the
// pointer itself must be unique, but not // pointer itself must be unique, but not
// necessarily *mutable* // necessarily *mutable*
self.adjust_upvar_borrow_kind_for_unique(base); self.adjust_upvar_borrow_kind_for_unique(&base);
} }
} }
@ -410,7 +411,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
} }
} }
fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: mc::cmt<'tcx>) { fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: &mc::cmt_<'tcx>) {
debug!("adjust_upvar_borrow_kind_for_unique(cmt={:?})", cmt); debug!("adjust_upvar_borrow_kind_for_unique(cmt={:?})", cmt);
match cmt.cat.clone() { match cmt.cat.clone() {
@ -419,7 +420,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
Categorization::Downcast(base, _) => { Categorization::Downcast(base, _) => {
// Interior or owned data is unique if base is // Interior or owned data is unique if base is
// unique. // unique.
self.adjust_upvar_borrow_kind_for_unique(base); self.adjust_upvar_borrow_kind_for_unique(&base);
} }
Categorization::Deref(base, mc::BorrowedPtr(..)) | Categorization::Deref(base, mc::BorrowedPtr(..)) |
@ -427,7 +428,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
if !self.try_adjust_upvar_deref(cmt, ty::UniqueImmBorrow) { if !self.try_adjust_upvar_deref(cmt, ty::UniqueImmBorrow) {
// for a borrowed pointer to be unique, its // for a borrowed pointer to be unique, its
// base must be unique // base must be unique
self.adjust_upvar_borrow_kind_for_unique(base); self.adjust_upvar_borrow_kind_for_unique(&base);
} }
} }
@ -439,7 +440,9 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
} }
} }
fn try_adjust_upvar_deref(&mut self, cmt: mc::cmt<'tcx>, borrow_kind: ty::BorrowKind) -> bool { fn try_adjust_upvar_deref(&mut self, cmt: &mc::cmt_<'tcx>, borrow_kind: ty::BorrowKind)
-> bool
{
assert!(match borrow_kind { assert!(match borrow_kind {
ty::MutBorrow => true, ty::MutBorrow => true,
ty::UniqueImmBorrow => true, ty::UniqueImmBorrow => true,
@ -581,17 +584,19 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> {
&mut self, &mut self,
_consume_id: ast::NodeId, _consume_id: ast::NodeId,
_consume_span: Span, _consume_span: Span,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
mode: euv::ConsumeMode, mode: euv::ConsumeMode,
) { ) {
debug!("consume(cmt={:?},mode={:?})", cmt, mode); debug!("consume(cmt={:?},mode={:?})", cmt, mode);
self.adjust_upvar_borrow_kind_for_consume(cmt, mode); self.adjust_upvar_borrow_kind_for_consume(cmt, mode);
} }
fn matched_pat(&mut self, _matched_pat: &hir::Pat, _cmt: mc::cmt<'tcx>, _mode: euv::MatchMode) { fn matched_pat(&mut self, _matched_pat: &hir::Pat, _cmt: &mc::cmt_<'tcx>,
_mode: euv::MatchMode) {
} }
fn consume_pat(&mut self, _consume_pat: &hir::Pat, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) { fn consume_pat(&mut self, _consume_pat: &hir::Pat, cmt: &mc::cmt_<'tcx>,
mode: euv::ConsumeMode) {
debug!("consume_pat(cmt={:?},mode={:?})", cmt, mode); debug!("consume_pat(cmt={:?},mode={:?})", cmt, mode);
self.adjust_upvar_borrow_kind_for_consume(cmt, mode); self.adjust_upvar_borrow_kind_for_consume(cmt, mode);
} }
@ -600,7 +605,7 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> {
&mut self, &mut self,
borrow_id: ast::NodeId, borrow_id: ast::NodeId,
_borrow_span: Span, _borrow_span: Span,
cmt: mc::cmt<'tcx>, cmt: &mc::cmt_<'tcx>,
_loan_region: ty::Region<'tcx>, _loan_region: ty::Region<'tcx>,
bk: ty::BorrowKind, bk: ty::BorrowKind,
_loan_cause: euv::LoanCause, _loan_cause: euv::LoanCause,
@ -629,7 +634,7 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> {
&mut self, &mut self,
_assignment_id: ast::NodeId, _assignment_id: ast::NodeId,
_assignment_span: Span, _assignment_span: Span,
assignee_cmt: mc::cmt<'tcx>, assignee_cmt: &mc::cmt_<'tcx>,
_mode: euv::MutateMode, _mode: euv::MutateMode,
) { ) {
debug!("mutate(assignee_cmt={:?})", assignee_cmt); debug!("mutate(assignee_cmt={:?})", assignee_cmt);