fix numerous dynamic borrow failures

This commit is contained in:
Niko Matsakis 2013-05-02 14:32:37 -04:00
parent 5f886342be
commit 88ec89d3fe
12 changed files with 78 additions and 66 deletions

View File

@ -133,7 +133,7 @@ pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
/// Because this code is so perf. sensitive, use a static constant so that
/// debug printouts are compiled out most of the time.
static ENABLE_DEBUG_PTR: bool = false;
static ENABLE_DEBUG_PTR: bool = true;
#[inline]
pub fn debug_ptr<T>(tag: &'static str, p: *const T) {

View File

@ -26,19 +26,20 @@ pub fn ignore<T>(_x: T) { }
/// Sets `*ptr` to `new_value`, invokes `op()`, and then restores the
/// original value of `*ptr`.
///
/// NB: This function accepts `@mut T` and not `&mut T` to avoid
/// an obvious borrowck hazard. Typically passing in `&mut T` will
/// cause borrow check errors because it freezes whatever location
/// that `&mut T` is stored in (either statically or dynamically).
#[inline(always)]
pub fn with<T:Copy,R>(
ptr: &mut T,
new_value: T,
pub fn with<T,R>(
ptr: @mut T,
mut value: T,
op: &fn() -> R) -> R
{
// NDM: if swap operator were defined somewhat differently,
// we wouldn't need to copy...
let old_value = *ptr;
*ptr = new_value;
value <-> *ptr;
let result = op();
*ptr = old_value;
*ptr = value;
return result;
}

View File

@ -112,7 +112,6 @@ use util::ppaux::ty_to_str;
use core::cast::transmute;
use core::hashmap::HashMap;
use core::util::with;
use syntax::ast::*;
use syntax::codemap::span;
use syntax::parse::token::special_idents;
@ -343,9 +342,10 @@ pub impl IrMaps {
}
fn visit_item(item: @item, self: @mut IrMaps, v: vt<@mut IrMaps>) {
do with(&mut self.cur_item, item.id) {
visit::visit_item(item, self, v)
}
let old_cur_item = self.cur_item;
self.cur_item = item.id;
visit::visit_item(item, self, v);
self.cur_item = old_cur_item;
}
fn visit_fn(fk: &visit::fn_kind,
@ -762,11 +762,13 @@ pub impl Liveness {
None => {
// Vanilla 'break' or 'loop', so use the enclosing
// loop scope
let loop_scope = &mut *self.loop_scope;
if loop_scope.len() == 0 {
let len = { // FIXME(#5074) stage0
let loop_scope = &mut *self.loop_scope;
loop_scope.len()
};
if len == 0 {
self.tcx.sess.span_bug(sp, ~"break outside loop");
}
else {
} else {
// FIXME(#5275): this shouldn't have to be a method...
self.last_loop_scope()
}

View File

@ -949,7 +949,8 @@ pub fn determine_rp_in_crate(sess: Session,
let cx = &mut *cx;
while cx.worklist.len() != 0 {
let c_id = cx.worklist.pop();
let c_variance = *cx.region_paramd_items.get(&c_id);
let c_variance = { *cx.region_paramd_items.get(&c_id) };
// NOTE cleanup scopes cause an exaggerated lock here
debug!("popped %d from worklist", c_id);
match cx.dep_map.find(&c_id) {
None => {}

View File

@ -779,9 +779,9 @@ pub fn Resolver(session: Session,
unresolved_imports: 0,
current_module: current_module,
value_ribs: ~[],
type_ribs: ~[],
label_ribs: ~[],
value_ribs: @mut ~[],
type_ribs: @mut ~[],
label_ribs: @mut ~[],
xray_context: NoXray,
current_trait_refs: None,
@ -830,13 +830,13 @@ pub struct Resolver {
// The current set of local scopes, for values.
// FIXME #4948: Reuse ribs to avoid allocation.
value_ribs: ~[@Rib],
value_ribs: @mut ~[@Rib],
// The current set of local scopes, for types.
type_ribs: ~[@Rib],
type_ribs: @mut ~[@Rib],
// The current set of local scopes, for labels.
label_ribs: ~[@Rib],
label_ribs: @mut ~[@Rib],
// Whether the current context is an X-ray context. An X-ray context is
// allowed to access private names of any module.
@ -4313,19 +4313,18 @@ pub impl Resolver {
}
pat_struct(path, _, _) => {
let structs: &mut HashSet<def_id> = &mut self.structs;
match self.resolve_path(path, TypeNS, false, visitor) {
Some(def_ty(class_id))
if structs.contains(&class_id) => {
if self.structs.contains(&class_id) => {
let class_def = def_struct(class_id);
self.record_def(pattern.id, class_def);
}
Some(definition @ def_struct(class_id))
if structs.contains(&class_id) => {
Some(definition @ def_struct(class_id)) => {
assert!(self.structs.contains(&class_id));
self.record_def(pattern.id, definition);
}
Some(definition @ def_variant(_, variant_id))
if structs.contains(&variant_id) => {
if self.structs.contains(&variant_id) => {
self.record_def(pattern.id, definition);
}
result => {
@ -4627,12 +4626,12 @@ pub impl Resolver {
let search_result;
match namespace {
ValueNS => {
search_result = self.search_ribs(&mut self.value_ribs, ident,
search_result = self.search_ribs(self.value_ribs, ident,
span,
DontAllowCapturingSelf);
}
TypeNS => {
search_result = self.search_ribs(&mut self.type_ribs, ident,
search_result = self.search_ribs(self.type_ribs, ident,
span, AllowCapturingSelf);
}
}
@ -4822,15 +4821,14 @@ pub impl Resolver {
expr_struct(path, _, _) => {
// Resolve the path to the structure it goes to.
let structs: &mut HashSet<def_id> = &mut self.structs;
match self.resolve_path(path, TypeNS, false, visitor) {
Some(def_ty(class_id)) | Some(def_struct(class_id))
if structs.contains(&class_id) => {
if self.structs.contains(&class_id) => {
let class_def = def_struct(class_id);
self.record_def(expr.id, class_def);
}
Some(definition @ def_variant(_, class_id))
if structs.contains(&class_id) => {
if self.structs.contains(&class_id) => {
self.record_def(expr.id, definition);
}
_ => {
@ -4856,7 +4854,7 @@ pub impl Resolver {
}
expr_break(Some(label)) | expr_again(Some(label)) => {
match self.search_ribs(&mut self.label_ribs, label, expr.span,
match self.search_ribs(self.label_ribs, label, expr.span,
DontAllowCapturingSelf) {
None =>
self.session.span_err(expr.span,

View File

@ -244,11 +244,14 @@ fn lookup_vtable(vcx: &VtableContext,
// Nothing found. Continue.
}
Some(implementations) => {
let implementations: &mut ~[@Impl] = *implementations;
let len = { // FIXME(#5074): stage0 requires it
let implementations: &mut ~[@Impl] = *implementations;
implementations.len()
};
// implementations is the list of all impls in scope for
// trait_ref. (Usually, there's just one.)
for uint::range(0, implementations.len()) |i| {
for uint::range(0, len) |i| {
let im = implementations[i];
// im is one specific impl of trait_ref.

View File

@ -240,8 +240,8 @@ pub impl CoherenceChecker {
fn check_implementation(&self,
item: @item, associated_traits: ~[@trait_ref]) {
let self_type = self.crate_context.tcx.tcache.get(
&local_def(item.id));
let tcx = self.crate_context.tcx;
let self_type = ty::lookup_item_type(tcx, local_def(item.id));
// If there are no traits, then this implementation must have a
// base type.
@ -452,10 +452,8 @@ pub impl CoherenceChecker {
}
fn check_implementation_coherence(&self) {
let coherence_info = &mut self.crate_context.coherence_info;
let extension_methods = &coherence_info.extension_methods;
for extension_methods.each_key |&trait_id| {
let coherence_info = self.crate_context.coherence_info;
for coherence_info.extension_methods.each_key |&trait_id| {
self.check_implementation_coherence_of(trait_id);
}
}
@ -514,13 +512,16 @@ pub impl CoherenceChecker {
}
fn iter_impls_of_trait(&self, trait_def_id: def_id, f: &fn(@Impl)) {
let coherence_info = &mut self.crate_context.coherence_info;
let extension_methods = &coherence_info.extension_methods;
let coherence_info = self.crate_context.coherence_info;
let extension_methods = &*coherence_info.extension_methods;
match extension_methods.find(&trait_def_id) {
Some(impls) => {
let impls: &mut ~[@Impl] = *impls;
for uint::range(0, impls.len()) |i| {
let len = { // FIXME(#5074) stage0 requires this
let impls: &mut ~[@Impl] = *impls;
impls.len()
};
for uint::range(0, len) |i| {
f(impls[i]);
}
}
@ -1014,7 +1015,7 @@ pub impl CoherenceChecker {
//
fn populate_destructor_table(&self) {
let coherence_info = &mut self.crate_context.coherence_info;
let coherence_info = self.crate_context.coherence_info;
let tcx = self.crate_context.tcx;
let drop_trait = tcx.lang_items.drop_trait();
let impls_opt = coherence_info.extension_methods.find(&drop_trait);

View File

@ -16,6 +16,7 @@ use middle::typeck::infer::lub::Lub;
use middle::typeck::infer::sub::Sub;
use middle::typeck::infer::to_str::InferStr;
use middle::typeck::infer::{cres, InferCtxt};
use middle::typeck::infer::fold_regions_in_sig;
use middle::typeck::isr_alist;
use syntax::ast;
use syntax::ast::{Many, Once, extern_fn, impure_fn, m_const, m_imm, m_mutbl};
@ -188,7 +189,8 @@ impl Combine for Glb {
let new_vars =
self.infcx.region_vars.vars_created_since_snapshot(snapshot);
let sig1 =
self.infcx.fold_regions_in_sig(
fold_regions_in_sig(
self.infcx.tcx,
&sig0,
|r, _in_fn| generalize_region(self, snapshot,
new_vars, a_isr, a_vars, b_vars,

View File

@ -16,6 +16,7 @@ use middle::typeck::infer::lattice::*;
use middle::typeck::infer::sub::Sub;
use middle::typeck::infer::to_str::InferStr;
use middle::typeck::infer::{cres, InferCtxt};
use middle::typeck::infer::fold_regions_in_sig;
use middle::typeck::isr_alist;
use util::common::indent;
use util::ppaux::mt_to_str;
@ -141,7 +142,8 @@ impl Combine for Lub {
let new_vars =
self.infcx.region_vars.vars_created_since_snapshot(snapshot);
let sig1 =
self.infcx.fold_regions_in_sig(
fold_regions_in_sig(
self.infcx.tcx,
&sig0,
|r, _in_fn| generalize_region(self, snapshot, new_vars,
a_isr, r));

View File

@ -574,7 +574,7 @@ pub impl InferCtxt {
}
/// Execute `f` and commit the bindings if successful
fn commit<T,E>(&mut self, f: &fn() -> Result<T,E>) -> Result<T,E> {
fn commit<T,E>(@mut self, f: &fn() -> Result<T,E>) -> Result<T,E> {
assert!(!self.in_snapshot());
debug!("commit()");
@ -589,7 +589,7 @@ pub impl InferCtxt {
}
/// Execute `f`, unroll bindings on failure
fn try<T,E>(&mut self, f: &fn() -> Result<T,E>) -> Result<T,E> {
fn try<T,E>(@mut self, f: &fn() -> Result<T,E>) -> Result<T,E> {
debug!("try()");
do indent {
let snapshot = self.start_snapshot();
@ -603,7 +603,7 @@ pub impl InferCtxt {
}
/// Execute `f` then unroll any bindings it creates
fn probe<T,E>(&mut self, f: &fn() -> Result<T,E>) -> Result<T,E> {
fn probe<T,E>(@mut self, f: &fn() -> Result<T,E>) -> Result<T,E> {
debug!("probe()");
do indent {
let snapshot = self.start_snapshot();
@ -783,15 +783,14 @@ pub impl InferCtxt {
});
(fn_sig, isr)
}
fn fold_regions_in_sig(
&mut self,
fn_sig: &ty::FnSig,
fldr: &fn(r: ty::Region, in_fn: bool) -> ty::Region) -> ty::FnSig
{
do ty::fold_sig(fn_sig) |t| {
ty::fold_regions(self.tcx, t, fldr)
}
}
}
pub fn fold_regions_in_sig(
tcx: ty::ctxt,
fn_sig: &ty::FnSig,
fldr: &fn(r: ty::Region, in_fn: bool) -> ty::Region) -> ty::FnSig
{
do ty::fold_sig(fn_sig) |t| {
ty::fold_regions(tcx, t, fldr)
}
}

View File

@ -76,6 +76,9 @@ pub mod middle {
}
pub mod ty;
pub mod subst;
#[cfg(stage0)] #[path = "resolve_stage0.rs"]
pub mod resolve;
#[cfg(not(stage0))]
pub mod resolve;
#[path = "typeck/mod.rs"]
pub mod typeck;

View File

@ -355,7 +355,7 @@ pub impl CodeMap {
}
pub fn span_to_str(&self, sp: span) -> ~str {
let files = &mut *self.files;
let files = &*self.files;
if files.len() == 0 && sp == dummy_sp() {
return ~"no-location";
}