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 /// Because this code is so perf. sensitive, use a static constant so that
/// debug printouts are compiled out most of the time. /// debug printouts are compiled out most of the time.
static ENABLE_DEBUG_PTR: bool = false; static ENABLE_DEBUG_PTR: bool = true;
#[inline] #[inline]
pub fn debug_ptr<T>(tag: &'static str, p: *const T) { 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 /// Sets `*ptr` to `new_value`, invokes `op()`, and then restores the
/// original value of `*ptr`. /// 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)] #[inline(always)]
pub fn with<T:Copy,R>( pub fn with<T,R>(
ptr: &mut T, ptr: @mut T,
new_value: T, mut value: T,
op: &fn() -> R) -> R op: &fn() -> R) -> R
{ {
// NDM: if swap operator were defined somewhat differently, value <-> *ptr;
// we wouldn't need to copy...
let old_value = *ptr;
*ptr = new_value;
let result = op(); let result = op();
*ptr = old_value; *ptr = value;
return result; return result;
} }

View File

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

View File

@ -949,7 +949,8 @@ pub fn determine_rp_in_crate(sess: Session,
let cx = &mut *cx; let cx = &mut *cx;
while cx.worklist.len() != 0 { while cx.worklist.len() != 0 {
let c_id = cx.worklist.pop(); 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); debug!("popped %d from worklist", c_id);
match cx.dep_map.find(&c_id) { match cx.dep_map.find(&c_id) {
None => {} None => {}

View File

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

View File

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

View File

@ -240,8 +240,8 @@ pub impl CoherenceChecker {
fn check_implementation(&self, fn check_implementation(&self,
item: @item, associated_traits: ~[@trait_ref]) { item: @item, associated_traits: ~[@trait_ref]) {
let self_type = self.crate_context.tcx.tcache.get( let tcx = self.crate_context.tcx;
&local_def(item.id)); let self_type = ty::lookup_item_type(tcx, local_def(item.id));
// If there are no traits, then this implementation must have a // If there are no traits, then this implementation must have a
// base type. // base type.
@ -452,10 +452,8 @@ pub impl CoherenceChecker {
} }
fn check_implementation_coherence(&self) { fn check_implementation_coherence(&self) {
let coherence_info = &mut self.crate_context.coherence_info; let coherence_info = self.crate_context.coherence_info;
let extension_methods = &coherence_info.extension_methods; for coherence_info.extension_methods.each_key |&trait_id| {
for extension_methods.each_key |&trait_id| {
self.check_implementation_coherence_of(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)) { fn iter_impls_of_trait(&self, trait_def_id: def_id, f: &fn(@Impl)) {
let coherence_info = &mut self.crate_context.coherence_info; let coherence_info = self.crate_context.coherence_info;
let extension_methods = &coherence_info.extension_methods; let extension_methods = &*coherence_info.extension_methods;
match extension_methods.find(&trait_def_id) { match extension_methods.find(&trait_def_id) {
Some(impls) => { Some(impls) => {
let len = { // FIXME(#5074) stage0 requires this
let impls: &mut ~[@Impl] = *impls; let impls: &mut ~[@Impl] = *impls;
for uint::range(0, impls.len()) |i| { impls.len()
};
for uint::range(0, len) |i| {
f(impls[i]); f(impls[i]);
} }
} }
@ -1014,7 +1015,7 @@ pub impl CoherenceChecker {
// //
fn populate_destructor_table(&self) { 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 tcx = self.crate_context.tcx;
let drop_trait = tcx.lang_items.drop_trait(); let drop_trait = tcx.lang_items.drop_trait();
let impls_opt = coherence_info.extension_methods.find(&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::sub::Sub;
use middle::typeck::infer::to_str::InferStr; use middle::typeck::infer::to_str::InferStr;
use middle::typeck::infer::{cres, InferCtxt}; use middle::typeck::infer::{cres, InferCtxt};
use middle::typeck::infer::fold_regions_in_sig;
use middle::typeck::isr_alist; use middle::typeck::isr_alist;
use syntax::ast; use syntax::ast;
use syntax::ast::{Many, Once, extern_fn, impure_fn, m_const, m_imm, m_mutbl}; 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 = let new_vars =
self.infcx.region_vars.vars_created_since_snapshot(snapshot); self.infcx.region_vars.vars_created_since_snapshot(snapshot);
let sig1 = let sig1 =
self.infcx.fold_regions_in_sig( fold_regions_in_sig(
self.infcx.tcx,
&sig0, &sig0,
|r, _in_fn| generalize_region(self, snapshot, |r, _in_fn| generalize_region(self, snapshot,
new_vars, a_isr, a_vars, b_vars, 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::sub::Sub;
use middle::typeck::infer::to_str::InferStr; use middle::typeck::infer::to_str::InferStr;
use middle::typeck::infer::{cres, InferCtxt}; use middle::typeck::infer::{cres, InferCtxt};
use middle::typeck::infer::fold_regions_in_sig;
use middle::typeck::isr_alist; use middle::typeck::isr_alist;
use util::common::indent; use util::common::indent;
use util::ppaux::mt_to_str; use util::ppaux::mt_to_str;
@ -141,7 +142,8 @@ impl Combine for Lub {
let new_vars = let new_vars =
self.infcx.region_vars.vars_created_since_snapshot(snapshot); self.infcx.region_vars.vars_created_since_snapshot(snapshot);
let sig1 = let sig1 =
self.infcx.fold_regions_in_sig( fold_regions_in_sig(
self.infcx.tcx,
&sig0, &sig0,
|r, _in_fn| generalize_region(self, snapshot, new_vars, |r, _in_fn| generalize_region(self, snapshot, new_vars,
a_isr, r)); a_isr, r));

View File

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

View File

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

View File

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