diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index 3c3c4371ebb..b92a23a53ee 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -82,10 +82,12 @@ impl<'a> visit::Visitor<()> for GatherLoanCtxt<'a> { fn visit_block(&mut self, b: &Block, _: ()) { gather_loans_in_block(self, b); } - fn visit_fn(&mut self, fk: &FnKind, fd: &FnDecl, b: &Block, - s: Span, n: NodeId, _: ()) { - gather_loans_in_fn(self, fk, fd, b, s, n); - } + + /// Do not visit closures or fn items here, the outer loop in + /// borrowck/mod will visit them for us in turn. + fn visit_fn(&mut self, _: &FnKind, _: &FnDecl, _: &Block, + _: Span, _: NodeId, _: ()) {} + fn visit_stmt(&mut self, s: &Stmt, _: ()) { visit::walk_stmt(self, s, ()); } @@ -99,10 +101,20 @@ impl<'a> visit::Visitor<()> for GatherLoanCtxt<'a> { // #7740: Do not visit items here, not even fn items nor methods // of impl items; the outer loop in borrowck/mod will visit them // for us in turn. Thus override visit_item's walk with a no-op. - fn visit_item(&mut self, _: &ast::Item, _: ()) { } + fn visit_item(&mut self, _: &ast::Item, _: ()) {} } -pub fn gather_loans(bccx: &BorrowckCtxt, decl: &ast::FnDecl, body: &ast::Block) +fn add_pat_to_id_range(this: &mut GatherLoanCtxt, + p: &ast::Pat) { + // NB: This visitor function just adds the pat ids into the id + // range. We gather loans that occur in patterns using the + // `gather_pat()` method below. Eventually these two should be + // brought together. + this.id_range.add(p.id); + visit::walk_pat(this, p, ()); +} + +pub fn gather_loans_in_fn(bccx: &BorrowckCtxt, decl: &ast::FnDecl, body: &ast::Block) -> (IdRange, Vec, move_data::MoveData) { let mut glcx = GatherLoanCtxt { bccx: bccx, @@ -119,27 +131,6 @@ pub fn gather_loans(bccx: &BorrowckCtxt, decl: &ast::FnDecl, body: &ast::Block) (id_range, all_loans, move_data) } -fn add_pat_to_id_range(this: &mut GatherLoanCtxt, - p: &ast::Pat) { - // NB: This visitor function just adds the pat ids into the id - // range. We gather loans that occur in patterns using the - // `gather_pat()` method below. Eventually these two should be - // brought together. - this.id_range.add(p.id); - visit::walk_pat(this, p, ()); -} - -fn gather_loans_in_fn(_v: &mut GatherLoanCtxt, - _fk: &FnKind, - _decl: &ast::FnDecl, - _body: &ast::Block, - _sp: Span, - _id: ast::NodeId) { - // Do not visit closures or fn items here, the outer loop in - // borrowck/mod will visit them for us in turn. - return; -} - fn gather_loans_in_block(this: &mut GatherLoanCtxt, blk: &ast::Block) { this.id_range.add(blk.id); @@ -171,6 +162,28 @@ fn gather_loans_in_local(this: &mut GatherLoanCtxt, visit::walk_local(this, local, ()); } +pub fn gather_loans_in_static_initializer(bccx: &mut BorrowckCtxt, expr: &ast::Expr) { + + debug!("gather_loans_in_item(expr={})", expr.repr(bccx.tcx)); + + let mut glcx = GatherLoanCtxt { + bccx: bccx, + id_range: IdRange::max(), + all_loans: Vec::new(), + item_ub: expr.id, + repeating_ids: vec!(expr.id), + move_data: MoveData::new() + }; + + match expr.node { + // Just visit the expression if the + // item is taking an address. + ast::ExprAddrOf(..) => { + glcx.visit_expr(expr, ()); + } + _ => {} + } +} fn gather_loans_in_expr(this: &mut GatherLoanCtxt, ex: &ast::Expr) { diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index bb6956556b5..9657e935873 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -69,6 +69,10 @@ impl<'a> Visitor<()> for BorrowckCtxt<'a> { b: &Block, s: Span, n: NodeId, _: ()) { borrowck_fn(self, fk, fd, b, s, n); } + + fn visit_item(&mut self, item: &ast::Item, _: ()) { + borrowck_item(self, item); + } } pub fn check_crate(tcx: &ty::ctxt, @@ -117,6 +121,20 @@ pub fn check_crate(tcx: &ty::ctxt, } } +fn borrowck_item(this: &mut BorrowckCtxt, item: &ast::Item) { + // Gather loans for items. Note that we don't need + // to check loans for single expressions. The check + // loan step is intended for things that have a data + // flow dependent conditions. + match item.node { + ast::ItemStatic(_, _, ex) => { + gather_loans::gather_loans_in_static_initializer(this, ex); + } + _ => {} + } + visit::walk_item(this, item, ()); +} + fn borrowck_fn(this: &mut BorrowckCtxt, fk: &FnKind, decl: &ast::FnDecl, @@ -127,7 +145,7 @@ fn borrowck_fn(this: &mut BorrowckCtxt, // Check the body of fn items. let (id_range, all_loans, move_data) = - gather_loans::gather_loans(this, decl, body); + gather_loans::gather_loans_in_fn(this, decl, body); let mut loan_dfcx = DataFlowContext::new(this.tcx, this.method_map,