Skip to content

Refactored new ScopeData for improved abstraction. #19033

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions src/librustc/metadata/tydecode.rs
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@

pub use self::DefIdSource::*;

use middle::region;
use middle::subst;
use middle::subst::VecPerParamSpace;
use middle::ty::{mod, Ty};
@@ -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
@@ -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) {
17 changes: 14 additions & 3 deletions src/librustc/metadata/tyencode.rs
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@

use std::cell::RefCell;

use middle::region;
use middle::subst;
use middle::subst::VecPerParamSpace;
use middle::ty::ParamTy;
@@ -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");
@@ -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) => {
20 changes: 16 additions & 4 deletions src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
@@ -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 {
50 changes: 28 additions & 22 deletions src/librustc/middle/borrowck/check_loans.rs
Original file line number Diff line number Diff line change
@@ -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;
@@ -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,
@@ -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
@@ -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 {
@@ -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 {
@@ -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 {
@@ -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);
@@ -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");

@@ -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
@@ -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
});
20 changes: 13 additions & 7 deletions src/librustc/middle/borrowck/gather_loans/lifetime.rs
Original file line number Diff line number Diff line change
@@ -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;
@@ -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,
@@ -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,
@@ -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));
@@ -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)))
@@ -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
Loading