diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 15fbaf44d89..13849512ba6 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -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, /*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) { /*! * 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); } } diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs index f250b105d0b..b44db1f3fc9 100644 --- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs @@ -30,12 +30,14 @@ struct GatherMoveInfo { span_path_opt: Option } +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, 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, assignee_id: ast::NodeId) { move_data.add_assignment(bccx.tcx, assignee_loan_path, diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index ef98cdc0cae..106c2a5ee52 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -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|) { 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); }); diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs index 39ea9e17b26..c4e1b0bf27f 100644 --- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs +++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs @@ -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 ) + SafeIf(Rc, Vec) } 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) } } } diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index df8d882864e..ba01e4aa418 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -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, - - // Statistics: - stats: @BorrowStats -} - -pub struct BorrowStats { - loaned_paths_same: Cell, - loaned_paths_imm: Cell, - stable_paths: Cell, - guaranteed_paths: Cell, } // 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, cmt: mc::cmt, kind: ty::BorrowKind, - restrictions: Vec , + restrictions: Vec, 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, 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> { //! 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, 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)) } } diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs index b35eefcc73f..efdc103d14d 100644 --- a/src/librustc/middle/borrowck/move_data.rs +++ b/src/librustc/middle/borrowck/move_data.rs @@ -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>, /// Cache of loan path to move path index, for easy lookup. - pub path_map: RefCell>, + pub path_map: RefCell, MovePathIndex>>, /// Each move or uninitialized variable gets an entry here. pub moves: RefCell>, @@ -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, /// 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 { + 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) -> 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) -> Option { - 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) -> Vec { 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, result: &mut Vec) { /*! * 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, id: ast::NodeId, kind: MoveKind) { /*! @@ -355,7 +353,7 @@ impl MoveData { pub fn add_assignment(&self, tcx: &ty::ctxt, - lp: @LoanPath, + lp: Rc, 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, + 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, f: |&Assignment| -> bool) -> bool { /*!