rustc: de-@ borrowck.

This commit is contained in:
Eduard Burtescu 2014-04-14 22:34:42 +03:00
parent 3683f16e9e
commit d55deaeb21
6 changed files with 137 additions and 160 deletions

View File

@ -30,6 +30,8 @@ use syntax::visit::Visitor;
use syntax::visit;
use util::ppaux::Repr;
use std::rc::Rc;
struct CheckLoanCtxt<'a> {
bccx: &'a BorrowckCtxt<'a>,
dfcx_loans: &'a LoanDataFlow<'a>,
@ -82,7 +84,7 @@ pub fn check_loans(bccx: &BorrowckCtxt,
#[deriving(Eq)]
enum MoveError {
MoveOk,
MoveWhileBorrowed(/*loan*/@LoanPath, /*loan*/Span)
MoveWhileBorrowed(/*loan*/Rc<LoanPath>, /*loan*/Span)
}
impl<'a> CheckLoanCtxt<'a> {
@ -121,7 +123,7 @@ impl<'a> CheckLoanCtxt<'a> {
pub fn each_in_scope_restriction(&self,
scope_id: ast::NodeId,
loan_path: @LoanPath,
loan_path: &LoanPath,
op: |&Loan, &Restriction| -> bool)
-> bool {
//! Iterates through all the in-scope restrictions for the
@ -133,7 +135,7 @@ impl<'a> CheckLoanCtxt<'a> {
let mut ret = true;
for restr in loan.restrictions.iter() {
if restr.loan_path == loan_path {
if *restr.loan_path == *loan_path {
if !op(loan, restr) {
ret = false;
break;
@ -243,7 +245,7 @@ impl<'a> CheckLoanCtxt<'a> {
"it".to_owned()
} else {
format!("`{}`",
self.bccx.loan_path_to_str(old_loan.loan_path))
self.bccx.loan_path_to_str(&*old_loan.loan_path))
};
match (new_loan.kind, old_loan.kind) {
@ -252,7 +254,7 @@ impl<'a> CheckLoanCtxt<'a> {
new_loan.span,
format!("cannot borrow `{}` as mutable \
more than once at a time",
self.bccx.loan_path_to_str(new_loan.loan_path)));
self.bccx.loan_path_to_str(&*new_loan.loan_path)));
}
(ty::UniqueImmBorrow, _) => {
@ -260,7 +262,7 @@ impl<'a> CheckLoanCtxt<'a> {
new_loan.span,
format!("closure requires unique access to `{}` \
but {} is already borrowed",
self.bccx.loan_path_to_str(new_loan.loan_path),
self.bccx.loan_path_to_str(&*new_loan.loan_path),
old_pronoun));
}
@ -269,7 +271,7 @@ impl<'a> CheckLoanCtxt<'a> {
new_loan.span,
format!("cannot borrow `{}` as {} because \
previous closure requires unique access",
self.bccx.loan_path_to_str(new_loan.loan_path),
self.bccx.loan_path_to_str(&*new_loan.loan_path),
new_loan.kind.to_user_str()));
}
@ -278,7 +280,7 @@ impl<'a> CheckLoanCtxt<'a> {
new_loan.span,
format!("cannot borrow `{}` as {} because \
{} is also borrowed as {}",
self.bccx.loan_path_to_str(new_loan.loan_path),
self.bccx.loan_path_to_str(&*new_loan.loan_path),
new_loan.kind.to_user_str(),
old_pronoun,
old_loan.kind.to_user_str()));
@ -290,7 +292,7 @@ impl<'a> CheckLoanCtxt<'a> {
self.bccx.span_note(
span,
format!("borrow occurs due to use of `{}` in closure",
self.bccx.loan_path_to_str(new_loan.loan_path)));
self.bccx.loan_path_to_str(&*new_loan.loan_path)));
}
_ => { }
}
@ -300,21 +302,21 @@ impl<'a> CheckLoanCtxt<'a> {
format!("the mutable borrow prevents subsequent \
moves, borrows, or modification of `{0}` \
until the borrow ends",
self.bccx.loan_path_to_str(old_loan.loan_path))
self.bccx.loan_path_to_str(&*old_loan.loan_path))
}
ty::ImmBorrow => {
format!("the immutable borrow prevents subsequent \
moves or mutable borrows of `{0}` \
until the borrow ends",
self.bccx.loan_path_to_str(old_loan.loan_path))
self.bccx.loan_path_to_str(&*old_loan.loan_path))
}
ty::UniqueImmBorrow => {
format!("the unique capture prevents subsequent \
moves or borrows of `{0}` \
until the borrow ends",
self.bccx.loan_path_to_str(old_loan.loan_path))
self.bccx.loan_path_to_str(&*old_loan.loan_path))
}
};
@ -322,12 +324,12 @@ impl<'a> CheckLoanCtxt<'a> {
ClosureCapture(_) => {
format!("previous borrow of `{}` occurs here due to \
use in closure",
self.bccx.loan_path_to_str(old_loan.loan_path))
self.bccx.loan_path_to_str(&*old_loan.loan_path))
}
AddrOf | AutoRef | RefBinding => {
format!("previous borrow of `{}` occurs here",
self.bccx.loan_path_to_str(old_loan.loan_path))
self.bccx.loan_path_to_str(&*old_loan.loan_path))
}
};
@ -356,7 +358,7 @@ impl<'a> CheckLoanCtxt<'a> {
id: ast::NodeId,
span: Span,
use_kind: MovedValueUseKind,
lp: @LoanPath) {
lp: &Rc<LoanPath>) {
/*!
* Reports an error if `expr` (which should be a path)
* is using a moved/uninitialized value
@ -368,7 +370,7 @@ impl<'a> CheckLoanCtxt<'a> {
self.bccx.report_use_of_moved_value(
span,
use_kind,
lp,
&**lp,
move,
moved_lp);
false
@ -404,10 +406,10 @@ impl<'a> CheckLoanCtxt<'a> {
if self.is_local_variable(cmt) {
assert!(cmt.mutbl.is_immutable()); // no "const" locals
let lp = opt_loan_path(cmt).unwrap();
self.move_data.each_assignment_of(expr.id, lp, |assign| {
self.move_data.each_assignment_of(expr.id, &lp, |assign| {
self.bccx.report_reassigned_immutable_variable(
expr.span,
lp,
&*lp,
assign);
false
});
@ -422,7 +424,7 @@ impl<'a> CheckLoanCtxt<'a> {
format!("cannot assign to {} {} `{}`",
cmt.mutbl.to_user_str(),
self.bccx.cmt_to_str(cmt),
self.bccx.loan_path_to_str(lp)));
self.bccx.loan_path_to_str(&*lp)));
}
None => {
self.bccx.span_err(
@ -571,10 +573,10 @@ impl<'a> CheckLoanCtxt<'a> {
// owned pointer are borrowed, and hence while `v[*]` is not
// restricted from being written, `v` is.
let cont = this.each_in_scope_restriction(expr.id,
loan_path,
&*loan_path,
|loan, restr| {
if restr.set.intersects(RESTR_MUTATE) {
this.report_illegal_mutation(expr, loan_path, loan);
this.report_illegal_mutation(expr, &*loan_path, loan);
false
} else {
true
@ -623,17 +625,17 @@ impl<'a> CheckLoanCtxt<'a> {
//
// Here the restriction that `v` not be mutated would be misapplied
// to block the subpath `v[1]`.
let full_loan_path = loan_path;
let full_loan_path = loan_path.clone();
let mut loan_path = loan_path;
loop {
match *loan_path {
loan_path = match *loan_path {
// Peel back one layer if, for `loan_path` to be
// mutable, `lp_base` must be mutable. This occurs
// with inherited mutability and with `&mut`
// pointers.
LpExtend(lp_base, mc::McInherited, _) |
LpExtend(lp_base, _, LpDeref(mc::BorrowedPtr(ty::MutBorrow, _))) => {
loan_path = lp_base;
LpExtend(ref lp_base, mc::McInherited, _) |
LpExtend(ref lp_base, _, LpDeref(mc::BorrowedPtr(ty::MutBorrow, _))) => {
lp_base.clone()
}
// Otherwise stop iterating
@ -642,12 +644,12 @@ impl<'a> CheckLoanCtxt<'a> {
LpVar(_) => {
return true;
}
}
};
// Check for a non-const loan of `loan_path`
let cont = this.each_in_scope_loan(expr.id, |loan| {
if loan.loan_path == loan_path {
this.report_illegal_mutation(expr, full_loan_path, loan);
this.report_illegal_mutation(expr, &*full_loan_path, loan);
false
} else {
true
@ -700,7 +702,7 @@ impl<'a> CheckLoanCtxt<'a> {
self.bccx.span_note(
loan_span,
format!("borrow of `{}` occurs here",
self.bccx.loan_path_to_str(loan_path)));
self.bccx.loan_path_to_str(&*loan_path)));
}
}
true
@ -712,13 +714,12 @@ impl<'a> CheckLoanCtxt<'a> {
span: Span) {
for cap_var in self.bccx.capture_map.get(&closure_id).iter() {
let var_id = ast_util::def_id_of_def(cap_var.def).node;
let var_path = @LpVar(var_id);
self.check_if_path_is_moved(closure_id, span,
MovedInCapture, var_path);
MovedInCapture, &Rc::new(LpVar(var_id)));
match cap_var.mode {
moves::CapRef | moves::CapCopy => {}
moves::CapMove => {
check_by_move_capture(self, closure_id, cap_var, var_path);
check_by_move_capture(self, closure_id, cap_var, &LpVar(var_id));
}
}
}
@ -727,7 +728,7 @@ impl<'a> CheckLoanCtxt<'a> {
fn check_by_move_capture(this: &CheckLoanCtxt,
closure_id: ast::NodeId,
cap_var: &moves::CaptureVar,
move_path: @LoanPath) {
move_path: &LoanPath) {
let move_err = this.analyze_move_out_from(closure_id, move_path);
match move_err {
MoveOk => {}
@ -740,7 +741,7 @@ impl<'a> CheckLoanCtxt<'a> {
this.bccx.span_note(
loan_span,
format!("borrow of `{}` occurs here",
this.bccx.loan_path_to_str(loan_path)));
this.bccx.loan_path_to_str(&*loan_path)));
}
}
}
@ -748,7 +749,7 @@ impl<'a> CheckLoanCtxt<'a> {
pub fn analyze_move_out_from(&self,
expr_id: ast::NodeId,
mut move_path: @LoanPath)
move_path: &LoanPath)
-> MoveError {
debug!("analyze_move_out_from(expr_id={:?}, move_path={})",
self.tcx().map.node_to_str(expr_id),
@ -756,22 +757,23 @@ impl<'a> CheckLoanCtxt<'a> {
// We must check every element of a move path. See
// `borrowck-move-subcomponent.rs` for a test case.
loop {
// check for a conflicting loan:
let mut ret = MoveOk;
self.each_in_scope_restriction(expr_id, move_path, |loan, _| {
// Any restriction prevents moves.
ret = MoveWhileBorrowed(loan.loan_path, loan.span);
false
});
if ret != MoveOk {
return ret
}
// check for a conflicting loan:
let mut ret = MoveOk;
self.each_in_scope_restriction(expr_id, move_path, |loan, _| {
// Any restriction prevents moves.
ret = MoveWhileBorrowed(loan.loan_path.clone(), loan.span);
false
});
match *move_path {
LpVar(_) => return MoveOk,
LpExtend(subpath, _, _) => move_path = subpath,
if ret != MoveOk {
return ret
}
match *move_path {
LpVar(_) => MoveOk,
LpExtend(ref subpath, _, _) => {
self.analyze_move_out_from(expr_id, &**subpath)
}
}
}
@ -812,8 +814,7 @@ fn check_loans_in_expr<'a>(this: &mut CheckLoanCtxt<'a>,
if !this.move_data.is_assignee(expr.id) {
let cmt = this.bccx.cat_expr_unadjusted(expr);
debug!("path cmt={}", cmt.repr(this.tcx()));
let r = opt_loan_path(cmt);
for &lp in r.iter() {
for lp in opt_loan_path(cmt).iter() {
this.check_if_path_is_moved(expr.id, expr.span, MovedInUse, lp);
}
}

View File

@ -30,12 +30,14 @@ struct GatherMoveInfo {
span_path_opt: Option<MoveSpanAndPath>
}
use std::rc::Rc;
pub fn gather_decl(bccx: &BorrowckCtxt,
move_data: &MoveData,
decl_id: ast::NodeId,
_decl_span: Span,
var_id: ast::NodeId) {
let loan_path = @LpVar(var_id);
let loan_path = Rc::new(LpVar(var_id));
move_data.add_move(bccx.tcx, loan_path, decl_id, Declared);
}
@ -131,7 +133,7 @@ pub fn gather_assignment(bccx: &BorrowckCtxt,
move_data: &MoveData,
assignment_id: ast::NodeId,
assignment_span: Span,
assignee_loan_path: @LoanPath,
assignee_loan_path: Rc<LoanPath>,
assignee_id: ast::NodeId) {
move_data.add_assignment(bccx.tcx,
assignee_loan_path,
@ -145,7 +147,7 @@ pub fn gather_move_and_assignment(bccx: &BorrowckCtxt,
move_data: &MoveData,
assignment_id: ast::NodeId,
assignment_span: Span,
assignee_loan_path: @LoanPath,
assignee_loan_path: Rc<LoanPath>,
assignee_id: ast::NodeId) {
move_data.add_assignment(bccx.tcx,
assignee_loan_path,

View File

@ -36,6 +36,8 @@ use syntax::visit;
use syntax::visit::{Visitor, FnKind};
use syntax::ast::{Expr, FnDecl, Block, NodeId, Stmt, Pat, Local};
use std::rc::Rc;
mod lifetime;
mod restrictions;
mod gather_moves;
@ -296,7 +298,7 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
}
}
fn with_assignee_loan_path(bccx: &BorrowckCtxt, expr: &ast::Expr, op: |@LoanPath|) {
fn with_assignee_loan_path(bccx: &BorrowckCtxt, expr: &ast::Expr, op: |Rc<LoanPath>|) {
let cmt = bccx.cat_expr(expr);
match opt_loan_path(cmt) {
Some(lp) => op(lp),
@ -611,11 +613,11 @@ impl<'a> GatherLoanCtxt<'a> {
let gen_scope = self.compute_gen_scope(borrow_id, loan_scope);
debug!("gen_scope = {:?}", gen_scope);
let kill_scope = self.compute_kill_scope(loan_scope, loan_path);
let kill_scope = self.compute_kill_scope(loan_scope, &*loan_path);
debug!("kill_scope = {:?}", kill_scope);
if req_kind == ty::MutBorrow {
self.mark_loan_path_as_mutated(loan_path);
self.mark_loan_path_as_mutated(&*loan_path);
}
Loan {
@ -717,7 +719,7 @@ impl<'a> GatherLoanCtxt<'a> {
}
}
pub fn mark_loan_path_as_mutated(&self, loan_path: @LoanPath) {
pub fn mark_loan_path_as_mutated(&self, loan_path: &LoanPath) {
//! For mutable loans of content whose mutability derives
//! from a local variable, mark the mutability decl as necessary.
@ -725,8 +727,8 @@ impl<'a> GatherLoanCtxt<'a> {
LpVar(local_id) => {
self.tcx().used_mut_nodes.borrow_mut().insert(local_id);
}
LpExtend(base, mc::McInherited, _) => {
self.mark_loan_path_as_mutated(base);
LpExtend(ref base, mc::McInherited, _) => {
self.mark_loan_path_as_mutated(&**base);
}
LpExtend(_, mc::McDeclared, _) |
LpExtend(_, mc::McImmutable, _) => {
@ -751,7 +753,7 @@ impl<'a> GatherLoanCtxt<'a> {
}
}
pub fn compute_kill_scope(&self, loan_scope: ast::NodeId, lp: @LoanPath)
pub fn compute_kill_scope(&self, loan_scope: ast::NodeId, lp: &LoanPath)
-> ast::NodeId {
//! Determine when the loan restrictions go out of scope.
//! This is either when the lifetime expires or when the
@ -826,7 +828,7 @@ impl<'a> GatherLoanCtxt<'a> {
&self.move_data,
id,
span,
@LpVar(id),
Rc::new(LpVar(id)),
id);
});

View File

@ -18,9 +18,11 @@ use middle::ty;
use syntax::codemap::Span;
use util::ppaux::Repr;
use std::rc::Rc;
pub enum RestrictionResult {
Safe,
SafeIf(@LoanPath, Vec<Restriction> )
SafeIf(Rc<LoanPath>, Vec<Restriction>)
}
pub fn compute_restrictions(bccx: &BorrowckCtxt,
@ -73,9 +75,11 @@ impl<'a> RestrictionsContext<'a> {
mc::cat_arg(local_id) |
mc::cat_upvar(ty::UpvarId {var_id: local_id, ..}, _) => {
// R-Variable
let lp = @LpVar(local_id);
SafeIf(lp, vec!(Restriction {loan_path: lp,
set: restrictions}))
let lp = Rc::new(LpVar(local_id));
SafeIf(lp.clone(), vec!(Restriction {
loan_path: lp,
set: restrictions
}))
}
mc::cat_downcast(cmt_base) => {
@ -170,9 +174,13 @@ impl<'a> RestrictionsContext<'a> {
restrictions: RestrictionSet) -> RestrictionResult {
match result {
Safe => Safe,
SafeIf(base_lp, base_vec) => {
let lp = @LpExtend(base_lp, mc, elem);
SafeIf(lp, base_vec.append_one(Restriction { loan_path: lp, set: restrictions }))
SafeIf(base_lp, mut base_vec) => {
let lp = Rc::new(LpExtend(base_lp, mc, elem));
base_vec.push(Restriction {
loan_path: lp.clone(),
set: restrictions
});
SafeIf(lp, base_vec)
}
}
}

View File

@ -21,11 +21,11 @@ use middle::dataflow::DataFlowOperator;
use util::nodemap::{NodeMap, NodeSet};
use util::ppaux::{note_and_explain_region, Repr, UserString};
use std::cell::{Cell, RefCell};
use collections::HashMap;
use std::cell::RefCell;
use std::ops::{BitOr, BitAnd};
use std::result::Result;
use std::rc::Rc;
use std::strbuf::StrBuf;
use collections::HashMap;
use syntax::ast;
use syntax::ast_map;
use syntax::ast_util;
@ -86,36 +86,12 @@ pub fn check_crate(tcx: &ty::ctxt,
moves_map: moves_map,
moved_variables_set: moved_variables_set,
capture_map: capture_map,
root_map: RefCell::new(HashMap::new()),
stats: @BorrowStats {
loaned_paths_same: Cell::new(0),
loaned_paths_imm: Cell::new(0),
stable_paths: Cell::new(0),
guaranteed_paths: Cell::new(0),
}
root_map: RefCell::new(HashMap::new())
};
visit::walk_crate(&mut bccx, krate, ());
if tcx.sess.borrowck_stats() {
println!("--- borrowck stats ---");
println!("paths requiring guarantees: {}",
bccx.stats.guaranteed_paths.get());
println!("paths requiring loans : {}",
make_stat(&bccx, bccx.stats.loaned_paths_same.get()));
println!("paths requiring imm loans : {}",
make_stat(&bccx, bccx.stats.loaned_paths_imm.get()));
println!("stable paths : {}",
make_stat(&bccx, bccx.stats.stable_paths.get()));
}
return bccx.root_map.unwrap();
fn make_stat(bccx: &BorrowckCtxt, stat: uint) -> ~str {
let stat_f = stat as f64;
let total = bccx.stats.guaranteed_paths.get() as f64;
format!("{} ({:.0f}%)", stat, stat_f * 100.0 / total)
}
}
fn borrowck_item(this: &mut BorrowckCtxt, item: &ast::Item) {
@ -175,16 +151,6 @@ pub struct BorrowckCtxt<'a> {
moved_variables_set: &'a NodeSet,
capture_map: &'a moves::CaptureMap,
root_map: RefCell<root_map>,
// Statistics:
stats: @BorrowStats
}
pub struct BorrowStats {
loaned_paths_same: Cell<uint>,
loaned_paths_imm: Cell<uint>,
stable_paths: Cell<uint>,
guaranteed_paths: Cell<uint>,
}
// The keys to the root map combine the `id` of the deref expression
@ -220,10 +186,10 @@ pub enum PartialTotal {
/// Record of a loan that was issued.
pub struct Loan {
index: uint,
loan_path: @LoanPath,
loan_path: Rc<LoanPath>,
cmt: mc::cmt,
kind: ty::BorrowKind,
restrictions: Vec<Restriction> ,
restrictions: Vec<Restriction>,
gen_scope: ast::NodeId,
kill_scope: ast::NodeId,
span: Span,
@ -241,7 +207,7 @@ pub enum LoanCause {
#[deriving(Eq, TotalEq, Hash)]
pub enum LoanPath {
LpVar(ast::NodeId), // `x` in doc.rs
LpExtend(@LoanPath, mc::MutabilityCategory, LoanPathElem)
LpExtend(Rc<LoanPath>, mc::MutabilityCategory, LoanPathElem)
}
#[deriving(Eq, TotalEq, Hash)]
@ -254,12 +220,12 @@ impl LoanPath {
pub fn node_id(&self) -> ast::NodeId {
match *self {
LpVar(local_id) => local_id,
LpExtend(base, _, _) => base.node_id()
LpExtend(ref base, _, _) => base.node_id()
}
}
}
pub fn opt_loan_path(cmt: mc::cmt) -> Option<@LoanPath> {
pub fn opt_loan_path(cmt: mc::cmt) -> Option<Rc<LoanPath>> {
//! Computes the `LoanPath` (if any) for a `cmt`.
//! Note that this logic is somewhat duplicated in
//! the method `compute()` found in `gather_loans::restrictions`,
@ -277,18 +243,18 @@ pub fn opt_loan_path(cmt: mc::cmt) -> Option<@LoanPath> {
mc::cat_arg(id) |
mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: id, .. }) |
mc::cat_upvar(ty::UpvarId {var_id: id, ..}, _) => {
Some(@LpVar(id))
Some(Rc::new(LpVar(id)))
}
mc::cat_deref(cmt_base, _, pk) => {
opt_loan_path(cmt_base).map(|lp| {
@LpExtend(lp, cmt.mutbl, LpDeref(pk))
Rc::new(LpExtend(lp, cmt.mutbl, LpDeref(pk)))
})
}
mc::cat_interior(cmt_base, ik) => {
opt_loan_path(cmt_base).map(|lp| {
@LpExtend(lp, cmt.mutbl, LpInterior(ik))
Rc::new(LpExtend(lp, cmt.mutbl, LpInterior(ik)))
})
}
@ -313,7 +279,7 @@ pub fn opt_loan_path(cmt: mc::cmt) -> Option<@LoanPath> {
// because the restriction against moves is implied.
pub struct Restriction {
loan_path: @LoanPath,
loan_path: Rc<LoanPath>,
set: RestrictionSet
}
@ -528,7 +494,7 @@ impl<'a> BorrowckCtxt<'a> {
use_kind: MovedValueUseKind,
lp: &LoanPath,
move: &move_data::Move,
moved_lp: @LoanPath) {
moved_lp: &LoanPath) {
let verb = match use_kind {
MovedInUse => "use",
MovedInCapture => "capture",
@ -651,7 +617,7 @@ impl<'a> BorrowckCtxt<'a> {
Some(lp) => format!("{} {} `{}`",
err.cmt.mutbl.to_user_str(),
self.cmt_to_str(err.cmt),
self.loan_path_to_str(lp)),
self.loan_path_to_str(&*lp)),
};
match err.cause {
@ -669,13 +635,13 @@ impl<'a> BorrowckCtxt<'a> {
err_out_of_scope(..) => {
let msg = match opt_loan_path(err.cmt) {
None => format!("borrowed value"),
Some(lp) => format!("`{}`", self.loan_path_to_str(lp)),
Some(lp) => format!("`{}`", self.loan_path_to_str(&*lp)),
};
format!("{} does not live long enough", msg)
}
err_borrowed_pointer_too_short(..) => {
let descr = match opt_loan_path(err.cmt) {
Some(lp) => format!("`{}`", self.loan_path_to_str(lp)),
Some(lp) => format!("`{}`", self.loan_path_to_str(&*lp)),
None => self.cmt_to_str(err.cmt),
};
@ -769,7 +735,7 @@ impl<'a> BorrowckCtxt<'a> {
err_borrowed_pointer_too_short(loan_scope, ptr_scope, _) => {
let descr = match opt_loan_path(err.cmt) {
Some(lp) => format!("`{}`", self.loan_path_to_str(lp)),
Some(lp) => format!("`{}`", self.loan_path_to_str(&*lp)),
None => self.cmt_to_str(err.cmt),
};
note_and_explain_region(
@ -794,8 +760,8 @@ impl<'a> BorrowckCtxt<'a> {
out.push_str(ty::local_var_name_str(self.tcx, id).get());
}
LpExtend(lp_base, _, LpInterior(mc::InteriorField(fname))) => {
self.append_autoderefd_loan_path_to_str(lp_base, out);
LpExtend(ref lp_base, _, LpInterior(mc::InteriorField(fname))) => {
self.append_autoderefd_loan_path_to_str(&**lp_base, out);
match fname {
mc::NamedField(fname) => {
out.push_char('.');
@ -808,14 +774,14 @@ impl<'a> BorrowckCtxt<'a> {
}
}
LpExtend(lp_base, _, LpInterior(mc::InteriorElement(_))) => {
self.append_autoderefd_loan_path_to_str(lp_base, out);
LpExtend(ref lp_base, _, LpInterior(mc::InteriorElement(_))) => {
self.append_autoderefd_loan_path_to_str(&**lp_base, out);
out.push_str("[..]");
}
LpExtend(lp_base, _, LpDeref(_)) => {
LpExtend(ref lp_base, _, LpDeref(_)) => {
out.push_char('*');
self.append_loan_path_to_str(lp_base, out);
self.append_loan_path_to_str(&**lp_base, out);
}
}
}
@ -824,11 +790,11 @@ impl<'a> BorrowckCtxt<'a> {
loan_path: &LoanPath,
out: &mut StrBuf) {
match *loan_path {
LpExtend(lp_base, _, LpDeref(_)) => {
LpExtend(ref lp_base, _, LpDeref(_)) => {
// For a path like `(*x).f` or `(*x)[3]`, autoderef
// rules would normally allow users to omit the `*x`.
// So just serialize such paths to `x.f` or x[3]` respectively.
self.append_autoderefd_loan_path_to_str(lp_base, out)
self.append_autoderefd_loan_path_to_str(&**lp_base, out)
}
LpVar(..) | LpExtend(_, _, LpInterior(..)) => {
@ -887,11 +853,11 @@ impl Repr for LoanPath {
format!("$({})", tcx.map.node_to_str(id))
}
&LpExtend(lp, _, LpDeref(_)) => {
&LpExtend(ref lp, _, LpDeref(_)) => {
format!("{}.*", lp.repr(tcx))
}
&LpExtend(lp, _, LpInterior(ref interior)) => {
&LpExtend(ref lp, _, LpInterior(ref interior)) => {
format!("{}.{}", lp.repr(tcx), interior.repr(tcx))
}
}

View File

@ -16,6 +16,7 @@ comments in the section "Moves and initialization" and in `doc.rs`.
*/
use std::cell::RefCell;
use std::rc::Rc;
use std::uint;
use collections::{HashMap, HashSet};
use middle::borrowck::*;
@ -32,7 +33,7 @@ pub struct MoveData {
pub paths: RefCell<Vec<MovePath>>,
/// Cache of loan path to move path index, for easy lookup.
pub path_map: RefCell<HashMap<@LoanPath, MovePathIndex>>,
pub path_map: RefCell<HashMap<Rc<LoanPath>, MovePathIndex>>,
/// Each move or uninitialized variable gets an entry here.
pub moves: RefCell<Vec<Move>>,
@ -96,7 +97,7 @@ static InvalidMoveIndex: MoveIndex =
pub struct MovePath {
/// Loan path corresponding to this move path
pub loan_path: @LoanPath,
pub loan_path: Rc<LoanPath>,
/// Parent pointer, `InvalidMovePathIndex` if root
pub parent: MovePathIndex,
@ -181,8 +182,8 @@ impl MoveData {
}
}
fn path_loan_path(&self, index: MovePathIndex) -> @LoanPath {
self.paths.borrow().get(index.get()).loan_path
fn path_loan_path(&self, index: MovePathIndex) -> Rc<LoanPath> {
self.paths.borrow().get(index.get()).loan_path.clone()
}
fn path_parent(&self, index: MovePathIndex) -> MovePathIndex {
@ -225,7 +226,7 @@ impl MoveData {
pub fn move_path(&self,
tcx: &ty::ctxt,
lp: @LoanPath) -> MovePathIndex {
lp: Rc<LoanPath>) -> MovePathIndex {
/*!
* Returns the existing move path index for `lp`, if any,
* and otherwise adds a new index for `lp` and any of its
@ -244,7 +245,7 @@ impl MoveData {
let index = MovePathIndex(self.paths.borrow().len());
self.paths.borrow_mut().push(MovePath {
loan_path: lp,
loan_path: lp.clone(),
parent: InvalidMovePathIndex,
first_move: InvalidMoveIndex,
first_child: InvalidMovePathIndex,
@ -254,8 +255,8 @@ impl MoveData {
index
}
LpExtend(base, _, _) => {
let parent_index = self.move_path(tcx, base);
LpExtend(ref base, _, _) => {
let parent_index = self.move_path(tcx, base.clone());
let index = MovePathIndex(self.paths.borrow().len());
@ -263,7 +264,7 @@ impl MoveData {
self.set_path_first_child(parent_index, index);
self.paths.borrow_mut().push(MovePath {
loan_path: lp,
loan_path: lp.clone(),
parent: parent_index,
first_move: InvalidMoveIndex,
first_child: InvalidMovePathIndex,
@ -283,29 +284,26 @@ impl MoveData {
return index;
}
fn existing_move_path(&self,
lp: @LoanPath)
fn existing_move_path(&self, lp: &Rc<LoanPath>)
-> Option<MovePathIndex> {
self.path_map.borrow().find_copy(&lp)
self.path_map.borrow().find_copy(lp)
}
fn existing_base_paths(&self,
lp: @LoanPath)
fn existing_base_paths(&self, lp: &Rc<LoanPath>)
-> Vec<MovePathIndex> {
let mut result = vec!();
self.add_existing_base_paths(lp, &mut result);
result
}
fn add_existing_base_paths(&self,
lp: @LoanPath,
fn add_existing_base_paths(&self, lp: &Rc<LoanPath>,
result: &mut Vec<MovePathIndex>) {
/*!
* Adds any existing move path indices for `lp` and any base
* paths of `lp` to `result`, but does not add new move paths
*/
match self.path_map.borrow().find_copy(&lp) {
match self.path_map.borrow().find_copy(lp) {
Some(index) => {
self.each_base_path(index, |p| {
result.push(p);
@ -313,9 +311,9 @@ impl MoveData {
});
}
None => {
match *lp {
match **lp {
LpVar(..) => { }
LpExtend(b, _, _) => {
LpExtend(ref b, _, _) => {
self.add_existing_base_paths(b, result);
}
}
@ -326,7 +324,7 @@ impl MoveData {
pub fn add_move(&self,
tcx: &ty::ctxt,
lp: @LoanPath,
lp: Rc<LoanPath>,
id: ast::NodeId,
kind: MoveKind) {
/*!
@ -355,7 +353,7 @@ impl MoveData {
pub fn add_assignment(&self,
tcx: &ty::ctxt,
lp: @LoanPath,
lp: Rc<LoanPath>,
assign_id: ast::NodeId,
span: Span,
assignee_id: ast::NodeId,
@ -368,7 +366,7 @@ impl MoveData {
debug!("add_assignment(lp={}, assign_id={:?}, assignee_id={:?}",
lp.repr(tcx), assign_id, assignee_id);
let path_index = self.move_path(tcx, lp);
let path_index = self.move_path(tcx, lp.clone());
if !is_also_move {
self.assignee_ids.borrow_mut().insert(assignee_id);
@ -535,7 +533,7 @@ impl<'a> FlowedMoveData<'a> {
pub fn each_path_moved_by(&self,
id: ast::NodeId,
f: |&Move, @LoanPath| -> bool)
f: |&Move, &LoanPath| -> bool)
-> bool {
/*!
* Iterates through each path moved by `id`
@ -545,14 +543,14 @@ impl<'a> FlowedMoveData<'a> {
let move = self.move_data.moves.borrow();
let move = move.get(index);
let moved_path = move.path;
f(move, self.move_data.path_loan_path(moved_path))
f(move, &*self.move_data.path_loan_path(moved_path))
})
}
pub fn each_move_of(&self,
id: ast::NodeId,
loan_path: @LoanPath,
f: |&Move, @LoanPath| -> bool)
loan_path: &Rc<LoanPath>,
f: |&Move, &LoanPath| -> bool)
-> bool {
/*!
* Iterates through each move of `loan_path` (or some base path
@ -587,7 +585,7 @@ impl<'a> FlowedMoveData<'a> {
if base_indices.iter().any(|x| x == &moved_path) {
// Scenario 1 or 2: `loan_path` or some base path of
// `loan_path` was moved.
if !f(move, self.move_data.path_loan_path(moved_path)) {
if !f(move, &*self.move_data.path_loan_path(moved_path)) {
ret = false;
}
} else {
@ -596,7 +594,7 @@ impl<'a> FlowedMoveData<'a> {
if p == loan_path_index {
// Scenario 3: some extension of `loan_path`
// was moved
f(move, self.move_data.path_loan_path(moved_path))
f(move, &*self.move_data.path_loan_path(moved_path))
} else {
true
}
@ -617,7 +615,7 @@ impl<'a> FlowedMoveData<'a> {
pub fn each_assignment_of(&self,
id: ast::NodeId,
loan_path: @LoanPath,
loan_path: &Rc<LoanPath>,
f: |&Assignment| -> bool)
-> bool {
/*!