Skip to content

Commit

Permalink
Add ty to LoanPath.
Browse files Browse the repository at this point in the history
To make this clean, refactored old `LoanPath` enum into a
`LoanPath` struct with a `ty::t` and a newly-added `LoanPathVariant` enum.

This enabled me to get rid of the ugly and fragile `LoanPath::to_type`
method, and I can probably also get rid of other stuff that was
supporting it, maybe.
  • Loading branch information
pnkfelix committed Nov 25, 2014
1 parent d6c8f3b commit 91b88c5
Show file tree
Hide file tree
Showing 8 changed files with 206 additions and 175 deletions.
82 changes: 42 additions & 40 deletions src/librustc/middle/borrowck/check_loans.rs
Expand Up @@ -19,6 +19,8 @@
use self::UseError::*;

use middle::borrowck::*;
use middle::borrowck::LoanPathElem::*;
use middle::borrowck::LoanPathKind::*;
use middle::expr_use_visitor as euv;
use middle::mem_categorization as mc;
use middle::region;
Expand All @@ -33,51 +35,51 @@ use std::rc::Rc;
// be less precise in its handling of Box while still allowing moves out of a
// Box. They should be removed when OwnedPtr is removed from LoanPath.

fn owned_ptr_base_path<'a>(loan_path: &'a LoanPath) -> &'a LoanPath {
fn owned_ptr_base_path<'a, 'tcx>(loan_path: &'a LoanPath<'tcx>) -> &'a LoanPath<'tcx> {
//! Returns the base of the leftmost dereference of an OwnedPtr in
//! `loan_path`. If there is no dereference of an OwnedPtr in `loan_path`,
//! then it just returns `loan_path` itself.

return match owned_ptr_base_path_helper(loan_path) {
return match helper(loan_path) {
Some(new_loan_path) => new_loan_path,
None => loan_path.clone()
};

fn owned_ptr_base_path_helper<'a>(loan_path: &'a LoanPath) -> Option<&'a LoanPath> {
match *loan_path {
fn helper<'a, 'tcx>(loan_path: &'a LoanPath<'tcx>) -> Option<&'a LoanPath<'tcx>> {
match loan_path.kind {
LpVar(_) | LpUpvar(_) => None,
LpExtend(ref lp_base, _, LpDeref(mc::OwnedPtr)) => {
match owned_ptr_base_path_helper(&**lp_base) {
match helper(&**lp_base) {
v @ Some(_) => v,
None => Some(&**lp_base)
}
}
LpDowncast(ref lp_base, _) |
LpExtend(ref lp_base, _, _) => owned_ptr_base_path_helper(&**lp_base)
LpExtend(ref lp_base, _, _) => helper(&**lp_base)
}
}
}

fn owned_ptr_base_path_rc(loan_path: &Rc<LoanPath>) -> Rc<LoanPath> {
fn owned_ptr_base_path_rc<'tcx>(loan_path: &Rc<LoanPath<'tcx>>) -> Rc<LoanPath<'tcx>> {
//! The equivalent of `owned_ptr_base_path` for an &Rc<LoanPath> rather than
//! a &LoanPath.

return match owned_ptr_base_path_helper(loan_path) {
return match helper(loan_path) {
Some(new_loan_path) => new_loan_path,
None => loan_path.clone()
};

fn owned_ptr_base_path_helper(loan_path: &Rc<LoanPath>) -> Option<Rc<LoanPath>> {
match **loan_path {
fn helper<'tcx>(loan_path: &Rc<LoanPath<'tcx>>) -> Option<Rc<LoanPath<'tcx>>> {
match loan_path.kind {
LpVar(_) | LpUpvar(_) => None,
LpExtend(ref lp_base, _, LpDeref(mc::OwnedPtr)) => {
match owned_ptr_base_path_helper(lp_base) {
match helper(lp_base) {
v @ Some(_) => v,
None => Some(lp_base.clone())
}
}
LpDowncast(ref lp_base, _) |
LpExtend(ref lp_base, _, _) => owned_ptr_base_path_helper(lp_base)
LpExtend(ref lp_base, _, _) => helper(lp_base)
}
}
}
Expand All @@ -86,7 +88,7 @@ struct CheckLoanCtxt<'a, 'tcx: 'a> {
bccx: &'a BorrowckCtxt<'a, 'tcx>,
dfcx_loans: &'a LoanDataFlow<'a, 'tcx>,
move_data: move_data::FlowedMoveData<'a, 'tcx>,
all_loans: &'a [Loan],
all_loans: &'a [Loan<'tcx>],
}

impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
Expand Down Expand Up @@ -185,7 +187,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
dfcx_loans: &LoanDataFlow<'b, 'tcx>,
move_data: move_data::FlowedMoveData<'c, 'tcx>,
all_loans: &[Loan],
all_loans: &[Loan<'tcx>],
decl: &ast::FnDecl,
body: &ast::Block) {
debug!("check_loans(body id={})", body.id);
Expand All @@ -204,9 +206,9 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
}

#[deriving(PartialEq)]
enum UseError {
enum UseError<'tcx> {
UseOk,
UseWhileBorrowed(/*loan*/Rc<LoanPath>, /*loan*/Span)
UseWhileBorrowed(/*loan*/Rc<LoanPath<'tcx>>, /*loan*/Span)
}

fn compatible_borrow_kinds(borrow_kind1: ty::BorrowKind,
Expand All @@ -218,7 +220,7 @@ fn compatible_borrow_kinds(borrow_kind1: ty::BorrowKind,
impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
pub fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.bccx.tcx }

pub fn each_issued_loan(&self, scope: region::CodeExtent, op: |&Loan| -> bool)
pub fn each_issued_loan(&self, scope: region::CodeExtent, op: |&Loan<'tcx>| -> bool)
-> bool {
//! Iterates over each loan that has been issued
//! on entrance to `scope`, regardless of whether it is
Expand All @@ -234,7 +236,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {

pub fn each_in_scope_loan(&self,
scope: region::CodeExtent,
op: |&Loan| -> bool)
op: |&Loan<'tcx>| -> bool)
-> bool {
//! Like `each_issued_loan()`, but only considers loans that are
//! currently in scope.
Expand All @@ -251,8 +253,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {

fn each_in_scope_loan_affecting_path(&self,
scope: region::CodeExtent,
loan_path: &LoanPath,
op: |&Loan| -> bool)
loan_path: &LoanPath<'tcx>,
op: |&Loan<'tcx>| -> bool)
-> bool {
//! Iterates through all of the in-scope loans affecting `loan_path`,
//! calling `op`, and ceasing iteration if `false` is returned.
Expand Down Expand Up @@ -296,7 +298,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {

let mut loan_path = loan_path;
loop {
match *loan_path {
match loan_path.kind {
LpVar(_) | LpUpvar(_) => {
break;
}
Expand Down Expand Up @@ -366,8 +368,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
}

pub fn report_error_if_loans_conflict(&self,
old_loan: &Loan,
new_loan: &Loan) {
old_loan: &Loan<'tcx>,
new_loan: &Loan<'tcx>) {
//! Checks whether `old_loan` and `new_loan` can safely be issued
//! simultaneously.

Expand All @@ -386,10 +388,10 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
}

pub fn report_error_if_loan_conflicts_with_restriction(&self,
loan1: &Loan,
loan2: &Loan,
old_loan: &Loan,
new_loan: &Loan)
loan1: &Loan<'tcx>,
loan2: &Loan<'tcx>,
old_loan: &Loan<'tcx>,
new_loan: &Loan<'tcx>)
-> bool {
//! Checks whether the restrictions introduced by `loan1` would
//! prohibit `loan2`. Returns false if an error is reported.
Expand Down Expand Up @@ -552,7 +554,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
true
}

fn is_local_variable_or_arg(&self, cmt: mc::cmt) -> bool {
fn is_local_variable_or_arg(&self, cmt: mc::cmt<'tcx>) -> bool {
match cmt.cat {
mc::cat_local(_) => true,
_ => false
Expand All @@ -562,7 +564,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
fn consume_common(&self,
id: ast::NodeId,
span: Span,
cmt: mc::cmt,
cmt: mc::cmt<'tcx>,
mode: euv::ConsumeMode) {
match opt_loan_path(&cmt) {
Some(lp) => {
Expand Down Expand Up @@ -603,7 +605,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
fn check_for_copy_of_frozen_path(&self,
id: ast::NodeId,
span: Span,
copy_path: &LoanPath) {
copy_path: &LoanPath<'tcx>) {
match self.analyze_restrictions_on_use(id, copy_path, ty::ImmBorrow) {
UseOk => { }
UseWhileBorrowed(loan_path, loan_span) => {
Expand All @@ -624,7 +626,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
fn check_for_move_of_borrowed_path(&self,
id: ast::NodeId,
span: Span,
move_path: &LoanPath,
move_path: &LoanPath<'tcx>,
move_kind: move_data::MoveKind) {
// We want to detect if there are any loans at all, so we search for
// any loans incompatible with MutBorrrow, since all other kinds of
Expand Down Expand Up @@ -655,9 +657,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {

pub fn analyze_restrictions_on_use(&self,
expr_id: ast::NodeId,
use_path: &LoanPath,
use_path: &LoanPath<'tcx>,
borrow_kind: ty::BorrowKind)
-> UseError {
-> UseError<'tcx> {
debug!("analyze_restrictions_on_use(expr_id={}, use_path={})",
self.tcx().map.node_to_string(expr_id),
use_path.repr(self.tcx()));
Expand All @@ -681,7 +683,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
id: ast::NodeId,
span: Span,
use_kind: MovedValueUseKind,
lp: &Rc<LoanPath>) {
lp: &Rc<LoanPath<'tcx>>) {
/*!
* Reports an error if `expr` (which should be a path)
* is using a moved/uninitialized value
Expand All @@ -705,7 +707,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
id: ast::NodeId,
span: Span,
use_kind: MovedValueUseKind,
lp: &Rc<LoanPath>)
lp: &Rc<LoanPath<'tcx>>)
{
/*!
* Reports an error if assigning to `lp` will use a
Expand All @@ -725,7 +727,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
* (*p).x = 22; // not ok, p is uninitialized, can't deref
*/

match **lp {
match lp.kind {
LpVar(_) | LpUpvar(_) => {
// assigning to `x` does not require that `x` is initialized
}
Expand Down Expand Up @@ -923,11 +925,11 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
}
}

fn check_for_assignment_to_borrowed_path(
this: &CheckLoanCtxt,
fn check_for_assignment_to_borrowed_path<'a, 'tcx>(
this: &CheckLoanCtxt<'a, 'tcx>,
assignment_id: ast::NodeId,
assignment_span: Span,
assignee_cmt: mc::cmt)
assignee_cmt: mc::cmt<'tcx>)
{
//! Check for assignments that violate the terms of an
//! outstanding loan.
Expand All @@ -947,7 +949,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {

pub fn report_illegal_mutation(&self,
span: Span,
loan_path: &LoanPath,
loan_path: &LoanPath<'tcx>,
loan: &Loan) {
self.bccx.span_err(
span,
Expand Down
34 changes: 18 additions & 16 deletions src/librustc/middle/borrowck/gather_loans/gather_moves.rs
Expand Up @@ -13,6 +13,7 @@
*/

use middle::borrowck::*;
use middle::borrowck::LoanPathKind::*;
use middle::borrowck::gather_loans::move_error::MoveSpanAndPath;
use middle::borrowck::gather_loans::move_error::{MoveError, MoveErrorCollector};
use middle::borrowck::move_data::*;
Expand All @@ -32,17 +33,18 @@ struct GatherMoveInfo<'tcx> {
span_path_opt: Option<MoveSpanAndPath>
}

pub fn gather_decl(bccx: &BorrowckCtxt,
move_data: &MoveData,
decl_id: ast::NodeId,
_decl_span: Span,
var_id: ast::NodeId) {
let loan_path = Rc::new(LpVar(var_id));
pub fn gather_decl<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
move_data: &MoveData<'tcx>,
decl_id: ast::NodeId,
_decl_span: Span,
var_id: ast::NodeId) {
let ty = ty::node_id_to_type(bccx.tcx, var_id);
let loan_path = Rc::new(LoanPath::new(LpVar(var_id), ty));
move_data.add_move(bccx.tcx, loan_path, decl_id, Declared);
}

pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
move_data: &MoveData,
move_data: &MoveData<'tcx>,
move_error_collector: &MoveErrorCollector<'tcx>,
move_expr_id: ast::NodeId,
cmt: mc::cmt<'tcx>,
Expand All @@ -61,7 +63,7 @@ pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
}

pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
move_data: &MoveData,
move_data: &MoveData<'tcx>,
move_error_collector: &MoveErrorCollector<'tcx>,
move_pat: &ast::Pat,
cmt: mc::cmt<'tcx>) {
Expand All @@ -82,7 +84,7 @@ pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
}

fn gather_move<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
move_data: &MoveData,
move_data: &MoveData<'tcx>,
move_error_collector: &MoveErrorCollector<'tcx>,
move_info: GatherMoveInfo<'tcx>) {
debug!("gather_move(move_id={}, cmt={})",
Expand Down Expand Up @@ -112,13 +114,13 @@ fn gather_move<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
}
}

pub fn gather_assignment(bccx: &BorrowckCtxt,
move_data: &MoveData,
assignment_id: ast::NodeId,
assignment_span: Span,
assignee_loan_path: Rc<LoanPath>,
assignee_id: ast::NodeId,
mode: euv::MutateMode) {
pub fn gather_assignment<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
move_data: &MoveData<'tcx>,
assignment_id: ast::NodeId,
assignment_span: Span,
assignee_loan_path: Rc<LoanPath<'tcx>>,
assignee_id: ast::NodeId,
mode: euv::MutateMode) {
move_data.add_assignment(bccx.tcx,
assignee_loan_path,
assignment_id,
Expand Down
17 changes: 9 additions & 8 deletions src/librustc/middle/borrowck/gather_loans/mod.rs
Expand Up @@ -17,6 +17,7 @@
// sure that all of these loans are honored.

use middle::borrowck::*;
use middle::borrowck::LoanPathKind::*;
use middle::borrowck::move_data::MoveData;
use middle::expr_use_visitor as euv;
use middle::mem_categorization as mc;
Expand All @@ -35,10 +36,10 @@ mod restrictions;
mod gather_moves;
mod move_error;

pub fn gather_loans_in_fn(bccx: &BorrowckCtxt,
decl: &ast::FnDecl,
body: &ast::Block)
-> (Vec<Loan>, move_data::MoveData)
pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
decl: &ast::FnDecl,
body: &ast::Block)
-> (Vec<Loan<'tcx>>, move_data::MoveData<'tcx>)
{
let mut glcx = GatherLoanCtxt {
bccx: bccx,
Expand All @@ -60,9 +61,9 @@ pub fn gather_loans_in_fn(bccx: &BorrowckCtxt,

struct GatherLoanCtxt<'a, 'tcx: 'a> {
bccx: &'a BorrowckCtxt<'a, 'tcx>,
move_data: move_data::MoveData,
move_data: move_data::MoveData<'tcx>,
move_error_collector: move_error::MoveErrorCollector<'tcx>,
all_loans: Vec<Loan>,
all_loans: Vec<Loan<'tcx>>,
/// `item_ub` is used as an upper-bound on the lifetime whenever we
/// ask for the scope of an expression categorized as an upvar.
item_ub: region::CodeExtent,
Expand Down Expand Up @@ -395,7 +396,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
//! For mutable loans of content whose mutability derives
//! from a local variable, mark the mutability decl as necessary.

match *loan_path {
match loan_path.kind {
LpVar(local_id) |
LpUpvar(ty::UpvarId{ var_id: local_id, closure_expr_id: _ }) => {
self.tcx().used_mut_nodes.borrow_mut().insert(local_id);
Expand Down Expand Up @@ -427,7 +428,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
}
}

pub fn compute_kill_scope(&self, loan_scope: region::CodeExtent, lp: &LoanPath)
pub fn compute_kill_scope(&self, loan_scope: region::CodeExtent, lp: &LoanPath<'tcx>)
-> region::CodeExtent {
//! Determine when the loan restrictions go out of scope.
//! This is either when the lifetime expires or when the
Expand Down

0 comments on commit 91b88c5

Please sign in to comment.