Skip to content

Commit

Permalink
auto merge of #19033 : pnkfelix/rust/fsk-introduce-scopedata-via-refa…
Browse files Browse the repository at this point in the history
…ctor, r=nikomatsakis

(Previously, scopes were solely identified with NodeId's; this
refactoring prepares for a future where that does not hold.)

Ground work for a proper fix to #8861.
  • Loading branch information
bors committed Nov 20, 2014
2 parents 1d81776 + 5ff9087 commit 394269d
Show file tree
Hide file tree
Showing 25 changed files with 420 additions and 269 deletions.
19 changes: 15 additions & 4 deletions src/librustc/metadata/tydecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

pub use self::DefIdSource::*;

use middle::region;
use middle::subst;
use middle::subst::VecPerParamSpace;
use middle::ty::{mod, Ty};
Expand Down Expand Up @@ -315,17 +316,17 @@ fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region {
}
'f' => {
assert_eq!(next(st), '[');
let id = parse_uint(st) as ast::NodeId;
let scope = parse_scope(st);
assert_eq!(next(st), '|');
let br = parse_bound_region(st, |x,y| conv(x,y));
assert_eq!(next(st), ']');
ty::ReFree(ty::FreeRegion {scope_id: id,
ty::ReFree(ty::FreeRegion { scope: scope,
bound_region: br})
}
's' => {
let id = parse_uint(st) as ast::NodeId;
let scope = parse_scope(st);
assert_eq!(next(st), '|');
ty::ReScope(id)
ty::ReScope(scope)
}
't' => {
ty::ReStatic
Expand All @@ -337,6 +338,16 @@ fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region {
}
}

fn parse_scope(st: &mut PState) -> region::CodeExtent {
match next(st) {
'M' => {
let node_id = parse_uint(st) as ast::NodeId;
region::CodeExtent::Misc(node_id)
}
_ => panic!("parse_scope: bad input")
}
}

fn parse_opt<'a, 'tcx, T>(st: &mut PState<'a, 'tcx>, f: |&mut PState<'a, 'tcx>| -> T)
-> Option<T> {
match next(st) {
Expand Down
17 changes: 14 additions & 3 deletions src/librustc/metadata/tyencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

use std::cell::RefCell;

use middle::region;
use middle::subst;
use middle::subst::VecPerParamSpace;
use middle::ty::ParamTy;
Expand Down Expand Up @@ -143,12 +144,16 @@ pub fn enc_region(w: &mut SeekableMemWriter, cx: &ctxt, r: ty::Region) {
token::get_name(name));
}
ty::ReFree(ref fr) => {
mywrite!(w, "f[{}|", fr.scope_id);
mywrite!(w, "f[");
enc_scope(w, cx, fr.scope);
mywrite!(w, "|");
enc_bound_region(w, cx, fr.bound_region);
mywrite!(w, "]");
}
ty::ReScope(nid) => {
mywrite!(w, "s{}|", nid);
ty::ReScope(scope) => {
mywrite!(w, "s");
enc_scope(w, cx, scope);
mywrite!(w, "|");
}
ty::ReStatic => {
mywrite!(w, "t");
Expand All @@ -163,6 +168,12 @@ pub fn enc_region(w: &mut SeekableMemWriter, cx: &ctxt, r: ty::Region) {
}
}

fn enc_scope(w: &mut SeekableMemWriter, _cx: &ctxt, scope: region::CodeExtent) {
match scope {
region::CodeExtent::Misc(node_id) => mywrite!(w, "M{}", node_id)
}
}

fn enc_bound_region(w: &mut SeekableMemWriter, cx: &ctxt, br: ty::BoundRegion) {
match br {
ty::BrAnon(idx) => {
Expand Down
20 changes: 16 additions & 4 deletions src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,20 +489,32 @@ impl tr for ty::Region {
ty::ReEarlyBound(id, space, index, ident) => {
ty::ReEarlyBound(dcx.tr_id(id), space, index, ident)
}
ty::ReScope(id) => {
ty::ReScope(dcx.tr_id(id))
ty::ReScope(scope) => {
ty::ReScope(scope.tr(dcx))
}
ty::ReEmpty | ty::ReStatic | ty::ReInfer(..) => {
*self
}
ty::ReFree(ref fr) => {
ty::ReFree(ty::FreeRegion {scope_id: dcx.tr_id(fr.scope_id),
bound_region: fr.bound_region.tr(dcx)})
ty::ReFree(fr.tr(dcx))
}
}
}
}

impl tr for ty::FreeRegion {
fn tr(&self, dcx: &DecodeContext) -> ty::FreeRegion {
ty::FreeRegion { scope: self.scope.tr(dcx),
bound_region: self.bound_region.tr(dcx) }
}
}

impl tr for region::CodeExtent {
fn tr(&self, dcx: &DecodeContext) -> region::CodeExtent {
self.map_id(|id| dcx.tr_id(id))
}
}

impl tr for ty::BoundRegion {
fn tr(&self, dcx: &DecodeContext) -> ty::BoundRegion {
match *self {
Expand Down
50 changes: 28 additions & 22 deletions src/librustc/middle/borrowck/check_loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use self::UseError::*;
use middle::borrowck::*;
use middle::expr_use_visitor as euv;
use middle::mem_categorization as mc;
use middle::region;
use middle::ty;
use syntax::ast;
use syntax::codemap::Span;
Expand Down Expand Up @@ -134,7 +135,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
None => { }
}

self.check_for_conflicting_loans(borrow_id);
self.check_for_conflicting_loans(region::CodeExtent::from_node_id(borrow_id));
}

fn mutate(&mut self,
Expand Down Expand Up @@ -215,30 +216,30 @@ 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_id: ast::NodeId, op: |&Loan| -> bool)
pub fn each_issued_loan(&self, scope: region::CodeExtent, op: |&Loan| -> bool)
-> bool {
//! Iterates over each loan that has been issued
//! on entrance to `scope_id`, regardless of whether it is
//! on entrance to `scope`, regardless of whether it is
//! actually *in scope* at that point. Sometimes loans
//! are issued for future scopes and thus they may have been
//! *issued* but not yet be in effect.

self.dfcx_loans.each_bit_on_entry(scope_id, |loan_index| {
self.dfcx_loans.each_bit_on_entry(scope.node_id(), |loan_index| {
let loan = &self.all_loans[loan_index];
op(loan)
})
}

pub fn each_in_scope_loan(&self,
scope_id: ast::NodeId,
scope: region::CodeExtent,
op: |&Loan| -> bool)
-> bool {
//! Like `each_issued_loan()`, but only considers loans that are
//! currently in scope.

let tcx = self.tcx();
self.each_issued_loan(scope_id, |loan| {
if tcx.region_maps.is_subscope_of(scope_id, loan.kill_scope) {
self.each_issued_loan(scope, |loan| {
if tcx.region_maps.is_subscope_of(scope, loan.kill_scope) {
op(loan)
} else {
true
Expand All @@ -247,7 +248,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
}

fn each_in_scope_loan_affecting_path(&self,
scope_id: ast::NodeId,
scope: region::CodeExtent,
loan_path: &LoanPath,
op: |&Loan| -> bool)
-> bool {
Expand All @@ -262,7 +263,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
// let y = a; // Conflicts with restriction

let loan_path = owned_ptr_base_path(loan_path);
let cont = self.each_in_scope_loan(scope_id, |loan| {
let cont = self.each_in_scope_loan(scope, |loan| {
let mut ret = true;
for restr_path in loan.restricted_paths.iter() {
if **restr_path == *loan_path {
Expand Down Expand Up @@ -302,7 +303,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
}
}

let cont = self.each_in_scope_loan(scope_id, |loan| {
let cont = self.each_in_scope_loan(scope, |loan| {
if *loan.loan_path == *loan_path {
op(loan)
} else {
Expand All @@ -318,30 +319,33 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
return true;
}

pub fn loans_generated_by(&self, scope_id: ast::NodeId) -> Vec<uint> {
pub fn loans_generated_by(&self, scope: region::CodeExtent) -> Vec<uint> {
//! Returns a vector of the loans that are generated as
//! we encounter `scope_id`.
//! we enter `scope`.

let mut result = Vec::new();
self.dfcx_loans.each_gen_bit(scope_id, |loan_index| {
self.dfcx_loans.each_gen_bit(scope.node_id(), |loan_index| {
result.push(loan_index);
true
});
return result;
}

pub fn check_for_conflicting_loans(&self, scope_id: ast::NodeId) {
pub fn check_for_conflicting_loans(&self, scope: region::CodeExtent) {
//! Checks to see whether any of the loans that are issued
//! by `scope_id` conflict with loans that have already been
//! issued when we enter `scope_id` (for example, we do not
//! on entrance to `scope` conflict with loans that have already been
//! issued when we enter `scope` (for example, we do not
//! permit two `&mut` borrows of the same variable).
//!
//! (Note that some loans can be *issued* without necessarily
//! taking effect yet.)

debug!("check_for_conflicting_loans(scope_id={})", scope_id);
debug!("check_for_conflicting_loans(scope={})", scope);

let new_loan_indices = self.loans_generated_by(scope_id);
let new_loan_indices = self.loans_generated_by(scope);
debug!("new_loan_indices = {}", new_loan_indices);

self.each_issued_loan(scope_id, |issued_loan| {
self.each_issued_loan(scope, |issued_loan| {
for &new_loan_index in new_loan_indices.iter() {
let new_loan = &self.all_loans[new_loan_index];
self.report_error_if_loans_conflict(issued_loan, new_loan);
Expand Down Expand Up @@ -535,7 +539,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
old_loan.span,
format!("{}; {}", borrow_summary, rule_summary).as_slice());

let old_loan_span = self.tcx().map.span(old_loan.kill_scope);
let old_loan_span = self.tcx().map.span(old_loan.kill_scope.node_id());
self.bccx.span_end_note(old_loan_span,
"previous borrow ends here");

Expand Down Expand Up @@ -657,7 +661,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {

let mut ret = UseOk;

self.each_in_scope_loan_affecting_path(expr_id, use_path, |loan| {
self.each_in_scope_loan_affecting_path(
region::CodeExtent::from_node_id(expr_id), use_path, |loan| {
if !compatible_borrow_kinds(loan.kind, borrow_kind) {
ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span);
false
Expand Down Expand Up @@ -924,7 +929,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
None => { return; /* no loan path, can't be any loans */ }
};

this.each_in_scope_loan_affecting_path(assignment_id, &*loan_path, |loan| {
let scope = region::CodeExtent::from_node_id(assignment_id);
this.each_in_scope_loan_affecting_path(scope, &*loan_path, |loan| {
this.report_illegal_mutation(assignment_span, &*loan_path, loan);
false
});
Expand Down
20 changes: 13 additions & 7 deletions src/librustc/middle/borrowck/gather_loans/lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use middle::borrowck::*;
use middle::expr_use_visitor as euv;
use middle::mem_categorization as mc;
use middle::region;
use middle::ty;
use util::ppaux::Repr;
use syntax::ast;
Expand All @@ -24,17 +25,20 @@ use syntax::codemap::Span;
type R = Result<(),()>;

pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
item_scope_id: ast::NodeId,
item_scope: region::CodeExtent,
span: Span,
cause: euv::LoanCause,
cmt: mc::cmt<'tcx>,
loan_region: ty::Region,
_: ty::BorrowKind)
-> Result<(),()> {
//! Reports error if `loan_region` is larger than S
//! where S is `item_scope` if `cmt` is an upvar,
//! and is scope of `cmt` otherwise.
debug!("guarantee_lifetime(cmt={}, loan_region={})",
cmt.repr(bccx.tcx), loan_region.repr(bccx.tcx));
let ctxt = GuaranteeLifetimeContext {bccx: bccx,
item_scope_id: item_scope_id,
item_scope: item_scope,
span: span,
cause: cause,
loan_region: loan_region,
Expand All @@ -48,8 +52,8 @@ pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
struct GuaranteeLifetimeContext<'a, 'tcx: 'a> {
bccx: &'a BorrowckCtxt<'a, 'tcx>,

// the node id of the function body for the enclosing item
item_scope_id: ast::NodeId,
// the scope of the function body for the enclosing item
item_scope: region::CodeExtent,

span: Span,
cause: euv::LoanCause,
Expand All @@ -60,7 +64,9 @@ struct GuaranteeLifetimeContext<'a, 'tcx: 'a> {
impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {

fn check(&self, cmt: &mc::cmt<'tcx>, discr_scope: Option<ast::NodeId>) -> R {
//! Main routine. Walks down `cmt` until we find the "guarantor".
//! Main routine. Walks down `cmt` until we find the
//! "guarantor". Reports an error if `self.loan_region` is
//! larger than scope of `cmt`.
debug!("guarantee_lifetime.check(cmt={}, loan_region={})",
cmt.repr(self.bccx.tcx),
self.loan_region.repr(self.bccx.tcx));
Expand Down Expand Up @@ -88,7 +94,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
}

fn check_scope(&self, max_scope: ty::Region) -> R {
//! Reports an error if `loan_region` is larger than `valid_scope`
//! Reports an error if `loan_region` is larger than `max_scope`

if !self.bccx.is_subregion_of(self.loan_region, max_scope) {
Err(self.report_error(err_out_of_scope(max_scope, self.loan_region)))
Expand All @@ -109,7 +115,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
temp_scope
}
mc::cat_upvar(..) => {
ty::ReScope(self.item_scope_id)
ty::ReScope(self.item_scope)
}
mc::cat_static_item => {
ty::ReStatic
Expand Down
Loading

0 comments on commit 394269d

Please sign in to comment.