diff --git a/src/libextra/ebml.rs b/src/libextra/ebml.rs index 16a4327640114..27d7a1dee9922 100644 --- a/src/libextra/ebml.rs +++ b/src/libextra/ebml.rs @@ -593,22 +593,13 @@ pub mod writer { use std::io::extensions::u64_to_be_bytes; // ebml writing - pub struct Encoder { + pub struct Encoder<'a> { // FIXME(#5665): this should take a trait object - writer: @mut MemWriter, + writer: &'a mut MemWriter, priv size_positions: ~[uint], } - impl Clone for Encoder { - fn clone(&self) -> Encoder { - Encoder { - writer: self.writer, - size_positions: self.size_positions.clone(), - } - } - } - - fn write_sized_vuint(w: @mut MemWriter, n: uint, size: uint) { + fn write_sized_vuint(w: &mut MemWriter, n: uint, size: uint) { match size { 1u => w.write(&[0x80u8 | (n as u8)]), 2u => w.write(&[0x40u8 | ((n >> 8_u) as u8), n as u8]), @@ -620,7 +611,7 @@ pub mod writer { }; } - fn write_vuint(w: @mut MemWriter, n: uint) { + fn write_vuint(w: &mut MemWriter, n: uint) { if n < 0x7f_u { write_sized_vuint(w, n, 1u); return; } if n < 0x4000_u { write_sized_vuint(w, n, 2u); return; } if n < 0x200000_u { write_sized_vuint(w, n, 3u); return; } @@ -628,7 +619,7 @@ pub mod writer { fail!("vint to write too big: {}", n); } - pub fn Encoder(w: @mut MemWriter) -> Encoder { + pub fn Encoder<'a>(w: &'a mut MemWriter) -> Encoder<'a> { let size_positions: ~[uint] = ~[]; Encoder { writer: w, @@ -637,7 +628,15 @@ pub mod writer { } // FIXME (#2741): Provide a function to write the standard ebml header. - impl Encoder { + impl<'a> Encoder<'a> { + /// XXX(pcwalton): Workaround for badness in trans. DO NOT USE ME. + pub unsafe fn unsafe_clone(&self) -> Encoder<'a> { + Encoder { + writer: cast::transmute_copy(&self.writer), + size_positions: self.size_positions.clone(), + } + } + pub fn start_tag(&mut self, tag_id: uint) { debug!("Start tag {}", tag_id); @@ -739,7 +738,7 @@ pub mod writer { // Totally lame approach. static DEBUG: bool = true; - impl Encoder { + impl<'a> Encoder<'a> { // used internally to emit things like the vector length and so on fn _emit_tagged_uint(&mut self, t: EbmlEncoderTag, v: uint) { assert!(v <= 0xFFFF_FFFF_u); @@ -755,9 +754,7 @@ pub mod writer { // try and check failures more quickly. if DEBUG { self.wr_tagged_str(EsLabel as uint, label) } } - } - impl Encoder { pub fn emit_opaque(&mut self, f: |&mut Encoder|) { self.start_tag(EsOpaque as uint); f(self); @@ -765,7 +762,7 @@ pub mod writer { } } - impl ::serialize::Encoder for Encoder { + impl<'a> ::serialize::Encoder for Encoder<'a> { fn emit_nil(&mut self) {} fn emit_uint(&mut self, v: uint) { @@ -820,7 +817,7 @@ pub mod writer { self.wr_tagged_str(EsStr as uint, v) } - fn emit_enum(&mut self, name: &str, f: |&mut Encoder|) { + fn emit_enum(&mut self, name: &str, f: |&mut Encoder<'a>|) { self._emit_label(name); self.start_tag(EsEnum as uint); f(self); @@ -831,14 +828,14 @@ pub mod writer { _: &str, v_id: uint, _: uint, - f: |&mut Encoder|) { + f: |&mut Encoder<'a>|) { self._emit_tagged_uint(EsEnumVid, v_id); self.start_tag(EsEnumBody as uint); f(self); self.end_tag(); } - fn emit_enum_variant_arg(&mut self, _: uint, f: |&mut Encoder|) { + fn emit_enum_variant_arg(&mut self, _: uint, f: |&mut Encoder<'a>|) { f(self) } @@ -846,83 +843,88 @@ pub mod writer { v_name: &str, v_id: uint, cnt: uint, - f: |&mut Encoder|) { + f: |&mut Encoder<'a>|) { self.emit_enum_variant(v_name, v_id, cnt, f) } fn emit_enum_struct_variant_field(&mut self, _: &str, idx: uint, - f: |&mut Encoder|) { + f: |&mut Encoder<'a>|) { self.emit_enum_variant_arg(idx, f) } - fn emit_struct(&mut self, _: &str, _len: uint, f: |&mut Encoder|) { + fn emit_struct(&mut self, + _: &str, + _len: uint, + f: |&mut Encoder<'a>|) { f(self) } fn emit_struct_field(&mut self, name: &str, _: uint, - f: |&mut Encoder|) { + f: |&mut Encoder<'a>|) { self._emit_label(name); f(self) } - fn emit_tuple(&mut self, len: uint, f: |&mut Encoder|) { + fn emit_tuple(&mut self, len: uint, f: |&mut Encoder<'a>|) { self.emit_seq(len, f) } - fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Encoder|) { + fn emit_tuple_arg(&mut self, idx: uint, f: |&mut Encoder<'a>|) { self.emit_seq_elt(idx, f) } fn emit_tuple_struct(&mut self, _: &str, len: uint, - f: |&mut Encoder|) { + f: |&mut Encoder<'a>|) { self.emit_seq(len, f) } - fn emit_tuple_struct_arg(&mut self, idx: uint, f: |&mut Encoder|) { + fn emit_tuple_struct_arg(&mut self, + idx: uint, + f: |&mut Encoder<'a>|) { self.emit_seq_elt(idx, f) } - fn emit_option(&mut self, f: |&mut Encoder|) { + fn emit_option(&mut self, f: |&mut Encoder<'a>|) { self.emit_enum("Option", f); } fn emit_option_none(&mut self) { self.emit_enum_variant("None", 0, 0, |_| ()) } - fn emit_option_some(&mut self, f: |&mut Encoder|) { + fn emit_option_some(&mut self, f: |&mut Encoder<'a>|) { self.emit_enum_variant("Some", 1, 1, f) } - fn emit_seq(&mut self, len: uint, f: |&mut Encoder|) { + fn emit_seq(&mut self, len: uint, f: |&mut Encoder<'a>|) { self.start_tag(EsVec as uint); self._emit_tagged_uint(EsVecLen, len); f(self); self.end_tag(); } - fn emit_seq_elt(&mut self, _idx: uint, f: |&mut Encoder|) { + fn emit_seq_elt(&mut self, _idx: uint, f: |&mut Encoder<'a>|) { self.start_tag(EsVecElt as uint); f(self); self.end_tag(); } - fn emit_map(&mut self, len: uint, f: |&mut Encoder|) { + fn emit_map(&mut self, len: uint, f: |&mut Encoder<'a>|) { self.start_tag(EsMap as uint); self._emit_tagged_uint(EsMapLen, len); f(self); self.end_tag(); } - fn emit_map_elt_key(&mut self, _idx: uint, f: |&mut Encoder|) { + fn emit_map_elt_key(&mut self, _idx: uint, f: |&mut Encoder<'a>|) { self.start_tag(EsMapKey as uint); f(self); self.end_tag(); } - fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder|) { + fn emit_map_elt_val(&mut self, _idx: uint, f: |&mut Encoder<'a>|) { self.start_tag(EsMapVal as uint); f(self); self.end_tag(); @@ -948,9 +950,11 @@ mod tests { fn test_option_int() { fn test_v(v: Option) { debug!("v == {:?}", v); - let wr = @mut MemWriter::new(); - let mut ebml_w = writer::Encoder(wr); - v.encode(&mut ebml_w); + let mut wr = MemWriter::new(); + { + let mut ebml_w = writer::Encoder(&mut wr); + v.encode(&mut ebml_w); + } let ebml_doc = reader::Doc(*wr.inner_ref()); let mut deser = reader::Decoder(ebml_doc); let v1 = serialize::Decodable::decode(&mut deser); diff --git a/src/librustc/back/archive.rs b/src/librustc/back/archive.rs index 453f0c42d8d8e..07457b1db27cc 100644 --- a/src/librustc/back/archive.rs +++ b/src/librustc/back/archive.rs @@ -187,7 +187,11 @@ impl Archive { let mut rustpath = filesearch::rust_path(); rustpath.push(self.sess.filesearch.get_target_lib_path()); - let path = self.sess.opts.addl_lib_search_paths.iter(); + let addl_lib_search_paths = self.sess + .opts + .addl_lib_search_paths + .borrow(); + let path = addl_lib_search_paths.get().iter(); for path in path.chain(rustpath.iter()) { debug!("looking for {} inside {}", name, path.display()); let test = path.join(oslibname.as_slice()); diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 11a63db6abaaf..a85d5f35b5a3d 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -208,8 +208,9 @@ pub mod write { // Emit the bytecode if we're either saving our temporaries or // emitting an rlib. Whenever an rlib is create, the bytecode is // inserted into the archive in order to allow LTO against it. + let outputs = sess.outputs.borrow(); if sess.opts.save_temps || - sess.outputs.iter().any(|&o| o == session::OutputRlib) { + outputs.get().iter().any(|&o| o == session::OutputRlib) { output.with_extension("bc").with_c_str(|buf| { llvm::LLVMWriteBitcodeToFile(llmod, buf); }) @@ -520,15 +521,20 @@ pub fn symbol_hash(tcx: ty::ctxt, hash.to_managed() } -pub fn get_symbol_hash(ccx: &mut CrateContext, t: ty::t) -> @str { - match ccx.type_hashcodes.find(&t) { - Some(&h) => h, - None => { - let hash = symbol_hash(ccx.tcx, &mut ccx.symbol_hasher, t, &ccx.link_meta); - ccx.type_hashcodes.insert(t, hash); - hash - } +pub fn get_symbol_hash(ccx: &CrateContext, t: ty::t) -> @str { + { + let type_hashcodes = ccx.type_hashcodes.borrow(); + match type_hashcodes.get().find(&t) { + Some(&h) => return h, + None => {} + } } + + let mut type_hashcodes = ccx.type_hashcodes.borrow_mut(); + let mut symbol_hasher = ccx.symbol_hasher.borrow_mut(); + let hash = symbol_hash(ccx.tcx, symbol_hasher.get(), t, &ccx.link_meta); + type_hashcodes.get().insert(t, hash); + hash } @@ -657,7 +663,7 @@ pub fn exported_name(sess: Session, mangle(sess, path, Some(hash), Some(vers.as_slice())) } -pub fn mangle_exported_name(ccx: &mut CrateContext, +pub fn mangle_exported_name(ccx: &CrateContext, path: path, t: ty::t) -> ~str { let hash = get_symbol_hash(ccx, t); @@ -666,7 +672,7 @@ pub fn mangle_exported_name(ccx: &mut CrateContext, ccx.link_meta.pkgid.version_or_default()); } -pub fn mangle_internal_name_by_type_only(ccx: &mut CrateContext, +pub fn mangle_internal_name_by_type_only(ccx: &CrateContext, t: ty::t, name: &str) -> ~str { let s = ppaux::ty_to_short_str(ccx.tcx, t); @@ -678,7 +684,7 @@ pub fn mangle_internal_name_by_type_only(ccx: &mut CrateContext, None); } -pub fn mangle_internal_name_by_type_and_seq(ccx: &mut CrateContext, +pub fn mangle_internal_name_by_type_and_seq(ccx: &CrateContext, t: ty::t, name: &str) -> ~str { let s = ppaux::ty_to_str(ccx.tcx, t); @@ -690,7 +696,7 @@ pub fn mangle_internal_name_by_type_and_seq(ccx: &mut CrateContext, None); } -pub fn mangle_internal_name_by_path_and_seq(ccx: &mut CrateContext, +pub fn mangle_internal_name_by_path_and_seq(ccx: &CrateContext, mut path: path, flav: &str) -> ~str { let (_, name) = gensym_name(flav); @@ -698,7 +704,7 @@ pub fn mangle_internal_name_by_path_and_seq(ccx: &mut CrateContext, mangle(ccx.sess, path, None, None) } -pub fn mangle_internal_name_by_path(ccx: &mut CrateContext, path: path) -> ~str { +pub fn mangle_internal_name_by_path(ccx: &CrateContext, path: path) -> ~str { mangle(ccx.sess, path, None, None) } @@ -740,7 +746,8 @@ pub fn link_binary(sess: Session, out_filename: &Path, lm: &LinkMeta) -> ~[Path] { let mut out_filenames = ~[]; - for &output in sess.outputs.iter() { + let outputs = sess.outputs.borrow(); + for &output in outputs.get().iter() { let out_file = link_binary_output(sess, trans, output, obj_filename, out_filename, lm); out_filenames.push(out_file); @@ -848,7 +855,9 @@ fn link_rlib(sess: Session, out_filename: &Path) -> Archive { let mut a = Archive::create(sess, out_filename, obj_filename); - for &(ref l, kind) in sess.cstore.get_used_libraries().iter() { + let used_libraries = sess.cstore.get_used_libraries(); + let used_libraries = used_libraries.borrow(); + for &(ref l, kind) in used_libraries.get().iter() { match kind { cstore::NativeStatic => { a.add_native_library(l.as_slice()); @@ -1082,7 +1091,9 @@ fn link_args(sess: Session, // Finally add all the linker arguments provided on the command line along // with any #[link_args] attributes found inside the crate args.push_all(sess.opts.linker_args); - for arg in sess.cstore.get_used_link_args().iter() { + let used_link_args = sess.cstore.get_used_link_args(); + let used_link_args = used_link_args.borrow(); + for arg in used_link_args.get().iter() { args.push(arg.clone()); } return args; @@ -1100,7 +1111,8 @@ fn link_args(sess: Session, // in the current crate. Upstream crates with native library dependencies // may have their native library pulled in above. fn add_local_native_libraries(args: &mut ~[~str], sess: Session) { - for path in sess.opts.addl_lib_search_paths.iter() { + let addl_lib_search_paths = sess.opts.addl_lib_search_paths.borrow(); + for path in addl_lib_search_paths.get().iter() { // FIXME (#9639): This needs to handle non-utf8 paths args.push("-L" + path.as_str().unwrap().to_owned()); } @@ -1111,7 +1123,9 @@ fn add_local_native_libraries(args: &mut ~[~str], sess: Session) { args.push("-L" + path.as_str().unwrap().to_owned()); } - for &(ref l, kind) in sess.cstore.get_used_libraries().iter() { + let used_libraries = sess.cstore.get_used_libraries(); + let used_libraries = used_libraries.borrow(); + for &(ref l, kind) in used_libraries.get().iter() { match kind { cstore::NativeUnknown | cstore::NativeStatic => { args.push("-l" + *l); diff --git a/src/librustc/back/lto.rs b/src/librustc/back/lto.rs index 697b2a6686b65..2425b36687e2d 100644 --- a/src/librustc/back/lto.rs +++ b/src/librustc/back/lto.rs @@ -20,7 +20,8 @@ use std::libc; pub fn run(sess: session::Session, llmod: ModuleRef, tm: TargetMachineRef, reachable: &[~str]) { // Make sure we actually can run LTO - for output in sess.outputs.iter() { + let outputs = sess.outputs.borrow(); + for output in outputs.get().iter() { match *output { session::OutputExecutable | session::OutputStaticlib => {} _ => { diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 530f90c6bfb86..2b9acb1db9d54 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -26,6 +26,7 @@ use middle; use util::common::time; use util::ppaux; +use std::cell::{Cell, RefCell}; use std::hashmap::{HashMap,HashSet}; use std::io; use std::io::fs; @@ -165,8 +166,8 @@ pub fn phase_2_configure_and_expand(sess: Session, mut crate: ast::Crate) -> ast::Crate { let time_passes = sess.time_passes(); - *sess.building_library = session::building_library(sess.opts, &crate); - *sess.outputs = session::collect_outputs(sess.opts, crate.attrs); + sess.building_library.set(session::building_library(sess.opts, &crate)); + sess.outputs.set(session::collect_outputs(sess.opts, crate.attrs)); time(time_passes, "gated feature checking", (), |_| front::feature_gate::check_crate(sess, &crate)); @@ -211,7 +212,7 @@ pub struct CrateAnalysis { exported_items: middle::privacy::ExportedItems, ty_cx: ty::ctxt, maps: astencode::Maps, - reachable: @mut HashSet + reachable: @RefCell> } /// Run the resolution, typechecking, region checking and other @@ -271,8 +272,7 @@ pub fn phase_3_run_analysis_passes(sess: Session, method_map, ty_cx)); let maps = (external_exports, last_private_map); - let exported_items = - time(time_passes, "privacy checking", maps, |(a, b)| + let exported_items = time(time_passes, "privacy checking", maps, |(a, b)| middle::privacy::check_crate(ty_cx, &method_map, &exp_map2, a, b, crate)); @@ -308,9 +308,16 @@ pub fn phase_3_run_analysis_passes(sess: Session, time(time_passes, "reachability checking", (), |_| reachable::find_reachable(ty_cx, method_map, &exported_items)); - time(time_passes, "death checking", (), |_| - middle::dead::check_crate(ty_cx, method_map, - &exported_items, reachable_map, crate)); + { + let reachable_map = reachable_map.borrow(); + time(time_passes, "death checking", (), |_| { + middle::dead::check_crate(ty_cx, + method_map, + &exported_items, + reachable_map.get(), + crate) + }); + } time(time_passes, "lint checking", (), |_| lint::check_crate(ty_cx, method_map, &exported_items, crate)); @@ -562,13 +569,14 @@ pub fn pretty_print_input(sess: Session, let src = sess.codemap.get_filemap(source_name(input)).src; let rdr = @mut MemReader::new(src.as_bytes().to_owned()); + let stdout = io::stdout(); pprust::print_crate(sess.codemap, token::get_ident_interner(), sess.span_diagnostic, &crate, source_name(input), rdr as @mut io::Reader, - @mut io::stdout() as @mut io::Writer, + @mut stdout as @mut io::Writer, annotation, is_expanded); } @@ -815,7 +823,7 @@ pub fn build_session_options(binary: @str, lint_opts: lint_opts, save_temps: save_temps, output_type: output_type, - addl_lib_search_paths: @mut addl_lib_search_paths, + addl_lib_search_paths: @RefCell::new(addl_lib_search_paths), ar: ar, linker: linker, linker_args: linker_args, @@ -854,7 +862,7 @@ pub fn build_session_(sopts: @session::options, let target_cfg = build_target_config(sopts, demitter); let p_s = parse::new_parse_sess_special_handler(span_diagnostic_handler, cm); - let cstore = @mut CStore::new(token::get_ident_interner()); + let cstore = @CStore::new(token::get_ident_interner()); let filesearch = filesearch::mk_filesearch( &sopts.maybe_sysroot, sopts.target_triple, @@ -866,15 +874,15 @@ pub fn build_session_(sopts: @session::options, parse_sess: p_s, codemap: cm, // For a library crate, this is always none - entry_fn: @mut None, - entry_type: @mut None, + entry_fn: RefCell::new(None), + entry_type: Cell::new(None), span_diagnostic: span_diagnostic_handler, filesearch: filesearch, - building_library: @mut false, + building_library: Cell::new(false), working_dir: os::getcwd(), - lints: @mut HashMap::new(), - node_id: @mut 1, - outputs: @mut ~[], + lints: RefCell::new(HashMap::new()), + node_id: Cell::new(1), + outputs: @RefCell::new(~[]), } } @@ -1031,7 +1039,7 @@ pub fn build_output_filenames(input: &input, } } - if *sess.building_library { + if sess.building_library.get() { out_path = dirpath.join(os::dll_filename(stem)); obj_path = { let mut p = dirpath.join(stem); @@ -1052,7 +1060,7 @@ pub fn build_output_filenames(input: &input, out_file.with_extension(obj_suffix) }; - if *sess.building_library { + if sess.building_library.get() { sess.warn("ignoring specified output filename for library."); } @@ -1073,7 +1081,7 @@ pub fn early_error(emitter: @diagnostic::Emitter, msg: &str) -> ! { fail!(); } -pub fn list_metadata(sess: Session, path: &Path, out: @mut io::Writer) { +pub fn list_metadata(sess: Session, path: &Path, out: &mut io::Writer) { metadata::loader::list_file_metadata( token::get_ident_interner(), session::sess_os_to_meta_os(sess.targ_cfg.os), path, out); diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 9492e22921a18..e3167dee06809 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -28,6 +28,7 @@ use syntax::abi; use syntax::parse::token; use syntax; +use std::cell::{Cell, RefCell}; use std::hashmap::{HashMap,HashSet}; pub struct config { @@ -147,9 +148,9 @@ pub struct options { lint_opts: ~[(lint::lint, lint::level)], save_temps: bool, output_type: back::link::output_type, - addl_lib_search_paths: @mut HashSet, // This is mutable for rustpkg, which - // updates search paths based on the - // parsed code + // This is mutable for rustpkg, which updates search paths based on the + // parsed code. + addl_lib_search_paths: @RefCell>, ar: Option<~str>, linker: Option<~str>, linker_args: ~[~str], @@ -201,19 +202,20 @@ pub enum OutputStyle { pub struct Session_ { targ_cfg: @config, opts: @options, - cstore: @mut metadata::cstore::CStore, + cstore: @metadata::cstore::CStore, parse_sess: @mut ParseSess, codemap: @codemap::CodeMap, // For a library crate, this is always none - entry_fn: @mut Option<(NodeId, codemap::Span)>, - entry_type: @mut Option, + entry_fn: RefCell>, + entry_type: Cell>, span_diagnostic: @mut diagnostic::span_handler, filesearch: @filesearch::FileSearch, - building_library: @mut bool, + building_library: Cell, working_dir: Path, - lints: @mut HashMap, - node_id: @mut ast::NodeId, - outputs: @mut ~[OutputStyle], + lints: RefCell>, + node_id: Cell, + outputs: @RefCell<~[OutputStyle]>, } pub type Session = @Session_; @@ -269,20 +271,21 @@ impl Session_ { id: ast::NodeId, sp: Span, msg: ~str) { - match self.lints.find_mut(&id) { + let mut lints = self.lints.borrow_mut(); + match lints.get().find_mut(&id) { Some(arr) => { arr.push((lint, sp, msg)); return; } None => {} } - self.lints.insert(id, ~[(lint, sp, msg)]); + lints.get().insert(id, ~[(lint, sp, msg)]); } pub fn next_node_id(&self) -> ast::NodeId { self.reserve_node_ids(1) } pub fn reserve_node_ids(&self, count: ast::NodeId) -> ast::NodeId { - let v = *self.node_id; + let v = self.node_id.get(); match v.checked_add(&count) { - Some(next) => { *self.node_id = next; } + Some(next) => { self.node_id.set(next); } None => self.bug("Input too large, ran out of node ids!") } @@ -382,7 +385,7 @@ pub fn basic_options() -> @options { lint_opts: ~[], save_temps: false, output_type: link::output_type_exe, - addl_lib_search_paths: @mut HashSet::new(), + addl_lib_search_paths: @RefCell::new(HashSet::new()), ar: None, linker: None, linker_args: ~[], diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs index 1503e4effeb36..03f9a3459a3a9 100644 --- a/src/librustc/front/std_inject.rs +++ b/src/librustc/front/std_inject.rs @@ -69,7 +69,7 @@ impl fold::ast_fold for StandardLibraryInjector { span: dummy_sp() }]; - if use_uv(&crate) && !*self.sess.building_library { + if use_uv(&crate) && !self.sess.building_library.get() { vis.push(ast::view_item { node: ast::view_item_extern_mod(self.sess.ident_of("green"), None, diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index f2f729561cf27..47ef4b94058ba 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -14,6 +14,7 @@ use driver::session; use front::config; +use std::cell::RefCell; use std::vec; use syntax::ast_util::*; use syntax::attr::AttrMetaMethods; @@ -38,9 +39,9 @@ struct Test { struct TestCtxt { sess: session::Session, - path: ~[ast::Ident], + path: RefCell<~[ast::Ident]>, ext_cx: @ExtCtxt, - testfns: ~[Test], + testfns: RefCell<~[Test]>, is_extra: bool, config: ast::CrateConfig, } @@ -62,7 +63,7 @@ pub fn modify_for_testing(sess: session::Session, } struct TestHarnessGenerator { - cx: @mut TestCtxt, + cx: @TestCtxt, } impl fold::ast_fold for TestHarnessGenerator { @@ -78,9 +79,12 @@ impl fold::ast_fold for TestHarnessGenerator { } fn fold_item(&self, i: @ast::item) -> SmallVector<@ast::item> { - self.cx.path.push(i.ident); + { + let mut path = self.cx.path.borrow_mut(); + path.get().push(i.ident); + } debug!("current path: {}", - ast_util::path_name_i(self.cx.path.clone())); + ast_util::path_name_i(self.cx.path.get())); if is_test_fn(self.cx, i) || is_bench_fn(i) { match i.node { @@ -95,12 +99,15 @@ impl fold::ast_fold for TestHarnessGenerator { debug!("this is a test function"); let test = Test { span: i.span, - path: self.cx.path.clone(), + path: self.cx.path.get(), bench: is_bench_fn(i), ignore: is_ignored(self.cx, i), should_fail: should_fail(i) }; - self.cx.testfns.push(test); + { + let mut testfns = self.cx.testfns.borrow_mut(); + testfns.get().push(test); + } // debug!("have {} test/bench functions", // cx.testfns.len()); } @@ -108,7 +115,10 @@ impl fold::ast_fold for TestHarnessGenerator { } let res = fold::noop_fold_item(i, self); - self.cx.path.pop(); + { + let mut path = self.cx.path.borrow_mut(); + path.get().pop(); + } res } @@ -116,8 +126,8 @@ impl fold::ast_fold for TestHarnessGenerator { // Remove any #[main] from the AST so it doesn't clash with // the one we're going to add. Only if compiling an executable. - fn nomain(cx: @mut TestCtxt, item: @ast::item) -> @ast::item { - if !*cx.sess.building_library { + fn nomain(cx: @TestCtxt, item: @ast::item) -> @ast::item { + if !cx.sess.building_library.get() { @ast::item { attrs: item.attrs.iter().filter_map(|attr| { if "main" != attr.name() { @@ -144,11 +154,11 @@ impl fold::ast_fold for TestHarnessGenerator { fn generate_test_harness(sess: session::Session, crate: ast::Crate) -> ast::Crate { - let cx: @mut TestCtxt = @mut TestCtxt { + let cx: @TestCtxt = @TestCtxt { sess: sess, ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone()), - path: ~[], - testfns: ~[], + path: RefCell::new(~[]), + testfns: RefCell::new(~[]), is_extra: is_extra(&crate), config: crate.config.clone(), }; @@ -180,7 +190,7 @@ fn strip_test_functions(crate: ast::Crate) -> ast::Crate { }) } -fn is_test_fn(cx: @mut TestCtxt, i: @ast::item) -> bool { +fn is_test_fn(cx: @TestCtxt, i: @ast::item) -> bool { let has_test_attr = attr::contains_name(i.attrs, "test"); fn has_test_signature(i: @ast::item) -> bool { @@ -233,7 +243,7 @@ fn is_bench_fn(i: @ast::item) -> bool { return has_bench_attr && has_test_signature(i); } -fn is_ignored(cx: @mut TestCtxt, i: @ast::item) -> bool { +fn is_ignored(cx: @TestCtxt, i: @ast::item) -> bool { i.attrs.iter().any(|attr| { // check ignore(cfg(foo, bar)) "ignore" == attr.name() && match attr.meta_item_list() { @@ -382,10 +392,13 @@ fn is_extra(crate: &ast::Crate) -> bool { } fn mk_test_descs(cx: &TestCtxt) -> @ast::Expr { - debug!("building test vector from {} tests", cx.testfns.len()); let mut descs = ~[]; - for test in cx.testfns.iter() { - descs.push(mk_test_desc_and_fn_rec(cx, test)); + { + let testfns = cx.testfns.borrow(); + debug!("building test vector from {} tests", testfns.get().len()); + for test in testfns.get().iter() { + descs.push(mk_test_desc_and_fn_rec(cx, test)); + } } let inner_expr = @ast::Expr { diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 710a5dc93c0ed..a9f67e3108998 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -275,8 +275,9 @@ pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) { if ls { match input { d::file_input(ref ifile) => { + let mut stdout = io::stdout(); d::list_metadata(sess, &(*ifile), - @mut io::stdout() as @mut io::Writer); + &mut stdout as &mut io::Writer); } d::str_input(_) => { d::early_error(demitter, "can not list metadata for stdin"); diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 754b5c8fb0807..50a35e9d1bf81 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -11,6 +11,7 @@ #[allow(non_uppercase_pattern_statics)]; use std::c_str::ToCStr; +use std::cell::RefCell; use std::hashmap::HashMap; use std::libc::{c_uint, c_ushort, c_void, free}; use std::str::raw::from_c_str; @@ -1804,32 +1805,24 @@ pub fn SetFunctionAttribute(Fn: ValueRef, attr: Attribute) { /* Memory-managed object interface to type handles. */ pub struct TypeNames { - type_names: HashMap, - named_types: HashMap<~str, TypeRef> + named_types: RefCell>, } impl TypeNames { pub fn new() -> TypeNames { TypeNames { - type_names: HashMap::new(), - named_types: HashMap::new() + named_types: RefCell::new(HashMap::new()) } } - pub fn associate_type(&mut self, s: &str, t: &Type) { - assert!(self.type_names.insert(t.to_ref(), s.to_owned())); - assert!(self.named_types.insert(s.to_owned(), t.to_ref())); - } - - pub fn find_name<'r>(&'r self, ty: &Type) -> Option<&'r str> { - match self.type_names.find(&ty.to_ref()) { - Some(a) => Some(a.slice(0, a.len())), - None => None - } + pub fn associate_type(&self, s: &str, t: &Type) { + let mut named_types = self.named_types.borrow_mut(); + assert!(named_types.get().insert(s.to_owned(), t.to_ref())); } pub fn find_type(&self, s: &str) -> Option { - self.named_types.find_equiv(&s).map(|x| Type::from_ref(*x)) + let named_types = self.named_types.borrow(); + named_types.get().find_equiv(&s).map(|x| Type::from_ref(*x)) } pub fn type_to_str(&self, ty: Type) -> ~str { diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index efa28b9b6bdd6..de5ae08cf5756 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -15,6 +15,7 @@ use metadata::cstore; use metadata::decoder; use metadata::loader; +use std::cell::RefCell; use std::hashmap::HashMap; use syntax::ast; use syntax::abi; @@ -33,22 +34,30 @@ pub fn read_crates(sess: Session, crate: &ast::Crate, os: loader::Os, intr: @ident_interner) { - let e = @mut Env { + let mut e = Env { sess: sess, os: os, - crate_cache: @mut ~[], + crate_cache: @RefCell::new(~[]), next_crate_num: 1, intr: intr }; - let mut v = ReadCrateVisitor{ e:e }; - visit_crate(e, crate); - visit::walk_crate(&mut v, crate, ()); - dump_crates(*e.crate_cache); - warn_if_multiple_versions(e, sess.diagnostic(), *e.crate_cache); + visit_crate(&e, crate); + { + let mut v = ReadCrateVisitor { + e: &mut e + }; + visit::walk_crate(&mut v, crate, ()); + } + let crate_cache = e.crate_cache.borrow(); + dump_crates(*crate_cache.get()); + warn_if_multiple_versions(&mut e, sess.diagnostic(), *crate_cache.get()); } -struct ReadCrateVisitor { e:@mut Env } -impl visit::Visitor<()> for ReadCrateVisitor { +struct ReadCrateVisitor<'a> { + e: &'a mut Env, +} + +impl<'a> visit::Visitor<()> for ReadCrateVisitor<'a> { fn visit_view_item(&mut self, a:&ast::view_item, _:()) { visit_view_item(self.e, a); visit::walk_view_item(self, a, ()); @@ -76,7 +85,7 @@ fn dump_crates(crate_cache: &[cache_entry]) { } } -fn warn_if_multiple_versions(e: @mut Env, +fn warn_if_multiple_versions(e: &mut Env, diag: @mut span_handler, crate_cache: &[cache_entry]) { if crate_cache.len() != 0u { @@ -103,7 +112,7 @@ fn warn_if_multiple_versions(e: @mut Env, struct Env { sess: Session, os: loader::Os, - crate_cache: @mut ~[cache_entry], + crate_cache: @RefCell<~[cache_entry]>, next_crate_num: ast::CrateNum, intr: @ident_interner } @@ -121,7 +130,7 @@ fn visit_crate(e: &Env, c: &ast::Crate) { } } -fn visit_view_item(e: @mut Env, i: &ast::view_item) { +fn visit_view_item(e: &mut Env, i: &ast::view_item) { match i.node { ast::view_item_extern_mod(ident, path_opt, _, id) => { let ident = token::ident_to_str(&ident); @@ -234,7 +243,8 @@ fn visit_item(e: &Env, i: @ast::item) { } fn existing_match(e: &Env, name: @str, version: @str, hash: &str) -> Option { - for c in e.crate_cache.iter() { + let crate_cache = e.crate_cache.borrow(); + for c in crate_cache.get().iter() { let pkgid_version = match c.pkgid.version { None => @"0.0", Some(ref ver) => ver.to_managed(), @@ -248,7 +258,7 @@ fn existing_match(e: &Env, name: @str, version: @str, hash: &str) -> Option cstore::cnum_map { +fn resolve_crate_deps(e: &mut Env, cdata: &[u8]) -> cstore::cnum_map { debug!("resolving deps of external crate"); // The map from crate numbers in the crate we're resolving to local crate // numbers @@ -340,5 +353,5 @@ fn resolve_crate_deps(e: @mut Env, cdata: &[u8]) -> cstore::cnum_map { } } } - return @mut cnum_map; + return @RefCell::new(cnum_map); } diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index ea8ad1d73d23f..ffb6eb3679273 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -30,19 +30,19 @@ pub struct StaticMethodInfo { vis: ast::visibility, } -pub fn get_symbol(cstore: @mut cstore::CStore, def: ast::DefId) -> ~str { +pub fn get_symbol(cstore: @cstore::CStore, def: ast::DefId) -> ~str { let cdata = cstore.get_crate_data(def.crate).data(); return decoder::get_symbol(cdata, def.node); } -pub fn get_type_param_count(cstore: @mut cstore::CStore, def: ast::DefId) +pub fn get_type_param_count(cstore: @cstore::CStore, def: ast::DefId) -> uint { let cdata = cstore.get_crate_data(def.crate).data(); return decoder::get_type_param_count(cdata, def.node); } /// Iterates over all the language items in the given crate. -pub fn each_lang_item(cstore: @mut cstore::CStore, +pub fn each_lang_item(cstore: @cstore::CStore, cnum: ast::CrateNum, f: |ast::NodeId, uint| -> bool) -> bool { @@ -51,7 +51,7 @@ pub fn each_lang_item(cstore: @mut cstore::CStore, } /// Iterates over each child of the given item. -pub fn each_child_of_item(cstore: @mut cstore::CStore, +pub fn each_child_of_item(cstore: @cstore::CStore, def_id: ast::DefId, callback: |decoder::DefLike, ast::Ident, @@ -68,7 +68,7 @@ pub fn each_child_of_item(cstore: @mut cstore::CStore, } /// Iterates over each top-level crate item. -pub fn each_top_level_item_of_crate(cstore: @mut cstore::CStore, +pub fn each_top_level_item_of_crate(cstore: @cstore::CStore, cnum: ast::CrateNum, callback: |decoder::DefLike, ast::Ident, @@ -131,7 +131,7 @@ pub fn get_method(tcx: ty::ctxt, def: ast::DefId) -> ty::Method { decoder::get_method(tcx.cstore.intr, cdata, def.node, tcx) } -pub fn get_method_name_and_explicit_self(cstore: @mut cstore::CStore, +pub fn get_method_name_and_explicit_self(cstore: @cstore::CStore, def: ast::DefId) -> (ast::Ident, ast::explicit_self_) { @@ -139,13 +139,13 @@ pub fn get_method_name_and_explicit_self(cstore: @mut cstore::CStore, decoder::get_method_name_and_explicit_self(cstore.intr, cdata, def.node) } -pub fn get_trait_method_def_ids(cstore: @mut cstore::CStore, +pub fn get_trait_method_def_ids(cstore: @cstore::CStore, def: ast::DefId) -> ~[ast::DefId] { let cdata = cstore.get_crate_data(def.crate); decoder::get_trait_method_def_ids(cdata, def.node) } -pub fn get_item_variances(cstore: @mut cstore::CStore, +pub fn get_item_variances(cstore: @cstore::CStore, def: ast::DefId) -> ty::ItemVariances { let cdata = cstore.get_crate_data(def.crate); decoder::get_item_variances(cdata, def.node) @@ -165,27 +165,27 @@ pub fn get_supertraits(tcx: ty::ctxt, def: ast::DefId) -> ~[@ty::TraitRef] { decoder::get_supertraits(cdata, def.node, tcx) } -pub fn get_type_name_if_impl(cstore: @mut cstore::CStore, def: ast::DefId) +pub fn get_type_name_if_impl(cstore: @cstore::CStore, def: ast::DefId) -> Option { let cdata = cstore.get_crate_data(def.crate); decoder::get_type_name_if_impl(cdata, def.node) } -pub fn get_static_methods_if_impl(cstore: @mut cstore::CStore, +pub fn get_static_methods_if_impl(cstore: @cstore::CStore, def: ast::DefId) -> Option<~[StaticMethodInfo]> { let cdata = cstore.get_crate_data(def.crate); decoder::get_static_methods_if_impl(cstore.intr, cdata, def.node) } -pub fn get_item_attrs(cstore: @mut cstore::CStore, +pub fn get_item_attrs(cstore: @cstore::CStore, def_id: ast::DefId, f: |~[@ast::MetaItem]|) { let cdata = cstore.get_crate_data(def_id.crate); decoder::get_item_attrs(cdata, def_id.node, f) } -pub fn get_struct_fields(cstore: @mut cstore::CStore, +pub fn get_struct_fields(cstore: @cstore::CStore, def: ast::DefId) -> ~[ty::field_ty] { let cdata = cstore.get_crate_data(def.crate); @@ -247,7 +247,7 @@ pub fn get_impl_vtables(tcx: ty::ctxt, decoder::get_impl_vtables(cdata, def.node, tcx) } -pub fn get_impl_method(cstore: @mut cstore::CStore, +pub fn get_impl_method(cstore: @cstore::CStore, def: ast::DefId, mname: ast::Ident) -> Option { @@ -255,35 +255,35 @@ pub fn get_impl_method(cstore: @mut cstore::CStore, decoder::get_impl_method(cstore.intr, cdata, def.node, mname) } -pub fn get_item_visibility(cstore: @mut cstore::CStore, +pub fn get_item_visibility(cstore: @cstore::CStore, def_id: ast::DefId) -> ast::visibility { let cdata = cstore.get_crate_data(def_id.crate); decoder::get_item_visibility(cdata, def_id.node) } -pub fn get_native_libraries(cstore: @mut cstore::CStore, +pub fn get_native_libraries(cstore: @cstore::CStore, crate_num: ast::CrateNum) -> ~[(cstore::NativeLibaryKind, ~str)] { let cdata = cstore.get_crate_data(crate_num); decoder::get_native_libraries(cdata) } -pub fn each_impl(cstore: @mut cstore::CStore, +pub fn each_impl(cstore: @cstore::CStore, crate_num: ast::CrateNum, callback: |ast::DefId|) { let cdata = cstore.get_crate_data(crate_num); decoder::each_impl(cdata, callback) } -pub fn each_implementation_for_type(cstore: @mut cstore::CStore, +pub fn each_implementation_for_type(cstore: @cstore::CStore, def_id: ast::DefId, callback: |ast::DefId|) { let cdata = cstore.get_crate_data(def_id.crate); decoder::each_implementation_for_type(cdata, def_id.node, callback) } -pub fn each_implementation_for_trait(cstore: @mut cstore::CStore, +pub fn each_implementation_for_trait(cstore: @cstore::CStore, def_id: ast::DefId, callback: |ast::DefId|) { let cdata = cstore.get_crate_data(def_id.crate); @@ -293,7 +293,7 @@ pub fn each_implementation_for_trait(cstore: @mut cstore::CStore, /// If the given def ID describes a method belonging to a trait (either a /// default method or an implementation of a trait method), returns the ID of /// the trait that the method belongs to. Otherwise, returns `None`. -pub fn get_trait_of_method(cstore: @mut cstore::CStore, +pub fn get_trait_of_method(cstore: @cstore::CStore, def_id: ast::DefId, tcx: ty::ctxt) -> Option { diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index 5972555d69c99..f567665256bdc 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -15,6 +15,7 @@ use metadata::decoder; use metadata::loader; +use std::cell::RefCell; use std::hashmap::HashMap; use syntax::ast; use syntax::parse::token::ident_interner; @@ -23,7 +24,7 @@ use syntax::parse::token::ident_interner; // local crate numbers (as generated during this session). Each external // crate may refer to types in other external crates, and each has their // own crate numbers. -pub type cnum_map = @mut HashMap; +pub type cnum_map = @RefCell>; pub enum MetadataBlob { MetadataVec(~[u8]), @@ -60,11 +61,11 @@ pub struct CrateSource { } pub struct CStore { - priv metas: HashMap , - priv extern_mod_crate_map: extern_mod_crate_map, - priv used_crate_sources: ~[CrateSource], - priv used_libraries: ~[(~str, NativeLibaryKind)], - priv used_link_args: ~[~str], + priv metas: RefCell>, + priv extern_mod_crate_map: RefCell, + priv used_crate_sources: RefCell<~[CrateSource]>, + priv used_libraries: RefCell<~[(~str, NativeLibaryKind)]>, + priv used_link_args: RefCell<~[~str]>, intr: @ident_interner } @@ -74,17 +75,18 @@ type extern_mod_crate_map = HashMap; impl CStore { pub fn new(intr: @ident_interner) -> CStore { CStore { - metas: HashMap::new(), - extern_mod_crate_map: HashMap::new(), - used_crate_sources: ~[], - used_libraries: ~[], - used_link_args: ~[], + metas: RefCell::new(HashMap::new()), + extern_mod_crate_map: RefCell::new(HashMap::new()), + used_crate_sources: RefCell::new(~[]), + used_libraries: RefCell::new(~[]), + used_link_args: RefCell::new(~[]), intr: intr } } pub fn get_crate_data(&self, cnum: ast::CrateNum) -> @crate_metadata { - *self.metas.get(&cnum) + let metas = self.metas.borrow(); + *metas.get().get(&cnum) } pub fn get_crate_hash(&self, cnum: ast::CrateNum) -> @str { @@ -97,33 +99,35 @@ impl CStore { decoder::get_crate_vers(cdata.data()) } - pub fn set_crate_data(&mut self, cnum: ast::CrateNum, data: @crate_metadata) { - self.metas.insert(cnum, data); + pub fn set_crate_data(&self, cnum: ast::CrateNum, data: @crate_metadata) { + let mut metas = self.metas.borrow_mut(); + metas.get().insert(cnum, data); } pub fn have_crate_data(&self, cnum: ast::CrateNum) -> bool { - self.metas.contains_key(&cnum) + let metas = self.metas.borrow(); + metas.get().contains_key(&cnum) } pub fn iter_crate_data(&self, i: |ast::CrateNum, @crate_metadata|) { - for (&k, &v) in self.metas.iter() { + let metas = self.metas.borrow(); + for (&k, &v) in metas.get().iter() { i(k, v); } } - pub fn add_used_crate_source(&mut self, src: CrateSource) { - if !self.used_crate_sources.contains(&src) { - self.used_crate_sources.push(src); + pub fn add_used_crate_source(&self, src: CrateSource) { + let mut used_crate_sources = self.used_crate_sources.borrow_mut(); + if !used_crate_sources.get().contains(&src) { + used_crate_sources.get().push(src); } } - pub fn get_used_crate_sources<'a>(&'a self) -> &'a [CrateSource] { - self.used_crate_sources.as_slice() - } - pub fn get_used_crates(&self, prefer: LinkagePreference) -> ~[(ast::CrateNum, Option)] { - self.used_crate_sources.iter() + let used_crate_sources = self.used_crate_sources.borrow(); + used_crate_sources.get() + .iter() .map(|src| (src.cnum, match prefer { RequireDynamic => src.dylib.clone(), RequireStatic => src.rlib.clone(), @@ -131,38 +135,44 @@ impl CStore { .collect() } - pub fn add_used_library(&mut self, lib: ~str, kind: NativeLibaryKind) -> bool { + pub fn add_used_library(&self, lib: ~str, kind: NativeLibaryKind) + -> bool { assert!(!lib.is_empty()); - if self.used_libraries.iter().any(|&(ref x, _)| x == &lib) { + let mut used_libraries = self.used_libraries.borrow_mut(); + if used_libraries.get().iter().any(|&(ref x, _)| x == &lib) { return false; } - self.used_libraries.push((lib, kind)); + used_libraries.get().push((lib, kind)); true } - pub fn get_used_libraries<'a>(&'a self) -> &'a [(~str, NativeLibaryKind)] { - self.used_libraries.as_slice() + pub fn get_used_libraries<'a>(&'a self) + -> &'a RefCell<~[(~str, NativeLibaryKind)]> { + &self.used_libraries } - pub fn add_used_link_args(&mut self, args: &str) { + pub fn add_used_link_args(&self, args: &str) { + let mut used_link_args = self.used_link_args.borrow_mut(); for s in args.split(' ') { - self.used_link_args.push(s.to_owned()); + used_link_args.get().push(s.to_owned()); } } - pub fn get_used_link_args<'a>(&'a self) -> &'a [~str] { - self.used_link_args.as_slice() + pub fn get_used_link_args<'a>(&'a self) -> &'a RefCell<~[~str]> { + &self.used_link_args } - pub fn add_extern_mod_stmt_cnum(&mut self, + pub fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: ast::CrateNum) { - self.extern_mod_crate_map.insert(emod_id, cnum); + let mut extern_mod_crate_map = self.extern_mod_crate_map.borrow_mut(); + extern_mod_crate_map.get().insert(emod_id, cnum); } pub fn find_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { - self.extern_mod_crate_map.find(&emod_id).map(|x| *x) + let extern_mod_crate_map = self.extern_mod_crate_map.borrow(); + extern_mod_crate_map.get().find(&emod_id).map(|x| *x) } // returns hashes of crates directly used by this crate. Hashes are sorted by @@ -170,7 +180,8 @@ impl CStore { pub fn get_dep_hashes(&self) -> ~[@str] { let mut result = ~[]; - for (_, &cnum) in self.extern_mod_crate_map.iter() { + let extern_mod_crate_map = self.extern_mod_crate_map.borrow(); + for (_, &cnum) in extern_mod_crate_map.get().iter() { let cdata = self.get_crate_data(cnum); let hash = decoder::get_crate_hash(cdata.data()); let vers = decoder::get_crate_vers(cdata.data()); diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index e21a41d9ba25c..a0b339cc91d74 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -494,6 +494,7 @@ pub fn get_symbol(data: &[u8], id: ast::NodeId) -> ~str { } // Something that a name can resolve to. +#[deriving(Clone)] pub enum DefLike { DlDef(ast::Def), DlImpl(ast::DefId), @@ -1109,7 +1110,7 @@ fn get_attributes(md: ebml::Doc) -> ~[ast::Attribute] { } fn list_crate_attributes(intr: @ident_interner, md: ebml::Doc, hash: &str, - out: @mut io::Writer) { + out: &mut io::Writer) { write!(out, "=Crate Attributes ({})=\n", hash); let r = get_attributes(md); @@ -1152,7 +1153,7 @@ pub fn get_crate_deps(data: &[u8]) -> ~[CrateDep] { return deps; } -fn list_crate_deps(data: &[u8], out: @mut io::Writer) { +fn list_crate_deps(data: &[u8], out: &mut io::Writer) { write!(out, "=External Dependencies=\n"); let r = get_crate_deps(data); @@ -1179,7 +1180,7 @@ pub fn get_crate_vers(data: &[u8]) -> @str { } pub fn list_crate_metadata(intr: @ident_interner, bytes: &[u8], - out: @mut io::Writer) { + out: &mut io::Writer) { let hash = get_crate_hash(bytes); let md = reader::Doc(bytes); list_crate_attributes(intr, md, hash, out); @@ -1196,9 +1197,15 @@ pub fn translate_def_id(cdata: Cmd, did: ast::DefId) -> ast::DefId { return ast::DefId { crate: cdata.cnum, node: did.node }; } - match cdata.cnum_map.find(&did.crate) { - option::Some(&n) => ast::DefId { crate: n, node: did.node }, - option::None => fail!("didn't find a crate in the cnum_map") + let cnum_map = cdata.cnum_map.borrow(); + match cnum_map.get().find(&did.crate) { + Some(&n) => { + ast::DefId { + crate: n, + node: did.node, + } + } + None => fail!("didn't find a crate in the cnum_map") } } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index c331c71ac9ee1..7bd87f5dff816 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -22,6 +22,7 @@ use middle::typeck; use middle; use std::cast; +use std::cell::{Cell, RefCell}; use std::hashmap::{HashMap, HashSet}; use std::io::mem::MemWriter; use std::io::{Writer, Seek, Decorator}; @@ -48,7 +49,7 @@ use syntax; use writer = extra::ebml::writer; // used by astencode: -type abbrev_map = @mut HashMap; +type abbrev_map = @RefCell>; pub type encode_inlined_item<'a> = 'a |ecx: &EncodeContext, ebml_w: &mut writer::Encoder, @@ -59,48 +60,45 @@ pub struct EncodeParams<'a> { diag: @mut span_handler, tcx: ty::ctxt, reexports2: middle::resolve::ExportMap2, - item_symbols: &'a HashMap, - discrim_symbols: &'a HashMap, - non_inlineable_statics: &'a HashSet, + item_symbols: &'a RefCell>, + non_inlineable_statics: &'a RefCell>, link_meta: &'a LinkMeta, - cstore: @mut cstore::CStore, + cstore: @cstore::CStore, encode_inlined_item: encode_inlined_item<'a>, - reachable: @mut HashSet, + reachable: @RefCell>, } struct Stats { - inline_bytes: u64, - attr_bytes: u64, - dep_bytes: u64, - lang_item_bytes: u64, - native_lib_bytes: u64, - impl_bytes: u64, - misc_bytes: u64, - item_bytes: u64, - index_bytes: u64, - zero_bytes: u64, - total_bytes: u64, - - n_inlines: uint + inline_bytes: Cell, + attr_bytes: Cell, + dep_bytes: Cell, + lang_item_bytes: Cell, + native_lib_bytes: Cell, + impl_bytes: Cell, + misc_bytes: Cell, + item_bytes: Cell, + index_bytes: Cell, + zero_bytes: Cell, + total_bytes: Cell, } pub struct EncodeContext<'a> { diag: @mut span_handler, tcx: ty::ctxt, - stats: @mut Stats, + stats: @Stats, reexports2: middle::resolve::ExportMap2, - item_symbols: &'a HashMap, - discrim_symbols: &'a HashMap, - non_inlineable_statics: &'a HashSet, + item_symbols: &'a RefCell>, + non_inlineable_statics: &'a RefCell>, link_meta: &'a LinkMeta, cstore: &'a cstore::CStore, encode_inlined_item: encode_inlined_item<'a>, type_abbrevs: abbrev_map, - reachable: @mut HashSet, + reachable: @RefCell>, } pub fn reachable(ecx: &EncodeContext, id: NodeId) -> bool { - ecx.reachable.contains(&id) + let reachable = ecx.reachable.borrow(); + reachable.get().contains(&id) } fn encode_name(ecx: &EncodeContext, @@ -283,7 +281,8 @@ fn encode_symbol(ecx: &EncodeContext, ebml_w: &mut writer::Encoder, id: NodeId) { ebml_w.start_tag(tag_items_data_item_symbol); - match ecx.item_symbols.find(&id) { + let item_symbols = ecx.item_symbols.borrow(); + match item_symbols.get().find(&id) { Some(x) => { debug!("encode_symbol(id={:?}, str={})", id, *x); ebml_w.writer.write(x.as_bytes()); @@ -338,7 +337,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext, id: NodeId, variants: &[P], path: &[ast_map::path_elt], - index: @mut ~[entry], + index: @RefCell<~[entry]>, generics: &ast::Generics) { debug!("encode_enum_variant_info(id={:?})", id); @@ -348,8 +347,13 @@ fn encode_enum_variant_info(ecx: &EncodeContext, ast::DefId { crate: LOCAL_CRATE, node: id }); for variant in variants.iter() { let def_id = local_def(variant.node.id); - index.push(entry {val: variant.node.id as i64, - pos: ebml_w.writer.tell()}); + { + let mut index = index.borrow_mut(); + index.get().push(entry { + val: variant.node.id as i64, + pos: ebml_w.writer.tell(), + }); + } ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, def_id); match variant.node.kind { @@ -442,9 +446,11 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext, ebml_w: &mut writer::Encoder, exp: &middle::resolve::Export2) -> bool { - match ecx.tcx.inherent_impls.find(&exp.def_id) { + let inherent_impls = ecx.tcx.inherent_impls.borrow(); + match inherent_impls.get().find(&exp.def_id) { Some(implementations) => { - for &base_impl in implementations.iter() { + let implementations = implementations.borrow(); + for &base_impl in implementations.get().iter() { for &m in base_impl.methods.iter() { if m.explicit_self == ast::sty_static { encode_reexported_static_method(ecx, ebml_w, exp, @@ -463,7 +469,8 @@ fn encode_reexported_static_trait_methods(ecx: &EncodeContext, ebml_w: &mut writer::Encoder, exp: &middle::resolve::Export2) -> bool { - match ecx.tcx.trait_methods_cache.find(&exp.def_id) { + let trait_methods_cache = ecx.tcx.trait_methods_cache.borrow(); + match trait_methods_cache.get().find(&exp.def_id) { Some(methods) => { for &m in methods.iter() { if m.explicit_self == ast::sty_static { @@ -553,7 +560,8 @@ fn encode_reexports(ecx: &EncodeContext, id: NodeId, path: &[ast_map::path_elt]) { debug!("(encoding info for module) encoding reexports for {}", id); - match ecx.reexports2.find(&id) { + let reexports2 = ecx.reexports2.borrow(); + match reexports2.get().find(&id) { Some(ref exports) => { debug!("(encoding info for module) found reexports for {}", id); for exp in exports.iter() { @@ -715,7 +723,7 @@ fn encode_info_for_struct(ecx: &EncodeContext, ebml_w: &mut writer::Encoder, path: &[ast_map::path_elt], fields: &[struct_field], - global_index: @mut ~[entry]) + global_index: @RefCell<~[entry]>) -> ~[entry] { /* Each class has its own index, since different classes may have fields with the same name */ @@ -731,7 +739,13 @@ fn encode_info_for_struct(ecx: &EncodeContext, let id = field.node.id; index.push(entry {val: id as i64, pos: ebml_w.writer.tell()}); - global_index.push(entry {val: id as i64, pos: ebml_w.writer.tell()}); + { + let mut global_index = global_index.borrow_mut(); + global_index.get().push(entry { + val: id as i64, + pos: ebml_w.writer.tell(), + }); + } ebml_w.start_tag(tag_items_data_item); debug!("encode_info_for_struct: doing {} {}", tcx.sess.str_of(nm), id); @@ -750,9 +764,15 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext, path: &[ast_map::path_elt], name: ast::Ident, ctor_id: NodeId, - index: @mut ~[entry], + index: @RefCell<~[entry]>, struct_id: NodeId) { - index.push(entry { val: ctor_id as i64, pos: ebml_w.writer.tell() }); + { + let mut index = index.borrow_mut(); + index.get().push(entry { + val: ctor_id as i64, + pos: ebml_w.writer.tell(), + }); + } ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(ctor_id)); @@ -762,7 +782,8 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext, encode_path(ecx, ebml_w, path, ast_map::path_name(name)); encode_parent_item(ebml_w, local_def(struct_id)); - if ecx.item_symbols.contains_key(&ctor_id) { + let item_symbols = ecx.item_symbols.borrow(); + if item_symbols.get().contains_key(&ctor_id) { encode_symbol(ecx, ebml_w, ctor_id); } @@ -860,10 +881,12 @@ fn should_inline(attrs: &[Attribute]) -> bool { fn encode_inherent_implementations(ecx: &EncodeContext, ebml_w: &mut writer::Encoder, def_id: DefId) { - match ecx.tcx.inherent_impls.find(&def_id) { + let inherent_impls = ecx.tcx.inherent_impls.borrow(); + match inherent_impls.get().find(&def_id) { None => {} Some(&implementations) => { - for implementation in implementations.iter() { + let implementations = implementations.borrow(); + for implementation in implementations.get().iter() { ebml_w.start_tag(tag_items_data_item_inherent_impl); encode_def_id(ebml_w, implementation.did); ebml_w.end_tag(); @@ -876,10 +899,12 @@ fn encode_inherent_implementations(ecx: &EncodeContext, fn encode_extension_implementations(ecx: &EncodeContext, ebml_w: &mut writer::Encoder, trait_def_id: DefId) { - match ecx.tcx.trait_impls.find(&trait_def_id) { + let trait_impls = ecx.tcx.trait_impls.borrow(); + match trait_impls.get().find(&trait_def_id) { None => {} Some(&implementations) => { - for implementation in implementations.iter() { + let implementations = implementations.borrow(); + for implementation in implementations.get().iter() { ebml_w.start_tag(tag_items_data_item_extension_impl); encode_def_id(ebml_w, implementation.did); ebml_w.end_tag(); @@ -891,14 +916,18 @@ fn encode_extension_implementations(ecx: &EncodeContext, fn encode_info_for_item(ecx: &EncodeContext, ebml_w: &mut writer::Encoder, item: @item, - index: @mut ~[entry], + index: @RefCell<~[entry]>, path: &[ast_map::path_elt], vis: ast::visibility) { let tcx = ecx.tcx; fn add_to_index(item: @item, ebml_w: &writer::Encoder, - index: @mut ~[entry]) { - index.push(entry { val: item.id as i64, pos: ebml_w.writer.tell() }); + index: @RefCell<~[entry]>) { + let mut index = index.borrow_mut(); + index.get().push(entry { + val: item.id as i64, + pos: ebml_w.writer.tell(), + }); } let add_to_index: || = || add_to_index(item, ebml_w, index); @@ -921,7 +950,14 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_name(ecx, ebml_w, item.ident); let elt = ast_map::path_pretty_name(item.ident, item.id as u64); encode_path(ecx, ebml_w, path, elt); - if !ecx.non_inlineable_statics.contains(&item.id) { + + let non_inlineable; + { + let non_inlineable_statics = ecx.non_inlineable_statics.borrow(); + non_inlineable = non_inlineable_statics.get().contains(&item.id); + } + + if !non_inlineable { (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item)); } encode_visibility(ebml_w, vis); @@ -1072,7 +1108,8 @@ fn encode_info_for_item(ecx: &EncodeContext, item_impl(_, ref opt_trait, ty, ref ast_methods) => { // We need to encode information about the default methods we // have inherited, so we drive this based on the impl structure. - let imp = tcx.impls.get(&def_id); + let impls = tcx.impls.borrow(); + let imp = impls.get().get(&def_id); add_to_index(); ebml_w.start_tag(tag_items_data_item); @@ -1121,8 +1158,13 @@ fn encode_info_for_item(ecx: &EncodeContext, Some(ast_methods[i]) } else { None }; - index.push(entry {val: m.def_id.node as i64, - pos: ebml_w.writer.tell()}); + { + let mut index = index.borrow_mut(); + index.get().push(entry { + val: m.def_id.node as i64, + pos: ebml_w.writer.tell(), + }); + } encode_info_for_method(ecx, ebml_w, *m, @@ -1177,8 +1219,13 @@ fn encode_info_for_item(ecx: &EncodeContext, let method_ty = ty::method(tcx, method_def_id); - index.push(entry {val: method_def_id.node as i64, - pos: ebml_w.writer.tell()}); + { + let mut index = index.borrow_mut(); + index.get().push(entry { + val: method_def_id.node as i64, + pos: ebml_w.writer.tell(), + }); + } ebml_w.start_tag(tag_items_data_item); @@ -1242,10 +1289,16 @@ fn encode_info_for_item(ecx: &EncodeContext, fn encode_info_for_foreign_item(ecx: &EncodeContext, ebml_w: &mut writer::Encoder, nitem: @foreign_item, - index: @mut ~[entry], + index: @RefCell<~[entry]>, path: &ast_map::path, abi: AbiSet) { - index.push(entry { val: nitem.id as i64, pos: ebml_w.writer.tell() }); + { + let mut index = index.borrow_mut(); + index.get().push(entry { + val: nitem.id as i64, + pos: ebml_w.writer.tell(), + }); + } ebml_w.start_tag(tag_items_data_item); match nitem.node { @@ -1280,11 +1333,16 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext, fn my_visit_expr(_e:@Expr) { } -fn my_visit_item(i:@item, items: ast_map::map, ebml_w:&writer::Encoder, - ecx_ptr:*int, index: @mut ~[entry]) { +fn my_visit_item(i: @item, + items: ast_map::map, + ebml_w: &mut writer::Encoder, + ecx_ptr: *int, + index: @RefCell<~[entry]>) { match items.get_copy(&i.id) { ast_map::node_item(_, pt) => { - let mut ebml_w = ebml_w.clone(); + let mut ebml_w = unsafe { + ebml_w.unsafe_clone() + }; // See above let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) }; encode_info_for_item(ecx, &mut ebml_w, i, index, *pt, i.vis); @@ -1293,8 +1351,11 @@ fn my_visit_item(i:@item, items: ast_map::map, ebml_w:&writer::Encoder, } } -fn my_visit_foreign_item(ni:@foreign_item, items: ast_map::map, ebml_w:&writer::Encoder, - ecx_ptr:*int, index: @mut ~[entry]) { +fn my_visit_foreign_item(ni: @foreign_item, + items: ast_map::map, + ebml_w: &mut writer::Encoder, + ecx_ptr:*int, + index: @RefCell<~[entry]>) { match items.get_copy(&ni.id) { ast_map::node_foreign_item(_, abi, _, pt) => { debug!("writing foreign item {}::{}", @@ -1303,9 +1364,11 @@ fn my_visit_foreign_item(ni:@foreign_item, items: ast_map::map, ebml_w:&writer:: token::get_ident_interner()), token::ident_to_str(&ni.ident)); - let mut ebml_w = ebml_w.clone(); + let mut ebml_w = unsafe { + ebml_w.unsafe_clone() + }; // See above - let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) }; + let ecx: &EncodeContext = unsafe { cast::transmute(ecx_ptr) }; encode_info_for_foreign_item(ecx, &mut ebml_w, ni, @@ -1318,15 +1381,14 @@ fn my_visit_foreign_item(ni:@foreign_item, items: ast_map::map, ebml_w:&writer:: } } -struct EncodeVisitor { - ebml_w_for_visit_item: writer::Encoder, - ebml_w_for_visit_foreign_item: writer::Encoder, +struct EncodeVisitor<'a,'b> { + ebml_w_for_visit_item: &'a mut writer::Encoder<'b>, ecx_ptr:*int, items: ast_map::map, - index: @mut ~[entry], + index: @RefCell<~[entry]>, } -impl visit::Visitor<()> for EncodeVisitor { +impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> { fn visit_expr(&mut self, ex:@Expr, _:()) { visit::walk_expr(self, ex, ()); my_visit_expr(ex); @@ -1335,7 +1397,7 @@ impl visit::Visitor<()> for EncodeVisitor { visit::walk_item(self, i, ()); my_visit_item(i, self.items, - &self.ebml_w_for_visit_item, + self.ebml_w_for_visit_item, self.ecx_ptr, self.index); } @@ -1343,7 +1405,7 @@ impl visit::Visitor<()> for EncodeVisitor { visit::walk_foreign_item(self, ni, ()); my_visit_foreign_item(ni, self.items, - &self.ebml_w_for_visit_foreign_item, + self.ebml_w_for_visit_item, self.ecx_ptr, self.index); } @@ -1353,9 +1415,15 @@ fn encode_info_for_items(ecx: &EncodeContext, ebml_w: &mut writer::Encoder, crate: &Crate) -> ~[entry] { - let index = @mut ~[]; + let index = @RefCell::new(~[]); ebml_w.start_tag(tag_items_data); - index.push(entry { val: CRATE_NODE_ID as i64, pos: ebml_w.writer.tell() }); + { + let mut index = index.borrow_mut(); + index.get().push(entry { + val: CRATE_NODE_ID as i64, + pos: ebml_w.writer.tell(), + }); + } encode_info_for_mod(ecx, ebml_w, &crate.module, @@ -1367,18 +1435,19 @@ fn encode_info_for_items(ecx: &EncodeContext, // See comment in `encode_side_tables_for_ii` in astencode let ecx_ptr : *int = unsafe { cast::transmute(ecx) }; - let mut visitor = EncodeVisitor { - index: index, - items: items, - ecx_ptr: ecx_ptr, - ebml_w_for_visit_item: (*ebml_w).clone(), - ebml_w_for_visit_foreign_item: (*ebml_w).clone(), - }; + { + let mut visitor = EncodeVisitor { + index: index, + items: items, + ecx_ptr: ecx_ptr, + ebml_w_for_visit_item: &mut *ebml_w, + }; - visit::walk_crate(&mut visitor, crate, ()); + visit::walk_crate(&mut visitor, crate, ()); + } ebml_w.end_tag(); - return /*bad*/(*index).clone(); + return /*bad*/(*index).get(); } @@ -1387,16 +1456,19 @@ fn encode_info_for_items(ecx: &EncodeContext, fn create_index( index: ~[entry]) -> ~[@~[entry]] { - let mut buckets: ~[@mut ~[entry]] = ~[]; - for _ in range(0u, 256u) { buckets.push(@mut ~[]); }; + let mut buckets: ~[@RefCell<~[entry]>] = ~[]; + for _ in range(0u, 256u) { + buckets.push(@RefCell::new(~[])); + } for elt in index.iter() { let h = elt.val.hash() as uint; - buckets[h % 256].push((*elt).clone()); + let mut bucket = buckets[h % 256].borrow_mut(); + bucket.get().push((*elt).clone()); } let mut buckets_frozen = ~[]; for bucket in buckets.iter() { - buckets_frozen.push(@/*bad*/(**bucket).clone()); + buckets_frozen.push(@/*bad*/(**bucket).get()); } return buckets_frozen; } @@ -1404,7 +1476,7 @@ fn create_index( fn encode_index( ebml_w: &mut writer::Encoder, buckets: ~[@~[entry]], - write_fn: |@mut MemWriter, &T|) { + write_fn: |&mut MemWriter, &T|) { ebml_w.start_tag(tag_index); let mut bucket_locs = ~[]; ebml_w.start_tag(tag_index_buckets); @@ -1434,7 +1506,7 @@ fn encode_index( ebml_w.end_tag(); } -fn write_i64(writer: @mut MemWriter, &n: &i64) { +fn write_i64(writer: &mut MemWriter, &n: &i64) { let wr: &mut MemWriter = writer; assert!(n < 0x7fff_ffff); wr.write_be_u32(n as u32); @@ -1588,7 +1660,9 @@ fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) { fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) { ebml_w.start_tag(tag_native_libraries); - for &(ref lib, kind) in ecx.cstore.get_used_libraries().iter() { + let used_libraries = ecx.tcx.sess.cstore.get_used_libraries(); + let used_libraries = used_libraries.borrow(); + for &(ref lib, kind) in used_libraries.get().iter() { match kind { cstore::NativeStatic => {} // these libraries are not propagated cstore::NativeFramework | cstore::NativeUnknown => { @@ -1610,17 +1684,18 @@ fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) { ebml_w.end_tag(); } -struct ImplVisitor<'a> { +struct ImplVisitor<'a,'b> { ecx: &'a EncodeContext<'a>, - ebml_w: &'a mut writer::Encoder, + ebml_w: &'a mut writer::Encoder<'b>, } -impl<'a> Visitor<()> for ImplVisitor<'a> { +impl<'a,'b> Visitor<()> for ImplVisitor<'a,'b> { fn visit_item(&mut self, item: @item, _: ()) { match item.node { item_impl(_, Some(ref trait_ref), _, _) => { let def_map = self.ecx.tcx.def_map; - let trait_def = def_map.get_copy(&trait_ref.ref_id); + let def_map = def_map.borrow(); + let trait_def = def_map.get().get_copy(&trait_ref.ref_id); let def_id = ast_util::def_id_of_def(trait_def); // Load eagerly if this is an implementation of the Drop trait @@ -1721,27 +1796,25 @@ pub static metadata_encoding_version : &'static [u8] = 0, 0, 0, 1 ]; pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] { - let wr = @mut MemWriter::new(); + let mut wr = MemWriter::new(); let stats = Stats { - inline_bytes: 0, - attr_bytes: 0, - dep_bytes: 0, - lang_item_bytes: 0, - native_lib_bytes: 0, - impl_bytes: 0, - misc_bytes: 0, - item_bytes: 0, - index_bytes: 0, - zero_bytes: 0, - total_bytes: 0, - n_inlines: 0 + inline_bytes: Cell::new(0), + attr_bytes: Cell::new(0), + dep_bytes: Cell::new(0), + lang_item_bytes: Cell::new(0), + native_lib_bytes: Cell::new(0), + impl_bytes: Cell::new(0), + misc_bytes: Cell::new(0), + item_bytes: Cell::new(0), + index_bytes: Cell::new(0), + zero_bytes: Cell::new(0), + total_bytes: Cell::new(0), }; let EncodeParams { item_symbols, diag, tcx, reexports2, - discrim_symbols, cstore, encode_inlined_item, link_meta, @@ -1749,15 +1822,14 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] { non_inlineable_statics, .. } = parms; - let type_abbrevs = @mut HashMap::new(); - let stats = @mut stats; + let type_abbrevs = @RefCell::new(HashMap::new()); + let stats = @stats; let ecx = EncodeContext { diag: diag, tcx: tcx, stats: stats, reexports2: reexports2, item_symbols: item_symbols, - discrim_symbols: discrim_symbols, non_inlineable_statics: non_inlineable_statics, link_meta: link_meta, cstore: cstore, @@ -1766,81 +1838,81 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] { reachable: reachable, }; - let mut ebml_w = writer::Encoder(wr); + let mut ebml_w = writer::Encoder(&mut wr); encode_hash(&mut ebml_w, ecx.link_meta.crate_hash); - let mut i = wr.tell(); + let mut i = ebml_w.writer.tell(); let crate_attrs = synthesize_crate_attrs(&ecx, crate); encode_attributes(&mut ebml_w, crate_attrs); - ecx.stats.attr_bytes = wr.tell() - i; + ecx.stats.attr_bytes.set(ebml_w.writer.tell() - i); - i = wr.tell(); + i = ebml_w.writer.tell(); encode_crate_deps(&ecx, &mut ebml_w, ecx.cstore); - ecx.stats.dep_bytes = wr.tell() - i; + ecx.stats.dep_bytes.set(ebml_w.writer.tell() - i); // Encode the language items. - i = wr.tell(); + i = ebml_w.writer.tell(); encode_lang_items(&ecx, &mut ebml_w); - ecx.stats.lang_item_bytes = wr.tell() - i; + ecx.stats.lang_item_bytes.set(ebml_w.writer.tell() - i); // Encode the native libraries used - i = wr.tell(); + i = ebml_w.writer.tell(); encode_native_libraries(&ecx, &mut ebml_w); - ecx.stats.native_lib_bytes = wr.tell() - i; + ecx.stats.native_lib_bytes.set(ebml_w.writer.tell() - i); // Encode the def IDs of impls, for coherence checking. - i = wr.tell(); + i = ebml_w.writer.tell(); encode_impls(&ecx, crate, &mut ebml_w); - ecx.stats.impl_bytes = wr.tell() - i; + ecx.stats.impl_bytes.set(ebml_w.writer.tell() - i); // Encode miscellaneous info. - i = wr.tell(); + i = ebml_w.writer.tell(); encode_misc_info(&ecx, crate, &mut ebml_w); - ecx.stats.misc_bytes = wr.tell() - i; + ecx.stats.misc_bytes.set(ebml_w.writer.tell() - i); // Encode and index the items. ebml_w.start_tag(tag_items); - i = wr.tell(); + i = ebml_w.writer.tell(); let items_index = encode_info_for_items(&ecx, &mut ebml_w, crate); - ecx.stats.item_bytes = wr.tell() - i; + ecx.stats.item_bytes.set(ebml_w.writer.tell() - i); - i = wr.tell(); + i = ebml_w.writer.tell(); let items_buckets = create_index(items_index); encode_index(&mut ebml_w, items_buckets, write_i64); - ecx.stats.index_bytes = wr.tell() - i; + ecx.stats.index_bytes.set(ebml_w.writer.tell() - i); ebml_w.end_tag(); - ecx.stats.total_bytes = wr.tell(); + ecx.stats.total_bytes.set(ebml_w.writer.tell()); if (tcx.sess.meta_stats()) { - for e in wr.inner_ref().iter() { + for e in ebml_w.writer.inner_ref().iter() { if *e == 0 { - ecx.stats.zero_bytes += 1; + ecx.stats.zero_bytes.set(ecx.stats.zero_bytes.get() + 1); } } println("metadata stats:"); - println!(" inline bytes: {}", ecx.stats.inline_bytes); - println!(" attribute bytes: {}", ecx.stats.attr_bytes); - println!(" dep bytes: {}", ecx.stats.dep_bytes); - println!(" lang item bytes: {}", ecx.stats.lang_item_bytes); - println!(" native bytes: {}", ecx.stats.native_lib_bytes); - println!(" impl bytes: {}", ecx.stats.impl_bytes); - println!(" misc bytes: {}", ecx.stats.misc_bytes); - println!(" item bytes: {}", ecx.stats.item_bytes); - println!(" index bytes: {}", ecx.stats.index_bytes); - println!(" zero bytes: {}", ecx.stats.zero_bytes); - println!(" total bytes: {}", ecx.stats.total_bytes); + println!(" inline bytes: {}", ecx.stats.inline_bytes.get()); + println!(" attribute bytes: {}", ecx.stats.attr_bytes.get()); + println!(" dep bytes: {}", ecx.stats.dep_bytes.get()); + println!(" lang item bytes: {}", ecx.stats.lang_item_bytes.get()); + println!(" native bytes: {}", ecx.stats.native_lib_bytes.get()); + println!(" impl bytes: {}", ecx.stats.impl_bytes.get()); + println!(" misc bytes: {}", ecx.stats.misc_bytes.get()); + println!(" item bytes: {}", ecx.stats.item_bytes.get()); + println!(" index bytes: {}", ecx.stats.index_bytes.get()); + println!(" zero bytes: {}", ecx.stats.zero_bytes.get()); + println!(" total bytes: {}", ecx.stats.total_bytes.get()); } // Pad this, since something (LLVM, presumably) is cutting off the // remaining % 4 bytes. - wr.write(&[0u8, 0u8, 0u8, 0u8]); + ebml_w.writer.write(&[0u8, 0u8, 0u8, 0u8]); // This is a horrible thing to do to the outer MemWriter, but thankfully we // don't use it again so... it's ok right? - return util::replace(wr.inner_mut_ref(), ~[]); + return util::replace(ebml_w.writer.inner_mut_ref(), ~[]); } // Get the encoded string for a type @@ -1850,7 +1922,7 @@ pub fn encoded_ty(tcx: ty::ctxt, t: ty::t) -> ~str { ds: def_to_str, tcx: tcx, abbrevs: tyencode::ac_no_abbrevs}; - let wr = @mut MemWriter::new(); - tyencode::enc_ty(wr, cx, t); + let mut wr = MemWriter::new(); + tyencode::enc_ty(&mut wr, cx, t); str::from_utf8_owned(wr.inner_ref().to_owned()) } diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index 66d42cf44298f..692cc12ec6f5d 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use std::cell::RefCell; use std::option; use std::os; use std::io; @@ -42,11 +42,11 @@ pub trait FileSearch { pub fn mk_filesearch(maybe_sysroot: &Option<@Path>, target_triple: &str, - addl_lib_search_paths: @mut HashSet) + addl_lib_search_paths: @RefCell>) -> @FileSearch { struct FileSearchImpl { sysroot: @Path, - addl_lib_search_paths: @mut HashSet, + addl_lib_search_paths: @RefCell>, target_triple: ~str } impl FileSearch for FileSearchImpl { @@ -56,9 +56,10 @@ pub fn mk_filesearch(maybe_sysroot: &Option<@Path>, let mut visited_dirs = HashSet::new(); let mut found = false; + let addl_lib_search_paths = self.addl_lib_search_paths.borrow(); debug!("filesearch: searching additional lib search paths [{:?}]", - self.addl_lib_search_paths.len()); - for path in self.addl_lib_search_paths.iter() { + addl_lib_search_paths.get().len()); + for path in addl_lib_search_paths.get().iter() { match f(path) { FileMatches => found = true, FileDoesntMatch => () diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index d670fc532b5f9..e954fc06c9435 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -380,7 +380,7 @@ pub fn read_meta_section_name(os: Os) -> &'static str { pub fn list_file_metadata(intr: @ident_interner, os: Os, path: &Path, - out: @mut io::Writer) { + out: &mut io::Writer) { match get_metadata_section(os, path) { option::Some(bytes) => decoder::list_crate_metadata(intr, bytes.as_slice(), diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 9f91fa6ed8fb0..2e989f48b8002 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -380,15 +380,21 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t { let key = ty::creader_cache_key {cnum: st.crate, pos: pos, len: len }; - match st.tcx.rcache.find(&key) { - Some(&tt) => return tt, + + let tt_opt = { + let rcache = st.tcx.rcache.borrow(); + rcache.get().find_copy(&key) + }; + match tt_opt { + Some(tt) => return tt, None => { let mut ps = PState { pos: pos, .. *st }; let tt = parse_ty(&mut ps, |x,y| conv(x,y)); - st.tcx.rcache.insert(key, tt); + let mut rcache = st.tcx.rcache.borrow_mut(); + rcache.get().insert(key, tt); return tt; } } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 6896b951c7778..06d74055af40c 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -10,6 +10,7 @@ // Type encoding +use std::cell::RefCell; use std::hashmap::HashMap; use std::io; use std::io::{Decorator, Writer, Seek}; @@ -50,32 +51,45 @@ pub struct ty_abbrev { pub enum abbrev_ctxt { ac_no_abbrevs, - ac_use_abbrevs(@mut HashMap), + ac_use_abbrevs(@RefCell>), } -fn mywrite(w: @mut MemWriter, fmt: &fmt::Arguments) { +fn mywrite(w: &mut MemWriter, fmt: &fmt::Arguments) { fmt::write(&mut *w as &mut io::Writer, fmt); } -pub fn enc_ty(w: @mut MemWriter, cx: @ctxt, t: ty::t) { +pub fn enc_ty(w: &mut MemWriter, cx: @ctxt, t: ty::t) { match cx.abbrevs { ac_no_abbrevs => { - let result_str = match cx.tcx.short_names_cache.find(&t) { - Some(&s) => s, + let result_str_opt; + { + let short_names_cache = cx.tcx.short_names_cache.borrow(); + result_str_opt = short_names_cache.get() + .find(&t) + .map(|result| *result); + } + let result_str = match result_str_opt { + Some(s) => s, None => { - let wr = @mut MemWriter::new(); + let wr = &mut MemWriter::new(); enc_sty(wr, cx, &ty::get(t).sty); let s = str::from_utf8(*wr.inner_ref()).to_managed(); - cx.tcx.short_names_cache.insert(t, s); + let mut short_names_cache = cx.tcx + .short_names_cache + .borrow_mut(); + short_names_cache.get().insert(t, s); s - } - }; - w.write(result_str.as_bytes()); + } + }; + w.write(result_str.as_bytes()); } ac_use_abbrevs(abbrevs) => { - match abbrevs.find(&t) { - Some(a) => { w.write(a.s.as_bytes()); return; } - None => {} + { + let mut abbrevs = abbrevs.borrow_mut(); + match abbrevs.get().find(&t) { + Some(a) => { w.write(a.s.as_bytes()); return; } + None => {} + } } let pos = w.tell(); enc_sty(w, cx, &ty::get(t).sty); @@ -94,44 +108,47 @@ pub fn enc_ty(w: @mut MemWriter, cx: @ctxt, t: ty::t) { let a = ty_abbrev { pos: pos as uint, len: len as uint, s: s }; - abbrevs.insert(t, a); + { + let mut abbrevs = abbrevs.borrow_mut(); + abbrevs.get().insert(t, a); + } } return; } } } -fn enc_mutability(w: @mut MemWriter, mt: ast::Mutability) { +fn enc_mutability(w: &mut MemWriter, mt: ast::Mutability) { match mt { MutImmutable => (), MutMutable => mywrite!(w, "m"), } } -fn enc_mt(w: @mut MemWriter, cx: @ctxt, mt: ty::mt) { +fn enc_mt(w: &mut MemWriter, cx: @ctxt, mt: ty::mt) { enc_mutability(w, mt.mutbl); enc_ty(w, cx, mt.ty); } -fn enc_opt(w: @mut MemWriter, t: Option, enc_f: |T|) { +fn enc_opt(w: &mut MemWriter, t: Option, enc_f: |&mut MemWriter, T|) { match t { None => mywrite!(w, "n"), Some(v) => { mywrite!(w, "s"); - enc_f(v); + enc_f(w, v); } } } -fn enc_substs(w: @mut MemWriter, cx: @ctxt, substs: &ty::substs) { +fn enc_substs(w: &mut MemWriter, cx: @ctxt, substs: &ty::substs) { enc_region_substs(w, cx, &substs.regions); - enc_opt(w, substs.self_ty, |t| enc_ty(w, cx, t)); + enc_opt(w, substs.self_ty, |w, t| enc_ty(w, cx, t)); mywrite!(w, "["); for t in substs.tps.iter() { enc_ty(w, cx, *t); } mywrite!(w, "]"); } -fn enc_region_substs(w: @mut MemWriter, cx: @ctxt, substs: &ty::RegionSubsts) { +fn enc_region_substs(w: &mut MemWriter, cx: @ctxt, substs: &ty::RegionSubsts) { match *substs { ty::ErasedRegions => { mywrite!(w, "e"); @@ -146,7 +163,7 @@ fn enc_region_substs(w: @mut MemWriter, cx: @ctxt, substs: &ty::RegionSubsts) { } } -fn enc_region(w: @mut MemWriter, cx: @ctxt, r: ty::Region) { +fn enc_region(w: &mut MemWriter, cx: @ctxt, r: ty::Region) { match r { ty::ReLateBound(id, br) => { mywrite!(w, "b[{}|", id); @@ -180,7 +197,7 @@ fn enc_region(w: @mut MemWriter, cx: @ctxt, r: ty::Region) { } } -fn enc_bound_region(w: @mut MemWriter, cx: @ctxt, br: ty::BoundRegion) { +fn enc_bound_region(w: &mut MemWriter, cx: @ctxt, br: ty::BoundRegion) { match br { ty::BrAnon(idx) => { mywrite!(w, "a{}|", idx); @@ -196,7 +213,7 @@ fn enc_bound_region(w: @mut MemWriter, cx: @ctxt, br: ty::BoundRegion) { } } -pub fn enc_vstore(w: @mut MemWriter, cx: @ctxt, v: ty::vstore) { +pub fn enc_vstore(w: &mut MemWriter, cx: @ctxt, v: ty::vstore) { mywrite!(w, "/"); match v { ty::vstore_fixed(u) => mywrite!(w, "{}|", u), @@ -209,12 +226,12 @@ pub fn enc_vstore(w: @mut MemWriter, cx: @ctxt, v: ty::vstore) { } } -pub fn enc_trait_ref(w: @mut MemWriter, cx: @ctxt, s: &ty::TraitRef) { +pub fn enc_trait_ref(w: &mut MemWriter, cx: @ctxt, s: &ty::TraitRef) { mywrite!(w, "{}|", (cx.ds)(s.def_id)); enc_substs(w, cx, &s.substs); } -pub fn enc_trait_store(w: @mut MemWriter, cx: @ctxt, s: ty::TraitStore) { +pub fn enc_trait_store(w: &mut MemWriter, cx: @ctxt, s: ty::TraitStore) { match s { ty::UniqTraitStore => mywrite!(w, "~"), ty::BoxTraitStore => mywrite!(w, "@"), @@ -225,7 +242,7 @@ pub fn enc_trait_store(w: @mut MemWriter, cx: @ctxt, s: ty::TraitStore) { } } -fn enc_sty(w: @mut MemWriter, cx: @ctxt, st: &ty::sty) { +fn enc_sty(w: &mut MemWriter, cx: @ctxt, st: &ty::sty) { match *st { ty::ty_nil => mywrite!(w, "n"), ty::ty_bot => mywrite!(w, "z"), @@ -325,7 +342,7 @@ fn enc_sty(w: @mut MemWriter, cx: @ctxt, st: &ty::sty) { } } -fn enc_sigil(w: @mut MemWriter, sigil: Sigil) { +fn enc_sigil(w: &mut MemWriter, sigil: Sigil) { match sigil { ManagedSigil => mywrite!(w, "@"), OwnedSigil => mywrite!(w, "~"), @@ -333,7 +350,7 @@ fn enc_sigil(w: @mut MemWriter, sigil: Sigil) { } } -fn enc_purity(w: @mut MemWriter, p: purity) { +fn enc_purity(w: &mut MemWriter, p: purity) { match p { impure_fn => mywrite!(w, "i"), unsafe_fn => mywrite!(w, "u"), @@ -341,7 +358,7 @@ fn enc_purity(w: @mut MemWriter, p: purity) { } } -fn enc_abi_set(w: @mut MemWriter, abis: AbiSet) { +fn enc_abi_set(w: &mut MemWriter, abis: AbiSet) { mywrite!(w, "["); abis.each(|abi| { mywrite!(w, "{},", abi.name()); @@ -350,20 +367,20 @@ fn enc_abi_set(w: @mut MemWriter, abis: AbiSet) { mywrite!(w, "]") } -fn enc_onceness(w: @mut MemWriter, o: Onceness) { +fn enc_onceness(w: &mut MemWriter, o: Onceness) { match o { Once => mywrite!(w, "o"), Many => mywrite!(w, "m") } } -pub fn enc_bare_fn_ty(w: @mut MemWriter, cx: @ctxt, ft: &ty::BareFnTy) { +pub fn enc_bare_fn_ty(w: &mut MemWriter, cx: @ctxt, ft: &ty::BareFnTy) { enc_purity(w, ft.purity); enc_abi_set(w, ft.abis); enc_fn_sig(w, cx, &ft.sig); } -fn enc_closure_ty(w: @mut MemWriter, cx: @ctxt, ft: &ty::ClosureTy) { +fn enc_closure_ty(w: &mut MemWriter, cx: @ctxt, ft: &ty::ClosureTy) { enc_sigil(w, ft.sigil); enc_purity(w, ft.purity); enc_onceness(w, ft.onceness); @@ -374,7 +391,7 @@ fn enc_closure_ty(w: @mut MemWriter, cx: @ctxt, ft: &ty::ClosureTy) { enc_fn_sig(w, cx, &ft.sig); } -fn enc_fn_sig(w: @mut MemWriter, cx: @ctxt, fsig: &ty::FnSig) { +fn enc_fn_sig(w: &mut MemWriter, cx: @ctxt, fsig: &ty::FnSig) { mywrite!(w, "[{}|", fsig.binder_id); for ty in fsig.inputs.iter() { enc_ty(w, cx, *ty); @@ -388,7 +405,7 @@ fn enc_fn_sig(w: @mut MemWriter, cx: @ctxt, fsig: &ty::FnSig) { enc_ty(w, cx, fsig.output); } -fn enc_bounds(w: @mut MemWriter, cx: @ctxt, bs: &ty::ParamBounds) { +fn enc_bounds(w: &mut MemWriter, cx: @ctxt, bs: &ty::ParamBounds) { for bound in bs.builtin_bounds.iter() { match bound { ty::BoundSend => mywrite!(w, "S"), @@ -407,7 +424,7 @@ fn enc_bounds(w: @mut MemWriter, cx: @ctxt, bs: &ty::ParamBounds) { mywrite!(w, "."); } -pub fn enc_type_param_def(w: @mut MemWriter, cx: @ctxt, v: &ty::TypeParameterDef) { +pub fn enc_type_param_def(w: &mut MemWriter, cx: @ctxt, v: &ty::TypeParameterDef) { mywrite!(w, "{}:{}|", cx.tcx.sess.str_of(v.ident), (cx.ds)(v.def_id)); enc_bounds(w, cx, v.bounds); } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 93302739178bd..38f23a900d890 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -788,7 +788,7 @@ trait ebml_writer_helpers { tpbt: ty::ty_param_bounds_and_ty); } -impl ebml_writer_helpers for writer::Encoder { +impl<'a> ebml_writer_helpers for writer::Encoder<'a> { fn emit_ty(&mut self, ecx: &e::EncodeContext, ty: ty::t) { self.emit_opaque(|this| e::write_type(ecx, this, ty)) } @@ -840,8 +840,10 @@ trait write_tag_and_id { fn id(&mut self, id: ast::NodeId); } -impl write_tag_and_id for writer::Encoder { - fn tag(&mut self, tag_id: c::astencode_tag, f: |&mut writer::Encoder|) { +impl<'a> write_tag_and_id for writer::Encoder<'a> { + fn tag(&mut self, + tag_id: c::astencode_tag, + f: |&mut writer::Encoder<'a>|) { self.start_tag(tag_id as uint); f(self); self.end_tag(); @@ -852,18 +854,23 @@ impl write_tag_and_id for writer::Encoder { } } -struct SideTableEncodingIdVisitor { +struct SideTableEncodingIdVisitor<'a,'b> { ecx_ptr: *libc::c_void, - new_ebml_w: writer::Encoder, + new_ebml_w: &'a mut writer::Encoder<'b>, maps: Maps, } -impl ast_util::IdVisitingOperation for SideTableEncodingIdVisitor { +impl<'a,'b> ast_util::IdVisitingOperation for + SideTableEncodingIdVisitor<'a,'b> { fn visit_id(&self, id: ast::NodeId) { // Note: this will cause a copy of ebml_w, which is bad as // it is mutable. But I believe it's harmless since we generate // balanced EBML. - let mut new_ebml_w = self.new_ebml_w.clone(); + // + // XXX(pcwalton): Don't copy this way. + let mut new_ebml_w = unsafe { + self.new_ebml_w.unsafe_clone() + }; // See above let ecx: &e::EncodeContext = unsafe { cast::transmute(self.ecx_ptr) @@ -877,7 +884,9 @@ fn encode_side_tables_for_ii(ecx: &e::EncodeContext, ebml_w: &mut writer::Encoder, ii: &ast::inlined_item) { ebml_w.start_tag(c::tag_table as uint); - let new_ebml_w = (*ebml_w).clone(); + let mut new_ebml_w = unsafe { + ebml_w.unsafe_clone() + }; // Because the ast visitor uses @IdVisitingOperation, I can't pass in // ecx directly, but /I/ know that it'll be fine since the lifetime is @@ -886,7 +895,7 @@ fn encode_side_tables_for_ii(ecx: &e::EncodeContext, ecx_ptr: unsafe { cast::transmute(ecx) }, - new_ebml_w: new_ebml_w, + new_ebml_w: &mut new_ebml_w, maps: maps, }); ebml_w.end_tag(); @@ -901,7 +910,8 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, debug!("Encoding side tables for id {}", id); { - let r = tcx.def_map.find(&id); + let def_map = tcx.def_map.borrow(); + let r = def_map.get().find(&id); for def in r.iter() { ebml_w.tag(c::tag_table_def, |ebml_w| { ebml_w.id(id); @@ -911,7 +921,8 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, } { - let r = tcx.node_types.find(&(id as uint)); + let node_types = tcx.node_types.borrow(); + let r = node_types.get().find(&(id as uint)); for &ty in r.iter() { ebml_w.tag(c::tag_table_node_type, |ebml_w| { ebml_w.id(id); @@ -923,7 +934,8 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, } { - let r = tcx.node_type_substs.find(&id); + let node_type_substs = tcx.node_type_substs.borrow(); + let r = node_type_substs.get().find(&id); for tys in r.iter() { ebml_w.tag(c::tag_table_node_type_subst, |ebml_w| { ebml_w.id(id); @@ -935,7 +947,8 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, } { - let r = tcx.freevars.find(&id); + let freevars = tcx.freevars.borrow(); + let r = freevars.get().find(&id); for &fv in r.iter() { ebml_w.tag(c::tag_table_freevars, |ebml_w| { ebml_w.id(id); @@ -950,7 +963,8 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, let lid = ast::DefId { crate: ast::LOCAL_CRATE, node: id }; { - let r = tcx.tcache.find(&lid); + let tcache = tcx.tcache.borrow(); + let r = tcache.get().find(&lid); for &tpbt in r.iter() { ebml_w.tag(c::tag_table_tcache, |ebml_w| { ebml_w.id(id); @@ -962,8 +976,11 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, } { - let r = tcx.ty_param_defs.find(&id); - for &type_param_def in r.iter() { + let r = { + let ty_param_defs = tcx.ty_param_defs.borrow(); + ty_param_defs.get().find(&id).map(|def| *def) + }; + for type_param_def in r.iter() { ebml_w.tag(c::tag_table_param_defs, |ebml_w| { ebml_w.id(id); ebml_w.tag(c::tag_table_val, |ebml_w| { @@ -974,7 +991,8 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, } { - let r = maps.method_map.find(&id); + let method_map = maps.method_map.borrow(); + let r = method_map.get().find(&id); for &mme in r.iter() { ebml_w.tag(c::tag_table_method_map, |ebml_w| { ebml_w.id(id); @@ -986,7 +1004,8 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, } { - let r = maps.vtable_map.find(&id); + let vtable_map = maps.vtable_map.borrow(); + let r = vtable_map.get().find(&id); for &dr in r.iter() { ebml_w.tag(c::tag_table_vtable_map, |ebml_w| { ebml_w.id(id); @@ -998,7 +1017,8 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, } { - let r = tcx.adjustments.find(&id); + let adjustments = tcx.adjustments.borrow(); + let r = adjustments.get().find(&id); for adj in r.iter() { ebml_w.tag(c::tag_table_adjustments, |ebml_w| { ebml_w.id(id); @@ -1010,7 +1030,8 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, } { - let r = maps.capture_map.find(&id); + let capture_map = maps.capture_map.borrow(); + let r = capture_map.get().find(&id); for &cap_vars in r.iter() { ebml_w.tag(c::tag_table_capture_map, |ebml_w| { ebml_w.id(id); @@ -1218,54 +1239,72 @@ fn decode_side_tables(xcx: @ExtendedDecodeContext, match value { c::tag_table_def => { let def = decode_def(xcx, val_doc); - dcx.tcx.def_map.insert(id, def); + let mut def_map = dcx.tcx.def_map.borrow_mut(); + def_map.get().insert(id, def); } c::tag_table_node_type => { let ty = val_dsr.read_ty(xcx); debug!("inserting ty for node {:?}: {}", id, ty_to_str(dcx.tcx, ty)); - dcx.tcx.node_types.insert(id as uint, ty); + let mut node_types = dcx.tcx.node_types.borrow_mut(); + node_types.get().insert(id as uint, ty); } c::tag_table_node_type_subst => { let tys = val_dsr.read_tys(xcx); - dcx.tcx.node_type_substs.insert(id, tys); + let mut node_type_substs = dcx.tcx + .node_type_substs + .borrow_mut(); + node_type_substs.get().insert(id, tys); } c::tag_table_freevars => { let fv_info = @val_dsr.read_to_vec(|val_dsr| { @val_dsr.read_freevar_entry(xcx) }); - dcx.tcx.freevars.insert(id, fv_info); + let mut freevars = dcx.tcx.freevars.borrow_mut(); + freevars.get().insert(id, fv_info); } c::tag_table_tcache => { let tpbt = val_dsr.read_ty_param_bounds_and_ty(xcx); let lid = ast::DefId { crate: ast::LOCAL_CRATE, node: id }; - dcx.tcx.tcache.insert(lid, tpbt); + let mut tcache = dcx.tcx.tcache.borrow_mut(); + tcache.get().insert(lid, tpbt); } c::tag_table_param_defs => { let bounds = val_dsr.read_type_param_def(xcx); - dcx.tcx.ty_param_defs.insert(id, bounds); + let mut ty_param_defs = dcx.tcx + .ty_param_defs + .borrow_mut(); + ty_param_defs.get().insert(id, bounds); } c::tag_table_method_map => { - dcx.maps.method_map.insert( - id, - val_dsr.read_method_map_entry(xcx)); + let entry = val_dsr.read_method_map_entry(xcx); + let mut method_map = dcx.maps.method_map.borrow_mut(); + method_map.get().insert(id, entry); } c::tag_table_vtable_map => { - dcx.maps.vtable_map.insert( - id, - val_dsr.read_vtable_res(xcx.dcx.tcx, xcx.dcx.cdata)); + let vtable_res = + val_dsr.read_vtable_res(xcx.dcx.tcx, + xcx.dcx.cdata); + let mut vtable_map = dcx.maps.vtable_map.borrow_mut(); + vtable_map.get().insert(id, vtable_res); } c::tag_table_adjustments => { let adj: @ty::AutoAdjustment = @Decodable::decode(val_dsr); adj.tr(xcx); - dcx.tcx.adjustments.insert(id, adj); + let mut adjustments = dcx.tcx + .adjustments + .borrow_mut(); + adjustments.get().insert(id, adj); } c::tag_table_capture_map => { let cvars = at_vec::to_managed_move( val_dsr.read_to_vec( |val_dsr| val_dsr.read_capture_var(xcx))); - dcx.maps.capture_map.insert(id, cvars); + let mut capture_map = dcx.maps + .capture_map + .borrow_mut(); + capture_map.get().insert(id, cvars); } _ => { xcx.dcx.tcx.sess.bug( @@ -1335,9 +1374,11 @@ fn roundtrip(in_item: Option<@ast::item>) { use std::io::mem::MemWriter; let in_item = in_item.unwrap(); - let wr = @mut MemWriter::new(); - let mut ebml_w = writer::Encoder(wr); - encode_item_ast(&mut ebml_w, in_item); + let mut wr = MemWriter::new(); + { + let mut ebml_w = writer::Encoder(&mut wr); + encode_item_ast(&mut ebml_w, in_item); + } let ebml_doc = reader::Doc(wr.inner_ref().as_slice()); let out_item = decode_item_ast(ebml_doc); diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 13c45cc8e36d2..6176f5601c14b 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -18,7 +18,6 @@ // 4. moves do not affect things loaned out in any way -use std::hashmap::HashSet; use mc = middle::mem_categorization; use middle::borrowck::*; use middle::moves; @@ -37,7 +36,6 @@ struct CheckLoanCtxt<'a> { dfcx_loans: &'a LoanDataFlow, move_data: @move_data::FlowedMoveData, all_loans: &'a [Loan], - reported: @mut HashSet, } impl<'a> Visitor<()> for CheckLoanCtxt<'a> { @@ -75,7 +73,6 @@ pub fn check_loans(bccx: &BorrowckCtxt, dfcx_loans: dfcx_loans, move_data: @move_data, all_loans: all_loans, - reported: @mut HashSet::new(), }; clcx.visit_block(body, ()); @@ -296,9 +293,13 @@ impl<'a> CheckLoanCtxt<'a> { pub fn check_assignment(&self, expr: @ast::Expr) { // We don't use cat_expr() here because we don't want to treat // auto-ref'd parameters in overloaded operators as rvalues. - let cmt = match self.bccx.tcx.adjustments.find(&expr.id) { + let adj = { + let adjustments = self.bccx.tcx.adjustments.borrow(); + adjustments.get().find_copy(&expr.id) + }; + let cmt = match adj { None => self.bccx.cat_expr_unadjusted(expr), - Some(&adj) => self.bccx.cat_expr_autoderefd(expr, adj) + Some(adj) => self.bccx.cat_expr_autoderefd(expr, adj) }; debug!("check_assignment(cmt={})", cmt.repr(self.tcx())); @@ -356,7 +357,10 @@ impl<'a> CheckLoanCtxt<'a> { mc::cat_local(id) | mc::cat_arg(id) | mc::cat_self(id) => { - this.tcx().used_mut_nodes.insert(id); + let mut used_mut_nodes = this.tcx() + .used_mut_nodes + .borrow_mut(); + used_mut_nodes.get().insert(id); return; } @@ -415,7 +419,10 @@ impl<'a> CheckLoanCtxt<'a> { derefs: deref_count }; debug!("Inserting write guard at {:?}", key); - this.bccx.write_guard_map.insert(key); + let mut write_guard_map = this.bccx + .write_guard_map + .borrow_mut(); + write_guard_map.get().insert(key); } _ => {} @@ -709,7 +716,8 @@ fn check_loans_in_fn<'a>(this: &mut CheckLoanCtxt<'a>, fn check_captured_variables(this: &CheckLoanCtxt, closure_id: ast::NodeId, span: Span) { - let cap_vars = this.bccx.capture_map.get(&closure_id); + let capture_map = this.bccx.capture_map.borrow(); + let cap_vars = capture_map.get().get(&closure_id); for cap_var in cap_vars.iter() { let var_id = ast_util::def_id_of_def(cap_var.def).node; let var_path = @LpVar(var_id); @@ -762,6 +770,7 @@ fn check_loans_in_expr<'a>(this: &mut CheckLoanCtxt<'a>, this.check_for_conflicting_loans(expr.id); this.check_move_out_from_expr(expr); + let method_map = this.bccx.method_map.borrow(); match expr.node { ast::ExprSelf | ast::ExprPath(..) => { @@ -786,7 +795,7 @@ fn check_loans_in_expr<'a>(this: &mut CheckLoanCtxt<'a>, } ast::ExprIndex(callee_id, _, rval) | ast::ExprBinary(callee_id, _, _, rval) - if this.bccx.method_map.contains_key(&expr.id) => { + if method_map.get().contains_key(&expr.id) => { this.check_call(expr, None, callee_id, @@ -794,7 +803,7 @@ fn check_loans_in_expr<'a>(this: &mut CheckLoanCtxt<'a>, [rval]); } ast::ExprUnary(callee_id, _, _) | ast::ExprIndex(callee_id, _, _) - if this.bccx.method_map.contains_key(&expr.id) => { + if method_map.get().contains_key(&expr.id) => { this.check_call(expr, None, callee_id, diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs index 2b8c500b637c8..907a8e8fdd975 100644 --- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs @@ -23,7 +23,7 @@ use syntax::codemap::Span; use util::ppaux::{UserString}; pub fn gather_decl(bccx: &BorrowckCtxt, - move_data: &mut MoveData, + move_data: &MoveData, decl_id: ast::NodeId, _decl_span: Span, var_id: ast::NodeId) { @@ -32,7 +32,7 @@ pub fn gather_decl(bccx: &BorrowckCtxt, } pub fn gather_move_from_expr(bccx: &BorrowckCtxt, - move_data: &mut MoveData, + move_data: &MoveData, move_expr: @ast::Expr, cmt: mc::cmt) { gather_move_from_expr_or_pat(bccx, move_data, move_expr.id, @@ -40,7 +40,7 @@ pub fn gather_move_from_expr(bccx: &BorrowckCtxt, } pub fn gather_move_from_pat(bccx: &BorrowckCtxt, - move_data: &mut MoveData, + move_data: &MoveData, move_pat: @ast::Pat, cmt: mc::cmt) { gather_move_from_expr_or_pat(bccx, move_data, move_pat.id, @@ -48,7 +48,7 @@ pub fn gather_move_from_pat(bccx: &BorrowckCtxt, } fn gather_move_from_expr_or_pat(bccx: &BorrowckCtxt, - move_data: &mut MoveData, + move_data: &MoveData, move_id: ast::NodeId, move_kind: MoveKind, cmt: mc::cmt) { @@ -67,9 +67,10 @@ fn gather_move_from_expr_or_pat(bccx: &BorrowckCtxt, } pub fn gather_captures(bccx: &BorrowckCtxt, - move_data: &mut MoveData, + move_data: &MoveData, closure_expr: @ast::Expr) { - let captured_vars = bccx.capture_map.get(&closure_expr.id); + let capture_map = bccx.capture_map.borrow(); + let captured_vars = capture_map.get().get(&closure_expr.id); for captured_var in captured_vars.iter() { match captured_var.mode { moves::CapMove => { @@ -84,7 +85,7 @@ pub fn gather_captures(bccx: &BorrowckCtxt, } pub fn gather_assignment(bccx: &BorrowckCtxt, - move_data: &mut MoveData, + move_data: &MoveData, assignment_id: ast::NodeId, assignment_span: Span, assignee_loan_path: @LoanPath, diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs index 8c6384c029677..38598e8b78fc9 100644 --- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs +++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs @@ -279,7 +279,9 @@ impl<'a> GuaranteeLifetimeContext<'a> { // Add a record of what is required let rm_key = root_map_key {id: cmt_deref.id, derefs: derefs}; let root_info = RootInfo {scope: root_scope, freeze: opt_dyna}; - self.bccx.root_map.insert(rm_key, root_info); + + let mut root_map = self.bccx.root_map.borrow_mut(); + root_map.get().insert(rm_key, root_info); debug!("root_key: {:?} root_info: {:?}", rm_key, root_info); Ok(()) @@ -303,7 +305,10 @@ impl<'a> GuaranteeLifetimeContext<'a> { mc::cat_local(id) | mc::cat_self(id) | mc::cat_arg(id) => { - self.bccx.moved_variables_set.contains(&id) + let moved_variables_set = self.bccx + .moved_variables_set + .borrow(); + moved_variables_set.get().contains(&id) } mc::cat_rvalue(..) | mc::cat_static_item | diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index c07a7767c24a0..36e35760400d0 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -26,6 +26,7 @@ use middle::ty; use util::common::indenter; use util::ppaux::{Repr}; +use std::cell::RefCell; use syntax::ast; use syntax::ast_util::id_range; use syntax::codemap::Span; @@ -67,8 +68,8 @@ mod gather_moves; struct GatherLoanCtxt<'a> { bccx: &'a BorrowckCtxt, id_range: id_range, - move_data: @mut move_data::MoveData, - all_loans: @mut ~[Loan], + move_data: @move_data::MoveData, + all_loans: @RefCell<~[Loan]>, item_ub: ast::NodeId, repeating_ids: ~[ast::NodeId] } @@ -85,7 +86,7 @@ impl<'a> visit::Visitor<()> for GatherLoanCtxt<'a> { gather_loans_in_fn(self, fk, fd, b, s, n); } fn visit_stmt(&mut self, s:@Stmt, _:()) { - add_stmt_to_map(self, s); + visit::walk_stmt(self, s, ()); } fn visit_pat(&mut self, p:&Pat, _:()) { add_pat_to_id_range(self, p); @@ -103,14 +104,14 @@ impl<'a> visit::Visitor<()> for GatherLoanCtxt<'a> { pub fn gather_loans(bccx: &BorrowckCtxt, decl: &ast::fn_decl, body: ast::P) - -> (id_range, @mut ~[Loan], @mut move_data::MoveData) { + -> (id_range, @RefCell<~[Loan]>, @move_data::MoveData) { let mut glcx = GatherLoanCtxt { bccx: bccx, id_range: id_range::max(), - all_loans: @mut ~[], + all_loans: @RefCell::new(~[]), item_ub: body.id, repeating_ids: ~[body.id], - move_data: @mut MoveData::new() + move_data: @MoveData::new() }; glcx.gather_fn_arg_patterns(decl, body); @@ -208,7 +209,8 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt, // If this expression is borrowed, have to ensure it remains valid: { - let r = tcx.adjustments.find(&ex.id); + let adjustments = tcx.adjustments.borrow(); + let r = adjustments.get().find(&ex.id); for &adjustments in r.iter() { this.guarantee_adjustments(ex, *adjustments); } @@ -222,6 +224,7 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt, } // Special checks for various kinds of expressions: + let method_map = this.bccx.method_map.borrow(); match ex.node { ast::ExprAddrOf(mutbl, base) => { let base_cmt = this.bccx.cat_expr(base); @@ -269,7 +272,7 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt, ast::ExprIndex(_, _, arg) | ast::ExprBinary(_, _, _, arg) - if this.bccx.method_map.contains_key(&ex.id) => { + if method_map.get().contains_key(&ex.id) => { // Arguments in method calls are always passed by ref. // // Currently these do not use adjustments, so we have to @@ -509,9 +512,9 @@ impl<'a> GatherLoanCtxt<'a> { self.mark_loan_path_as_mutated(loan_path); } - let all_loans = &mut *self.all_loans; // FIXME(#5074) + let all_loans = self.all_loans.borrow(); Loan { - index: all_loans.len(), + index: all_loans.get().len(), loan_path: loan_path, cmt: cmt, mutbl: req_mutbl, @@ -529,7 +532,10 @@ impl<'a> GatherLoanCtxt<'a> { // let loan_path = loan.loan_path; // let loan_gen_scope = loan.gen_scope; // let loan_kill_scope = loan.kill_scope; - self.all_loans.push(loan); + { + let mut all_loans = self.all_loans.borrow_mut(); + all_loans.get().push(loan); + } // if loan_gen_scope != borrow_id { // FIXME(#6268) Nested method calls @@ -605,7 +611,10 @@ impl<'a> GatherLoanCtxt<'a> { match *loan_path { LpVar(local_id) => { - self.tcx().used_mut_nodes.insert(local_id); + let mut used_mut_nodes = self.tcx() + .used_mut_nodes + .borrow_mut(); + used_mut_nodes.get().insert(local_id); } LpExtend(base, mc::McInherited, _) => { self.mark_loan_path_as_mutated(base); @@ -823,15 +832,3 @@ impl<'a> GatherLoanCtxt<'a> { } } -// Setting up info that preserve needs. -// This is just the most convenient place to do it. -fn add_stmt_to_map(this: &mut GatherLoanCtxt, - stmt: @ast::Stmt) { - match stmt.node { - ast::StmtExpr(_, id) | ast::StmtSemi(_, id) => { - this.bccx.stmt_map.insert(id); - } - _ => () - } - visit::walk_stmt(this, stmt, ()); -} diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index bbe2efa3c5561..61e5d1f25fe7c 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -17,9 +17,9 @@ use middle::typeck; use middle::moves; use middle::dataflow::DataFlowContext; use middle::dataflow::DataFlowOperator; -use util::common::stmt_set; use util::ppaux::{note_and_explain_region, Repr, UserString}; +use std::cell::{Cell, RefCell}; use std::hashmap::{HashSet, HashMap}; use std::ops::{BitOr, BitAnd}; use std::result::{Result}; @@ -82,15 +82,12 @@ pub fn check_crate( moved_variables_set: moved_variables_set, capture_map: capture_map, root_map: root_map(), - loan_map: @mut HashMap::new(), - write_guard_map: @mut HashSet::new(), - stmt_map: @mut HashSet::new(), - stats: @mut BorrowStats { - loaned_paths_same: 0, - loaned_paths_imm: 0, - stable_paths: 0, - req_pure_paths: 0, - guaranteed_paths: 0, + write_guard_map: @RefCell::new(HashSet::new()), + stats: @BorrowStats { + loaned_paths_same: Cell::new(0), + loaned_paths_imm: Cell::new(0), + stable_paths: Cell::new(0), + guaranteed_paths: Cell::new(0), } }; let bccx = &mut bccx; @@ -100,22 +97,20 @@ pub fn check_crate( if tcx.sess.borrowck_stats() { println("--- borrowck stats ---"); println!("paths requiring guarantees: {}", - bccx.stats.guaranteed_paths); + bccx.stats.guaranteed_paths.get()); println!("paths requiring loans : {}", - make_stat(bccx, bccx.stats.loaned_paths_same)); + make_stat(bccx, bccx.stats.loaned_paths_same.get())); println!("paths requiring imm loans : {}", - make_stat(bccx, bccx.stats.loaned_paths_imm)); + make_stat(bccx, bccx.stats.loaned_paths_imm.get())); println!("stable paths : {}", - make_stat(bccx, bccx.stats.stable_paths)); - println!("paths requiring purity : {}", - make_stat(bccx, bccx.stats.req_pure_paths)); + make_stat(bccx, bccx.stats.stable_paths.get())); } return (bccx.root_map, bccx.write_guard_map); fn make_stat(bccx: &mut BorrowckCtxt, stat: uint) -> ~str { let stat_f = stat as f64; - let total = bccx.stats.guaranteed_paths as f64; + let total = bccx.stats.guaranteed_paths.get() as f64; format!("{} ({:.0f}%)", stat , stat_f * 100.0 / total) } } @@ -138,16 +133,18 @@ 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); - let mut loan_dfcx = - DataFlowContext::new(this.tcx, - this.method_map, - LoanDataFlowOperator, - id_range, - all_loans.len()); - for (loan_idx, loan) in all_loans.iter().enumerate() { + + let all_loans = all_loans.borrow(); + let mut loan_dfcx = DataFlowContext::new(this.tcx, + this.method_map, + LoanDataFlowOperator, + id_range, + all_loans.get().len()); + for (loan_idx, loan) in all_loans.get().iter().enumerate() { loan_dfcx.add_gen(loan.gen_scope, loan_idx); loan_dfcx.add_kill(loan.kill_scope, loan_idx); } + loan_dfcx.propagate(body); let flowed_moves = move_data::FlowedMoveData::new(move_data, @@ -157,7 +154,7 @@ fn borrowck_fn(this: &mut BorrowckCtxt, body); check_loans::check_loans(this, &loan_dfcx, flowed_moves, - *all_loans, body); + *all_loans.get(), body); } } @@ -174,24 +171,19 @@ pub struct BorrowckCtxt { moved_variables_set: moves::MovedVariablesSet, capture_map: moves::CaptureMap, root_map: root_map, - loan_map: LoanMap, write_guard_map: write_guard_map, - stmt_map: stmt_set, // Statistics: - stats: @mut BorrowStats + stats: @BorrowStats } pub struct BorrowStats { - loaned_paths_same: uint, - loaned_paths_imm: uint, - stable_paths: uint, - req_pure_paths: uint, - guaranteed_paths: uint + loaned_paths_same: Cell, + loaned_paths_imm: Cell, + stable_paths: Cell, + guaranteed_paths: Cell, } -pub type LoanMap = @mut HashMap; - // The keys to the root map combine the `id` of the deref expression // with the number of types that it is *autodereferenced*. So, for // example, imagine I have a variable `x: @@@T` and an expression @@ -223,7 +215,7 @@ pub struct root_map_key { // A set containing IDs of expressions of gc'd type that need to have a write // guard. -pub type write_guard_map = @mut HashSet; +pub type write_guard_map = @RefCell>; pub type BckResult = Result; @@ -413,10 +405,10 @@ pub struct RootInfo { freeze: Option // Some() if we should freeze box at runtime } -pub type root_map = @mut HashMap; +pub type root_map = @RefCell>; pub fn root_map() -> root_map { - return @mut HashMap::new(); + return @RefCell::new(HashMap::new()); } pub enum DynaFreezeKind { @@ -481,7 +473,8 @@ impl BorrowckCtxt { } pub fn is_move(&self, id: ast::NodeId) -> bool { - self.moves_map.contains(&id) + let moves_map = self.moves_map.borrow(); + moves_map.get().contains(&id) } pub fn cat_expr(&self, expr: @ast::Expr) -> mc::cmt { diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs index dc58423a42478..6d3bdc3fe4f1d 100644 --- a/src/librustc/middle/borrowck/move_data.rs +++ b/src/librustc/middle/borrowck/move_data.rs @@ -15,7 +15,7 @@ comments in the section "Moves and initialization" and in `doc.rs`. */ - +use std::cell::RefCell; use std::hashmap::{HashMap, HashSet}; use std::uint; use middle::borrowck::*; @@ -32,32 +32,33 @@ use util::ppaux::Repr; pub struct MoveData { /// Move paths. See section "Move paths" in `doc.rs`. - paths: ~[MovePath], + paths: RefCell<~[MovePath]>, /// Cache of loan path to move path index, for easy lookup. - path_map: HashMap<@LoanPath, MovePathIndex>, + path_map: RefCell>, /// Each move or uninitialized variable gets an entry here. - moves: ~[Move], + moves: RefCell<~[Move]>, /// Assignments to a variable, like `x = foo`. These are assigned /// bits for dataflow, since we must track them to ensure that /// immutable variables are assigned at most once along each path. - var_assignments: ~[Assignment], + var_assignments: RefCell<~[Assignment]>, /// Assignments to a path, like `x.f = foo`. These are not /// assigned dataflow bits, but we track them because they still /// kill move bits. - path_assignments: ~[Assignment], - assignee_ids: HashSet, + path_assignments: RefCell<~[Assignment]>, + assignee_ids: RefCell>, } pub struct FlowedMoveData { - move_data: @mut MoveData, - // ^~~~~~~~~~~~~ - // It makes me sad to use @mut here, except that due to - // the visitor design, this is what gather_loans - // must produce. + move_data: @MoveData, + // ^~~~~~~~~ + // It makes me sad to use @ here, except that due to + // the old visitor design, this is what gather_loans + // used to have to produce, and this code hasn't been + // updated. dfcx_moves: MoveDataFlow, @@ -165,36 +166,66 @@ pub type AssignDataFlow = DataFlowContext; impl MoveData { pub fn new() -> MoveData { MoveData { - paths: ~[], - path_map: HashMap::new(), - moves: ~[], - path_assignments: ~[], - var_assignments: ~[], - assignee_ids: HashSet::new(), + paths: RefCell::new(~[]), + path_map: RefCell::new(HashMap::new()), + moves: RefCell::new(~[]), + path_assignments: RefCell::new(~[]), + var_assignments: RefCell::new(~[]), + assignee_ids: RefCell::new(HashSet::new()), } } - fn path<'a>(&'a self, index: MovePathIndex) -> &'a MovePath { - //! Type safe indexing operator - &self.paths[*index] + fn path_loan_path(&self, index: MovePathIndex) -> @LoanPath { + let paths = self.paths.borrow(); + paths.get()[*index].loan_path } - fn mut_path<'a>(&'a mut self, index: MovePathIndex) -> &'a mut MovePath { - //! Type safe indexing operator - &mut self.paths[*index] + fn path_parent(&self, index: MovePathIndex) -> MovePathIndex { + let paths = self.paths.borrow(); + paths.get()[*index].parent + } + + fn path_first_move(&self, index: MovePathIndex) -> MoveIndex { + let paths = self.paths.borrow(); + paths.get()[*index].first_move + } + + fn path_first_child(&self, index: MovePathIndex) -> MovePathIndex { + let paths = self.paths.borrow(); + paths.get()[*index].first_child + } + + fn path_next_sibling(&self, index: MovePathIndex) -> MovePathIndex { + let paths = self.paths.borrow(); + paths.get()[*index].next_sibling + } + + fn set_path_first_move(&self, + index: MovePathIndex, + first_move: MoveIndex) { + let mut paths = self.paths.borrow_mut(); + paths.get()[*index].first_move = first_move } - fn move<'a>(&'a self, index: MoveIndex) -> &'a Move { + fn set_path_first_child(&self, + index: MovePathIndex, + first_child: MovePathIndex) { + let mut paths = self.paths.borrow_mut(); + paths.get()[*index].first_child = first_child + } + + fn move_next_move(&self, index: MoveIndex) -> MoveIndex { //! Type safe indexing operator - &self.moves[*index] + let moves = self.moves.borrow(); + moves.get()[*index].next_move } fn is_var_path(&self, index: MovePathIndex) -> bool { //! True if `index` refers to a variable - self.path(index).parent == InvalidMovePathIndex + self.path_parent(index) == InvalidMovePathIndex } - pub fn move_path(&mut self, + pub fn move_path(&self, tcx: ty::ctxt, lp: @LoanPath) -> MovePathIndex { /*! @@ -203,18 +234,22 @@ impl MoveData { * base paths that do not yet have an index. */ - match self.path_map.find(&lp) { - Some(&index) => { - return index; + { + let path_map = self.path_map.borrow(); + match path_map.get().find(&lp) { + Some(&index) => { + return index; + } + None => {} } - None => {} } let index = match *lp { LpVar(..) => { - let index = MovePathIndex(self.paths.len()); + let mut paths = self.paths.borrow_mut(); + let index = MovePathIndex(paths.get().len()); - self.paths.push(MovePath { + paths.get().push(MovePath { loan_path: lp, parent: InvalidMovePathIndex, first_move: InvalidMoveIndex, @@ -227,18 +262,25 @@ impl MoveData { LpExtend(base, _, _) => { let parent_index = self.move_path(tcx, base); - let index = MovePathIndex(self.paths.len()); - let next_sibling = self.path(parent_index).first_child; - self.mut_path(parent_index).first_child = index; - - self.paths.push(MovePath { - loan_path: lp, - parent: parent_index, - first_move: InvalidMoveIndex, - first_child: InvalidMovePathIndex, - next_sibling: next_sibling, - }); + let index = { + let paths = self.paths.borrow(); + MovePathIndex(paths.get().len()) + }; + + let next_sibling = self.path_first_child(parent_index); + self.set_path_first_child(parent_index, index); + + { + let mut paths = self.paths.borrow_mut(); + paths.get().push(MovePath { + loan_path: lp, + parent: parent_index, + first_move: InvalidMoveIndex, + first_child: InvalidMovePathIndex, + next_sibling: next_sibling, + }); + } index } @@ -248,15 +290,19 @@ impl MoveData { lp.repr(tcx), index); - assert_eq!(*index, self.paths.len() - 1); - self.path_map.insert(lp, index); + let paths = self.paths.borrow(); + assert_eq!(*index, paths.get().len() - 1); + + let mut path_map = self.path_map.borrow_mut(); + path_map.get().insert(lp, index); return index; } fn existing_move_path(&self, lp: @LoanPath) -> Option { - self.path_map.find_copy(&lp) + let path_map = self.path_map.borrow(); + path_map.get().find_copy(&lp) } fn existing_base_paths(&self, @@ -275,7 +321,11 @@ impl MoveData { * paths of `lp` to `result`, but does not add new move paths */ - match self.path_map.find_copy(&lp) { + let index_opt = { + let path_map = self.path_map.borrow(); + path_map.get().find_copy(&lp) + }; + match index_opt { Some(index) => { self.each_base_path(index, |p| { result.push(p); @@ -294,7 +344,7 @@ impl MoveData { } - pub fn add_move(&mut self, + pub fn add_move(&self, tcx: ty::ctxt, lp: @LoanPath, id: ast::NodeId, @@ -310,20 +360,26 @@ impl MoveData { kind); let path_index = self.move_path(tcx, lp); - let move_index = MoveIndex(self.moves.len()); - - let next_move = self.path(path_index).first_move; - self.mut_path(path_index).first_move = move_index; + let move_index = { + let moves = self.moves.borrow(); + MoveIndex(moves.get().len()) + }; - self.moves.push(Move { - path: path_index, - id: id, - kind: kind, - next_move: next_move - }); + let next_move = self.path_first_move(path_index); + self.set_path_first_move(path_index, move_index); + + { + let mut moves = self.moves.borrow_mut(); + moves.get().push(Move { + path: path_index, + id: id, + kind: kind, + next_move: next_move + }); + } } - pub fn add_assignment(&mut self, + pub fn add_assignment(&self, tcx: ty::ctxt, lp: @LoanPath, assign_id: ast::NodeId, @@ -339,7 +395,10 @@ impl MoveData { let path_index = self.move_path(tcx, lp); - self.assignee_ids.insert(assignee_id); + { + let mut assignee_ids = self.assignee_ids.borrow_mut(); + assignee_ids.get().insert(assignee_id); + } let assignment = Assignment { path: path_index, @@ -348,15 +407,19 @@ impl MoveData { }; if self.is_var_path(path_index) { + let mut var_assignments = self.var_assignments.borrow_mut(); debug!("add_assignment[var](lp={}, assignment={}, path_index={:?})", - lp.repr(tcx), self.var_assignments.len(), path_index); + lp.repr(tcx), var_assignments.get().len(), path_index); - self.var_assignments.push(assignment); + var_assignments.get().push(assignment); } else { debug!("add_assignment[path](lp={}, path_index={:?})", lp.repr(tcx), path_index); - self.path_assignments.push(assignment); + { + let mut path_assignments = self.path_assignments.borrow_mut(); + path_assignments.get().push(assignment); + } } } @@ -372,41 +435,60 @@ impl MoveData { * killed by scoping. See `doc.rs` for more details. */ - for (i, move) in self.moves.iter().enumerate() { - dfcx_moves.add_gen(move.id, i); + { + let moves = self.moves.borrow(); + for (i, move) in moves.get().iter().enumerate() { + dfcx_moves.add_gen(move.id, i); + } } - for (i, assignment) in self.var_assignments.iter().enumerate() { - dfcx_assign.add_gen(assignment.id, i); - self.kill_moves(assignment.path, assignment.id, dfcx_moves); + { + let var_assignments = self.var_assignments.borrow(); + for (i, assignment) in var_assignments.get().iter().enumerate() { + dfcx_assign.add_gen(assignment.id, i); + self.kill_moves(assignment.path, assignment.id, dfcx_moves); + } } - for assignment in self.path_assignments.iter() { - self.kill_moves(assignment.path, assignment.id, dfcx_moves); + { + let path_assignments = self.path_assignments.borrow(); + for assignment in path_assignments.get().iter() { + self.kill_moves(assignment.path, assignment.id, dfcx_moves); + } } // Kill all moves related to a variable `x` when it goes out // of scope: - for path in self.paths.iter() { - match *path.loan_path { - LpVar(id) => { - let kill_id = tcx.region_maps.encl_scope(id); - let path = *self.path_map.get(&path.loan_path); - self.kill_moves(path, kill_id, dfcx_moves); + { + let paths = self.paths.borrow(); + for path in paths.get().iter() { + match *path.loan_path { + LpVar(id) => { + let kill_id = tcx.region_maps.encl_scope(id); + let path = { + let path_map = self.path_map.borrow(); + *path_map.get().get(&path.loan_path) + }; + self.kill_moves(path, kill_id, dfcx_moves); + } + LpExtend(..) => {} } - LpExtend(..) => {} } } // Kill all assignments when the variable goes out of scope: - for (assignment_index, assignment) in self.var_assignments.iter().enumerate() { - match *self.path(assignment.path).loan_path { - LpVar(id) => { - let kill_id = tcx.region_maps.encl_scope(id); - dfcx_assign.add_kill(kill_id, assignment_index); - } - LpExtend(..) => { - tcx.sess.bug("Var assignment for non var path"); + { + let var_assignments = self.var_assignments.borrow(); + for (assignment_index, assignment) in + var_assignments.get().iter().enumerate() { + match *self.path_loan_path(assignment.path) { + LpVar(id) => { + let kill_id = tcx.region_maps.encl_scope(id); + dfcx_assign.add_kill(kill_id, assignment_index); + } + LpExtend(..) => { + tcx.sess.bug("Var assignment for non var path"); + } } } } @@ -419,7 +501,7 @@ impl MoveData { if !f(p) { return false; } - p = self.path(p).parent; + p = self.path_parent(p); } return true; } @@ -432,12 +514,12 @@ impl MoveData { return false; } - let mut p = self.path(index).first_child; + let mut p = self.path_first_child(index); while p != InvalidMovePathIndex { if !self.each_extending_path(p, |x| f(x)) { return false; } - p = self.path(p).next_sibling; + p = self.path_next_sibling(p); } return true; @@ -449,13 +531,13 @@ impl MoveData { -> bool { let mut ret = true; self.each_extending_path(index0, |index| { - let mut p = self.path(index).first_move; + let mut p = self.path_first_move(index); while p != InvalidMoveIndex { if !f(p) { ret = false; break; } - p = self.move(p).next_move; + p = self.move_next_move(p); } ret }); @@ -474,25 +556,28 @@ impl MoveData { } impl FlowedMoveData { - pub fn new(move_data: @mut MoveData, + pub fn new(move_data: @MoveData, tcx: ty::ctxt, method_map: typeck::method_map, id_range: ast_util::id_range, body: &ast::Block) - -> FlowedMoveData - { - let mut dfcx_moves = + -> FlowedMoveData { + let mut dfcx_moves = { + let moves = move_data.moves.borrow(); DataFlowContext::new(tcx, method_map, MoveDataFlowOperator, id_range, - move_data.moves.len()); - let mut dfcx_assign = + moves.get().len()) + }; + let mut dfcx_assign = { + let var_assignments = move_data.var_assignments.borrow(); DataFlowContext::new(tcx, method_map, AssignDataFlowOperator, id_range, - move_data.var_assignments.len()); + var_assignments.get().len()) + }; move_data.add_gen_kills(tcx, &mut dfcx_moves, &mut dfcx_assign); dfcx_moves.propagate(body); dfcx_assign.propagate(body); @@ -512,9 +597,10 @@ impl FlowedMoveData { */ self.dfcx_moves.each_gen_bit_frozen(id, |index| { - let move = &self.move_data.moves[index]; + let moves = self.move_data.moves.borrow(); + let move = &moves.get()[index]; let moved_path = move.path; - f(move, self.move_data.path(moved_path).loan_path) + f(move, self.move_data.path_loan_path(moved_path)) }) } @@ -550,12 +636,13 @@ impl FlowedMoveData { let mut ret = true; self.dfcx_moves.each_bit_on_entry_frozen(id, |index| { - let move = &self.move_data.moves[index]; + let moves = self.move_data.moves.borrow(); + let move = &moves.get()[index]; let moved_path = move.path; if base_indices.iter().any(|x| x == &moved_path) { // Scenario 1 or 2: `loan_path` or some base path of // `loan_path` was moved. - if !f(move, self.move_data.path(moved_path).loan_path) { + if !f(move, self.move_data.path_loan_path(moved_path)) { ret = false; } } else { @@ -564,7 +651,7 @@ impl FlowedMoveData { if p == loan_path_index { // Scenario 3: some extension of `loan_path` // was moved - f(move, self.move_data.path(moved_path).loan_path) + f(move, self.move_data.path_loan_path(moved_path)) } else { true } @@ -581,7 +668,8 @@ impl FlowedMoveData { -> bool { //! True if `id` is the id of the LHS of an assignment - self.move_data.assignee_ids.iter().any(|x| x == &id) + let assignee_ids = self.move_data.assignee_ids.borrow(); + assignee_ids.get().iter().any(|x| x == &id) } pub fn each_assignment_of(&self, @@ -606,7 +694,8 @@ impl FlowedMoveData { }; self.dfcx_assign.each_bit_on_entry_frozen(id, |index| { - let assignment = &self.move_data.var_assignments[index]; + let var_assignments = self.move_data.var_assignments.borrow(); + let assignment = &var_assignments.get()[index]; if assignment.path == loan_path_index && !f(assignment) { false } else { diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 4a12ac4ccff4b..d5823e025be10 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -496,7 +496,8 @@ impl CFGBuilder { } Some(_) => { - match self.tcx.def_map.find(&expr.id) { + let def_map = self.tcx.def_map.borrow(); + match def_map.get().find(&expr.id) { Some(&ast::DefLabel(loop_id)) => { for l in self.loop_scopes.iter() { if l.loop_id == loop_id { @@ -519,6 +520,7 @@ impl CFGBuilder { } fn is_method_call(&self, expr: &ast::Expr) -> bool { - self.method_map.contains_key(&expr.id) + let method_map = self.method_map.borrow(); + method_map.get().contains_key(&expr.id) } } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 39cd3356fae61..4dfdd00c27ad6 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -15,6 +15,7 @@ use middle::ty; use middle::typeck; use util::ppaux; +use std::cell::RefCell; use syntax::ast::*; use syntax::codemap; use syntax::{ast_util, ast_map}; @@ -122,7 +123,8 @@ pub fn check_expr(v: &mut CheckCrateVisitor, } ExprLit(@codemap::Spanned {node: lit_str(..), ..}) => { } ExprBinary(..) | ExprUnary(..) => { - if method_map.contains_key(&e.id) { + let method_map = method_map.borrow(); + if method_map.get().contains_key(&e.id) { sess.span_err(e.span, "user-defined operators are not \ allowed in constant expressions"); } @@ -146,7 +148,8 @@ pub fn check_expr(v: &mut CheckCrateVisitor, e.span, "paths in constants may only refer to \ items without type parameters"); } - match def_map.find(&e.id) { + let def_map = def_map.borrow(); + match def_map.get().find(&e.id) { Some(&DefStatic(..)) | Some(&DefFn(_, _)) | Some(&DefVariant(_, _, _)) | @@ -165,7 +168,8 @@ pub fn check_expr(v: &mut CheckCrateVisitor, } } ExprCall(callee, _, NoSugar) => { - match def_map.find(&callee.id) { + let def_map = def_map.borrow(); + match def_map.get().find(&callee.id) { Some(&DefStruct(..)) => {} // OK. Some(&DefVariant(..)) => {} // OK. _ => { @@ -214,7 +218,7 @@ struct env { sess: Session, ast_map: ast_map::map, def_map: resolve::DefMap, - idstack: @mut ~[NodeId] + idstack: @RefCell<~[NodeId]>, } struct CheckItemRecursionVisitor { @@ -232,7 +236,7 @@ pub fn check_item_recursion(sess: Session, sess: sess, ast_map: ast_map, def_map: def_map, - idstack: @mut ~[] + idstack: @RefCell::new(~[]), }; let mut visitor = CheckItemRecursionVisitor { env: env }; @@ -241,25 +245,36 @@ pub fn check_item_recursion(sess: Session, impl Visitor<()> for CheckItemRecursionVisitor { fn visit_item(&mut self, it: @item, _: ()) { - if self.env.idstack.iter().any(|x| x == &(it.id)) { - self.env.sess.span_fatal(self.env.root_it.span, "recursive constant"); + { + let mut idstack = self.env.idstack.borrow_mut(); + if idstack.get().iter().any(|x| x == &(it.id)) { + self.env.sess.span_fatal(self.env.root_it.span, + "recursive constant"); + } + idstack.get().push(it.id); } - self.env.idstack.push(it.id); visit::walk_item(self, it, ()); - self.env.idstack.pop(); + { + let mut idstack = self.env.idstack.borrow_mut(); + idstack.get().pop(); + } } fn visit_expr(&mut self, e: @Expr, _: ()) { match e.node { - ExprPath(..) => match self.env.def_map.find(&e.id) { - Some(&DefStatic(def_id, _)) if ast_util::is_local(def_id) => - match self.env.ast_map.get_copy(&def_id.node) { - ast_map::node_item(it, _) => { - self.visit_item(it, ()); - } - _ => fail!("const not bound to an item") - }, - _ => () + ExprPath(..) => { + let def_map = self.env.def_map.borrow(); + match def_map.get().find(&e.id) { + Some(&DefStatic(def_id, _)) if + ast_util::is_local(def_id) => + match self.env.ast_map.get_copy(&def_id.node) { + ast_map::node_item(it, _) => { + self.visit_item(it, ()); + } + _ => fail!("const not bound to an item") + }, + _ => () + } }, _ => () } diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 948c7932ca0dc..35ac2190888a5 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -121,8 +121,12 @@ fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) { // Check that we do not match against a static NaN (#6804) let pat_matches_nan: |&Pat| -> bool = |p| { - match cx.tcx.def_map.find(&p.id) { - Some(&DefStatic(did, false)) => { + let opt_def = { + let def_map = cx.tcx.def_map.borrow(); + def_map.get().find_copy(&p.id) + }; + match opt_def { + Some(DefStatic(did, false)) => { let const_expr = lookup_const_by_id(cx.tcx, did).unwrap(); match eval_const_expr(cx.tcx, const_expr) { const_float(f) if f.is_nan() => true, @@ -334,9 +338,13 @@ fn pat_ctor_id(cx: &MatchCheckCtxt, p: @Pat) -> Option { match pat.node { PatWild | PatWildMulti => { None } PatIdent(_, _, _) | PatEnum(_, _) => { - match cx.tcx.def_map.find(&pat.id) { - Some(&DefVariant(_, id, _)) => Some(variant(id)), - Some(&DefStatic(did, false)) => { + let opt_def = { + let def_map = cx.tcx.def_map.borrow(); + def_map.get().find_copy(&pat.id) + }; + match opt_def { + Some(DefVariant(_, id, _)) => Some(variant(id)), + Some(DefStatic(did, false)) => { let const_expr = lookup_const_by_id(cx.tcx, did).unwrap(); Some(val(eval_const_expr(cx.tcx, const_expr))) } @@ -348,7 +356,8 @@ fn pat_ctor_id(cx: &MatchCheckCtxt, p: @Pat) -> Option { Some(range(eval_const_expr(cx.tcx, lo), eval_const_expr(cx.tcx, hi))) } PatStruct(..) => { - match cx.tcx.def_map.find(&pat.id) { + let def_map = cx.tcx.def_map.borrow(); + match def_map.get().find(&pat.id) { Some(&DefVariant(_, id, _)) => Some(variant(id)), _ => Some(single) } @@ -370,7 +379,8 @@ fn is_wild(cx: &MatchCheckCtxt, p: @Pat) -> bool { match pat.node { PatWild | PatWildMulti => { true } PatIdent(_, _, _) => { - match cx.tcx.def_map.find(&pat.id) { + let def_map = cx.tcx.def_map.borrow(); + match def_map.get().find(&pat.id) { Some(&DefVariant(_, _, _)) | Some(&DefStatic(..)) => { false } _ => { true } } @@ -551,15 +561,19 @@ fn specialize(cx: &MatchCheckCtxt, Some(vec::append(vec::from_elem(arity, wild_multi()), r.tail())) } PatIdent(_, _, _) => { - match cx.tcx.def_map.find(&pat_id) { - Some(&DefVariant(_, id, _)) => { + let opt_def = { + let def_map = cx.tcx.def_map.borrow(); + def_map.get().find_copy(&pat_id) + }; + match opt_def { + Some(DefVariant(_, id, _)) => { if variant(id) == *ctor_id { Some(r.tail().to_owned()) } else { None } } - Some(&DefStatic(did, _)) => { + Some(DefStatic(did, _)) => { let const_expr = lookup_const_by_id(cx.tcx, did).unwrap(); let e_v = eval_const_expr(cx.tcx, const_expr); @@ -608,7 +622,11 @@ fn specialize(cx: &MatchCheckCtxt, } } PatEnum(_, args) => { - match cx.tcx.def_map.get_copy(&pat_id) { + let opt_def = { + let def_map = cx.tcx.def_map.borrow(); + def_map.get().get_copy(&pat_id) + }; + match opt_def { DefStatic(did, _) => { let const_expr = lookup_const_by_id(cx.tcx, did).unwrap(); @@ -668,7 +686,11 @@ fn specialize(cx: &MatchCheckCtxt, } PatStruct(_, ref pattern_fields, _) => { // Is this a struct or an enum variant? - match cx.tcx.def_map.get_copy(&pat_id) { + let opt_def = { + let def_map = cx.tcx.def_map.borrow(); + def_map.get().get_copy(&pat_id) + }; + match opt_def { DefVariant(_, variant_id, _) => { if variant(variant_id) == *ctor_id { let struct_fields = ty::lookup_struct_fields(cx.tcx, variant_id); @@ -838,13 +860,17 @@ fn check_fn(v: &mut CheckMatchVisitor, } fn is_refutable(cx: &MatchCheckCtxt, pat: &Pat) -> bool { - match cx.tcx.def_map.find(&pat.id) { - Some(&DefVariant(enum_id, _, _)) => { + let opt_def = { + let def_map = cx.tcx.def_map.borrow(); + def_map.get().find_copy(&pat.id) + }; + match opt_def { + Some(DefVariant(enum_id, _, _)) => { if ty::enum_variants(cx.tcx, enum_id).len() != 1u { return true; } } - Some(&DefStatic(..)) => return true, + Some(DefStatic(..)) => return true, _ => () } @@ -889,7 +915,8 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, by_ref_span = Some(span); } BindByValue(_) => { - if cx.moves_map.contains(&id) { + let moves_map = cx.moves_map.borrow(); + if moves_map.get().contains(&id) { any_by_move = true; } } @@ -926,7 +953,8 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, if pat_is_binding(def_map, p) { match p.node { PatIdent(_, _, sub) => { - if cx.moves_map.contains(&p.id) { + let moves_map = cx.moves_map.borrow(); + if moves_map.get().contains(&p.id) { check_move(p, sub); } } diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 248ff1fdd1632..d0dd36cda9605 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -19,6 +19,7 @@ use syntax::visit; use syntax::visit::Visitor; use syntax::ast::*; +use std::cell::RefCell; use std::hashmap::{HashMap, HashSet}; // @@ -77,11 +78,17 @@ pub fn join_all>(mut cs: It) -> constness { } pub fn lookup_const(tcx: ty::ctxt, e: &Expr) -> Option<@Expr> { - match tcx.def_map.find(&e.id) { - Some(&ast::DefStatic(def_id, false)) => - lookup_const_by_id(tcx, def_id), - Some(&ast::DefVariant(enum_def, variant_def, _)) => - lookup_variant_by_id(tcx, enum_def, variant_def), + let opt_def = { + let def_map = tcx.def_map.borrow(); + def_map.get().find_copy(&e.id) + }; + match opt_def { + Some(ast::DefStatic(def_id, false)) => { + lookup_const_by_id(tcx, def_id) + } + Some(ast::DefVariant(enum_def, variant_def, _)) => { + lookup_variant_by_id(tcx, enum_def, variant_def) + } _ => None } } @@ -111,16 +118,19 @@ pub fn lookup_variant_by_id(tcx: ty::ctxt, Some(_) => None } } else { - match tcx.extern_const_variants.find(&variant_def) { - Some(&e) => return e, - None => {} + { + let extern_const_variants = tcx.extern_const_variants.borrow(); + match extern_const_variants.get().find(&variant_def) { + Some(&e) => return e, + None => {} + } } let maps = astencode::Maps { - root_map: @mut HashMap::new(), - method_map: @mut HashMap::new(), - vtable_map: @mut HashMap::new(), - write_guard_map: @mut HashSet::new(), - capture_map: @mut HashMap::new() + root_map: @RefCell::new(HashMap::new()), + method_map: @RefCell::new(HashMap::new()), + vtable_map: @RefCell::new(HashMap::new()), + write_guard_map: @RefCell::new(HashSet::new()), + capture_map: @RefCell::new(HashMap::new()) }; let e = match csearch::maybe_get_item_ast(tcx, enum_def, |a, b, c, d| astencode::decode_inlined_item(a, @@ -136,8 +146,12 @@ pub fn lookup_variant_by_id(tcx: ty::ctxt, }, _ => None }; - tcx.extern_const_variants.insert(variant_def, e); - return e; + { + let mut extern_const_variants = tcx.extern_const_variants + .borrow_mut(); + extern_const_variants.get().insert(variant_def, e); + return e; + } } } @@ -154,16 +168,19 @@ pub fn lookup_const_by_id(tcx: ty::ctxt, Some(_) => None } } else { - match tcx.extern_const_statics.find(&def_id) { - Some(&e) => return e, - None => {} + { + let extern_const_statics = tcx.extern_const_statics.borrow(); + match extern_const_statics.get().find(&def_id) { + Some(&e) => return e, + None => {} + } } let maps = astencode::Maps { - root_map: @mut HashMap::new(), - method_map: @mut HashMap::new(), - vtable_map: @mut HashMap::new(), - write_guard_map: @mut HashSet::new(), - capture_map: @mut HashMap::new() + root_map: @RefCell::new(HashMap::new()), + method_map: @RefCell::new(HashMap::new()), + vtable_map: @RefCell::new(HashMap::new()), + write_guard_map: @RefCell::new(HashSet::new()), + capture_map: @RefCell::new(HashMap::new()) }; let e = match csearch::maybe_get_item_ast(tcx, def_id, |a, b, c, d| astencode::decode_inlined_item(a, b, maps, c, d)) { @@ -173,8 +190,12 @@ pub fn lookup_const_by_id(tcx: ty::ctxt, }, _ => None }; - tcx.extern_const_statics.insert(def_id, e); - return e; + { + let mut extern_const_statics = tcx.extern_const_statics + .borrow_mut(); + extern_const_statics.get().insert(def_id, e); + return e; + } } } diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 6a6e8f958fffc..142c69a5233ef 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -874,7 +874,8 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> { } Some(_) => { - match self.tcx().def_map.find(&expr.id) { + let def_map = self.tcx().def_map.borrow(); + match def_map.get().find(&expr.id) { Some(&ast::DefLabel(loop_id)) => { match loop_scopes.iter().position(|l| l.loop_id == loop_id) { Some(i) => i, @@ -899,7 +900,8 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> { } fn is_method_call(&self, expr: &ast::Expr) -> bool { - self.dfcx.method_map.contains_key(&expr.id) + let method_map = self.dfcx.method_map.borrow(); + method_map.get().contains_key(&expr.id) } fn reset(&mut self, bits: &mut [uint]) { diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index fe4da4181da39..d26954ad45856 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -63,7 +63,8 @@ impl MarkSymbolVisitor { } fn lookup_and_handle_definition(&mut self, id: &ast::NodeId) { - let def = match self.tcx.def_map.find(id) { + let def_map = self.tcx.def_map.borrow(); + let def = match def_map.get().find(id) { Some(&def) => def, None => return }; @@ -134,7 +135,8 @@ impl Visitor<()> for MarkSymbolVisitor { fn visit_expr(&mut self, expr: @ast::Expr, _: ()) { match expr.node { ast::ExprMethodCall(..) => { - match self.method_map.find(&expr.id) { + let method_map = self.method_map.borrow(); + match method_map.get().find(&expr.id) { Some(&typeck::method_map_entry { origin: typeck::method_static(def_id), .. @@ -211,7 +213,7 @@ fn create_and_seed_worklist(tcx: ty::ctxt, } // Seed entry point - match *tcx.sess.entry_fn { + match tcx.sess.entry_fn.get() { Some((id, _)) => worklist.push(id), None => () } @@ -282,10 +284,12 @@ impl DeadVisitor { // method of a private type is used, but the type itself is never // called directly. let def_id = local_def(id); - match self.tcx.inherent_impls.find(&def_id) { + let inherent_impls = self.tcx.inherent_impls.borrow(); + match inherent_impls.get().find(&def_id) { None => (), Some(ref impl_list) => { - for impl_ in impl_list.iter() { + let impl_list = impl_list.borrow(); + for impl_ in impl_list.get().iter() { for method in impl_.methods.iter() { if self.live_symbols.contains(&method.def_id.node) { return true; diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index aff37264f24e2..d4c566d4a604a 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -56,7 +56,8 @@ impl EffectCheckVisitor { UnsafeBlock(block_id) => { // OK, but record this. debug!("effect: recording unsafe block as used: {:?}", block_id); - let _ = self.tcx.used_unsafe.insert(block_id); + let mut used_unsafe = self.tcx.used_unsafe.borrow_mut(); + let _ = used_unsafe.get().insert(block_id); } UnsafeFn => {} } diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 4103812d36189..53a8b93c232da 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -45,14 +45,14 @@ impl Visitor<()> for EntryContext { } pub fn find_entry_point(session: Session, crate: &Crate, ast_map: ast_map::map) { - if *session.building_library { + if session.building_library.get() { // No need to find a main function return; } // If the user wants no main function at all, then stop here. if attr::contains_name(crate.attrs, "no_main") { - *session.entry_type = Some(session::EntryNone); + session.entry_type.set(Some(session::EntryNone)); return } @@ -122,16 +122,16 @@ fn find_item(item: @item, ctxt: &mut EntryContext) { fn configure_main(this: &mut EntryContext) { if this.start_fn.is_some() { - *this.session.entry_fn = this.start_fn; - *this.session.entry_type = Some(session::EntryStart); + this.session.entry_fn.set(this.start_fn); + this.session.entry_type.set(Some(session::EntryStart)); } else if this.attr_main_fn.is_some() { - *this.session.entry_fn = this.attr_main_fn; - *this.session.entry_type = Some(session::EntryMain); + this.session.entry_fn.set(this.attr_main_fn); + this.session.entry_type.set(Some(session::EntryMain)); } else if this.main_fn.is_some() { - *this.session.entry_fn = this.main_fn; - *this.session.entry_type = Some(session::EntryMain); + this.session.entry_fn.set(this.main_fn); + this.session.entry_type.set(Some(session::EntryMain)); } else { - if !*this.session.building_library { + if !this.session.building_library.get() { // No main function this.session.err("main function not found"); if !this.non_main_fns.is_empty() { diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs index 10b72b06048d3..9d7dc6fdc7e8f 100644 --- a/src/librustc/middle/freevars.rs +++ b/src/librustc/middle/freevars.rs @@ -30,11 +30,11 @@ pub struct freevar_entry { span: Span //< First span where it is accessed (there can be multiple) } pub type freevar_info = @~[@freevar_entry]; -pub type freevar_map = @mut HashMap; +pub type freevar_map = HashMap; struct CollectFreevarsVisitor { - seen: @mut HashMap, - refs: @mut ~[@freevar_entry], + seen: HashMap, + refs: ~[@freevar_entry], def_map: resolve::DefMap, } @@ -52,7 +52,8 @@ impl Visitor for CollectFreevarsVisitor { } ast::ExprPath(..) | ast::ExprSelf => { let mut i = 0; - match self.def_map.find(&expr.id) { + let def_map = self.def_map.borrow(); + match def_map.get().find(&expr.id) { None => fail!("path not found"), Some(&df) => { let mut def = df; @@ -90,8 +91,8 @@ impl Visitor for CollectFreevarsVisitor { // in order to start the search. fn collect_freevars(def_map: resolve::DefMap, blk: ast::P) -> freevar_info { - let seen = @mut HashMap::new(); - let refs = @mut ~[]; + let seen = HashMap::new(); + let refs = ~[]; let mut v = CollectFreevarsVisitor { seen: seen, @@ -100,7 +101,11 @@ fn collect_freevars(def_map: resolve::DefMap, blk: ast::P) }; v.visit_block(blk, 1); - return @(*refs).clone(); + let CollectFreevarsVisitor { + refs, + .. + } = v; + return @refs; } struct AnnotateFreevarsVisitor { @@ -124,21 +129,24 @@ impl Visitor<()> for AnnotateFreevarsVisitor { // one pass. This could be improved upon if it turns out to matter. pub fn annotate_freevars(def_map: resolve::DefMap, crate: &ast::Crate) -> freevar_map { - let freevars = @mut HashMap::new(); - let mut visitor = AnnotateFreevarsVisitor { def_map: def_map, - freevars: freevars, + freevars: HashMap::new(), }; visit::walk_crate(&mut visitor, crate, ()); - return freevars; + let AnnotateFreevarsVisitor { + freevars, + .. + } = visitor; + freevars } pub fn get_freevars(tcx: ty::ctxt, fid: ast::NodeId) -> freevar_info { - match tcx.freevars.find(&fid) { - None => fail!("get_freevars: {} has no freevars", fid), - Some(&d) => return d + let freevars = tcx.freevars.borrow(); + match freevars.get().find(&fid) { + None => fail!("get_freevars: {} has no freevars", fid), + Some(&d) => return d } } diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 195f7798eb0f5..e426f92759fac 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -116,11 +116,18 @@ fn check_struct_safe_for_destructor(cx: &mut Context, } fn check_impl_of_trait(cx: &mut Context, it: @item, trait_ref: &trait_ref, self_type: &Ty) { - let ast_trait_def = cx.tcx.def_map.find(&trait_ref.ref_id) - .expect("trait ref not in def map!"); + let def_map = cx.tcx.def_map.borrow(); + let ast_trait_def = def_map.get() + .find(&trait_ref.ref_id) + .expect("trait ref not in def map!"); let trait_def_id = ast_util::def_id_of_def(*ast_trait_def); - let trait_def = cx.tcx.trait_defs.find(&trait_def_id) - .expect("trait def not in trait-defs map!"); + let trait_def; + { + let trait_defs = cx.tcx.trait_defs.borrow(); + trait_def = *trait_defs.get() + .find(&trait_def_id) + .expect("trait def not in trait-defs map!"); + } // If this trait has builtin-kind supertraits, meet them. let self_ty: ty::t = ty::node_id_to_type(cx.tcx, it.id); @@ -139,7 +146,7 @@ fn check_impl_of_trait(cx: &mut Context, it: @item, trait_ref: &trait_ref, self_ match self_type.node { ty_path(_, ref bounds, path_node_id) => { assert!(bounds.is_none()); - let struct_def = cx.tcx.def_map.get_copy(&path_node_id); + let struct_def = def_map.get().get_copy(&path_node_id); let struct_did = ast_util::def_id_of_def(struct_def); check_struct_safe_for_destructor(cx, self_type.span, struct_did); } @@ -264,11 +271,14 @@ pub fn check_expr(cx: &mut Context, e: @Expr) { None => e.id, }; { - let r = cx.tcx.node_type_substs.find(&type_parameter_id); + let node_type_substs = cx.tcx.node_type_substs.borrow(); + let r = node_type_substs.get().find(&type_parameter_id); for ts in r.iter() { + let def_map = cx.tcx.def_map.borrow(); let type_param_defs = match e.node { ExprPath(_) => { - let did = ast_util::def_id_of_def(cx.tcx.def_map.get_copy(&e.id)); + let did = ast_util::def_id_of_def(def_map.get() + .get_copy(&e.id)); ty::lookup_item_type(cx.tcx, did).generics.type_param_defs } _ => { @@ -326,9 +336,11 @@ pub fn check_expr(cx: &mut Context, e: @Expr) { fn check_ty(cx: &mut Context, aty: &Ty) { match aty.node { ty_path(_, _, id) => { - let r = cx.tcx.node_type_substs.find(&id); + let node_type_substs = cx.tcx.node_type_substs.borrow(); + let r = node_type_substs.get().find(&id); for ts in r.iter() { - let did = ast_util::def_id_of_def(cx.tcx.def_map.get_copy(&id)); + let def_map = cx.tcx.def_map.borrow(); + let did = ast_util::def_id_of_def(def_map.get().get_copy(&id)); let type_param_defs = ty::lookup_item_type(cx.tcx, did).generics.type_param_defs; for (&ty, type_param_def) in ts.iter().zip(type_param_defs.iter()) { diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index cb4208128d5c7..d94bfe1447e01 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -712,7 +712,8 @@ fn check_item_ctypes(cx: &Context, it: &ast::item) { fn check_ty(cx: &Context, ty: &ast::Ty) { match ty.node { ast::ty_path(_, _, id) => { - match cx.tcx.def_map.get_copy(&id) { + let def_map = cx.tcx.def_map.borrow(); + match def_map.get().get_copy(&id) { ast::DefPrimTy(ast::ty_int(ast::ty_i)) => { cx.span_lint(ctypes, ty.span, "found rust type `int` in foreign module, while \ @@ -983,7 +984,8 @@ fn check_item_non_uppercase_statics(cx: &Context, it: &ast::item) { fn check_pat_non_uppercase_statics(cx: &Context, p: &ast::Pat) { // Lint for constants that look like binding identifiers (#7526) - match (&p.node, cx.tcx.def_map.find(&p.id)) { + let def_map = cx.tcx.def_map.borrow(); + match (&p.node, def_map.get().find(&p.id)) { (&ast::PatIdent(_, ref path, _), Some(&ast::DefStatic(_, false))) => { // last identifier alone is right choice for this lint. let ident = path.segments.last().identifier; @@ -1001,8 +1003,9 @@ fn check_unused_unsafe(cx: &Context, e: &ast::Expr) { match e.node { // Don't warn about generated blocks, that'll just pollute the output. ast::ExprBlock(ref blk) => { + let used_unsafe = cx.tcx.used_unsafe.borrow(); if blk.rules == ast::UnsafeBlock(ast::UserProvided) && - !cx.tcx.used_unsafe.contains(&blk.id) { + !used_unsafe.get().contains(&blk.id) { cx.span_lint(unused_unsafe, blk.span, "unnecessary `unsafe` block"); } @@ -1037,7 +1040,8 @@ fn check_unused_mut_pat(cx: &Context, p: &ast::Pat) { } }; - if !initial_underscore && !cx.tcx.used_mut_nodes.contains(&p.id) { + let used_mut_nodes = cx.tcx.used_mut_nodes.borrow(); + if !initial_underscore && !used_mut_nodes.get().contains(&p.id) { cx.span_lint(unused_mut, p.span, "variable does not need to be mutable"); } @@ -1073,7 +1077,11 @@ fn check_unnecessary_allocation(cx: &Context, e: &ast::Expr) { cx.span_lint(unnecessary_allocation, e.span, msg); }; - match cx.tcx.adjustments.find_copy(&e.id) { + let adjustment = { + let adjustments = cx.tcx.adjustments.borrow(); + adjustments.get().find_copy(&e.id) + }; + match adjustment { Some(@ty::AutoDerefRef(ty::AutoDerefRef { autoref, .. })) => { match (allocation, autoref) { (VectorAllocation, Some(ty::AutoBorrowVec(..))) => { @@ -1141,7 +1149,14 @@ fn check_missing_doc_method(cx: &Context, m: &ast::method) { crate: ast::LOCAL_CRATE, node: m.id }; - match cx.tcx.methods.find(&did) { + + let method_opt; + { + let methods = cx.tcx.methods.borrow(); + method_opt = methods.get().find(&did).map(|method| *method); + } + + match method_opt { None => cx.tcx.sess.span_bug(m.span, "missing method descriptor?!"), Some(md) => { match md.container { @@ -1184,13 +1199,15 @@ fn check_missing_doc_variant(cx: &Context, v: &ast::variant) { fn check_stability(cx: &Context, e: &ast::Expr) { let id = match e.node { ast::ExprPath(..) | ast::ExprStruct(..) => { - match cx.tcx.def_map.find(&e.id) { + let def_map = cx.tcx.def_map.borrow(); + match def_map.get().find(&e.id) { Some(&def) => ast_util::def_id_of_def(def), None => return } } ast::ExprMethodCall(..) => { - match cx.method_map.find(&e.id) { + let method_map = cx.method_map.borrow(); + match method_map.get().find(&e.id) { Some(&typeck::method_map_entry { origin, .. }) => { match origin { typeck::method_static(def_id) => { @@ -1413,7 +1430,8 @@ impl<'a> Visitor<()> for Context<'a> { impl<'a> IdVisitingOperation for Context<'a> { fn visit_id(&self, id: ast::NodeId) { - match self.tcx.sess.lints.pop(&id) { + let mut lints = self.tcx.sess.lints.borrow_mut(); + match lints.get().pop(&id) { None => {} Some(l) => { for (lint, span, msg) in l.move_iter() { @@ -1465,7 +1483,8 @@ pub fn check_crate(tcx: ty::ctxt, // If we missed any lints added to the session, then there's a bug somewhere // in the iteration code. - for (id, v) in tcx.sess.lints.iter() { + let lints = tcx.sess.lints.borrow(); + for (id, v) in lints.get().iter() { for &(lint, span, ref msg) in v.iter() { tcx.sess.span_bug(span, format!("unprocessed lint {:?} at {}: {}", lint, diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index ca9acf61aa8d5..8532f959a2cd1 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -110,6 +110,7 @@ use middle::typeck; use middle::moves; use std::cast::transmute; +use std::cell::{Cell, RefCell}; use std::hashmap::HashMap; use std::io; use std::str; @@ -154,13 +155,13 @@ fn live_node_kind_to_str(lnk: LiveNodeKind, cx: ty::ctxt) -> ~str { struct LivenessVisitor; -impl Visitor<@mut IrMaps> for LivenessVisitor { - fn visit_fn(&mut self, fk:&fn_kind, fd:&fn_decl, b:P, s:Span, n:NodeId, e:@mut IrMaps) { +impl Visitor<@IrMaps> for LivenessVisitor { + fn visit_fn(&mut self, fk:&fn_kind, fd:&fn_decl, b:P, s:Span, n:NodeId, e:@IrMaps) { visit_fn(self, fk, fd, b, s, n, e); } - fn visit_local(&mut self, l:@Local, e:@mut IrMaps) { visit_local(self, l, e); } - fn visit_expr(&mut self, ex:@Expr, e:@mut IrMaps) { visit_expr(self, ex, e); } - fn visit_arm(&mut self, a:&Arm, e:@mut IrMaps) { visit_arm(self, a, e); } + fn visit_local(&mut self, l:@Local, e:@IrMaps) { visit_local(self, l, e); } + fn visit_expr(&mut self, ex:@Expr, e:@IrMaps) { visit_expr(self, ex, e); } + fn visit_arm(&mut self, a:&Arm, e:@IrMaps) { visit_arm(self, a, e); } } pub fn check_crate(tcx: ty::ctxt, @@ -169,9 +170,7 @@ pub fn check_crate(tcx: ty::ctxt, crate: &Crate) { let mut visitor = LivenessVisitor; - let initial_maps = @mut IrMaps(tcx, - method_map, - capture_map); + let initial_maps = @IrMaps(tcx, method_map, capture_map); visit::walk_crate(&mut visitor, crate, initial_maps); tcx.sess.abort_if_errors(); } @@ -244,13 +243,13 @@ struct IrMaps { method_map: typeck::method_map, capture_map: moves::CaptureMap, - num_live_nodes: uint, - num_vars: uint, - live_node_map: HashMap, - variable_map: HashMap, - capture_info_map: HashMap, - var_kinds: ~[VarKind], - lnks: ~[LiveNodeKind], + num_live_nodes: Cell, + num_vars: Cell, + live_node_map: RefCell>, + variable_map: RefCell>, + capture_info_map: RefCell>, + var_kinds: RefCell<~[VarKind]>, + lnks: RefCell<~[LiveNodeKind]>, } fn IrMaps(tcx: ty::ctxt, @@ -261,21 +260,23 @@ fn IrMaps(tcx: ty::ctxt, tcx: tcx, method_map: method_map, capture_map: capture_map, - num_live_nodes: 0, - num_vars: 0, - live_node_map: HashMap::new(), - variable_map: HashMap::new(), - capture_info_map: HashMap::new(), - var_kinds: ~[], - lnks: ~[], + num_live_nodes: Cell::new(0), + num_vars: Cell::new(0), + live_node_map: RefCell::new(HashMap::new()), + variable_map: RefCell::new(HashMap::new()), + capture_info_map: RefCell::new(HashMap::new()), + var_kinds: RefCell::new(~[]), + lnks: RefCell::new(~[]), } } impl IrMaps { - pub fn add_live_node(&mut self, lnk: LiveNodeKind) -> LiveNode { - let ln = LiveNode(self.num_live_nodes); - self.lnks.push(lnk); - self.num_live_nodes += 1; + pub fn add_live_node(&self, lnk: LiveNodeKind) -> LiveNode { + let num_live_nodes = self.num_live_nodes.get(); + let ln = LiveNode(num_live_nodes); + let mut lnks = self.lnks.borrow_mut(); + lnks.get().push(lnk); + self.num_live_nodes.set(num_live_nodes + 1); debug!("{} is of kind {}", ln.to_str(), live_node_kind_to_str(lnk, self.tcx)); @@ -283,23 +284,26 @@ impl IrMaps { ln } - pub fn add_live_node_for_node(&mut self, - node_id: NodeId, - lnk: LiveNodeKind) { + pub fn add_live_node_for_node(&self, node_id: NodeId, lnk: LiveNodeKind) { let ln = self.add_live_node(lnk); - self.live_node_map.insert(node_id, ln); + let mut live_node_map = self.live_node_map.borrow_mut(); + live_node_map.get().insert(node_id, ln); debug!("{} is node {}", ln.to_str(), node_id); } - pub fn add_variable(&mut self, vk: VarKind) -> Variable { - let v = Variable(self.num_vars); - self.var_kinds.push(vk); - self.num_vars += 1; + pub fn add_variable(&self, vk: VarKind) -> Variable { + let v = Variable(self.num_vars.get()); + { + let mut var_kinds = self.var_kinds.borrow_mut(); + var_kinds.get().push(vk); + } + self.num_vars.set(self.num_vars.get() + 1); match vk { Local(LocalInfo { id: node_id, .. }) | Arg(node_id, _) => { - self.variable_map.insert(node_id, v); + let mut variable_map = self.variable_map.borrow_mut(); + variable_map.get().insert(node_id, v); }, ImplicitRet => {} } @@ -309,8 +313,9 @@ impl IrMaps { v } - pub fn variable(&mut self, node_id: NodeId, span: Span) -> Variable { - match self.variable_map.find(&node_id) { + pub fn variable(&self, node_id: NodeId, span: Span) -> Variable { + let variable_map = self.variable_map.borrow(); + match variable_map.get().find(&node_id) { Some(&var) => var, None => { self.tcx.sess.span_bug( @@ -319,8 +324,9 @@ impl IrMaps { } } - pub fn variable_name(&mut self, var: Variable) -> @str { - match self.var_kinds[*var] { + pub fn variable_name(&self, var: Variable) -> @str { + let var_kinds = self.var_kinds.borrow(); + match var_kinds.get()[*var] { Local(LocalInfo { ident: nm, .. }) | Arg(_, nm) => { self.tcx.sess.str_of(nm) }, @@ -328,12 +334,14 @@ impl IrMaps { } } - pub fn set_captures(&mut self, node_id: NodeId, cs: ~[CaptureInfo]) { - self.capture_info_map.insert(node_id, @cs); + pub fn set_captures(&self, node_id: NodeId, cs: ~[CaptureInfo]) { + let mut capture_info_map = self.capture_info_map.borrow_mut(); + capture_info_map.get().insert(node_id, @cs); } - pub fn captures(&mut self, expr: &Expr) -> @~[CaptureInfo] { - match self.capture_info_map.find(&expr.id) { + pub fn captures(&self, expr: &Expr) -> @~[CaptureInfo] { + let capture_info_map = self.capture_info_map.borrow(); + match capture_info_map.get().find(&expr.id) { Some(&caps) => caps, None => { self.tcx.sess.span_bug(expr.span, "no registered caps"); @@ -341,8 +349,9 @@ impl IrMaps { } } - pub fn lnk(&mut self, ln: LiveNode) -> LiveNodeKind { - self.lnks[*ln] + pub fn lnk(&self, ln: LiveNode) -> LiveNodeKind { + let lnks = self.lnks.borrow(); + lnks.get()[*ln] } } @@ -367,14 +376,12 @@ fn visit_fn(v: &mut LivenessVisitor, body: P, sp: Span, id: NodeId, - this: @mut IrMaps) { + this: @IrMaps) { debug!("visit_fn: id={}", id); let _i = ::util::common::indenter(); // swap in a new set of IR maps for this function body: - let fn_maps = @mut IrMaps(this.tcx, - this.method_map, - this.capture_map); + let fn_maps = @IrMaps(this.tcx, this.method_map, this.capture_map); unsafe { debug!("creating fn_maps: {}", transmute::<&IrMaps, *IrMaps>(fn_maps)); @@ -428,7 +435,7 @@ fn visit_fn(v: &mut LivenessVisitor, lsets.warn_about_unused_args(decl, entry_ln); } -fn visit_local(v: &mut LivenessVisitor, local: @Local, this: @mut IrMaps) { +fn visit_local(v: &mut LivenessVisitor, local: @Local, this: @IrMaps) { let def_map = this.tcx.def_map; pat_util::pat_bindings(def_map, local.pat, |bm, p_id, sp, path| { debug!("adding local variable {}", p_id); @@ -452,7 +459,7 @@ fn visit_local(v: &mut LivenessVisitor, local: @Local, this: @mut IrMaps) { visit::walk_local(v, local, this); } -fn visit_arm(v: &mut LivenessVisitor, arm: &Arm, this: @mut IrMaps) { +fn visit_arm(v: &mut LivenessVisitor, arm: &Arm, this: @IrMaps) { let def_map = this.tcx.def_map; for pat in arm.pats.iter() { pat_util::pat_bindings(def_map, *pat, |bm, p_id, sp, path| { @@ -475,11 +482,12 @@ fn visit_arm(v: &mut LivenessVisitor, arm: &Arm, this: @mut IrMaps) { visit::walk_arm(v, arm, this); } -fn visit_expr(v: &mut LivenessVisitor, expr: @Expr, this: @mut IrMaps) { +fn visit_expr(v: &mut LivenessVisitor, expr: @Expr, this: @IrMaps) { match expr.node { // live nodes required for uses or definitions of variables: ExprPath(_) | ExprSelf => { - let def = this.tcx.def_map.get_copy(&expr.id); + let def_map = this.tcx.def_map.borrow(); + let def = def_map.get().get_copy(&expr.id); debug!("expr {}: path that leads to {:?}", expr.id, def); if moves::moved_variable_node_id_from_def(def).is_some() { this.add_live_node_for_node(expr.id, ExprNode(expr.span)); @@ -495,7 +503,8 @@ fn visit_expr(v: &mut LivenessVisitor, expr: @Expr, this: @mut IrMaps) { // being the location that the variable is used. This results // in better error messages than just pointing at the closure // construction site. - let cvs = this.capture_map.get(&expr.id); + let capture_map = this.capture_map.borrow(); + let cvs = capture_map.get().get(&expr.id); let mut call_caps = ~[]; for cv in cvs.iter() { match moves::moved_variable_node_id_from_def(cv.def) { @@ -576,17 +585,17 @@ static ACC_READ: uint = 1u; static ACC_WRITE: uint = 2u; static ACC_USE: uint = 4u; -type LiveNodeMap = @mut HashMap; +type LiveNodeMap = @RefCell>; pub struct Liveness { tcx: ty::ctxt, - ir: @mut IrMaps, + ir: @IrMaps, s: Specials, - successors: @mut ~[LiveNode], - users: @mut ~[Users], + successors: @RefCell<~[LiveNode]>, + users: @RefCell<~[Users]>, // The list of node IDs for the nested loop scopes // we're in. - loop_scope: @mut ~[NodeId], + loop_scope: @RefCell<~[NodeId]>, // mappings from loop node ID to LiveNode // ("break" label should map to loop node ID, // it probably doesn't now) @@ -594,24 +603,27 @@ pub struct Liveness { cont_ln: LiveNodeMap } -fn Liveness(ir: @mut IrMaps, specials: Specials) -> Liveness { +fn Liveness(ir: @IrMaps, specials: Specials) -> Liveness { Liveness { ir: ir, tcx: ir.tcx, s: specials, - successors: @mut vec::from_elem(ir.num_live_nodes, invalid_node()), - users: @mut vec::from_elem(ir.num_live_nodes * ir.num_vars, - invalid_users()), - loop_scope: @mut ~[], - break_ln: @mut HashMap::new(), - cont_ln: @mut HashMap::new() + successors: @RefCell::new(vec::from_elem(ir.num_live_nodes.get(), + invalid_node())), + users: @RefCell::new(vec::from_elem(ir.num_live_nodes.get() * + ir.num_vars.get(), + invalid_users())), + loop_scope: @RefCell::new(~[]), + break_ln: @RefCell::new(HashMap::new()), + cont_ln: @RefCell::new(HashMap::new()), } } impl Liveness { pub fn live_node(&self, node_id: NodeId, span: Span) -> LiveNode { - let ir: &mut IrMaps = self.ir; - match ir.live_node_map.find(&node_id) { + let ir: &IrMaps = self.ir; + let live_node_map = ir.live_node_map.borrow(); + match live_node_map.get().find(&node_id) { Some(&ln) => ln, None => { // This must be a mismatch between the ir_map construction @@ -668,13 +680,14 @@ impl Liveness { } pub fn idx(&self, ln: LiveNode, var: Variable) -> uint { - *ln * self.ir.num_vars + *var + *ln * self.ir.num_vars.get() + *var } pub fn live_on_entry(&self, ln: LiveNode, var: Variable) -> Option { assert!(ln.is_valid()); - let reader = self.users[self.idx(ln, var)].reader; + let users = self.users.borrow(); + let reader = users.get()[self.idx(ln, var)].reader; if reader.is_valid() {Some(self.ir.lnk(reader))} else {None} } @@ -683,24 +696,34 @@ impl Liveness { */ pub fn live_on_exit(&self, ln: LiveNode, var: Variable) -> Option { - self.live_on_entry(self.successors[*ln], var) + let successor = { + let successors = self.successors.borrow(); + successors.get()[*ln] + }; + self.live_on_entry(successor, var) } pub fn used_on_entry(&self, ln: LiveNode, var: Variable) -> bool { assert!(ln.is_valid()); - self.users[self.idx(ln, var)].used + let users = self.users.borrow(); + users.get()[self.idx(ln, var)].used } pub fn assigned_on_entry(&self, ln: LiveNode, var: Variable) -> Option { assert!(ln.is_valid()); - let writer = self.users[self.idx(ln, var)].writer; + let users = self.users.borrow(); + let writer = users.get()[self.idx(ln, var)].writer; if writer.is_valid() {Some(self.ir.lnk(writer))} else {None} } pub fn assigned_on_exit(&self, ln: LiveNode, var: Variable) -> Option { - self.assigned_on_entry(self.successors[*ln], var) + let successor = { + let successors = self.successors.borrow(); + successors.get()[*ln] + }; + self.assigned_on_entry(successor, var) } pub fn indices2(&self, @@ -709,7 +732,7 @@ impl Liveness { op: |uint, uint|) { let node_base_idx = self.idx(ln, Variable(0u)); let succ_base_idx = self.idx(succ_ln, Variable(0u)); - for var_idx in range(0u, self.ir.num_vars) { + for var_idx in range(0u, self.ir.num_vars.get()) { op(node_base_idx + var_idx, succ_base_idx + var_idx); } } @@ -719,7 +742,7 @@ impl Liveness { ln: LiveNode, test: |uint| -> LiveNode) { let node_base_idx = self.idx(ln, Variable(0)); - for var_idx in range(0u, self.ir.num_vars) { + for var_idx in range(0u, self.ir.num_vars.get()) { let idx = node_base_idx + var_idx; if test(idx).is_valid() { write!(wr, " {}", Variable(var_idx).to_str()); @@ -733,17 +756,21 @@ impl Liveness { sp: Span) -> NodeId { match opt_label { - Some(_) => // Refers to a labeled loop. Use the results of resolve - // to find with one - match self.tcx.def_map.find(&id) { + Some(_) => { + // Refers to a labeled loop. Use the results of resolve + // to find with one + let def_map = self.tcx.def_map.borrow(); + match def_map.get().find(&id) { Some(&DefLabel(loop_id)) => loop_id, _ => self.tcx.sess.span_bug(sp, "Label on break/loop \ doesn't refer to a loop") - }, + } + } None => { // Vanilla 'break' or 'loop', so use the enclosing // loop scope - if self.loop_scope.len() == 0 { + let loop_scope = self.loop_scope.borrow(); + if loop_scope.get().len() == 0 { self.tcx.sess.span_bug(sp, "break outside loop"); } else { // FIXME(#5275): this shouldn't have to be a method... @@ -754,23 +781,37 @@ impl Liveness { } pub fn last_loop_scope(&self) -> NodeId { - let loop_scope = &mut *self.loop_scope; - *loop_scope.last() + let loop_scope = self.loop_scope.borrow(); + *loop_scope.get().last() } pub fn ln_str(&self, ln: LiveNode) -> ~str { str::from_utf8_owned(io::mem::with_mem_writer(|wr| { let wr = wr as &mut io::Writer; - write!(wr, "[ln({}) of kind {:?} reads", *ln, self.ir.lnks[*ln]); - self.write_vars(wr, ln, |idx| self.users[idx].reader ); + { + let lnks = self.ir.lnks.borrow(); + write!(wr, + "[ln({}) of kind {:?} reads", + *ln, + lnks.get()[*ln]); + } + let users = self.users.borrow(); + self.write_vars(wr, ln, |idx| users.get()[idx].reader); write!(wr, " writes"); - self.write_vars(wr, ln, |idx| self.users[idx].writer ); - write!(wr, " precedes {}]", self.successors[*ln].to_str()); + self.write_vars(wr, ln, |idx| users.get()[idx].writer); + let successor = { + let successors = self.successors.borrow(); + successors.get()[*ln] + }; + write!(wr, " precedes {}]", successor.to_str()); })) } pub fn init_empty(&self, ln: LiveNode, succ_ln: LiveNode) { - self.successors[*ln] = succ_ln; + { + let mut successors = self.successors.borrow_mut(); + successors.get()[*ln] = succ_ln; + } // It is not necessary to initialize the // values to empty because this is the value @@ -784,9 +825,14 @@ impl Liveness { pub fn init_from_succ(&self, ln: LiveNode, succ_ln: LiveNode) { // more efficient version of init_empty() / merge_from_succ() - self.successors[*ln] = succ_ln; + { + let mut successors = self.successors.borrow_mut(); + successors.get()[*ln] = succ_ln; + } + self.indices2(ln, succ_ln, |idx, succ_idx| { - self.users[idx] = self.users[succ_idx] + let mut users = self.users.borrow_mut(); + users.get()[idx] = users.get()[succ_idx] }); debug!("init_from_succ(ln={}, succ={})", self.ln_str(ln), self.ln_str(succ_ln)); @@ -801,13 +847,13 @@ impl Liveness { let mut changed = false; self.indices2(ln, succ_ln, |idx, succ_idx| { - let users = &mut *self.users; - changed |= copy_if_invalid(users[succ_idx].reader, - &mut users[idx].reader); - changed |= copy_if_invalid(users[succ_idx].writer, - &mut users[idx].writer); - if users[succ_idx].used && !users[idx].used { - users[idx].used = true; + let mut users = self.users.borrow_mut(); + changed |= copy_if_invalid(users.get()[succ_idx].reader, + &mut users.get()[idx].reader); + changed |= copy_if_invalid(users.get()[succ_idx].writer, + &mut users.get()[idx].writer); + if users.get()[succ_idx].used && !users.get()[idx].used { + users.get()[idx].used = true; changed = true; } }); @@ -832,8 +878,9 @@ impl Liveness { // this) so we just clear out all the data. pub fn define(&self, writer: LiveNode, var: Variable) { let idx = self.idx(writer, var); - self.users[idx].reader = invalid_node(); - self.users[idx].writer = invalid_node(); + let mut users = self.users.borrow_mut(); + users.get()[idx].reader = invalid_node(); + users.get()[idx].writer = invalid_node(); debug!("{} defines {} (idx={}): {}", writer.to_str(), var.to_str(), idx, self.ln_str(writer)); @@ -842,8 +889,8 @@ impl Liveness { // Either read, write, or both depending on the acc bitset pub fn acc(&self, ln: LiveNode, var: Variable, acc: uint) { let idx = self.idx(ln, var); - let users = &mut *self.users; - let user = &mut users[idx]; + let mut users = self.users.borrow_mut(); + let user = &mut users.get()[idx]; if (acc & ACC_WRITE) != 0 { user.reader = invalid_node(); @@ -881,7 +928,7 @@ impl Liveness { // hack to skip the loop unless debug! is enabled: debug!("^^ liveness computation results for body {} (entry={})", { - for ln_idx in range(0u, self.ir.num_live_nodes) { + for ln_idx in range(0u, self.ir.num_live_nodes.get()) { debug!("{}", self.ln_str(LiveNode(ln_idx))); } body.id @@ -1090,7 +1137,8 @@ impl Liveness { // Now that we know the label we're going to, // look it up in the break loop nodes table - match self.break_ln.find(&sc) { + let break_ln = self.break_ln.borrow(); + match break_ln.get().find(&sc) { Some(&b) => b, None => self.tcx.sess.span_bug(expr.span, "Break to unknown label") @@ -1104,7 +1152,8 @@ impl Liveness { // Now that we know the label we're going to, // look it up in the continue loop nodes table - match self.cont_ln.find(&sc) { + let cont_ln = self.cont_ln.borrow(); + match cont_ln.get().find(&sc) { Some(&b) => b, None => self.tcx.sess.span_bug(expr.span, "Loop to unknown label") @@ -1299,7 +1348,8 @@ impl Liveness { pub fn access_path(&self, expr: &Expr, succ: LiveNode, acc: uint) -> LiveNode { - let def = self.tcx.def_map.get_copy(&expr.id); + let def_map = self.tcx.def_map.borrow(); + let def = def_map.get().get_copy(&expr.id); match moves::moved_variable_node_id_from_def(def) { Some(nid) => { let ln = self.live_node(expr.id, expr.span); @@ -1380,12 +1430,22 @@ impl Liveness { cont_ln: LiveNode, f: || -> R) -> R { - debug!("with_loop_nodes: {} {}", loop_node_id, *break_ln); - self.loop_scope.push(loop_node_id); - self.break_ln.insert(loop_node_id, break_ln); - self.cont_ln.insert(loop_node_id, cont_ln); + debug!("with_loop_nodes: {} {}", loop_node_id, *break_ln); + { + let mut loop_scope = self.loop_scope.borrow_mut(); + loop_scope.get().push(loop_node_id); + } + { + let mut this_break_ln = self.break_ln.borrow_mut(); + let mut this_cont_ln = self.cont_ln.borrow_mut(); + this_break_ln.get().insert(loop_node_id, break_ln); + this_cont_ln.get().insert(loop_node_id, cont_ln); + } let r = f(); - self.loop_scope.pop(); + { + let mut loop_scope = self.loop_scope.borrow_mut(); + loop_scope.get().pop(); + } r } } @@ -1517,7 +1577,8 @@ impl Liveness { pub fn check_lvalue(&mut self, expr: @Expr) { match expr.node { ExprPath(_) => { - match self.tcx.def_map.get_copy(&expr.id) { + let def_map = self.tcx.def_map.borrow(); + match def_map.get().get_copy(&expr.id) { DefLocal(nid, _) => { // Assignment to an immutable variable or argument: only legal // if there is no later assignment. If this local is actually diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 0c44f58aeb406..b39ddecf8c4f6 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -340,7 +340,8 @@ impl mem_categorization_ctxt { } pub fn cat_expr(&self, expr: @ast::Expr) -> cmt { - match self.tcx.adjustments.find(&expr.id) { + let adjustments = self.tcx.adjustments.borrow(); + match adjustments.get().find(&expr.id) { None => { // No adjustments. self.cat_expr_unadjusted(expr) @@ -389,7 +390,8 @@ impl mem_categorization_ctxt { let expr_ty = self.expr_ty(expr); match expr.node { ast::ExprUnary(_, ast::UnDeref, e_base) => { - if self.method_map.contains_key(&expr.id) { + let method_map = self.method_map.borrow(); + if method_map.get().contains_key(&expr.id) { return self.cat_rvalue_node(expr, expr_ty); } @@ -400,14 +402,16 @@ impl mem_categorization_ctxt { ast::ExprField(base, f_name, _) => { // Method calls are now a special syntactic form, // so `a.b` should always be a field. - assert!(!self.method_map.contains_key(&expr.id)); + let method_map = self.method_map.borrow(); + assert!(!method_map.get().contains_key(&expr.id)); let base_cmt = self.cat_expr(base); self.cat_field(expr, base_cmt, f_name, self.expr_ty(expr)) } ast::ExprIndex(_, base, _) => { - if self.method_map.contains_key(&expr.id) { + let method_map = self.method_map.borrow(); + if method_map.get().contains_key(&expr.id) { return self.cat_rvalue_node(expr, expr_ty); } @@ -416,7 +420,8 @@ impl mem_categorization_ctxt { } ast::ExprPath(_) | ast::ExprSelf => { - let def = self.tcx.def_map.get_copy(&expr.id); + let def_map = self.tcx.def_map.borrow(); + let def = def_map.get().get_copy(&expr.id); self.cat_def(expr.id, expr.span, expr_ty, def) } @@ -884,7 +889,8 @@ impl mem_categorization_ctxt { // variant(..) } ast::PatEnum(_, Some(ref subpats)) => { - match self.tcx.def_map.find(&pat.id) { + let def_map = self.tcx.def_map.borrow(); + match def_map.get().find(&pat.id) { Some(&ast::DefVariant(enum_did, _, _)) => { // variant(x, y, z) @@ -1070,7 +1076,8 @@ pub fn field_mutbl(tcx: ty::ctxt, } } ty::ty_enum(..) => { - match tcx.def_map.get_copy(&node_id) { + let def_map = tcx.def_map.borrow(); + match def_map.get().get_copy(&node_id) { ast::DefVariant(_, variant_id, _) => { let r = ty::lookup_struct_fields(tcx, variant_id); for fld in r.iter() { diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index c9911480199e8..f4f0c5c8073d5 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -130,13 +130,14 @@ and so on. use middle::pat_util::{pat_bindings}; use middle::freevars; use middle::ty; -use middle::typeck::{method_map}; +use middle::typeck::method_map; use util::ppaux; use util::ppaux::Repr; use util::common::indenter; use util::ppaux::UserString; use std::at_vec; +use std::cell::RefCell; use std::hashmap::{HashSet, HashMap}; use syntax::ast::*; use syntax::ast_util; @@ -158,9 +159,9 @@ pub struct CaptureVar { mode: CaptureMode // How variable is being accessed } -pub type CaptureMap = @mut HashMap; +pub type CaptureMap = @RefCell>; -pub type MovesMap = @mut HashSet; +pub type MovesMap = @RefCell>; /** * Set of variable node-ids that are moved. @@ -168,7 +169,7 @@ pub type MovesMap = @mut HashSet; * Note: The `VariableMovesMap` stores expression ids that * are moves, whereas this set stores the ids of the variables * that are moved at some point */ -pub type MovedVariablesSet = @mut HashSet; +pub type MovedVariablesSet = @RefCell>; /** See the section Output on the module comment for explanation. */ #[deriving(Clone)] @@ -214,9 +215,9 @@ pub fn compute_moves(tcx: ty::ctxt, tcx: tcx, method_map: method_map, move_maps: MoveMaps { - moves_map: @mut HashSet::new(), - capture_map: @mut HashMap::new(), - moved_variables_set: @mut HashSet::new() + moves_map: @RefCell::new(HashSet::new()), + capture_map: @RefCell::new(HashMap::new()), + moved_variables_set: @RefCell::new(HashSet::new()) } }; let visit_cx = &mut visit_cx; @@ -282,7 +283,10 @@ impl VisitContext { let expr_ty = ty::expr_ty_adjusted(self.tcx, expr); if ty::type_moves_by_default(self.tcx, expr_ty) { - self.move_maps.moves_map.insert(expr.id); + { + let mut moves_map = self.move_maps.moves_map.borrow_mut(); + moves_map.get().insert(expr.id); + } self.use_expr(expr, Move); } else { self.use_expr(expr, Read); @@ -321,11 +325,14 @@ impl VisitContext { // `expr_mode` refers to the post-adjustment value. If one of // those adjustments is to take a reference, then it's only // reading the underlying expression, not moving it. - let comp_mode = match self.tcx.adjustments.find(&expr.id) { - Some(&@ty::AutoDerefRef( - ty::AutoDerefRef { - autoref: Some(_), ..})) => Read, - _ => expr_mode + let comp_mode = { + let adjustments = self.tcx.adjustments.borrow(); + match adjustments.get().find(&expr.id) { + Some(&@ty::AutoDerefRef( + ty::AutoDerefRef { + autoref: Some(_), ..})) => Read, + _ => expr_mode + } }; debug!("comp_mode = {:?}", comp_mode); @@ -334,10 +341,15 @@ impl VisitContext { ExprPath(..) | ExprSelf => { match comp_mode { Move => { - let def = self.tcx.def_map.get_copy(&expr.id); + let def_map = self.tcx.def_map.borrow(); + let def = def_map.get().get_copy(&expr.id); let r = moved_variable_node_id_from_def(def); for &id in r.iter() { - self.move_maps.moved_variables_set.insert(id); + let mut moved_variables_set = + self.move_maps + .moved_variables_set + .borrow_mut(); + moved_variables_set.get().insert(id); } } Read => {} @@ -384,7 +396,12 @@ impl VisitContext { // closures should be noncopyable, they shouldn't move by default; // calling a closure should only consume it if it's once. if mode == Move { - self.move_maps.moves_map.insert(callee.id); + { + let mut moves_map = self.move_maps + .moves_map + .borrow_mut(); + moves_map.get().insert(callee.id); + } } self.use_expr(callee, mode); self.use_fn_args(callee.id, *args); @@ -561,7 +578,12 @@ impl VisitContext { self.use_pat(a.pat); } let cap_vars = self.compute_captures(expr.id); - self.move_maps.capture_map.insert(expr.id, cap_vars); + { + let mut capture_map = self.move_maps + .capture_map + .borrow_mut(); + capture_map.get().insert(expr.id, cap_vars); + } self.consume_block(body); } @@ -582,7 +604,8 @@ impl VisitContext { receiver_expr: @Expr, arg_exprs: &[@Expr]) -> bool { - if !self.method_map.contains_key(&expr.id) { + let method_map = self.method_map.borrow(); + if !method_map.get().contains_key(&expr.id) { return false; } @@ -633,7 +656,10 @@ impl VisitContext { id, bm, binding_moves); if binding_moves { - self.move_maps.moves_map.insert(id); + { + let mut moves_map = self.move_maps.moves_map.borrow_mut(); + moves_map.get().insert(id); + } } }) } diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index 9ef7a5f147db5..85217a7d55ece 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -31,7 +31,8 @@ pub fn pat_id_map(dm: resolve::DefMap, pat: &Pat) -> PatIdMap { pub fn pat_is_variant_or_struct(dm: resolve::DefMap, pat: &Pat) -> bool { match pat.node { PatEnum(_, _) | PatIdent(_, _, None) | PatStruct(..) => { - match dm.find(&pat.id) { + let dm = dm.borrow(); + match dm.get().find(&pat.id) { Some(&DefVariant(..)) | Some(&DefStruct(..)) => true, _ => false } @@ -43,7 +44,8 @@ pub fn pat_is_variant_or_struct(dm: resolve::DefMap, pat: &Pat) -> bool { pub fn pat_is_const(dm: resolve::DefMap, pat: &Pat) -> bool { match pat.node { PatIdent(_, _, None) | PatEnum(..) => { - match dm.find(&pat.id) { + let dm = dm.borrow(); + match dm.get().find(&pat.id) { Some(&DefStatic(_, false)) => true, _ => false } diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index ded8d11786a2e..707446a78fe21 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -220,7 +220,8 @@ impl<'a> Visitor<()> for EmbargoVisitor<'a> { ast::item_impl(_, _, ref ty, ref methods) => { let public_ty = match ty.node { ast::ty_path(_, _, id) => { - match self.tcx.def_map.get_copy(&id) { + let def_map = self.tcx.def_map.borrow(); + match def_map.get().get_copy(&id) { ast::DefPrimTy(..) => true, def => { let did = def_id_of_def(def); @@ -293,8 +294,9 @@ impl<'a> Visitor<()> for EmbargoVisitor<'a> { // This code is here instead of in visit_item so that the // crate module gets processed as well. if self.prev_exported { - assert!(self.exp_map2.contains_key(&id), "wut {:?}", id); - for export in self.exp_map2.get(&id).iter() { + let exp_map2 = self.exp_map2.borrow(); + assert!(exp_map2.get().contains_key(&id), "wut {:?}", id); + for export in exp_map2.get().get(&id).iter() { if is_local(export.def_id) && export.reexport { self.reexports.insert(export.def_id.node); } @@ -340,7 +342,9 @@ impl<'a> PrivacyVisitor<'a> { return Allowable; } debug!("privacy - is {:?} a public method", did); - return match self.tcx.methods.find(&did) { + + let methods = self.tcx.methods.borrow(); + return match methods.get().find(&did) { Some(meth) => { debug!("privacy - well at least it's a method: {:?}", meth); match meth.container { @@ -556,7 +560,8 @@ impl<'a> PrivacyVisitor<'a> { // Checks that a path is in scope. fn check_path(&mut self, span: Span, path_id: ast::NodeId, path: &ast::Path) { debug!("privacy - path {}", self.nodestr(path_id)); - let def = self.tcx.def_map.get_copy(&path_id); + let def_map = self.tcx.def_map.borrow(); + let def = def_map.get().get_copy(&path_id); let ck = |tyname: &str| { let origdid = def_id_of_def(def); match *self.last_private_map.get(&path_id) { @@ -569,7 +574,8 @@ impl<'a> PrivacyVisitor<'a> { } } }; - match self.tcx.def_map.get_copy(&path_id) { + let def_map = self.tcx.def_map.borrow(); + match def_map.get().get_copy(&path_id) { ast::DefStaticMethod(..) => ck("static method"), ast::DefFn(..) => ck("function"), ast::DefStatic(..) => ck("static"), @@ -619,7 +625,8 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> { ast::ExprField(base, ident, _) => { // Method calls are now a special syntactic form, // so `a.b` should always be a field. - assert!(!self.method_map.contains_key(&expr.id)); + let method_map = self.method_map.borrow(); + assert!(!method_map.get().contains_key(&expr.id)); // With type_autoderef, make sure we don't // allow pointers to violate privacy @@ -638,7 +645,8 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> { ty::expr_ty(self.tcx, base)); match ty::get(t).sty { ty::ty_enum(_, _) | ty::ty_struct(_, _) => { - let entry = match self.method_map.find(&expr.id) { + let method_map = self.method_map.borrow(); + let entry = match method_map.get().find(&expr.id) { None => { self.tcx.sess.span_bug(expr.span, "method call not in \ @@ -660,7 +668,8 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> { } } ty::ty_enum(_, _) => { - match self.tcx.def_map.get_copy(&expr.id) { + let def_map = self.tcx.def_map.borrow(); + match def_map.get().get_copy(&expr.id) { ast::DefVariant(_, variant_id, _) => { for field in fields.iter() { self.check_field(expr.span, variant_id, @@ -745,7 +754,8 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> { } } ty::ty_enum(_, _) => { - match self.tcx.def_map.find(&pattern.id) { + let def_map = self.tcx.def_map.borrow(); + match def_map.get().find(&pattern.id) { Some(&ast::DefVariant(_, variant_id, _)) => { for field in fields.iter() { self.check_field(pattern.span, variant_id, diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index d665d279a1759..bbf366c0b061f 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -19,6 +19,7 @@ use middle::ty; use middle::typeck; use middle::privacy; +use std::cell::RefCell; use std::hashmap::HashSet; use syntax::ast; use syntax::ast_map; @@ -84,17 +85,17 @@ struct ReachableContext { // methods they've been resolved to. method_map: typeck::method_map, // The set of items which must be exported in the linkage sense. - reachable_symbols: @mut HashSet, + reachable_symbols: @RefCell>, // A worklist of item IDs. Each item ID in this worklist will be inlined // and will be scanned for further references. - worklist: @mut ~[ast::NodeId], + worklist: @RefCell<~[ast::NodeId]>, } struct MarkSymbolVisitor { - worklist: @mut ~[ast::NodeId], + worklist: @RefCell<~[ast::NodeId]>, method_map: typeck::method_map, tcx: ty::ctxt, - reachable_symbols: @mut HashSet, + reachable_symbols: @RefCell>, } impl Visitor<()> for MarkSymbolVisitor { @@ -103,7 +104,8 @@ impl Visitor<()> for MarkSymbolVisitor { match expr.node { ast::ExprPath(_) => { - let def = match self.tcx.def_map.find(&expr.id) { + let def_map = self.tcx.def_map.borrow(); + let def = match def_map.get().find(&expr.id) { Some(&def) => def, None => { self.tcx.sess.span_bug(expr.span, @@ -115,7 +117,10 @@ impl Visitor<()> for MarkSymbolVisitor { if is_local(def_id) { if ReachableContext:: def_id_represents_local_inlined_item(self.tcx, def_id) { - self.worklist.push(def_id.node) + { + let mut worklist = self.worklist.borrow_mut(); + worklist.get().push(def_id.node) + } } else { match def { // If this path leads to a static, then we may have @@ -123,20 +128,24 @@ impl Visitor<()> for MarkSymbolVisitor { // is indeed reachable (address_insignificant // statics are *never* reachable). ast::DefStatic(..) => { - self.worklist.push(def_id.node); + let mut worklist = self.worklist.borrow_mut(); + worklist.get().push(def_id.node); } // If this wasn't a static, then this destination is // surely reachable. _ => { - self.reachable_symbols.insert(def_id.node); + let mut reachable_symbols = + self.reachable_symbols.borrow_mut(); + reachable_symbols.get().insert(def_id.node); } } } } } ast::ExprMethodCall(..) => { - match self.method_map.find(&expr.id) { + let method_map = self.method_map.borrow(); + match method_map.get().find(&expr.id) { Some(&typeck::method_map_entry { origin: typeck::method_static(def_id), .. @@ -146,9 +155,17 @@ impl Visitor<()> for MarkSymbolVisitor { def_id_represents_local_inlined_item( self.tcx, def_id) { - self.worklist.push(def_id.node) + { + let mut worklist = self.worklist + .borrow_mut(); + worklist.get().push(def_id.node) } - self.reachable_symbols.insert(def_id.node); + } + { + let mut reachable_symbols = + self.reachable_symbols.borrow_mut(); + reachable_symbols.get().insert(def_id.node); + } } } Some(_) => {} @@ -177,8 +194,8 @@ impl ReachableContext { ReachableContext { tcx: tcx, method_map: method_map, - reachable_symbols: @mut HashSet::new(), - worklist: @mut ~[], + reachable_symbols: @RefCell::new(HashSet::new()), + worklist: @RefCell::new(~[]), } } @@ -257,11 +274,19 @@ impl ReachableContext { fn propagate(&self) { let mut visitor = self.init_visitor(); let mut scanned = HashSet::new(); - while self.worklist.len() > 0 { - let search_item = self.worklist.pop(); - if scanned.contains(&search_item) { - continue - } + loop { + let search_item = { + let mut worklist = self.worklist.borrow_mut(); + if worklist.get().len() == 0 { + break + } + let search_item = worklist.get().pop(); + if scanned.contains(&search_item) { + continue + } + search_item + }; + scanned.insert(search_item); match self.tcx.items.find(&search_item) { Some(item) => self.propagate_node(item, search_item, @@ -279,7 +304,7 @@ impl ReachableContext { fn propagate_node(&self, node: &ast_map::ast_node, search_item: ast::NodeId, visitor: &mut MarkSymbolVisitor) { - if !*self.tcx.sess.building_library { + if !self.tcx.sess.building_library.get() { // If we are building an executable, then there's no need to flag // anything as external except for `extern fn` types. These // functions may still participate in some form of native interface, @@ -289,7 +314,9 @@ impl ReachableContext { ast_map::node_item(item, _) => { match item.node { ast::item_fn(_, ast::extern_fn, _, _, _) => { - self.reachable_symbols.insert(search_item); + let mut reachable_symbols = + self.reachable_symbols.borrow_mut(); + reachable_symbols.get().insert(search_item); } _ => {} } @@ -301,7 +328,8 @@ impl ReachableContext { // continue to participate in linkage after this product is // produced. In this case, we traverse the ast node, recursing on // all reachable nodes from this one. - self.reachable_symbols.insert(search_item); + let mut reachable_symbols = self.reachable_symbols.borrow_mut(); + reachable_symbols.get().insert(search_item); } match *node { @@ -318,7 +346,9 @@ impl ReachableContext { ast::item_static(..) => { if attr::contains_name(item.attrs, "address_insignificant") { - self.reachable_symbols.remove(&search_item); + let mut reachable_symbols = + self.reachable_symbols.borrow_mut(); + reachable_symbols.get().remove(&search_item); } } @@ -374,9 +404,12 @@ impl ReachableContext { // this properly would result in the necessity of computing *type* // reachability, which might result in a compile time loss. fn mark_destructors_reachable(&self) { - for (_, destructor_def_id) in self.tcx.destructor_for_type.iter() { + let destructor_for_type = self.tcx.destructor_for_type.borrow(); + for (_, destructor_def_id) in destructor_for_type.get().iter() { if destructor_def_id.crate == ast::LOCAL_CRATE { - self.reachable_symbols.insert(destructor_def_id.node); + let mut reachable_symbols = self.reachable_symbols + .borrow_mut(); + reachable_symbols.get().insert(destructor_def_id.node); } } } @@ -385,13 +418,14 @@ impl ReachableContext { pub fn find_reachable(tcx: ty::ctxt, method_map: typeck::method_map, exported_items: &privacy::ExportedItems) - -> @mut HashSet { + -> @RefCell> { let reachable_context = ReachableContext::new(tcx, method_map); // Step 1: Seed the worklist with all nodes which were found to be public as // a result of the privacy pass for &id in exported_items.iter() { - reachable_context.worklist.push(id); + let mut worklist = reachable_context.worklist.borrow_mut(); + worklist.get().push(id); } // Step 2: Mark all symbols that the symbols on the worklist touch. diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 32d86eb962960..3f8f2f35100d7 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -25,6 +25,7 @@ use driver::session::Session; use middle::ty::{FreeRegion}; use middle::ty; +use std::cell::RefCell; use std::hashmap::{HashMap, HashSet}; use syntax::codemap::Span; use syntax::{ast, visit}; @@ -50,9 +51,9 @@ The region maps encode information about region relationships. necessarily how I think things ought to work */ pub struct RegionMaps { - priv scope_map: HashMap, - priv free_region_map: HashMap, - priv cleanup_scopes: HashSet + priv scope_map: RefCell>, + priv free_region_map: RefCell>, + priv cleanup_scopes: RefCell>, } #[deriving(Clone)] @@ -68,13 +69,14 @@ struct RegionResolutionVisitor { sess: Session, // Generated maps: - region_maps: @mut RegionMaps, + region_maps: @RegionMaps, } impl RegionMaps { - pub fn relate_free_regions(&mut self, sub: FreeRegion, sup: FreeRegion) { - match self.free_region_map.find_mut(&sub) { + pub fn relate_free_regions(&self, sub: FreeRegion, sup: FreeRegion) { + let mut free_region_map = self.free_region_map.borrow_mut(); + match free_region_map.get().find_mut(&sub) { Some(sups) => { if !sups.iter().any(|x| x == &sup) { sups.push(sup); @@ -86,49 +88,55 @@ impl RegionMaps { debug!("relate_free_regions(sub={:?}, sup={:?})", sub, sup); - self.free_region_map.insert(sub, ~[sup]); + free_region_map.get().insert(sub, ~[sup]); } - pub fn record_parent(&mut self, sub: ast::NodeId, sup: ast::NodeId) { + pub fn record_parent(&self, sub: ast::NodeId, sup: ast::NodeId) { debug!("record_parent(sub={:?}, sup={:?})", sub, sup); assert!(sub != sup); - self.scope_map.insert(sub, sup); + let mut scope_map = self.scope_map.borrow_mut(); + scope_map.get().insert(sub, sup); } - pub fn record_cleanup_scope(&mut self, scope_id: ast::NodeId) { + pub fn record_cleanup_scope(&self, scope_id: ast::NodeId) { //! Records that a scope is a CLEANUP SCOPE. This is invoked //! from within regionck. We wait until regionck because we do //! not know which operators are overloaded until that point, //! and only overloaded operators result in cleanup scopes. - self.cleanup_scopes.insert(scope_id); + let mut cleanup_scopes = self.cleanup_scopes.borrow_mut(); + cleanup_scopes.get().insert(scope_id); } pub fn opt_encl_scope(&self, id: ast::NodeId) -> Option { //! Returns the narrowest scope that encloses `id`, if any. - self.scope_map.find(&id).map(|x| *x) + let scope_map = self.scope_map.borrow(); + scope_map.get().find(&id).map(|x| *x) } pub fn encl_scope(&self, id: ast::NodeId) -> ast::NodeId { //! Returns the narrowest scope that encloses `id`, if any. - match self.scope_map.find(&id) { + let scope_map = self.scope_map.borrow(); + match scope_map.get().find(&id) { Some(&r) => r, None => { fail!("No enclosing scope for id {:?}", id); } } } pub fn is_cleanup_scope(&self, scope_id: ast::NodeId) -> bool { - self.cleanup_scopes.contains(&scope_id) + let cleanup_scopes = self.cleanup_scopes.borrow(); + cleanup_scopes.get().contains(&scope_id) } pub fn cleanup_scope(&self, expr_id: ast::NodeId) -> ast::NodeId { //! Returns the scope when temps in expr will be cleaned up let mut id = self.encl_scope(expr_id); - while !self.cleanup_scopes.contains(&id) { + let cleanup_scopes = self.cleanup_scopes.borrow(); + while !cleanup_scopes.get().contains(&id) { id = self.encl_scope(id); } return id; @@ -157,7 +165,8 @@ impl RegionMaps { let mut s = subscope; while superscope != s { - match self.scope_map.find(&s) { + let scope_map = self.scope_map.borrow(); + match scope_map.get().find(&s) { None => { debug!("is_subscope_of({:?}, {:?}, s={:?})=false", subscope, superscope, s); @@ -193,7 +202,8 @@ impl RegionMaps { let mut queue = ~[sub]; let mut i = 0; while i < queue.len() { - match self.free_region_map.find(&queue[i]) { + let free_region_map = self.free_region_map.borrow(); + match free_region_map.get().find(&queue[i]) { Some(parents) => { for parent in parents.iter() { if *parent == sup { @@ -298,7 +308,8 @@ impl RegionMaps { let mut result = ~[scope]; let mut scope = scope; loop { - match this.scope_map.find(&scope) { + let scope_map = this.scope_map.borrow(); + match scope_map.get().find(&scope) { None => return result, Some(&superscope) => { result.push(superscope); @@ -493,13 +504,11 @@ impl Visitor for RegionResolutionVisitor { } } -pub fn resolve_crate(sess: Session, - crate: &ast::Crate) -> @mut RegionMaps -{ - let region_maps = @mut RegionMaps { - scope_map: HashMap::new(), - free_region_map: HashMap::new(), - cleanup_scopes: HashSet::new(), +pub fn resolve_crate(sess: Session, crate: &ast::Crate) -> @RegionMaps { + let region_maps = @RegionMaps { + scope_map: RefCell::new(HashMap::new()), + free_region_map: RefCell::new(HashMap::new()), + cleanup_scopes: RefCell::new(HashSet::new()), }; let cx = Context {parent: None, var_parent: None}; diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 1fb6e53d925e4..40934b985d346 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -29,12 +29,13 @@ use syntax::opt_vec::OptVec; use syntax::visit; use syntax::visit::Visitor; +use std::cell::{Cell, RefCell}; use std::uint; use std::hashmap::{HashMap, HashSet}; use std::util; // Definition mapping -pub type DefMap = @mut HashMap; +pub type DefMap = @RefCell>; struct binding_info { span: Span, @@ -45,11 +46,11 @@ struct binding_info { type BindingMap = HashMap; // Trait method resolution -pub type TraitMap = HashMap; +pub type TraitMap = HashMap>; // This is the replacement export map. It maps a module to all of the exports // within. -pub type ExportMap2 = @mut HashMap; +pub type ExportMap2 = @RefCell>; pub struct Export2 { name: @str, // The name of the target. @@ -112,7 +113,7 @@ enum NamespaceResult { UnboundResult, /// Means that resolve has determined that the name is bound in the Module /// argument, and specified by the NameBindings argument. - BoundResult(@mut Module, @mut NameBindings) + BoundResult(@Module, @NameBindings) } impl NamespaceResult { @@ -165,7 +166,7 @@ enum ImportDirectiveSubclass { /// The context that we thread through while building the reduced graph. #[deriving(Clone)] enum ReducedGraphParent { - ModuleReducedGraphParent(@mut Module) + ModuleReducedGraphParent(@Module) } enum ResolveResult { @@ -245,7 +246,7 @@ enum SearchThroughModulesFlag { enum ModulePrefixResult { NoPrefixFound, - PrefixFound(@mut Module, uint) + PrefixFound(@Module, uint) } #[deriving(Eq)] @@ -283,16 +284,16 @@ enum DuplicateCheckingMode { /// One local scope. struct Rib { - bindings: @mut HashMap, - self_binding: @mut Option, + bindings: RefCell>, + self_binding: RefCell>, kind: RibKind, } impl Rib { fn new(kind: RibKind) -> Rib { Rib { - bindings: @mut HashMap::new(), - self_binding: @mut None, + bindings: RefCell::new(HashMap::new()), + self_binding: RefCell::new(None), kind: kind } } @@ -325,15 +326,14 @@ impl ImportDirective { } /// The item that an import resolves to. +#[deriving(Clone)] struct Target { - target_module: @mut Module, - bindings: @mut NameBindings, + target_module: @Module, + bindings: @NameBindings, } impl Target { - fn new(target_module: @mut Module, - bindings: @mut NameBindings) - -> Target { + fn new(target_module: @Module, bindings: @NameBindings) -> Target { Target { target_module: target_module, bindings: bindings @@ -347,50 +347,50 @@ struct ImportResolution { /// should *not* be used whenever resolution is being performed, this is /// only looked at for glob imports statements currently. Privacy testing /// occurs during a later phase of compilation. - is_public: bool, + is_public: Cell, // The number of outstanding references to this name. When this reaches // zero, outside modules can count on the targets being correct. Before // then, all bets are off; future imports could override this name. - outstanding_references: uint, + outstanding_references: Cell, /// The value that this `use` directive names, if there is one. - value_target: Option, + value_target: RefCell>, /// The source node of the `use` directive leading to the value target /// being non-none - value_id: NodeId, + value_id: Cell, /// The type that this `use` directive names, if there is one. - type_target: Option, + type_target: RefCell>, /// The source node of the `use` directive leading to the type target /// being non-none - type_id: NodeId, + type_id: Cell, } impl ImportResolution { fn new(id: NodeId, is_public: bool) -> ImportResolution { ImportResolution { - type_id: id, - value_id: id, - outstanding_references: 0, - value_target: None, - type_target: None, - is_public: is_public, + type_id: Cell::new(id), + value_id: Cell::new(id), + outstanding_references: Cell::new(0), + value_target: RefCell::new(None), + type_target: RefCell::new(None), + is_public: Cell::new(is_public), } } fn target_for_namespace(&self, namespace: Namespace) -> Option { match namespace { - TypeNS => return self.type_target, - ValueNS => return self.value_target, + TypeNS => return self.type_target.get(), + ValueNS => return self.value_target.get(), } } fn id(&self, namespace: Namespace) -> NodeId { match namespace { - TypeNS => self.type_id, - ValueNS => self.value_id, + TypeNS => self.type_id.get(), + ValueNS => self.value_id.get(), } } } @@ -398,8 +398,8 @@ impl ImportResolution { /// The link from a module up to its nearest parent node. enum ParentLink { NoParentLink, - ModuleParentLink(@mut Module, Ident), - BlockParentLink(@mut Module, NodeId) + ModuleParentLink(@Module, Ident), + BlockParentLink(@Module, NodeId) } /// The type of module this is. @@ -415,16 +415,16 @@ enum ModuleKind { /// One node in the tree of modules. struct Module { parent_link: ParentLink, - def_id: Option, - kind: ModuleKind, + def_id: Cell>, + kind: Cell, is_public: bool, - children: @mut HashMap, - imports: @mut ~[@ImportDirective], + children: RefCell>, + imports: RefCell<~[@ImportDirective]>, // The external module children of this node that were declared with // `extern mod`. - external_module_children: @mut HashMap, + external_module_children: RefCell>, // The anonymous children of this node. Anonymous children are pseudo- // modules that are implicitly created around items contained within @@ -440,21 +440,21 @@ struct Module { // // There will be an anonymous module created around `g` with the ID of the // entry block for `f`. - anonymous_children: @mut HashMap, + anonymous_children: RefCell>, // The status of resolving each import in this module. - import_resolutions: @mut HashMap, + import_resolutions: RefCell>, // The number of unresolved globs that this module exports. - glob_count: uint, + glob_count: Cell, // The index of the import we're resolving. - resolved_import_count: uint, + resolved_import_count: Cell, // Whether this module is populated. If not populated, any attempt to // access the children must be preceded with a // `populate_module_if_necessary` call. - populated: bool, + populated: Cell, } impl Module { @@ -463,38 +463,40 @@ impl Module { kind: ModuleKind, external: bool, is_public: bool) - -> Module { + -> Module { Module { parent_link: parent_link, - def_id: def_id, - kind: kind, + def_id: Cell::new(def_id), + kind: Cell::new(kind), is_public: is_public, - children: @mut HashMap::new(), - imports: @mut ~[], - external_module_children: @mut HashMap::new(), - anonymous_children: @mut HashMap::new(), - import_resolutions: @mut HashMap::new(), - glob_count: 0, - resolved_import_count: 0, - populated: !external, + children: RefCell::new(HashMap::new()), + imports: RefCell::new(~[]), + external_module_children: RefCell::new(HashMap::new()), + anonymous_children: RefCell::new(HashMap::new()), + import_resolutions: RefCell::new(HashMap::new()), + glob_count: Cell::new(0), + resolved_import_count: Cell::new(0), + populated: Cell::new(!external), } } fn all_imports_resolved(&self) -> bool { - let imports = &mut *self.imports; - return imports.len() == self.resolved_import_count; + let mut imports = self.imports.borrow_mut(); + return imports.get().len() == self.resolved_import_count.get(); } } // Records a possibly-private type definition. +#[deriving(Clone)] struct TypeNsDef { is_public: bool, // see note in ImportResolution about how to use this - module_def: Option<@mut Module>, + module_def: Option<@Module>, type_def: Option, type_span: Option } // Records a possibly-private value definition. +#[deriving(Clone)] struct ValueNsDef { is_public: bool, // see note in ImportResolution about how to use this def: Def, @@ -504,8 +506,8 @@ struct ValueNsDef { // Records the definitions (at most one for each namespace) that a name is // bound to. struct NameBindings { - type_def: Option, //< Meaning in type namespace. - value_def: Option, //< Meaning in value namespace. + type_def: RefCell>, //< Meaning in type namespace. + value_def: RefCell>, //< Meaning in value namespace. } /// Ways in which a trait can be referenced @@ -517,7 +519,7 @@ enum TraitReferenceType { impl NameBindings { /// Creates a new module in this set of name bindings. - fn define_module(&mut self, + fn define_module(&self, parent_link: ParentLink, def_id: Option, kind: ModuleKind, @@ -525,100 +527,104 @@ impl NameBindings { is_public: bool, sp: Span) { // Merges the module with the existing type def or creates a new one. - let module_ = @mut Module::new(parent_link, def_id, kind, external, + let module_ = @Module::new(parent_link, def_id, kind, external, is_public); - match self.type_def { + match self.type_def.get() { None => { - self.type_def = Some(TypeNsDef { + self.type_def.set(Some(TypeNsDef { is_public: is_public, module_def: Some(module_), type_def: None, type_span: Some(sp) - }); + })); } Some(type_def) => { - self.type_def = Some(TypeNsDef { + self.type_def.set(Some(TypeNsDef { is_public: is_public, module_def: Some(module_), type_span: Some(sp), type_def: type_def.type_def - }); + })); } } } /// Sets the kind of the module, creating a new one if necessary. - fn set_module_kind(&mut self, + fn set_module_kind(&self, parent_link: ParentLink, def_id: Option, kind: ModuleKind, external: bool, is_public: bool, _sp: Span) { - match self.type_def { + match self.type_def.get() { None => { - let module = @mut Module::new(parent_link, def_id, kind, + let module = @Module::new(parent_link, def_id, kind, external, is_public); - self.type_def = Some(TypeNsDef { + self.type_def.set(Some(TypeNsDef { is_public: is_public, module_def: Some(module), type_def: None, type_span: None, - }) + })) } Some(type_def) => { match type_def.module_def { None => { - let module = @mut Module::new(parent_link, + let module = @Module::new(parent_link, def_id, kind, external, is_public); - self.type_def = Some(TypeNsDef { + self.type_def.set(Some(TypeNsDef { is_public: is_public, module_def: Some(module), type_def: type_def.type_def, type_span: None, - }) + })) } - Some(module_def) => module_def.kind = kind, + Some(module_def) => module_def.kind.set(kind), } } } } /// Records a type definition. - fn define_type(&mut self, def: Def, sp: Span, is_public: bool) { + fn define_type(&self, def: Def, sp: Span, is_public: bool) { // Merges the type with the existing type def or creates a new one. - match self.type_def { + match self.type_def.get() { None => { - self.type_def = Some(TypeNsDef { + self.type_def.set(Some(TypeNsDef { module_def: None, type_def: Some(def), type_span: Some(sp), is_public: is_public, - }); + })); } Some(type_def) => { - self.type_def = Some(TypeNsDef { + self.type_def.set(Some(TypeNsDef { type_def: Some(def), type_span: Some(sp), module_def: type_def.module_def, is_public: is_public, - }); + })); } } } /// Records a value definition. - fn define_value(&mut self, def: Def, sp: Span, is_public: bool) { - self.value_def = Some(ValueNsDef { def: def, value_span: Some(sp), - is_public: is_public }); + fn define_value(&self, def: Def, sp: Span, is_public: bool) { + self.value_def.set(Some(ValueNsDef { + def: def, + value_span: Some(sp), + is_public: is_public, + })); } /// Returns the module node if applicable. - fn get_module_if_available(&self) -> Option<@mut Module> { - match self.type_def { + fn get_module_if_available(&self) -> Option<@Module> { + let type_def = self.type_def.borrow(); + match *type_def.get() { Some(ref type_def) => (*type_def).module_def, None => None } @@ -628,7 +634,7 @@ impl NameBindings { * Returns the module node. Fails if this node does not have a module * definition. */ - fn get_module(&mut self) -> @mut Module { + fn get_module(&self) -> @Module { match self.get_module_if_available() { None => { fail!("get_module called on a node with no module \ @@ -640,17 +646,17 @@ impl NameBindings { fn defined_in_namespace(&self, namespace: Namespace) -> bool { match namespace { - TypeNS => return self.type_def.is_some(), - ValueNS => return self.value_def.is_some() + TypeNS => return self.type_def.get().is_some(), + ValueNS => return self.value_def.get().is_some() } } fn defined_in_public_namespace(&self, namespace: Namespace) -> bool { match namespace { - TypeNS => match self.type_def { + TypeNS => match self.type_def.get() { Some(def) => def.is_public, None => false }, - ValueNS => match self.value_def { + ValueNS => match self.value_def.get() { Some(def) => def.is_public, None => false } } @@ -659,15 +665,15 @@ impl NameBindings { fn def_for_namespace(&self, namespace: Namespace) -> Option { match namespace { TypeNS => { - match self.type_def { + match self.type_def.get() { None => None, - Some(ref type_def) => { - match (*type_def).type_def { + Some(type_def) => { + match type_def.type_def { Some(type_def) => Some(type_def), None => { match type_def.module_def { Some(module) => { - match module.def_id { + match module.def_id.get() { Some(did) => Some(DefMod(did)), None => None, } @@ -680,7 +686,7 @@ impl NameBindings { } } ValueNS => { - match self.value_def { + match self.value_def.get() { None => None, Some(value_def) => Some(value_def.def) } @@ -692,13 +698,13 @@ impl NameBindings { if self.defined_in_namespace(namespace) { match namespace { TypeNS => { - match self.type_def { + match self.type_def.get() { None => None, Some(type_def) => type_def.type_span } } ValueNS => { - match self.value_def { + match self.value_def.get() { None => None, Some(value_def) => value_def.value_span } @@ -712,8 +718,8 @@ impl NameBindings { fn NameBindings() -> NameBindings { NameBindings { - type_def: None, - value_def: None + type_def: RefCell::new(None), + value_def: RefCell::new(None), } } @@ -767,7 +773,7 @@ fn namespace_error_to_str(ns: NamespaceError) -> &'static str { fn Resolver(session: Session, lang_items: LanguageItems, crate_span: Span) -> Resolver { - let graph_root = @mut NameBindings(); + let graph_root = @NameBindings(); graph_root.define_module(NoParentLink, Some(DefId { crate: 0, node: 0 }), @@ -787,15 +793,15 @@ fn Resolver(session: Session, graph_root: graph_root, - method_map: @mut HashMap::new(), + method_map: @RefCell::new(HashMap::new()), structs: HashSet::new(), unresolved_imports: 0, current_module: current_module, - value_ribs: @mut ~[], - type_ribs: @mut ~[], - label_ribs: @mut ~[], + value_ribs: @RefCell::new(~[]), + type_ribs: @RefCell::new(~[]), + label_ribs: @RefCell::new(~[]), current_trait_refs: None, @@ -806,8 +812,8 @@ fn Resolver(session: Session, namespaces: ~[ TypeNS, ValueNS ], - def_map: @mut HashMap::new(), - export_map2: @mut HashMap::new(), + def_map: @RefCell::new(HashMap::new()), + export_map2: @RefCell::new(HashMap::new()), trait_map: HashMap::new(), used_imports: HashSet::new(), external_exports: HashSet::new(), @@ -827,26 +833,26 @@ struct Resolver { intr: @ident_interner, - graph_root: @mut NameBindings, + graph_root: @NameBindings, - method_map: @mut HashMap>, + method_map: @RefCell>>, structs: HashSet, // The number of imports that are currently unresolved. unresolved_imports: uint, // The module that represents the current item scope. - current_module: @mut Module, + current_module: @Module, // The current set of local scopes, for values. // FIXME #4948: Reuse ribs to avoid allocation. - value_ribs: @mut ~[@Rib], + value_ribs: @RefCell<~[@Rib]>, // The current set of local scopes, for types. - type_ribs: @mut ~[@Rib], + type_ribs: @RefCell<~[@Rib]>, // The current set of local scopes, for labels. - label_ribs: @mut ~[@Rib], + label_ribs: @RefCell<~[@Rib]>, // The trait that the current context can refer to. current_trait_refs: Option<~[DefId]>, @@ -954,7 +960,7 @@ impl Resolver { /// Returns the current module tracked by the reduced graph parent. fn get_module_from_parent(&mut self, reduced_graph_parent: ReducedGraphParent) - -> @mut Module { + -> @Module { match reduced_graph_parent { ModuleReducedGraphParent(module_) => { return module_; @@ -978,7 +984,7 @@ impl Resolver { duplicate_checking_mode: DuplicateCheckingMode, // For printing errors sp: Span) - -> (@mut NameBindings, ReducedGraphParent) { + -> (@NameBindings, ReducedGraphParent) { // If this is the immediate descendant of a module, then we add the // child name directly. Otherwise, we create or reuse an anonymous // module and add the child to that. @@ -992,13 +998,18 @@ impl Resolver { // Add or reuse the child. let new_parent = ModuleReducedGraphParent(module_); - match module_.children.find(&name.name) { + let child_opt = { + let children = module_.children.borrow(); + children.get().find_copy(&name.name) + }; + match child_opt { None => { - let child = @mut NameBindings(); - module_.children.insert(name.name, child); + let child = @NameBindings(); + let mut children = module_.children.borrow_mut(); + children.get().insert(name.name, child); return (child, new_parent); } - Some(&child) => { + Some(child) => { // Enforce the duplicate checking mode: // // * If we're requesting duplicate module checking, check that @@ -1234,11 +1245,15 @@ impl Resolver { ty_path(ref path, _, _) if path.segments.len() == 1 => { let name = path_to_ident(path); - let new_parent = match parent.children.find(&name.name) { + let existing_parent_opt = { + let children = parent.children.borrow(); + children.get().find_copy(&name.name) + }; + let new_parent = match existing_parent_opt { // It already exists - Some(&child) if child.get_module_if_available() - .is_some() && - child.get_module().kind == + Some(child) if child.get_module_if_available() + .is_some() && + child.get_module().kind.get() == ImplModuleKind => { ModuleReducedGraphParent(child.get_module()) } @@ -1364,10 +1379,11 @@ impl Resolver { let def_id = local_def(item.id); for (name, _) in method_names.iter() { - if !self.method_map.contains_key(name) { - self.method_map.insert(*name, HashSet::new()); + let mut method_map = self.method_map.borrow_mut(); + if !method_map.get().contains_key(name) { + method_map.get().insert(*name, HashSet::new()); } - match self.method_map.find_mut(name) { + match method_map.get().find_mut(name) { Some(s) => { s.insert(def_id); }, _ => fail!("Can't happen"), } @@ -1499,15 +1515,19 @@ impl Resolver { self.external_exports.insert(def_id); let parent_link = ModuleParentLink (self.get_module_from_parent(parent), name); - let external_module = @mut Module::new(parent_link, + let external_module = @Module::new(parent_link, Some(def_id), NormalModuleKind, false, true); - parent.external_module_children.insert( - name.name, - external_module); + { + let mut external_module_children = + parent.external_module_children.borrow_mut(); + external_module_children.get().insert( + name.name, + external_module); + } self.build_reduced_graph_for_external_crate( external_module); @@ -1564,14 +1584,18 @@ impl Resolver { block_id); let parent_module = self.get_module_from_parent(parent); - let new_module = @mut Module::new( + let new_module = @Module::new( BlockParentLink(parent_module, block_id), None, AnonymousModuleKind, false, false); - parent_module.anonymous_children.insert(block_id, new_module); - ModuleReducedGraphParent(new_module) + { + let mut anonymous_children = parent_module.anonymous_children + .borrow_mut(); + anonymous_children.get().insert(block_id, new_module); + ModuleReducedGraphParent(new_module) + } } else { parent } @@ -1580,7 +1604,7 @@ impl Resolver { fn handle_external_def(&mut self, def: Def, vis: visibility, - child_name_bindings: @mut NameBindings, + child_name_bindings: @NameBindings, final_ident: &str, ident: Ident, new_parent: ReducedGraphParent) { @@ -1590,7 +1614,7 @@ impl Resolver { let is_public = vis == ast::public; let is_exported = is_public && match new_parent { ModuleReducedGraphParent(module) => { - match module.def_id { + match module.def_id.get() { None => true, Some(did) => self.external_exports.contains(&did) } @@ -1602,11 +1626,11 @@ impl Resolver { match def { DefMod(def_id) | DefForeignMod(def_id) | DefStruct(def_id) | DefTy(def_id) => { - match child_name_bindings.type_def { + match child_name_bindings.type_def.get() { Some(TypeNsDef { module_def: Some(module_def), .. }) => { debug!("(building reduced graph for external crate) \ already created module"); - module_def.def_id = Some(def_id); + module_def.def_id.set(Some(def_id)); } Some(_) | None => { debug!("(building reduced graph for \ @@ -1677,10 +1701,11 @@ impl Resolver { } } for name in interned_method_names.iter() { - if !self.method_map.contains_key(name) { - self.method_map.insert(*name, HashSet::new()); + let mut method_map = self.method_map.borrow_mut(); + if !method_map.get().contains_key(name) { + method_map.get().insert(*name, HashSet::new()); } - match self.method_map.find_mut(name) { + match method_map.get().find_mut(name) { Some(s) => { s.insert(def_id); }, _ => fail!("Can't happen"), } @@ -1729,7 +1754,7 @@ impl Resolver { /// Builds the reduced graph for a single item in an external crate. fn build_reduced_graph_for_external_crate_def(&mut self, - root: @mut Module, + root: @Module, def_like: DefLike, ident: Ident, visibility: visibility) { @@ -1794,7 +1819,7 @@ impl Resolver { // Process the static methods. First, // create the module. let type_module; - match child_name_bindings.type_def { + match child_name_bindings.type_def.get() { Some(TypeNsDef { module_def: Some(module_def), .. @@ -1805,7 +1830,7 @@ impl Resolver { // Mark it as an impl module if // necessary. - type_module.kind = ImplModuleKind; + type_module.kind.set(ImplModuleKind); } Some(_) | None => { let parent_link = @@ -1864,11 +1889,11 @@ impl Resolver { } /// Builds the reduced graph rooted at the given external module. - fn populate_external_module(&mut self, module: @mut Module) { + fn populate_external_module(&mut self, module: @Module) { debug!("(populating external module) attempting to populate {}", self.module_to_str(module)); - let def_id = match module.def_id { + let def_id = match module.def_id.get() { None => { debug!("(populating external module) ... no def ID!"); return @@ -1886,24 +1911,27 @@ impl Resolver { child_ident, visibility) }); - module.populated = true + module.populated.set(true) } /// Ensures that the reduced graph rooted at the given external module /// is built, building it if it is not. - fn populate_module_if_necessary(&mut self, module: @mut Module) { - if !module.populated { + fn populate_module_if_necessary(&mut self, module: @Module) { + if !module.populated.get() { self.populate_external_module(module) } - assert!(module.populated) + assert!(module.populated.get()) } /// Builds the reduced graph rooted at the 'use' directive for an external /// crate. fn build_reduced_graph_for_external_crate(&mut self, - root: @mut Module) { + root: @Module) { csearch::each_top_level_item_of_crate(self.session.cstore, - root.def_id.unwrap().crate, + root.def_id + .get() + .unwrap() + .crate, |def_like, ident, visibility| { self.build_reduced_graph_for_external_crate_def(root, def_like, @@ -1914,7 +1942,7 @@ impl Resolver { /// Creates and adds an import directive to the given module. fn build_import_directive(&mut self, - module_: @mut Module, + module_: @Module, module_path: ~[Ident], subclass: @ImportDirectiveSubclass, span: Span, @@ -1923,7 +1951,11 @@ impl Resolver { let directive = @ImportDirective::new(module_path, subclass, span, id, is_public); - module_.imports.push(directive); + + { + let mut imports = module_.imports.borrow_mut(); + imports.get().push(directive); + } // Bump the reference count on the name. Or, if this is a glob, set // the appropriate flag. @@ -1935,21 +1967,25 @@ impl Resolver { self.idents_to_str(directive.module_path), self.session.str_of(target)); - match module_.import_resolutions.find(&target.name) { + let mut import_resolutions = module_.import_resolutions + .borrow_mut(); + match import_resolutions.get().find(&target.name) { Some(&resolution) => { debug!("(building import directive) bumping \ reference"); - resolution.outstanding_references += 1; + resolution.outstanding_references.set( + resolution.outstanding_references.get() + 1); // the source of this name is different now - resolution.type_id = id; - resolution.value_id = id; + resolution.type_id.set(id); + resolution.value_id.set(id); } None => { debug!("(building import directive) creating new"); - let resolution = @mut ImportResolution::new(id, is_public); - resolution.outstanding_references = 1; - module_.import_resolutions.insert(target.name, resolution); + let resolution = @ImportResolution::new(id, is_public); + resolution.outstanding_references.set(1); + import_resolutions.get().insert(target.name, + resolution); } } } @@ -1957,7 +1993,7 @@ impl Resolver { // Set the glob flag. This tells us that we don't know the // module's exports ahead of time. - module_.glob_count += 1; + module_.glob_count.set(module_.glob_count.get() + 1); } } @@ -2002,30 +2038,34 @@ impl Resolver { /// Attempts to resolve imports for the given module and all of its /// submodules. fn resolve_imports_for_module_subtree(&mut self, - module_: @mut Module) { + module_: @Module) { debug!("(resolving imports for module subtree) resolving {}", self.module_to_str(module_)); self.resolve_imports_for_module(module_); self.populate_module_if_necessary(module_); - for (_, &child_node) in module_.children.iter() { - match child_node.get_module_if_available() { - None => { - // Nothing to do. - } - Some(child_module) => { - self.resolve_imports_for_module_subtree(child_module); + { + let children = module_.children.borrow(); + for (_, &child_node) in children.get().iter() { + match child_node.get_module_if_available() { + None => { + // Nothing to do. + } + Some(child_module) => { + self.resolve_imports_for_module_subtree(child_module); + } } } } - for (_, &child_module) in module_.anonymous_children.iter() { + let anonymous_children = module_.anonymous_children.borrow(); + for (_, &child_module) in anonymous_children.get().iter() { self.resolve_imports_for_module_subtree(child_module); } } /// Attempts to resolve imports for the given module only. - fn resolve_imports_for_module(&mut self, module: @mut Module) { + fn resolve_imports_for_module(&mut self, module: @Module) { if module.all_imports_resolved() { debug!("(resolving imports for module) all imports resolved for \ {}", @@ -2033,11 +2073,11 @@ impl Resolver { return; } - let imports = &mut *module.imports; - let import_count = imports.len(); - while module.resolved_import_count < import_count { - let import_index = module.resolved_import_count; - let import_directive = imports[import_index]; + let mut imports = module.imports.borrow_mut(); + let import_count = imports.get().len(); + while module.resolved_import_count.get() < import_count { + let import_index = module.resolved_import_count.get(); + let import_directive = imports.get()[import_index]; match self.resolve_import_for_module(module, import_directive) { Failed => { // We presumably emitted an error. Continue. @@ -2056,7 +2096,8 @@ impl Resolver { } } - module.resolved_import_count += 1; + module.resolved_import_count + .set(module.resolved_import_count.get() + 1); } } @@ -2110,9 +2151,9 @@ impl Resolver { /// currently-unresolved imports, or success if we know the name exists. /// If successful, the resolved bindings are written into the module. fn resolve_import_for_module(&mut self, - module_: @mut Module, + module_: @Module, import_directive: @ImportDirective) - -> ResolveResult<()> { + -> ResolveResult<()> { let mut resolution_result = Failed; let module_path = &import_directive.module_path; @@ -2188,8 +2229,8 @@ impl Resolver { if !resolution_result.indeterminate() { match *import_directive.subclass { GlobImport => { - assert!(module_.glob_count >= 1); - module_.glob_count -= 1; + assert!(module_.glob_count.get() >= 1); + module_.glob_count.set(module_.glob_count.get() - 1); } SingleImport(..) => { // Ignore. @@ -2200,22 +2241,21 @@ impl Resolver { return resolution_result; } - fn create_name_bindings_from_module(module: @mut Module) - -> NameBindings { + fn create_name_bindings_from_module(module: @Module) -> NameBindings { NameBindings { - type_def: Some(TypeNsDef { + type_def: RefCell::new(Some(TypeNsDef { is_public: false, module_def: Some(module), type_def: None, type_span: None - }), - value_def: None, + })), + value_def: RefCell::new(None), } } fn resolve_single_import(&mut self, - module_: @mut Module, - containing_module: @mut Module, + module_: @Module, + containing_module: @Module, target: Ident, source: Ident, directive: &ImportDirective, @@ -2238,18 +2278,22 @@ impl Resolver { // Search for direct children of the containing module. self.populate_module_if_necessary(containing_module); - match containing_module.children.find(&source.name) { - None => { - // Continue. - } - Some(child_name_bindings) => { - if child_name_bindings.defined_in_namespace(ValueNS) { - value_result = BoundResult(containing_module, - *child_name_bindings); + + { + let children = containing_module.children.borrow(); + match children.get().find(&source.name) { + None => { + // Continue. } - if child_name_bindings.defined_in_namespace(TypeNS) { - type_result = BoundResult(containing_module, - *child_name_bindings); + Some(child_name_bindings) => { + if child_name_bindings.defined_in_namespace(ValueNS) { + value_result = BoundResult(containing_module, + *child_name_bindings); + } + if child_name_bindings.defined_in_namespace(TypeNS) { + type_result = BoundResult(containing_module, + *child_name_bindings); + } } } } @@ -2264,7 +2308,7 @@ impl Resolver { // containing module, bail out. We don't know enough to be // able to resolve this import. - if containing_module.glob_count > 0 { + if containing_module.glob_count.get() > 0 { debug!("(resolving single import) unresolved glob; \ bailing out"); return Indeterminate; @@ -2273,7 +2317,9 @@ impl Resolver { // Now search the exported imports within the containing // module. - match containing_module.import_resolutions.find(&source.name) { + let import_resolutions = containing_module.import_resolutions + .borrow(); + match import_resolutions.get().find(&source.name) { None => { // The containing module definitely doesn't have an // exported import with the name in question. We can @@ -2288,18 +2334,17 @@ impl Resolver { } } Some(import_resolution) - if import_resolution.outstanding_references + if import_resolution.outstanding_references.get() == 0 => { fn get_binding(this: &mut Resolver, - import_resolution: - @mut ImportResolution, + import_resolution: @ImportResolution, namespace: Namespace) -> NamespaceResult { // Import resolutions must be declared with "pub" // in order to be exported. - if !import_resolution.is_public { + if !import_resolution.is_public.get() { return UnboundResult; } @@ -2322,12 +2367,12 @@ impl Resolver { if value_result.is_unknown() { value_result = get_binding(self, *import_resolution, ValueNS); - used_reexport = import_resolution.is_public; + used_reexport = import_resolution.is_public.get(); } if type_result.is_unknown() { type_result = get_binding(self, *import_resolution, TypeNS); - used_reexport = import_resolution.is_public; + used_reexport = import_resolution.is_public.get(); } } @@ -2347,13 +2392,18 @@ impl Resolver { match type_result { BoundResult(..) => {} _ => { - match containing_module.external_module_children - .find(&source.name) { + let module_opt = { + let mut external_module_children = + containing_module.external_module_children + .borrow_mut(); + external_module_children.get().find_copy(&source.name) + }; + match module_opt { None => {} // Continue. Some(module) => { let name_bindings = - @mut Resolver::create_name_bindings_from_module( - *module); + @Resolver::create_name_bindings_from_module( + module); type_result = BoundResult(containing_module, name_bindings); used_public = true; @@ -2363,15 +2413,18 @@ impl Resolver { } // We've successfully resolved the import. Write the results in. - assert!(module_.import_resolutions.contains_key(&target.name)); - let import_resolution = module_.import_resolutions.get(&target.name); + let import_resolution = { + let import_resolutions = module_.import_resolutions.borrow(); + assert!(import_resolutions.get().contains_key(&target.name)); + import_resolutions.get().get_copy(&target.name) + }; match value_result { BoundResult(target_module, name_bindings) => { debug!("(resolving single import) found value target"); - import_resolution.value_target = - Some(Target::new(target_module, name_bindings)); - import_resolution.value_id = directive.id; + import_resolution.value_target.set( + Some(Target::new(target_module, name_bindings))); + import_resolution.value_id.set(directive.id); used_public = name_bindings.defined_in_public_namespace(ValueNS); } UnboundResult => { /* Continue. */ } @@ -2382,10 +2435,10 @@ impl Resolver { match type_result { BoundResult(target_module, name_bindings) => { debug!("(resolving single import) found type target: {:?}", - name_bindings.type_def.unwrap().type_def); - import_resolution.type_target = - Some(Target::new(target_module, name_bindings)); - import_resolution.type_id = directive.id; + name_bindings.type_def.get().unwrap().type_def); + import_resolution.type_target.set( + Some(Target::new(target_module, name_bindings))); + import_resolution.type_id.set(directive.id); used_public = name_bindings.defined_in_public_namespace(TypeNS); } UnboundResult => { /* Continue. */ } @@ -2394,8 +2447,8 @@ impl Resolver { } } - if import_resolution.value_target.is_none() && - import_resolution.type_target.is_none() { + if import_resolution.value_target.get().is_none() && + import_resolution.type_target.get().is_none() { let msg = format!("unresolved import: there is no \ `{}` in `{}`", self.session.str_of(source), @@ -2405,26 +2458,29 @@ impl Resolver { } let used_public = used_reexport || used_public; - assert!(import_resolution.outstanding_references >= 1); - import_resolution.outstanding_references -= 1; + assert!(import_resolution.outstanding_references.get() >= 1); + import_resolution.outstanding_references.set( + import_resolution.outstanding_references.get() - 1); // record what this import resolves to for later uses in documentation, // this may resolve to either a value or a type, but for documentation // purposes it's good enough to just favor one over the other. - match import_resolution.value_target { + match import_resolution.value_target.get() { Some(target) => { let def = target.bindings.def_for_namespace(ValueNS).unwrap(); - self.def_map.insert(directive.id, def); + let mut def_map = self.def_map.borrow_mut(); + def_map.get().insert(directive.id, def); let did = def_id_of_def(def); self.last_private.insert(directive.id, if used_public {lp} else {DependsOn(did)}); } None => {} } - match import_resolution.type_target { + match import_resolution.type_target.get() { Some(target) => { let def = target.bindings.def_for_namespace(TypeNS).unwrap(); - self.def_map.insert(directive.id, def); + let mut def_map = self.def_map.borrow_mut(); + def_map.get().insert(directive.id, def); let did = def_id_of_def(def); self.last_private.insert(directive.id, if used_public {lp} else {DependsOn(did)}); @@ -2440,8 +2496,8 @@ impl Resolver { // succeeds or bails out (as importing * from an empty module or a module // that exports nothing is valid). fn resolve_glob_import(&mut self, - module_: @mut Module, - containing_module: @mut Module, + module_: @Module, + containing_module: @Module, id: NodeId, is_public: bool, lp: LastPrivate) @@ -2459,72 +2515,77 @@ impl Resolver { return Indeterminate; } - assert_eq!(containing_module.glob_count, 0); + assert_eq!(containing_module.glob_count.get(), 0); // Add all resolved imports from the containing module. - for (ident, target_import_resolution) in containing_module.import_resolutions.iter() { - + let import_resolutions = containing_module.import_resolutions + .borrow(); + for (ident, target_import_resolution) in import_resolutions.get() + .iter() { debug!("(resolving glob import) writing module resolution \ {:?} into `{}`", - target_import_resolution.type_target.is_none(), + target_import_resolution.type_target.get().is_none(), self.module_to_str(module_)); - if !target_import_resolution.is_public { + if !target_import_resolution.is_public.get() { debug!("(resolving glob import) nevermind, just kidding"); continue } // Here we merge two import resolutions. - match module_.import_resolutions.find(ident) { + let mut import_resolutions = module_.import_resolutions + .borrow_mut(); + match import_resolutions.get().find(ident) { None => { // Simple: just copy the old import resolution. let new_import_resolution = - @mut ImportResolution::new(id, is_public); - new_import_resolution.value_target = - target_import_resolution.value_target; - new_import_resolution.type_target = - target_import_resolution.type_target; + @ImportResolution::new(id, is_public); + new_import_resolution.value_target.set( + target_import_resolution.value_target.get()); + new_import_resolution.type_target.set( + target_import_resolution.type_target.get()); - module_.import_resolutions.insert + import_resolutions.get().insert (*ident, new_import_resolution); } Some(&dest_import_resolution) => { // Merge the two import resolutions at a finer-grained // level. - match target_import_resolution.value_target { + match target_import_resolution.value_target.get() { None => { // Continue. } Some(value_target) => { - dest_import_resolution.value_target = - Some(value_target); + dest_import_resolution.value_target.set( + Some(value_target)); } } - match target_import_resolution.type_target { + match target_import_resolution.type_target.get() { None => { // Continue. } Some(type_target) => { - dest_import_resolution.type_target = - Some(type_target); + dest_import_resolution.type_target.set( + Some(type_target)); } } - dest_import_resolution.is_public = is_public; + dest_import_resolution.is_public.set(is_public); } } } - let merge_import_resolution = |name, - name_bindings: @mut NameBindings| { + let merge_import_resolution = |name, name_bindings: @NameBindings| { let dest_import_resolution; - match module_.import_resolutions.find(&name) { + let mut import_resolutions = module_.import_resolutions + .borrow_mut(); + match import_resolutions.get().find(&name) { None => { // Create a new import resolution from this child. - dest_import_resolution = @mut ImportResolution::new(id, - is_public); - module_.import_resolutions.insert - (name, dest_import_resolution); + dest_import_resolution = + @ImportResolution::new(id, is_public); + import_resolutions.get().insert(name, + dest_import_resolution); } Some(&existing_import_resolution) => { dest_import_resolution = existing_import_resolution; @@ -2540,36 +2601,45 @@ impl Resolver { // Merge the child item into the import resolution. if name_bindings.defined_in_public_namespace(ValueNS) { debug!("(resolving glob import) ... for value target"); - dest_import_resolution.value_target = - Some(Target::new(containing_module, name_bindings)); - dest_import_resolution.value_id = id; + dest_import_resolution.value_target.set( + Some(Target::new(containing_module, name_bindings))); + dest_import_resolution.value_id.set(id); } if name_bindings.defined_in_public_namespace(TypeNS) { debug!("(resolving glob import) ... for type target"); - dest_import_resolution.type_target = - Some(Target::new(containing_module, name_bindings)); - dest_import_resolution.type_id = id; + dest_import_resolution.type_target.set( + Some(Target::new(containing_module, name_bindings))); + dest_import_resolution.type_id.set(id); } - dest_import_resolution.is_public = is_public; + dest_import_resolution.is_public.set(is_public); }; // Add all children from the containing module. self.populate_module_if_necessary(containing_module); - for (&name, name_bindings) in containing_module.children.iter() { - merge_import_resolution(name, *name_bindings); + + { + let children = containing_module.children.borrow(); + for (&name, name_bindings) in children.get().iter() { + merge_import_resolution(name, *name_bindings); + } } // Add external module children from the containing module. - for (&name, module) in containing_module.external_module_children.iter() { - let name_bindings = - @mut Resolver::create_name_bindings_from_module(*module); - merge_import_resolution(name, name_bindings); + { + let external_module_children = + containing_module.external_module_children.borrow(); + for (&name, module) in external_module_children.get().iter() { + let name_bindings = + @Resolver::create_name_bindings_from_module(*module); + merge_import_resolution(name, name_bindings); + } } // Record the destination of this import - match containing_module.def_id { + match containing_module.def_id.get() { Some(did) => { - self.def_map.insert(id, DefMod(did)); + let mut def_map = self.def_map.borrow_mut(); + def_map.get().insert(id, DefMod(did)); self.last_private.insert(id, lp); } None => {} @@ -2581,13 +2651,13 @@ impl Resolver { /// Resolves the given module path from the given root `module_`. fn resolve_module_path_from_root(&mut self, - module_: @mut Module, + module_: @Module, module_path: &[Ident], index: uint, span: Span, name_search_type: NameSearchType, lp: LastPrivate) - -> ResolveResult<(@mut Module, LastPrivate)> { + -> ResolveResult<(@Module, LastPrivate)> { let mut search_module = module_; let mut index = index; let module_path_len = module_path.len(); @@ -2631,7 +2701,7 @@ impl Resolver { Success((target, used_proxy)) => { // Check to see whether there are type bindings, and, if // so, whether there is a module within. - match target.bindings.type_def { + match target.bindings.type_def.get() { Some(type_def) => { match type_def.module_def { None => { @@ -2649,7 +2719,7 @@ impl Resolver { // import, do not allow traits and impls // to be selected. match (name_search_type, - module_def.kind) { + module_def.kind.get()) { (ImportSearch, TraitModuleKind) | (ImportSearch, ImplModuleKind) => { self.resolve_error( @@ -2666,7 +2736,8 @@ impl Resolver { // resolving this import chain. if !used_proxy && !search_module.is_public { - match search_module.def_id { + match search_module.def_id + .get() { Some(did) => { closest_private = DependsOn(did); @@ -2703,12 +2774,12 @@ impl Resolver { /// On success, returns the resolved module, and the closest *private* /// module found to the destination when resolving this path. fn resolve_module_path(&mut self, - module_: @mut Module, + module_: @Module, module_path: &[Ident], use_lexical_scope: UseLexicalScopeFlag, span: Span, name_search_type: NameSearchType) - -> ResolveResult<(@mut Module, LastPrivate)> { + -> ResolveResult<(@Module, LastPrivate)> { let module_path_len = module_path.len(); assert!(module_path_len > 0); @@ -2786,7 +2857,9 @@ impl Resolver { Success(PrefixFound(containing_module, index)) => { search_module = containing_module; start_index = index; - last_private = DependsOn(containing_module.def_id.unwrap()); + last_private = DependsOn(containing_module.def_id + .get() + .unwrap()); } } @@ -2801,7 +2874,7 @@ impl Resolver { /// Invariant: This must only be called during main resolution, not during /// import resolution. fn resolve_item_in_lexical_scope(&mut self, - module_: @mut Module, + module_: @Module, name: Ident, namespace: Namespace, search_through_modules: @@ -2816,20 +2889,26 @@ impl Resolver { // The current module node is handled specially. First, check for // its immediate children. self.populate_module_if_necessary(module_); - match module_.children.find(&name.name) { - Some(name_bindings) - if name_bindings.defined_in_namespace(namespace) => { - debug!("top name bindings succeeded"); - return Success((Target::new(module_, *name_bindings), false)); + + { + let children = module_.children.borrow(); + match children.get().find(&name.name) { + Some(name_bindings) + if name_bindings.defined_in_namespace(namespace) => { + debug!("top name bindings succeeded"); + return Success((Target::new(module_, *name_bindings), + false)); + } + Some(_) | None => { /* Not found; continue. */ } } - Some(_) | None => { /* Not found; continue. */ } } // Now check for its import directives. We don't have to have resolved // all its imports in the usual way; this is because chains of // adjacent import statements are processed as though they mutated the // current scope. - match module_.import_resolutions.find(&name.name) { + let import_resolutions = module_.import_resolutions.borrow(); + match import_resolutions.get().find(&name.name) { None => { // Not found; continue. } @@ -2853,12 +2932,16 @@ impl Resolver { // Search for external modules. if namespace == TypeNS { - match module_.external_module_children.find(&name.name) { + let module_opt = { + let external_module_children = + module_.external_module_children.borrow(); + external_module_children.get().find_copy(&name.name) + }; + match module_opt { None => {} Some(module) => { let name_bindings = - @mut Resolver::create_name_bindings_from_module( - *module); + @Resolver::create_name_bindings_from_module(module); debug!("lower name bindings succeeded"); return Success((Target::new(module_, name_bindings), false)); } @@ -2879,7 +2962,7 @@ impl Resolver { ModuleParentLink(parent_module_node, _) => { match search_through_modules { DontSearchThroughModules => { - match search_module.kind { + match search_module.kind.get() { NormalModuleKind => { // We stop the search here. debug!("(resolving item in lexical \ @@ -2934,19 +3017,19 @@ impl Resolver { /// Resolves a module name in the current lexical scope. fn resolve_module_in_lexical_scope(&mut self, - module_: @mut Module, + module_: @Module, name: Ident) - -> ResolveResult<@mut Module> { + -> ResolveResult<@Module> { // If this module is an anonymous module, resolve the item in the // lexical scope. Otherwise, resolve the item from the crate root. let resolve_result = self.resolve_item_in_lexical_scope( module_, name, TypeNS, DontSearchThroughModules); match resolve_result { Success((target, _)) => { - let bindings = &mut *target.bindings; - match bindings.type_def { - Some(ref type_def) => { - match (*type_def).module_def { + let bindings = &*target.bindings; + match bindings.type_def.get() { + Some(type_def) => { + match type_def.module_def { None => { error!("!!! (resolving module in lexical \ scope) module wasn't actually a \ @@ -2979,15 +3062,15 @@ impl Resolver { } /// Returns the nearest normal module parent of the given module. - fn get_nearest_normal_module_parent(&mut self, module_: @mut Module) - -> Option<@mut Module> { + fn get_nearest_normal_module_parent(&mut self, module_: @Module) + -> Option<@Module> { let mut module_ = module_; loop { match module_.parent_link { NoParentLink => return None, ModuleParentLink(new_module, _) | BlockParentLink(new_module, _) => { - match new_module.kind { + match new_module.kind.get() { NormalModuleKind => return Some(new_module), ExternModuleKind | TraitModuleKind | @@ -3001,10 +3084,9 @@ impl Resolver { /// Returns the nearest normal module parent of the given module, or the /// module itself if it is a normal module. - fn get_nearest_normal_module_parent_or_self(&mut self, - module_: @mut Module) - -> @mut Module { - match module_.kind { + fn get_nearest_normal_module_parent_or_self(&mut self, module_: @Module) + -> @Module { + match module_.kind.get() { NormalModuleKind => return module_, ExternModuleKind | TraitModuleKind | @@ -3022,7 +3104,7 @@ impl Resolver { /// (b) some chain of `super::`. /// grammar: (SELF MOD_SEP ) ? (SUPER MOD_SEP) * fn resolve_module_prefix(&mut self, - module_: @mut Module, + module_: @Module, module_path: &[Ident]) -> ResolveResult { // Start at the current module if we see `self` or `super`, or at the @@ -3068,7 +3150,7 @@ impl Resolver { /// The boolean returned on success is an indicator of whether this lookup /// passed through a public re-export proxy. fn resolve_name_in_module(&mut self, - module_: @mut Module, + module_: @Module, name: Ident, namespace: Namespace, name_search_type: NameSearchType) @@ -3079,14 +3161,19 @@ impl Resolver { // First, check the direct children of the module. self.populate_module_if_necessary(module_); - match module_.children.find(&name.name) { - Some(name_bindings) - if name_bindings.defined_in_namespace(namespace) => { - debug!("(resolving name in module) found node as child"); - return Success((Target::new(module_, *name_bindings), false)); - } - Some(_) | None => { - // Continue. + + { + let children = module_.children.borrow(); + match children.get().find(&name.name) { + Some(name_bindings) + if name_bindings.defined_in_namespace(namespace) => { + debug!("(resolving name in module) found node as child"); + return Success((Target::new(module_, *name_bindings), + false)); + } + Some(_) | None => { + // Continue. + } } } @@ -3095,14 +3182,15 @@ impl Resolver { // If this is a search of all imports, we should be done with glob // resolution at this point. if name_search_type == PathSearch { - assert_eq!(module_.glob_count, 0); + assert_eq!(module_.glob_count.get(), 0); } // Check the list of resolved imports. - match module_.import_resolutions.find(&name.name) { + let import_resolutions = module_.import_resolutions.borrow(); + match import_resolutions.get().find(&name.name) { Some(import_resolution) => { - if import_resolution.is_public && - import_resolution.outstanding_references != 0 { + if import_resolution.is_public.get() && + import_resolution.outstanding_references.get() != 0 { debug!("(resolving name in module) import \ unresolved; bailing out"); return Indeterminate; @@ -3126,12 +3214,16 @@ impl Resolver { // Finally, search through external children. if namespace == TypeNS { - match module_.external_module_children.find(&name.name) { + let module_opt = { + let external_module_children = + module_.external_module_children.borrow(); + external_module_children.get().find_copy(&name.name) + }; + match module_opt { None => {} Some(module) => { let name_bindings = - @mut Resolver::create_name_bindings_from_module( - *module); + @Resolver::create_name_bindings_from_module(module); return Success((Target::new(module_, name_bindings), false)); } } @@ -3143,35 +3235,44 @@ impl Resolver { return Failed; } - fn report_unresolved_imports(&mut self, module_: @mut Module) { - let index = module_.resolved_import_count; - let imports: &mut ~[@ImportDirective] = &mut *module_.imports; - let import_count = imports.len(); + fn report_unresolved_imports(&mut self, module_: @Module) { + let index = module_.resolved_import_count.get(); + let mut imports = module_.imports.borrow_mut(); + let import_count = imports.get().len(); if index != import_count { - let sn = self.session.codemap.span_to_snippet(imports[index].span).unwrap(); + let sn = self.session + .codemap + .span_to_snippet(imports.get()[index].span) + .unwrap(); if sn.contains("::") { - self.resolve_error(imports[index].span, "unresolved import"); + self.resolve_error(imports.get()[index].span, + "unresolved import"); } else { let err = format!("unresolved import (maybe you meant `{}::*`?)", sn.slice(0, sn.len())); - self.resolve_error(imports[index].span, err); + self.resolve_error(imports.get()[index].span, err); } } // Descend into children and anonymous children. self.populate_module_if_necessary(module_); - for (_, &child_node) in module_.children.iter() { - match child_node.get_module_if_available() { - None => { - // Continue. - } - Some(child_module) => { - self.report_unresolved_imports(child_module); + + { + let children = module_.children.borrow(); + for (_, &child_node) in children.get().iter() { + match child_node.get_module_if_available() { + None => { + // Continue. + } + Some(child_module) => { + self.report_unresolved_imports(child_module); + } } } } - for (_, &module_) in module_.anonymous_children.iter() { + let anonymous_children = module_.anonymous_children.borrow(); + for (_, &module_) in anonymous_children.get().iter() { self.report_unresolved_imports(module_); } } @@ -3191,11 +3292,11 @@ impl Resolver { } fn record_exports_for_module_subtree(&mut self, - module_: @mut Module) { + module_: @Module) { // If this isn't a local crate, then bail out. We don't need to record // exports for nonlocal crates. - match module_.def_id { + match module_.def_id.get() { Some(def_id) if def_id.crate == LOCAL_CRATE => { // OK. Continue. debug!("(recording exports for module subtree) recording \ @@ -3220,29 +3321,34 @@ impl Resolver { self.record_exports_for_module(module_); self.populate_module_if_necessary(module_); - for (_, &child_name_bindings) in module_.children.iter() { - match child_name_bindings.get_module_if_available() { - None => { - // Nothing to do. - } - Some(child_module) => { - self.record_exports_for_module_subtree(child_module); + { + let children = module_.children.borrow(); + for (_, &child_name_bindings) in children.get().iter() { + match child_name_bindings.get_module_if_available() { + None => { + // Nothing to do. + } + Some(child_module) => { + self.record_exports_for_module_subtree(child_module); + } } } } - for (_, &child_module) in module_.anonymous_children.iter() { + let anonymous_children = module_.anonymous_children.borrow(); + for (_, &child_module) in anonymous_children.get().iter() { self.record_exports_for_module_subtree(child_module); } } - fn record_exports_for_module(&mut self, module_: @mut Module) { + fn record_exports_for_module(&mut self, module_: @Module) { let mut exports2 = ~[]; self.add_exports_for_module(&mut exports2, module_); - match module_.def_id { + match module_.def_id.get() { Some(def_id) => { - self.export_map2.insert(def_id.node, exports2); + let mut export_map2 = self.export_map2.borrow_mut(); + export_map2.get().insert(def_id.node, exports2); debug!("(computing exports) writing exports for {} (some)", def_id.node); } @@ -3253,7 +3359,7 @@ impl Resolver { fn add_exports_of_namebindings(&mut self, exports2: &mut ~[Export2], name: Name, - namebindings: @mut NameBindings, + namebindings: @NameBindings, ns: Namespace, reexport: bool) { match namebindings.def_for_namespace(ns) { @@ -3276,9 +3382,12 @@ impl Resolver { fn add_exports_for_module(&mut self, exports2: &mut ~[Export2], - module_: @mut Module) { - for (name, importresolution) in module_.import_resolutions.iter() { - if !importresolution.is_public { continue } + module_: @Module) { + let import_resolutions = module_.import_resolutions.borrow(); + for (name, importresolution) in import_resolutions.get().iter() { + if !importresolution.is_public.get() { + continue + } let xs = [TypeNS, ValueNS]; for &ns in xs.iter() { match importresolution.target_for_namespace(ns) { @@ -3325,7 +3434,9 @@ impl Resolver { } Some(name) => { self.populate_module_if_necessary(orig_module); - match orig_module.children.find(&name.name) { + + let children = orig_module.children.borrow(); + match children.get().find(&name.name) { None => { debug!("!!! (with scope) didn't find `{}` in `{}`", self.session.str_of(name), @@ -3403,9 +3514,11 @@ impl Resolver { // If the def is a ty param, and came from the parent // item, it's ok match def { - DefTyParam(did, _) - if self.def_map.find(&did.node).map(|x| *x) - == Some(DefTyParamBinder(item_id)) => { + DefTyParam(did, _) if { + let def_map = self.def_map.borrow(); + def_map.get().find(&did.node).map(|x| *x) + == Some(DefTyParamBinder(item_id)) + } => { // ok } _ => { @@ -3486,8 +3599,12 @@ impl Resolver { let mut i = ribs.len(); while i != 0 { i -= 1; - match ribs[i].bindings.find(&name) { - Some(&def_like) => { + let binding_opt = { + let bindings = ribs[i].bindings.borrow(); + bindings.get().find_copy(&name) + }; + match binding_opt { + Some(def_like) => { return self.upvarify(ribs, i, def_like, span, allow_capturing_self); } @@ -3561,11 +3678,16 @@ impl Resolver { item_trait(ref generics, ref traits, ref methods) => { // Create a new rib for the self type. let self_type_rib = @Rib::new(NormalRibKind); - self.type_ribs.push(self_type_rib); + { + let mut type_ribs = self.type_ribs.borrow_mut(); + type_ribs.get().push(self_type_rib); + } // plain insert (no renaming) let name = self.type_self_ident.name; - self_type_rib.bindings.insert(name, - DlDef(DefSelfTy(item.id))); + { + let mut bindings = self_type_rib.bindings.borrow_mut(); + bindings.get().insert(name, DlDef(DefSelfTy(item.id))); + } // Create a new rib for the trait-wide type parameters. self.with_type_parameter_rib(HasTypeParameters(generics, @@ -3617,7 +3739,8 @@ impl Resolver { } }); - self.type_ribs.pop(); + let mut type_ribs = self.type_ribs.borrow_mut(); + type_ribs.get().pop(); } item_struct(ref struct_def, ref generics) => { @@ -3688,7 +3811,10 @@ impl Resolver { rib_kind) => { let function_type_rib = @Rib::new(rib_kind); - self.type_ribs.push(function_type_rib); + { + let mut type_ribs = self.type_ribs.borrow_mut(); + type_ribs.get().push(function_type_rib); + } for (index, type_parameter) in generics.ty_params.iter().enumerate() { let ident = type_parameter.ident; @@ -3702,7 +3828,9 @@ impl Resolver { self.record_def(type_parameter.id, (DefTyParamBinder(node_id), AllPublic)); // plain insert (no renaming) - function_type_rib.bindings.insert(ident.name, def_like); + let mut bindings = function_type_rib.bindings + .borrow_mut(); + bindings.get().insert(ident.name, def_like); } } @@ -3715,7 +3843,8 @@ impl Resolver { match type_parameters { HasTypeParameters(..) => { - self.type_ribs.pop(); + let mut type_ribs = self.type_ribs.borrow_mut(); + type_ribs.get().pop(); } NoTypeParameters => { @@ -3725,17 +3854,33 @@ impl Resolver { } fn with_label_rib(&mut self, f: |&mut Resolver|) { - self.label_ribs.push(@Rib::new(NormalRibKind)); + { + let mut label_ribs = self.label_ribs.borrow_mut(); + label_ribs.get().push(@Rib::new(NormalRibKind)); + } + f(self); - self.label_ribs.pop(); + + { + let mut label_ribs = self.label_ribs.borrow_mut(); + label_ribs.get().pop(); + } } fn with_constant_rib(&mut self, f: |&mut Resolver|) { - self.value_ribs.push(@Rib::new(ConstantItemRibKind)); - self.type_ribs.push(@Rib::new(ConstantItemRibKind)); + { + let mut value_ribs = self.value_ribs.borrow_mut(); + let mut type_ribs = self.type_ribs.borrow_mut(); + value_ribs.get().push(@Rib::new(ConstantItemRibKind)); + type_ribs.get().push(@Rib::new(ConstantItemRibKind)); + } f(self); - self.type_ribs.pop(); - self.value_ribs.pop(); + { + let mut value_ribs = self.value_ribs.borrow_mut(); + let mut type_ribs = self.type_ribs.borrow_mut(); + type_ribs.get().pop(); + value_ribs.get().pop(); + } } fn resolve_function(&mut self, @@ -3746,11 +3891,17 @@ impl Resolver { self_binding: SelfBinding) { // Create a value rib for the function. let function_value_rib = @Rib::new(rib_kind); - self.value_ribs.push(function_value_rib); + { + let mut value_ribs = self.value_ribs.borrow_mut(); + value_ribs.get().push(function_value_rib); + } // Create a label rib for the function. - let function_label_rib = @Rib::new(rib_kind); - self.label_ribs.push(function_label_rib); + { + let mut label_ribs = self.label_ribs.borrow_mut(); + let function_label_rib = @Rib::new(rib_kind); + label_ribs.get().push(function_label_rib); + } // If this function has type parameters, add them now. self.with_type_parameter_rib(type_parameters, |this| { @@ -3775,7 +3926,7 @@ impl Resolver { _ => false }; let def_like = DlDef(DefSelf(self_node_id, mutable)); - *function_value_rib.self_binding = Some(def_like); + function_value_rib.self_binding.set(Some(def_like)); } } @@ -3806,8 +3957,11 @@ impl Resolver { debug!("(resolving function) leaving function"); }); - self.label_ribs.pop(); - self.value_ribs.pop(); + let mut label_ribs = self.label_ribs.borrow_mut(); + label_ribs.get().pop(); + + let mut value_ribs = self.value_ribs.borrow_mut(); + value_ribs.get().pop(); } fn resolve_type_parameters(&mut self, @@ -3945,7 +4099,8 @@ impl Resolver { // Record the current set of trait references. let mut new_trait_refs = ~[]; { - let r = this.def_map.find(&trait_reference.ref_id); + let def_map = this.def_map.borrow(); + let r = def_map.get().find(&trait_reference.ref_id); for &def in r.iter() { new_trait_refs.push(def_id_of_def(*def)); } @@ -4080,11 +4235,16 @@ impl Resolver { } fn resolve_arm(&mut self, arm: &Arm) { - self.value_ribs.push(@Rib::new(NormalRibKind)); + { + let mut value_ribs = self.value_ribs.borrow_mut(); + value_ribs.get().push(@Rib::new(NormalRibKind)); + } - let bindings_list = @mut HashMap::new(); + let mut bindings_list = HashMap::new(); for pattern in arm.pats.iter() { - self.resolve_pattern(*pattern, RefutableMode, Some(bindings_list)); + self.resolve_pattern(*pattern, + RefutableMode, + Some(&mut bindings_list)); } // This has to happen *after* we determine which @@ -4094,16 +4254,23 @@ impl Resolver { visit::walk_expr_opt(self, arm.guard, ()); self.resolve_block(arm.body); - self.value_ribs.pop(); + let mut value_ribs = self.value_ribs.borrow_mut(); + value_ribs.get().pop(); } fn resolve_block(&mut self, block: P) { debug!("(resolving block) entering block"); - self.value_ribs.push(@Rib::new(NormalRibKind)); + { + let mut value_ribs = self.value_ribs.borrow_mut(); + value_ribs.get().push(@Rib::new(NormalRibKind)); + } // Move down in the graph, if there's an anonymous module rooted here. let orig_module = self.current_module; - match self.current_module.anonymous_children.find(&block.id) { + let anonymous_children = self.current_module + .anonymous_children + .borrow(); + match anonymous_children.get().find(&block.id) { None => { /* Nothing to do. */ } Some(&anonymous_module) => { debug!("(resolving block) found anonymous module, moving \ @@ -4118,7 +4285,8 @@ impl Resolver { // Move back up. self.current_module = orig_module; - self.value_ribs.pop(); + let mut value_ribs = self.value_ribs.borrow_mut(); + value_ribs.get().pop(); debug!("(resolving block) leaving block"); } @@ -4230,7 +4398,7 @@ impl Resolver { mode: PatternBindingMode, // Maps idents to the node ID for the (outermost) // pattern that binds them - bindings_list: Option<@mut HashMap>) { + mut bindings_list: Option<&mut HashMap>) { let pat_id = pattern.id; walk_pat(pattern, |pattern| { match pattern.node { @@ -4320,16 +4488,22 @@ impl Resolver { // passes make about or-patterns.) match bindings_list { - Some(bindings_list) + Some(ref mut bindings_list) if !bindings_list.contains_key(&renamed) => { let this = &mut *self; - let last_rib = this.value_ribs[ - this.value_ribs.len() - 1]; - last_rib.bindings.insert(renamed, - DlDef(def)); + { + let mut value_ribs = + this.value_ribs.borrow_mut(); + let last_rib = value_ribs.get()[ + value_ribs.get().len() - 1]; + let mut bindings = + last_rib.bindings.borrow_mut(); + bindings.get().insert(renamed, + DlDef(def)); + } bindings_list.insert(renamed, pat_id); } - Some(b) => { + Some(ref mut b) => { if b.find(&renamed) == Some(&pat_id) { // Then this is a duplicate variable // in the same disjunct, which is an @@ -4344,10 +4518,16 @@ impl Resolver { } None => { let this = &mut *self; - let last_rib = this.value_ribs[ - this.value_ribs.len() - 1]; - last_rib.bindings.insert(renamed, - DlDef(def)); + { + let mut value_ribs = + this.value_ribs.borrow_mut(); + let last_rib = value_ribs.get()[ + value_ribs.get().len() - 1]; + let mut bindings = + last_rib.bindings.borrow_mut(); + bindings.get().insert(renamed, + DlDef(def)); + } } } } @@ -4485,8 +4665,9 @@ impl Resolver { Success((target, _)) => { debug!("(resolve bare identifier pattern) succeeded in \ finding {} at {:?}", - self.session.str_of(name), target.bindings.value_def); - match target.bindings.value_def { + self.session.str_of(name), + target.bindings.value_def.get()); + match target.bindings.value_def.get() { None => { fail!("resolved name in the value namespace to a \ set of name bindings with no def?!"); @@ -4590,33 +4771,39 @@ impl Resolver { // FIXME #4952: Merge me with resolve_name_in_module? fn resolve_definition_of_name_in_module(&mut self, - containing_module: @mut Module, + containing_module: @Module, name: Ident, namespace: Namespace) -> NameDefinition { // First, search children. self.populate_module_if_necessary(containing_module); - match containing_module.children.find(&name.name) { - Some(child_name_bindings) => { - match child_name_bindings.def_for_namespace(namespace) { - Some(def) => { - // Found it. Stop the search here. - let p = child_name_bindings.defined_in_public_namespace( - namespace); - let lp = if p {AllPublic} else { - DependsOn(def_id_of_def(def)) - }; - return ChildNameDefinition(def, lp); + + { + let children = containing_module.children.borrow(); + match children.get().find(&name.name) { + Some(child_name_bindings) => { + match child_name_bindings.def_for_namespace(namespace) { + Some(def) => { + // Found it. Stop the search here. + let p = child_name_bindings.defined_in_public_namespace( + namespace); + let lp = if p {AllPublic} else { + DependsOn(def_id_of_def(def)) + }; + return ChildNameDefinition(def, lp); + } + None => {} } - None => {} } + None => {} } - None => {} } // Next, search import resolutions. - match containing_module.import_resolutions.find(&name.name) { - Some(import_resolution) if import_resolution.is_public => { + let import_resolutions = containing_module.import_resolutions + .borrow(); + match import_resolutions.get().find(&name.name) { + Some(import_resolution) if import_resolution.is_public.get() => { match (*import_resolution).target_for_namespace(namespace) { Some(target) => { match target.bindings.def_for_namespace(namespace) { @@ -4640,10 +4827,15 @@ impl Resolver { // Finally, search through external children. if namespace == TypeNS { - match containing_module.external_module_children.find(&name.name) { + let module_opt = { + let external_module_children = + containing_module.external_module_children.borrow(); + external_module_children.get().find_copy(&name.name) + }; + match module_opt { None => {} Some(module) => { - match module.def_id { + match module.def_id.get() { None => {} // Continue. Some(def_id) => { let lp = if module.is_public {AllPublic} else { @@ -4702,11 +4894,12 @@ impl Resolver { (def, last_private.or(lp)) } }; - match containing_module.kind { + match containing_module.kind.get() { TraitModuleKind | ImplModuleKind => { - match self.method_map.find(&ident.name) { + let method_map = self.method_map.borrow(); + match method_map.get().find(&ident.name) { Some(s) => { - match containing_module.def_id { + match containing_module.def_id.get() { Some(def_id) if s.contains(&def_id) => { debug!("containing module was a trait or impl \ and name was a method -> not resolved"); @@ -4782,14 +4975,19 @@ impl Resolver { match namespace { ValueNS => { let renamed = mtwt_resolve(ident); - search_result = self.search_ribs(self.value_ribs, renamed, + let mut value_ribs = self.value_ribs.borrow_mut(); + search_result = self.search_ribs(value_ribs.get(), + renamed, span, DontAllowCapturingSelf); } TypeNS => { let name = ident.name; - search_result = self.search_ribs(self.type_ribs, name, - span, AllowCapturingSelf); + let mut type_ribs = self.type_ribs.borrow_mut(); + search_result = self.search_ribs(type_ribs.get(), + name, + span, + AllowCapturingSelf); } } @@ -4810,12 +5008,20 @@ impl Resolver { fn resolve_self_value_in_local_ribs(&mut self, span: Span) -> Option { // FIXME #4950: This should not use a while loop. - let mut i = self.value_ribs.len(); + let mut i = { + let value_ribs = self.value_ribs.borrow(); + value_ribs.get().len() + }; while i != 0 { i -= 1; - match *self.value_ribs[i].self_binding { + let self_binding_opt = { + let value_ribs = self.value_ribs.borrow(); + value_ribs.get()[i].self_binding.get() + }; + match self_binding_opt { Some(def_like) => { - match self.upvarify(self.value_ribs, + let mut value_ribs = self.value_ribs.borrow_mut(); + match self.upvarify(value_ribs.get(), i, def_like, span, @@ -4900,10 +5106,15 @@ impl Resolver { let mut maybes: ~[@str] = ~[]; let mut values: ~[uint] = ~[]; - let mut j = this.value_ribs.len(); + let mut j = { + let value_ribs = this.value_ribs.borrow(); + value_ribs.get().len() + }; while j != 0 { j -= 1; - for (&k, _) in this.value_ribs[j].bindings.iter() { + let value_ribs = this.value_ribs.borrow(); + let bindings = value_ribs.get()[j].bindings.borrow(); + for (&k, _) in bindings.get().iter() { maybes.push(interner_get(k)); values.push(uint::max_value); } @@ -5050,9 +5261,14 @@ impl Resolver { ExprLoop(_, Some(label)) => { self.with_label_rib(|this| { let def_like = DlDef(DefLabel(expr.id)); - let rib = this.label_ribs[this.label_ribs.len() - 1]; // plain insert (no renaming) - rib.bindings.insert(label.name, def_like); + { + let mut label_ribs = this.label_ribs.borrow_mut(); + let rib = label_ribs.get()[label_ribs.get().len() - + 1]; + let mut bindings = rib.bindings.borrow_mut(); + bindings.get().insert(label.name, def_like); + } visit::walk_expr(this, expr, ()); }) @@ -5061,7 +5277,8 @@ impl Resolver { ExprForLoop(..) => fail!("non-desugared expr_for_loop"), ExprBreak(Some(label)) | ExprAgain(Some(label)) => { - match self.search_ribs(self.label_ribs, label, expr.span, + let mut label_ribs = self.label_ribs.borrow_mut(); + match self.search_ribs(label_ribs.get(), label, expr.span, DontAllowCapturingSelf) { None => self.resolve_error(expr.span, @@ -5106,14 +5323,14 @@ impl Resolver { // the field name so that we can do some nice error reporting // later on in typeck. let traits = self.search_for_traits_containing_method(ident); - self.trait_map.insert(expr.id, @mut traits); + self.trait_map.insert(expr.id, @RefCell::new(traits)); } ExprMethodCall(_, _, ident, _, _, _) => { debug!("(recording candidate traits for expr) recording \ traits for {}", expr.id); let traits = self.search_for_traits_containing_method(ident); - self.trait_map.insert(expr.id, @mut traits); + self.trait_map.insert(expr.id, @RefCell::new(traits)); } ExprBinary(_, BiAdd, _, _) | ExprAssignOp(_, BiAdd, _, _) => { let i = self.lang_items.add_trait(); @@ -5189,7 +5406,8 @@ impl Resolver { let mut found_traits = ~[]; let mut search_module = self.current_module; - match self.method_map.find(&name.name) { + let method_map = self.method_map.borrow(); + match method_map.get().find(&name.name) { Some(candidate_traits) => loop { // Look for the current trait. match self.current_trait_refs { @@ -5209,8 +5427,9 @@ impl Resolver { // Look for trait children. self.populate_module_if_necessary(search_module); - for (_, &child_name_bindings) in - search_module.children.iter() { + + let children = search_module.children.borrow(); + for (_, &child_name_bindings) in children.get().iter() { match child_name_bindings.def_for_namespace(TypeNS) { Some(def) => { match def { @@ -5233,7 +5452,10 @@ impl Resolver { } // Look for imports. - for (_, &import_resolution) in search_module.import_resolutions.iter() { + let import_resolutions = search_module.import_resolutions + .borrow(); + for (_, &import_resolution) in import_resolutions.get() + .iter() { match import_resolution.target_for_namespace(TypeNS) { None => { // Continue. @@ -5248,7 +5470,8 @@ impl Resolver { &mut found_traits, trait_def_id, name); self.used_imports.insert( - import_resolution.type_id); + import_resolution.type_id + .get()); } } _ => { @@ -5298,7 +5521,7 @@ impl Resolver { trait_id: Option) { match trait_id { Some(trait_id) => { - self.trait_map.insert(expr_id, @mut ~[trait_id]); + self.trait_map.insert(expr_id, @RefCell::new(~[trait_id])); } None => {} } @@ -5308,7 +5531,8 @@ impl Resolver { debug!("(recording def) recording {:?} for {:?}, last private {:?}", def, node_id, lp); self.last_private.insert(node_id, lp); - self.def_map.insert_or_update_with(node_id, def, |_, old_value| { + let mut def_map = self.def_map.borrow_mut(); + def_map.get().insert_or_update_with(node_id, def, |_, old_value| { // Resolve appears to "resolve" the same ID multiple // times, so here is a sanity check it at least comes to // the same conclusion! - nmatsakis @@ -5390,7 +5614,7 @@ impl Resolver { // /// A somewhat inefficient routine to obtain the name of a module. - fn module_to_str(&mut self, module_: @mut Module) -> ~str { + fn module_to_str(&mut self, module_: @Module) -> ~str { let mut idents = ~[]; let mut current_module = module_; loop { @@ -5416,17 +5640,19 @@ impl Resolver { } #[allow(dead_code)] // useful for debugging - fn dump_module(&mut self, module_: @mut Module) { + fn dump_module(&mut self, module_: @Module) { debug!("Dump of module `{}`:", self.module_to_str(module_)); debug!("Children:"); self.populate_module_if_necessary(module_); - for (&name, _) in module_.children.iter() { + let children = module_.children.borrow(); + for (&name, _) in children.get().iter() { debug!("* {}", interner_get(name)); } debug!("Import resolutions:"); - for (name, import_resolution) in module_.import_resolutions.iter() { + let import_resolutions = module_.import_resolutions.borrow(); + for (name, import_resolution) in import_resolutions.get().iter() { let value_repr; match import_resolution.target_for_namespace(ValueNS) { None => { value_repr = ~""; } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 74f7b37265a72..d62a58460d043 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -18,6 +18,7 @@ */ use driver::session; +use std::cell::RefCell; use std::hashmap::HashMap; use syntax::ast; use syntax::codemap::Span; @@ -33,7 +34,7 @@ pub type NamedRegionMap = HashMap; struct LifetimeContext { sess: session::Session, - named_region_map: @mut NamedRegionMap, + named_region_map: @RefCell, } enum ScopeChain<'a> { @@ -43,12 +44,11 @@ enum ScopeChain<'a> { RootScope } -pub fn crate(sess: session::Session, - crate: &ast::Crate) - -> @mut NamedRegionMap { +pub fn crate(sess: session::Session, crate: &ast::Crate) + -> @RefCell { let mut ctxt = LifetimeContext { sess: sess, - named_region_map: @mut HashMap::new() + named_region_map: @RefCell::new(HashMap::new()) }; visit::walk_crate(&mut ctxt, crate, &RootScope); sess.abort_if_errors(); @@ -305,7 +305,8 @@ impl LifetimeContext { self.sess.intr()), lifetime_ref.id, def); - self.named_region_map.insert(lifetime_ref.id, def); + let mut named_region_map = self.named_region_map.borrow_mut(); + named_region_map.get().insert(lifetime_ref.id, def); } } diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 745c9a2a29a7d..949a4369f0b3c 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -219,6 +219,7 @@ use middle::ty; use util::common::indenter; use util::ppaux::{Repr, vec_map_to_str}; +use std::cell::Cell; use std::hashmap::HashMap; use std::ptr; use std::vec; @@ -310,7 +311,7 @@ pub enum opt_result { lower_bound(Result), range_result(Result, Result), } -fn trans_opt(bcx: @mut Block, o: &Opt) -> opt_result { +fn trans_opt(bcx: @Block, o: &Opt) -> opt_result { let _icx = push_ctxt("match::trans_opt"); let ccx = bcx.ccx(); let bcx = bcx; @@ -345,10 +346,11 @@ fn trans_opt(bcx: @mut Block, o: &Opt) -> opt_result { } } -fn variant_opt(bcx: @mut Block, pat_id: ast::NodeId) +fn variant_opt(bcx: @Block, pat_id: ast::NodeId) -> Opt { let ccx = bcx.ccx(); - match ccx.tcx.def_map.get_copy(&pat_id) { + let def_map = ccx.tcx.def_map.borrow(); + match def_map.get().get_copy(&pat_id) { ast::DefVariant(enum_id, var_id, _) => { let variants = ty::enum_variants(ccx.tcx, enum_id); for v in (*variants).iter() { @@ -396,7 +398,7 @@ type BindingsMap = HashMap; #[deriving(Clone)] struct ArmData<'a> { - bodycx: @mut Block, + bodycx: @Block, arm: &'a ast::Arm, bindings_map: @BindingsMap } @@ -435,7 +437,7 @@ fn has_nested_bindings(m: &[Match], col: uint) -> bool { return false; } -fn expand_nested_bindings<'r>(bcx: @mut Block, +fn expand_nested_bindings<'r>(bcx: @Block, m: &[Match<'r>], col: uint, val: ValueRef) @@ -469,7 +471,7 @@ fn expand_nested_bindings<'r>(bcx: @mut Block, }) } -fn assert_is_binding_or_wild(bcx: @mut Block, p: @ast::Pat) { +fn assert_is_binding_or_wild(bcx: @Block, p: @ast::Pat) { if !pat_is_binding_or_wild(bcx.tcx().def_map, p) { bcx.sess().span_bug( p.span, @@ -480,7 +482,7 @@ fn assert_is_binding_or_wild(bcx: @mut Block, p: @ast::Pat) { type enter_pat<'a> = 'a |@ast::Pat| -> Option<~[@ast::Pat]>; -fn enter_match<'r>(bcx: @mut Block, +fn enter_match<'r>(bcx: @Block, dm: DefMap, m: &[Match<'r>], col: uint, @@ -529,7 +531,7 @@ fn enter_match<'r>(bcx: @mut Block, return result; } -fn enter_default<'r>(bcx: @mut Block, +fn enter_default<'r>(bcx: @Block, dm: DefMap, m: &[Match<'r>], col: uint, @@ -599,7 +601,7 @@ fn enter_default<'r>(bcx: @mut Block, // so all patterns must either be records (resp. tuples) or // wildcards -fn enter_opt<'r>(bcx: @mut Block, +fn enter_opt<'r>(bcx: @Block, m: &[Match<'r>], opt: &Opt, col: uint, @@ -621,7 +623,10 @@ fn enter_opt<'r>(bcx: @mut Block, let answer = match p.node { ast::PatEnum(..) | ast::PatIdent(_, _, None) if pat_is_const(tcx.def_map, p) => { - let const_def = tcx.def_map.get_copy(&p.id); + let const_def = { + let def_map = tcx.def_map.borrow(); + def_map.get().get_copy(&p.id) + }; let const_def_id = ast_util::def_id_of_def(const_def); if opt_eq(tcx, &lit(ConstLit(const_def_id)), opt) { Some(~[]) @@ -658,7 +663,11 @@ fn enter_opt<'r>(bcx: @mut Block, if opt_eq(tcx, &variant_opt(bcx, p.id), opt) { // Look up the struct variant ID. let struct_id; - match tcx.def_map.get_copy(&p.id) { + let defn = { + let def_map = tcx.def_map.borrow(); + def_map.get().get_copy(&p.id) + }; + match defn { ast::DefVariant(_, found_struct_id, _) => { struct_id = found_struct_id; } @@ -735,7 +744,7 @@ fn enter_opt<'r>(bcx: @mut Block, }) } -fn enter_rec_or_struct<'r>(bcx: @mut Block, +fn enter_rec_or_struct<'r>(bcx: @Block, dm: DefMap, m: &[Match<'r>], col: uint, @@ -770,7 +779,7 @@ fn enter_rec_or_struct<'r>(bcx: @mut Block, }) } -fn enter_tup<'r>(bcx: @mut Block, +fn enter_tup<'r>(bcx: @Block, dm: DefMap, m: &[Match<'r>], col: uint, @@ -796,7 +805,7 @@ fn enter_tup<'r>(bcx: @mut Block, }) } -fn enter_tuple_struct<'r>(bcx: @mut Block, +fn enter_tuple_struct<'r>(bcx: @Block, dm: DefMap, m: &[Match<'r>], col: uint, @@ -822,7 +831,7 @@ fn enter_tuple_struct<'r>(bcx: @mut Block, }) } -fn enter_box<'r>(bcx: @mut Block, +fn enter_box<'r>(bcx: @Block, dm: DefMap, m: &[Match<'r>], col: uint, @@ -849,7 +858,7 @@ fn enter_box<'r>(bcx: @mut Block, }) } -fn enter_uniq<'r>(bcx: @mut Block, +fn enter_uniq<'r>(bcx: @Block, dm: DefMap, m: &[Match<'r>], col: uint, @@ -876,7 +885,7 @@ fn enter_uniq<'r>(bcx: @mut Block, }) } -fn enter_region<'r>(bcx: @mut Block, +fn enter_region<'r>(bcx: @Block, dm: DefMap, m: &[Match<'r>], col: uint, @@ -906,7 +915,7 @@ fn enter_region<'r>(bcx: @mut Block, // Returns the options in one column of matches. An option is something that // needs to be conditionally matched at runtime; for example, the discriminant // on a set of enum variants or a literal. -fn get_options(bcx: @mut Block, m: &[Match], col: uint) -> ~[Opt] { +fn get_options(bcx: @Block, m: &[Match], col: uint) -> ~[Opt] { let ccx = bcx.ccx(); fn add_to_set(tcx: ty::ctxt, set: &mut ~[Opt], val: Opt) { if set.iter().any(|l| opt_eq(tcx, l, &val)) {return;} @@ -939,16 +948,20 @@ fn get_options(bcx: @mut Block, m: &[Match], col: uint) -> ~[Opt] { ast::PatIdent(..) => { // This is one of: an enum variant, a unit-like struct, or a // variable binding. - match ccx.tcx.def_map.find(&cur.id) { - Some(&ast::DefVariant(..)) => { + let opt_def = { + let def_map = ccx.tcx.def_map.borrow(); + def_map.get().find_copy(&cur.id) + }; + match opt_def { + Some(ast::DefVariant(..)) => { add_to_set(ccx.tcx, &mut found, variant_opt(bcx, cur.id)); } - Some(&ast::DefStruct(..)) => { + Some(ast::DefStruct(..)) => { add_to_set(ccx.tcx, &mut found, lit(UnitLikeStructLit(cur.id))); } - Some(&ast::DefStatic(const_did, false)) => { + Some(ast::DefStatic(const_did, false)) => { add_to_set(ccx.tcx, &mut found, lit(ConstLit(const_did))); } @@ -958,13 +971,17 @@ fn get_options(bcx: @mut Block, m: &[Match], col: uint) -> ~[Opt] { ast::PatEnum(..) | ast::PatStruct(..) => { // This could be one of: a tuple-like enum variant, a // struct-like enum variant, or a struct. - match ccx.tcx.def_map.find(&cur.id) { - Some(&ast::DefFn(..)) | - Some(&ast::DefVariant(..)) => { + let opt_def = { + let def_map = ccx.tcx.def_map.borrow(); + def_map.get().find_copy(&cur.id) + }; + match opt_def { + Some(ast::DefFn(..)) | + Some(ast::DefVariant(..)) => { add_to_set(ccx.tcx, &mut found, variant_opt(bcx, cur.id)); } - Some(&ast::DefStatic(const_did, false)) => { + Some(ast::DefStatic(const_did, false)) => { add_to_set(ccx.tcx, &mut found, lit(ConstLit(const_did))); } @@ -990,10 +1007,10 @@ fn get_options(bcx: @mut Block, m: &[Match], col: uint) -> ~[Opt] { struct ExtractedBlock { vals: ~[ValueRef], - bcx: @mut Block + bcx: @Block } -fn extract_variant_args(bcx: @mut Block, +fn extract_variant_args(bcx: @Block, repr: &adt::Repr, disr_val: ty::Disr, val: ValueRef) @@ -1006,7 +1023,7 @@ fn extract_variant_args(bcx: @mut Block, ExtractedBlock { vals: args, bcx: bcx } } -fn match_datum(bcx: @mut Block, val: ValueRef, pat_id: ast::NodeId) -> Datum { +fn match_datum(bcx: @Block, val: ValueRef, pat_id: ast::NodeId) -> Datum { //! Helper for converting from the ValueRef that we pass around in //! the match code, which is always by ref, into a Datum. Eventually //! we should just pass around a Datum and be done with it. @@ -1016,7 +1033,7 @@ fn match_datum(bcx: @mut Block, val: ValueRef, pat_id: ast::NodeId) -> Datum { } -fn extract_vec_elems(bcx: @mut Block, +fn extract_vec_elems(bcx: @Block, pat_span: Span, pat_id: ast::NodeId, elem_count: uint, @@ -1069,7 +1086,7 @@ fn extract_vec_elems(bcx: @mut Block, /// Function returns None if there is no struct pattern. /// Function doesn't collect fields from struct-like enum variants. /// Function can return empty list if there is only wildcard struct pattern. -fn collect_record_or_struct_fields(bcx: @mut Block, +fn collect_record_or_struct_fields(bcx: @Block, m: &[Match], col: uint) -> Option<~[ast::Ident]> { @@ -1105,22 +1122,23 @@ fn collect_record_or_struct_fields(bcx: @mut Block, } } -fn pats_require_rooting(bcx: @mut Block, +fn pats_require_rooting(bcx: @Block, m: &[Match], col: uint) -> bool { m.iter().any(|br| { let pat_id = br.pats[col].id; let key = root_map_key {id: pat_id, derefs: 0u }; - bcx.ccx().maps.root_map.contains_key(&key) + let root_map = bcx.ccx().maps.root_map.borrow(); + root_map.get().contains_key(&key) }) } -fn root_pats_as_necessary(mut bcx: @mut Block, +fn root_pats_as_necessary(mut bcx: @Block, m: &[Match], col: uint, val: ValueRef) - -> @mut Block { + -> @Block { for br in m.iter() { let pat_id = br.pats[col].id; if pat_id != 0 { @@ -1163,12 +1181,13 @@ fn any_tup_pat(m: &[Match], col: uint) -> bool { any_pat!(m, ast::PatTup(_)) } -fn any_tuple_struct_pat(bcx: @mut Block, m: &[Match], col: uint) -> bool { +fn any_tuple_struct_pat(bcx: @Block, m: &[Match], col: uint) -> bool { m.iter().any(|br| { let pat = br.pats[col]; match pat.node { ast::PatEnum(_, Some(_)) => { - match bcx.tcx().def_map.find(&pat.id) { + let def_map = bcx.tcx().def_map.borrow(); + match def_map.get().find(&pat.id) { Some(&ast::DefFn(..)) | Some(&ast::DefStruct(..)) => true, _ => false @@ -1184,22 +1203,22 @@ trait CustomFailureHandler { } struct DynamicFailureHandler { - bcx: @mut Block, + bcx: @Block, sp: Span, msg: @str, - finished: @mut Option, + finished: @Cell>, } impl CustomFailureHandler for DynamicFailureHandler { fn handle_fail(&self) -> BasicBlockRef { - match *self.finished { + match self.finished.get() { Some(bb) => return bb, _ => (), } let fail_cx = sub_block(self.bcx, "case_fallthrough"); controlflow::trans_fail(fail_cx, Some(self.sp), self.msg); - *self.finished = Some(fail_cx.llbb); + self.finished.set(Some(fail_cx.llbb)); fail_cx.llbb } } @@ -1271,7 +1290,7 @@ pub enum branch_kind { no_branch, single, switch, compare, compare_vec_len, } // Compiles a comparison between two things. // // NB: This must produce an i1, not a Rust bool (i8). -fn compare_values(cx: @mut Block, +fn compare_values(cx: @Block, lhs: ValueRef, rhs: ValueRef, rhs_t: ty::t) @@ -1314,10 +1333,10 @@ fn compare_values(cx: @mut Block, } } -fn store_non_ref_bindings(bcx: @mut Block, +fn store_non_ref_bindings(bcx: @Block, bindings_map: &BindingsMap, mut opt_temp_cleanups: Option<&mut ~[ValueRef]>) - -> @mut Block + -> @Block { /*! * @@ -1348,17 +1367,15 @@ fn store_non_ref_bindings(bcx: @mut Block, return bcx; } -fn insert_lllocals(bcx: @mut Block, +fn insert_lllocals(bcx: @Block, bindings_map: &BindingsMap, - add_cleans: bool) -> @mut Block { + add_cleans: bool) -> @Block { /*! * For each binding in `data.bindings_map`, adds an appropriate entry into * the `fcx.lllocals` map. If add_cleans is true, then adds cleanups for * the bindings. */ - let llmap = bcx.fcx.lllocals; - for (&ident, &binding_info) in bindings_map.iter() { let llval = match binding_info.trmode { // By value bindings: use the stack slot that we @@ -1377,8 +1394,13 @@ fn insert_lllocals(bcx: @mut Block, } }; - debug!("binding {:?} to {}", binding_info.id, bcx.val_to_str(llval)); - llmap.insert(binding_info.id, llval); + { + debug!("binding {:?} to {}", + binding_info.id, + bcx.val_to_str(llval)); + let mut llmap = bcx.fcx.lllocals.borrow_mut(); + llmap.get().insert(binding_info.id, llval); + } if bcx.sess().opts.extra_debuginfo { debuginfo::create_match_binding_metadata(bcx, @@ -1391,13 +1413,13 @@ fn insert_lllocals(bcx: @mut Block, return bcx; } -fn compile_guard(bcx: @mut Block, +fn compile_guard(bcx: @Block, guard_expr: &ast::Expr, data: &ArmData, m: &[Match], vals: &[ValueRef], chk: FailureHandler) - -> @mut Block { + -> @Block { debug!("compile_guard(bcx={}, guard_expr={}, m={}, vals={})", bcx.to_str(), bcx.expr_to_str(guard_expr), @@ -1432,7 +1454,7 @@ fn compile_guard(bcx: @mut Block, bcx }); - fn drop_bindings(bcx: @mut Block, data: &ArmData) -> @mut Block { + fn drop_bindings(bcx: @Block, data: &ArmData) -> @Block { let mut bcx = bcx; for (_, &binding_info) in data.bindings_map.iter() { match binding_info.trmode { @@ -1441,13 +1463,14 @@ fn compile_guard(bcx: @mut Block, } TrByRef => {} } - bcx.fcx.lllocals.remove(&binding_info.id); + let mut lllocals = bcx.fcx.lllocals.borrow_mut(); + lllocals.get().remove(&binding_info.id); } return bcx; } } -fn compile_submatch(bcx: @mut Block, +fn compile_submatch(bcx: @Block, m: &[Match], vals: &[ValueRef], chk: FailureHandler) { @@ -1499,7 +1522,7 @@ fn compile_submatch(bcx: @mut Block, } } -fn compile_submatch_continue(mut bcx: @mut Block, +fn compile_submatch_continue(mut bcx: @Block, m: &[Match], vals: &[ValueRef], chk: FailureHandler, @@ -1816,18 +1839,18 @@ fn compile_submatch_continue(mut bcx: @mut Block, } } -pub fn trans_match(bcx: @mut Block, +pub fn trans_match(bcx: @Block, match_expr: &ast::Expr, discr_expr: &ast::Expr, arms: &[ast::Arm], - dest: Dest) -> @mut Block { + dest: Dest) -> @Block { let _icx = push_ctxt("match::trans_match"); with_scope(bcx, match_expr.info(), "match", |bcx| { trans_match_inner(bcx, discr_expr, arms, dest) }) } -fn create_bindings_map(bcx: @mut Block, pat: @ast::Pat) -> BindingsMap { +fn create_bindings_map(bcx: @Block, pat: @ast::Pat) -> BindingsMap { // Create the bindings map, which is a mapping from each binding name // to an alloca() that will be the value for that local variable. // Note that we use the names because each binding will have many ids @@ -1867,10 +1890,10 @@ fn create_bindings_map(bcx: @mut Block, pat: @ast::Pat) -> BindingsMap { return bindings_map; } -fn trans_match_inner(scope_cx: @mut Block, +fn trans_match_inner(scope_cx: @Block, discr_expr: &ast::Expr, arms: &[ast::Arm], - dest: Dest) -> @mut Block { + dest: Dest) -> @Block { let _icx = push_ctxt("match::trans_match_inner"); let mut bcx = scope_cx; let tcx = bcx.tcx(); @@ -1878,7 +1901,7 @@ fn trans_match_inner(scope_cx: @mut Block, let discr_datum = unpack_datum!(bcx, { expr::trans_to_datum(bcx, discr_expr) }); - if bcx.unreachable { + if bcx.unreachable.get() { return bcx; } @@ -1906,7 +1929,7 @@ fn trans_match_inner(scope_cx: @mut Block, let chk = { if ty::type_is_empty(tcx, t) { // Special case for empty types - let fail_cx = @mut None; + let fail_cx = @Cell::new(None); let fail_handler = @DynamicFailureHandler { bcx: scope_cx, sp: discr_expr.span, @@ -1952,10 +1975,10 @@ enum IrrefutablePatternBindingMode { BindArgument } -pub fn store_local(bcx: @mut Block, +pub fn store_local(bcx: @Block, pat: @ast::Pat, opt_init_expr: Option<@ast::Expr>) - -> @mut Block { + -> @Block { /*! * Generates code for a local variable declaration like * `let ;` or `let = `. @@ -2006,7 +2029,7 @@ pub fn store_local(bcx: @mut Block, } }; - fn create_dummy_locals(mut bcx: @mut Block, pat: @ast::Pat) -> @mut Block { + fn create_dummy_locals(mut bcx: @Block, pat: @ast::Pat) -> @Block { // create dummy memory for the variables if we have no // value to store into them immediately let tcx = bcx.tcx(); @@ -2019,10 +2042,10 @@ pub fn store_local(bcx: @mut Block, } } -pub fn store_arg(mut bcx: @mut Block, +pub fn store_arg(mut bcx: @Block, pat: @ast::Pat, llval: ValueRef) - -> @mut Block { + -> @Block { /*! * Generates code for argument patterns like `fn foo(: T)`. * Creates entries in the `llargs` map for each of the bindings @@ -2056,7 +2079,8 @@ pub fn store_arg(mut bcx: @mut Block, // Optimized path for `x: T` case. This just adopts // `llval` wholesale as the pointer for `x`, avoiding the // general logic which may copy out of `llval`. - bcx.fcx.llargs.insert(pat.id, llval); + let mut llargs = bcx.fcx.llargs.borrow_mut(); + llargs.get().insert(pat.id, llval); } else { // General path. Copy out the values that are used in the // pattern. @@ -2066,30 +2090,30 @@ pub fn store_arg(mut bcx: @mut Block, return bcx; } -fn mk_binding_alloca(mut bcx: @mut Block, +fn mk_binding_alloca(mut bcx: @Block, p_id: ast::NodeId, path: &ast::Path, binding_mode: IrrefutablePatternBindingMode, - populate: |@mut Block, ty::t, ValueRef| -> @mut Block) - -> @mut Block { + populate: |@Block, ty::t, ValueRef| -> @Block) + -> @Block { let var_ty = node_id_type(bcx, p_id); let ident = ast_util::path_to_ident(path); let llval = alloc_ty(bcx, var_ty, bcx.ident(ident)); bcx = populate(bcx, var_ty, llval); - let llmap = match binding_mode { - BindLocal => bcx.fcx.lllocals, - BindArgument => bcx.fcx.llargs + let mut llmap = match binding_mode { + BindLocal => bcx.fcx.lllocals.borrow_mut(), + BindArgument => bcx.fcx.llargs.borrow_mut(), }; - llmap.insert(p_id, llval); + llmap.get().insert(p_id, llval); add_clean(bcx, llval, var_ty); return bcx; } -fn bind_irrefutable_pat(bcx: @mut Block, +fn bind_irrefutable_pat(bcx: @Block, pat: @ast::Pat, val: ValueRef, binding_mode: IrrefutablePatternBindingMode) - -> @mut Block { + -> @Block { /*! * A simple version of the pattern matching code that only handles * irrefutable patterns. This is used in let/argument patterns, @@ -2159,7 +2183,8 @@ fn bind_irrefutable_pat(bcx: @mut Block, } } ast::PatEnum(_, ref sub_pats) => { - match bcx.tcx().def_map.find(&pat.id) { + let def_map = bcx.tcx().def_map.borrow(); + match def_map.get().find(&pat.id) { Some(&ast::DefVariant(enum_id, var_id, _)) => { let repr = adt::represent_node(bcx, pat.id); let vinfo = ty::enum_variant_with_id(ccx.tcx, diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index 7893a63fa5d53..5d70a3ad2664c 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -111,24 +111,29 @@ pub struct Struct { * these, for places in trans where the `ty::t` isn't directly * available. */ -pub fn represent_node(bcx: @mut Block, node: ast::NodeId) -> @Repr { +pub fn represent_node(bcx: @Block, node: ast::NodeId) -> @Repr { represent_type(bcx.ccx(), node_id_type(bcx, node)) } /// Decides how to represent a given type. -pub fn represent_type(cx: &mut CrateContext, t: ty::t) -> @Repr { +pub fn represent_type(cx: &CrateContext, t: ty::t) -> @Repr { debug!("Representing: {}", ty_to_str(cx.tcx, t)); - match cx.adt_reprs.find(&t) { - Some(repr) => return *repr, - None => { } + { + let adt_reprs = cx.adt_reprs.borrow(); + match adt_reprs.get().find(&t) { + Some(repr) => return *repr, + None => {} + } } + let repr = @represent_type_uncached(cx, t); debug!("Represented as: {:?}", repr) - cx.adt_reprs.insert(t, repr); + let mut adt_reprs = cx.adt_reprs.borrow_mut(); + adt_reprs.get().insert(t, repr); return repr; } -fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr { +fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr { match ty::get(t).sty { ty::ty_tup(ref elems) => { return Univariant(mk_struct(cx, *elems, false), false) @@ -250,7 +255,7 @@ pub fn is_ffi_safe(tcx: ty::ctxt, def_id: ast::DefId) -> bool { // this should probably all be in ty struct Case { discr: Disr, tys: ~[ty::t] } impl Case { - fn is_zerolen(&self, cx: &mut CrateContext) -> bool { + fn is_zerolen(&self, cx: &CrateContext) -> bool { mk_struct(cx, self.tys, false).size == 0 } fn find_ptr(&self) -> Option { @@ -268,7 +273,7 @@ fn get_cases(tcx: ty::ctxt, def_id: ast::DefId, substs: &ty::substs) -> ~[Case] } -fn mk_struct(cx: &mut CrateContext, tys: &[ty::t], packed: bool) -> Struct { +fn mk_struct(cx: &CrateContext, tys: &[ty::t], packed: bool) -> Struct { let lltys = tys.map(|&ty| type_of::sizing_type_of(cx, ty)); let llty_rec = Type::struct_(lltys, packed); Struct { @@ -286,7 +291,7 @@ struct IntBounds { uhi: u64 } -fn mk_cenum(cx: &mut CrateContext, hint: Hint, bounds: &IntBounds) -> Repr { +fn mk_cenum(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> Repr { let it = range_to_inttype(cx, hint, bounds); match it { attr::SignedInt(_) => CEnum(it, bounds.slo as Disr, bounds.shi as Disr), @@ -294,7 +299,7 @@ fn mk_cenum(cx: &mut CrateContext, hint: Hint, bounds: &IntBounds) -> Repr { } } -fn range_to_inttype(cx: &mut CrateContext, hint: Hint, bounds: &IntBounds) -> IntType { +fn range_to_inttype(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> IntType { debug!("range_to_inttype: {:?} {:?}", hint, bounds); // Lists of sizes to try. u64 is always allowed as a fallback. static choose_shortest: &'static[IntType] = &[ @@ -334,14 +339,14 @@ fn range_to_inttype(cx: &mut CrateContext, hint: Hint, bounds: &IntBounds) -> In return attr::UnsignedInt(ast::ty_u64); } -pub fn ll_inttype(cx: &mut CrateContext, ity: IntType) -> Type { +pub fn ll_inttype(cx: &CrateContext, ity: IntType) -> Type { match ity { attr::SignedInt(t) => Type::int_from_ty(cx, t), attr::UnsignedInt(t) => Type::uint_from_ty(cx, t) } } -fn bounds_usable(cx: &mut CrateContext, ity: IntType, bounds: &IntBounds) -> bool { +fn bounds_usable(cx: &CrateContext, ity: IntType, bounds: &IntBounds) -> bool { debug!("bounds_usable: {:?} {:?}", ity, bounds); match ity { attr::SignedInt(_) => { @@ -375,16 +380,16 @@ pub fn ty_of_inttype(ity: IntType) -> ty::t { * and fill in the actual contents in a second pass to prevent * unbounded recursion; see also the comments in `trans::type_of`. */ -pub fn type_of(cx: &mut CrateContext, r: &Repr) -> Type { +pub fn type_of(cx: &CrateContext, r: &Repr) -> Type { generic_type_of(cx, r, None, false) } -pub fn sizing_type_of(cx: &mut CrateContext, r: &Repr) -> Type { +pub fn sizing_type_of(cx: &CrateContext, r: &Repr) -> Type { generic_type_of(cx, r, None, true) } -pub fn incomplete_type_of(cx: &mut CrateContext, r: &Repr, name: &str) -> Type { +pub fn incomplete_type_of(cx: &CrateContext, r: &Repr, name: &str) -> Type { generic_type_of(cx, r, Some(name), false) } -pub fn finish_type_of(cx: &mut CrateContext, r: &Repr, llty: &mut Type) { +pub fn finish_type_of(cx: &CrateContext, r: &Repr, llty: &mut Type) { match *r { CEnum(..) | General(..) => { } Univariant(ref st, _) | NullablePointer{ nonnull: ref st, .. } => @@ -392,7 +397,7 @@ pub fn finish_type_of(cx: &mut CrateContext, r: &Repr, llty: &mut Type) { } } -fn generic_type_of(cx: &mut CrateContext, r: &Repr, name: Option<&str>, sizing: bool) -> Type { +fn generic_type_of(cx: &CrateContext, r: &Repr, name: Option<&str>, sizing: bool) -> Type { match *r { CEnum(ity, _, _) => ll_inttype(cx, ity), Univariant(ref st, _) | NullablePointer{ nonnull: ref st, .. } => { @@ -444,7 +449,7 @@ fn generic_type_of(cx: &mut CrateContext, r: &Repr, name: Option<&str>, sizing: } } -fn struct_llfields(cx: &mut CrateContext, st: &Struct, sizing: bool) -> ~[Type] { +fn struct_llfields(cx: &CrateContext, st: &Struct, sizing: bool) -> ~[Type] { if sizing { st.fields.map(|&ty| type_of::sizing_type_of(cx, ty)) } else { @@ -458,7 +463,7 @@ fn struct_llfields(cx: &mut CrateContext, st: &Struct, sizing: bool) -> ~[Type] * * This should ideally be less tightly tied to `_match`. */ -pub fn trans_switch(bcx: @mut Block, r: &Repr, scrutinee: ValueRef) +pub fn trans_switch(bcx: @Block, r: &Repr, scrutinee: ValueRef) -> (_match::branch_kind, Option) { match *r { CEnum(..) | General(..) => { @@ -476,7 +481,7 @@ pub fn trans_switch(bcx: @mut Block, r: &Repr, scrutinee: ValueRef) /// Obtain the actual discriminant of a value. -pub fn trans_get_discr(bcx: @mut Block, r: &Repr, scrutinee: ValueRef, cast_to: Option) +pub fn trans_get_discr(bcx: @Block, r: &Repr, scrutinee: ValueRef, cast_to: Option) -> ValueRef { let signed; let val; @@ -505,7 +510,7 @@ pub fn trans_get_discr(bcx: @mut Block, r: &Repr, scrutinee: ValueRef, cast_to: } } -fn nullable_bitdiscr(bcx: @mut Block, nonnull: &Struct, nndiscr: Disr, ptrfield: uint, +fn nullable_bitdiscr(bcx: @Block, nonnull: &Struct, nndiscr: Disr, ptrfield: uint, scrutinee: ValueRef) -> ValueRef { let cmp = if nndiscr == 0 { IntEQ } else { IntNE }; let llptr = Load(bcx, GEPi(bcx, scrutinee, [0, ptrfield])); @@ -514,7 +519,7 @@ fn nullable_bitdiscr(bcx: @mut Block, nonnull: &Struct, nndiscr: Disr, ptrfield: } /// Helper for cases where the discriminant is simply loaded. -fn load_discr(bcx: @mut Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr) +fn load_discr(bcx: @Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr) -> ValueRef { let llty = ll_inttype(bcx.ccx(), ity); assert_eq!(val_ty(ptr), llty.ptr_to()); @@ -542,7 +547,7 @@ fn load_discr(bcx: @mut Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr * * This should ideally be less tightly tied to `_match`. */ -pub fn trans_case(bcx: @mut Block, r: &Repr, discr: Disr) -> _match::opt_result { +pub fn trans_case(bcx: @Block, r: &Repr, discr: Disr) -> _match::opt_result { match *r { CEnum(ity, _, _) => { _match::single_result(rslt(bcx, C_integral(ll_inttype(bcx.ccx(), ity), @@ -567,7 +572,7 @@ pub fn trans_case(bcx: @mut Block, r: &Repr, discr: Disr) -> _match::opt_result * representation. The fields, if any, should then be initialized via * `trans_field_ptr`. */ -pub fn trans_start_init(bcx: @mut Block, r: &Repr, val: ValueRef, discr: Disr) { +pub fn trans_start_init(bcx: @Block, r: &Repr, val: ValueRef, discr: Disr) { match *r { CEnum(ity, min, max) => { assert_discr_in_range(ity, min, max, discr); @@ -623,7 +628,7 @@ pub fn num_args(r: &Repr, discr: Disr) -> uint { } /// Access a field, at a point when the value's case is known. -pub fn trans_field_ptr(bcx: @mut Block, r: &Repr, val: ValueRef, discr: Disr, +pub fn trans_field_ptr(bcx: @Block, r: &Repr, val: ValueRef, discr: Disr, ix: uint) -> ValueRef { // Note: if this ever needs to generate conditionals (e.g., if we // decide to do some kind of cdr-coding-like non-unique repr @@ -656,7 +661,7 @@ pub fn trans_field_ptr(bcx: @mut Block, r: &Repr, val: ValueRef, discr: Disr, } } -fn struct_field_ptr(bcx: @mut Block, st: &Struct, val: ValueRef, ix: uint, +fn struct_field_ptr(bcx: @Block, st: &Struct, val: ValueRef, ix: uint, needs_cast: bool) -> ValueRef { let ccx = bcx.ccx(); @@ -672,7 +677,7 @@ fn struct_field_ptr(bcx: @mut Block, st: &Struct, val: ValueRef, ix: uint, } /// Access the struct drop flag, if present. -pub fn trans_drop_flag_ptr(bcx: @mut Block, r: &Repr, val: ValueRef) -> ValueRef { +pub fn trans_drop_flag_ptr(bcx: @Block, r: &Repr, val: ValueRef) -> ValueRef { match *r { Univariant(ref st, true) => GEPi(bcx, val, [0, st.fields.len() - 1]), _ => bcx.ccx().sess.bug("tried to get drop flag of non-droppable type") @@ -700,7 +705,7 @@ pub fn trans_drop_flag_ptr(bcx: @mut Block, r: &Repr, val: ValueRef) -> ValueRef * this could be changed in the future to avoid allocating unnecessary * space after values of shorter-than-maximum cases. */ -pub fn trans_const(ccx: &mut CrateContext, r: &Repr, discr: Disr, +pub fn trans_const(ccx: &CrateContext, r: &Repr, discr: Disr, vals: &[ValueRef]) -> ValueRef { match *r { CEnum(ity, min, max) => { @@ -745,7 +750,7 @@ pub fn trans_const(ccx: &mut CrateContext, r: &Repr, discr: Disr, * a two-element struct will locate it at offset 4, and accesses to it * will read the wrong memory. */ -fn build_const_struct(ccx: &mut CrateContext, st: &Struct, vals: &[ValueRef]) +fn build_const_struct(ccx: &CrateContext, st: &Struct, vals: &[ValueRef]) -> ~[ValueRef] { assert_eq!(vals.len(), st.fields.len()); @@ -786,7 +791,7 @@ fn padding(size: u64) -> ValueRef { fn roundup(x: u64, a: u64) -> u64 { ((x + (a - 1)) / a) * a } /// Get the discriminant of a constant value. (Not currently used.) -pub fn const_get_discrim(ccx: &mut CrateContext, r: &Repr, val: ValueRef) +pub fn const_get_discrim(ccx: &CrateContext, r: &Repr, val: ValueRef) -> Disr { match *r { CEnum(ity, _, _) => { @@ -820,7 +825,7 @@ pub fn const_get_discrim(ccx: &mut CrateContext, r: &Repr, val: ValueRef) * (Not to be confused with `common::const_get_elt`, which operates on * raw LLVM-level structs and arrays.) */ -pub fn const_get_field(ccx: &mut CrateContext, r: &Repr, val: ValueRef, +pub fn const_get_field(ccx: &CrateContext, r: &Repr, val: ValueRef, _discr: Disr, ix: uint) -> ValueRef { match *r { CEnum(..) => ccx.sess.bug("element access in C-like enum const"), @@ -831,7 +836,7 @@ pub fn const_get_field(ccx: &mut CrateContext, r: &Repr, val: ValueRef, } /// Extract field of struct-like const, skipping our alignment padding. -fn const_struct_field(ccx: &mut CrateContext, val: ValueRef, ix: uint) +fn const_struct_field(ccx: &CrateContext, val: ValueRef, ix: uint) -> ValueRef { // Get the ix-th non-undef element of the struct. let mut real_ix = 0; // actual position in the struct diff --git a/src/librustc/middle/trans/asm.rs b/src/librustc/middle/trans/asm.rs index 7b936b61976bc..5dd7c0c3b44f1 100644 --- a/src/librustc/middle/trans/asm.rs +++ b/src/librustc/middle/trans/asm.rs @@ -27,7 +27,7 @@ use middle::trans::type_::Type; use syntax::ast; // Take an inline assembly expression and splat it out via LLVM -pub fn trans_inline_asm(bcx: @mut Block, ia: &ast::inline_asm) -> @mut Block { +pub fn trans_inline_asm(bcx: @Block, ia: &ast::inline_asm) -> @Block { let mut bcx = bcx; let mut constraints = ~[]; diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 9076b0a37557d..0b2ee710e9913 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -69,6 +69,7 @@ use util::sha2::Sha256; use middle::trans::type_::Type; use std::c_str::ToCStr; +use std::cell::{Cell, RefCell}; use std::hashmap::HashMap; use std::libc::c_uint; use std::vec; @@ -131,21 +132,21 @@ pub fn push_ctxt(s: &'static str) -> _InsnCtxt { } pub struct StatRecorder<'a> { - ccx: @mut CrateContext, + ccx: @CrateContext, name: &'a str, start: u64, istart: uint, } impl<'a> StatRecorder<'a> { - pub fn new(ccx: @mut CrateContext, + pub fn new(ccx: @CrateContext, name: &'a str) -> StatRecorder<'a> { let start = if ccx.sess.trans_stats() { time::precise_time_ns() } else { 0 }; - let istart = ccx.stats.n_llvm_insns; + let istart = ccx.stats.n_llvm_insns.get(); StatRecorder { ccx: ccx, name: name, @@ -161,13 +162,16 @@ impl<'a> Drop for StatRecorder<'a> { if self.ccx.sess.trans_stats() { let end = time::precise_time_ns(); let elapsed = ((end - self.start) / 1_000_000) as uint; - let iend = self.ccx.stats.n_llvm_insns; - self.ccx.stats.fn_stats.push((self.name.to_owned(), - elapsed, - iend - self.istart)); - self.ccx.stats.n_fns += 1; + let iend = self.ccx.stats.n_llvm_insns.get(); + { + let mut fn_stats = self.ccx.stats.fn_stats.borrow_mut(); + fn_stats.get().push((self.name.to_owned(), + elapsed, + iend - self.istart)); + } + self.ccx.stats.n_fns.set(self.ccx.stats.n_fns.get() + 1); // Reset LLVM insn count to avoid compound costs. - self.ccx.stats.n_llvm_insns = self.istart; + self.ccx.stats.n_llvm_insns.set(self.istart); } } } @@ -203,21 +207,27 @@ pub fn get_extern_fn(externs: &mut ExternMap, llmod: ModuleRef, name: &str, f } -fn get_extern_rust_fn(ccx: &mut CrateContext, inputs: &[ty::t], output: ty::t, +fn get_extern_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t, name: &str, did: ast::DefId) -> ValueRef { - match ccx.externs.find_equiv(&name) { - Some(n) => return *n, - None => () + { + let externs = ccx.externs.borrow(); + match externs.get().find_equiv(&name) { + Some(n) => return *n, + None => () + } } + let f = decl_rust_fn(ccx, inputs, output, name); csearch::get_item_attrs(ccx.tcx.cstore, did, |meta_items| { set_llvm_fn_attrs(meta_items.iter().map(|&x| attr::mk_attr(x)).to_owned_vec(), f) }); - ccx.externs.insert(name.to_owned(), f); + + let mut externs = ccx.externs.borrow_mut(); + externs.get().insert(name.to_owned(), f); f } -fn decl_rust_fn(ccx: &mut CrateContext, inputs: &[ty::t], output: ty::t, name: &str) -> ValueRef { +fn decl_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t, name: &str) -> ValueRef { let llfty = type_of_rust_fn(ccx, inputs, output); let llfn = decl_cdecl_fn(ccx.llmod, name, llfty); @@ -270,7 +280,7 @@ fn decl_rust_fn(ccx: &mut CrateContext, inputs: &[ty::t], output: ty::t, name: & llfn } -pub fn decl_internal_rust_fn(ccx: &mut CrateContext, inputs: &[ty::t], output: ty::t, +pub fn decl_internal_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t, name: &str) -> ValueRef { let llfn = decl_rust_fn(ccx, inputs, output, name); lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage); @@ -297,7 +307,7 @@ pub fn get_extern_const(externs: &mut ExternMap, llmod: ModuleRef, // known. // // The runtime equivalent is box_body() in "rust_internal.h". -pub fn opaque_box_body(bcx: @mut Block, +pub fn opaque_box_body(bcx: @Block, body_t: ty::t, boxptr: ValueRef) -> ValueRef { let _icx = push_ctxt("opaque_box_body"); @@ -310,14 +320,14 @@ pub fn opaque_box_body(bcx: @mut Block, // malloc_raw_dyn: allocates a box to contain a given type, but with a // potentially dynamic size. -pub fn malloc_raw_dyn(bcx: @mut Block, +pub fn malloc_raw_dyn(bcx: @Block, t: ty::t, heap: heap, size: ValueRef) -> Result { let _icx = push_ctxt("malloc_raw"); let ccx = bcx.ccx(); - fn require_alloc_fn(bcx: @mut Block, t: ty::t, it: LangItem) -> ast::DefId { + fn require_alloc_fn(bcx: @Block, t: ty::t, it: LangItem) -> ast::DefId { let li = &bcx.tcx().lang_items; match li.require(it) { Ok(id) => id, @@ -377,21 +387,21 @@ pub fn malloc_raw_dyn(bcx: @mut Block, // malloc_raw: expects an unboxed type and returns a pointer to // enough space for a box of that type. This includes a rust_opaque_box // header. -pub fn malloc_raw(bcx: @mut Block, t: ty::t, heap: heap) -> Result { +pub fn malloc_raw(bcx: @Block, t: ty::t, heap: heap) -> Result { let ty = type_of(bcx.ccx(), t); let size = llsize_of(bcx.ccx(), ty); malloc_raw_dyn(bcx, t, heap, size) } pub struct MallocResult { - bcx: @mut Block, + bcx: @Block, smart_ptr: ValueRef, body: ValueRef } // malloc_general_dyn: usefully wraps malloc_raw_dyn; allocates a smart // pointer, and pulls out the body -pub fn malloc_general_dyn(bcx: @mut Block, t: ty::t, heap: heap, size: ValueRef) +pub fn malloc_general_dyn(bcx: @Block, t: ty::t, heap: heap, size: ValueRef) -> MallocResult { assert!(heap != heap_exchange); let _icx = push_ctxt("malloc_general"); @@ -405,13 +415,13 @@ pub fn malloc_general_dyn(bcx: @mut Block, t: ty::t, heap: heap, size: ValueRef) } } -pub fn malloc_general(bcx: @mut Block, t: ty::t, heap: heap) -> MallocResult { +pub fn malloc_general(bcx: @Block, t: ty::t, heap: heap) -> MallocResult { let ty = type_of(bcx.ccx(), t); assert!(heap != heap_exchange); malloc_general_dyn(bcx, t, heap, llsize_of(bcx.ccx(), ty)) } -pub fn heap_for_unique(bcx: @mut Block, t: ty::t) -> heap { +pub fn heap_for_unique(bcx: @Block, t: ty::t) -> heap { if ty::type_contents(bcx.tcx(), t).owns_managed() { heap_managed_unique } else { @@ -419,7 +429,7 @@ pub fn heap_for_unique(bcx: @mut Block, t: ty::t) -> heap { } } -pub fn maybe_set_managed_unique_rc(bcx: @mut Block, bx: ValueRef, heap: heap) { +pub fn maybe_set_managed_unique_rc(bcx: @Block, bx: ValueRef, heap: heap) { assert!(heap != heap_exchange); if heap == heap_managed_unique { // In cases where we are looking at a unique-typed allocation in the @@ -434,21 +444,24 @@ pub fn maybe_set_managed_unique_rc(bcx: @mut Block, bx: ValueRef, heap: heap) { // Type descriptor and type glue stuff -pub fn get_tydesc_simple(ccx: &mut CrateContext, t: ty::t) -> ValueRef { +pub fn get_tydesc_simple(ccx: &CrateContext, t: ty::t) -> ValueRef { get_tydesc(ccx, t).tydesc } -pub fn get_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info { - match ccx.tydescs.find(&t) { - Some(&inf) => { - return inf; +pub fn get_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info { + { + let tydescs = ccx.tydescs.borrow(); + match tydescs.get().find(&t) { + Some(&inf) => return inf, + _ => { } } - _ => { } } - ccx.stats.n_static_tydescs += 1u; + ccx.stats.n_static_tydescs.set(ccx.stats.n_static_tydescs.get() + 1u); let inf = glue::declare_tydesc(ccx, t); - ccx.tydescs.insert(t, inf); + + let mut tydescs = ccx.tydescs.borrow_mut(); + tydescs.get().insert(t, inf); return inf; } @@ -506,15 +519,16 @@ pub fn set_no_split_stack(f: ValueRef) { // Double-check that we never ask LLVM to declare the same symbol twice. It // silently mangles such symbols, breaking our linkage model. -pub fn note_unique_llvm_symbol(ccx: &mut CrateContext, sym: @str) { - if ccx.all_llvm_symbols.contains(&sym) { +pub fn note_unique_llvm_symbol(ccx: &CrateContext, sym: @str) { + let mut all_llvm_symbols = ccx.all_llvm_symbols.borrow_mut(); + if all_llvm_symbols.get().contains(&sym) { ccx.sess.bug(~"duplicate LLVM symbol: " + sym); } - ccx.all_llvm_symbols.insert(sym); + all_llvm_symbols.get().insert(sym); } -pub fn get_res_dtor(ccx: @mut CrateContext, +pub fn get_res_dtor(ccx: @CrateContext, did: ast::DefId, parent_id: ast::DefId, substs: &[ty::t]) @@ -555,11 +569,15 @@ pub fn get_res_dtor(ccx: @mut CrateContext, None, ty::lookup_item_type(tcx, parent_id).ty); let llty = type_of_dtor(ccx, class_ty); - get_extern_fn(&mut ccx.externs, - ccx.llmod, - name, - lib::llvm::CCallConv, - llty) + + { + let mut externs = ccx.externs.borrow_mut(); + get_extern_fn(externs.get(), + ccx.llmod, + name, + lib::llvm::CCallConv, + llty) + } } } @@ -579,7 +597,7 @@ pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) { pub enum scalar_type { nil_type, signed_int, unsigned_int, floating_point, } // NB: This produces an i1, not a Rust bool (i8). -pub fn compare_scalar_types(cx: @mut Block, +pub fn compare_scalar_types(cx: @Block, lhs: ValueRef, rhs: ValueRef, t: ty::t, @@ -611,14 +629,14 @@ pub fn compare_scalar_types(cx: @mut Block, // A helper function to do the actual comparison of scalar values. -pub fn compare_scalar_values(cx: @mut Block, +pub fn compare_scalar_values(cx: @Block, lhs: ValueRef, rhs: ValueRef, nt: scalar_type, op: ast::BinOp) -> ValueRef { let _icx = push_ctxt("compare_scalar_values"); - fn die(cx: @mut Block) -> ! { + fn die(cx: @Block) -> ! { cx.tcx().sess.bug("compare_scalar_values: must be a\ comparison operator"); } @@ -672,25 +690,25 @@ pub fn compare_scalar_values(cx: @mut Block, } } -pub type val_and_ty_fn<'a> = 'a |@mut Block, ValueRef, ty::t| - -> @mut Block; +pub type val_and_ty_fn<'a> = 'a |@Block, ValueRef, ty::t| + -> @Block; -pub fn load_inbounds(cx: @mut Block, p: ValueRef, idxs: &[uint]) -> ValueRef { +pub fn load_inbounds(cx: @Block, p: ValueRef, idxs: &[uint]) -> ValueRef { return Load(cx, GEPi(cx, p, idxs)); } -pub fn store_inbounds(cx: @mut Block, v: ValueRef, p: ValueRef, idxs: &[uint]) { +pub fn store_inbounds(cx: @Block, v: ValueRef, p: ValueRef, idxs: &[uint]) { Store(cx, v, GEPi(cx, p, idxs)); } // Iterates through the elements of a structural type. -pub fn iter_structural_ty(cx: @mut Block, av: ValueRef, t: ty::t, - f: val_and_ty_fn) -> @mut Block { +pub fn iter_structural_ty(cx: @Block, av: ValueRef, t: ty::t, + f: val_and_ty_fn) -> @Block { let _icx = push_ctxt("iter_structural_ty"); - fn iter_variant(cx: @mut Block, repr: &adt::Repr, av: ValueRef, + fn iter_variant(cx: @Block, repr: &adt::Repr, av: ValueRef, variant: @ty::VariantInfo, - tps: &[ty::t], f: val_and_ty_fn) -> @mut Block { + tps: &[ty::t], f: val_and_ty_fn) -> @Block { let _icx = push_ctxt("iter_variant"); let tcx = cx.tcx(); let mut cx = cx; @@ -776,7 +794,7 @@ pub fn iter_structural_ty(cx: @mut Block, av: ValueRef, t: ty::t, return cx; } -pub fn cast_shift_expr_rhs(cx: @mut Block, op: ast::BinOp, +pub fn cast_shift_expr_rhs(cx: @Block, op: ast::BinOp, lhs: ValueRef, rhs: ValueRef) -> ValueRef { cast_shift_rhs(op, lhs, rhs, |a,b| Trunc(cx, a, b), @@ -818,8 +836,8 @@ pub fn cast_shift_rhs(op: ast::BinOp, } } -pub fn fail_if_zero(cx: @mut Block, span: Span, divrem: ast::BinOp, - rhs: ValueRef, rhs_t: ty::t) -> @mut Block { +pub fn fail_if_zero(cx: @Block, span: Span, divrem: ast::BinOp, + rhs: ValueRef, rhs_t: ty::t) -> @Block { let text = if divrem == ast::BiDiv { @"attempted to divide by zero" } else { @@ -848,7 +866,7 @@ pub fn null_env_ptr(ccx: &CrateContext) -> ValueRef { C_null(Type::opaque_box(ccx).ptr_to()) } -pub fn trans_external_path(ccx: &mut CrateContext, did: ast::DefId, t: ty::t) -> ValueRef { +pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> ValueRef { let name = csearch::get_symbol(ccx.sess.cstore, did); match ty::get(t).sty { ty::ty_bare_fn(ref fn_ty) => { @@ -861,7 +879,8 @@ pub fn trans_external_path(ccx: &mut CrateContext, did: ast::DefId, t: ty::t) -> let c = foreign::llvm_calling_convention(ccx, fn_ty.abis); let cconv = c.unwrap_or(lib::llvm::CCallConv); let llty = type_of_fn_from_ty(ccx, t); - get_extern_fn(&mut ccx.externs, ccx.llmod, name, cconv, llty) + let mut externs = ccx.externs.borrow_mut(); + get_extern_fn(externs.get(), ccx.llmod, name, cconv, llty) } } } @@ -870,19 +889,20 @@ pub fn trans_external_path(ccx: &mut CrateContext, did: ast::DefId, t: ty::t) -> } _ => { let llty = type_of(ccx, t); - get_extern_const(&mut ccx.externs, ccx.llmod, name, llty) + let mut externs = ccx.externs.borrow_mut(); + get_extern_const(externs.get(), ccx.llmod, name, llty) } } } -pub fn invoke(bcx: @mut Block, +pub fn invoke(bcx: @Block, llfn: ValueRef, llargs: ~[ValueRef], attributes: &[(uint, lib::llvm::Attribute)], call_info: Option) - -> (ValueRef, @mut Block) { + -> (ValueRef, @Block) { let _icx = push_ctxt("invoke_"); - if bcx.unreachable { + if bcx.unreachable.get() { return (C_null(Type::i8()), bcx); } @@ -934,7 +954,7 @@ pub fn invoke(bcx: @mut Block, } } -pub fn need_invoke(bcx: @mut Block) -> bool { +pub fn need_invoke(bcx: @Block) -> bool { if bcx.ccx().sess.no_landing_pads() { return false; } @@ -950,11 +970,12 @@ pub fn need_invoke(bcx: @mut Block) -> bool { // Walk the scopes to look for cleanups let mut cur = bcx; - let mut cur_scope = cur.scope; + let mut cur_scope = cur.scope.get(); loop { cur_scope = match cur_scope { Some(inf) => { - for cleanup in inf.cleanups.iter() { + let cleanups = inf.cleanups.borrow(); + for cleanup in cleanups.get().iter() { match *cleanup { clean(_, cleanup_type) | clean_temp(_, _, cleanup_type) => { if cleanup_type == normal_exit_and_unwind { @@ -970,16 +991,16 @@ pub fn need_invoke(bcx: @mut Block) -> bool { Some(next) => next, None => return false }; - cur.scope + cur.scope.get() } } } } -pub fn have_cached_lpad(bcx: @mut Block) -> bool { +pub fn have_cached_lpad(bcx: @Block) -> bool { let mut res = false; in_lpad_scope_cx(bcx, |inf| { - match inf.landing_pad { + match inf.landing_pad.get() { Some(_) => res = true, None => res = false } @@ -987,9 +1008,9 @@ pub fn have_cached_lpad(bcx: @mut Block) -> bool { return res; } -pub fn in_lpad_scope_cx(bcx: @mut Block, f: |si: &mut ScopeInfo|) { +pub fn in_lpad_scope_cx(bcx: @Block, f: |si: &ScopeInfo|) { let mut bcx = bcx; - let mut cur_scope = bcx.scope; + let mut cur_scope = bcx.scope.get(); loop { cur_scope = match cur_scope { Some(inf) => { @@ -1001,24 +1022,24 @@ pub fn in_lpad_scope_cx(bcx: @mut Block, f: |si: &mut ScopeInfo|) { } None => { bcx = block_parent(bcx); - bcx.scope + bcx.scope.get() } } } } -pub fn get_landing_pad(bcx: @mut Block) -> BasicBlockRef { +pub fn get_landing_pad(bcx: @Block) -> BasicBlockRef { let _icx = push_ctxt("get_landing_pad"); let mut cached = None; let mut pad_bcx = bcx; // Guaranteed to be set below in_lpad_scope_cx(bcx, |inf| { // If there is a valid landing pad still around, use it - match inf.landing_pad { + match inf.landing_pad.get() { Some(target) => cached = Some(target), None => { pad_bcx = lpad_block(bcx, "unwind"); - inf.landing_pad = Some(pad_bcx.llbb); + inf.landing_pad.set(Some(pad_bcx.llbb)); } } }); @@ -1039,11 +1060,11 @@ pub fn get_landing_pad(bcx: @mut Block) -> BasicBlockRef { // We store the retval in a function-central alloca, so that calls to // Resume can find it. - match bcx.fcx.personality { + match bcx.fcx.personality.get() { Some(addr) => Store(pad_bcx, llretval, addr), None => { let addr = alloca(pad_bcx, val_ty(llretval), ""); - bcx.fcx.personality = Some(addr); + bcx.fcx.personality.set(Some(addr)); Store(pad_bcx, llretval, addr); } } @@ -1053,9 +1074,9 @@ pub fn get_landing_pad(bcx: @mut Block) -> BasicBlockRef { return pad_bcx.llbb; } -pub fn find_bcx_for_scope(bcx: @mut Block, scope_id: ast::NodeId) -> @mut Block { +pub fn find_bcx_for_scope(bcx: @Block, scope_id: ast::NodeId) -> @Block { let mut bcx_sid = bcx; - let mut cur_scope = bcx_sid.scope; + let mut cur_scope = bcx_sid.scope.get(); loop { cur_scope = match cur_scope { Some(inf) => { @@ -1075,14 +1096,14 @@ pub fn find_bcx_for_scope(bcx: @mut Block, scope_id: ast::NodeId) -> @mut Block None => bcx.tcx().sess.bug(format!("no enclosing scope with id {}", scope_id)), Some(bcx_par) => bcx_par }; - bcx_sid.scope + bcx_sid.scope.get() } } } } -pub fn do_spill(bcx: @mut Block, v: ValueRef, t: ty::t) -> ValueRef { +pub fn do_spill(bcx: @Block, v: ValueRef, t: ty::t) -> ValueRef { if ty::type_is_bot(t) { return C_null(Type::i8p()); } @@ -1093,31 +1114,31 @@ pub fn do_spill(bcx: @mut Block, v: ValueRef, t: ty::t) -> ValueRef { // Since this function does *not* root, it is the caller's responsibility to // ensure that the referent is pointed to by a root. -pub fn do_spill_noroot(cx: @mut Block, v: ValueRef) -> ValueRef { +pub fn do_spill_noroot(cx: @Block, v: ValueRef) -> ValueRef { let llptr = alloca(cx, val_ty(v), ""); Store(cx, v, llptr); return llptr; } -pub fn spill_if_immediate(cx: @mut Block, v: ValueRef, t: ty::t) -> ValueRef { +pub fn spill_if_immediate(cx: @Block, v: ValueRef, t: ty::t) -> ValueRef { let _icx = push_ctxt("spill_if_immediate"); if type_is_immediate(cx.ccx(), t) { return do_spill(cx, v, t); } return v; } -pub fn load_if_immediate(cx: @mut Block, v: ValueRef, t: ty::t) -> ValueRef { +pub fn load_if_immediate(cx: @Block, v: ValueRef, t: ty::t) -> ValueRef { let _icx = push_ctxt("load_if_immediate"); if type_is_immediate(cx.ccx(), t) { return Load(cx, v); } return v; } -pub fn ignore_lhs(_bcx: @mut Block, local: &ast::Local) -> bool { +pub fn ignore_lhs(_bcx: @Block, local: &ast::Local) -> bool { match local.pat.node { ast::PatWild => true, _ => false } } -pub fn init_local(bcx: @mut Block, local: &ast::Local) -> @mut Block { +pub fn init_local(bcx: @Block, local: &ast::Local) -> @Block { debug!("init_local(bcx={}, local.id={:?})", bcx.to_str(), local.id); @@ -1138,7 +1159,7 @@ pub fn init_local(bcx: @mut Block, local: &ast::Local) -> @mut Block { _match::store_local(bcx, local.pat, local.init) } -pub fn trans_stmt(cx: @mut Block, s: &ast::Stmt) -> @mut Block { +pub fn trans_stmt(cx: @Block, s: &ast::Stmt) -> @Block { let _icx = push_ctxt("trans_stmt"); debug!("trans_stmt({})", stmt_to_str(s, cx.tcx().sess.intr())); @@ -1171,25 +1192,25 @@ pub fn trans_stmt(cx: @mut Block, s: &ast::Stmt) -> @mut Block { // You probably don't want to use this one. See the // next three functions instead. -pub fn new_block(cx: @mut FunctionContext, - parent: Option<@mut Block>, - scope: Option<@mut ScopeInfo>, +pub fn new_block(cx: @FunctionContext, + parent: Option<@Block>, + scope: Option<@ScopeInfo>, is_lpad: bool, name: &str, opt_node_info: Option) - -> @mut Block { + -> @Block { unsafe { let llbb = name.with_c_str(|buf| { llvm::LLVMAppendBasicBlockInContext(cx.ccx.llcx, cx.llfn, buf) }); - let bcx = @mut Block::new(llbb, + let bcx = @Block::new(llbb, parent, is_lpad, opt_node_info, cx); - bcx.scope = scope; + bcx.scope.set(scope); for cx in parent.iter() { - if cx.unreachable { + if cx.unreachable.get() { Unreachable(bcx); break; } @@ -1198,61 +1219,62 @@ pub fn new_block(cx: @mut FunctionContext, } } -pub fn simple_block_scope(parent: Option<@mut ScopeInfo>, - node_info: Option) -> @mut ScopeInfo { - @mut ScopeInfo { +pub fn simple_block_scope(parent: Option<@ScopeInfo>, + node_info: Option) + -> @ScopeInfo { + @ScopeInfo { parent: parent, loop_break: None, loop_label: None, - cleanups: ~[], - cleanup_paths: ~[], - landing_pad: None, + cleanups: RefCell::new(~[]), + cleanup_paths: RefCell::new(~[]), + landing_pad: Cell::new(None), node_info: node_info, } } // Use this when you're at the top block of a function or the like. -pub fn top_scope_block(fcx: @mut FunctionContext, opt_node_info: Option) - -> @mut Block { +pub fn top_scope_block(fcx: @FunctionContext, opt_node_info: Option) + -> @Block { return new_block(fcx, None, Some(simple_block_scope(None, opt_node_info)), false, "function top level", opt_node_info); } -pub fn scope_block(bcx: @mut Block, +pub fn scope_block(bcx: @Block, opt_node_info: Option, - n: &str) -> @mut Block { + n: &str) -> @Block { return new_block(bcx.fcx, Some(bcx), Some(simple_block_scope(None, opt_node_info)), bcx.is_lpad, n, opt_node_info); } -pub fn loop_scope_block(bcx: @mut Block, - loop_break: @mut Block, +pub fn loop_scope_block(bcx: @Block, + loop_break: @Block, loop_label: Option, n: &str, - opt_node_info: Option) -> @mut Block { - return new_block(bcx.fcx, Some(bcx), Some(@mut ScopeInfo { + opt_node_info: Option) -> @Block { + return new_block(bcx.fcx, Some(bcx), Some(@ScopeInfo { parent: None, loop_break: Some(loop_break), loop_label: loop_label, - cleanups: ~[], - cleanup_paths: ~[], - landing_pad: None, + cleanups: RefCell::new(~[]), + cleanup_paths: RefCell::new(~[]), + landing_pad: Cell::new(None), node_info: opt_node_info, }), bcx.is_lpad, n, opt_node_info); } // Use this when creating a block for the inside of a landing pad. -pub fn lpad_block(bcx: @mut Block, n: &str) -> @mut Block { +pub fn lpad_block(bcx: @Block, n: &str) -> @Block { new_block(bcx.fcx, Some(bcx), None, true, n, None) } // Use this when you're making a general CFG BB within a scope. -pub fn sub_block(bcx: @mut Block, n: &str) -> @mut Block { +pub fn sub_block(bcx: @Block, n: &str) -> @Block { new_block(bcx.fcx, Some(bcx), None, bcx.is_lpad, n, None) } -pub fn raw_block(fcx: @mut FunctionContext, is_lpad: bool, llbb: BasicBlockRef) -> @mut Block { - @mut Block::new(llbb, None, is_lpad, None, fcx) +pub fn raw_block(fcx: @FunctionContext, is_lpad: bool, llbb: BasicBlockRef) -> @Block { + @Block::new(llbb, None, is_lpad, None, fcx) } @@ -1263,19 +1285,21 @@ pub fn raw_block(fcx: @mut FunctionContext, is_lpad: bool, llbb: BasicBlockRef) // need to make sure those variables go out of scope when the block ends. We // do that by running a 'cleanup' function for each variable. // trans_block_cleanups runs all the cleanup functions for the block. -pub fn trans_block_cleanups(bcx: @mut Block, cleanups: ~[cleanup]) -> @mut Block { +pub fn trans_block_cleanups(bcx: @Block, cleanups: ~[cleanup]) -> @Block { trans_block_cleanups_(bcx, cleanups, false) } -pub fn trans_block_cleanups_(bcx: @mut Block, +pub fn trans_block_cleanups_(bcx: @Block, cleanups: &[cleanup], /* cleanup_cx: block, */ - is_lpad: bool) -> @mut Block { + is_lpad: bool) -> @Block { let _icx = push_ctxt("trans_block_cleanups"); // NB: Don't short-circuit even if this block is unreachable because // GC-based cleanup needs to the see that the roots are live. let no_lpads = bcx.ccx().sess.no_landing_pads(); - if bcx.unreachable && !no_lpads { return bcx; } + if bcx.unreachable.get() && !no_lpads { + return bcx + } let mut bcx = bcx; for cu in cleanups.rev_iter() { match *cu { @@ -1294,7 +1318,7 @@ pub fn trans_block_cleanups_(bcx: @mut Block, // In the last argument, Some(block) mean jump to this block, and none means // this is a landing pad and leaving should be accomplished with a resume // instruction. -pub fn cleanup_and_leave(bcx: @mut Block, +pub fn cleanup_and_leave(bcx: @Block, upto: Option, leave: Option) { let _icx = push_ctxt("cleanup_and_leave"); @@ -1304,18 +1328,24 @@ pub fn cleanup_and_leave(bcx: @mut Block, loop { debug!("cleanup_and_leave: leaving {}", cur.to_str()); - let mut cur_scope = cur.scope; + let mut cur_scope = cur.scope.get(); loop { cur_scope = match cur_scope { Some (inf) if !inf.empty_cleanups() => { let (sub_cx, dest, inf_cleanups) = { - let inf = &mut *inf; + let inf = &*inf; let mut skip = 0; let mut dest = None; { - let r = (*inf).cleanup_paths.rev_iter().find(|cp| cp.target == leave); + let cleanup_paths = inf.cleanup_paths.borrow(); + let r = cleanup_paths.get() + .rev_iter() + .find(|cp| { + cp.target == leave + }); for cp in r.iter() { - if cp.size == inf.cleanups.len() { + let cleanups = inf.cleanups.borrow(); + if cp.size == cleanups.get().len() { Br(bcx, cp.dest); return; } @@ -1326,12 +1356,15 @@ pub fn cleanup_and_leave(bcx: @mut Block, } let sub_cx = sub_block(bcx, "cleanup"); Br(bcx, sub_cx.llbb); - inf.cleanup_paths.push(cleanup_path { + let cleanups = inf.cleanups.borrow(); + let mut cleanup_paths = inf.cleanup_paths + .borrow_mut(); + cleanup_paths.get().push(cleanup_path { target: leave, - size: inf.cleanups.len(), + size: cleanups.get().len(), dest: sub_cx.llbb }); - (sub_cx, dest, inf.cleanups.tailn(skip).to_owned()) + (sub_cx, dest, cleanups.get().tailn(skip).to_owned()) }; bcx = trans_block_cleanups_(sub_cx, inf_cleanups, @@ -1359,24 +1392,27 @@ pub fn cleanup_and_leave(bcx: @mut Block, match leave { Some(target) => Br(bcx, target), None => { - let ll_load = Load(bcx, bcx.fcx.personality.unwrap()); + let ll_load = Load(bcx, bcx.fcx.personality.get().unwrap()); Resume(bcx, ll_load); } } } -pub fn cleanup_block(bcx: @mut Block, upto: Option) -> @mut Block{ +pub fn cleanup_block(bcx: @Block, upto: Option) -> @Block{ let _icx = push_ctxt("cleanup_block"); let mut cur = bcx; let mut bcx = bcx; loop { debug!("cleanup_block: {}", cur.to_str()); - let mut cur_scope = cur.scope; + let mut cur_scope = cur.scope.get(); loop { cur_scope = match cur_scope { - Some (inf) => { - bcx = trans_block_cleanups_(bcx, inf.cleanups.to_owned(), false); + Some(inf) => { + let cleanups = inf.cleanups.borrow(); + bcx = trans_block_cleanups_(bcx, + cleanups.get().to_owned(), + false); inf.parent } None => break @@ -1395,60 +1431,60 @@ pub fn cleanup_block(bcx: @mut Block, upto: Option) -> @mut Block bcx } -pub fn cleanup_and_Br(bcx: @mut Block, upto: @mut Block, target: BasicBlockRef) { +pub fn cleanup_and_Br(bcx: @Block, upto: @Block, target: BasicBlockRef) { let _icx = push_ctxt("cleanup_and_Br"); cleanup_and_leave(bcx, Some(upto.llbb), Some(target)); } -pub fn leave_block(bcx: @mut Block, out_of: @mut Block) -> @mut Block { +pub fn leave_block(bcx: @Block, out_of: @Block) -> @Block { let _icx = push_ctxt("leave_block"); let next_cx = sub_block(block_parent(out_of), "next"); - if bcx.unreachable { Unreachable(next_cx); } + if bcx.unreachable.get() { + Unreachable(next_cx); + } cleanup_and_Br(bcx, out_of, next_cx.llbb); next_cx } -pub fn with_scope(bcx: @mut Block, +pub fn with_scope(bcx: @Block, opt_node_info: Option, name: &str, - f: |@mut Block| -> @mut Block) - -> @mut Block { + f: |@Block| -> @Block) + -> @Block { let _icx = push_ctxt("with_scope"); debug!("with_scope(bcx={}, opt_node_info={:?}, name={})", bcx.to_str(), opt_node_info, name); let _indenter = indenter(); - let scope = simple_block_scope(bcx.scope, opt_node_info); - bcx.scope = Some(scope); + let scope = simple_block_scope(bcx.scope.get(), opt_node_info); + bcx.scope.set(Some(scope)); let ret = f(bcx); - let ret = trans_block_cleanups_(ret, (scope.cleanups).clone(), false); - bcx.scope = scope.parent; + let ret = trans_block_cleanups_(ret, scope.cleanups.get(), false); + bcx.scope.set(scope.parent); ret } -pub fn with_scope_result(bcx: @mut Block, +pub fn with_scope_result(bcx: @Block, opt_node_info: Option, _name: &str, - f: |@mut Block| -> Result) + f: |@Block| -> Result) -> Result { let _icx = push_ctxt("with_scope_result"); - let scope = simple_block_scope(bcx.scope, opt_node_info); - bcx.scope = Some(scope); + let scope = simple_block_scope(bcx.scope.get(), opt_node_info); + bcx.scope.set(Some(scope)); let Result { bcx: out_bcx, val } = f(bcx); - let out_bcx = trans_block_cleanups_(out_bcx, - (scope.cleanups).clone(), - false); - bcx.scope = scope.parent; + let out_bcx = trans_block_cleanups_(out_bcx, scope.cleanups.get(), false); + bcx.scope.set(scope.parent); rslt(out_bcx, val) } -pub fn with_scope_datumblock(bcx: @mut Block, +pub fn with_scope_datumblock(bcx: @Block, opt_node_info: Option, name: &str, - f: |@mut Block| -> datum::DatumBlock) + f: |@Block| -> datum::DatumBlock) -> datum::DatumBlock { use middle::trans::datum::DatumBlock; @@ -1473,20 +1509,22 @@ pub fn block_locals(b: &ast::Block, it: |@ast::Local|) { } } -pub fn with_cond(bcx: @mut Block, +pub fn with_cond(bcx: @Block, val: ValueRef, - f: |@mut Block| -> @mut Block) - -> @mut Block { + f: |@Block| -> @Block) + -> @Block { let _icx = push_ctxt("with_cond"); let next_cx = base::sub_block(bcx, "next"); let cond_cx = base::sub_block(bcx, "cond"); CondBr(bcx, val, cond_cx.llbb, next_cx.llbb); let after_cx = f(cond_cx); - if !after_cx.terminated { Br(after_cx, next_cx.llbb); } + if !after_cx.terminated.get() { + Br(after_cx, next_cx.llbb); + } next_cx } -pub fn call_memcpy(cx: @mut Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) { +pub fn call_memcpy(cx: @Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) { let _icx = push_ctxt("call_memcpy"); let ccx = cx.ccx(); let key = match ccx.sess.targ_cfg.arch { @@ -1502,7 +1540,7 @@ pub fn call_memcpy(cx: @mut Block, dst: ValueRef, src: ValueRef, n_bytes: ValueR Call(cx, memcpy, [dst_ptr, src_ptr, size, align, volatile], []); } -pub fn memcpy_ty(bcx: @mut Block, dst: ValueRef, src: ValueRef, t: ty::t) { +pub fn memcpy_ty(bcx: @Block, dst: ValueRef, src: ValueRef, t: ty::t) { let _icx = push_ctxt("memcpy_ty"); let ccx = bcx.ccx(); if ty::type_is_structural(t) { @@ -1515,8 +1553,8 @@ pub fn memcpy_ty(bcx: @mut Block, dst: ValueRef, src: ValueRef, t: ty::t) { } } -pub fn zero_mem(cx: @mut Block, llptr: ValueRef, t: ty::t) { - if cx.unreachable { return; } +pub fn zero_mem(cx: @Block, llptr: ValueRef, t: ty::t) { + if cx.unreachable.get() { return; } let _icx = push_ctxt("zero_mem"); let bcx = cx; let ccx = cx.ccx(); @@ -1547,7 +1585,7 @@ pub fn memzero(b: &Builder, llptr: ValueRef, ty: Type) { b.call(llintrinsicfn, [llptr, llzeroval, size, align, volatile], []); } -pub fn alloc_ty(bcx: @mut Block, t: ty::t, name: &str) -> ValueRef { +pub fn alloc_ty(bcx: @Block, t: ty::t, name: &str) -> ValueRef { let _icx = push_ctxt("alloc_ty"); let ccx = bcx.ccx(); let ty = type_of::type_of(ccx, t); @@ -1556,13 +1594,13 @@ pub fn alloc_ty(bcx: @mut Block, t: ty::t, name: &str) -> ValueRef { return val; } -pub fn alloca(cx: @mut Block, ty: Type, name: &str) -> ValueRef { +pub fn alloca(cx: @Block, ty: Type, name: &str) -> ValueRef { alloca_maybe_zeroed(cx, ty, name, false) } -pub fn alloca_maybe_zeroed(cx: @mut Block, ty: Type, name: &str, zero: bool) -> ValueRef { +pub fn alloca_maybe_zeroed(cx: @Block, ty: Type, name: &str, zero: bool) -> ValueRef { let _icx = push_ctxt("alloca"); - if cx.unreachable { + if cx.unreachable.get() { unsafe { return llvm::LLVMGetUndef(ty.ptr_to().to_ref()); } @@ -1571,15 +1609,15 @@ pub fn alloca_maybe_zeroed(cx: @mut Block, ty: Type, name: &str, zero: bool) -> let p = Alloca(cx, ty, name); if zero { let b = cx.fcx.ccx.builder(); - b.position_before(cx.fcx.alloca_insert_pt.unwrap()); + b.position_before(cx.fcx.alloca_insert_pt.get().unwrap()); memzero(&b, p, ty); } p } -pub fn arrayalloca(cx: @mut Block, ty: Type, v: ValueRef) -> ValueRef { +pub fn arrayalloca(cx: @Block, ty: Type, v: ValueRef) -> ValueRef { let _icx = push_ctxt("arrayalloca"); - if cx.unreachable { + if cx.unreachable.get() { unsafe { return llvm::LLVMGetUndef(ty.to_ref()); } @@ -1612,13 +1650,13 @@ pub fn mk_return_basic_block(llfn: ValueRef) -> BasicBlockRef { // Creates and returns space for, or returns the argument representing, the // slot where the return value of the function must go. -pub fn make_return_pointer(fcx: @mut FunctionContext, output_type: ty::t) -> ValueRef { +pub fn make_return_pointer(fcx: @FunctionContext, output_type: ty::t) -> ValueRef { unsafe { if type_of::return_uses_outptr(fcx.ccx, output_type) { llvm::LLVMGetParam(fcx.llfn, 0) } else { let lloutputtype = type_of::type_of(fcx.ccx, output_type); - let bcx = fcx.entry_bcx.unwrap(); + let bcx = fcx.entry_bcx.get().unwrap(); Alloca(bcx, lloutputtype, "__make_return_pointer") } } @@ -1630,7 +1668,7 @@ pub fn make_return_pointer(fcx: @mut FunctionContext, output_type: ty::t) -> Val // - create_llargs_for_fn_args. // - new_fn_ctxt // - trans_args -pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext, +pub fn new_fn_ctxt_w_id(ccx: @CrateContext, path: path, llfndecl: ValueRef, id: ast::NodeId, @@ -1639,7 +1677,7 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext, param_substs: Option<@param_substs>, opt_node_info: Option, sp: Option) - -> @mut FunctionContext { + -> @FunctionContext { for p in param_substs.iter() { p.validate(); } debug!("new_fn_ctxt_w_id(path={}, id={:?}, \ @@ -1657,21 +1695,21 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext, let uses_outptr = type_of::return_uses_outptr(ccx, substd_output_type); let debug_context = debuginfo::create_function_debug_context(ccx, id, param_substs, llfndecl); - let fcx = @mut FunctionContext { + let fcx = @FunctionContext { llfn: llfndecl, llenv: unsafe { - llvm::LLVMGetUndef(Type::i8p().to_ref()) + Cell::new(llvm::LLVMGetUndef(Type::i8p().to_ref())) }, - llretptr: None, - entry_bcx: None, - alloca_insert_pt: None, - llreturn: None, - llself: None, - personality: None, + llretptr: Cell::new(None), + entry_bcx: RefCell::new(None), + alloca_insert_pt: Cell::new(None), + llreturn: Cell::new(None), + llself: Cell::new(None), + personality: Cell::new(None), caller_expects_out_pointer: uses_outptr, - llargs: @mut HashMap::new(), - lllocals: @mut HashMap::new(), - llupvars: @mut HashMap::new(), + llargs: RefCell::new(HashMap::new()), + lllocals: RefCell::new(HashMap::new()), + llupvars: RefCell::new(HashMap::new()), id: id, param_substs: param_substs, span: sp, @@ -1679,16 +1717,17 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext, ccx: ccx, debug_context: debug_context, }; - fcx.llenv = unsafe { + fcx.llenv.set(unsafe { llvm::LLVMGetParam(llfndecl, fcx.env_arg_pos() as c_uint) - }; + }); unsafe { let entry_bcx = top_scope_block(fcx, opt_node_info); Load(entry_bcx, C_null(Type::i8p())); - fcx.entry_bcx = Some(entry_bcx); - fcx.alloca_insert_pt = Some(llvm::LLVMGetFirstInstruction(entry_bcx.llbb)); + fcx.entry_bcx.set(Some(entry_bcx)); + fcx.alloca_insert_pt.set(Some( + llvm::LLVMGetFirstInstruction(entry_bcx.llbb))); } if !ty::type_is_voidish(ccx.tcx, substd_output_type) { @@ -1698,18 +1737,19 @@ pub fn new_fn_ctxt_w_id(ccx: @mut CrateContext, // Otherwise, we normally allocate the llretptr, unless we // have been instructed to skip it for immediate return // values. - fcx.llretptr = Some(make_return_pointer(fcx, substd_output_type)); + fcx.llretptr.set(Some(make_return_pointer(fcx, + substd_output_type))); } } fcx } -pub fn new_fn_ctxt(ccx: @mut CrateContext, +pub fn new_fn_ctxt(ccx: @CrateContext, path: path, llfndecl: ValueRef, output_type: ty::t, sp: Option) - -> @mut FunctionContext { + -> @FunctionContext { new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, false, None, None, sp) } @@ -1727,7 +1767,7 @@ pub fn new_fn_ctxt(ccx: @mut CrateContext, // spaces that have been created for them (by code in the llallocas field of // the function's fn_ctxt). create_llargs_for_fn_args populates the llargs // field of the fn_ctxt with -pub fn create_llargs_for_fn_args(cx: @mut FunctionContext, +pub fn create_llargs_for_fn_args(cx: @FunctionContext, self_arg: self_arg, args: &[ast::arg]) -> ~[ValueRef] { @@ -1735,11 +1775,11 @@ pub fn create_llargs_for_fn_args(cx: @mut FunctionContext, match self_arg { impl_self(tt, self_mode) => { - cx.llself = Some(ValSelfData { - v: cx.llenv, + cx.llself.set(Some(ValSelfData { + v: cx.llenv.get(), t: tt, is_copy: self_mode == ty::ByCopy - }); + })); } no_self => () } @@ -1751,11 +1791,11 @@ pub fn create_llargs_for_fn_args(cx: @mut FunctionContext, }) } -pub fn copy_args_to_allocas(fcx: @mut FunctionContext, - bcx: @mut Block, +pub fn copy_args_to_allocas(fcx: @FunctionContext, + bcx: @Block, args: &[ast::arg], raw_llargs: &[ValueRef], - arg_tys: &[ty::t]) -> @mut Block { + arg_tys: &[ty::t]) -> @Block { debug!("copy_args_to_allocas: raw_llargs={} arg_tys={}", raw_llargs.llrepr(fcx.ccx), arg_tys.repr(fcx.ccx.tcx)); @@ -1763,7 +1803,7 @@ pub fn copy_args_to_allocas(fcx: @mut FunctionContext, let _icx = push_ctxt("copy_args_to_allocas"); let mut bcx = bcx; - match fcx.llself { + match fcx.llself.get() { Some(slf) => { let self_val = if slf.is_copy && datum::appropriate_mode(bcx.ccx(), slf.t).is_by_value() { @@ -1775,7 +1815,7 @@ pub fn copy_args_to_allocas(fcx: @mut FunctionContext, PointerCast(bcx, slf.v, type_of(bcx.ccx(), slf.t).ptr_to()) }; - fcx.llself = Some(ValSelfData {v: self_val, ..slf}); + fcx.llself.set(Some(ValSelfData {v: self_val, ..slf})); add_clean(bcx, self_val, slf.t); if fcx.ccx.sess.opts.extra_debuginfo { @@ -1815,12 +1855,12 @@ pub fn copy_args_to_allocas(fcx: @mut FunctionContext, // Ties up the llstaticallocas -> llloadenv -> lltop edges, // and builds the return block. -pub fn finish_fn(fcx: @mut FunctionContext, last_bcx: @mut Block) { +pub fn finish_fn(fcx: @FunctionContext, last_bcx: @Block) { let _icx = push_ctxt("finish_fn"); - let ret_cx = match fcx.llreturn { + let ret_cx = match fcx.llreturn.get() { Some(llreturn) => { - if !last_bcx.terminated { + if !last_bcx.terminated.get() { Br(last_bcx, llreturn); } raw_block(fcx, false, llreturn) @@ -1833,13 +1873,13 @@ pub fn finish_fn(fcx: @mut FunctionContext, last_bcx: @mut Block) { } // Builds the return block for a function. -pub fn build_return_block(fcx: &FunctionContext, ret_cx: @mut Block) { +pub fn build_return_block(fcx: &FunctionContext, ret_cx: @Block) { // Return the value if this function immediate; otherwise, return void. - if fcx.llretptr.is_none() || fcx.caller_expects_out_pointer { + if fcx.llretptr.get().is_none() || fcx.caller_expects_out_pointer { return RetVoid(ret_cx); } - let retptr = Value(fcx.llretptr.unwrap()); + let retptr = Value(fcx.llretptr.get().unwrap()); let retval = match retptr.get_dominating_store(ret_cx) { // If there's only a single store to the ret slot, we can directly return // the value that was stored and omit the store and the alloca @@ -1854,7 +1894,7 @@ pub fn build_return_block(fcx: &FunctionContext, ret_cx: @mut Block) { retval } // Otherwise, load the return value from the ret slot - None => Load(ret_cx, fcx.llretptr.unwrap()) + None => Load(ret_cx, fcx.llretptr.get().unwrap()) }; @@ -1866,7 +1906,7 @@ pub enum self_arg { impl_self(ty::t, ty::SelfMode), no_self, } // trans_closure: Builds an LLVM function out of a source function. // If the function closes over its environment a closure will be // returned. -pub fn trans_closure(ccx: @mut CrateContext, +pub fn trans_closure(ccx: @CrateContext, path: path, decl: &ast::fn_decl, body: &ast::Block, @@ -1876,8 +1916,9 @@ pub fn trans_closure(ccx: @mut CrateContext, id: ast::NodeId, _attributes: &[ast::Attribute], output_type: ty::t, - maybe_load_env: |@mut FunctionContext|) { - ccx.stats.n_closures += 1; + maybe_load_env: |@FunctionContext|) { + ccx.stats.n_closures.set(ccx.stats.n_closures.get() + 1); + let _icx = push_ctxt("trans_closure"); set_uwtable(llfndecl); @@ -1896,7 +1937,7 @@ pub fn trans_closure(ccx: @mut CrateContext, // Create the first basic block in the function and keep a handle on it to // pass to finish_fn later. - let bcx_top = fcx.entry_bcx.unwrap(); + let bcx_top = fcx.entry_bcx.get().unwrap(); let mut bcx = bcx_top; let block_ty = node_id_type(bcx, body.id); @@ -1920,11 +1961,11 @@ pub fn trans_closure(ccx: @mut CrateContext, if body.expr.is_none() || ty::type_is_voidish(bcx.tcx(), block_ty) { bcx = controlflow::trans_block(bcx, body, expr::Ignore); } else { - let dest = expr::SaveIn(fcx.llretptr.unwrap()); + let dest = expr::SaveIn(fcx.llretptr.get().unwrap()); bcx = controlflow::trans_block(bcx, body, dest); } - match fcx.llreturn { + match fcx.llreturn.get() { Some(llreturn) => cleanup_and_Br(bcx, bcx_top, llreturn), None => bcx = cleanup_block(bcx, Some(bcx_top.llbb)) }; @@ -1932,7 +1973,8 @@ pub fn trans_closure(ccx: @mut CrateContext, // Put return block after all other blocks. // This somewhat improves single-stepping experience in debugger. unsafe { - for &llreturn in fcx.llreturn.iter() { + let llreturn = fcx.llreturn.get(); + for &llreturn in llreturn.iter() { llvm::LLVMMoveBasicBlockAfter(llreturn, bcx.llbb); } } @@ -1943,7 +1985,7 @@ pub fn trans_closure(ccx: @mut CrateContext, // trans_fn: creates an LLVM function corresponding to a source language // function. -pub fn trans_fn(ccx: @mut CrateContext, +pub fn trans_fn(ccx: @CrateContext, path: path, decl: &ast::fn_decl, body: &ast::Block, @@ -1973,7 +2015,7 @@ pub fn trans_fn(ccx: @mut CrateContext, |_fcx| { }); } -fn insert_synthetic_type_entries(bcx: @mut Block, +fn insert_synthetic_type_entries(bcx: @Block, fn_args: &[ast::arg], arg_tys: &[ty::t]) { @@ -1996,11 +2038,13 @@ fn insert_synthetic_type_entries(bcx: @mut Block, let pat_id = fn_args[i].pat.id; let arg_ty = arg_tys[i]; - tcx.node_types.insert(pat_id as uint, arg_ty); + + let mut node_types = tcx.node_types.borrow_mut(); + node_types.get().insert(pat_id as uint, arg_ty); } } -pub fn trans_enum_variant(ccx: @mut CrateContext, +pub fn trans_enum_variant(ccx: @CrateContext, _enum_id: ast::NodeId, variant: &ast::variant, args: &[ast::variant_arg], @@ -2018,7 +2062,7 @@ pub fn trans_enum_variant(ccx: @mut CrateContext, llfndecl); } -pub fn trans_tuple_struct(ccx: @mut CrateContext, +pub fn trans_tuple_struct(ccx: @CrateContext, fields: &[ast::struct_field], ctor_id: ast::NodeId, param_substs: Option<@param_substs>, @@ -2050,7 +2094,7 @@ impl IdAndTy for ast::struct_field { } pub fn trans_enum_variant_or_tuple_like_struct( - ccx: @mut CrateContext, + ccx: @CrateContext, ctor_id: ast::NodeId, args: &[A], disr: ty::Disr, @@ -2108,27 +2152,30 @@ pub fn trans_enum_variant_or_tuple_like_struct( let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args); - let bcx = fcx.entry_bcx.unwrap(); + let bcx = fcx.entry_bcx.get().unwrap(); insert_synthetic_type_entries(bcx, fn_args, arg_tys); let bcx = copy_args_to_allocas(fcx, bcx, fn_args, raw_llargs, arg_tys); let repr = adt::represent_type(ccx, result_ty); - adt::trans_start_init(bcx, repr, fcx.llretptr.unwrap(), disr); + adt::trans_start_init(bcx, repr, fcx.llretptr.get().unwrap(), disr); for (i, fn_arg) in fn_args.iter().enumerate() { let lldestptr = adt::trans_field_ptr(bcx, repr, - fcx.llretptr.unwrap(), + fcx.llretptr.get().unwrap(), disr, i); - let llarg = fcx.llargs.get_copy(&fn_arg.pat.id); + let llarg = { + let llargs = fcx.llargs.borrow(); + llargs.get().get_copy(&fn_arg.pat.id) + }; let arg_ty = arg_tys[i]; memcpy_ty(bcx, lldestptr, llarg, arg_ty); } finish_fn(fcx, bcx); } -pub fn trans_enum_def(ccx: @mut CrateContext, enum_definition: &ast::enum_def, +pub fn trans_enum_def(ccx: @CrateContext, enum_definition: &ast::enum_def, id: ast::NodeId, vi: @~[@ty::VariantInfo], i: &mut uint) { for &variant in enum_definition.variants.iter() { @@ -2152,7 +2199,7 @@ pub fn trans_enum_def(ccx: @mut CrateContext, enum_definition: &ast::enum_def, } pub struct TransItemVisitor { - ccx: @mut CrateContext, + ccx: @CrateContext, } impl Visitor<()> for TransItemVisitor { @@ -2161,7 +2208,7 @@ impl Visitor<()> for TransItemVisitor { } } -pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) { +pub fn trans_item(ccx: @CrateContext, item: &ast::item) { let _icx = push_ctxt("trans_item"); let path = match ccx.tcx.items.get_copy(&item.id) { ast_map::node_item(_, p) => p, @@ -2227,7 +2274,9 @@ pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) { "cannot have static_assert on a mutable \ static"); } - let v = ccx.const_values.get_copy(&item.id); + + let const_values = ccx.const_values.borrow(); + let v = const_values.get().get_copy(&item.id); unsafe { if !(llvm::LLVMConstIntGetZExtValue(v) != 0) { ccx.sess.span_fatal(expr.span, "static assertion failed"); @@ -2255,7 +2304,7 @@ pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) { } } -pub fn trans_struct_def(ccx: @mut CrateContext, struct_def: @ast::struct_def) { +pub fn trans_struct_def(ccx: @CrateContext, struct_def: @ast::struct_def) { // If this is a tuple-like struct, translate the constructor. match struct_def.ctor_id { // We only need to translate a constructor if there are fields; @@ -2274,27 +2323,33 @@ pub fn trans_struct_def(ccx: @mut CrateContext, struct_def: @ast::struct_def) { // separate modules in the compiled program. That's because modules exist // only as a convenience for humans working with the code, to organize names // and control visibility. -pub fn trans_mod(ccx: @mut CrateContext, m: &ast::_mod) { +pub fn trans_mod(ccx: @CrateContext, m: &ast::_mod) { let _icx = push_ctxt("trans_mod"); for item in m.items.iter() { trans_item(ccx, *item); } } -fn finish_register_fn(ccx: @mut CrateContext, sp: Span, sym: ~str, node_id: ast::NodeId, +fn finish_register_fn(ccx: @CrateContext, sp: Span, sym: ~str, node_id: ast::NodeId, llfn: ValueRef) { - ccx.item_symbols.insert(node_id, sym); + { + let mut item_symbols = ccx.item_symbols.borrow_mut(); + item_symbols.get().insert(node_id, sym); + } - if !ccx.reachable.contains(&node_id) { - lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage); + { + let reachable = ccx.reachable.borrow(); + if !reachable.get().contains(&node_id) { + lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage); + } } - if is_entry_fn(&ccx.sess, node_id) && !*ccx.sess.building_library { + if is_entry_fn(&ccx.sess, node_id) && !ccx.sess.building_library.get() { create_entry_wrapper(ccx, sp, llfn); } } -pub fn register_fn(ccx: @mut CrateContext, +pub fn register_fn(ccx: @CrateContext, sp: Span, sym: ~str, node_id: ast::NodeId, @@ -2314,7 +2369,7 @@ pub fn register_fn(ccx: @mut CrateContext, } // only use this for foreign function ABIs and glue, use `register_fn` for Rust functions -pub fn register_fn_llvmty(ccx: @mut CrateContext, +pub fn register_fn_llvmty(ccx: @CrateContext, sp: Span, sym: ~str, node_id: ast::NodeId, @@ -2331,7 +2386,7 @@ pub fn register_fn_llvmty(ccx: @mut CrateContext, } pub fn is_entry_fn(sess: &Session, node_id: ast::NodeId) -> bool { - match *sess.entry_fn { + match sess.entry_fn.get() { Some((entry_id, _)) => node_id == entry_id, None => false } @@ -2339,10 +2394,10 @@ pub fn is_entry_fn(sess: &Session, node_id: ast::NodeId) -> bool { // Create a _rust_main(args: ~[str]) function which will be called from the // runtime rust_start function -pub fn create_entry_wrapper(ccx: @mut CrateContext, +pub fn create_entry_wrapper(ccx: @CrateContext, _sp: Span, main_llfn: ValueRef) { - let et = ccx.sess.entry_type.unwrap(); + let et = ccx.sess.entry_type.get().unwrap(); match et { session::EntryMain => { create_entry_fn(ccx, main_llfn, true); @@ -2351,7 +2406,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext, session::EntryNone => {} // Do nothing. } - fn create_entry_fn(ccx: @mut CrateContext, + fn create_entry_fn(ccx: @CrateContext, rust_main: ValueRef, use_start_lang_item: bool) { let llfty = Type::func([ccx.int_type, Type::i8().ptr_to().ptr_to()], @@ -2413,7 +2468,7 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext, } } -pub fn fill_fn_pair(bcx: @mut Block, pair: ValueRef, llfn: ValueRef, +pub fn fill_fn_pair(bcx: @Block, pair: ValueRef, llfn: ValueRef, llenvptr: ValueRef) { let ccx = bcx.ccx(); let code_cell = GEPi(bcx, pair, [0u, abi::fn_field_code]); @@ -2427,7 +2482,7 @@ pub fn item_path(ccx: &CrateContext, id: &ast::NodeId) -> path { ty::item_path(ccx.tcx, ast_util::local_def(*id)) } -fn exported_name(ccx: &mut CrateContext, path: path, ty: ty::t, attrs: &[ast::Attribute]) -> ~str { +fn exported_name(ccx: &CrateContext, path: path, ty: ty::t, attrs: &[ast::Attribute]) -> ~str { match attr::first_attr_value_str_by_name(attrs, "export_name") { // Use provided name Some(name) => name.to_owned(), @@ -2441,10 +2496,14 @@ fn exported_name(ccx: &mut CrateContext, path: path, ty: ty::t, attrs: &[ast::At } } -pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef { +pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef { debug!("get_item_val(id=`{:?}`)", id); - let val = ccx.item_vals.find_copy(&id); + let val = { + let item_vals = ccx.item_vals.borrow(); + item_vals.get().find_copy(&id) + }; + match val { Some(v) => v, None => { @@ -2465,18 +2524,27 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef { // using the current crate's name/version // information in the hash of the symbol debug!("making {}", sym); - let sym = match ccx.external_srcs.find(&i.id) { - Some(&did) => { - debug!("but found in other crate..."); - csearch::get_symbol(ccx.sess.cstore, did) + let sym = { + let external_srcs = ccx.external_srcs + .borrow(); + match external_srcs.get().find(&i.id) { + Some(&did) => { + debug!("but found in other crate..."); + csearch::get_symbol(ccx.sess.cstore, + did) + } + None => sym } - None => sym }; // We need the translated value here, because for enums the // LLVM type is not fully determined by the Rust type. let (v, inlineable) = consts::const_expr(ccx, expr); - ccx.const_values.insert(id, v); + { + let mut const_values = ccx.const_values + .borrow_mut(); + const_values.get().insert(id, v); + } let mut inlineable = inlineable; unsafe { @@ -2485,18 +2553,27 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef { llvm::LLVMAddGlobal(ccx.llmod, llty, buf) }); - if !ccx.reachable.contains(&id) { - lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage); + { + let reachable = ccx.reachable.borrow(); + if !reachable.get().contains(&id) { + lib::llvm::SetLinkage( + g, + lib::llvm::InternalLinkage); + } } // Apply the `unnamed_addr` attribute if // requested if attr::contains_name(i.attrs, "address_insignificant"){ - if ccx.reachable.contains(&id) { - ccx.sess.span_bug(i.span, - "insignificant static is \ - reachable"); + { + let reachable = + ccx.reachable.borrow(); + if reachable.get().contains(&id) { + ccx.sess.span_bug(i.span, + "insignificant static is \ + reachable"); + } } lib::llvm::SetUnnamedAddr(g, true); @@ -2525,9 +2602,15 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef { if !inlineable { debug!("{} not inlined", sym); - ccx.non_inlineable_statics.insert(id); + let mut non_inlineable_statics = + ccx.non_inlineable_statics + .borrow_mut(); + non_inlineable_statics.get().insert(id); } - ccx.item_symbols.insert(i.id, sym); + + let mut item_symbols = ccx.item_symbols + .borrow_mut(); + item_symbols.get().insert(i.id, sym); g } } @@ -2595,7 +2678,7 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef { // library then we've already declared the crate map // so use that instead. if attr::contains_name(ni.attrs, "crate_map") { - if *ccx.sess.building_library { + if ccx.sess.building_library.get() { let s = "_rust_crate_map_toplevel"; let g = unsafe { s.with_c_str(|buf| { @@ -2679,17 +2762,21 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef { // foreign items (extern fns and extern statics) don't have internal // linkage b/c that doesn't quite make sense. Otherwise items can // have internal linkage if they're not reachable. - if !foreign && !ccx.reachable.contains(&id) { - lib::llvm::SetLinkage(val, lib::llvm::InternalLinkage); + { + let reachable = ccx.reachable.borrow(); + if !foreign && !reachable.get().contains(&id) { + lib::llvm::SetLinkage(val, lib::llvm::InternalLinkage); + } } - ccx.item_vals.insert(id, val); + let mut item_vals = ccx.item_vals.borrow_mut(); + item_vals.get().insert(id, val); val } } } -pub fn register_method(ccx: @mut CrateContext, +pub fn register_method(ccx: @CrateContext, id: ast::NodeId, path: @ast_map::path, m: @ast::method) -> ValueRef { @@ -2705,7 +2792,7 @@ pub fn register_method(ccx: @mut CrateContext, llfn } -pub fn vp2i(cx: @mut Block, v: ValueRef) -> ValueRef { +pub fn vp2i(cx: @Block, v: ValueRef) -> ValueRef { let ccx = cx.ccx(); return PtrToInt(cx, v, ccx.int_type); } @@ -2873,14 +2960,14 @@ pub fn declare_dbg_intrinsics(llmod: ModuleRef, intrinsics: &mut HashMap<&'stati "llvm.dbg.value", [Type::metadata(), Type::i64(), Type::metadata()], Type::void()); } -pub fn trap(bcx: @mut Block) { +pub fn trap(bcx: @Block) { match bcx.ccx().intrinsics.find_equiv(& &"llvm.trap") { Some(&x) => { Call(bcx, x, [], []); }, _ => bcx.sess().bug("unbound llvm.trap in trap") } } -pub fn decl_gc_metadata(ccx: &mut CrateContext, llmod_id: &str) { +pub fn decl_gc_metadata(ccx: &CrateContext, llmod_id: &str) { if !ccx.sess.opts.gc || !ccx.uses_gc { return; } @@ -2894,14 +2981,19 @@ pub fn decl_gc_metadata(ccx: &mut CrateContext, llmod_id: &str) { unsafe { llvm::LLVMSetGlobalConstant(gc_metadata, True); lib::llvm::SetLinkage(gc_metadata, lib::llvm::ExternalLinkage); - ccx.module_data.insert(~"_gc_module_metadata", gc_metadata); + + let mut module_data = ccx.module_data.borrow_mut(); + module_data.get().insert(~"_gc_module_metadata", gc_metadata); } } -pub fn create_module_map(ccx: &mut CrateContext) -> (ValueRef, uint) { +pub fn create_module_map(ccx: &CrateContext) -> (ValueRef, uint) { let str_slice_type = Type::struct_([Type::i8p(), ccx.int_type], false); let elttype = Type::struct_([str_slice_type, ccx.int_type], false); - let maptype = Type::array(&elttype, ccx.module_data.len() as u64); + let maptype = { + let module_data = ccx.module_data.borrow(); + Type::array(&elttype, module_data.get().len() as u64) + }; let map = "_rust_mod_map".with_c_str(|buf| { unsafe { llvm::LLVMAddGlobal(ccx.llmod, maptype.to_ref(), buf) @@ -2913,16 +3005,22 @@ pub fn create_module_map(ccx: &mut CrateContext) -> (ValueRef, uint) { // This is not ideal, but the borrow checker doesn't // like the multiple borrows. At least, it doesn't // like them on the current snapshot. (2013-06-14) - let mut keys = ~[]; - for (k, _) in ccx.module_data.iter() { - keys.push(k.to_managed()); - } + let keys = { + let mut keys = ~[]; + let module_data = ccx.module_data.borrow(); + for (k, _) in module_data.get().iter() { + keys.push(k.to_managed()); + } + keys + }; for key in keys.iter() { - let val = *ccx.module_data.find_equiv(key).unwrap(); + let llestrval = C_estr_slice(ccx, *key); + let module_data = ccx.module_data.borrow(); + let val = *module_data.get().find_equiv(key).unwrap(); let v_ptr = p2i(ccx, val); let elt = C_struct([ - C_estr_slice(ccx, *key), + llestrval, v_ptr ], false); elts.push(elt); @@ -2946,7 +3044,7 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta, let mut n_subcrates = 1; let cstore = sess.cstore; while cstore.have_crate_data(n_subcrates) { n_subcrates += 1; } - let is_top = !*sess.building_library || sess.gen_crate_map(); + let is_top = !sess.building_library.get() || sess.gen_crate_map(); let sym_name = if is_top { ~"_rust_crate_map_toplevel" } else { @@ -2977,7 +3075,7 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta, return (sym_name, map); } -pub fn fill_crate_map(ccx: @mut CrateContext, map: ValueRef) { +pub fn fill_crate_map(ccx: @CrateContext, map: ValueRef) { let mut subcrates: ~[ValueRef] = ~[]; let mut i = 1; let cstore = ccx.sess.cstore; @@ -3039,14 +3137,12 @@ pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::encode_ let diag = cx.sess.diagnostic(); let item_symbols = &cx.item_symbols; - let discrim_symbols = &cx.discrim_symbols; let link_meta = &cx.link_meta; encoder::EncodeParams { diag: diag, tcx: cx.tcx, reexports2: cx.exp_map2, item_symbols: item_symbols, - discrim_symbols: discrim_symbols, non_inlineable_statics: &cx.non_inlineable_statics, link_meta: link_meta, cstore: cx.sess.cstore, @@ -3058,7 +3154,9 @@ pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::encode_ pub fn write_metadata(cx: &CrateContext, crate: &ast::Crate) -> ~[u8] { use extra::flate; - if !*cx.sess.building_library { return ~[]; } + if !cx.sess.building_library.get() { + return ~[] + } let encode_inlined_item: encoder::encode_inlined_item = |ecx, ebml_w, path, ii| @@ -3109,7 +3207,7 @@ pub fn trans_crate(sess: session::Session, // 1. http://llvm.org/bugs/show_bug.cgi?id=11479 let llmod_id = link_meta.pkgid.name.clone() + ".rc"; - let ccx = @mut CrateContext::new(sess, + let ccx = @CrateContext::new(sess, llmod_id, analysis.ty_cx, analysis.exp_map2, @@ -3131,8 +3229,7 @@ pub fn trans_crate(sess: session::Session, // __rust_crate_map_toplevel symbol (extra underscore) which it will // subsequently fail to find. So to mitigate that we just introduce // an alias from the symbol it expects to the one that actually exists. - if ccx.sess.targ_cfg.os == OsWin32 && - !*ccx.sess.building_library { + if ccx.sess.targ_cfg.os == OsWin32 && !ccx.sess.building_library.get() { let maptype = val_ty(ccx.crate_map).to_ref(); @@ -3153,29 +3250,33 @@ pub fn trans_crate(sess: session::Session, let metadata = write_metadata(ccx, &crate); if ccx.sess.trans_stats() { println("--- trans stats ---"); - println!("n_static_tydescs: {}", ccx.stats.n_static_tydescs); - println!("n_glues_created: {}", ccx.stats.n_glues_created); - println!("n_null_glues: {}", ccx.stats.n_null_glues); - println!("n_real_glues: {}", ccx.stats.n_real_glues); - - println!("n_fns: {}", ccx.stats.n_fns); - println!("n_monos: {}", ccx.stats.n_monos); - println!("n_inlines: {}", ccx.stats.n_inlines); - println!("n_closures: {}", ccx.stats.n_closures); + println!("n_static_tydescs: {}", ccx.stats.n_static_tydescs.get()); + println!("n_glues_created: {}", ccx.stats.n_glues_created.get()); + println!("n_null_glues: {}", ccx.stats.n_null_glues.get()); + println!("n_real_glues: {}", ccx.stats.n_real_glues.get()); + + println!("n_fns: {}", ccx.stats.n_fns.get()); + println!("n_monos: {}", ccx.stats.n_monos.get()); + println!("n_inlines: {}", ccx.stats.n_inlines.get()); + println!("n_closures: {}", ccx.stats.n_closures.get()); println("fn stats:"); - - ccx.stats.fn_stats.sort_by(|&(_, _, insns_a), &(_, _, insns_b)| insns_b.cmp(&insns_a)); - - for tuple in ccx.stats.fn_stats.iter() { - match *tuple { - (ref name, ms, insns) => { - println!("{} insns, {} ms, {}", insns, ms, *name); + { + let mut fn_stats = ccx.stats.fn_stats.borrow_mut(); + fn_stats.get().sort_by(|&(_, _, insns_a), &(_, _, insns_b)| { + insns_b.cmp(&insns_a) + }); + for tuple in fn_stats.get().iter() { + match *tuple { + (ref name, ms, insns) => { + println!("{} insns, {} ms, {}", insns, ms, *name); + } } } } } if ccx.sess.count_llvm_insns() { - for (k, v) in ccx.stats.llvm_insns.iter() { + let llvm_insns = ccx.stats.llvm_insns.borrow(); + for (k, v) in llvm_insns.get().iter() { println!("{:7u} {}", *v, *k); } } @@ -3183,9 +3284,14 @@ pub fn trans_crate(sess: session::Session, let llcx = ccx.llcx; let link_meta = ccx.link_meta.clone(); let llmod = ccx.llmod; - let mut reachable = ccx.reachable.iter().filter_map(|id| { - ccx.item_symbols.find(id).map(|s| s.to_owned()) - }).to_owned_vec(); + + let mut reachable = { + let reachable_map = ccx.reachable.borrow(); + reachable_map.get().iter().filter_map(|id| { + let item_symbols = ccx.item_symbols.borrow(); + item_symbols.get().find(id).map(|s| s.to_owned()) + }).to_owned_vec() + }; // Make sure that some other crucial symbols are not eliminated from the // module. This includes the main function, the crate map (used for debug diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index 2042c6ddad104..faf210c1a9ea0 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -23,12 +23,12 @@ use middle::trans::type_::Type; use std::cast; use std::libc::{c_uint, c_ulonglong, c_char}; -pub fn terminate(cx: &mut Block, _: &str) { - cx.terminated = true; +pub fn terminate(cx: &Block, _: &str) { + cx.terminated.set(true); } pub fn check_not_terminated(cx: &Block) { - if cx.terminated { + if cx.terminated.get() { fail!("already terminated!"); } } @@ -47,45 +47,45 @@ pub fn B(cx: &Block) -> Builder { // for (fail/break/return statements, call to diverging functions, etc), and // further instructions to the block should simply be ignored. -pub fn RetVoid(cx: &mut Block) { - if cx.unreachable { return; } +pub fn RetVoid(cx: &Block) { + if cx.unreachable.get() { return; } check_not_terminated(cx); terminate(cx, "RetVoid"); B(cx).ret_void(); } -pub fn Ret(cx: @mut Block, V: ValueRef) { - if cx.unreachable { return; } +pub fn Ret(cx: @Block, V: ValueRef) { + if cx.unreachable.get() { return; } check_not_terminated(cx); terminate(cx, "Ret"); B(cx).ret(V); } -pub fn AggregateRet(cx: @mut Block, RetVals: &[ValueRef]) { - if cx.unreachable { return; } +pub fn AggregateRet(cx: @Block, RetVals: &[ValueRef]) { + if cx.unreachable.get() { return; } check_not_terminated(cx); terminate(cx, "AggregateRet"); B(cx).aggregate_ret(RetVals); } -pub fn Br(cx: @mut Block, Dest: BasicBlockRef) { - if cx.unreachable { return; } +pub fn Br(cx: @Block, Dest: BasicBlockRef) { + if cx.unreachable.get() { return; } check_not_terminated(cx); terminate(cx, "Br"); B(cx).br(Dest); } -pub fn CondBr(cx: @mut Block, If: ValueRef, Then: BasicBlockRef, +pub fn CondBr(cx: @Block, If: ValueRef, Then: BasicBlockRef, Else: BasicBlockRef) { - if cx.unreachable { return; } + if cx.unreachable.get() { return; } check_not_terminated(cx); terminate(cx, "CondBr"); B(cx).cond_br(If, Then, Else); } -pub fn Switch(cx: &mut Block, V: ValueRef, Else: BasicBlockRef, NumCases: uint) +pub fn Switch(cx: &Block, V: ValueRef, Else: BasicBlockRef, NumCases: uint) -> ValueRef { - if cx.unreachable { return _Undef(V); } + if cx.unreachable.get() { return _Undef(V); } check_not_terminated(cx); terminate(cx, "Switch"); B(cx).switch(V, Else, NumCases) @@ -98,21 +98,21 @@ pub fn AddCase(S: ValueRef, OnVal: ValueRef, Dest: BasicBlockRef) { } } -pub fn IndirectBr(cx: &mut Block, Addr: ValueRef, NumDests: uint) { - if cx.unreachable { return; } +pub fn IndirectBr(cx: &Block, Addr: ValueRef, NumDests: uint) { + if cx.unreachable.get() { return; } check_not_terminated(cx); terminate(cx, "IndirectBr"); B(cx).indirect_br(Addr, NumDests); } -pub fn Invoke(cx: @mut Block, +pub fn Invoke(cx: @Block, Fn: ValueRef, Args: &[ValueRef], Then: BasicBlockRef, Catch: BasicBlockRef, attributes: &[(uint, lib::llvm::Attribute)]) -> ValueRef { - if cx.unreachable { + if cx.unreachable.get() { return C_null(Type::i8()); } check_not_terminated(cx); @@ -123,10 +123,12 @@ pub fn Invoke(cx: @mut Block, B(cx).invoke(Fn, Args, Then, Catch, attributes) } -pub fn Unreachable(cx: &mut Block) { - if cx.unreachable { return; } - cx.unreachable = true; - if !cx.terminated { +pub fn Unreachable(cx: &Block) { + if cx.unreachable.get() { + return + } + cx.unreachable.set(true); + if !cx.terminated.get() { B(cx).unreachable(); } } @@ -139,202 +141,202 @@ pub fn _Undef(val: ValueRef) -> ValueRef { /* Arithmetic */ pub fn Add(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).add(LHS, RHS) } pub fn NSWAdd(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).nswadd(LHS, RHS) } pub fn NUWAdd(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).nuwadd(LHS, RHS) } pub fn FAdd(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).fadd(LHS, RHS) } pub fn Sub(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).sub(LHS, RHS) } pub fn NSWSub(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).nswsub(LHS, RHS) } pub fn NUWSub(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).nuwsub(LHS, RHS) } pub fn FSub(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).fsub(LHS, RHS) } pub fn Mul(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).mul(LHS, RHS) } pub fn NSWMul(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).nswmul(LHS, RHS) } pub fn NUWMul(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).nuwmul(LHS, RHS) } pub fn FMul(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).fmul(LHS, RHS) } pub fn UDiv(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).udiv(LHS, RHS) } pub fn SDiv(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).sdiv(LHS, RHS) } pub fn ExactSDiv(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).exactsdiv(LHS, RHS) } pub fn FDiv(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).fdiv(LHS, RHS) } pub fn URem(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).urem(LHS, RHS) } pub fn SRem(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).srem(LHS, RHS) } pub fn FRem(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).frem(LHS, RHS) } pub fn Shl(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).shl(LHS, RHS) } pub fn LShr(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).lshr(LHS, RHS) } pub fn AShr(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).ashr(LHS, RHS) } pub fn And(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).and(LHS, RHS) } pub fn Or(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).or(LHS, RHS) } pub fn Xor(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).xor(LHS, RHS) } pub fn BinOp(cx: &Block, Op: Opcode, LHS: ValueRef, RHS: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(LHS); } + if cx.unreachable.get() { return _Undef(LHS); } B(cx).binop(Op, LHS, RHS) } pub fn Neg(cx: &Block, V: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(V); } + if cx.unreachable.get() { return _Undef(V); } B(cx).neg(V) } pub fn NSWNeg(cx: &Block, V: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(V); } + if cx.unreachable.get() { return _Undef(V); } B(cx).nswneg(V) } pub fn NUWNeg(cx: &Block, V: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(V); } + if cx.unreachable.get() { return _Undef(V); } B(cx).nuwneg(V) } pub fn FNeg(cx: &Block, V: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(V); } + if cx.unreachable.get() { return _Undef(V); } B(cx).fneg(V) } pub fn Not(cx: &Block, V: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(V); } + if cx.unreachable.get() { return _Undef(V); } B(cx).not(V) } /* Memory */ pub fn Malloc(cx: &Block, Ty: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::i8p().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i8p().to_ref()); } B(cx).malloc(Ty) } } pub fn ArrayMalloc(cx: &Block, Ty: Type, Val: ValueRef) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::i8p().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i8p().to_ref()); } B(cx).array_malloc(Ty, Val) } } pub fn Alloca(cx: &Block, Ty: Type, name: &str) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Ty.ptr_to().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Ty.ptr_to().to_ref()); } let b = cx.fcx.ccx.builder(); - b.position_before(cx.fcx.alloca_insert_pt.unwrap()); + b.position_before(cx.fcx.alloca_insert_pt.get().unwrap()); b.alloca(Ty, name) } } pub fn ArrayAlloca(cx: &Block, Ty: Type, Val: ValueRef) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Ty.ptr_to().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Ty.ptr_to().to_ref()); } let b = cx.fcx.ccx.builder(); - b.position_before(cx.fcx.alloca_insert_pt.unwrap()); + b.position_before(cx.fcx.alloca_insert_pt.get().unwrap()); b.array_alloca(Ty, Val) } } pub fn Free(cx: &Block, PointerVal: ValueRef) { - if cx.unreachable { return; } + if cx.unreachable.get() { return; } B(cx).free(PointerVal) } pub fn Load(cx: &Block, PointerVal: ValueRef) -> ValueRef { unsafe { let ccx = cx.fcx.ccx; - if cx.unreachable { + if cx.unreachable.get() { let ty = val_ty(PointerVal); let eltty = if ty.kind() == lib::llvm::Array { ty.element_type() @@ -350,7 +352,7 @@ pub fn Load(cx: &Block, PointerVal: ValueRef) -> ValueRef { pub fn AtomicLoad(cx: &Block, PointerVal: ValueRef, order: AtomicOrdering) -> ValueRef { unsafe { let ccx = cx.fcx.ccx; - if cx.unreachable { + if cx.unreachable.get() { return llvm::LLVMGetUndef(ccx.int_type.to_ref()); } B(cx).atomic_load(PointerVal, order) @@ -360,7 +362,7 @@ pub fn AtomicLoad(cx: &Block, PointerVal: ValueRef, order: AtomicOrdering) -> Va pub fn LoadRangeAssert(cx: &Block, PointerVal: ValueRef, lo: c_ulonglong, hi: c_ulonglong, signed: lib::llvm::Bool) -> ValueRef { - if cx.unreachable { + if cx.unreachable.get() { let ccx = cx.fcx.ccx; let ty = val_ty(PointerVal); let eltty = if ty.kind() == lib::llvm::Array { @@ -377,18 +379,18 @@ pub fn LoadRangeAssert(cx: &Block, PointerVal: ValueRef, lo: c_ulonglong, } pub fn Store(cx: &Block, Val: ValueRef, Ptr: ValueRef) { - if cx.unreachable { return; } + if cx.unreachable.get() { return; } B(cx).store(Val, Ptr) } pub fn AtomicStore(cx: &Block, Val: ValueRef, Ptr: ValueRef, order: AtomicOrdering) { - if cx.unreachable { return; } + if cx.unreachable.get() { return; } B(cx).atomic_store(Val, Ptr, order) } pub fn GEP(cx: &Block, Pointer: ValueRef, Indices: &[ValueRef]) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref()); } B(cx).gep(Pointer, Indices) } } @@ -398,35 +400,35 @@ pub fn GEP(cx: &Block, Pointer: ValueRef, Indices: &[ValueRef]) -> ValueRef { #[inline] pub fn GEPi(cx: &Block, base: ValueRef, ixs: &[uint]) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref()); } B(cx).gepi(base, ixs) } } pub fn InBoundsGEP(cx: &Block, Pointer: ValueRef, Indices: &[ValueRef]) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref()); } B(cx).inbounds_gep(Pointer, Indices) } } pub fn StructGEP(cx: &Block, Pointer: ValueRef, Idx: uint) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref()); } B(cx).struct_gep(Pointer, Idx) } } pub fn GlobalString(cx: &Block, _Str: *c_char) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::i8p().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i8p().to_ref()); } B(cx).global_string(_Str) } } pub fn GlobalStringPtr(cx: &Block, _Str: *c_char) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::i8p().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i8p().to_ref()); } B(cx).global_string_ptr(_Str) } } @@ -434,105 +436,105 @@ pub fn GlobalStringPtr(cx: &Block, _Str: *c_char) -> ValueRef { /* Casts */ pub fn Trunc(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).trunc(Val, DestTy) } } pub fn ZExt(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).zext(Val, DestTy) } } pub fn SExt(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).sext(Val, DestTy) } } pub fn FPToUI(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).fptoui(Val, DestTy) } } pub fn FPToSI(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).fptosi(Val, DestTy) } } pub fn UIToFP(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).uitofp(Val, DestTy) } } pub fn SIToFP(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).sitofp(Val, DestTy) } } pub fn FPTrunc(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).fptrunc(Val, DestTy) } } pub fn FPExt(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).fpext(Val, DestTy) } } pub fn PtrToInt(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).ptrtoint(Val, DestTy) } } pub fn IntToPtr(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).inttoptr(Val, DestTy) } } pub fn BitCast(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).bitcast(Val, DestTy) } } pub fn ZExtOrBitCast(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).zext_or_bitcast(Val, DestTy) } } pub fn SExtOrBitCast(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).sext_or_bitcast(Val, DestTy) } } pub fn TruncOrBitCast(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).trunc_or_bitcast(Val, DestTy) } } @@ -540,28 +542,28 @@ pub fn TruncOrBitCast(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { pub fn Cast(cx: &Block, Op: Opcode, Val: ValueRef, DestTy: Type, _: *u8) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).cast(Op, Val, DestTy) } } pub fn PointerCast(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).pointercast(Val, DestTy) } } pub fn IntCast(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).intcast(Val, DestTy) } } pub fn FPCast(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(DestTy.to_ref()); } B(cx).fpcast(Val, DestTy) } } @@ -571,7 +573,7 @@ pub fn FPCast(cx: &Block, Val: ValueRef, DestTy: Type) -> ValueRef { pub fn ICmp(cx: &Block, Op: IntPredicate, LHS: ValueRef, RHS: ValueRef) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::i1().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i1().to_ref()); } B(cx).icmp(Op, LHS, RHS) } } @@ -579,7 +581,7 @@ pub fn ICmp(cx: &Block, Op: IntPredicate, LHS: ValueRef, RHS: ValueRef) pub fn FCmp(cx: &Block, Op: RealPredicate, LHS: ValueRef, RHS: ValueRef) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::i1().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i1().to_ref()); } B(cx).fcmp(Op, LHS, RHS) } } @@ -587,14 +589,14 @@ pub fn FCmp(cx: &Block, Op: RealPredicate, LHS: ValueRef, RHS: ValueRef) /* Miscellaneous instructions */ pub fn EmptyPhi(cx: &Block, Ty: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Ty.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Ty.to_ref()); } B(cx).empty_phi(Ty) } } pub fn Phi(cx: &Block, Ty: Type, vals: &[ValueRef], bbs: &[BasicBlockRef]) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Ty.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Ty.to_ref()); } B(cx).phi(Ty, vals, bbs) } } @@ -639,36 +641,36 @@ pub fn InlineAsmCall(cx: &Block, asm: *c_char, cons: *c_char, pub fn Call(cx: &Block, Fn: ValueRef, Args: &[ValueRef], attributes: &[(uint, lib::llvm::Attribute)]) -> ValueRef { - if cx.unreachable { return _UndefReturn(cx, Fn); } + if cx.unreachable.get() { return _UndefReturn(cx, Fn); } B(cx).call(Fn, Args, attributes) } pub fn CallWithConv(cx: &Block, Fn: ValueRef, Args: &[ValueRef], Conv: CallConv, attributes: &[(uint, lib::llvm::Attribute)]) -> ValueRef { - if cx.unreachable { return _UndefReturn(cx, Fn); } + if cx.unreachable.get() { return _UndefReturn(cx, Fn); } B(cx).call_with_conv(Fn, Args, Conv, attributes) } pub fn AtomicFence(cx: &Block, order: AtomicOrdering) { - if cx.unreachable { return; } + if cx.unreachable.get() { return; } B(cx).atomic_fence(order) } pub fn Select(cx: &Block, If: ValueRef, Then: ValueRef, Else: ValueRef) -> ValueRef { - if cx.unreachable { return _Undef(Then); } + if cx.unreachable.get() { return _Undef(Then); } B(cx).select(If, Then, Else) } pub fn VAArg(cx: &Block, list: ValueRef, Ty: Type) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Ty.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Ty.to_ref()); } B(cx).va_arg(list, Ty) } } pub fn ExtractElement(cx: &Block, VecVal: ValueRef, Index: ValueRef) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().to_ref()); } B(cx).extract_element(VecVal, Index) } } @@ -676,7 +678,7 @@ pub fn ExtractElement(cx: &Block, VecVal: ValueRef, Index: ValueRef) -> ValueRef pub fn InsertElement(cx: &Block, VecVal: ValueRef, EltVal: ValueRef, Index: ValueRef) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().to_ref()); } B(cx).insert_element(VecVal, EltVal, Index) } } @@ -684,42 +686,42 @@ pub fn InsertElement(cx: &Block, VecVal: ValueRef, EltVal: ValueRef, pub fn ShuffleVector(cx: &Block, V1: ValueRef, V2: ValueRef, Mask: ValueRef) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().to_ref()); } B(cx).shuffle_vector(V1, V2, Mask) } } pub fn VectorSplat(cx: &Block, NumElts: uint, EltVal: ValueRef) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().to_ref()); } B(cx).vector_splat(NumElts, EltVal) } } pub fn ExtractValue(cx: &Block, AggVal: ValueRef, Index: uint) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().to_ref()); } B(cx).extract_value(AggVal, Index) } } pub fn InsertValue(cx: &Block, AggVal: ValueRef, EltVal: ValueRef, Index: uint) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().to_ref()); } B(cx).insert_value(AggVal, EltVal, Index) } } pub fn IsNull(cx: &Block, Val: ValueRef) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::i1().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i1().to_ref()); } B(cx).is_null(Val) } } pub fn IsNotNull(cx: &Block, Val: ValueRef) -> ValueRef { unsafe { - if cx.unreachable { return llvm::LLVMGetUndef(Type::i1().to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i1().to_ref()); } B(cx).is_not_null(Val) } } @@ -727,20 +729,20 @@ pub fn IsNotNull(cx: &Block, Val: ValueRef) -> ValueRef { pub fn PtrDiff(cx: &Block, LHS: ValueRef, RHS: ValueRef) -> ValueRef { unsafe { let ccx = cx.fcx.ccx; - if cx.unreachable { return llvm::LLVMGetUndef(ccx.int_type.to_ref()); } + if cx.unreachable.get() { return llvm::LLVMGetUndef(ccx.int_type.to_ref()); } B(cx).ptrdiff(LHS, RHS) } } pub fn Trap(cx: &Block) { - if cx.unreachable { return; } + if cx.unreachable.get() { return; } B(cx).trap(); } pub fn LandingPad(cx: &Block, Ty: Type, PersFn: ValueRef, NumClauses: uint) -> ValueRef { check_not_terminated(cx); - assert!(!cx.unreachable); + assert!(!cx.unreachable.get()); B(cx).landing_pad(Ty, PersFn, NumClauses) } @@ -748,7 +750,7 @@ pub fn SetCleanup(cx: &Block, LandingPad: ValueRef) { B(cx).set_cleanup(LandingPad) } -pub fn Resume(cx: @mut Block, Exn: ValueRef) -> ValueRef { +pub fn Resume(cx: @Block, Exn: ValueRef) -> ValueRef { check_not_terminated(cx); terminate(cx, "Resume"); B(cx).resume(Exn) diff --git a/src/librustc/middle/trans/builder.rs b/src/librustc/middle/trans/builder.rs index 02e2232bfc8f0..eacc6f84db118 100644 --- a/src/librustc/middle/trans/builder.rs +++ b/src/librustc/middle/trans/builder.rs @@ -25,7 +25,7 @@ use std::ptr::is_not_null; pub struct Builder { llbuilder: BuilderRef, - ccx: @mut CrateContext, + ccx: @CrateContext, } // This is a really awful way to get a zero-length c-string, but better (and a @@ -38,7 +38,7 @@ pub fn noname() -> *c_char { } impl Builder { - pub fn new(ccx: @mut CrateContext) -> Builder { + pub fn new(ccx: @CrateContext) -> Builder { Builder { llbuilder: ccx.builder.B, ccx: ccx, @@ -47,11 +47,14 @@ impl Builder { pub fn count_insn(&self, category: &str) { if self.ccx.sess.trans_stats() { - self.ccx.stats.n_llvm_insns += 1; + self.ccx.stats.n_llvm_insns.set(self.ccx + .stats + .n_llvm_insns + .get() + 1); } if self.ccx.sess.count_llvm_insns() { base::with_insn_ctxt(|v| { - let h = &mut self.ccx.stats.llvm_insns; + let mut h = self.ccx.stats.llvm_insns.borrow_mut(); // Build version of path with cycles removed. @@ -79,11 +82,11 @@ impl Builder { s.push_char('/'); s.push_str(category); - let n = match h.find(&s) { + let n = match h.get().find(&s) { Some(&n) => n, _ => 0u }; - h.insert(s, n+1u); + h.get().insert(s, n+1u); }) } } diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs index 8648bf6f34803..bb05221ae1019 100644 --- a/src/librustc/middle/trans/cabi.rs +++ b/src/librustc/middle/trans/cabi.rs @@ -89,7 +89,7 @@ pub struct FnType { ret_ty: ArgType, } -pub fn compute_abi_info(ccx: &mut CrateContext, +pub fn compute_abi_info(ccx: &CrateContext, atys: &[Type], rty: Type, ret_def: bool) -> FnType { diff --git a/src/librustc/middle/trans/cabi_arm.rs b/src/librustc/middle/trans/cabi_arm.rs index 736feeb0618a4..a73c098805d6a 100644 --- a/src/librustc/middle/trans/cabi_arm.rs +++ b/src/librustc/middle/trans/cabi_arm.rs @@ -127,7 +127,7 @@ fn is_reg_ty(ty: Type) -> bool { } } -pub fn compute_abi_info(_ccx: &mut CrateContext, +pub fn compute_abi_info(_ccx: &CrateContext, atys: &[Type], rty: Type, ret_def: bool) -> FnType { diff --git a/src/librustc/middle/trans/cabi_mips.rs b/src/librustc/middle/trans/cabi_mips.rs index e98618c4e0108..54155cd3f7825 100644 --- a/src/librustc/middle/trans/cabi_mips.rs +++ b/src/librustc/middle/trans/cabi_mips.rs @@ -158,7 +158,7 @@ fn struct_ty(ty: Type) -> Type { return Type::struct_(fields, false); } -pub fn compute_abi_info(_ccx: &mut CrateContext, +pub fn compute_abi_info(_ccx: &CrateContext, atys: &[Type], rty: Type, ret_def: bool) -> FnType { diff --git a/src/librustc/middle/trans/cabi_x86.rs b/src/librustc/middle/trans/cabi_x86.rs index f8cc246f6828e..616dc0703a73e 100644 --- a/src/librustc/middle/trans/cabi_x86.rs +++ b/src/librustc/middle/trans/cabi_x86.rs @@ -16,7 +16,7 @@ use super::common::*; use super::machine::*; use middle::trans::type_::Type; -pub fn compute_abi_info(ccx: &mut CrateContext, +pub fn compute_abi_info(ccx: &CrateContext, atys: &[Type], rty: Type, ret_def: bool) -> FnType { diff --git a/src/librustc/middle/trans/cabi_x86_64.rs b/src/librustc/middle/trans/cabi_x86_64.rs index 329651cb1941a..564efa8c06864 100644 --- a/src/librustc/middle/trans/cabi_x86_64.rs +++ b/src/librustc/middle/trans/cabi_x86_64.rs @@ -332,7 +332,7 @@ fn llreg_ty(cls: &[RegClass]) -> Type { return Type::struct_(tys, false); } -pub fn compute_abi_info(_ccx: &mut CrateContext, +pub fn compute_abi_info(_ccx: &CrateContext, atys: &[Type], rty: Type, ret_def: bool) -> FnType { diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index db193b9200ae1..df916f0463bce 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -71,11 +71,11 @@ pub enum CalleeData { } pub struct Callee { - bcx: @mut Block, + bcx: @Block, data: CalleeData } -pub fn trans(bcx: @mut Block, expr: &ast::Expr) -> Callee { +pub fn trans(bcx: @Block, expr: &ast::Expr) -> Callee { let _icx = push_ctxt("trans_callee"); debug!("callee::trans(expr={})", expr.repr(bcx.tcx())); @@ -90,7 +90,7 @@ pub fn trans(bcx: @mut Block, expr: &ast::Expr) -> Callee { // any other expressions are closures: return datum_callee(bcx, expr); - fn datum_callee(bcx: @mut Block, expr: &ast::Expr) -> Callee { + fn datum_callee(bcx: @Block, expr: &ast::Expr) -> Callee { let DatumBlock {bcx, datum} = expr::trans_to_datum(bcx, expr); match ty::get(datum.ty).sty { ty::ty_bare_fn(..) => { @@ -109,11 +109,11 @@ pub fn trans(bcx: @mut Block, expr: &ast::Expr) -> Callee { } } - fn fn_callee(bcx: @mut Block, fd: FnData) -> Callee { + fn fn_callee(bcx: @Block, fd: FnData) -> Callee { return Callee {bcx: bcx, data: Fn(fd)}; } - fn trans_def(bcx: @mut Block, def: ast::Def, ref_expr: &ast::Expr) -> Callee { + fn trans_def(bcx: @Block, def: ast::Def, ref_expr: &ast::Expr) -> Callee { match def { ast::DefFn(did, _) | ast::DefStaticMethod(did, ast::FromImpl(_), _) => { @@ -158,14 +158,14 @@ pub fn trans(bcx: @mut Block, expr: &ast::Expr) -> Callee { } } -pub fn trans_fn_ref_to_callee(bcx: @mut Block, +pub fn trans_fn_ref_to_callee(bcx: @Block, def_id: ast::DefId, ref_id: ast::NodeId) -> Callee { Callee {bcx: bcx, data: Fn(trans_fn_ref(bcx, def_id, ref_id))} } -pub fn trans_fn_ref(bcx: @mut Block, +pub fn trans_fn_ref(bcx: @Block, def_id: ast::DefId, ref_id: ast::NodeId) -> FnData { /*! @@ -185,7 +185,7 @@ pub fn trans_fn_ref(bcx: @mut Block, } pub fn trans_fn_ref_with_vtables_to_callee( - bcx: @mut Block, + bcx: @Block, def_id: ast::DefId, ref_id: ast::NodeId, type_params: &[ty::t], @@ -196,7 +196,7 @@ pub fn trans_fn_ref_with_vtables_to_callee( type_params, vtables))} } -fn resolve_default_method_vtables(bcx: @mut Block, +fn resolve_default_method_vtables(bcx: @Block, impl_id: ast::DefId, method: &ty::Method, substs: &ty::substs, @@ -239,7 +239,7 @@ fn resolve_default_method_vtables(bcx: @mut Block, pub fn trans_fn_ref_with_vtables( - bcx: @mut Block, // + bcx: @Block, // def_id: ast::DefId, // def id of fn ref_id: ast::NodeId, // node id of use of fn; may be zero if N/A type_params: &[ty::t], // values for fn's ty params @@ -444,13 +444,13 @@ pub fn trans_fn_ref_with_vtables( // ______________________________________________________________________ // Translating calls -pub fn trans_call(in_cx: @mut Block, +pub fn trans_call(in_cx: @Block, call_ex: &ast::Expr, f: &ast::Expr, args: CallArgs, id: ast::NodeId, dest: expr::Dest) - -> @mut Block { + -> @Block { let _icx = push_ctxt("trans_call"); trans_call_inner(in_cx, call_ex.info(), @@ -462,13 +462,13 @@ pub fn trans_call(in_cx: @mut Block, DontAutorefArg).bcx } -pub fn trans_method_call(in_cx: @mut Block, +pub fn trans_method_call(in_cx: @Block, call_ex: &ast::Expr, callee_id: ast::NodeId, rcvr: &ast::Expr, args: CallArgs, dest: expr::Dest) - -> @mut Block { + -> @Block { let _icx = push_ctxt("trans_method_call"); debug!("trans_method_call(call_ex={}, rcvr={})", call_ex.repr(in_cx.tcx()), @@ -479,7 +479,11 @@ pub fn trans_method_call(in_cx: @mut Block, node_id_type(in_cx, callee_id), expr_ty(in_cx, call_ex), |cx| { - match cx.ccx().maps.method_map.find_copy(&call_ex.id) { + let origin_opt = { + let mut method_map = cx.ccx().maps.method_map.borrow_mut(); + method_map.get().find_copy(&call_ex.id) + }; + match origin_opt { Some(origin) => { debug!("origin for {}: {}", call_ex.repr(in_cx.tcx()), @@ -500,7 +504,7 @@ pub fn trans_method_call(in_cx: @mut Block, DontAutorefArg).bcx } -pub fn trans_lang_call(bcx: @mut Block, +pub fn trans_lang_call(bcx: @Block, did: ast::DefId, args: &[ValueRef], dest: Option) @@ -527,12 +531,12 @@ pub fn trans_lang_call(bcx: @mut Block, DontAutorefArg) } -pub fn trans_lang_call_with_type_params(bcx: @mut Block, +pub fn trans_lang_call_with_type_params(bcx: @Block, did: ast::DefId, args: &[ValueRef], type_params: &[ty::t], dest: expr::Dest) - -> @mut Block { + -> @Block { let fty; if did.crate == ast::LOCAL_CRATE { fty = ty::node_id_to_type(bcx.tcx(), did.node); @@ -567,11 +571,11 @@ pub fn trans_lang_call_with_type_params(bcx: @mut Block, ArgVals(args), Some(dest), DontAutorefArg).bcx; } -pub fn trans_call_inner(in_cx: @mut Block, +pub fn trans_call_inner(in_cx: @Block, call_info: Option, callee_ty: ty::t, ret_ty: ty::t, - get_callee: |@mut Block| -> Callee, + get_callee: |@Block| -> Callee, args: CallArgs, dest: Option, autoref_arg: AutorefArg) @@ -755,11 +759,11 @@ pub enum CallArgs<'a> { ArgVals(&'a [ValueRef]) } -pub fn trans_args(cx: @mut Block, +pub fn trans_args(cx: @Block, args: CallArgs, fn_ty: ty::t, autoref_arg: AutorefArg, - llargs: &mut ~[ValueRef]) -> @mut Block + llargs: &mut ~[ValueRef]) -> @Block { let _icx = push_ctxt("trans_args"); let mut temp_cleanups = ~[]; @@ -814,7 +818,7 @@ pub enum AutorefArg { // temp_cleanups: cleanups that should run only if failure occurs before the // call takes place: -pub fn trans_arg_expr(bcx: @mut Block, +pub fn trans_arg_expr(bcx: @Block, formal_arg_ty: ty::t, self_mode: ty::SelfMode, arg_expr: &ast::Expr, diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 768d3cbd4b2c8..1d56601cfba44 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -155,7 +155,7 @@ pub fn mk_closure_tys(tcx: ty::ctxt, return cdata_ty; } -fn heap_for_unique_closure(bcx: @mut Block, t: ty::t) -> heap { +fn heap_for_unique_closure(bcx: @Block, t: ty::t) -> heap { if ty::type_contents(bcx.tcx(), t).owns_managed() { heap_managed_unique } else { @@ -163,7 +163,7 @@ fn heap_for_unique_closure(bcx: @mut Block, t: ty::t) -> heap { } } -pub fn allocate_cbox(bcx: @mut Block, sigil: ast::Sigil, cdata_ty: ty::t) +pub fn allocate_cbox(bcx: @Block, sigil: ast::Sigil, cdata_ty: ty::t) -> Result { let _icx = push_ctxt("closure::allocate_cbox"); let ccx = bcx.ccx(); @@ -188,14 +188,14 @@ pub fn allocate_cbox(bcx: @mut Block, sigil: ast::Sigil, cdata_ty: ty::t) pub struct ClosureResult { llbox: ValueRef, // llvalue of ptr to closure cdata_ty: ty::t, // type of the closure data - bcx: @mut Block // final bcx + bcx: @Block // final bcx } // Given a block context and a list of tydescs and values to bind // construct a closure out of them. If copying is true, it is a // heap allocated closure that copies the upvars into environment. // Otherwise, it is stack allocated and copies pointers to the upvars. -pub fn store_environment(bcx: @mut Block, +pub fn store_environment(bcx: @Block, bound_values: ~[EnvValue], sigil: ast::Sigil) -> ClosureResult { @@ -257,7 +257,7 @@ pub fn store_environment(bcx: @mut Block, // Given a context and a list of upvars, build a closure. This just // collects the upvars and packages them up for store_environment. -pub fn build_closure(bcx0: @mut Block, +pub fn build_closure(bcx0: @Block, cap_vars: &[moves::CaptureVar], sigil: ast::Sigil) -> ClosureResult { let _icx = push_ctxt("closure::build_closure"); @@ -293,7 +293,7 @@ pub fn build_closure(bcx0: @mut Block, // Given an enclosing block context, a new function context, a closure type, // and a list of upvars, generate code to load and populate the environment // with the upvars and type descriptors. -pub fn load_environment(fcx: @mut FunctionContext, +pub fn load_environment(fcx: @FunctionContext, cdata_ty: ty::t, cap_vars: &[moves::CaptureVar], sigil: ast::Sigil) { @@ -304,10 +304,10 @@ pub fn load_environment(fcx: @mut FunctionContext, return; } - let bcx = fcx.entry_bcx.unwrap(); + let bcx = fcx.entry_bcx.get().unwrap(); // Load a pointer to the closure data, skipping over the box header: - let llcdata = opaque_box_body(bcx, cdata_ty, fcx.llenv); + let llcdata = opaque_box_body(bcx, cdata_ty, fcx.llenv.get()); // Store the pointer to closure data in an alloca for debug info because that's what the // llvm.dbg.declare intrinsic expects @@ -328,7 +328,11 @@ pub fn load_environment(fcx: @mut FunctionContext, ast::ManagedSigil | ast::OwnedSigil => {} } let def_id = ast_util::def_id_of_def(cap_var.def); - fcx.llupvars.insert(def_id.node, upvarptr); + + { + let mut llupvars = fcx.llupvars.borrow_mut(); + llupvars.get().insert(def_id.node, upvarptr); + } for &env_pointer_alloca in env_pointer_alloca.iter() { debuginfo::create_captured_var_metadata( @@ -345,13 +349,13 @@ pub fn load_environment(fcx: @mut FunctionContext, } } -pub fn trans_expr_fn(bcx: @mut Block, +pub fn trans_expr_fn(bcx: @Block, sigil: ast::Sigil, decl: &ast::fn_decl, body: &ast::Block, outer_id: ast::NodeId, user_id: ast::NodeId, - dest: expr::Dest) -> @mut Block { + dest: expr::Dest) -> @Block { /*! * * Translates the body of a closure expression. @@ -400,7 +404,10 @@ pub fn trans_expr_fn(bcx: @mut Block, let Result {bcx: bcx, val: closure} = match sigil { ast::BorrowedSigil | ast::ManagedSigil | ast::OwnedSigil => { - let cap_vars = ccx.maps.capture_map.get_copy(&user_id); + let cap_vars = { + let capture_map = ccx.maps.capture_map.borrow(); + capture_map.get().get_copy(&user_id) + }; let ClosureResult {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, sigil); trans_closure(ccx, @@ -422,12 +429,12 @@ pub fn trans_expr_fn(bcx: @mut Block, return bcx; } -pub fn make_closure_glue(cx: @mut Block, +pub fn make_closure_glue(cx: @Block, v: ValueRef, t: ty::t, - glue_fn: |@mut Block, v: ValueRef, t: ty::t| - -> @mut Block) - -> @mut Block { + glue_fn: |@Block, v: ValueRef, t: ty::t| + -> @Block) + -> @Block { let _icx = push_ctxt("closure::make_closure_glue"); let bcx = cx; let tcx = cx.tcx(); @@ -447,10 +454,10 @@ pub fn make_closure_glue(cx: @mut Block, } pub fn make_opaque_cbox_drop_glue( - bcx: @mut Block, + bcx: @Block, sigil: ast::Sigil, cboxptr: ValueRef) // ptr to the opaque closure - -> @mut Block { + -> @Block { let _icx = push_ctxt("closure::make_opaque_cbox_drop_glue"); match sigil { ast::BorrowedSigil => bcx, @@ -465,11 +472,11 @@ pub fn make_opaque_cbox_drop_glue( } } -pub fn make_opaque_cbox_free_glue( - bcx: @mut Block, - sigil: ast::Sigil, - cbox: ValueRef) // ptr to ptr to the opaque closure - -> @mut Block { +/// `cbox` is a pointer to a pointer to an opaque closure. +pub fn make_opaque_cbox_free_glue(bcx: @Block, + sigil: ast::Sigil, + cbox: ValueRef) + -> @Block { let _icx = push_ctxt("closure::make_opaque_cbox_free_glue"); match sigil { ast::BorrowedSigil => { diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index e64e44695f3e9..0fadcbe53be09 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -35,6 +35,7 @@ use middle::trans::type_::Type; use std::c_str::ToCStr; use std::cast::transmute; use std::cast; +use std::cell::{Cell, RefCell}; use std::hashmap::HashMap; use std::libc::{c_uint, c_longlong, c_ulonglong, c_char}; use std::vec; @@ -46,7 +47,7 @@ use syntax::{ast, ast_map}; pub use middle::trans::context::CrateContext; -fn type_is_newtype_immediate(ccx: &mut CrateContext, ty: ty::t) -> bool { +fn type_is_newtype_immediate(ccx: &CrateContext, ty: ty::t) -> bool { match ty::get(ty).sty { ty::ty_struct(def_id, ref substs) => { let fields = ty::struct_fields(ccx.tcx, def_id, substs); @@ -58,7 +59,7 @@ fn type_is_newtype_immediate(ccx: &mut CrateContext, ty: ty::t) -> bool { } } -pub fn type_is_immediate(ccx: &mut CrateContext, ty: ty::t) -> bool { +pub fn type_is_immediate(ccx: &CrateContext, ty: ty::t) -> bool { use middle::trans::machine::llsize_of_alloc; use middle::trans::type_of::sizing_type_of; let tcx = ccx.tcx; @@ -92,10 +93,10 @@ pub struct tydesc_info { align: ValueRef, borrow_offset: ValueRef, name: ValueRef, - take_glue: Option, - drop_glue: Option, - free_glue: Option, - visit_glue: Option + take_glue: Cell>, + drop_glue: Cell>, + free_glue: Cell>, + visit_glue: Cell>, } /* @@ -125,18 +126,18 @@ pub struct tydesc_info { */ pub struct Stats { - n_static_tydescs: uint, - n_glues_created: uint, - n_null_glues: uint, - n_real_glues: uint, - n_fns: uint, - n_monos: uint, - n_inlines: uint, - n_closures: uint, - n_llvm_insns: uint, - llvm_insn_ctxt: ~[~str], - llvm_insns: HashMap<~str, uint>, - fn_stats: ~[(~str, uint, uint)] // (ident, time-in-ms, llvm-instructions) + n_static_tydescs: Cell, + n_glues_created: Cell, + n_null_glues: Cell, + n_real_glues: Cell, + n_fns: Cell, + n_monos: Cell, + n_inlines: Cell, + n_closures: Cell, + n_llvm_insns: Cell, + llvm_insns: RefCell>, + // (ident, time-in-ms, llvm-instructions) + fn_stats: RefCell<~[(~str, uint, uint)]>, } pub struct BuilderRef_res { @@ -205,33 +206,33 @@ pub struct FunctionContext { // The implicit environment argument that arrives in the function we're // creating. - llenv: ValueRef, + llenv: Cell, // The place to store the return value. If the return type is immediate, // this is an alloca in the function. Otherwise, it's the hidden first // parameter to the function. After function construction, this should // always be Some. - llretptr: Option, + llretptr: Cell>, - entry_bcx: Option<@mut Block>, + entry_bcx: RefCell>, // These elements: "hoisted basic blocks" containing // administrative activities that have to happen in only one place in // the function, due to LLVM's quirks. // A marker for the place where we want to insert the function's static // allocas, so that LLVM will coalesce them into a single alloca call. - alloca_insert_pt: Option, - llreturn: Option, + alloca_insert_pt: Cell>, + llreturn: Cell>, // The 'self' value currently in use in this function, if there // is one. // // NB: This is the type of the self *variable*, not the self *type*. The // self type is set only for default methods, while the self variable is // set for all methods. - llself: Option, + llself: Cell>, // The a value alloca'd for calls to upcalls.rust_personality. Used when // outputting the resume instruction. - personality: Option, + personality: Cell>, // True if the caller expects this fn to use the out pointer to // return. Either way, your code should write into llretptr, but if @@ -239,12 +240,12 @@ pub struct FunctionContext { caller_expects_out_pointer: bool, // Maps arguments to allocas created for them in llallocas. - llargs: @mut HashMap, + llargs: RefCell>, // Maps the def_ids for local variables to the allocas created for // them in llallocas. - lllocals: @mut HashMap, + lllocals: RefCell>, // Same as above, but for closure upvars - llupvars: @mut HashMap, + llupvars: RefCell>, // The NodeId of the function, or -1 if it doesn't correspond to // a user-defined function. @@ -260,7 +261,7 @@ pub struct FunctionContext { path: path, // This function's enclosing crate context. - ccx: @mut CrateContext, + ccx: @CrateContext, // Used and maintained by the debuginfo module. debug_context: debuginfo::FunctionDebugContext, @@ -288,26 +289,28 @@ impl FunctionContext { } } - pub fn cleanup(&mut self) { + pub fn cleanup(&self) { unsafe { - llvm::LLVMInstructionEraseFromParent(self.alloca_insert_pt.unwrap()); + llvm::LLVMInstructionEraseFromParent(self.alloca_insert_pt + .get() + .unwrap()); } // Remove the cycle between fcx and bcx, so memory can be freed - self.entry_bcx = None; + self.entry_bcx.set(None); } - pub fn get_llreturn(&mut self) -> BasicBlockRef { - if self.llreturn.is_none() { - self.llreturn = Some(base::mk_return_basic_block(self.llfn)); + pub fn get_llreturn(&self) -> BasicBlockRef { + if self.llreturn.get().is_none() { + self.llreturn.set(Some(base::mk_return_basic_block(self.llfn))); } - self.llreturn.unwrap() + self.llreturn.get().unwrap() } } -pub fn warn_not_to_commit(ccx: &mut CrateContext, msg: &str) { - if !ccx.do_not_commit_warning_issued { - ccx.do_not_commit_warning_issued = true; +pub fn warn_not_to_commit(ccx: &CrateContext, msg: &str) { + if !ccx.do_not_commit_warning_issued.get() { + ccx.do_not_commit_warning_issued.set(true); ccx.sess.warn(msg.to_str() + " -- do not commit like this!"); } } @@ -331,7 +334,7 @@ pub enum cleantype { /// A cleanup function: a built-in destructor. pub trait CleanupFunction { - fn clean(&self, block: @mut Block) -> @mut Block; + fn clean(&self, block: @Block) -> @Block; } /// A cleanup function that calls the "drop glue" (destructor function) on @@ -342,7 +345,7 @@ pub struct TypeDroppingCleanupFunction { } impl CleanupFunction for TypeDroppingCleanupFunction { - fn clean(&self, block: @mut Block) -> @mut Block { + fn clean(&self, block: @Block) -> @Block { glue::drop_ty(block, self.val, self.t) } } @@ -355,7 +358,7 @@ pub struct ImmediateTypeDroppingCleanupFunction { } impl CleanupFunction for ImmediateTypeDroppingCleanupFunction { - fn clean(&self, block: @mut Block) -> @mut Block { + fn clean(&self, block: @Block) -> @Block { glue::drop_ty_immediate(block, self.val, self.t) } } @@ -371,7 +374,7 @@ pub struct WriteGuardReleasingCleanupFunction { } impl CleanupFunction for WriteGuardReleasingCleanupFunction { - fn clean(&self, bcx: @mut Block) -> @mut Block { + fn clean(&self, bcx: @Block) -> @Block { write_guard::return_to_mut(bcx, self.root_key, self.frozen_val_ref, @@ -387,7 +390,7 @@ pub struct GCHeapFreeingCleanupFunction { } impl CleanupFunction for GCHeapFreeingCleanupFunction { - fn clean(&self, bcx: @mut Block) -> @mut Block { + fn clean(&self, bcx: @Block) -> @Block { glue::trans_free(bcx, self.ptr) } } @@ -398,7 +401,7 @@ pub struct ExchangeHeapFreeingCleanupFunction { } impl CleanupFunction for ExchangeHeapFreeingCleanupFunction { - fn clean(&self, bcx: @mut Block) -> @mut Block { + fn clean(&self, bcx: @Block) -> @Block { glue::trans_exchange_free(bcx, self.ptr) } } @@ -427,14 +430,21 @@ pub struct cleanup_path { dest: BasicBlockRef } -pub fn shrink_scope_clean(scope_info: &mut ScopeInfo, size: uint) { - scope_info.landing_pad = None; - scope_info.cleanup_paths = scope_info.cleanup_paths.iter() - .take_while(|&cu| cu.size <= size).map(|&x|x).collect(); +pub fn shrink_scope_clean(scope_info: &ScopeInfo, size: uint) { + scope_info.landing_pad.set(None); + let new_cleanup_paths = { + let cleanup_paths = scope_info.cleanup_paths.borrow(); + cleanup_paths.get() + .iter() + .take_while(|&cu| cu.size <= size) + .map(|&x| x) + .collect() + }; + scope_info.cleanup_paths.set(new_cleanup_paths) } -pub fn grow_scope_clean(scope_info: &mut ScopeInfo) { - scope_info.landing_pad = None; +pub fn grow_scope_clean(scope_info: &ScopeInfo) { + scope_info.landing_pad.set(None); } pub fn cleanup_type(cx: ty::ctxt, ty: ty::t) -> cleantype { @@ -445,7 +455,7 @@ pub fn cleanup_type(cx: ty::ctxt, ty: ty::t) -> cleantype { } } -pub fn add_clean(bcx: @mut Block, val: ValueRef, t: ty::t) { +pub fn add_clean(bcx: @Block, val: ValueRef, t: ty::t) { if !ty::type_needs_drop(bcx.tcx(), t) { return } @@ -454,44 +464,50 @@ pub fn add_clean(bcx: @mut Block, val: ValueRef, t: ty::t) { let cleanup_type = cleanup_type(bcx.tcx(), t); in_scope_cx(bcx, None, |scope_info| { - scope_info.cleanups.push(clean(@TypeDroppingCleanupFunction { - val: val, - t: t, - } as @CleanupFunction, - cleanup_type)); + { + let mut cleanups = scope_info.cleanups.borrow_mut(); + cleanups.get().push(clean(@TypeDroppingCleanupFunction { + val: val, + t: t, + } as @CleanupFunction, + cleanup_type)); + } grow_scope_clean(scope_info); }) } -pub fn add_clean_temp_immediate(cx: @mut Block, val: ValueRef, ty: ty::t) { +pub fn add_clean_temp_immediate(cx: @Block, val: ValueRef, ty: ty::t) { if !ty::type_needs_drop(cx.tcx(), ty) { return; } debug!("add_clean_temp_immediate({}, {}, {})", cx.to_str(), cx.val_to_str(val), ty.repr(cx.tcx())); let cleanup_type = cleanup_type(cx.tcx(), ty); in_scope_cx(cx, None, |scope_info| { - scope_info.cleanups.push(clean_temp(val, - @ImmediateTypeDroppingCleanupFunction { - val: val, - t: ty, - } as @CleanupFunction, - cleanup_type)); + { + let mut cleanups = scope_info.cleanups.borrow_mut(); + cleanups.get().push(clean_temp(val, + @ImmediateTypeDroppingCleanupFunction { + val: val, + t: ty, + } as @CleanupFunction, + cleanup_type)); + } grow_scope_clean(scope_info); }) } -pub fn add_clean_temp_mem(bcx: @mut Block, val: ValueRef, t: ty::t) { +pub fn add_clean_temp_mem(bcx: @Block, val: ValueRef, t: ty::t) { add_clean_temp_mem_in_scope_(bcx, None, val, t); } -pub fn add_clean_temp_mem_in_scope(bcx: @mut Block, +pub fn add_clean_temp_mem_in_scope(bcx: @Block, scope_id: ast::NodeId, val: ValueRef, t: ty::t) { add_clean_temp_mem_in_scope_(bcx, Some(scope_id), val, t); } -pub fn add_clean_temp_mem_in_scope_(bcx: @mut Block, scope_id: Option, +pub fn add_clean_temp_mem_in_scope_(bcx: @Block, scope_id: Option, val: ValueRef, t: ty::t) { if !ty::type_needs_drop(bcx.tcx(), t) { return; } debug!("add_clean_temp_mem({}, {}, {})", @@ -499,16 +515,19 @@ pub fn add_clean_temp_mem_in_scope_(bcx: @mut Block, scope_id: Option { @GCHeapFreeingCleanupFunction { @@ -555,9 +577,12 @@ pub fn add_clean_free(cx: @mut Block, ptr: ValueRef, heap: heap) { } }; in_scope_cx(cx, None, |scope_info| { - scope_info.cleanups.push(clean_temp(ptr, - free_fn, - normal_exit_and_unwind)); + { + let mut cleanups = scope_info.cleanups.borrow_mut(); + cleanups.get().push(clean_temp(ptr, + free_fn, + normal_exit_and_unwind)); + } grow_scope_clean(scope_info); }) } @@ -566,50 +591,58 @@ pub fn add_clean_free(cx: @mut Block, ptr: ValueRef, heap: heap) { // to a system where we can also cancel the cleanup on local variables, but // this will be more involved. For now, we simply zero out the local, and the // drop glue checks whether it is zero. -pub fn revoke_clean(cx: @mut Block, val: ValueRef) { +pub fn revoke_clean(cx: @Block, val: ValueRef) { in_scope_cx(cx, None, |scope_info| { - let cleanup_pos = scope_info.cleanups.iter().position( - |cu| match *cu { - clean_temp(v, _, _) if v == val => true, - _ => false - }); + let cleanup_pos = { + let mut cleanups = scope_info.cleanups.borrow_mut(); + cleanups.get().iter().position(|cu| { + match *cu { + clean_temp(v, _, _) if v == val => true, + _ => false + } + }) + }; for i in cleanup_pos.iter() { - scope_info.cleanups = - vec::append(scope_info.cleanups.slice(0u, *i).to_owned(), - scope_info.cleanups.slice(*i + 1u, - scope_info.cleanups.len())); + let new_cleanups = { + let cleanups = scope_info.cleanups.borrow(); + vec::append(cleanups.get().slice(0u, *i).to_owned(), + cleanups.get().slice(*i + 1u, cleanups.get() + .len())) + }; + scope_info.cleanups.set(new_cleanups); shrink_scope_clean(scope_info, *i); } }) } -pub fn block_cleanups(bcx: &mut Block) -> ~[cleanup] { - match bcx.scope { +pub fn block_cleanups(bcx: &Block) -> ~[cleanup] { + match bcx.scope.get() { None => ~[], - Some(inf) => inf.cleanups.clone(), + Some(inf) => inf.cleanups.get(), } } pub struct ScopeInfo { - parent: Option<@mut ScopeInfo>, - loop_break: Option<@mut Block>, + parent: Option<@ScopeInfo>, + loop_break: Option<@Block>, loop_label: Option, // A list of functions that must be run at when leaving this // block, cleaning up any variables that were introduced in the // block. - cleanups: ~[cleanup], + cleanups: RefCell<~[cleanup]>, // Existing cleanup paths that may be reused, indexed by destination and // cleared when the set of cleanups changes. - cleanup_paths: ~[cleanup_path], + cleanup_paths: RefCell<~[cleanup_path]>, // Unwinding landing pad. Also cleared when cleanups change. - landing_pad: Option, + landing_pad: Cell>, // info about the AST node this scope originated from, if any node_info: Option, } impl ScopeInfo { - pub fn empty_cleanups(&mut self) -> bool { - self.cleanups.is_empty() + pub fn empty_cleanups(&self) -> bool { + let cleanups = self.cleanups.borrow(); + cleanups.get().is_empty() } } @@ -657,41 +690,40 @@ pub struct Block { // instructions into that block by way of this block context. // The block pointing to this one in the function's digraph. llbb: BasicBlockRef, - terminated: bool, - unreachable: bool, - parent: Option<@mut Block>, + terminated: Cell, + unreachable: Cell, + parent: Option<@Block>, // The current scope within this basic block - scope: Option<@mut ScopeInfo>, + scope: RefCell>, // Is this block part of a landing pad? is_lpad: bool, // info about the AST node this block originated from, if any node_info: Option, // The function context for the function to which this block is // attached. - fcx: @mut FunctionContext + fcx: @FunctionContext } impl Block { - pub fn new(llbb: BasicBlockRef, - parent: Option<@mut Block>, + parent: Option<@Block>, is_lpad: bool, node_info: Option, - fcx: @mut FunctionContext) - -> Block { + fcx: @FunctionContext) + -> Block { Block { llbb: llbb, - terminated: false, - unreachable: false, + terminated: Cell::new(false), + unreachable: Cell::new(false), parent: parent, - scope: None, + scope: RefCell::new(None), is_lpad: is_lpad, node_info: node_info, fcx: fcx } } - pub fn ccx(&self) -> @mut CrateContext { self.fcx.ccx } + pub fn ccx(&self) -> @CrateContext { self.fcx.ccx } pub fn tcx(&self) -> ty::ctxt { self.fcx.ccx.tcx } pub fn sess(&self) -> Session { self.fcx.ccx.sess } @@ -716,7 +748,8 @@ impl Block { } pub fn def(&self, nid: ast::NodeId) -> ast::Def { - match self.tcx().def_map.find(&nid) { + let def_map = self.tcx().def_map.borrow(); + match def_map.get().find(&nid) { Some(&v) => v, None => { self.tcx().sess.bug(format!( @@ -748,16 +781,16 @@ impl Block { } pub struct Result { - bcx: @mut Block, + bcx: @Block, val: ValueRef } -pub fn rslt(bcx: @mut Block, val: ValueRef) -> Result { +pub fn rslt(bcx: @Block, val: ValueRef) -> Result { Result {bcx: bcx, val: val} } impl Result { - pub fn unpack(&self, bcx: &mut @mut Block) -> ValueRef { + pub fn unpack(&self, bcx: &mut @Block) -> ValueRef { *bcx = self.bcx; return self.val; } @@ -769,11 +802,11 @@ pub fn val_ty(v: ValueRef) -> Type { } } -pub fn in_scope_cx(cx: @mut Block, +pub fn in_scope_cx(cx: @Block, scope_id: Option, - f: |si: &mut ScopeInfo|) { + f: |si: &ScopeInfo|) { let mut cur = cx; - let mut cur_scope = cur.scope; + let mut cur_scope = cur.scope.get(); loop { cur_scope = match cur_scope { Some(inf) => match scope_id { @@ -795,13 +828,13 @@ pub fn in_scope_cx(cx: @mut Block, }, None => { cur = block_parent(cur); - cur.scope + cur.scope.get() } } } } -pub fn block_parent(cx: @mut Block) -> @mut Block { +pub fn block_parent(cx: @Block) -> @Block { match cx.parent { Some(b) => b, None => cx.sess().bug(format!("block_parent called on root block {:?}", @@ -887,11 +920,14 @@ pub fn C_u8(i: uint) -> ValueRef { // This is a 'c-like' raw string, which differs from // our boxed-and-length-annotated strings. -pub fn C_cstr(cx: &mut CrateContext, s: @str) -> ValueRef { +pub fn C_cstr(cx: &CrateContext, s: @str) -> ValueRef { unsafe { - match cx.const_cstr_cache.find_equiv(&s) { - Some(&llval) => return llval, - None => () + { + let const_cstr_cache = cx.const_cstr_cache.borrow(); + match const_cstr_cache.get().find_equiv(&s) { + Some(&llval) => return llval, + None => () + } } let sc = llvm::LLVMConstStringInContext(cx.llcx, @@ -906,15 +942,15 @@ pub fn C_cstr(cx: &mut CrateContext, s: @str) -> ValueRef { llvm::LLVMSetGlobalConstant(g, True); lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage); - cx.const_cstr_cache.insert(s, g); - - return g; + let mut const_cstr_cache = cx.const_cstr_cache.borrow_mut(); + const_cstr_cache.get().insert(s, g); + g } } // NB: Do not use `do_spill_noroot` to make this into a constant string, or // you will be kicked off fast isel. See issue #4352 for an example of this. -pub fn C_estr_slice(cx: &mut CrateContext, s: @str) -> ValueRef { +pub fn C_estr_slice(cx: &CrateContext, s: @str) -> ValueRef { unsafe { let len = s.len(); let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), Type::i8p().to_ref()); @@ -922,7 +958,7 @@ pub fn C_estr_slice(cx: &mut CrateContext, s: @str) -> ValueRef { } } -pub fn C_binary_slice(cx: &mut CrateContext, data: &[u8]) -> ValueRef { +pub fn C_binary_slice(cx: &CrateContext, data: &[u8]) -> ValueRef { unsafe { let len = data.len(); let lldata = C_bytes(data); @@ -1070,17 +1106,17 @@ pub struct mono_id_ { pub type mono_id = @mono_id_; -pub fn umax(cx: @mut Block, a: ValueRef, b: ValueRef) -> ValueRef { +pub fn umax(cx: @Block, a: ValueRef, b: ValueRef) -> ValueRef { let cond = build::ICmp(cx, lib::llvm::IntULT, a, b); return build::Select(cx, cond, b, a); } -pub fn umin(cx: @mut Block, a: ValueRef, b: ValueRef) -> ValueRef { +pub fn umin(cx: @Block, a: ValueRef, b: ValueRef) -> ValueRef { let cond = build::ICmp(cx, lib::llvm::IntULT, a, b); return build::Select(cx, cond, a, b); } -pub fn align_to(cx: @mut Block, off: ValueRef, align: ValueRef) -> ValueRef { +pub fn align_to(cx: @Block, off: ValueRef, align: ValueRef) -> ValueRef { let mask = build::Sub(cx, align, C_int(cx.ccx(), 1)); let bumped = build::Add(cx, off, mask); return build::And(cx, bumped, build::Not(cx, mask)); @@ -1105,7 +1141,7 @@ pub fn path_str(sess: session::Session, p: &[path_elt]) -> ~str { r } -pub fn monomorphize_type(bcx: &mut Block, t: ty::t) -> ty::t { +pub fn monomorphize_type(bcx: &Block, t: ty::t) -> ty::t { match bcx.fcx.param_substs { Some(substs) => { ty::subst_tps(bcx.tcx(), substs.tys, substs.self_ty, t) @@ -1118,23 +1154,23 @@ pub fn monomorphize_type(bcx: &mut Block, t: ty::t) -> ty::t { } } -pub fn node_id_type(bcx: &mut Block, id: ast::NodeId) -> ty::t { +pub fn node_id_type(bcx: &Block, id: ast::NodeId) -> ty::t { let tcx = bcx.tcx(); let t = ty::node_id_to_type(tcx, id); monomorphize_type(bcx, t) } -pub fn expr_ty(bcx: &mut Block, ex: &ast::Expr) -> ty::t { +pub fn expr_ty(bcx: &Block, ex: &ast::Expr) -> ty::t { node_id_type(bcx, ex.id) } -pub fn expr_ty_adjusted(bcx: &mut Block, ex: &ast::Expr) -> ty::t { +pub fn expr_ty_adjusted(bcx: &Block, ex: &ast::Expr) -> ty::t { let tcx = bcx.tcx(); let t = ty::expr_ty_adjusted(tcx, ex); monomorphize_type(bcx, t) } -pub fn node_id_type_params(bcx: &mut Block, id: ast::NodeId) -> ~[ty::t] { +pub fn node_id_type_params(bcx: &Block, id: ast::NodeId) -> ~[ty::t] { let tcx = bcx.tcx(); let params = ty::node_id_to_type_params(tcx, id); @@ -1154,9 +1190,10 @@ pub fn node_id_type_params(bcx: &mut Block, id: ast::NodeId) -> ~[ty::t] { } } -pub fn node_vtables(bcx: @mut Block, id: ast::NodeId) +pub fn node_vtables(bcx: @Block, id: ast::NodeId) -> Option { - let raw_vtables = bcx.ccx().maps.vtable_map.find(&id); + let vtable_map = bcx.ccx().maps.vtable_map.borrow(); + let raw_vtables = vtable_map.get().find(&id); raw_vtables.map(|vts| resolve_vtables_in_fn_ctxt(bcx.fcx, *vts)) } @@ -1254,7 +1291,7 @@ pub fn dummy_substs(tps: ~[ty::t]) -> ty::substs { } } -pub fn filename_and_line_num_from_span(bcx: @mut Block, +pub fn filename_and_line_num_from_span(bcx: @Block, span: Span) -> (ValueRef, ValueRef) { let loc = bcx.sess().parse_sess.cm.lookup_char_pos(span.lo); let filename_cstr = C_cstr(bcx.ccx(), loc.file.name); @@ -1264,11 +1301,11 @@ pub fn filename_and_line_num_from_span(bcx: @mut Block, } // Casts a Rust bool value to an i1. -pub fn bool_to_i1(bcx: @mut Block, llval: ValueRef) -> ValueRef { +pub fn bool_to_i1(bcx: @Block, llval: ValueRef) -> ValueRef { build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(false)) } -pub fn langcall(bcx: @mut Block, span: Option, msg: &str, +pub fn langcall(bcx: @Block, span: Option, msg: &str, li: LangItem) -> ast::DefId { match bcx.tcx().lang_items.require(li) { Ok(id) => id, diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 9a9f343744c95..19dc19262c022 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -35,7 +35,7 @@ use std::libc::c_uint; use std::vec; use syntax::{ast, ast_util, ast_map}; -pub fn const_lit(cx: &mut CrateContext, e: &ast::Expr, lit: ast::lit) +pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: ast::lit) -> ValueRef { let _icx = push_ctxt("trans_lit"); match lit.node { @@ -76,15 +76,16 @@ pub fn const_lit(cx: &mut CrateContext, e: &ast::Expr, lit: ast::lit) } } -pub fn const_ptrcast(cx: &mut CrateContext, a: ValueRef, t: Type) -> ValueRef { +pub fn const_ptrcast(cx: &CrateContext, a: ValueRef, t: Type) -> ValueRef { unsafe { let b = llvm::LLVMConstPointerCast(a, t.ptr_to().to_ref()); - assert!(cx.const_globals.insert(b as int, a)); + let mut const_globals = cx.const_globals.borrow_mut(); + assert!(const_globals.get().insert(b as int, a)); b } } -fn const_vec(cx: @mut CrateContext, e: &ast::Expr, es: &[@ast::Expr]) -> (ValueRef, Type, bool) { +fn const_vec(cx: @CrateContext, e: &ast::Expr, es: &[@ast::Expr]) -> (ValueRef, Type, bool) { let vec_ty = ty::expr_ty(cx.tcx, e); let unit_ty = ty::sequence_element_type(cx.tcx, vec_ty); let llunitty = type_of::type_of(cx, unit_ty); @@ -98,7 +99,7 @@ fn const_vec(cx: @mut CrateContext, e: &ast::Expr, es: &[@ast::Expr]) -> (ValueR (v, llunitty, inlineable.iter().fold(true, |a, &b| a && b)) } -fn const_addr_of(cx: &mut CrateContext, cv: ValueRef) -> ValueRef { +fn const_addr_of(cx: &CrateContext, cv: ValueRef) -> ValueRef { unsafe { let gv = "const".with_c_str(|name| { llvm::LLVMAddGlobal(cx.llmod, val_ty(cv).to_ref(), name) @@ -110,8 +111,9 @@ fn const_addr_of(cx: &mut CrateContext, cv: ValueRef) -> ValueRef { } } -fn const_deref_ptr(cx: &mut CrateContext, v: ValueRef) -> ValueRef { - let v = match cx.const_globals.find(&(v as int)) { +fn const_deref_ptr(cx: &CrateContext, v: ValueRef) -> ValueRef { + let const_globals = cx.const_globals.borrow(); + let v = match const_globals.get().find(&(v as int)) { Some(&v) => v, None => v }; @@ -121,13 +123,13 @@ fn const_deref_ptr(cx: &mut CrateContext, v: ValueRef) -> ValueRef { } } -fn const_deref_newtype(cx: &mut CrateContext, v: ValueRef, t: ty::t) +fn const_deref_newtype(cx: &CrateContext, v: ValueRef, t: ty::t) -> ValueRef { let repr = adt::represent_type(cx, t); adt::const_get_field(cx, repr, v, 0, 0) } -fn const_deref(cx: &mut CrateContext, v: ValueRef, t: ty::t, explicit: bool) +fn const_deref(cx: &CrateContext, v: ValueRef, t: ty::t, explicit: bool) -> (ValueRef, ty::t) { match ty::deref(cx.tcx, t, explicit) { Some(ref mt) => { @@ -153,9 +155,12 @@ fn const_deref(cx: &mut CrateContext, v: ValueRef, t: ty::t, explicit: bool) } } -pub fn get_const_val(cx: @mut CrateContext, +pub fn get_const_val(cx: @CrateContext, mut def_id: ast::DefId) -> (ValueRef, bool) { - let contains_key = cx.const_values.contains_key(&def_id.node); + let contains_key = { + let const_values = cx.const_values.borrow(); + const_values.get().contains_key(&def_id.node) + }; if !ast_util::is_local(def_id) || !contains_key { if !ast_util::is_local(def_id) { def_id = inline::maybe_instantiate_inline(cx, def_id); @@ -169,16 +174,22 @@ pub fn get_const_val(cx: @mut CrateContext, _ => cx.tcx.sess.bug("expected a const to be an item") } } - (cx.const_values.get_copy(&def_id.node), - !cx.non_inlineable_statics.contains(&def_id.node)) + + let const_values = cx.const_values.borrow(); + let non_inlineable_statics = cx.non_inlineable_statics.borrow(); + (const_values.get().get_copy(&def_id.node), + !non_inlineable_statics.get().contains(&def_id.node)) } -pub fn const_expr(cx: @mut CrateContext, e: &ast::Expr) -> (ValueRef, bool) { +pub fn const_expr(cx: @CrateContext, e: &ast::Expr) -> (ValueRef, bool) { let (llconst, inlineable) = const_expr_unadjusted(cx, e); let mut llconst = llconst; let mut inlineable = inlineable; let ety = ty::expr_ty(cx.tcx, e); - let adjustment = cx.tcx.adjustments.find_copy(&e.id); + let adjustment = { + let adjustments = cx.tcx.adjustments.borrow(); + adjustments.get().find_copy(&e.id) + }; match adjustment { None => { } Some(@ty::AutoAddEnv(ty::ReStatic, ast::BorrowedSigil)) => { @@ -257,9 +268,9 @@ pub fn const_expr(cx: @mut CrateContext, e: &ast::Expr) -> (ValueRef, bool) { // the bool returned is whether this expression can be inlined into other crates // if it's assigned to a static. -fn const_expr_unadjusted(cx: @mut CrateContext, +fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr) -> (ValueRef, bool) { - fn map_list(cx: @mut CrateContext, + fn map_list(cx: @CrateContext, exprs: &[@ast::Expr]) -> (~[ValueRef], bool) { exprs.iter().map(|&e| const_expr(cx, e)) .fold((~[], true), |(L, all_inlineable), (val, inlineable)| { @@ -574,8 +585,12 @@ fn const_expr_unadjusted(cx: @mut CrateContext, assert!(pth.segments.iter().all(|seg| seg.types.is_empty())); let tcx = cx.tcx; - match tcx.def_map.find(&e.id) { - Some(&ast::DefFn(def_id, _purity)) => { + let opt_def = { + let def_map = tcx.def_map.borrow(); + def_map.get().find_copy(&e.id) + }; + match opt_def { + Some(ast::DefFn(def_id, _purity)) => { if !ast_util::is_local(def_id) { let ty = csearch::get_type(cx.tcx, def_id).ty; (base::trans_external_path(cx, def_id, ty), true) @@ -584,10 +599,10 @@ fn const_expr_unadjusted(cx: @mut CrateContext, (base::get_item_val(cx, def_id.node), true) } } - Some(&ast::DefStatic(def_id, false)) => { + Some(ast::DefStatic(def_id, false)) => { get_const_val(cx, def_id) } - Some(&ast::DefVariant(enum_did, variant_did, _)) => { + Some(ast::DefVariant(enum_did, variant_did, _)) => { let ety = ty::expr_ty(cx.tcx, e); let repr = adt::represent_type(cx, ety); let vinfo = ty::enum_variant_with_id(cx.tcx, @@ -595,7 +610,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, variant_did); (adt::trans_const(cx, repr, vinfo.disr_val, []), true) } - Some(&ast::DefStruct(_)) => { + Some(ast::DefStruct(_)) => { let ety = ty::expr_ty(cx.tcx, e); let llty = type_of::type_of(cx, ety); (C_null(llty), true) @@ -607,14 +622,18 @@ fn const_expr_unadjusted(cx: @mut CrateContext, } ast::ExprCall(callee, ref args, _) => { let tcx = cx.tcx; - match tcx.def_map.find(&callee.id) { - Some(&ast::DefStruct(_)) => { + let opt_def = { + let def_map = tcx.def_map.borrow(); + def_map.get().find_copy(&callee.id) + }; + match opt_def { + Some(ast::DefStruct(_)) => { let ety = ty::expr_ty(cx.tcx, e); let repr = adt::represent_type(cx, ety); let (arg_vals, inlineable) = map_list(cx, *args); (adt::trans_const(cx, repr, 0, arg_vals), inlineable) } - Some(&ast::DefVariant(enum_did, variant_did, _)) => { + Some(ast::DefVariant(enum_did, variant_did, _)) => { let ety = ty::expr_ty(cx.tcx, e); let repr = adt::represent_type(cx, ety); let vinfo = ty::enum_variant_with_id(cx.tcx, @@ -634,13 +653,14 @@ fn const_expr_unadjusted(cx: @mut CrateContext, } } -pub fn trans_const(ccx: @mut CrateContext, m: ast::Mutability, id: ast::NodeId) { +pub fn trans_const(ccx: @CrateContext, m: ast::Mutability, id: ast::NodeId) { unsafe { let _icx = push_ctxt("trans_const"); let g = base::get_item_val(ccx, id); // At this point, get_item_val has already translated the // constant's initializer to determine its LLVM type. - let v = ccx.const_values.get_copy(&id); + let const_values = ccx.const_values.borrow(); + let v = const_values.get().get_copy(&id); llvm::LLVMSetInitializer(g, v); if m != ast::MutMutable { llvm::LLVMSetGlobalConstant(g, True); diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index aca267023c7e9..dbdadb46f4921 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -27,6 +27,7 @@ use middle::trans::type_::Type; use util::sha2::Sha256; +use std::cell::{Cell, RefCell}; use std::c_str::ToCStr; use std::hashmap::{HashMap, HashSet}; use std::local_data; @@ -44,36 +45,33 @@ pub struct CrateContext { metadata_llmod: ModuleRef, td: TargetData, tn: TypeNames, - externs: ExternMap, + externs: RefCell, intrinsics: HashMap<&'static str, ValueRef>, - item_vals: HashMap, + item_vals: RefCell>, exp_map2: resolve::ExportMap2, - reachable: @mut HashSet, - item_symbols: HashMap, + reachable: @RefCell>, + item_symbols: RefCell>, link_meta: LinkMeta, - enum_sizes: HashMap, - discrims: HashMap, - discrim_symbols: HashMap, - tydescs: HashMap, + tydescs: RefCell>, // Set when running emit_tydescs to enforce that no more tydescs are // created. - finished_tydescs: bool, + finished_tydescs: Cell, // Track mapping of external ids to local items imported for inlining - external: HashMap>, + external: RefCell>>, // Backwards version of the `external` map (inlined items to where they // came from) - external_srcs: HashMap, + external_srcs: RefCell>, // A set of static items which cannot be inlined into other crates. This // will pevent in ii_item() structures from being encoded into the metadata // that is generated - non_inlineable_statics: HashSet, + non_inlineable_statics: RefCell>, // Cache instances of monomorphized functions - monomorphized: HashMap, - monomorphizing: HashMap, + monomorphized: RefCell>, + monomorphizing: RefCell>, // Cache generated vtables - vtables: HashMap<(ty::t, mono_id), ValueRef>, + vtables: RefCell>, // Cache of constant strings, - const_cstr_cache: HashMap<@str, ValueRef>, + const_cstr_cache: RefCell>, // Reverse-direction for const ptrs cast from globals. // Key is an int, cast from a ValueRef holding a *T, @@ -83,27 +81,26 @@ pub struct CrateContext { // when we ptrcast, and we have to ptrcast during translation // of a [T] const because we form a slice, a [*T,int] pair, not // a pointer to an LLVM array type. - const_globals: HashMap, + const_globals: RefCell>, // Cache of emitted const values - const_values: HashMap, + const_values: RefCell>, // Cache of external const values - extern_const_values: HashMap, + extern_const_values: RefCell>, - impl_method_cache: HashMap<(ast::DefId, ast::Name), ast::DefId>, + impl_method_cache: RefCell>, - module_data: HashMap<~str, ValueRef>, - lltypes: HashMap, - llsizingtypes: HashMap, - adt_reprs: HashMap, - symbol_hasher: Sha256, - type_hashcodes: HashMap, - type_short_names: HashMap, - all_llvm_symbols: HashSet<@str>, + module_data: RefCell>, + lltypes: RefCell>, + llsizingtypes: RefCell>, + adt_reprs: RefCell>, + symbol_hasher: RefCell, + type_hashcodes: RefCell>, + all_llvm_symbols: RefCell>, tcx: ty::ctxt, maps: astencode::Maps, - stats: @mut Stats, + stats: @Stats, tydesc_type: Type, int_type: Type, opaque_vec_type: Type, @@ -115,7 +112,7 @@ pub struct CrateContext { // is not emitted by LLVM's GC pass when no functions use GC. uses_gc: bool, dbg_cx: Option, - do_not_commit_warning_issued: bool + do_not_commit_warning_issued: Cell, } impl CrateContext { @@ -126,7 +123,7 @@ impl CrateContext { maps: astencode::Maps, symbol_hasher: Sha256, link_meta: LinkMeta, - reachable: @mut HashSet) + reachable: @RefCell>) -> CrateContext { unsafe { let llcx = llvm::LLVMContextCreate(); @@ -150,7 +147,7 @@ impl CrateContext { let targ_cfg = sess.targ_cfg; let td = mk_target_data(sess.targ_cfg.target_strs.data_layout); - let mut tn = TypeNames::new(); + let tn = TypeNames::new(); let mut intrinsics = base::declare_intrinsics(llmod); if sess.opts.extra_debuginfo { @@ -184,52 +181,47 @@ impl CrateContext { metadata_llmod: metadata_llmod, td: td, tn: tn, - externs: HashMap::new(), + externs: RefCell::new(HashMap::new()), intrinsics: intrinsics, - item_vals: HashMap::new(), + item_vals: RefCell::new(HashMap::new()), exp_map2: emap2, reachable: reachable, - item_symbols: HashMap::new(), + item_symbols: RefCell::new(HashMap::new()), link_meta: link_meta, - enum_sizes: HashMap::new(), - discrims: HashMap::new(), - discrim_symbols: HashMap::new(), - tydescs: HashMap::new(), - finished_tydescs: false, - external: HashMap::new(), - external_srcs: HashMap::new(), - non_inlineable_statics: HashSet::new(), - monomorphized: HashMap::new(), - monomorphizing: HashMap::new(), - vtables: HashMap::new(), - const_cstr_cache: HashMap::new(), - const_globals: HashMap::new(), - const_values: HashMap::new(), - extern_const_values: HashMap::new(), - impl_method_cache: HashMap::new(), - module_data: HashMap::new(), - lltypes: HashMap::new(), - llsizingtypes: HashMap::new(), - adt_reprs: HashMap::new(), - symbol_hasher: symbol_hasher, - type_hashcodes: HashMap::new(), - type_short_names: HashMap::new(), - all_llvm_symbols: HashSet::new(), + tydescs: RefCell::new(HashMap::new()), + finished_tydescs: Cell::new(false), + external: RefCell::new(HashMap::new()), + external_srcs: RefCell::new(HashMap::new()), + non_inlineable_statics: RefCell::new(HashSet::new()), + monomorphized: RefCell::new(HashMap::new()), + monomorphizing: RefCell::new(HashMap::new()), + vtables: RefCell::new(HashMap::new()), + const_cstr_cache: RefCell::new(HashMap::new()), + const_globals: RefCell::new(HashMap::new()), + const_values: RefCell::new(HashMap::new()), + extern_const_values: RefCell::new(HashMap::new()), + impl_method_cache: RefCell::new(HashMap::new()), + module_data: RefCell::new(HashMap::new()), + lltypes: RefCell::new(HashMap::new()), + llsizingtypes: RefCell::new(HashMap::new()), + adt_reprs: RefCell::new(HashMap::new()), + symbol_hasher: RefCell::new(symbol_hasher), + type_hashcodes: RefCell::new(HashMap::new()), + all_llvm_symbols: RefCell::new(HashSet::new()), tcx: tcx, maps: maps, - stats: @mut Stats { - n_static_tydescs: 0u, - n_glues_created: 0u, - n_null_glues: 0u, - n_real_glues: 0u, - n_fns: 0u, - n_monos: 0u, - n_inlines: 0u, - n_closures: 0u, - n_llvm_insns: 0u, - llvm_insn_ctxt: ~[], - llvm_insns: HashMap::new(), - fn_stats: ~[] + stats: @Stats { + n_static_tydescs: Cell::new(0u), + n_glues_created: Cell::new(0u), + n_null_glues: Cell::new(0u), + n_real_glues: Cell::new(0u), + n_fns: Cell::new(0u), + n_monos: Cell::new(0u), + n_inlines: Cell::new(0u), + n_closures: Cell::new(0u), + n_llvm_insns: Cell::new(0u), + llvm_insns: RefCell::new(HashMap::new()), + fn_stats: RefCell::new(~[]), }, tydesc_type: tydesc_type, int_type: int_type, @@ -239,12 +231,12 @@ impl CrateContext { crate_map_name: crate_map_name, uses_gc: false, dbg_cx: dbg_cx, - do_not_commit_warning_issued: false + do_not_commit_warning_issued: Cell::new(false), } } } - pub fn builder(@mut self) -> Builder { + pub fn builder(@self) -> Builder { Builder::new(self) } diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index 240ab9d213003..0770e52f90a3d 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -28,7 +28,7 @@ use syntax::ast_util; use syntax::codemap::Span; use syntax::visit::Visitor; -pub fn trans_block(bcx: @mut Block, b: &ast::Block, dest: expr::Dest) -> @mut Block { +pub fn trans_block(bcx: @Block, b: &ast::Block, dest: expr::Dest) -> @Block { let _icx = push_ctxt("trans_block"); let mut bcx = bcx; for s in b.stmts.iter() { @@ -39,18 +39,18 @@ pub fn trans_block(bcx: @mut Block, b: &ast::Block, dest: expr::Dest) -> @mut Bl bcx = expr::trans_into(bcx, e, dest); } None => { - assert!(dest == expr::Ignore || bcx.unreachable); + assert!(dest == expr::Ignore || bcx.unreachable.get()); } } return bcx; } -pub fn trans_if(bcx: @mut Block, +pub fn trans_if(bcx: @Block, cond: &ast::Expr, thn: ast::P, els: Option<@ast::Expr>, dest: expr::Dest) - -> @mut Block { + -> @Block { debug!("trans_if(bcx={}, cond={}, thn={:?}, dest={})", bcx.to_str(), bcx.expr_to_str(cond), thn.id, dest.to_str(bcx.ccx())); @@ -137,8 +137,8 @@ pub fn trans_if(bcx: @mut Block, return next_bcx; // trans `else [ if { .. } ... | { .. } ]` - fn trans_if_else(else_bcx_in: @mut Block, elexpr: @ast::Expr, - dest: expr::Dest, cleanup: bool) -> @mut Block { + fn trans_if_else(else_bcx_in: @Block, elexpr: @ast::Expr, + dest: expr::Dest, cleanup: bool) -> @Block { let else_bcx_out = match elexpr.node { ast::ExprIf(_, _, _) => { let elseif_blk = ast_util::block_from_expr(elexpr); @@ -159,11 +159,11 @@ pub fn trans_if(bcx: @mut Block, } } -pub fn join_blocks(parent_bcx: @mut Block, in_cxs: &[@mut Block]) -> @mut Block { +pub fn join_blocks(parent_bcx: @Block, in_cxs: &[@Block]) -> @Block { let out = sub_block(parent_bcx, "join"); let mut reachable = false; for bcx in in_cxs.iter() { - if !bcx.unreachable { + if !bcx.unreachable.get() { Br(*bcx, out.llbb); reachable = true; } @@ -174,7 +174,7 @@ pub fn join_blocks(parent_bcx: @mut Block, in_cxs: &[@mut Block]) -> @mut Block return out; } -pub fn trans_while(bcx: @mut Block, cond: &ast::Expr, body: &ast::Block) -> @mut Block { +pub fn trans_while(bcx: @Block, cond: &ast::Expr, body: &ast::Block) -> @Block { let _icx = push_ctxt("trans_while"); let next_bcx = sub_block(bcx, "while next"); @@ -213,10 +213,10 @@ pub fn trans_while(bcx: @mut Block, cond: &ast::Expr, body: &ast::Block) -> @mut return next_bcx; } -pub fn trans_loop(bcx:@mut Block, +pub fn trans_loop(bcx:@Block, body: &ast::Block, opt_label: Option) - -> @mut Block { + -> @Block { let _icx = push_ctxt("trans_loop"); let next_bcx = sub_block(bcx, "next"); let body_bcx_in = loop_scope_block(bcx, next_bcx, opt_label, "`loop`", @@ -227,14 +227,14 @@ pub fn trans_loop(bcx:@mut Block, return next_bcx; } -pub fn trans_break_cont(bcx: @mut Block, +pub fn trans_break_cont(bcx: @Block, opt_label: Option, to_end: bool) - -> @mut Block { + -> @Block { let _icx = push_ctxt("trans_break_cont"); // Locate closest loop block, outputting cleanup as we go. let mut unwind = bcx; - let mut cur_scope = unwind.scope; + let mut cur_scope = unwind.scope.get(); let mut target; loop { cur_scope = match cur_scope { @@ -266,13 +266,15 @@ pub fn trans_break_cont(bcx: @mut Block, Some(bcx) => bcx, // This is a return from a loop body block None => { - Store(bcx, C_bool(!to_end), bcx.fcx.llretptr.unwrap()); + Store(bcx, + C_bool(!to_end), + bcx.fcx.llretptr.get().unwrap()); cleanup_and_leave(bcx, None, Some(bcx.fcx.get_llreturn())); Unreachable(bcx); return bcx; } }; - unwind.scope + unwind.scope.get() } } } @@ -281,18 +283,18 @@ pub fn trans_break_cont(bcx: @mut Block, return bcx; } -pub fn trans_break(bcx: @mut Block, label_opt: Option) -> @mut Block { +pub fn trans_break(bcx: @Block, label_opt: Option) -> @Block { return trans_break_cont(bcx, label_opt, true); } -pub fn trans_cont(bcx: @mut Block, label_opt: Option) -> @mut Block { +pub fn trans_cont(bcx: @Block, label_opt: Option) -> @Block { return trans_break_cont(bcx, label_opt, false); } -pub fn trans_ret(bcx: @mut Block, e: Option<@ast::Expr>) -> @mut Block { +pub fn trans_ret(bcx: @Block, e: Option<@ast::Expr>) -> @Block { let _icx = push_ctxt("trans_ret"); let mut bcx = bcx; - let dest = match bcx.fcx.llretptr { + let dest = match bcx.fcx.llretptr.get() { None => expr::Ignore, Some(retptr) => expr::SaveIn(retptr), }; @@ -307,10 +309,10 @@ pub fn trans_ret(bcx: @mut Block, e: Option<@ast::Expr>) -> @mut Block { return bcx; } -pub fn trans_fail_expr(bcx: @mut Block, +pub fn trans_fail_expr(bcx: @Block, sp_opt: Option, fail_expr: Option<@ast::Expr>) - -> @mut Block { + -> @Block { let _icx = push_ctxt("trans_fail_expr"); let mut bcx = bcx; match fail_expr { @@ -323,7 +325,7 @@ pub fn trans_fail_expr(bcx: @mut Block, if ty::type_is_str(arg_datum.ty) { let (lldata, _) = arg_datum.get_vec_base_and_len_no_root(bcx); return trans_fail_value(bcx, sp_opt, lldata); - } else if bcx.unreachable || ty::type_is_bot(arg_datum.ty) { + } else if bcx.unreachable.get() || ty::type_is_bot(arg_datum.ty) { return bcx; } else { bcx.sess().span_bug( @@ -335,19 +337,19 @@ pub fn trans_fail_expr(bcx: @mut Block, } } -pub fn trans_fail(bcx: @mut Block, +pub fn trans_fail(bcx: @Block, sp_opt: Option, fail_str: @str) - -> @mut Block { + -> @Block { let _icx = push_ctxt("trans_fail"); let V_fail_str = C_cstr(bcx.ccx(), fail_str); return trans_fail_value(bcx, sp_opt, V_fail_str); } -fn trans_fail_value(bcx: @mut Block, +fn trans_fail_value(bcx: @Block, sp_opt: Option, V_fail_str: ValueRef) - -> @mut Block { + -> @Block { let _icx = push_ctxt("trans_fail_value"); let ccx = bcx.ccx(); let (V_filename, V_line) = match sp_opt { @@ -370,8 +372,8 @@ fn trans_fail_value(bcx: @mut Block, return bcx; } -pub fn trans_fail_bounds_check(bcx: @mut Block, sp: Span, - index: ValueRef, len: ValueRef) -> @mut Block { +pub fn trans_fail_bounds_check(bcx: @Block, sp: Span, + index: ValueRef, len: ValueRef) -> @Block { let _icx = push_ctxt("trans_fail_bounds_check"); let (filename, line) = filename_and_line_num_from_span(bcx, sp); let args = ~[filename, line, index, len]; diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index 4fd6e08c8b584..6b8ff815a8360 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -128,7 +128,7 @@ pub struct Datum { } pub struct DatumBlock { - bcx: @mut Block, + bcx: @Block, datum: Datum, } @@ -165,14 +165,14 @@ pub fn immediate_rvalue(val: ValueRef, ty: ty::t) -> Datum { return Datum {val: val, ty: ty, mode: ByValue}; } -pub fn immediate_rvalue_bcx(bcx: @mut Block, +pub fn immediate_rvalue_bcx(bcx: @Block, val: ValueRef, ty: ty::t) -> DatumBlock { return DatumBlock {bcx: bcx, datum: immediate_rvalue(val, ty)}; } -pub fn scratch_datum(bcx: @mut Block, ty: ty::t, name: &str, zero: bool) -> Datum { +pub fn scratch_datum(bcx: @Block, ty: ty::t, name: &str, zero: bool) -> Datum { /*! * Allocates temporary space on the stack using alloca() and * returns a by-ref Datum pointing to it. If `zero` is true, the @@ -188,7 +188,7 @@ pub fn scratch_datum(bcx: @mut Block, ty: ty::t, name: &str, zero: bool) -> Datu Datum { val: scratch, ty: ty, mode: ByRef(RevokeClean) } } -pub fn appropriate_mode(ccx: &mut CrateContext, ty: ty::t) -> DatumMode { +pub fn appropriate_mode(ccx: &CrateContext, ty: ty::t) -> DatumMode { /*! * Indicates the "appropriate" mode for this value, * which is either by ref or by value, depending @@ -206,10 +206,10 @@ pub fn appropriate_mode(ccx: &mut CrateContext, ty: ty::t) -> DatumMode { impl Datum { pub fn store_to(&self, - bcx: @mut Block, + bcx: @Block, action: CopyAction, dst: ValueRef) - -> @mut Block { + -> @Block { /*! * * Stores this value into its final home. This moves if @@ -224,9 +224,9 @@ impl Datum { } pub fn store_to_dest(&self, - bcx: @mut Block, + bcx: @Block, dest: expr::Dest) - -> @mut Block { + -> @Block { match dest { expr::Ignore => { return bcx; @@ -238,30 +238,30 @@ impl Datum { } pub fn store_to_datum(&self, - bcx: @mut Block, + bcx: @Block, action: CopyAction, datum: Datum) - -> @mut Block { + -> @Block { debug!("store_to_datum(self={}, action={:?}, datum={})", self.to_str(bcx.ccx()), action, datum.to_str(bcx.ccx())); assert!(datum.mode.is_by_ref()); self.store_to(bcx, action, datum.val) } - pub fn move_to_datum(&self, bcx: @mut Block, action: CopyAction, datum: Datum) - -> @mut Block { + pub fn move_to_datum(&self, bcx: @Block, action: CopyAction, datum: Datum) + -> @Block { assert!(datum.mode.is_by_ref()); self.move_to(bcx, action, datum.val) } - pub fn copy_to_datum(&self, bcx: @mut Block, action: CopyAction, datum: Datum) - -> @mut Block { + pub fn copy_to_datum(&self, bcx: @Block, action: CopyAction, datum: Datum) + -> @Block { assert!(datum.mode.is_by_ref()); self.copy_to(bcx, action, datum.val) } - pub fn copy_to(&self, bcx: @mut Block, action: CopyAction, dst: ValueRef) - -> @mut Block { + pub fn copy_to(&self, bcx: @Block, action: CopyAction, dst: ValueRef) + -> @Block { /*! * * Copies the value into `dst`, which should be a pointer to a @@ -304,10 +304,10 @@ impl Datum { } pub fn copy_to_no_check(&self, - bcx: @mut Block, + bcx: @Block, action: CopyAction, dst: ValueRef) - -> @mut Block { + -> @Block { /*! * * A helper for `copy_to()` which does not check to see if we @@ -335,8 +335,8 @@ impl Datum { // This works like copy_val, except that it deinitializes the source. // Since it needs to zero out the source, src also needs to be an lval. // - pub fn move_to(&self, bcx: @mut Block, action: CopyAction, dst: ValueRef) - -> @mut Block { + pub fn move_to(&self, bcx: @Block, action: CopyAction, dst: ValueRef) + -> @Block { let _icx = push_ctxt("move_to"); let mut bcx = bcx; @@ -365,7 +365,7 @@ impl Datum { return bcx; } - pub fn add_clean(&self, bcx: @mut Block) { + pub fn add_clean(&self, bcx: @Block) { /*! * Schedules this datum for cleanup in `bcx`. The datum * must be an rvalue. @@ -385,7 +385,7 @@ impl Datum { } } - pub fn cancel_clean(&self, bcx: @mut Block) { + pub fn cancel_clean(&self, bcx: @Block) { if ty::type_needs_drop(bcx.tcx(), self.ty) { match self.mode { ByValue | @@ -410,7 +410,7 @@ impl Datum { self.mode) } - pub fn to_value_datum(&self, bcx: @mut Block) -> Datum { + pub fn to_value_datum(&self, bcx: @Block) -> Datum { /*! * * Yields a by-value form of this datum. This may involve @@ -427,7 +427,7 @@ impl Datum { } } - pub fn to_value_llval(&self, bcx: @mut Block) -> ValueRef { + pub fn to_value_llval(&self, bcx: @Block) -> ValueRef { /*! * * Yields the value itself. */ @@ -448,7 +448,7 @@ impl Datum { } } - pub fn to_ref_datum(&self, bcx: @mut Block) -> Datum { + pub fn to_ref_datum(&self, bcx: @Block) -> Datum { /*! * Yields a by-ref form of this datum. This may involve * creation of a temporary stack slot. The value returned by @@ -465,7 +465,7 @@ impl Datum { } } - pub fn to_ref_llval(&self, bcx: @mut Block) -> ValueRef { + pub fn to_ref_llval(&self, bcx: @Block) -> ValueRef { match self.mode { ByRef(_) => self.val, ByValue => { @@ -492,13 +492,13 @@ impl Datum { } } - pub fn appropriate_mode(&self, ccx: &mut CrateContext) -> DatumMode { + pub fn appropriate_mode(&self, ccx: &CrateContext) -> DatumMode { /*! See the `appropriate_mode()` function */ appropriate_mode(ccx, self.ty) } - pub fn to_appropriate_llval(&self, bcx: @mut Block) -> ValueRef { + pub fn to_appropriate_llval(&self, bcx: @Block) -> ValueRef { /*! * * Yields an llvalue with the `appropriate_mode()`. */ @@ -509,7 +509,7 @@ impl Datum { } } - pub fn to_appropriate_datum(&self, bcx: @mut Block) -> Datum { + pub fn to_appropriate_datum(&self, bcx: @Block) -> Datum { /*! * * Yields a datum with the `appropriate_mode()`. */ @@ -521,7 +521,7 @@ impl Datum { } pub fn get_element(&self, - bcx: @mut Block, + bcx: @Block, ty: ty::t, source: DatumCleanup, gep: |ValueRef| -> ValueRef) @@ -534,7 +534,7 @@ impl Datum { } } - pub fn drop_val(&self, bcx: @mut Block) -> @mut Block { + pub fn drop_val(&self, bcx: @Block) -> @Block { if !ty::type_needs_drop(bcx.tcx(), self.ty) { return bcx; } @@ -545,7 +545,7 @@ impl Datum { }; } - pub fn box_body(&self, bcx: @mut Block) -> Datum { + pub fn box_body(&self, bcx: @Block) -> Datum { /*! * * This datum must represent an @T or ~T box. Returns a new @@ -578,7 +578,7 @@ impl Datum { } } - pub fn to_rptr(&self, bcx: @mut Block) -> Datum { + pub fn to_rptr(&self, bcx: @Block) -> Datum { //! Returns a new datum of region-pointer type containing the //! the same ptr as this datum (after converting to by-ref //! using `to_ref_llval()`). @@ -599,12 +599,12 @@ impl Datum { /// derefs: Number of times deref'd already. /// is_auto: If true, only deref if auto-derefable. pub fn try_deref(&self, - bcx: @mut Block, + bcx: @Block, span: Span, expr_id: ast::NodeId, derefs: uint, is_auto: bool) - -> (Option, @mut Block) { + -> (Option, @Block) { let ccx = bcx.ccx(); debug!("try_deref(expr_id={:?}, derefs={:?}, is_auto={}, self={:?})", @@ -703,7 +703,7 @@ impl Datum { } } - fn deref_ptr(bcx: @mut Block, lv: &Datum, ty: ty::t) -> Datum { + fn deref_ptr(bcx: @Block, lv: &Datum, ty: ty::t) -> Datum { Datum { val: lv.to_value_llval(bcx), ty: ty, @@ -713,7 +713,7 @@ impl Datum { } /// expr: The deref expression. - pub fn deref(&self, bcx: @mut Block, expr: &ast::Expr, derefs: uint) + pub fn deref(&self, bcx: @Block, expr: &ast::Expr, derefs: uint) -> DatumBlock { match self.try_deref(bcx, expr.span, expr.id, derefs, false) { (Some(lvres), bcx) => DatumBlock { bcx: bcx, datum: lvres }, @@ -725,7 +725,7 @@ impl Datum { } pub fn autoderef(&self, - bcx: @mut Block, + bcx: @Block, span: Span, expr_id: ast::NodeId, max: uint) @@ -758,11 +758,11 @@ impl Datum { } pub fn get_vec_base_and_byte_len(&self, - mut bcx: @mut Block, + mut bcx: @Block, span: Span, expr_id: ast::NodeId, derefs: uint) - -> (@mut Block, ValueRef, ValueRef) { + -> (@Block, ValueRef, ValueRef) { //! Converts a vector into the slice pair. Performs rooting //! and write guards checks. @@ -772,7 +772,7 @@ impl Datum { (bcx, base, len) } - pub fn get_vec_base_and_byte_len_no_root(&self, bcx: @mut Block) + pub fn get_vec_base_and_byte_len_no_root(&self, bcx: @Block) -> (ValueRef, ValueRef) { //! Converts a vector into the slice pair. Des not root //! nor perform write guard checks. @@ -782,11 +782,11 @@ impl Datum { } pub fn get_vec_base_and_len(&self, - mut bcx: @mut Block, + mut bcx: @Block, span: Span, expr_id: ast::NodeId, derefs: uint) - -> (@mut Block, ValueRef, ValueRef) { + -> (@Block, ValueRef, ValueRef) { //! Converts a vector into the slice pair. Performs rooting //! and write guards checks. @@ -796,7 +796,7 @@ impl Datum { (bcx, base, len) } - pub fn get_vec_base_and_len_no_root(&self, bcx: @mut Block) + pub fn get_vec_base_and_len_no_root(&self, bcx: @Block) -> (ValueRef, ValueRef) { //! Converts a vector into the slice pair. Des not root //! nor perform write guard checks. @@ -806,21 +806,21 @@ impl Datum { } pub fn root_and_write_guard(&self, - bcx: @mut Block, + bcx: @Block, span: Span, expr_id: ast::NodeId, derefs: uint) - -> @mut Block { + -> @Block { write_guard::root_and_write_guard(self, bcx, span, expr_id, derefs) } - pub fn to_result(&self, bcx: @mut Block) -> common::Result { + pub fn to_result(&self, bcx: @Block) -> common::Result { rslt(bcx, self.to_appropriate_llval(bcx)) } } impl DatumBlock { - pub fn unpack(&self, bcx: &mut @mut Block) -> Datum { + pub fn unpack(&self, bcx: &mut @Block) -> Datum { *bcx = self.bcx; return self.datum; } @@ -830,22 +830,22 @@ impl DatumBlock { *self } - pub fn drop_val(&self) -> @mut Block { + pub fn drop_val(&self) -> @Block { self.datum.drop_val(self.bcx) } pub fn store_to(&self, action: CopyAction, dst: ValueRef) - -> @mut Block { + -> @Block { self.datum.store_to(self.bcx, action, dst) } - pub fn copy_to(&self, action: CopyAction, dst: ValueRef) -> @mut Block { + pub fn copy_to(&self, action: CopyAction, dst: ValueRef) -> @Block { self.datum.copy_to(self.bcx, action, dst) } - pub fn move_to(&self, action: CopyAction, dst: ValueRef) -> @mut Block { + pub fn move_to(&self, action: CopyAction, dst: ValueRef) -> @Block { self.datum.move_to(self.bcx, action, dst) } @@ -857,7 +857,7 @@ impl DatumBlock { rslt(self.bcx, self.datum.to_appropriate_llval(self.bcx)) } - pub fn ccx(&self) -> @mut CrateContext { + pub fn ccx(&self) -> @CrateContext { self.bcx.ccx() } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 61fadb7e23654..d81eaf8fab875 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -142,6 +142,7 @@ use middle::pat_util; use util::ppaux; use std::c_str::ToCStr; +use std::cell::{Cell, RefCell}; use std::hashmap::HashMap; use std::hashmap::HashSet; use std::libc::{c_uint, c_ulonglong, c_longlong}; @@ -174,13 +175,13 @@ pub struct CrateDebugContext { priv crate_file: ~str, priv llcontext: ContextRef, priv builder: DIBuilderRef, - priv current_debug_location: DebugLocation, - priv created_files: HashMap<~str, DIFile>, - priv created_types: HashMap, - priv namespace_map: HashMap<~[ast::Ident], @NamespaceTreeNode>, + priv current_debug_location: Cell, + priv created_files: RefCell>, + priv created_types: RefCell>, + priv namespace_map: RefCell>, // This collection is used to assert that composite types (structs, enums, ...) have their // members only set once: - priv composite_types_completed: HashSet, + priv composite_types_completed: RefCell>, } impl CrateDebugContext { @@ -193,11 +194,11 @@ impl CrateDebugContext { crate_file: crate, llcontext: llcontext, builder: builder, - current_debug_location: UnknownLocation, - created_files: HashMap::new(), - created_types: HashMap::new(), - namespace_map: HashMap::new(), - composite_types_completed: HashSet::new(), + current_debug_location: Cell::new(UnknownLocation), + created_files: RefCell::new(HashMap::new()), + created_types: RefCell::new(HashMap::new()), + namespace_map: RefCell::new(HashMap::new()), + composite_types_completed: RefCell::new(HashSet::new()), }; } } @@ -221,21 +222,6 @@ impl FunctionDebugContext { } } - fn get_mut_ref<'a>(&'a mut self, - cx: &CrateContext, - span: Span) - -> &'a mut FunctionDebugContextData { - match *self { - FunctionDebugContext(~ref mut data) => data, - DebugInfoDisabled => { - cx.sess.span_bug(span, FunctionDebugContext::debuginfo_disabled_message()); - } - FunctionWithoutDebugInfo => { - cx.sess.span_bug(span, FunctionDebugContext::should_be_ignored_message()); - } - } - } - fn debuginfo_disabled_message() -> &'static str { "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!" } @@ -247,10 +233,10 @@ impl FunctionDebugContext { } struct FunctionDebugContextData { - scope_map: HashMap, + scope_map: RefCell>, fn_metadata: DISubprogram, - argument_counter: uint, - source_locations_enabled: bool, + argument_counter: Cell, + source_locations_enabled: Cell, } enum VariableAccess<'a> { @@ -268,7 +254,7 @@ enum VariableKind { } /// Create any deferred debug metadata nodes -pub fn finalize(cx: @mut CrateContext) { +pub fn finalize(cx: @CrateContext) { if cx.dbg_cx.is_none() { return; } @@ -284,7 +270,7 @@ pub fn finalize(cx: @mut CrateContext) { /// Creates debug information for the given local variable. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_local_var_metadata(bcx: @mut Block, +pub fn create_local_var_metadata(bcx: @Block, local: &ast::Local) { if fn_should_be_ignored(bcx.fcx) { return; @@ -297,11 +283,15 @@ pub fn create_local_var_metadata(bcx: @mut Block, let var_ident = ast_util::path_to_ident(path_ref); let var_type = node_id_type(bcx, node_id); - let llptr = match bcx.fcx.lllocals.find_copy(&node_id) { - Some(v) => v, - None => { - bcx.tcx().sess.span_bug(span, - format!("No entry in lllocals table for {:?}", node_id)); + let llptr = { + let lllocals = bcx.fcx.lllocals.borrow(); + match lllocals.get().find_copy(&node_id) { + Some(v) => v, + None => { + bcx.tcx().sess.span_bug(span, + format!("No entry in lllocals table for {:?}", + node_id)); + } } }; @@ -320,7 +310,7 @@ pub fn create_local_var_metadata(bcx: @mut Block, /// Creates debug information for a variable captured in a closure. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_captured_var_metadata(bcx: @mut Block, +pub fn create_captured_var_metadata(bcx: @Block, node_id: ast::NodeId, env_data_type: ty::t, env_pointer: ValueRef, @@ -387,7 +377,7 @@ pub fn create_captured_var_metadata(bcx: @mut Block, /// Creates debug information for a local variable introduced in the head of a match-statement arm. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_match_binding_metadata(bcx: @mut Block, +pub fn create_match_binding_metadata(bcx: @Block, variable_ident: ast::Ident, node_id: ast::NodeId, variable_type: ty::t, @@ -396,10 +386,17 @@ pub fn create_match_binding_metadata(bcx: @mut Block, return; } - let llptr = match bcx.fcx.lllocals.find_copy(&node_id) { - Some(v) => v, - None => { - bcx.tcx().sess.span_bug(span, format!("No entry in lllocals table for {:?}", node_id)); + let llptr = { + let lllocals = bcx.fcx.lllocals.borrow(); + match lllocals.get().find_copy(&node_id) { + Some(v) => v, + None => { + bcx.tcx() + .sess + .span_bug(span, + format!("No entry in lllocals table for {:?}", + node_id)); + } } }; @@ -417,7 +414,7 @@ pub fn create_match_binding_metadata(bcx: @mut Block, /// Creates debug information for the self argument of a method. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_self_argument_metadata(bcx: @mut Block, +pub fn create_self_argument_metadata(bcx: @Block, type_of_self: ty::t, llptr: ValueRef) { if fn_should_be_ignored(bcx.fcx) { @@ -447,9 +444,9 @@ pub fn create_self_argument_metadata(bcx: @mut Block, let scope_metadata = bcx.fcx.debug_context.get_ref(bcx.ccx(), span).fn_metadata; let argument_index = { - let counter = &mut bcx.fcx.debug_context.get_mut_ref(bcx.ccx(), span).argument_counter; - let argument_index = *counter; - *counter += 1; + let counter = &bcx.fcx.debug_context.get_ref(bcx.ccx(), span).argument_counter; + let argument_index = counter.get(); + counter.set(argument_index + 1); argument_index }; @@ -492,7 +489,7 @@ pub fn create_self_argument_metadata(bcx: @mut Block, /// Creates debug information for the given function argument. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_argument_metadata(bcx: @mut Block, +pub fn create_argument_metadata(bcx: @Block, arg: &ast::arg) { if fn_should_be_ignored(bcx.fcx) { return; @@ -505,11 +502,15 @@ pub fn create_argument_metadata(bcx: @mut Block, let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata; pat_util::pat_bindings(def_map, arg.pat, |_, node_id, span, path_ref| { - let llptr = match bcx.fcx.llargs.find_copy(&node_id) { - Some(v) => v, - None => { - bcx.tcx().sess.span_bug(span, - format!("No entry in llargs table for {:?}", node_id)); + let llptr = { + let llargs = bcx.fcx.llargs.borrow(); + match llargs.get().find_copy(&node_id) { + Some(v) => v, + None => { + bcx.tcx().sess.span_bug(span, + format!("No entry in llargs table for {:?}", + node_id)); + } } }; @@ -522,9 +523,9 @@ pub fn create_argument_metadata(bcx: @mut Block, let argument_ident = ast_util::path_to_ident(path_ref); let argument_index = { - let counter = &mut fcx.debug_context.get_mut_ref(cx, span).argument_counter; - let argument_index = *counter; - *counter += 1; + let counter = &fcx.debug_context.get_ref(cx, span).argument_counter; + let argument_index = counter.get(); + counter.set(argument_index + 1); argument_index }; @@ -553,7 +554,7 @@ pub fn set_source_location(fcx: &FunctionContext, debug!("set_source_location: {}", cx.sess.codemap.span_to_str(span)); - if fcx.debug_context.get_ref(cx, span).source_locations_enabled { + if fcx.debug_context.get_ref(cx, span).source_locations_enabled.get() { let loc = span_start(cx, span); let scope = scope_metadata(fcx, node_id, span); @@ -580,9 +581,11 @@ pub fn clear_source_location(fcx: &FunctionContext) { /// when beginning to translate a new function. This functions switches source location emitting on /// and must therefore be called before the first real statement/expression of the function is /// translated. -pub fn start_emitting_source_locations(fcx: &mut FunctionContext) { +pub fn start_emitting_source_locations(fcx: &FunctionContext) { match fcx.debug_context { - FunctionDebugContext(~ref mut data) => data.source_locations_enabled = true, + FunctionDebugContext(~ref data) => { + data.source_locations_enabled.set(true) + }, _ => { /* safe to ignore */ } } } @@ -592,7 +595,7 @@ pub fn start_emitting_source_locations(fcx: &mut FunctionContext) { /// Returns the FunctionDebugContext for the function which holds state needed for debug info /// creation. The function may also return another variant of the FunctionDebugContext enum which /// indicates why no debuginfo should be created for the function. -pub fn create_function_debug_context(cx: &mut CrateContext, +pub fn create_function_debug_context(cx: &CrateContext, fn_ast_id: ast::NodeId, param_substs: Option<@param_substs>, llfn: ValueRef) -> FunctionDebugContext { @@ -716,7 +719,10 @@ pub fn create_function_debug_context(cx: &mut CrateContext, // (by being externally visible or by being inlined into something externally visible). It might // better to use the `exported_items` set from `driver::CrateAnalysis` in the future, but (atm) // this set is not available in the translation pass. - let is_local_to_unit = !cx.reachable.contains(&fn_ast_id); + let is_local_to_unit = { + let reachable = cx.reachable.borrow(); + !reachable.get().contains(&fn_ast_id) + }; let fn_metadata = function_name.with_c_str(|function_name| { linkage_name.with_c_str(|linkage_name| { @@ -742,22 +748,29 @@ pub fn create_function_debug_context(cx: &mut CrateContext, }); // Initialize fn debug context (including scope map and namespace map) - let mut fn_debug_context = ~FunctionDebugContextData { - scope_map: HashMap::new(), + let fn_debug_context = ~FunctionDebugContextData { + scope_map: RefCell::new(HashMap::new()), fn_metadata: fn_metadata, - argument_counter: 1, - source_locations_enabled: false, + argument_counter: Cell::new(1), + source_locations_enabled: Cell::new(false), }; let arg_pats = fn_decl.inputs.map(|arg_ref| arg_ref.pat); - populate_scope_map(cx, arg_pats, top_level_block, fn_metadata, &mut fn_debug_context.scope_map); + { + let mut scope_map = fn_debug_context.scope_map.borrow_mut(); + populate_scope_map(cx, + arg_pats, + top_level_block, + fn_metadata, + scope_map.get()); + } // Clear the debug location so we don't assign them in the function prelude set_debug_location(cx, UnknownLocation); return FunctionDebugContext(fn_debug_context); - fn get_function_signature(cx: &mut CrateContext, + fn get_function_signature(cx: &CrateContext, fn_ast_id: ast::NodeId, fn_decl: &ast::fn_decl, param_substs: Option<@param_substs>, @@ -805,7 +818,7 @@ pub fn create_function_debug_context(cx: &mut CrateContext, return create_DIArray(DIB(cx), signature); } - fn get_template_parameters(cx: &mut CrateContext, + fn get_template_parameters(cx: &CrateContext, generics: &ast::Generics, param_substs: Option<@param_substs>, file_metadata: DIFile, @@ -917,7 +930,7 @@ fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray { }; } -fn compile_unit_metadata(cx: @mut CrateContext) { +fn compile_unit_metadata(cx: @CrateContext) { let dcx = debug_context(cx); let crate_name: &str = dcx.crate_file; @@ -951,14 +964,14 @@ fn compile_unit_metadata(cx: @mut CrateContext) { }); } -fn declare_local(bcx: @mut Block, +fn declare_local(bcx: @Block, variable_ident: ast::Ident, variable_type: ty::t, scope_metadata: DIScope, variable_access: VariableAccess, variable_kind: VariableKind, span: Span) { - let cx: &mut CrateContext = bcx.ccx(); + let cx: &CrateContext = bcx.ccx(); let filename = span_start(cx, span).file.name; let file_metadata = file_metadata(cx, filename); @@ -1023,17 +1036,24 @@ fn declare_local(bcx: @mut Block, match variable_kind { ArgumentVariable(_) | CapturedVariable => { - assert!(!bcx.fcx.debug_context.get_ref(cx, span).source_locations_enabled); + assert!(!bcx.fcx + .debug_context + .get_ref(cx, span) + .source_locations_enabled + .get()); set_debug_location(cx, UnknownLocation); } _ => { /* nothing to do */ } } } -fn file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile { - match debug_context(cx).created_files.find_equiv(&full_path) { - Some(file_metadata) => return *file_metadata, - None => () +fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile { + { + let created_files = debug_context(cx).created_files.borrow(); + match created_files.get().find_equiv(&full_path) { + Some(file_metadata) => return *file_metadata, + None => () + } } debug!("file_metadata: {}", full_path); @@ -1056,7 +1076,8 @@ fn file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile { }) }); - debug_context(cx).created_files.insert(full_path.to_owned(), file_metadata); + let mut created_files = debug_context(cx).created_files.borrow_mut(); + created_files.get().insert(full_path.to_owned(), file_metadata); return file_metadata; } @@ -1066,8 +1087,9 @@ fn scope_metadata(fcx: &FunctionContext, span: Span) -> DIScope { let scope_map = &fcx.debug_context.get_ref(fcx.ccx, span).scope_map; + let scope_map = scope_map.borrow(); - match scope_map.find_copy(&node_id) { + match scope_map.get().find_copy(&node_id) { Some(scope_metadata) => scope_metadata, None => { let node = fcx.ccx.tcx.items.get_copy(&node_id); @@ -1078,7 +1100,7 @@ fn scope_metadata(fcx: &FunctionContext, } } -fn basic_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType { +fn basic_type_metadata(cx: &CrateContext, t: ty::t) -> DIType { debug!("basic_type_metadata: {:?}", ty::get(t)); @@ -1124,7 +1146,7 @@ fn basic_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType { return ty_metadata; } -fn pointer_type_metadata(cx: &mut CrateContext, +fn pointer_type_metadata(cx: &CrateContext, pointer_type: ty::t, pointee_type_metadata: DIType) -> DIType { @@ -1145,7 +1167,7 @@ fn pointer_type_metadata(cx: &mut CrateContext, } trait MemberDescriptionFactory { - fn create_member_descriptions(&self, cx: &mut CrateContext) + fn create_member_descriptions(&self, cx: &CrateContext) -> ~[MemberDescription]; } @@ -1155,7 +1177,7 @@ struct StructMemberDescriptionFactory { } impl MemberDescriptionFactory for StructMemberDescriptionFactory { - fn create_member_descriptions(&self, cx: &mut CrateContext) + fn create_member_descriptions(&self, cx: &CrateContext) -> ~[MemberDescription] { self.fields.map(|field| { let name = if field.ident.name == special_idents::unnamed_field.name { @@ -1174,7 +1196,7 @@ impl MemberDescriptionFactory for StructMemberDescriptionFactory { } } -fn prepare_struct_metadata(cx: &mut CrateContext, +fn prepare_struct_metadata(cx: &CrateContext, struct_type: ty::t, def_id: ast::DefId, substs: &ty::substs, @@ -1222,7 +1244,7 @@ enum RecursiveTypeDescription { impl RecursiveTypeDescription { - fn finalize(&self, cx: &mut CrateContext) -> DICompositeType { + fn finalize(&self, cx: &CrateContext) -> DICompositeType { match *self { FinalMetadata(metadata) => metadata, UnfinishedMetadata { @@ -1233,7 +1255,11 @@ impl RecursiveTypeDescription { member_description_factory } => { // Insert the stub into the cache in order to allow recursive references ... - debug_context(cx).created_types.insert(cache_id, metadata_stub); + { + let mut created_types = debug_context(cx).created_types + .borrow_mut(); + created_types.get().insert(cache_id, metadata_stub); + } // ... then create the member descriptions ... let member_descriptions = member_description_factory. @@ -1258,7 +1284,7 @@ struct TupleMemberDescriptionFactory { } impl MemberDescriptionFactory for TupleMemberDescriptionFactory { - fn create_member_descriptions(&self, cx: &mut CrateContext) + fn create_member_descriptions(&self, cx: &CrateContext) -> ~[MemberDescription] { self.component_types.map(|&component_type| { MemberDescription { @@ -1271,7 +1297,7 @@ impl MemberDescriptionFactory for TupleMemberDescriptionFactory { } } -fn prepare_tuple_metadata(cx: &mut CrateContext, +fn prepare_tuple_metadata(cx: &CrateContext, tuple_type: ty::t, component_types: &[ty::t], span: Span) @@ -1309,7 +1335,7 @@ struct GeneralMemberDescriptionFactory { } impl MemberDescriptionFactory for GeneralMemberDescriptionFactory { - fn create_member_descriptions(&self, cx: &mut CrateContext) + fn create_member_descriptions(&self, cx: &CrateContext) -> ~[MemberDescription] { // Capture type_rep, so we don't have to copy the struct_defs array let struct_defs = match *self.type_rep { @@ -1356,7 +1382,7 @@ struct EnumVariantMemberDescriptionFactory { } impl MemberDescriptionFactory for EnumVariantMemberDescriptionFactory { - fn create_member_descriptions(&self, cx: &mut CrateContext) + fn create_member_descriptions(&self, cx: &CrateContext) -> ~[MemberDescription] { self.args.iter().enumerate().map(|(i, &(name, ty))| { MemberDescription { @@ -1372,7 +1398,7 @@ impl MemberDescriptionFactory for EnumVariantMemberDescriptionFactory { } } -fn describe_variant(cx: &mut CrateContext, +fn describe_variant(cx: &CrateContext, struct_def: &adt::Struct, variant_info: &ty::VariantInfo, discriminant_type_metadata: Option, @@ -1435,7 +1461,7 @@ fn describe_variant(cx: &mut CrateContext, (metadata_stub, variant_llvm_type, member_description_factory) } -fn prepare_enum_metadata(cx: &mut CrateContext, +fn prepare_enum_metadata(cx: &CrateContext, enum_type: ty::t, enum_def_id: ast::DefId, span: Span) @@ -1600,7 +1626,7 @@ struct MemberDescription { /// Creates debug information for a composite type, that is, anything that results in a LLVM struct. /// /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums. -fn composite_type_metadata(cx: &mut CrateContext, +fn composite_type_metadata(cx: &CrateContext, composite_llvm_type: Type, composite_type_name: &str, member_descriptions: &[MemberDescription], @@ -1627,7 +1653,7 @@ fn composite_type_metadata(cx: &mut CrateContext, return composite_type_metadata; } -fn set_members_of_composite_type(cx: &mut CrateContext, +fn set_members_of_composite_type(cx: &CrateContext, composite_type_metadata: DICompositeType, composite_llvm_type: Type, member_descriptions: &[MemberDescription], @@ -1637,11 +1663,16 @@ fn set_members_of_composite_type(cx: &mut CrateContext, // used instead of a new one created in create_struct_stub. This would cause a hard to trace // assertion in DICompositeType::SetTypeArray(). The following check makes sure that we get a // better error message if this should happen again due to some regression. - if debug_context(cx).composite_types_completed.contains(&composite_type_metadata) { - cx.sess.span_bug(definition_span, "debuginfo::set_members_of_composite_type() - Already \ - completed forward declaration re-encountered."); - } else { - debug_context(cx).composite_types_completed.insert(composite_type_metadata); + { + let mut composite_types_completed = + debug_context(cx).composite_types_completed.borrow_mut(); + if composite_types_completed.get().contains(&composite_type_metadata) { + cx.sess.span_bug(definition_span, "debuginfo::set_members_of_composite_type() - \ + Already completed forward declaration \ + re-encountered."); + } else { + composite_types_completed.get().insert(composite_type_metadata); + } } let loc = span_start(cx, definition_span); @@ -1682,7 +1713,7 @@ fn set_members_of_composite_type(cx: &mut CrateContext, // A convenience wrapper around LLVMDIBuilderCreateStructType(). Does not do any caching, does not // add any fields to the struct. This can be done later with set_members_of_composite_type(). -fn create_struct_stub(cx: &mut CrateContext, +fn create_struct_stub(cx: &CrateContext, struct_llvm_type: Type, struct_type_name: &str, containing_scope: DIScope, @@ -1725,7 +1756,7 @@ fn create_struct_stub(cx: &mut CrateContext, }; } -fn boxed_type_metadata(cx: &mut CrateContext, +fn boxed_type_metadata(cx: &CrateContext, content_type_name: Option<&str>, content_llvm_type: Type, content_type_metadata: DIType, @@ -1804,7 +1835,7 @@ fn boxed_type_metadata(cx: &mut CrateContext, } } -fn fixed_vec_metadata(cx: &mut CrateContext, +fn fixed_vec_metadata(cx: &CrateContext, element_type: ty::t, len: uint, span: Span) @@ -1831,7 +1862,7 @@ fn fixed_vec_metadata(cx: &mut CrateContext, }; } -fn vec_metadata(cx: &mut CrateContext, +fn vec_metadata(cx: &CrateContext, element_type: ty::t, span: Span) -> DICompositeType { @@ -1891,7 +1922,7 @@ fn vec_metadata(cx: &mut CrateContext, span); } -fn boxed_vec_metadata(cx: &mut CrateContext, +fn boxed_vec_metadata(cx: &CrateContext, element_type: ty::t, span: Span) -> DICompositeType { @@ -1908,7 +1939,7 @@ fn boxed_vec_metadata(cx: &mut CrateContext, span); } -fn vec_slice_metadata(cx: &mut CrateContext, +fn vec_slice_metadata(cx: &CrateContext, vec_type: ty::t, element_type: ty::t, span: Span) @@ -1953,7 +1984,7 @@ fn vec_slice_metadata(cx: &mut CrateContext, file_metadata, span); - fn slice_layout_is_correct(cx: &mut CrateContext, + fn slice_layout_is_correct(cx: &CrateContext, member_llvm_types: &[Type], element_type: ty::t) -> bool { @@ -1963,7 +1994,7 @@ fn vec_slice_metadata(cx: &mut CrateContext, } } -fn subroutine_type_metadata(cx: &mut CrateContext, +fn subroutine_type_metadata(cx: &CrateContext, signature: &ty::FnSig, span: Span) -> DICompositeType { @@ -1991,7 +2022,7 @@ fn subroutine_type_metadata(cx: &mut CrateContext, }; } -fn trait_metadata(cx: &mut CrateContext, +fn trait_metadata(cx: &CrateContext, def_id: ast::DefId, trait_type: ty::t, substs: &ty::substs, @@ -2032,17 +2063,21 @@ fn cache_id_for_type(t: ty::t) -> uint { ty::type_id(t) } -fn type_metadata(cx: &mut CrateContext, +fn type_metadata(cx: &CrateContext, t: ty::t, usage_site_span: Span) -> DIType { let cache_id = cache_id_for_type(t); - match debug_context(cx).created_types.find(&cache_id) { - Some(type_metadata) => return *type_metadata, - None => () + + { + let created_types = debug_context(cx).created_types.borrow(); + match created_types.get().find(&cache_id) { + Some(type_metadata) => return *type_metadata, + None => () + } } - fn create_pointer_to_box_metadata(cx: &mut CrateContext, + fn create_pointer_to_box_metadata(cx: &CrateContext, pointer_type: ty::t, type_in_box: ty::t) -> DIType { @@ -2153,7 +2188,8 @@ fn type_metadata(cx: &mut CrateContext, _ => cx.sess.bug(format!("debuginfo: unexpected type in type_metadata: {:?}", sty)) }; - debug_context(cx).created_types.insert(cache_id, type_metadata); + let mut created_types = debug_context(cx).created_types.borrow_mut(); + created_types.get().insert(cache_id, type_metadata); return type_metadata; } @@ -2173,8 +2209,8 @@ impl DebugLocation { } } -fn set_debug_location(cx: &mut CrateContext, debug_location: DebugLocation) { - if debug_location == debug_context(cx).current_debug_location { +fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) { + if debug_location == debug_context(cx).current_debug_location.get() { return; } @@ -2201,7 +2237,7 @@ fn set_debug_location(cx: &mut CrateContext, debug_location: DebugLocation) { llvm::LLVMSetCurrentDebugLocation(cx.builder.B, metadata_node); } - debug_context(cx).current_debug_location = debug_location; + debug_context(cx).current_debug_location.set(debug_location); } //=------------------------------------------------------------------------------------------------- @@ -2213,7 +2249,7 @@ fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc { cx.sess.codemap.lookup_char_pos(span.lo) } -fn size_and_align_of(cx: &mut CrateContext, llvm_type: Type) -> (uint, uint) { +fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (uint, uint) { (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type)) } @@ -2222,8 +2258,9 @@ fn bytes_to_bits(bytes: uint) -> c_ulonglong { } #[inline] -fn debug_context<'a>(cx: &'a mut CrateContext) -> &'a mut CrateDebugContext { - cx.dbg_cx.get_mut_ref() +fn debug_context<'a>(cx: &'a CrateContext) -> &'a CrateDebugContext { + let debug_context: &'a CrateDebugContext = cx.dbg_cx.get_ref(); + debug_context } #[inline] @@ -2239,12 +2276,13 @@ fn fn_should_be_ignored(fcx: &FunctionContext) -> bool { } fn assert_type_for_node_id(cx: &CrateContext, node_id: ast::NodeId, error_span: Span) { - if !cx.tcx.node_types.contains_key(&(node_id as uint)) { + let node_types = cx.tcx.node_types.borrow(); + if !node_types.get().contains_key(&(node_id as uint)) { cx.sess.span_bug(error_span, "debuginfo: Could not find type for node id!"); } } -fn get_namespace_and_span_for_item(cx: &mut CrateContext, +fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: ast::DefId, warning_span: Span) -> (DIScope, Span) { @@ -2275,7 +2313,7 @@ fn get_namespace_and_span_for_item(cx: &mut CrateContext, // scope, creating DIScope DIEs along the way, and introducing *artificial* lexical scope // descriptors where necessary. These artificial scopes allow GDB to correctly handle name // shadowing. -fn populate_scope_map(cx: &mut CrateContext, +fn populate_scope_map(cx: &CrateContext, arg_pats: &[@ast::Pat], fn_entry_block: &ast::Block, fn_metadata: DISubprogram, @@ -2308,11 +2346,11 @@ fn populate_scope_map(cx: &mut CrateContext, }); // local helper functions for walking the AST. - fn with_new_scope(cx: &mut CrateContext, + fn with_new_scope(cx: &CrateContext, scope_span: Span, scope_stack: &mut ~[ScopeStackEntry], scope_map: &mut HashMap, - inner_walk: |&mut CrateContext, + inner_walk: |&CrateContext, &mut ~[ScopeStackEntry], &mut HashMap|) { // Create a new lexical scope and push it onto the stack @@ -2345,7 +2383,7 @@ fn populate_scope_map(cx: &mut CrateContext, scope_stack.pop(); } - fn walk_block(cx: &mut CrateContext, + fn walk_block(cx: &CrateContext, block: &ast::Block, scope_stack: &mut ~[ScopeStackEntry], scope_map: &mut HashMap) { @@ -2368,7 +2406,7 @@ fn populate_scope_map(cx: &mut CrateContext, } } - fn walk_decl(cx: &mut CrateContext, + fn walk_decl(cx: &CrateContext, decl: &ast::Decl, scope_stack: &mut ~[ScopeStackEntry], scope_map: &mut HashMap) { @@ -2386,7 +2424,7 @@ fn populate_scope_map(cx: &mut CrateContext, } } - fn walk_pattern(cx: &mut CrateContext, + fn walk_pattern(cx: &CrateContext, pat: @ast::Pat, scope_stack: &mut ~[ScopeStackEntry], scope_map: &mut HashMap) { @@ -2533,7 +2571,7 @@ fn populate_scope_map(cx: &mut CrateContext, } } - fn walk_expr(cx: &mut CrateContext, + fn walk_expr(cx: &CrateContext, exp: &ast::Expr, scope_stack: &mut ~[ScopeStackEntry], scope_map: &mut HashMap) { @@ -2771,7 +2809,7 @@ impl NamespaceTreeNode { } } -fn namespace_for_item(cx: &mut CrateContext, +fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId, warning_span: Span) -> @NamespaceTreeNode { @@ -2805,7 +2843,10 @@ fn namespace_for_item(cx: &mut CrateContext, let ident = path_element.ident(); current_key.push(ident); - let existing_node = debug_context(cx).namespace_map.find_copy(¤t_key); + let existing_node = { + let namespace_map = debug_context(cx).namespace_map.borrow(); + namespace_map.get().find_copy(¤t_key) + }; let current_node = match existing_node { Some(existing_node) => existing_node, None => { @@ -2833,7 +2874,11 @@ fn namespace_for_item(cx: &mut CrateContext, parent: parent_node, }; - debug_context(cx).namespace_map.insert(current_key.clone(), node); + { + let mut namespace_map = debug_context(cx).namespace_map + .borrow_mut(); + namespace_map.get().insert(current_key.clone(), node); + } node } diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index be07fbde9ffec..2990a27391fe6 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -175,14 +175,17 @@ impl Dest { } } -pub fn trans_to_datum(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { +pub fn trans_to_datum(bcx: @Block, expr: &ast::Expr) -> DatumBlock { debug!("trans_to_datum(expr={})", bcx.expr_to_str(expr)); let mut bcx = bcx; let mut datum = unpack_datum!(bcx, trans_to_datum_unadjusted(bcx, expr)); - let adjustment = match bcx.tcx().adjustments.find_copy(&expr.id) { - None => { return DatumBlock {bcx: bcx, datum: datum}; } - Some(adj) => { adj } + let adjustment = { + let adjustments = bcx.tcx().adjustments.borrow(); + match adjustments.get().find_copy(&expr.id) { + None => { return DatumBlock {bcx: bcx, datum: datum}; } + Some(adj) => { adj } + } }; debug!("unadjusted datum: {}", datum.to_str(bcx.ccx())); match *adjustment { @@ -229,11 +232,11 @@ pub fn trans_to_datum(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { debug!("after adjustments, datum={}", datum.to_str(bcx.ccx())); return DatumBlock {bcx: bcx, datum: datum}; - fn auto_ref(bcx: @mut Block, datum: Datum) -> DatumBlock { + fn auto_ref(bcx: @Block, datum: Datum) -> DatumBlock { DatumBlock {bcx: bcx, datum: datum.to_rptr(bcx)} } - fn auto_borrow_fn(bcx: @mut Block, + fn auto_borrow_fn(bcx: @Block, adjusted_ty: ty::t, datum: Datum) -> DatumBlock { // Currently, all closure types are represented precisely the @@ -244,7 +247,7 @@ pub fn trans_to_datum(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { mode: datum.mode}} } - fn auto_slice(bcx: @mut Block, + fn auto_slice(bcx: @Block, autoderefs: uint, expr: &ast::Expr, datum: Datum) -> DatumBlock { @@ -273,7 +276,7 @@ pub fn trans_to_datum(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { DatumBlock {bcx: bcx, datum: scratch} } - fn add_env(bcx: @mut Block, expr: &ast::Expr, datum: Datum) -> DatumBlock { + fn add_env(bcx: @Block, expr: &ast::Expr, datum: Datum) -> DatumBlock { // This is not the most efficient thing possible; since closures // are two words it'd be better if this were compiled in // 'dest' mode, but I can't find a nice way to structure the @@ -292,7 +295,7 @@ pub fn trans_to_datum(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { DatumBlock {bcx: bcx, datum: scratch} } - fn auto_slice_and_ref(bcx: @mut Block, + fn auto_slice_and_ref(bcx: @Block, autoderefs: uint, expr: &ast::Expr, datum: Datum) -> DatumBlock { @@ -300,7 +303,7 @@ pub fn trans_to_datum(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { auto_ref(bcx, datum) } - fn auto_borrow_obj(mut bcx: @mut Block, + fn auto_borrow_obj(mut bcx: @Block, autoderefs: uint, expr: &ast::Expr, source_datum: Datum) -> DatumBlock { @@ -414,8 +417,12 @@ pub fn trans_to_datum(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { } } -pub fn trans_into(bcx: @mut Block, expr: &ast::Expr, dest: Dest) -> @mut Block { - if bcx.tcx().adjustments.contains_key(&expr.id) { +pub fn trans_into(bcx: @Block, expr: &ast::Expr, dest: Dest) -> @Block { + let adjustment_found = { + let adjustments = bcx.tcx().adjustments.borrow(); + adjustments.get().contains_key(&expr.id) + }; + if adjustment_found { // use trans_to_datum, which is mildly less efficient but // which will perform the adjustments: let datumblock = trans_to_datum(bcx, expr); @@ -472,7 +479,7 @@ pub fn trans_into(bcx: @mut Block, expr: &ast::Expr, dest: Dest) -> @mut Block { }; } -fn trans_lvalue(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { +fn trans_lvalue(bcx: @Block, expr: &ast::Expr) -> DatumBlock { /*! * * Translates an lvalue expression, always yielding a by-ref @@ -480,7 +487,11 @@ fn trans_lvalue(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { * instead, but sometimes we call trans_lvalue() directly as a * means of asserting that a particular expression is an lvalue. */ - return match bcx.tcx().adjustments.find(&expr.id) { + let adjustment_opt = { + let adjustments = bcx.tcx().adjustments.borrow(); + adjustments.get().find_copy(&expr.id) + }; + match adjustment_opt { None => trans_lvalue_unadjusted(bcx, expr), Some(_) => { bcx.sess().span_bug( @@ -488,10 +499,10 @@ fn trans_lvalue(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { format!("trans_lvalue() called on an expression \ with adjustments")); } - }; + } } -fn trans_to_datum_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { +fn trans_to_datum_unadjusted(bcx: @Block, expr: &ast::Expr) -> DatumBlock { /*! * Translates an expression into a datum. If this expression * is an rvalue, this will result in a temporary value being @@ -551,13 +562,13 @@ fn trans_to_datum_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { } } - fn nil(bcx: @mut Block, ty: ty::t) -> DatumBlock { + fn nil(bcx: @Block, ty: ty::t) -> DatumBlock { let datum = immediate_rvalue(C_nil(), ty); DatumBlock {bcx: bcx, datum: datum} } } -fn trans_rvalue_datum_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { +fn trans_rvalue_datum_unadjusted(bcx: @Block, expr: &ast::Expr) -> DatumBlock { let _icx = push_ctxt("trans_rvalue_datum_unadjusted"); match expr.node { @@ -579,7 +590,10 @@ fn trans_rvalue_datum_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBloc } ast::ExprBinary(_, op, lhs, rhs) => { // if overloaded, would be RvalueDpsExpr - assert!(!bcx.ccx().maps.method_map.contains_key(&expr.id)); + { + let method_map = bcx.ccx().maps.method_map.borrow(); + assert!(!method_map.get().contains_key(&expr.id)); + } return trans_binary(bcx, expr, op, lhs, rhs); } @@ -608,11 +622,11 @@ fn trans_rvalue_datum_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBloc } } -fn trans_rvalue_stmt_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> @mut Block { +fn trans_rvalue_stmt_unadjusted(bcx: @Block, expr: &ast::Expr) -> @Block { let mut bcx = bcx; let _icx = push_ctxt("trans_rvalue_stmt"); - if bcx.unreachable { + if bcx.unreachable.get() { return bcx; } @@ -660,8 +674,8 @@ fn trans_rvalue_stmt_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> @mut Block }; } -fn trans_rvalue_dps_unadjusted(bcx: @mut Block, expr: &ast::Expr, - dest: Dest) -> @mut Block { +fn trans_rvalue_dps_unadjusted(bcx: @Block, expr: &ast::Expr, + dest: Dest) -> @Block { let _icx = push_ctxt("trans_rvalue_dps_unadjusted"); let tcx = bcx.tcx(); @@ -785,8 +799,8 @@ fn trans_rvalue_dps_unadjusted(bcx: @mut Block, expr: &ast::Expr, } } -fn trans_def_dps_unadjusted(bcx: @mut Block, ref_expr: &ast::Expr, - def: ast::Def, dest: Dest) -> @mut Block { +fn trans_def_dps_unadjusted(bcx: @Block, ref_expr: &ast::Expr, + def: ast::Def, dest: Dest) -> @Block { let _icx = push_ctxt("trans_def_dps_unadjusted"); let ccx = bcx.ccx(); @@ -835,7 +849,7 @@ fn trans_def_dps_unadjusted(bcx: @mut Block, ref_expr: &ast::Expr, } } -fn trans_def_datum_unadjusted(bcx: @mut Block, +fn trans_def_datum_unadjusted(bcx: @Block, ref_expr: &ast::Expr, def: ast::Def) -> DatumBlock { @@ -870,7 +884,7 @@ fn trans_def_datum_unadjusted(bcx: @mut Block, } } -fn trans_lvalue_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { +fn trans_lvalue_unadjusted(bcx: @Block, expr: &ast::Expr) -> DatumBlock { /*! * * Translates an lvalue expression, always yielding a by-ref @@ -907,7 +921,7 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { } }; - fn trans_rec_field(bcx: @mut Block, + fn trans_rec_field(bcx: @Block, base: &ast::Expr, field: ast::Ident) -> DatumBlock { //! Translates `base.field`. @@ -931,7 +945,7 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { }) } - fn trans_index(bcx: @mut Block, + fn trans_index(bcx: @Block, index_expr: &ast::Expr, base: &ast::Expr, idx: &ast::Expr) -> DatumBlock { @@ -985,7 +999,7 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { }; } - fn trans_def_lvalue(bcx: @mut Block, + fn trans_def_lvalue(bcx: @Block, ref_expr: &ast::Expr, def: ast::Def) -> DatumBlock @@ -997,7 +1011,7 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { ast::DefStatic(did, _) => { let const_ty = expr_ty(bcx, ref_expr); - fn get_did(ccx: @mut CrateContext, did: ast::DefId) + fn get_did(ccx: @CrateContext, did: ast::DefId) -> ast::DefId { if did.crate != ast::LOCAL_CRATE { inline::maybe_instantiate_inline(ccx, did) @@ -1006,7 +1020,7 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { } } - fn get_val(bcx: @mut Block, did: ast::DefId, const_ty: ty::t) + fn get_val(bcx: @Block, did: ast::DefId, const_ty: ty::t) -> ValueRef { // For external constants, we don't inline. if did.crate == ast::LOCAL_CRATE { @@ -1018,8 +1032,10 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { PointerCast(bcx, val, pty) } else { { - let extern_const_values = &bcx.ccx().extern_const_values; - match extern_const_values.find(&did) { + let extern_const_values = bcx.ccx() + .extern_const_values + .borrow(); + match extern_const_values.get().find(&did) { None => {} // Continue. Some(llval) => { return *llval; @@ -1037,8 +1053,9 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { llty.to_ref(), buf) }); - let extern_const_values = &mut bcx.ccx().extern_const_values; - extern_const_values.insert(did, llval); + let mut extern_const_values = + bcx.ccx().extern_const_values.borrow_mut(); + extern_const_values.get().insert(did, llval); llval } } @@ -1063,14 +1080,15 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: &ast::Expr) -> DatumBlock { } } -pub fn trans_local_var(bcx: @mut Block, def: ast::Def) -> Datum { +pub fn trans_local_var(bcx: @Block, def: ast::Def) -> Datum { let _icx = push_ctxt("trans_local_var"); return match def { ast::DefUpvar(nid, _, _, _) => { // Can't move upvars, so this is never a ZeroMemLastUse. let local_ty = node_id_type(bcx, nid); - match bcx.fcx.llupvars.find(&nid) { + let llupvars = bcx.fcx.llupvars.borrow(); + match llupvars.get().find(&nid) { Some(&val) => { Datum { val: val, @@ -1085,14 +1103,16 @@ pub fn trans_local_var(bcx: @mut Block, def: ast::Def) -> Datum { } } ast::DefArg(nid, _) => { - take_local(bcx, bcx.fcx.llargs, nid) + let llargs = bcx.fcx.llargs.borrow(); + take_local(bcx, llargs.get(), nid) } ast::DefLocal(nid, _) | ast::DefBinding(nid, _) => { - take_local(bcx, bcx.fcx.lllocals, nid) + let lllocals = bcx.fcx.lllocals.borrow(); + take_local(bcx, lllocals.get(), nid) } ast::DefSelf(nid, _) => { - let self_info: ValSelfData = match bcx.fcx.llself { - Some(ref self_info) => *self_info, + let self_info: ValSelfData = match bcx.fcx.llself.get() { + Some(self_info) => self_info, None => { bcx.sess().bug(format!( "trans_local_var: reference to self \ @@ -1115,7 +1135,7 @@ pub fn trans_local_var(bcx: @mut Block, def: ast::Def) -> Datum { } }; - fn take_local(bcx: @mut Block, + fn take_local(bcx: @Block, table: &HashMap, nid: ast::NodeId) -> Datum { let v = match table.find(&nid) { @@ -1160,7 +1180,11 @@ pub fn with_field_tys( ty.repr(tcx))); } Some(node_id) => { - match tcx.def_map.get_copy(&node_id) { + let opt_def = { + let def_map = tcx.def_map.borrow(); + def_map.get().get_copy(&node_id) + }; + match opt_def { ast::DefVariant(enum_id, variant_id, _) => { let variant_info = ty::enum_variant_with_id( tcx, enum_id, variant_id); @@ -1184,12 +1208,12 @@ pub fn with_field_tys( } } -fn trans_rec_or_struct(bcx: @mut Block, +fn trans_rec_or_struct(bcx: @Block, fields: &[ast::Field], base: Option<@ast::Expr>, expr_span: codemap::Span, id: ast::NodeId, - dest: Dest) -> @mut Block + dest: Dest) -> @Block { let _icx = push_ctxt("trans_rec"); let bcx = bcx; @@ -1263,10 +1287,10 @@ struct StructBaseInfo { * - `optbase` contains information on the base struct (if any) from * which remaining fields are copied; see comments on `StructBaseInfo`. */ -fn trans_adt(bcx: @mut Block, repr: &adt::Repr, discr: ty::Disr, +fn trans_adt(bcx: @Block, repr: &adt::Repr, discr: ty::Disr, fields: &[(uint, @ast::Expr)], optbase: Option, - dest: Dest) -> @mut Block { + dest: Dest) -> @Block { let _icx = push_ctxt("trans_adt"); let mut bcx = bcx; let addr = match dest { @@ -1311,7 +1335,7 @@ fn trans_adt(bcx: @mut Block, repr: &adt::Repr, discr: ty::Disr, } -fn trans_immediate_lit(bcx: @mut Block, expr: &ast::Expr, +fn trans_immediate_lit(bcx: @Block, expr: &ast::Expr, lit: ast::lit) -> DatumBlock { // must not be a string constant, that is a RvalueDpsExpr let _icx = push_ctxt("trans_immediate_lit"); @@ -1319,7 +1343,7 @@ fn trans_immediate_lit(bcx: @mut Block, expr: &ast::Expr, immediate_rvalue_bcx(bcx, consts::const_lit(bcx.ccx(), expr, lit), ty) } -fn trans_unary_datum(bcx: @mut Block, +fn trans_unary_datum(bcx: @Block, un_expr: &ast::Expr, op: ast::UnOp, sub_expr: &ast::Expr) -> DatumBlock { @@ -1329,7 +1353,10 @@ fn trans_unary_datum(bcx: @mut Block, assert!(op != ast::UnDeref); // if overloaded, would be RvalueDpsExpr - assert!(!bcx.ccx().maps.method_map.contains_key(&un_expr.id)); + { + let method_map = bcx.ccx().maps.method_map.borrow(); + assert!(!method_map.get().contains_key(&un_expr.id)); + } let un_ty = expr_ty(bcx, un_expr); let sub_ty = expr_ty(bcx, sub_expr); @@ -1379,7 +1406,7 @@ fn trans_unary_datum(bcx: @mut Block, } }; - fn trans_boxed_expr(bcx: @mut Block, + fn trans_boxed_expr(bcx: @Block, box_ty: ty::t, contents: &ast::Expr, contents_ty: ty::t, @@ -1408,7 +1435,7 @@ fn trans_unary_datum(bcx: @mut Block, } } -fn trans_addr_of(bcx: @mut Block, expr: &ast::Expr, +fn trans_addr_of(bcx: @Block, expr: &ast::Expr, subexpr: &ast::Expr) -> DatumBlock { let _icx = push_ctxt("trans_addr_of"); let mut bcx = bcx; @@ -1419,7 +1446,7 @@ fn trans_addr_of(bcx: @mut Block, expr: &ast::Expr, // Important to get types for both lhs and rhs, because one might be _|_ // and the other not. -fn trans_eager_binop(bcx: @mut Block, +fn trans_eager_binop(bcx: @Block, binop_expr: &ast::Expr, binop_ty: ty::t, op: ast::BinOp, @@ -1522,7 +1549,7 @@ fn trans_eager_binop(bcx: @mut Block, // refinement types would obviate the need for this enum lazy_binop_ty { lazy_and, lazy_or } -fn trans_lazy_binop(bcx: @mut Block, +fn trans_lazy_binop(bcx: @Block, binop_expr: &ast::Expr, op: lazy_binop_ty, a: &ast::Expr, @@ -1537,7 +1564,7 @@ fn trans_lazy_binop(bcx: @mut Block, }) }; - if past_lhs.unreachable { + if past_lhs.unreachable.get() { return immediate_rvalue_bcx(past_lhs, lhs, binop_ty); } @@ -1556,7 +1583,7 @@ fn trans_lazy_binop(bcx: @mut Block, }) }; - if past_rhs.unreachable { + if past_rhs.unreachable.get() { return immediate_rvalue_bcx(join, lhs, binop_ty); } @@ -1567,7 +1594,7 @@ fn trans_lazy_binop(bcx: @mut Block, return immediate_rvalue_bcx(join, phi, binop_ty); } -fn trans_binary(bcx: @mut Block, +fn trans_binary(bcx: @Block, binop_expr: &ast::Expr, op: ast::BinOp, lhs: &ast::Expr, @@ -1593,15 +1620,18 @@ fn trans_binary(bcx: @mut Block, } } -fn trans_overloaded_op(bcx: @mut Block, +fn trans_overloaded_op(bcx: @Block, expr: &ast::Expr, callee_id: ast::NodeId, rcvr: &ast::Expr, args: ~[@ast::Expr], ret_ty: ty::t, dest: Dest) - -> @mut Block { - let origin = bcx.ccx().maps.method_map.get_copy(&expr.id); + -> @Block { + let origin = { + let method_map = bcx.ccx().maps.method_map.borrow(); + method_map.get().get_copy(&expr.id) + }; let fty = node_id_type(bcx, callee_id); callee::trans_call_inner(bcx, expr.info(), @@ -1618,7 +1648,7 @@ fn trans_overloaded_op(bcx: @mut Block, DoAutorefArg).bcx } -fn int_cast(bcx: @mut Block, lldsttype: Type, llsrctype: Type, +fn int_cast(bcx: @Block, lldsttype: Type, llsrctype: Type, llsrc: ValueRef, signed: bool) -> ValueRef { let _icx = push_ctxt("int_cast"); unsafe { @@ -1636,7 +1666,7 @@ fn int_cast(bcx: @mut Block, lldsttype: Type, llsrctype: Type, } } -fn float_cast(bcx: @mut Block, lldsttype: Type, llsrctype: Type, +fn float_cast(bcx: @Block, lldsttype: Type, llsrctype: Type, llsrc: ValueRef) -> ValueRef { let _icx = push_ctxt("float_cast"); let srcsz = llsrctype.float_width(); @@ -1672,7 +1702,7 @@ pub fn cast_type_kind(t: ty::t) -> cast_kind { } } -fn trans_imm_cast(bcx: @mut Block, expr: &ast::Expr, +fn trans_imm_cast(bcx: @Block, expr: &ast::Expr, id: ast::NodeId) -> DatumBlock { let _icx = push_ctxt("trans_cast"); let ccx = bcx.ccx(); @@ -1747,12 +1777,12 @@ fn trans_imm_cast(bcx: @mut Block, expr: &ast::Expr, return immediate_rvalue_bcx(bcx, newval, t_out); } -fn trans_assign_op(bcx: @mut Block, +fn trans_assign_op(bcx: @Block, expr: &ast::Expr, callee_id: ast::NodeId, op: ast::BinOp, dst: &ast::Expr, - src: @ast::Expr) -> @mut Block + src: @ast::Expr) -> @Block { let _icx = push_ctxt("trans_assign_op"); let mut bcx = bcx; @@ -1763,7 +1793,11 @@ fn trans_assign_op(bcx: @mut Block, let dst_datum = unpack_datum!(bcx, trans_lvalue_unadjusted(bcx, dst)); // A user-defined operator method - if bcx.ccx().maps.method_map.find(&expr.id).is_some() { + let found = { + let method_map = bcx.ccx().maps.method_map.borrow(); + method_map.get().find(&expr.id).is_some() + }; + if found { // FIXME(#2528) evaluates the receiver twice!! let scratch = scratch_datum(bcx, dst_datum.ty, "__assign_op", false); let bcx = trans_overloaded_op(bcx, @@ -1788,16 +1822,20 @@ fn trans_assign_op(bcx: @mut Block, return result_datum.copy_to_datum(bcx, DROP_EXISTING, dst_datum); } -pub fn trans_log_level(bcx: @mut Block) -> DatumBlock { +pub fn trans_log_level(bcx: @Block) -> DatumBlock { let _icx = push_ctxt("trans_log_level"); let ccx = bcx.ccx(); let (modpath, modname) = { - let srccrate = match ccx.external_srcs.find(&bcx.fcx.id) { - Some(&src) => { - ccx.sess.cstore.get_crate_data(src.crate).name - } - None => ccx.link_meta.pkgid.name.to_managed(), + let srccrate; + { + let external_srcs = ccx.external_srcs.borrow(); + srccrate = match external_srcs.get().find(&bcx.fcx.id) { + Some(&src) => { + ccx.sess.cstore.get_crate_data(src.crate).name + } + None => ccx.link_meta.pkgid.name.to_managed(), + }; }; let mut modpath = ~[path_mod(ccx.sess.ident_of(srccrate))]; for e in bcx.fcx.path.iter() { @@ -1810,8 +1848,15 @@ pub fn trans_log_level(bcx: @mut Block) -> DatumBlock { (modpath, modname) }; - let global = if ccx.module_data.contains_key(&modname) { - ccx.module_data.get_copy(&modname) + let module_data_exists; + { + let module_data = ccx.module_data.borrow(); + module_data_exists = module_data.get().contains_key(&modname); + } + + let global = if module_data_exists { + let mut module_data = ccx.module_data.borrow_mut(); + module_data.get().get_copy(&modname) } else { let s = link::mangle_internal_name_by_path_and_seq( ccx, modpath, "loglevel"); @@ -1824,8 +1869,11 @@ pub fn trans_log_level(bcx: @mut Block) -> DatumBlock { llvm::LLVMSetInitializer(global, C_null(Type::i32())); lib::llvm::SetLinkage(global, lib::llvm::InternalLinkage); } - ccx.module_data.insert(modname, global); - global + { + let mut module_data = ccx.module_data.borrow_mut(); + module_data.get().insert(modname, global); + global + } }; return immediate_rvalue_bcx(bcx, Load(bcx, global), ty::mk_u32()); diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 5560efacfa535..21f268fb9471f 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -72,7 +72,7 @@ struct LlvmSignature { /////////////////////////////////////////////////////////////////////////// // Calls to external functions -pub fn llvm_calling_convention(ccx: &mut CrateContext, +pub fn llvm_calling_convention(ccx: &CrateContext, abis: AbiSet) -> Option { let os = ccx.sess.targ_cfg.os; let arch = ccx.sess.targ_cfg.arch; @@ -105,7 +105,7 @@ pub fn llvm_calling_convention(ccx: &mut CrateContext, } -pub fn register_foreign_item_fn(ccx: @mut CrateContext, +pub fn register_foreign_item_fn(ccx: @CrateContext, abis: AbiSet, path: &ast_map::path, foreign_item: @ast::foreign_item) -> ValueRef { @@ -146,19 +146,27 @@ pub fn register_foreign_item_fn(ccx: @mut CrateContext, // Create the LLVM value for the C extern fn let llfn_ty = lltype_for_fn_from_foreign_types(&tys); - let llfn = base::get_extern_fn(&mut ccx.externs, ccx.llmod, - lname, cc, llfn_ty); + + let llfn; + { + let mut externs = ccx.externs.borrow_mut(); + llfn = base::get_extern_fn(externs.get(), + ccx.llmod, + lname, + cc, + llfn_ty); + }; add_argument_attributes(&tys, llfn); return llfn; } -pub fn trans_native_call(bcx: @mut Block, +pub fn trans_native_call(bcx: @Block, callee_ty: ty::t, llfn: ValueRef, llretptr: ValueRef, llargs_rust: &[ValueRef], - passed_arg_tys: ~[ty::t]) -> @mut Block { + passed_arg_tys: ~[ty::t]) -> @Block { /*! * Prepares a call to a native function. This requires adapting * from the Rust argument passing rules to the native rules. @@ -341,7 +349,7 @@ pub fn trans_native_call(bcx: @mut Block, return bcx; } -pub fn trans_foreign_mod(ccx: @mut CrateContext, +pub fn trans_foreign_mod(ccx: @CrateContext, foreign_mod: &ast::foreign_mod) { let _icx = push_ctxt("foreign::trans_foreign_mod"); for &foreign_item in foreign_mod.items.iter() { @@ -360,7 +368,8 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext, } let lname = link_name(ccx, foreign_item); - ccx.item_symbols.insert(foreign_item.id, lname.to_owned()); + let mut item_symbols = ccx.item_symbols.borrow_mut(); + item_symbols.get().insert(foreign_item.id, lname.to_owned()); } } @@ -389,7 +398,7 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext, // inline the one into the other. Of course we could just generate the // correct code in the first place, but this is much simpler. -pub fn register_rust_fn_with_foreign_abi(ccx: @mut CrateContext, +pub fn register_rust_fn_with_foreign_abi(ccx: @CrateContext, sp: Span, sym: ~str, node_id: ast::NodeId) @@ -418,7 +427,7 @@ pub fn register_rust_fn_with_foreign_abi(ccx: @mut CrateContext, llfn } -pub fn trans_rust_fn_with_foreign_abi(ccx: @mut CrateContext, +pub fn trans_rust_fn_with_foreign_abi(ccx: @CrateContext, path: &ast_map::path, decl: &ast::fn_decl, body: &ast::Block, @@ -436,7 +445,7 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: @mut CrateContext, return build_wrap_fn(ccx, llrustfn, llwrapfn, &tys); } - fn build_rust_fn(ccx: @mut CrateContext, + fn build_rust_fn(ccx: @CrateContext, path: &ast_map::path, decl: &ast::fn_decl, body: &ast::Block, @@ -485,7 +494,7 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: @mut CrateContext, return llfndecl; } - unsafe fn build_wrap_fn(ccx: @mut CrateContext, + unsafe fn build_wrap_fn(ccx: @CrateContext, llrustfn: ValueRef, llwrapfn: ValueRef, tys: &ForeignTypes) { @@ -737,7 +746,7 @@ pub fn link_name(ccx: &CrateContext, i: @ast::foreign_item) -> @str { } } -fn foreign_signature(ccx: &mut CrateContext, fn_sig: &ty::FnSig, arg_tys: &[ty::t]) +fn foreign_signature(ccx: &CrateContext, fn_sig: &ty::FnSig, arg_tys: &[ty::t]) -> LlvmSignature { /*! * The ForeignSignature is the LLVM types of the arguments/return type @@ -756,12 +765,12 @@ fn foreign_signature(ccx: &mut CrateContext, fn_sig: &ty::FnSig, arg_tys: &[ty:: } } -fn foreign_types_for_id(ccx: &mut CrateContext, +fn foreign_types_for_id(ccx: &CrateContext, id: ast::NodeId) -> ForeignTypes { foreign_types_for_fn_ty(ccx, ty::node_id_to_type(ccx.tcx, id)) } -fn foreign_types_for_fn_ty(ccx: &mut CrateContext, +fn foreign_types_for_fn_ty(ccx: &CrateContext, ty: ty::t) -> ForeignTypes { let fn_sig = match ty::get(ty).sty { ty::ty_bare_fn(ref fn_ty) => fn_ty.sig.clone(), @@ -833,7 +842,7 @@ fn lltype_for_fn_from_foreign_types(tys: &ForeignTypes) -> Type { } } -pub fn lltype_for_foreign_fn(ccx: &mut CrateContext, ty: ty::t) -> Type { +pub fn lltype_for_foreign_fn(ccx: &CrateContext, ty: ty::t) -> Type { let fn_types = foreign_types_for_fn_ty(ccx, ty); lltype_for_fn_from_foreign_types(&fn_types) } diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index acbe2d13d12d0..cff0f5b316c3f 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -37,10 +37,11 @@ use util::ppaux::ty_to_short_str; use middle::trans::type_::Type; use std::c_str::ToCStr; +use std::cell::Cell; use std::libc::c_uint; use syntax::ast; -pub fn trans_free(cx: @mut Block, v: ValueRef) -> @mut Block { +pub fn trans_free(cx: @Block, v: ValueRef) -> @Block { let _icx = push_ctxt("trans_free"); callee::trans_lang_call(cx, langcall(cx, None, "", FreeFnLangItem), @@ -48,7 +49,7 @@ pub fn trans_free(cx: @mut Block, v: ValueRef) -> @mut Block { Some(expr::Ignore)).bcx } -pub fn trans_exchange_free(cx: @mut Block, v: ValueRef) -> @mut Block { +pub fn trans_exchange_free(cx: @Block, v: ValueRef) -> @Block { let _icx = push_ctxt("trans_exchange_free"); callee::trans_lang_call(cx, langcall(cx, None, "", ExchangeFreeFnLangItem), @@ -56,7 +57,7 @@ pub fn trans_exchange_free(cx: @mut Block, v: ValueRef) -> @mut Block { Some(expr::Ignore)).bcx } -pub fn take_ty(cx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { +pub fn take_ty(cx: @Block, v: ValueRef, t: ty::t) -> @Block { // NB: v is an *alias* of type t here, not a direct value. let _icx = push_ctxt("take_ty"); if ty::type_needs_drop(cx.tcx(), t) { @@ -65,7 +66,7 @@ pub fn take_ty(cx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { return cx; } -pub fn drop_ty(cx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { +pub fn drop_ty(cx: @Block, v: ValueRef, t: ty::t) -> @Block { // NB: v is an *alias* of type t here, not a direct value. let _icx = push_ctxt("drop_ty"); if ty::type_needs_drop(cx.tcx(), t) { @@ -74,14 +75,14 @@ pub fn drop_ty(cx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { return cx; } -pub fn drop_ty_immediate(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { +pub fn drop_ty_immediate(bcx: @Block, v: ValueRef, t: ty::t) -> @Block { let _icx = push_ctxt("drop_ty_immediate"); let vp = alloca(bcx, type_of(bcx.ccx(), t), ""); Store(bcx, v, vp); drop_ty(bcx, vp, t) } -pub fn free_ty(cx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { +pub fn free_ty(cx: @Block, v: ValueRef, t: ty::t) -> @Block { // NB: v is an *alias* of type t here, not a direct value. let _icx = push_ctxt("free_ty"); if ty::type_needs_drop(cx.tcx(), t) { @@ -90,7 +91,7 @@ pub fn free_ty(cx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { return cx; } -pub fn free_ty_immediate(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { +pub fn free_ty_immediate(bcx: @Block, v: ValueRef, t: ty::t) -> @Block { let _icx = push_ctxt("free_ty_immediate"); match ty::get(t).sty { ty::ty_uniq(_) | @@ -108,8 +109,8 @@ pub fn free_ty_immediate(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { } } -pub fn lazily_emit_all_tydesc_glue(ccx: @mut CrateContext, - static_ti: @mut tydesc_info) { +pub fn lazily_emit_all_tydesc_glue(ccx: @CrateContext, + static_ti: @tydesc_info) { lazily_emit_tydesc_glue(ccx, abi::tydesc_field_take_glue, static_ti); lazily_emit_tydesc_glue(ccx, abi::tydesc_field_drop_glue, static_ti); lazily_emit_tydesc_glue(ccx, abi::tydesc_field_free_glue, static_ti); @@ -173,9 +174,10 @@ pub fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t { return t; } -pub fn lazily_emit_simplified_tydesc_glue(ccx: @mut CrateContext, +pub fn lazily_emit_simplified_tydesc_glue(ccx: @CrateContext, field: uint, - ti: &mut tydesc_info) -> bool { + ti: &tydesc_info) + -> bool { let _icx = push_ctxt("lazily_emit_simplified_tydesc_glue"); let simpl = simplified_glue_type(ccx.tcx, field, ti.ty); if simpl != ti.ty { @@ -183,13 +185,13 @@ pub fn lazily_emit_simplified_tydesc_glue(ccx: @mut CrateContext, lazily_emit_tydesc_glue(ccx, field, simpl_ti); { if field == abi::tydesc_field_take_glue { - ti.take_glue = simpl_ti.take_glue; + ti.take_glue.set(simpl_ti.take_glue.get()); } else if field == abi::tydesc_field_drop_glue { - ti.drop_glue = simpl_ti.drop_glue; + ti.drop_glue.set(simpl_ti.drop_glue.get()); } else if field == abi::tydesc_field_free_glue { - ti.free_glue = simpl_ti.free_glue; + ti.free_glue.set(simpl_ti.free_glue.get()); } else if field == abi::tydesc_field_visit_glue { - ti.visit_glue = simpl_ti.visit_glue; + ti.visit_glue.set(simpl_ti.visit_glue.get()); } } return true; @@ -198,9 +200,9 @@ pub fn lazily_emit_simplified_tydesc_glue(ccx: @mut CrateContext, } -pub fn lazily_emit_tydesc_glue(ccx: @mut CrateContext, +pub fn lazily_emit_tydesc_glue(ccx: @CrateContext, field: uint, - ti: @mut tydesc_info) { + ti: @tydesc_info) { let _icx = push_ctxt("lazily_emit_tydesc_glue"); let llfnty = Type::glue_fn(type_of(ccx, ti.ty).ptr_to()); @@ -209,52 +211,52 @@ pub fn lazily_emit_tydesc_glue(ccx: @mut CrateContext, } if field == abi::tydesc_field_take_glue { - match ti.take_glue { + match ti.take_glue.get() { Some(_) => (), None => { debug!("+++ lazily_emit_tydesc_glue TAKE {}", ppaux::ty_to_str(ccx.tcx, ti.ty)); let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, "take"); - ti.take_glue = Some(glue_fn); + ti.take_glue.set(Some(glue_fn)); make_generic_glue(ccx, ti.ty, glue_fn, make_take_glue, "take"); debug!("--- lazily_emit_tydesc_glue TAKE {}", ppaux::ty_to_str(ccx.tcx, ti.ty)); } } } else if field == abi::tydesc_field_drop_glue { - match ti.drop_glue { + match ti.drop_glue.get() { Some(_) => (), None => { debug!("+++ lazily_emit_tydesc_glue DROP {}", ppaux::ty_to_str(ccx.tcx, ti.ty)); let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, "drop"); - ti.drop_glue = Some(glue_fn); + ti.drop_glue.set(Some(glue_fn)); make_generic_glue(ccx, ti.ty, glue_fn, make_drop_glue, "drop"); debug!("--- lazily_emit_tydesc_glue DROP {}", ppaux::ty_to_str(ccx.tcx, ti.ty)); } } } else if field == abi::tydesc_field_free_glue { - match ti.free_glue { + match ti.free_glue.get() { Some(_) => (), None => { debug!("+++ lazily_emit_tydesc_glue FREE {}", ppaux::ty_to_str(ccx.tcx, ti.ty)); let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, "free"); - ti.free_glue = Some(glue_fn); + ti.free_glue.set(Some(glue_fn)); make_generic_glue(ccx, ti.ty, glue_fn, make_free_glue, "free"); debug!("--- lazily_emit_tydesc_glue FREE {}", ppaux::ty_to_str(ccx.tcx, ti.ty)); } } } else if field == abi::tydesc_field_visit_glue { - match ti.visit_glue { + match ti.visit_glue.get() { Some(_) => (), None => { debug!("+++ lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_str(ccx.tcx, ti.ty)); let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, "visit"); - ti.visit_glue = Some(glue_fn); + ti.visit_glue.set(Some(glue_fn)); make_generic_glue(ccx, ti.ty, glue_fn, make_visit_glue, "visit"); debug!("--- lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_str(ccx.tcx, ti.ty)); @@ -264,29 +266,29 @@ pub fn lazily_emit_tydesc_glue(ccx: @mut CrateContext, } // See [Note-arg-mode] -pub fn call_tydesc_glue_full(bcx: @mut Block, +pub fn call_tydesc_glue_full(bcx: @Block, v: ValueRef, tydesc: ValueRef, field: uint, - static_ti: Option<@mut tydesc_info>) { + static_ti: Option<@tydesc_info>) { let _icx = push_ctxt("call_tydesc_glue_full"); let ccx = bcx.ccx(); // NB: Don't short-circuit even if this block is unreachable because // GC-based cleanup needs to the see that the roots are live. - if bcx.unreachable && !ccx.sess.no_landing_pads() { return; } + if bcx.unreachable.get() && !ccx.sess.no_landing_pads() { return; } let static_glue_fn = match static_ti { None => None, Some(sti) => { lazily_emit_tydesc_glue(ccx, field, sti); if field == abi::tydesc_field_take_glue { - sti.take_glue + sti.take_glue.get() } else if field == abi::tydesc_field_drop_glue { - sti.drop_glue + sti.drop_glue.get() } else if field == abi::tydesc_field_free_glue { - sti.free_glue + sti.free_glue.get() } else if field == abi::tydesc_field_visit_glue { - sti.visit_glue + sti.visit_glue.get() } else { None } @@ -323,15 +325,15 @@ pub fn call_tydesc_glue_full(bcx: @mut Block, } // See [Note-arg-mode] -pub fn call_tydesc_glue(cx: @mut Block, v: ValueRef, t: ty::t, field: uint) - -> @mut Block { +pub fn call_tydesc_glue(cx: @Block, v: ValueRef, t: ty::t, field: uint) + -> @Block { let _icx = push_ctxt("call_tydesc_glue"); let ti = get_tydesc(cx.ccx(), t); call_tydesc_glue_full(cx, v, ti.tydesc, field, Some(ti)); return cx; } -pub fn make_visit_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { +pub fn make_visit_glue(bcx: @Block, v: ValueRef, t: ty::t) -> @Block { let _icx = push_ctxt("make_visit_glue"); with_scope(bcx, None, "visitor cleanup", |bcx| { let mut bcx = bcx; @@ -350,7 +352,7 @@ pub fn make_visit_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { }) } -pub fn make_free_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { +pub fn make_free_glue(bcx: @Block, v: ValueRef, t: ty::t) -> @Block { // NB: v0 is an *alias* of type t here, not a direct value. let _icx = push_ctxt("make_free_glue"); match ty::get(t).sty { @@ -387,8 +389,8 @@ pub fn make_free_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { } } -pub fn trans_struct_drop_flag(bcx: @mut Block, t: ty::t, v0: ValueRef, dtor_did: ast::DefId, - class_did: ast::DefId, substs: &ty::substs) -> @mut Block { +pub fn trans_struct_drop_flag(bcx: @Block, t: ty::t, v0: ValueRef, dtor_did: ast::DefId, + class_did: ast::DefId, substs: &ty::substs) -> @Block { let repr = adt::represent_type(bcx.ccx(), t); let drop_flag = adt::trans_drop_flag_ptr(bcx, repr, v0); with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag)), |cx| { @@ -396,8 +398,8 @@ pub fn trans_struct_drop_flag(bcx: @mut Block, t: ty::t, v0: ValueRef, dtor_did: }) } -pub fn trans_struct_drop(bcx: @mut Block, t: ty::t, v0: ValueRef, dtor_did: ast::DefId, - class_did: ast::DefId, substs: &ty::substs) -> @mut Block { +pub fn trans_struct_drop(bcx: @Block, t: ty::t, v0: ValueRef, dtor_did: ast::DefId, + class_did: ast::DefId, substs: &ty::substs) -> @Block { let repr = adt::represent_type(bcx.ccx(), t); // Find and call the actual destructor @@ -434,7 +436,7 @@ pub fn trans_struct_drop(bcx: @mut Block, t: ty::t, v0: ValueRef, dtor_did: ast: }) } -pub fn make_drop_glue(bcx: @mut Block, v0: ValueRef, t: ty::t) -> @mut Block { +pub fn make_drop_glue(bcx: @Block, v0: ValueRef, t: ty::t) -> @Block { // NB: v0 is an *alias* of type t here, not a direct value. let _icx = push_ctxt("make_drop_glue"); let ccx = bcx.ccx(); @@ -505,10 +507,10 @@ pub fn make_drop_glue(bcx: @mut Block, v0: ValueRef, t: ty::t) -> @mut Block { } // box_ptr_ptr is optional, it is constructed if not supplied. -pub fn decr_refcnt_maybe_free(bcx: @mut Block, box_ptr: ValueRef, +pub fn decr_refcnt_maybe_free(bcx: @Block, box_ptr: ValueRef, box_ptr_ptr: Option, t: ty::t) - -> @mut Block { + -> @Block { let _icx = push_ctxt("decr_refcnt_maybe_free"); let ccx = bcx.ccx(); @@ -534,7 +536,7 @@ pub fn decr_refcnt_maybe_free(bcx: @mut Block, box_ptr: ValueRef, } -pub fn make_take_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { +pub fn make_take_glue(bcx: @Block, v: ValueRef, t: ty::t) -> @Block { let _icx = push_ctxt("make_take_glue"); // NB: v is a *pointer* to type t here, not a direct value. match ty::get(t).sty { @@ -575,7 +577,7 @@ pub fn make_take_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { } } -pub fn incr_refcnt_of_boxed(cx: @mut Block, box_ptr: ValueRef) { +pub fn incr_refcnt_of_boxed(cx: @Block, box_ptr: ValueRef) { let _icx = push_ctxt("incr_refcnt_of_boxed"); let ccx = cx.ccx(); let rc_ptr = GEPi(cx, box_ptr, [0u, abi::box_field_refcnt]); @@ -586,10 +588,10 @@ pub fn incr_refcnt_of_boxed(cx: @mut Block, box_ptr: ValueRef) { // Generates the declaration for (but doesn't emit) a type descriptor. -pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info { +pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info { // If emit_tydescs already ran, then we shouldn't be creating any new // tydescs. - assert!(!ccx.finished_tydescs); + assert!(!ccx.finished_tydescs.get()); let llty = type_of(ccx, t); @@ -623,26 +625,26 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info { let ty_name = C_estr_slice(ccx, ppaux::ty_to_str(ccx.tcx, t).to_managed()); - let inf = @mut tydesc_info { + let inf = @tydesc_info { ty: t, tydesc: gvar, size: llsize, align: llalign, borrow_offset: borrow_offset, name: ty_name, - take_glue: None, - drop_glue: None, - free_glue: None, - visit_glue: None + take_glue: Cell::new(None), + drop_glue: Cell::new(None), + free_glue: Cell::new(None), + visit_glue: Cell::new(None), }; debug!("--- declare_tydesc {}", ppaux::ty_to_str(ccx.tcx, t)); return inf; } -pub type glue_helper<'a> = 'a |@mut Block, ValueRef, ty::t| - -> @mut Block; +pub type glue_helper<'a> = 'a |@Block, ValueRef, ty::t| + -> @Block; -pub fn declare_generic_glue(ccx: &mut CrateContext, t: ty::t, llfnty: Type, +pub fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type, name: &str) -> ValueRef { let _icx = push_ctxt("declare_generic_glue"); let fn_nm = mangle_internal_name_by_type_and_seq(ccx, t, (~"glue_" + name)).to_managed(); @@ -652,7 +654,7 @@ pub fn declare_generic_glue(ccx: &mut CrateContext, t: ty::t, llfnty: Type, return llfn; } -pub fn make_generic_glue_inner(ccx: @mut CrateContext, +pub fn make_generic_glue_inner(ccx: @CrateContext, t: ty::t, llfn: ValueRef, helper: glue_helper) @@ -660,7 +662,7 @@ pub fn make_generic_glue_inner(ccx: @mut CrateContext, let _icx = push_ctxt("make_generic_glue_inner"); let fcx = new_fn_ctxt(ccx, ~[], llfn, ty::mk_nil(), None); lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage); - ccx.stats.n_glues_created += 1u; + ccx.stats.n_glues_created.set(ccx.stats.n_glues_created.get() + 1u); // All glue functions take values passed *by alias*; this is a // requirement since in many contexts glue is invoked indirectly and // the caller has no idea if it's dealing with something that can be @@ -669,7 +671,7 @@ pub fn make_generic_glue_inner(ccx: @mut CrateContext, // llfn is expected be declared to take a parameter of the appropriate // type, so we don't need to explicitly cast the function parameter. - let bcx = fcx.entry_bcx.unwrap(); + let bcx = fcx.entry_bcx.get().unwrap(); let rawptr0_arg = fcx.arg_pos(0u); let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, rawptr0_arg as c_uint) }; let bcx = helper(bcx, llrawptr0, t); @@ -679,7 +681,7 @@ pub fn make_generic_glue_inner(ccx: @mut CrateContext, return llfn; } -pub fn make_generic_glue(ccx: @mut CrateContext, +pub fn make_generic_glue(ccx: @CrateContext, t: ty::t, llfn: ValueRef, helper: glue_helper, @@ -691,13 +693,13 @@ pub fn make_generic_glue(ccx: @mut CrateContext, make_generic_glue_inner(ccx, t, llfn, helper) } -pub fn emit_tydescs(ccx: &mut CrateContext) { +pub fn emit_tydescs(ccx: &CrateContext) { let _icx = push_ctxt("emit_tydescs"); // As of this point, allow no more tydescs to be created. - ccx.finished_tydescs = true; + ccx.finished_tydescs.set(true); let glue_fn_ty = Type::generic_glue_fn(ccx).ptr_to(); - let tyds = &mut ccx.tydescs; - for (_, &val) in tyds.iter() { + let mut tyds = ccx.tydescs.borrow_mut(); + for (_, &val) in tyds.get().iter() { let ti = val; // Each of the glue functions needs to be cast to a generic type @@ -705,41 +707,61 @@ pub fn emit_tydescs(ccx: &mut CrateContext) { // tydesc type. Then we'll recast each function to its real type when // calling it. let take_glue = - match ti.take_glue { - None => { ccx.stats.n_null_glues += 1u; C_null(glue_fn_ty) } + match ti.take_glue.get() { + None => { + ccx.stats.n_null_glues.set(ccx.stats.n_null_glues.get() + + 1); + C_null(glue_fn_ty) + } Some(v) => { unsafe { - ccx.stats.n_real_glues += 1u; + ccx.stats.n_real_glues.set(ccx.stats.n_real_glues.get() + + 1); llvm::LLVMConstPointerCast(v, glue_fn_ty.to_ref()) } } }; let drop_glue = - match ti.drop_glue { - None => { ccx.stats.n_null_glues += 1u; C_null(glue_fn_ty) } + match ti.drop_glue.get() { + None => { + ccx.stats.n_null_glues.set(ccx.stats.n_null_glues.get() + + 1u); + C_null(glue_fn_ty) + } Some(v) => { unsafe { - ccx.stats.n_real_glues += 1u; + ccx.stats.n_real_glues.set(ccx.stats.n_real_glues.get() + + 1); llvm::LLVMConstPointerCast(v, glue_fn_ty.to_ref()) } } }; let free_glue = - match ti.free_glue { - None => { ccx.stats.n_null_glues += 1u; C_null(glue_fn_ty) } + match ti.free_glue.get() { + None => { + ccx.stats.n_null_glues.set(ccx.stats.n_null_glues.get() + + 1u); + C_null(glue_fn_ty) + } Some(v) => { unsafe { - ccx.stats.n_real_glues += 1u; + ccx.stats.n_real_glues.set(ccx.stats.n_real_glues.get() + + 1); llvm::LLVMConstPointerCast(v, glue_fn_ty.to_ref()) } } }; let visit_glue = - match ti.visit_glue { - None => { ccx.stats.n_null_glues += 1u; C_null(glue_fn_ty) } + match ti.visit_glue.get() { + None => { + ccx.stats.n_null_glues.set(ccx.stats.n_null_glues.get() + + 1u); + C_null(glue_fn_ty) + } Some(v) => { unsafe { - ccx.stats.n_real_glues += 1u; + ccx.stats.n_real_glues.set(ccx.stats.n_real_glues.get() + + 1); llvm::LLVMConstPointerCast(v, glue_fn_ty.to_ref()) } } diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index a3f6b7db326aa..bea58929323aa 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -23,21 +23,24 @@ use syntax::ast_map::path_name; use syntax::ast_util::local_def; use syntax::attr; -pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::DefId) +pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::DefId) -> ast::DefId { let _icx = push_ctxt("maybe_instantiate_inline"); - match ccx.external.find(&fn_id) { - Some(&Some(node_id)) => { - // Already inline - debug!("maybe_instantiate_inline({}): already inline as node id {}", - ty::item_path_str(ccx.tcx, fn_id), node_id); - return local_def(node_id); - } - Some(&None) => { - return fn_id; // Not inlinable - } - None => { - // Not seen yet + { + let external = ccx.external.borrow(); + match external.get().find(&fn_id) { + Some(&Some(node_id)) => { + // Already inline + debug!("maybe_instantiate_inline({}): already inline as node id {}", + ty::item_path_str(ccx.tcx, fn_id), node_id); + return local_def(node_id); + } + Some(&None) => { + return fn_id; // Not inlinable + } + None => { + // Not seen yet + } } } @@ -49,13 +52,19 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::DefId) }); return match csearch_result { csearch::not_found => { - ccx.external.insert(fn_id, None); + let mut external = ccx.external.borrow_mut(); + external.get().insert(fn_id, None); fn_id } csearch::found(ast::ii_item(item)) => { - ccx.external.insert(fn_id, Some(item.id)); - ccx.external_srcs.insert(item.id, fn_id); - ccx.stats.n_inlines += 1; + { + let mut external = ccx.external.borrow_mut(); + let mut external_srcs = ccx.external_srcs.borrow_mut(); + external.get().insert(fn_id, Some(item.id)); + external_srcs.get().insert(item.id, fn_id); + } + + ccx.stats.n_inlines.set(ccx.stats.n_inlines.get() + 1); trans_item(ccx, item); // We're bringing an external global into this crate, but we don't @@ -82,13 +91,22 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::DefId) local_def(item.id) } csearch::found(ast::ii_foreign(item)) => { - ccx.external.insert(fn_id, Some(item.id)); - ccx.external_srcs.insert(item.id, fn_id); - local_def(item.id) + { + let mut external = ccx.external.borrow_mut(); + let mut external_srcs = ccx.external_srcs.borrow_mut(); + external.get().insert(fn_id, Some(item.id)); + external_srcs.get().insert(item.id, fn_id); + } + local_def(item.id) } csearch::found_parent(parent_id, ast::ii_item(item)) => { - ccx.external.insert(parent_id, Some(item.id)); - ccx.external_srcs.insert(item.id, parent_id); + { + let mut external = ccx.external.borrow_mut(); + let mut external_srcs = ccx.external_srcs.borrow_mut(); + external.get().insert(parent_id, Some(item.id)); + external_srcs.get().insert(item.id, parent_id); + } + let mut my_id = 0; match item.node { ast::item_enum(_, _) => { @@ -96,14 +114,16 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::DefId) let vs_there = ty::enum_variants(ccx.tcx, parent_id); for (here, there) in vs_here.iter().zip(vs_there.iter()) { if there.id == fn_id { my_id = here.id.node; } - ccx.external.insert(there.id, Some(here.id.node)); + let mut external = ccx.external.borrow_mut(); + external.get().insert(there.id, Some(here.id.node)); } } ast::item_struct(ref struct_def, _) => { match struct_def.ctor_id { None => {} Some(ctor_id) => { - let _ = ccx.external.insert(fn_id, Some(ctor_id)); + let mut external = ccx.external.borrow_mut(); + let _ = external.get().insert(fn_id, Some(ctor_id)); my_id = ctor_id; } } @@ -119,9 +139,15 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::DefId) with a non-item parent"); } csearch::found(ast::ii_method(impl_did, is_provided, mth)) => { - ccx.stats.n_inlines += 1; - ccx.external.insert(fn_id, Some(mth.id)); - ccx.external_srcs.insert(mth.id, fn_id); + { + let mut external = ccx.external.borrow_mut(); + let mut external_srcs = ccx.external_srcs.borrow_mut(); + external.get().insert(fn_id, Some(mth.id)); + external_srcs.get().insert(mth.id, fn_id); + } + + ccx.stats.n_inlines.set(ccx.stats.n_inlines.get() + 1); + // If this is a default method, we can't look up the // impl type. But we aren't going to translate anyways, so don't. if is_provided { return local_def(mth.id); } diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index f83bdd799598e..02df3ff9c2046 100644 --- a/src/librustc/middle/trans/intrinsic.rs +++ b/src/librustc/middle/trans/intrinsic.rs @@ -29,7 +29,7 @@ use util::ppaux::ty_to_str; use middle::trans::machine::llsize_of; use middle::trans::type_::Type; -pub fn trans_intrinsic(ccx: @mut CrateContext, +pub fn trans_intrinsic(ccx: @CrateContext, decl: ValueRef, item: &ast::foreign_item, path: ast_map::path, @@ -38,7 +38,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, ref_id: Option) { debug!("trans_intrinsic(item.ident={})", ccx.sess.str_of(item.ident)); - fn simple_llvm_intrinsic(bcx: @mut Block, name: &'static str, num_args: uint) { + fn simple_llvm_intrinsic(bcx: @Block, name: &'static str, num_args: uint) { assert!(num_args <= 4); let mut args = [0 as ValueRef, ..4]; let first_real_arg = bcx.fcx.arg_pos(0u); @@ -50,7 +50,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, Ret(bcx, llcall); } - fn with_overflow_instrinsic(bcx: @mut Block, name: &'static str, t: ty::t) { + fn with_overflow_instrinsic(bcx: @Block, name: &'static str, t: ty::t) { let first_real_arg = bcx.fcx.arg_pos(0u); let a = get_param(bcx.fcx.llfn, first_real_arg); let b = get_param(bcx.fcx.llfn, first_real_arg + 1); @@ -73,7 +73,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, } } - fn copy_intrinsic(bcx: @mut Block, allow_overlap: bool, tp_ty: ty::t) { + fn copy_intrinsic(bcx: @Block, allow_overlap: bool, tp_ty: ty::t) { let ccx = bcx.ccx(); let lltp_ty = type_of::type_of(ccx, tp_ty); let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32); @@ -104,7 +104,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, RetVoid(bcx); } - fn memset_intrinsic(bcx: @mut Block, tp_ty: ty::t) { + fn memset_intrinsic(bcx: @Block, tp_ty: ty::t) { let ccx = bcx.ccx(); let lltp_ty = type_of::type_of(ccx, tp_ty); let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32); @@ -126,7 +126,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, RetVoid(bcx); } - fn count_zeros_intrinsic(bcx: @mut Block, name: &'static str) { + fn count_zeros_intrinsic(bcx: @Block, name: &'static str) { let x = get_param(bcx.fcx.llfn, bcx.fcx.arg_pos(0u)); let y = C_i1(false); let llfn = bcx.ccx().intrinsics.get_copy(&name); @@ -148,7 +148,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, set_always_inline(fcx.llfn); - let mut bcx = fcx.entry_bcx.unwrap(); + let mut bcx = fcx.entry_bcx.get().unwrap(); let first_real_arg = fcx.arg_pos(0u); let nm = ccx.sess.str_of(item.ident); @@ -290,7 +290,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, // NB: This needs to be kept in lockstep with the TypeId struct in // libstd/unstable/intrinsics.rs let val = C_named_struct(type_of::type_of(ccx, output_type), [C_u64(hash)]); - match bcx.fcx.llretptr { + match bcx.fcx.llretptr.get() { Some(ptr) => { Store(bcx, val, ptr); RetVoid(bcx); @@ -301,7 +301,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, "init" => { let tp_ty = substs.tys[0]; let lltp_ty = type_of::type_of(ccx, tp_ty); - match bcx.fcx.llretptr { + match bcx.fcx.llretptr.get() { Some(ptr) => { Store(bcx, C_null(lltp_ty), ptr); RetVoid(bcx); } None if ty::type_is_nil(tp_ty) => RetVoid(bcx), None => Ret(bcx, C_null(lltp_ty)), @@ -349,7 +349,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, if !ty::type_is_voidish(ccx.tcx, out_type) { let llsrcval = get_param(decl, first_real_arg); if type_is_immediate(ccx, in_type) { - match fcx.llretptr { + match fcx.llretptr.get() { Some(llretptr) => { Store(bcx, llsrcval, PointerCast(bcx, llretptr, llintype.ptr_to())); RetVoid(bcx); @@ -379,7 +379,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, // NB: Do not use a Load and Store here. This causes massive // code bloat when `transmute` is used on large structural // types. - let lldestptr = fcx.llretptr.unwrap(); + let lldestptr = fcx.llretptr.get().unwrap(); let lldestptr = PointerCast(bcx, lldestptr, Type::i8p()); let llsrcptr = PointerCast(bcx, llsrcval, Type::i8p()); diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index dff9f55e04ccc..f4df98870bbdf 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -46,7 +46,7 @@ for non-monomorphized methods only. Other methods will be generated once they are invoked with specific type parameters, see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`. */ -pub fn trans_impl(ccx: @mut CrateContext, +pub fn trans_impl(ccx: @CrateContext, path: path, name: ast::Ident, methods: &[@ast::method], @@ -97,7 +97,7 @@ pub fn trans_impl(ccx: @mut CrateContext, /// * `impl_id`: the node ID of the impl this method is inside /// /// XXX(pcwalton) Can we take `path` by reference? -pub fn trans_method(ccx: @mut CrateContext, +pub fn trans_method(ccx: @CrateContext, path: path, method: &ast::method, param_substs: Option<@param_substs>, @@ -138,7 +138,7 @@ pub fn trans_method(ccx: @mut CrateContext, []); } -pub fn trans_self_arg(bcx: @mut Block, +pub fn trans_self_arg(bcx: @Block, base: &ast::Expr, temp_cleanups: &mut ~[ValueRef], mentry: typeck::method_map_entry) -> Result { @@ -154,7 +154,7 @@ pub fn trans_self_arg(bcx: @mut Block, DontAutorefArg) } -pub fn trans_method_callee(bcx: @mut Block, +pub fn trans_method_callee(bcx: @Block, callee_id: ast::NodeId, this: &ast::Expr, mentry: typeck::method_map_entry) @@ -212,7 +212,7 @@ pub fn trans_method_callee(bcx: @mut Block, } } -pub fn trans_static_method_callee(bcx: @mut Block, +pub fn trans_static_method_callee(bcx: @Block, method_id: ast::DefId, trait_id: ast::DefId, callee_id: ast::NodeId) @@ -262,8 +262,11 @@ pub fn trans_static_method_callee(bcx: @mut Block, debug!("trans_static_method_callee: method_id={:?}, callee_id={:?}, \ name={}", method_id, callee_id, ccx.sess.str_of(mname)); - let vtbls = resolve_vtables_in_fn_ctxt( - bcx.fcx, ccx.maps.vtable_map.get_copy(&callee_id)); + let vtbls = { + let vtable_map = ccx.maps.vtable_map.borrow(); + vtable_map.get().get_copy(&callee_id) + }; + let vtbls = resolve_vtables_in_fn_ctxt(bcx.fcx, vtbls); match vtbls[bound_index][0] { typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => { @@ -293,25 +296,30 @@ pub fn trans_static_method_callee(bcx: @mut Block, } } -pub fn method_with_name(ccx: &mut CrateContext, +pub fn method_with_name(ccx: &CrateContext, impl_id: ast::DefId, name: ast::Name) -> ast::DefId { - let meth_id_opt = ccx.impl_method_cache.find_copy(&(impl_id, name)); - match meth_id_opt { - Some(m) => return m, - None => {} + { + let impl_method_cache = ccx.impl_method_cache.borrow(); + let meth_id_opt = impl_method_cache.get().find_copy(&(impl_id, name)); + match meth_id_opt { + Some(m) => return m, + None => {} + } } - let imp = ccx.tcx.impls.find(&impl_id) + let impls = ccx.tcx.impls.borrow(); + let imp = impls.get().find(&impl_id) .expect("could not find impl while translating"); let meth = imp.methods.iter().find(|m| m.ident.name == name) .expect("could not find method while translating"); - ccx.impl_method_cache.insert((impl_id, name), meth.def_id); + let mut impl_method_cache = ccx.impl_method_cache.borrow_mut(); + impl_method_cache.get().insert((impl_id, name), meth.def_id); meth.def_id } -pub fn trans_monomorphized_callee(bcx: @mut Block, +pub fn trans_monomorphized_callee(bcx: @Block, callee_id: ast::NodeId, base: &ast::Expr, mentry: typeck::method_map_entry, @@ -368,7 +376,7 @@ pub fn trans_monomorphized_callee(bcx: @mut Block, } -pub fn combine_impl_and_methods_tps(bcx: @mut Block, +pub fn combine_impl_and_methods_tps(bcx: @Block, mth_did: ast::DefId, callee_id: ast::NodeId, rcvr_substs: &[ty::t], @@ -417,7 +425,7 @@ pub fn combine_impl_and_methods_tps(bcx: @mut Block, return (ty_substs, vtables); } -pub fn trans_trait_callee(bcx: @mut Block, +pub fn trans_trait_callee(bcx: @Block, callee_id: ast::NodeId, n_method: uint, self_expr: &ast::Expr) @@ -459,7 +467,7 @@ pub fn trans_trait_callee(bcx: @mut Block, Some(self_scratch.val)) } -pub fn trans_trait_callee_from_llval(bcx: @mut Block, +pub fn trans_trait_callee_from_llval(bcx: @Block, callee_ty: ty::t, n_method: uint, llpair: ValueRef, @@ -505,7 +513,7 @@ pub fn trans_trait_callee_from_llval(bcx: @mut Block, }; } -pub fn vtable_id(ccx: @mut CrateContext, +pub fn vtable_id(ccx: @CrateContext, origin: &typeck::vtable_origin) -> mono_id { match origin { @@ -530,7 +538,7 @@ pub fn vtable_id(ccx: @mut CrateContext, /// Creates a returns a dynamic vtable for the given type and vtable origin. /// This is used only for objects. -pub fn get_vtable(bcx: @mut Block, +pub fn get_vtable(bcx: @Block, self_ty: ty::t, origins: typeck::vtable_param_res) -> ValueRef { @@ -539,9 +547,12 @@ pub fn get_vtable(bcx: @mut Block, // Check the cache. let hash_id = (self_ty, vtable_id(ccx, &origins[0])); - match ccx.vtables.find(&hash_id) { - Some(&val) => { return val } - None => { } + { + let vtables = ccx.vtables.borrow(); + match vtables.get().find(&hash_id) { + Some(&val) => { return val } + None => { } + } } // Not in the cache. Actually build it. @@ -559,12 +570,14 @@ pub fn get_vtable(bcx: @mut Block, glue::lazily_emit_all_tydesc_glue(ccx, tydesc); let vtable = make_vtable(ccx, tydesc, methods); - ccx.vtables.insert(hash_id, vtable); + + let mut vtables = ccx.vtables.borrow_mut(); + vtables.get().insert(hash_id, vtable); return vtable; } /// Helper function to declare and initialize the vtable. -pub fn make_vtable(ccx: &mut CrateContext, +pub fn make_vtable(ccx: &CrateContext, tydesc: &tydesc_info, ptrs: &[ValueRef]) -> ValueRef { @@ -588,7 +601,7 @@ pub fn make_vtable(ccx: &mut CrateContext, } } -fn emit_vtable_methods(bcx: @mut Block, +fn emit_vtable_methods(bcx: @Block, impl_id: ast::DefId, substs: &[ty::t], vtables: typeck::vtable_res) @@ -629,12 +642,12 @@ fn emit_vtable_methods(bcx: @mut Block, }) } -pub fn trans_trait_cast(bcx: @mut Block, +pub fn trans_trait_cast(bcx: @Block, val: &ast::Expr, id: ast::NodeId, dest: expr::Dest, _store: ty::TraitStore) - -> @mut Block { + -> @Block { let mut bcx = bcx; let _icx = push_ctxt("impl::trans_cast"); @@ -660,8 +673,11 @@ pub fn trans_trait_cast(bcx: @mut Block, // Store the vtable into the pair or triple. // This is structured a bit funny because of dynamic borrow failures. let origins = { - let res = ccx.maps.vtable_map.get(&id); - let res = resolve_vtables_in_fn_ctxt(bcx.fcx, *res); + let res = { + let vtable_map = ccx.maps.vtable_map.borrow(); + *vtable_map.get().get(&id) + }; + let res = resolve_vtables_in_fn_ctxt(bcx.fcx, res); res[0] }; let vtable = get_vtable(bcx, v_ty, origins); diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 3350a52e2bc2d..cf6bebbb1a2a7 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -28,7 +28,7 @@ use syntax::ast; use syntax::ast_map; use syntax::ast_util::local_def; -pub fn monomorphic_fn(ccx: @mut CrateContext, +pub fn monomorphic_fn(ccx: @CrateContext, fn_id: ast::DefId, real_substs: &ty::substs, vtables: Option, @@ -76,13 +76,16 @@ pub fn monomorphic_fn(ccx: @mut CrateContext, psubsts.repr(ccx.tcx), hash_id); - match ccx.monomorphized.find(&hash_id) { - Some(&val) => { - debug!("leaving monomorphic fn {}", - ty::item_path_str(ccx.tcx, fn_id)); - return (val, must_cast); - } - None => () + { + let monomorphized = ccx.monomorphized.borrow(); + match monomorphized.get().find(&hash_id) { + Some(&val) => { + debug!("leaving monomorphic fn {}", + ty::item_path_str(ccx.tcx, fn_id)); + return (val, must_cast); + } + None => () + } } let tpt = ty::lookup_item_type(ccx.tcx, fn_id); @@ -179,19 +182,24 @@ pub fn monomorphic_fn(ccx: @mut CrateContext, _ => fail!("expected bare rust fn or an intrinsic") }; - ccx.stats.n_monos += 1; + ccx.stats.n_monos.set(ccx.stats.n_monos.get() + 1); - let depth = match ccx.monomorphizing.find(&fn_id) { - Some(&d) => d, None => 0 - }; - // Random cut-off -- code that needs to instantiate the same function - // recursively more than thirty times can probably safely be assumed to be - // causing an infinite expansion. - if depth > 30 { - ccx.sess.span_fatal( - span, "overly deep expansion of inlined function"); + let depth; + { + let mut monomorphizing = ccx.monomorphizing.borrow_mut(); + depth = match monomorphizing.get().find(&fn_id) { + Some(&d) => d, None => 0 + }; + + // Random cut-off -- code that needs to instantiate the same function + // recursively more than thirty times can probably safely be assumed + // to be causing an infinite expansion. + if depth > 30 { + ccx.sess.span_fatal( + span, "overly deep expansion of inlined function"); + } + monomorphizing.get().insert(fn_id, depth + 1); } - ccx.monomorphizing.insert(fn_id, depth + 1); let (_, elt) = gensym_name(ccx.sess.str_of(name)); let mut pt = (*pt).clone(); @@ -201,7 +209,8 @@ pub fn monomorphic_fn(ccx: @mut CrateContext, let mk_lldecl = || { let lldecl = decl_internal_rust_fn(ccx, f.sig.inputs, f.sig.output, s); - ccx.monomorphized.insert(hash_id, lldecl); + let mut monomorphized = ccx.monomorphized.borrow_mut(); + monomorphized.get().insert(hash_id, lldecl); lldecl }; @@ -288,13 +297,17 @@ pub fn monomorphic_fn(ccx: @mut CrateContext, ccx.tcx.sess.bug(format!("Can't monomorphize a {:?}", map_node)) } }; - ccx.monomorphizing.insert(fn_id, depth); + + { + let mut monomorphizing = ccx.monomorphizing.borrow_mut(); + monomorphizing.get().insert(fn_id, depth); + } debug!("leaving monomorphic fn {}", ty::item_path_str(ccx.tcx, fn_id)); (lldecl, must_cast) } -pub fn make_mono_id(ccx: @mut CrateContext, +pub fn make_mono_id(ccx: @CrateContext, item: ast::DefId, substs: ¶m_substs) -> mono_id { // FIXME (possibly #5801): Need a lot of type hints to get diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 5278ff1549543..c30f421c9e54f 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -37,9 +37,9 @@ use middle::trans::type_::Type; pub struct Reflector { visitor_val: ValueRef, visitor_methods: @~[@ty::Method], - final_bcx: @mut Block, + final_bcx: @Block, tydesc_ty: Type, - bcx: @mut Block + bcx: @Block } impl Reflector { @@ -306,11 +306,11 @@ impl Reflector { // llvm::LLVMGetParam(llfdecl, fcx.arg_pos(0u) as c_uint) }; - let mut bcx = fcx.entry_bcx.unwrap(); + let mut bcx = fcx.entry_bcx.get().unwrap(); let arg = BitCast(bcx, arg, llptrty); let ret = adt::trans_get_discr(bcx, repr, arg, Some(Type::i64())); - Store(bcx, ret, fcx.llretptr.unwrap()); - match fcx.llreturn { + Store(bcx, ret, fcx.llretptr.get().unwrap()); + match fcx.llreturn.get() { Some(llreturn) => cleanup_and_Br(bcx, bcx, llreturn), None => bcx = cleanup_block(bcx, Some(bcx.llbb)) }; @@ -382,11 +382,11 @@ impl Reflector { } // Emit a sequence of calls to visit_ty::visit_foo -pub fn emit_calls_to_trait_visit_ty(bcx: @mut Block, +pub fn emit_calls_to_trait_visit_ty(bcx: @Block, t: ty::t, visitor_val: ValueRef, visitor_trait_id: DefId) - -> @mut Block { + -> @Block { let final = sub_block(bcx, "final"); let tydesc_ty = ty::get_tydesc_ty(bcx.ccx().tcx).unwrap(); let tydesc_ty = type_of(bcx.ccx(), tydesc_ty); diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs index 688a40650653a..17423c1dd0202 100644 --- a/src/librustc/middle/trans/tvec.rs +++ b/src/librustc/middle/trans/tvec.rs @@ -53,18 +53,18 @@ pub fn expand_boxed_vec_ty(tcx: ty::ctxt, t: ty::t) -> ty::t { } } -pub fn get_fill(bcx: @mut Block, vptr: ValueRef) -> ValueRef { +pub fn get_fill(bcx: @Block, vptr: ValueRef) -> ValueRef { let _icx = push_ctxt("tvec::get_fill"); Load(bcx, GEPi(bcx, vptr, [0u, abi::vec_elt_fill])) } -pub fn set_fill(bcx: @mut Block, vptr: ValueRef, fill: ValueRef) { +pub fn set_fill(bcx: @Block, vptr: ValueRef, fill: ValueRef) { Store(bcx, fill, GEPi(bcx, vptr, [0u, abi::vec_elt_fill])); } -pub fn get_alloc(bcx: @mut Block, vptr: ValueRef) -> ValueRef { +pub fn get_alloc(bcx: @Block, vptr: ValueRef) -> ValueRef { Load(bcx, GEPi(bcx, vptr, [0u, abi::vec_elt_alloc])) } -pub fn get_bodyptr(bcx: @mut Block, vptr: ValueRef, t: ty::t) -> ValueRef { +pub fn get_bodyptr(bcx: @Block, vptr: ValueRef, t: ty::t) -> ValueRef { if ty::type_contents(bcx.tcx(), t).owns_managed() { GEPi(bcx, vptr, [0u, abi::box_field_body]) } else { @@ -72,19 +72,19 @@ pub fn get_bodyptr(bcx: @mut Block, vptr: ValueRef, t: ty::t) -> ValueRef { } } -pub fn get_dataptr(bcx: @mut Block, vptr: ValueRef) -> ValueRef { +pub fn get_dataptr(bcx: @Block, vptr: ValueRef) -> ValueRef { let _icx = push_ctxt("tvec::get_dataptr"); GEPi(bcx, vptr, [0u, abi::vec_elt_elems, 0u]) } -pub fn pointer_add_byte(bcx: @mut Block, ptr: ValueRef, bytes: ValueRef) -> ValueRef { +pub fn pointer_add_byte(bcx: @Block, ptr: ValueRef, bytes: ValueRef) -> ValueRef { let _icx = push_ctxt("tvec::pointer_add_byte"); let old_ty = val_ty(ptr); let bptr = PointerCast(bcx, ptr, Type::i8p()); return PointerCast(bcx, InBoundsGEP(bcx, bptr, [bytes]), old_ty); } -pub fn alloc_raw(bcx: @mut Block, unit_ty: ty::t, +pub fn alloc_raw(bcx: @Block, unit_ty: ty::t, fill: ValueRef, alloc: ValueRef, heap: heap) -> Result { let _icx = push_ctxt("tvec::alloc_uniq"); let ccx = bcx.ccx(); @@ -107,12 +107,12 @@ pub fn alloc_raw(bcx: @mut Block, unit_ty: ty::t, } } -pub fn alloc_uniq_raw(bcx: @mut Block, unit_ty: ty::t, +pub fn alloc_uniq_raw(bcx: @Block, unit_ty: ty::t, fill: ValueRef, alloc: ValueRef) -> Result { alloc_raw(bcx, unit_ty, fill, alloc, base::heap_for_unique(bcx, unit_ty)) } -pub fn alloc_vec(bcx: @mut Block, +pub fn alloc_vec(bcx: @Block, unit_ty: ty::t, elts: uint, heap: heap) @@ -130,8 +130,8 @@ pub fn alloc_vec(bcx: @mut Block, return rslt(bcx, vptr); } -pub fn make_drop_glue_unboxed(bcx: @mut Block, vptr: ValueRef, vec_ty: ty::t) -> - @mut Block { +pub fn make_drop_glue_unboxed(bcx: @Block, vptr: ValueRef, vec_ty: ty::t) -> + @Block { let _icx = push_ctxt("tvec::make_drop_glue_unboxed"); let tcx = bcx.tcx(); let unit_ty = ty::sequence_element_type(tcx, vec_ty); @@ -160,11 +160,11 @@ impl VecTypes { } } -pub fn trans_fixed_vstore(bcx: @mut Block, +pub fn trans_fixed_vstore(bcx: @Block, vstore_expr: &ast::Expr, content_expr: &ast::Expr, dest: expr::Dest) - -> @mut Block { + -> @Block { //! // // [...] allocates a fixed-size array and moves it around "by value". @@ -189,11 +189,11 @@ pub fn trans_fixed_vstore(bcx: @mut Block, }; } -pub fn trans_slice_vstore(bcx: @mut Block, +pub fn trans_slice_vstore(bcx: @Block, vstore_expr: &ast::Expr, content_expr: &ast::Expr, dest: expr::Dest) - -> @mut Block { + -> @Block { //! // // &[...] allocates memory on the stack and writes the values into it, @@ -247,11 +247,11 @@ pub fn trans_slice_vstore(bcx: @mut Block, return bcx; } -pub fn trans_lit_str(bcx: @mut Block, +pub fn trans_lit_str(bcx: @Block, lit_expr: &ast::Expr, str_lit: @str, dest: Dest) - -> @mut Block { + -> @Block { //! // // Literal strings translate to slices into static memory. This is @@ -282,7 +282,7 @@ pub fn trans_lit_str(bcx: @mut Block, } -pub fn trans_uniq_or_managed_vstore(bcx: @mut Block, heap: heap, vstore_expr: &ast::Expr, +pub fn trans_uniq_or_managed_vstore(bcx: @Block, heap: heap, vstore_expr: &ast::Expr, content_expr: &ast::Expr) -> DatumBlock { //! // @@ -343,12 +343,12 @@ pub fn trans_uniq_or_managed_vstore(bcx: @mut Block, heap: heap, vstore_expr: &a return immediate_rvalue_bcx(bcx, val, vt.vec_ty); } -pub fn write_content(bcx: @mut Block, +pub fn write_content(bcx: @Block, vt: &VecTypes, vstore_expr: &ast::Expr, content_expr: &ast::Expr, dest: Dest) - -> @mut Block { + -> @Block { let _icx = push_ctxt("tvec::write_content"); let mut bcx = bcx; @@ -433,12 +433,12 @@ pub fn write_content(bcx: @mut Block, } } -pub fn vec_types_from_expr(bcx: @mut Block, vec_expr: &ast::Expr) -> VecTypes { +pub fn vec_types_from_expr(bcx: @Block, vec_expr: &ast::Expr) -> VecTypes { let vec_ty = node_id_type(bcx, vec_expr.id); vec_types(bcx, vec_ty) } -pub fn vec_types(bcx: @mut Block, vec_ty: ty::t) -> VecTypes { +pub fn vec_types(bcx: @Block, vec_ty: ty::t) -> VecTypes { let ccx = bcx.ccx(); let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty); let llunit_ty = type_of::type_of(ccx, unit_ty); @@ -452,7 +452,7 @@ pub fn vec_types(bcx: @mut Block, vec_ty: ty::t) -> VecTypes { llunit_alloc_size: llunit_alloc_size} } -pub fn elements_required(bcx: @mut Block, content_expr: &ast::Expr) -> uint { +pub fn elements_required(bcx: @Block, content_expr: &ast::Expr) -> uint { //! Figure out the number of elements we need to store this content match content_expr.node { @@ -468,7 +468,7 @@ pub fn elements_required(bcx: @mut Block, content_expr: &ast::Expr) -> uint { } } -pub fn get_base_and_byte_len(bcx: @mut Block, llval: ValueRef, +pub fn get_base_and_byte_len(bcx: @Block, llval: ValueRef, vec_ty: ty::t) -> (ValueRef, ValueRef) { //! // @@ -505,7 +505,7 @@ pub fn get_base_and_byte_len(bcx: @mut Block, llval: ValueRef, } } -pub fn get_base_and_len(bcx: @mut Block, llval: ValueRef, vec_ty: ty::t) -> (ValueRef, ValueRef) { +pub fn get_base_and_len(bcx: @Block, llval: ValueRef, vec_ty: ty::t) -> (ValueRef, ValueRef) { //! // // Converts a vector into the slice pair. The vector should be stored in @@ -539,15 +539,15 @@ pub fn get_base_and_len(bcx: @mut Block, llval: ValueRef, vec_ty: ty::t) -> (Val } } -pub type iter_vec_block<'a> = 'a |@mut Block, ValueRef, ty::t| - -> @mut Block; +pub type iter_vec_block<'a> = 'a |@Block, ValueRef, ty::t| + -> @Block; -pub fn iter_vec_loop(bcx: @mut Block, +pub fn iter_vec_loop(bcx: @Block, data_ptr: ValueRef, vt: &VecTypes, count: ValueRef, f: iter_vec_block - ) -> @mut Block { + ) -> @Block { let _icx = push_ctxt("tvec::iter_vec_loop"); let next_bcx = sub_block(bcx, "iter_vec_loop: while next"); @@ -597,8 +597,8 @@ pub fn iter_vec_loop(bcx: @mut Block, next_bcx } -pub fn iter_vec_raw(bcx: @mut Block, data_ptr: ValueRef, vec_ty: ty::t, - fill: ValueRef, f: iter_vec_block) -> @mut Block { +pub fn iter_vec_raw(bcx: @Block, data_ptr: ValueRef, vec_ty: ty::t, + fill: ValueRef, f: iter_vec_block) -> @Block { let _icx = push_ctxt("tvec::iter_vec_raw"); let vt = vec_types(bcx, vec_ty); @@ -632,15 +632,15 @@ pub fn iter_vec_raw(bcx: @mut Block, data_ptr: ValueRef, vec_ty: ty::t, } } -pub fn iter_vec_uniq(bcx: @mut Block, vptr: ValueRef, vec_ty: ty::t, - fill: ValueRef, f: iter_vec_block) -> @mut Block { +pub fn iter_vec_uniq(bcx: @Block, vptr: ValueRef, vec_ty: ty::t, + fill: ValueRef, f: iter_vec_block) -> @Block { let _icx = push_ctxt("tvec::iter_vec_uniq"); let data_ptr = get_dataptr(bcx, get_bodyptr(bcx, vptr, vec_ty)); iter_vec_raw(bcx, data_ptr, vec_ty, fill, f) } -pub fn iter_vec_unboxed(bcx: @mut Block, body_ptr: ValueRef, vec_ty: ty::t, - f: iter_vec_block) -> @mut Block { +pub fn iter_vec_unboxed(bcx: @Block, body_ptr: ValueRef, vec_ty: ty::t, + f: iter_vec_block) -> @Block { let _icx = push_ctxt("tvec::iter_vec_unboxed"); let fill = get_fill(bcx, body_ptr); let dataptr = get_dataptr(bcx, body_ptr); diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs index 4986854dd15f3..fae677497b869 100644 --- a/src/librustc/middle/trans/type_.rs +++ b/src/librustc/middle/trans/type_.rs @@ -187,7 +187,7 @@ impl Type { Type::array(&Type::i8().ptr_to(), 1) } - pub fn generic_glue_fn(cx: &mut CrateContext) -> Type { + pub fn generic_glue_fn(cx: &CrateContext) -> Type { match cx.tn.find_type("glue_fn") { Some(ty) => return ty, None => () diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index 17620a81e51a7..c1e6e46676181 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -21,15 +21,15 @@ use middle::trans::type_::Type; use syntax::ast; use syntax::opt_vec; -pub fn arg_is_indirect(ccx: &mut CrateContext, arg_ty: ty::t) -> bool { +pub fn arg_is_indirect(ccx: &CrateContext, arg_ty: ty::t) -> bool { !type_is_immediate(ccx, arg_ty) } -pub fn return_uses_outptr(ccx: &mut CrateContext, ty: ty::t) -> bool { +pub fn return_uses_outptr(ccx: &CrateContext, ty: ty::t) -> bool { !type_is_immediate(ccx, ty) } -pub fn type_of_explicit_arg(ccx: &mut CrateContext, arg_ty: ty::t) -> Type { +pub fn type_of_explicit_arg(ccx: &CrateContext, arg_ty: ty::t) -> Type { let llty = type_of(ccx, arg_ty); if arg_is_indirect(ccx, arg_ty) { llty.ptr_to() @@ -38,12 +38,12 @@ pub fn type_of_explicit_arg(ccx: &mut CrateContext, arg_ty: ty::t) -> Type { } } -pub fn type_of_explicit_args(ccx: &mut CrateContext, +pub fn type_of_explicit_args(ccx: &CrateContext, inputs: &[ty::t]) -> ~[Type] { inputs.map(|&arg_ty| type_of_explicit_arg(ccx, arg_ty)) } -pub fn type_of_rust_fn(cx: &mut CrateContext, +pub fn type_of_rust_fn(cx: &CrateContext, inputs: &[ty::t], output: ty::t) -> Type { let mut atys: ~[Type] = ~[]; @@ -71,7 +71,7 @@ pub fn type_of_rust_fn(cx: &mut CrateContext, } // Given a function type and a count of ty params, construct an llvm type -pub fn type_of_fn_from_ty(cx: &mut CrateContext, fty: ty::t) -> Type { +pub fn type_of_fn_from_ty(cx: &CrateContext, fty: ty::t) -> Type { return match ty::get(fty).sty { ty::ty_closure(ref f) => { type_of_rust_fn(cx, f.sig.inputs, f.sig.output) @@ -100,10 +100,13 @@ pub fn type_of_fn_from_ty(cx: &mut CrateContext, fty: ty::t) -> Type { // type behind pointers. This can help prevent infinite loops for // recursive types. For example, enum types rely on this behavior. -pub fn sizing_type_of(cx: &mut CrateContext, t: ty::t) -> Type { - match cx.llsizingtypes.find_copy(&t) { - Some(t) => return t, - None => () +pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type { + { + let llsizingtypes = cx.llsizingtypes.borrow(); + match llsizingtypes.get().find_copy(&t) { + Some(t) => return t, + None => () + } } let llsizingty = match ty::get(t).sty { @@ -166,18 +169,20 @@ pub fn sizing_type_of(cx: &mut CrateContext, t: ty::t) -> Type { } }; - cx.llsizingtypes.insert(t, llsizingty); + let mut llsizingtypes = cx.llsizingtypes.borrow_mut(); + llsizingtypes.get().insert(t, llsizingty); llsizingty } // NB: If you update this, be sure to update `sizing_type_of()` as well. -pub fn type_of(cx: &mut CrateContext, t: ty::t) -> Type { +pub fn type_of(cx: &CrateContext, t: ty::t) -> Type { // Check the cache. - match cx.lltypes.find(&t) { - Some(&llty) => { - return llty; + { + let lltypes = cx.lltypes.borrow(); + match lltypes.get().find(&t) { + Some(&llty) => return llty, + None => () } - None => () } debug!("type_of {} {:?}", t.repr(cx.tcx), t); @@ -197,7 +202,8 @@ pub fn type_of(cx: &mut CrateContext, t: ty::t) -> Type { t_norm.repr(cx.tcx), t_norm, cx.tn.type_to_str(llty)); - cx.lltypes.insert(t, llty); + let mut lltypes = cx.lltypes.borrow_mut(); + lltypes.get().insert(t, llty); return llty; } @@ -316,7 +322,10 @@ pub fn type_of(cx: &mut CrateContext, t: ty::t) -> Type { t.repr(cx.tcx), t, cx.tn.type_to_str(llty)); - cx.lltypes.insert(t, llty); + { + let mut lltypes = cx.lltypes.borrow_mut(); + lltypes.get().insert(t, llty); + } // If this was an enum or struct, fill in the type now. match ty::get(t).sty { @@ -350,7 +359,7 @@ pub fn llvm_type_name(cx: &CrateContext, } } -pub fn type_of_dtor(ccx: &mut CrateContext, self_ty: ty::t) -> Type { +pub fn type_of_dtor(ccx: &CrateContext, self_ty: ty::t) -> Type { let self_ty = type_of(ccx, self_ty).ptr_to(); Type::func([self_ty], &Type::void()) } diff --git a/src/librustc/middle/trans/uniq.rs b/src/librustc/middle/trans/uniq.rs index 18b45fb461381..a184ecda20db4 100644 --- a/src/librustc/middle/trans/uniq.rs +++ b/src/librustc/middle/trans/uniq.rs @@ -17,8 +17,8 @@ use middle::trans::datum::immediate_rvalue; use middle::trans::glue; use middle::ty; -pub fn make_free_glue(bcx: @mut Block, vptrptr: ValueRef, box_ty: ty::t) - -> @mut Block { +pub fn make_free_glue(bcx: @Block, vptrptr: ValueRef, box_ty: ty::t) + -> @Block { let _icx = push_ctxt("uniq::make_free_glue"); let box_datum = immediate_rvalue(Load(bcx, vptrptr), box_ty); diff --git a/src/librustc/middle/trans/value.rs b/src/librustc/middle/trans/value.rs index 59bc397a55884..14045f8ab744e 100644 --- a/src/librustc/middle/trans/value.rs +++ b/src/librustc/middle/trans/value.rs @@ -49,7 +49,7 @@ impl Value { /// This only performs a search for a trivially dominating store. The store /// must be the only user of this value, and there must not be any conditional /// branches between the store and the given block. - pub fn get_dominating_store(self, bcx: &mut Block) -> Option { + pub fn get_dominating_store(self, bcx: &Block) -> Option { match self.get_single_user().and_then(|user| user.as_store_inst()) { Some(store) => { store.get_parent().and_then(|store_bb| { diff --git a/src/librustc/middle/trans/write_guard.rs b/src/librustc/middle/trans/write_guard.rs index 2da2da80fdd6a..3b60dc3dd3789 100644 --- a/src/librustc/middle/trans/write_guard.rs +++ b/src/librustc/middle/trans/write_guard.rs @@ -34,10 +34,10 @@ use syntax::ast; use middle::trans::type_::Type; pub fn root_and_write_guard(datum: &Datum, - mut bcx: @mut Block, + mut bcx: @Block, span: Span, expr_id: ast::NodeId, - derefs: uint) -> @mut Block { + derefs: uint) -> @Block { let key = root_map_key { id: expr_id, derefs: derefs }; debug!("write_guard::root_and_write_guard(key={:?})", key); @@ -45,27 +45,31 @@ pub fn root_and_write_guard(datum: &Datum, // // (Note: root'd values are always boxes) let ccx = bcx.ccx(); - bcx = match ccx.maps.root_map.find(&key) { - None => bcx, - Some(&root_info) => root(datum, bcx, span, key, root_info) + bcx = { + let root_map = ccx.maps.root_map.borrow(); + match root_map.get().find(&key) { + None => bcx, + Some(&root_info) => root(datum, bcx, span, key, root_info) + } }; // Perform the write guard, if necessary. // // (Note: write-guarded values are always boxes) - if ccx.maps.write_guard_map.contains(&key) { + let write_guard_map = ccx.maps.write_guard_map.borrow(); + if write_guard_map.get().contains(&key) { perform_write_guard(datum, bcx, span) } else { bcx } } -pub fn return_to_mut(mut bcx: @mut Block, +pub fn return_to_mut(mut bcx: @Block, root_key: root_map_key, frozen_val_ref: ValueRef, bits_val_ref: ValueRef, filename_val: ValueRef, - line_val: ValueRef) -> @mut Block { + line_val: ValueRef) -> @Block { debug!("write_guard::return_to_mut(root_key={:?}, {}, {}, {})", root_key, bcx.to_str(), @@ -102,10 +106,10 @@ pub fn return_to_mut(mut bcx: @mut Block, } fn root(datum: &Datum, - mut bcx: @mut Block, + mut bcx: @Block, span: Span, root_key: root_map_key, - root_info: RootInfo) -> @mut Block { + root_info: RootInfo) -> @Block { //! In some cases, borrowck will decide that an @T/@[]/@str //! value must be rooted for the program to be safe. In that //! case, we will call this function, which will stash a copy @@ -120,7 +124,10 @@ fn root(datum: &Datum, let scratch = scratch_datum(bcx, datum.ty, "__write_guard", true); datum.copy_to_datum(bcx, INIT, scratch); let cleanup_bcx = find_bcx_for_scope(bcx, root_info.scope); - add_clean_temp_mem_in_scope(cleanup_bcx, root_info.scope, scratch.val, scratch.ty); + add_clean_temp_mem_in_scope(cleanup_bcx, + root_info.scope, + scratch.val, + scratch.ty); // Now, consider also freezing it. match root_info.freeze { @@ -165,9 +172,13 @@ fn root(datum: &Datum, Some(expr::Ignore)).bcx; } - add_clean_return_to_mut( - cleanup_bcx, root_info.scope, root_key, scratch.val, scratch_bits.val, - filename, line); + add_clean_return_to_mut(cleanup_bcx, + root_info.scope, + root_key, + scratch.val, + scratch_bits.val, + filename, + line); } } @@ -175,8 +186,8 @@ fn root(datum: &Datum, } fn perform_write_guard(datum: &Datum, - bcx: @mut Block, - span: Span) -> @mut Block { + bcx: @Block, + span: Span) -> @Block { debug!("perform_write_guard"); let llval = datum.to_value_llval(bcx); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index a8f4a27b75844..60bbca6cf358a 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use driver::session; use metadata::csearch; use metadata; @@ -30,6 +29,7 @@ use util::ppaux::{Repr, UserString}; use util::common::{indenter}; use std::cast; +use std::cell::{Cell, RefCell}; use std::cmp; use std::hashmap::{HashMap, HashSet}; use std::ops; @@ -174,7 +174,7 @@ pub struct creader_cache_key { len: uint } -type creader_cache = @mut HashMap; +type creader_cache = RefCell>; struct intern_key { sty: *sty, @@ -264,15 +264,15 @@ pub type ctxt = @ctxt_; /// later on. struct ctxt_ { diag: @mut syntax::diagnostic::span_handler, - interner: @mut HashMap, - next_id: @mut uint, - cstore: @mut metadata::cstore::CStore, + interner: RefCell>, + next_id: Cell, + cstore: @metadata::cstore::CStore, sess: session::Session, def_map: resolve::DefMap, - named_region_map: @mut resolve_lifetime::NamedRegionMap, + named_region_map: @RefCell, - region_maps: @mut middle::region::RegionMaps, + region_maps: @middle::region::RegionMaps, // Stores the types for various nodes in the AST. Note that this table // is not guaranteed to be populated until after typeck. See @@ -283,93 +283,93 @@ struct ctxt_ { // of this node. This only applies to nodes that refer to entities // parameterized by type parameters, such as generic fns, types, or // other items. - node_type_substs: @mut HashMap, + node_type_substs: RefCell>, // Maps from a method to the method "descriptor" - methods: @mut HashMap, + methods: RefCell>, // Maps from a trait def-id to a list of the def-ids of its methods - trait_method_def_ids: @mut HashMap, + trait_method_def_ids: RefCell>, // A cache for the trait_methods() routine - trait_methods_cache: @mut HashMap, + trait_methods_cache: RefCell>, - impl_trait_cache: @mut HashMap>, + impl_trait_cache: RefCell>>, - trait_refs: @mut HashMap, - trait_defs: @mut HashMap, + trait_refs: RefCell>, + trait_defs: RefCell>, /// Despite its name, `items` does not only map NodeId to an item but /// also to expr/stmt/local/arg/etc items: ast_map::map, - intrinsic_defs: @mut HashMap, - freevars: freevars::freevar_map, + intrinsic_defs: RefCell>, + freevars: RefCell, tcache: type_cache, rcache: creader_cache, - short_names_cache: @mut HashMap, - needs_unwind_cleanup_cache: @mut HashMap, - tc_cache: @mut HashMap, - ast_ty_to_ty_cache: @mut HashMap, - enum_var_cache: @mut HashMap, - ty_param_defs: @mut HashMap, - adjustments: @mut HashMap, - normalized_cache: @mut HashMap, + short_names_cache: RefCell>, + needs_unwind_cleanup_cache: RefCell>, + tc_cache: RefCell>, + ast_ty_to_ty_cache: RefCell>, + enum_var_cache: RefCell>, + ty_param_defs: RefCell>, + adjustments: RefCell>, + normalized_cache: RefCell>, lang_items: middle::lang_items::LanguageItems, // A mapping of fake provided method def_ids to the default implementation - provided_method_sources: @mut HashMap, - supertraits: @mut HashMap, + provided_method_sources: RefCell>, + supertraits: RefCell>, // Maps from def-id of a type or region parameter to its // (inferred) variance. - item_variance_map: @mut HashMap, + item_variance_map: RefCell>, // A mapping from the def ID of an enum or struct type to the def ID // of the method that implements its destructor. If the type is not // present in this map, it does not have a destructor. This map is // populated during the coherence phase of typechecking. - destructor_for_type: @mut HashMap, + destructor_for_type: RefCell>, // A method will be in this list if and only if it is a destructor. - destructors: @mut HashSet, + destructors: RefCell>, // Maps a trait onto a list of impls of that trait. - trait_impls: @mut HashMap, + trait_impls: RefCell>>, // Maps a def_id of a type to a list of its inherent impls. // Contains implementations of methods that are inherent to a type. // Methods in these implementations don't need to be exported. - inherent_impls: @mut HashMap, + inherent_impls: RefCell>>, // Maps a def_id of an impl to an Impl structure. // Note that this contains all of the impls that we know about, // including ones in other crates. It's not clear that this is the best // way to do it. - impls: @mut HashMap, + impls: RefCell>, // Set of used unsafe nodes (functions or blocks). Unsafe nodes not // present in this set can be warned about. - used_unsafe: @mut HashSet, + used_unsafe: RefCell>, // Set of nodes which mark locals as mutable which end up getting used at // some point. Local variable definitions not in this set can be warned // about. - used_mut_nodes: @mut HashSet, + used_mut_nodes: RefCell>, // vtable resolution information for impl declarations impl_vtables: typeck::impl_vtable_map, // The set of external nominal types whose implementations have been read. // This is used for lazy resolution of methods. - populated_external_types: @mut HashSet, + populated_external_types: RefCell>, // The set of external traits whose implementations have been read. This // is used for lazy resolution of traits. - populated_external_traits: @mut HashSet, + populated_external_traits: RefCell>, // These two caches are used by const_eval when decoding external statics // and variants that are found. - extern_const_statics: @mut HashMap>, - extern_const_variants: @mut HashMap>, + extern_const_statics: RefCell>>, + extern_const_variants: RefCell>>, } pub enum tbox_flag { @@ -953,73 +953,65 @@ pub struct ty_param_substs_and_ty { ty: ty::t } -type type_cache = @mut HashMap; - -pub type node_type_table = @mut HashMap; - -fn mk_rcache() -> creader_cache { - return @mut HashMap::new(); -} +type type_cache = RefCell>; -pub fn new_ty_hash() -> @mut HashMap { - @mut HashMap::new() -} +pub type node_type_table = RefCell>; pub fn mk_ctxt(s: session::Session, dm: resolve::DefMap, - named_region_map: @mut resolve_lifetime::NamedRegionMap, + named_region_map: @RefCell, amap: ast_map::map, freevars: freevars::freevar_map, - region_maps: @mut middle::region::RegionMaps, + region_maps: @middle::region::RegionMaps, lang_items: middle::lang_items::LanguageItems) -> ctxt { @ctxt_ { named_region_map: named_region_map, - item_variance_map: @mut HashMap::new(), + item_variance_map: RefCell::new(HashMap::new()), diag: s.diagnostic(), - interner: @mut HashMap::new(), - next_id: @mut primitives::LAST_PRIMITIVE_ID, + interner: RefCell::new(HashMap::new()), + next_id: Cell::new(primitives::LAST_PRIMITIVE_ID), cstore: s.cstore, sess: s, def_map: dm, region_maps: region_maps, - node_types: @mut HashMap::new(), - node_type_substs: @mut HashMap::new(), - trait_refs: @mut HashMap::new(), - trait_defs: @mut HashMap::new(), + node_types: RefCell::new(HashMap::new()), + node_type_substs: RefCell::new(HashMap::new()), + trait_refs: RefCell::new(HashMap::new()), + trait_defs: RefCell::new(HashMap::new()), items: amap, - intrinsic_defs: @mut HashMap::new(), - freevars: freevars, - tcache: @mut HashMap::new(), - rcache: mk_rcache(), - short_names_cache: new_ty_hash(), - needs_unwind_cleanup_cache: new_ty_hash(), - tc_cache: @mut HashMap::new(), - ast_ty_to_ty_cache: @mut HashMap::new(), - enum_var_cache: @mut HashMap::new(), - methods: @mut HashMap::new(), - trait_method_def_ids: @mut HashMap::new(), - trait_methods_cache: @mut HashMap::new(), - impl_trait_cache: @mut HashMap::new(), - ty_param_defs: @mut HashMap::new(), - adjustments: @mut HashMap::new(), - normalized_cache: new_ty_hash(), + intrinsic_defs: RefCell::new(HashMap::new()), + freevars: RefCell::new(freevars), + tcache: RefCell::new(HashMap::new()), + rcache: RefCell::new(HashMap::new()), + short_names_cache: RefCell::new(HashMap::new()), + needs_unwind_cleanup_cache: RefCell::new(HashMap::new()), + tc_cache: RefCell::new(HashMap::new()), + ast_ty_to_ty_cache: RefCell::new(HashMap::new()), + enum_var_cache: RefCell::new(HashMap::new()), + methods: RefCell::new(HashMap::new()), + trait_method_def_ids: RefCell::new(HashMap::new()), + trait_methods_cache: RefCell::new(HashMap::new()), + impl_trait_cache: RefCell::new(HashMap::new()), + ty_param_defs: RefCell::new(HashMap::new()), + adjustments: RefCell::new(HashMap::new()), + normalized_cache: RefCell::new(HashMap::new()), lang_items: lang_items, - provided_method_sources: @mut HashMap::new(), - supertraits: @mut HashMap::new(), - destructor_for_type: @mut HashMap::new(), - destructors: @mut HashSet::new(), - trait_impls: @mut HashMap::new(), - inherent_impls: @mut HashMap::new(), - impls: @mut HashMap::new(), - used_unsafe: @mut HashSet::new(), - used_mut_nodes: @mut HashSet::new(), - impl_vtables: @mut HashMap::new(), - populated_external_types: @mut HashSet::new(), - populated_external_traits: @mut HashSet::new(), - - extern_const_statics: @mut HashMap::new(), - extern_const_variants: @mut HashMap::new(), + provided_method_sources: RefCell::new(HashMap::new()), + supertraits: RefCell::new(HashMap::new()), + destructor_for_type: RefCell::new(HashMap::new()), + destructors: RefCell::new(HashSet::new()), + trait_impls: RefCell::new(HashMap::new()), + inherent_impls: RefCell::new(HashMap::new()), + impls: RefCell::new(HashMap::new()), + used_unsafe: RefCell::new(HashSet::new()), + used_mut_nodes: RefCell::new(HashSet::new()), + impl_vtables: RefCell::new(HashMap::new()), + populated_external_types: RefCell::new(HashSet::new()), + populated_external_traits: RefCell::new(HashSet::new()), + + extern_const_statics: RefCell::new(HashMap::new()), + extern_const_variants: RefCell::new(HashMap::new()), } } @@ -1042,9 +1034,13 @@ pub fn mk_t(cx: ctxt, st: sty) -> t { }; let key = intern_key { sty: to_unsafe_ptr(&st) }; - match cx.interner.find(&key) { - Some(t) => unsafe { return cast::transmute(&t.sty); }, - _ => () + + { + let mut interner = cx.interner.borrow_mut(); + match interner.get().find(&key) { + Some(t) => unsafe { return cast::transmute(&t.sty); }, + _ => () + } } let mut flags = 0u; @@ -1128,7 +1124,7 @@ pub fn mk_t(cx: ctxt, st: sty) -> t { let t = ~t_box_ { sty: st, - id: *cx.next_id, + id: cx.next_id.get(), flags: flags, }; @@ -1138,9 +1134,10 @@ pub fn mk_t(cx: ctxt, st: sty) -> t { sty: sty_ptr, }; - cx.interner.insert(key, t); + let mut interner = cx.interner.borrow_mut(); + interner.get().insert(key, t); - *cx.next_id += 1; + cx.next_id.set(cx.next_id.get() + 1); unsafe { cast::transmute::<*sty, t>(sty_ptr) @@ -1662,15 +1659,21 @@ pub fn type_needs_drop(cx: ctxt, ty: t) -> bool { // that only contain scalars and shared boxes can avoid unwind // cleanups. pub fn type_needs_unwind_cleanup(cx: ctxt, ty: t) -> bool { - match cx.needs_unwind_cleanup_cache.find(&ty) { - Some(&result) => return result, - None => () + { + let needs_unwind_cleanup_cache = cx.needs_unwind_cleanup_cache + .borrow(); + match needs_unwind_cleanup_cache.get().find(&ty) { + Some(&result) => return result, + None => () + } } let mut tycache = HashSet::new(); let needs_unwind_cleanup = type_needs_unwind_cleanup_(cx, ty, &mut tycache, false); - cx.needs_unwind_cleanup_cache.insert(ty, needs_unwind_cleanup); + let mut needs_unwind_cleanup_cache = cx.needs_unwind_cleanup_cache + .borrow_mut(); + needs_unwind_cleanup_cache.get().insert(ty, needs_unwind_cleanup); return needs_unwind_cleanup; } @@ -1958,14 +1961,20 @@ pub fn type_is_freezable(cx: ctxt, t: ty::t) -> bool { pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { let ty_id = type_id(ty); - match cx.tc_cache.find(&ty_id) { - Some(tc) => { return *tc; } - None => {} + + { + let tc_cache = cx.tc_cache.borrow(); + match tc_cache.get().find(&ty_id) { + Some(tc) => { return *tc; } + None => {} + } } let mut cache = HashMap::new(); let result = tc_ty(cx, ty, &mut cache); - cx.tc_cache.insert(ty_id, result); + + let mut tc_cache = cx.tc_cache.borrow_mut(); + tc_cache.get().insert(ty_id, result); return result; fn tc_ty(cx: ctxt, @@ -1998,9 +2007,12 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { Some(tc) => { return *tc; } None => {} } - match cx.tc_cache.find(&ty_id) { // Must check both caches! - Some(tc) => { return *tc; } - None => {} + { + let tc_cache = cx.tc_cache.borrow(); + match tc_cache.get().find(&ty_id) { // Must check both caches! + Some(tc) => { return *tc; } + None => {} + } } cache.insert(ty_id, TC::None); @@ -2103,7 +2115,8 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { // def-id. assert_eq!(p.def_id.crate, ast::LOCAL_CRATE); - let tp_def = cx.ty_param_defs.get(&p.def_id.node); + let ty_param_defs = cx.ty_param_defs.borrow(); + let tp_def = ty_param_defs.get().get(&p.def_id.node); kind_bounds_to_contents(cx, tp_def.bounds.builtin_bounds, tp_def.bounds.trait_bounds) @@ -2548,7 +2561,8 @@ pub fn type_is_sized(cx: ctxt, ty: ty::t) -> bool { match get(ty).sty { // FIXME(#6308) add trait, vec, str, etc here. ty_param(p) => { - let param_def = cx.ty_param_defs.get(&p.def_id.node); + let ty_param_defs = cx.ty_param_defs.borrow(); + let param_def = ty_param_defs.get().get(&p.def_id.node); if param_def.bounds.builtin_bounds.contains_elem(BoundSized) { return true; } @@ -2648,7 +2662,8 @@ pub fn index_sty(sty: &sty) -> Option { } pub fn node_id_to_trait_ref(cx: ctxt, id: ast::NodeId) -> @ty::TraitRef { - match cx.trait_refs.find(&id) { + let trait_refs = cx.trait_refs.borrow(); + match trait_refs.get().find(&id) { Some(&t) => t, None => cx.sess.bug( format!("node_id_to_trait_ref: no trait ref for node `{}`", @@ -2659,7 +2674,8 @@ pub fn node_id_to_trait_ref(cx: ctxt, id: ast::NodeId) -> @ty::TraitRef { pub fn node_id_to_type(cx: ctxt, id: ast::NodeId) -> t { //printfln!("{:?}/{:?}", id, cx.node_types.len()); - match cx.node_types.find(&(id as uint)) { + let node_types = cx.node_types.borrow(); + match node_types.get().find(&(id as uint)) { Some(&t) => t, None => cx.sess.bug( format!("node_id_to_type: no type for node `{}`", @@ -2670,14 +2686,16 @@ pub fn node_id_to_type(cx: ctxt, id: ast::NodeId) -> t { // XXX(pcwalton): Makes a copy, bleh. Probably better to not do that. pub fn node_id_to_type_params(cx: ctxt, id: ast::NodeId) -> ~[t] { - match cx.node_type_substs.find(&id) { + let node_type_substs = cx.node_type_substs.borrow(); + match node_type_substs.get().find(&id) { None => return ~[], Some(ts) => return (*ts).clone(), } } fn node_id_has_type_params(cx: ctxt, id: ast::NodeId) -> bool { - cx.node_type_substs.contains_key(&id) + let node_type_substs = cx.node_type_substs.borrow(); + node_type_substs.get().contains_key(&id) } pub fn fn_is_variadic(fty: t) -> bool { @@ -2851,14 +2869,18 @@ pub fn expr_ty_adjusted(cx: ctxt, expr: &ast::Expr) -> t { */ let unadjusted_ty = expr_ty(cx, expr); - adjust_ty(cx, expr.span, unadjusted_ty, cx.adjustments.find_copy(&expr.id)) + let adjustment = { + let adjustments = cx.adjustments.borrow(); + adjustments.get().find_copy(&expr.id) + }; + adjust_ty(cx, expr.span, unadjusted_ty, adjustment) } pub fn adjust_ty(cx: ctxt, span: Span, unadjusted_ty: ty::t, - adjustment: Option<@AutoAdjustment>) -> ty::t -{ + adjustment: Option<@AutoAdjustment>) + -> ty::t { /*! See `expr_ty_adjusted` */ return match adjustment { @@ -3027,7 +3049,8 @@ pub fn method_call_type_param_defs(tcx: ctxt, method_map: typeck::method_map, id: ast::NodeId) -> Option<@~[TypeParameterDef]> { - method_map.find(&id).map(|method| { + let method_map = method_map.borrow(); + method_map.get().find(&id).map(|method| { match method.origin { typeck::method_static(did) => { // n.b.: When we encode impl methods, the bounds @@ -3057,7 +3080,8 @@ pub fn method_call_type_param_defs(tcx: ctxt, } pub fn resolve_expr(tcx: ctxt, expr: &ast::Expr) -> ast::Def { - match tcx.def_map.find(&expr.id) { + let def_map = tcx.def_map.borrow(); + match def_map.get().find(&expr.id) { Some(&def) => def, None => { tcx.sess.span_bug(expr.span, format!( @@ -3090,14 +3114,17 @@ pub enum ExprKind { pub fn expr_kind(tcx: ctxt, method_map: typeck::method_map, expr: &ast::Expr) -> ExprKind { - if method_map.contains_key(&expr.id) { - // Overloaded operations are generally calls, and hence they are - // generated via DPS. However, assign_op (e.g., `x += y`) is an - // exception, as its result is always unit. - return match expr.node { - ast::ExprAssignOp(..) => RvalueStmtExpr, - _ => RvalueDpsExpr - }; + { + let method_map = method_map.borrow(); + if method_map.get().contains_key(&expr.id) { + // Overloaded operations are generally calls, and hence they are + // generated via DPS. However, assign_op (e.g., `x += y`) is an + // exception, as its result is always unit. + return match expr.node { + ast::ExprAssignOp(..) => RvalueStmtExpr, + _ => RvalueDpsExpr + }; + } } match expr.node { @@ -3151,7 +3178,8 @@ pub fn expr_kind(tcx: ctxt, } ast::ExprCast(..) => { - match tcx.node_types.find(&(expr.id as uint)) { + let node_types = tcx.node_types.borrow(); + match node_types.get().find(&(expr.id as uint)) { Some(&t) => { if type_is_trait(t) { RvalueDpsExpr @@ -3501,7 +3529,8 @@ pub fn def_has_ty_params(def: ast::Def) -> bool { } pub fn provided_source(cx: ctxt, id: ast::DefId) -> Option { - cx.provided_method_sources.find(&id).map(|x| *x) + let provided_method_sources = cx.provided_method_sources.borrow(); + provided_method_sources.get().find(&id).map(|x| *x) } pub fn provided_trait_methods(cx: ctxt, id: ast::DefId) -> ~[@Method] { @@ -3522,13 +3551,14 @@ pub fn provided_trait_methods(cx: ctxt, id: ast::DefId) -> ~[@Method] { } } -pub fn trait_supertraits(cx: ctxt, - id: ast::DefId) -> @~[@TraitRef] -{ +pub fn trait_supertraits(cx: ctxt, id: ast::DefId) -> @~[@TraitRef] { // Check the cache. - match cx.supertraits.find(&id) { - Some(&trait_refs) => { return trait_refs; } - None => {} // Continue. + { + let supertraits = cx.supertraits.borrow(); + match supertraits.get().find(&id) { + Some(&trait_refs) => { return trait_refs; } + None => {} // Continue. + } } // Not in the cache. It had better be in the metadata, which means it @@ -3538,7 +3568,8 @@ pub fn trait_supertraits(cx: ctxt, // Get the supertraits out of the metadata and create the // TraitRef for each. let result = @csearch::get_supertraits(cx, id); - cx.supertraits.insert(id, result); + let mut supertraits = cx.supertraits.borrow_mut(); + supertraits.get().insert(id, result); return result; } @@ -3583,34 +3614,44 @@ pub fn trait_method(cx: ctxt, trait_did: ast::DefId, idx: uint) -> @Method { pub fn trait_methods(cx: ctxt, trait_did: ast::DefId) -> @~[@Method] { - match cx.trait_methods_cache.find(&trait_did) { + let mut trait_methods_cache = cx.trait_methods_cache.borrow_mut(); + match trait_methods_cache.get().find(&trait_did) { Some(&methods) => methods, None => { let def_ids = ty::trait_method_def_ids(cx, trait_did); let methods = @def_ids.map(|d| ty::method(cx, *d)); - cx.trait_methods_cache.insert(trait_did, methods); + trait_methods_cache.get().insert(trait_did, methods); methods } } } pub fn method(cx: ctxt, id: ast::DefId) -> @Method { - lookup_locally_or_in_crate_store( - "methods", id, cx.methods, - || @csearch::get_method(cx, id)) + let mut methods = cx.methods.borrow_mut(); + lookup_locally_or_in_crate_store("methods", id, methods.get(), || { + @csearch::get_method(cx, id) + }) } pub fn trait_method_def_ids(cx: ctxt, id: ast::DefId) -> @~[DefId] { - lookup_locally_or_in_crate_store( - "trait_method_def_ids", id, cx.trait_method_def_ids, - || @csearch::get_trait_method_def_ids(cx.cstore, id)) + let mut trait_method_def_ids = cx.trait_method_def_ids.borrow_mut(); + lookup_locally_or_in_crate_store("trait_method_def_ids", + id, + trait_method_def_ids.get(), + || { + @csearch::get_trait_method_def_ids(cx.cstore, id) + }) } pub fn impl_trait_ref(cx: ctxt, id: ast::DefId) -> Option<@TraitRef> { - match cx.impl_trait_cache.find(&id) { - Some(&ret) => { return ret; } - None => {} + { + let mut impl_trait_cache = cx.impl_trait_cache.borrow_mut(); + match impl_trait_cache.get().find(&id) { + Some(&ret) => { return ret; } + None => {} + } } + let ret = if id.crate == ast::LOCAL_CRATE { debug!("(impl_trait_ref) searching for trait impl {:?}", id); match cx.items.find(&id.node) { @@ -3628,12 +3669,17 @@ pub fn impl_trait_ref(cx: ctxt, id: ast::DefId) -> Option<@TraitRef> { } else { csearch::get_impl_trait(cx, id) }; - cx.impl_trait_cache.insert(id, ret); + + let mut impl_trait_cache = cx.impl_trait_cache.borrow_mut(); + impl_trait_cache.get().insert(id, ret); return ret; } pub fn trait_ref_to_def_id(tcx: ctxt, tr: &ast::trait_ref) -> ast::DefId { - let def = tcx.def_map.find(&tr.ref_id).expect("no def-map entry for trait"); + let def_map = tcx.def_map.borrow(); + let def = def_map.get() + .find(&tr.ref_id) + .expect("no def-map entry for trait"); ast_util::def_id_of_def(*def) } @@ -3773,7 +3819,8 @@ impl DtorKind { /* If struct_id names a struct with a dtor, return Some(the dtor's id). Otherwise return none. */ pub fn ty_dtor(cx: ctxt, struct_id: DefId) -> DtorKind { - match cx.destructor_for_type.find(&struct_id) { + let destructor_for_type = cx.destructor_for_type.borrow(); + match destructor_for_type.get().find(&struct_id) { Some(&method_def_id) => { let flag = !has_attr(cx, struct_id, "unsafe_no_drop_flag"); @@ -3852,9 +3899,12 @@ pub fn type_is_empty(cx: ctxt, t: t) -> bool { } pub fn enum_variants(cx: ctxt, id: ast::DefId) -> @~[@VariantInfo] { - match cx.enum_var_cache.find(&id) { - Some(&variants) => return variants, - _ => { /* fallthrough */ } + { + let enum_var_cache = cx.enum_var_cache.borrow(); + match enum_var_cache.get().find(&id) { + Some(&variants) => return variants, + _ => { /* fallthrough */ } + } } let result = if ast::LOCAL_CRATE != id.crate { @@ -3901,8 +3951,12 @@ pub fn enum_variants(cx: ctxt, id: ast::DefId) -> @~[@VariantInfo] { _ => cx.sess.bug("enum_variants: id not bound to an enum") } }; - cx.enum_var_cache.insert(id, result); - result + + { + let mut enum_var_cache = cx.enum_var_cache.borrow_mut(); + enum_var_cache.get().insert(id, result); + result + } } @@ -3927,22 +3981,25 @@ pub fn enum_variant_with_id(cx: ctxt, pub fn lookup_item_type(cx: ctxt, did: ast::DefId) -> ty_param_bounds_and_ty { + let mut tcache = cx.tcache.borrow_mut(); lookup_locally_or_in_crate_store( - "tcache", did, cx.tcache, + "tcache", did, tcache.get(), || csearch::get_type(cx, did)) } pub fn lookup_impl_vtables(cx: ctxt, did: ast::DefId) -> typeck::impl_res { + let mut impl_vtables = cx.impl_vtables.borrow_mut(); lookup_locally_or_in_crate_store( - "impl_vtables", did, cx.impl_vtables, + "impl_vtables", did, impl_vtables.get(), || csearch::get_impl_vtables(cx, did) ) } /// Given the did of a trait, returns its canonical trait ref. pub fn lookup_trait_def(cx: ctxt, did: ast::DefId) -> @ty::TraitDef { - match cx.trait_defs.find(&did) { + let mut trait_defs = cx.trait_defs.borrow_mut(); + match trait_defs.get().find(&did) { Some(&trait_def) => { // The item is in this crate. The caller should have added it to the // type cache already @@ -3951,7 +4008,7 @@ pub fn lookup_trait_def(cx: ctxt, did: ast::DefId) -> @ty::TraitDef { None => { assert!(did.crate != ast::LOCAL_CRATE); let trait_def = @csearch::get_trait_def(cx, did); - cx.trait_defs.insert(did, trait_def); + trait_defs.get().insert(did, trait_def); return trait_def; } } @@ -4022,15 +4079,17 @@ pub fn lookup_field_type(tcx: ctxt, -> ty::t { let t = if id.crate == ast::LOCAL_CRATE { node_id_to_type(tcx, id.node) - } - else { - match tcx.tcache.find(&id) { - Some(&ty_param_bounds_and_ty {ty, ..}) => ty, - None => { - let tpt = csearch::get_field_type(tcx, struct_id, id); - tcx.tcache.insert(id, tpt); - tpt.ty - } + } else { + { + let mut tcache = tcx.tcache.borrow_mut(); + match tcache.get().find(&id) { + Some(&ty_param_bounds_and_ty {ty, ..}) => ty, + None => { + let tpt = csearch::get_field_type(tcx, struct_id, id); + tcache.get().insert(id, tpt); + tpt.ty + } + } } }; subst(tcx, substs, t) @@ -4213,13 +4272,20 @@ pub fn normalize_ty(cx: ctxt, t: t) -> t { fn tcx(&self) -> ty::ctxt { **self } fn fold_ty(&mut self, t: ty::t) -> ty::t { - match self.tcx().normalized_cache.find_copy(&t) { + let normalized_opt = { + let normalized_cache = self.tcx().normalized_cache.borrow(); + normalized_cache.get().find_copy(&t) + }; + match normalized_opt { Some(u) => { return u; } None => { let t_norm = ty_fold::super_fold_ty(self, t); - self.tcx().normalized_cache.insert(t, t_norm); + let mut normalized_cache = self.tcx() + .normalized_cache + .borrow_mut(); + normalized_cache.get().insert(t, t_norm); return t_norm; } } @@ -4395,14 +4461,16 @@ pub fn count_traits_and_supertraits(tcx: ctxt, pub fn get_tydesc_ty(tcx: ctxt) -> Result { tcx.lang_items.require(TyDescStructLangItem).map(|tydesc_lang_item| { - tcx.intrinsic_defs.find_copy(&tydesc_lang_item) + let intrinsic_defs = tcx.intrinsic_defs.borrow(); + intrinsic_defs.get().find_copy(&tydesc_lang_item) .expect("Failed to resolve TyDesc") }) } pub fn get_opaque_ty(tcx: ctxt) -> Result { tcx.lang_items.require(OpaqueStructLangItem).map(|opaque_lang_item| { - tcx.intrinsic_defs.find_copy(&opaque_lang_item) + let intrinsic_defs = tcx.intrinsic_defs.borrow(); + intrinsic_defs.get().find_copy(&opaque_lang_item) .expect("Failed to resolve Opaque") }) } @@ -4429,8 +4497,9 @@ pub fn visitor_object_ty(tcx: ctxt, } pub fn item_variances(tcx: ctxt, item_id: ast::DefId) -> @ItemVariances { + let mut item_variance_map = tcx.item_variance_map.borrow_mut(); lookup_locally_or_in_crate_store( - "item_variance_map", item_id, tcx.item_variance_map, + "item_variance_map", item_id, item_variance_map.get(), || @csearch::get_item_variances(tcx.cstore, item_id)) } @@ -4439,17 +4508,19 @@ fn record_trait_implementation(tcx: ctxt, trait_def_id: DefId, implementation: @Impl) { let implementation_list; - match tcx.trait_impls.find(&trait_def_id) { + let mut trait_impls = tcx.trait_impls.borrow_mut(); + match trait_impls.get().find(&trait_def_id) { None => { - implementation_list = @mut ~[]; - tcx.trait_impls.insert(trait_def_id, implementation_list); + implementation_list = @RefCell::new(~[]); + trait_impls.get().insert(trait_def_id, implementation_list); } Some(&existing_implementation_list) => { implementation_list = existing_implementation_list } } - implementation_list.push(implementation); + let mut implementation_list = implementation_list.borrow_mut(); + implementation_list.get().push(implementation); } /// Populates the type context with all the implementations for the given type @@ -4459,8 +4530,11 @@ pub fn populate_implementations_for_type_if_necessary(tcx: ctxt, if type_id.crate == LOCAL_CRATE { return } - if tcx.populated_external_types.contains(&type_id) { - return + { + let populated_external_types = tcx.populated_external_types.borrow(); + if populated_external_types.get().contains(&type_id) { + return + } } csearch::each_implementation_for_type(tcx.sess.cstore, type_id, @@ -4480,30 +4554,40 @@ pub fn populate_implementations_for_type_if_necessary(tcx: ctxt, // the map. This is a bit unfortunate. for method in implementation.methods.iter() { for source in method.provided_source.iter() { - tcx.provided_method_sources.insert(method.def_id, *source); + let mut provided_method_sources = + tcx.provided_method_sources.borrow_mut(); + provided_method_sources.get().insert(method.def_id, *source); } } // If this is an inherent implementation, record it. if associated_traits.is_none() { let implementation_list; - match tcx.inherent_impls.find(&type_id) { + let mut inherent_impls = tcx.inherent_impls.borrow_mut(); + match inherent_impls.get().find(&type_id) { None => { - implementation_list = @mut ~[]; - tcx.inherent_impls.insert(type_id, implementation_list); + implementation_list = @RefCell::new(~[]); + inherent_impls.get().insert(type_id, implementation_list); } Some(&existing_implementation_list) => { implementation_list = existing_implementation_list; } } - implementation_list.push(implementation); + { + let mut implementation_list = + implementation_list.borrow_mut(); + implementation_list.get().push(implementation); + } } // Store the implementation info. - tcx.impls.insert(implementation_def_id, implementation); + let mut impls = tcx.impls.borrow_mut(); + impls.get().insert(implementation_def_id, implementation); }); - tcx.populated_external_types.insert(type_id); + let mut populated_external_types = tcx.populated_external_types + .borrow_mut(); + populated_external_types.get().insert(type_id); } /// Populates the type context with all the implementations for the given @@ -4514,8 +4598,12 @@ pub fn populate_implementations_for_trait_if_necessary( if trait_id.crate == LOCAL_CRATE { return } - if tcx.populated_external_traits.contains(&trait_id) { - return + { + let populated_external_traits = tcx.populated_external_traits + .borrow(); + if populated_external_traits.get().contains(&trait_id) { + return + } } csearch::each_implementation_for_trait(tcx.sess.cstore, trait_id, @@ -4529,15 +4617,20 @@ pub fn populate_implementations_for_trait_if_necessary( // the map. This is a bit unfortunate. for method in implementation.methods.iter() { for source in method.provided_source.iter() { - tcx.provided_method_sources.insert(method.def_id, *source); + let mut provided_method_sources = + tcx.provided_method_sources.borrow_mut(); + provided_method_sources.get().insert(method.def_id, *source); } } // Store the implementation info. - tcx.impls.insert(implementation_def_id, implementation); + let mut impls = tcx.impls.borrow_mut(); + impls.get().insert(implementation_def_id, implementation); }); - tcx.populated_external_traits.insert(trait_id); + let mut populated_external_traits = tcx.populated_external_traits + .borrow_mut(); + populated_external_traits.get().insert(trait_id); } /// Given the def_id of an impl, return the def_id of the trait it implements. @@ -4569,7 +4662,12 @@ pub fn trait_of_method(tcx: ctxt, def_id: ast::DefId) if def_id.crate != LOCAL_CRATE { return csearch::get_trait_of_method(tcx.cstore, def_id, tcx); } - match tcx.methods.find(&def_id) { + let method; + { + let methods = tcx.methods.borrow(); + method = methods.get().find(&def_id).map(|method| *method); + } + match method { Some(method) => { match method.container { TraitContainer(def_id) => Some(def_id), @@ -4588,10 +4686,15 @@ pub fn trait_of_method(tcx: ctxt, def_id: ast::DefId) /// Otherwise, return `None`. pub fn trait_method_of_method(tcx: ctxt, def_id: ast::DefId) -> Option { - let name = match tcx.methods.find(&def_id) { - Some(method) => method.ident.name, - None => return None - }; + let method; + { + let methods = tcx.methods.borrow(); + match methods.get().find(&def_id) { + Some(m) => method = *m, + None => return None, + } + } + let name = method.ident.name; match trait_of_method(tcx, def_id) { Some(trait_did) => { let trait_methods = ty::trait_methods(tcx, trait_did); diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index eb17955f05016..0da9db5d5c2e3 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -76,12 +76,10 @@ pub trait AstConv { fn ty_infer(&self, span: Span) -> ty::t; } -pub fn ast_region_to_region( - tcx: ty::ctxt, - lifetime: &ast::Lifetime) - -> ty::Region -{ - let r = match tcx.named_region_map.find(&lifetime.id) { +pub fn ast_region_to_region(tcx: ty::ctxt, lifetime: &ast::Lifetime) + -> ty::Region { + let named_region_map = tcx.named_region_map.borrow(); + let r = match named_region_map.get().find(&lifetime.id) { None => { // should have been recorded by the `resolve_lifetime` pass tcx.sess.span_bug(lifetime.span, "unresolved lifetime"); @@ -321,7 +319,8 @@ pub fn ast_ty_to_ty( // Note that the "bounds must be empty if path is not a trait" // restriction is enforced in the below case for ty_path, which // will run after this as long as the path isn't a trait. - match tcx.def_map.find(&id) { + let def_map = tcx.def_map.borrow(); + match def_map.get().find(&id) { Some(&ast::DefPrimTy(ast::ty_str)) if a_seq_ty.mutbl == ast::MutImmutable => { check_path_args(tcx, path, NO_TPS | NO_REGIONS); return ty::mk_estr(tcx, vst); @@ -383,16 +382,22 @@ pub fn ast_ty_to_ty( let tcx = this.tcx(); - match tcx.ast_ty_to_ty_cache.find(&ast_ty.id) { - Some(&ty::atttce_resolved(ty)) => return ty, - Some(&ty::atttce_unresolved) => { - tcx.sess.span_fatal(ast_ty.span, "illegal recursive type; \ - insert an enum in the cycle, if this is desired"); - } - None => { /* go on */ } + { + let mut ast_ty_to_ty_cache = tcx.ast_ty_to_ty_cache.borrow_mut(); + match ast_ty_to_ty_cache.get().find(&ast_ty.id) { + Some(&ty::atttce_resolved(ty)) => return ty, + Some(&ty::atttce_unresolved) => { + tcx.sess.span_fatal(ast_ty.span, + "illegal recursive type; insert an enum \ + or struct in the cycle, if this is \ + desired"); + } + None => { /* go on */ } + } + ast_ty_to_ty_cache.get().insert(ast_ty.id, ty::atttce_unresolved); } - tcx.ast_ty_to_ty_cache.insert(ast_ty.id, ty::atttce_unresolved); + let typ = match ast_ty.node { ast::ty_nil => ty::mk_nil(), ast::ty_bot => ty::mk_bot(), @@ -457,7 +462,8 @@ pub fn ast_ty_to_ty( ty::mk_closure(tcx, fn_decl) } ast::ty_path(ref path, ref bounds, id) => { - let a_def = match tcx.def_map.find(&id) { + let def_map = tcx.def_map.borrow(); + let a_def = match def_map.get().find(&id) { None => tcx.sess.span_fatal( ast_ty.span, format!("unbound path {}", path_to_str(path, tcx.sess.intr()))), @@ -576,7 +582,8 @@ pub fn ast_ty_to_ty( } }; - tcx.ast_ty_to_ty_cache.insert(ast_ty.id, ty::atttce_resolved(typ)); + let mut ast_ty_to_ty_cache = tcx.ast_ty_to_ty_cache.borrow_mut(); + ast_ty_to_ty_cache.get().insert(ast_ty.id, ty::atttce_resolved(typ)); return typ; } diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 4623c0bc6d865..739437d278d97 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -25,7 +25,7 @@ use syntax::parse::token; use syntax::codemap::Span; use syntax::print::pprust; -pub fn check_match(fcx: @mut FnCtxt, +pub fn check_match(fcx: @FnCtxt, expr: @ast::Expr, discrim: @ast::Expr, arms: &[ast::Arm]) { @@ -102,7 +102,7 @@ pub fn check_match(fcx: @mut FnCtxt, } pub struct pat_ctxt { - fcx: @mut FnCtxt, + fcx: @FnCtxt, map: PatIdMap, } @@ -357,7 +357,8 @@ pub fn check_struct_pat(pcx: &pat_ctxt, pat_id: ast::NodeId, span: Span, let class_fields = ty::lookup_struct_fields(tcx, struct_id); // Check to ensure that the struct is the one specified. - match tcx.def_map.find(&pat_id) { + let def_map = tcx.def_map.borrow(); + match def_map.get().find(&pat_id) { Some(&ast::DefStruct(supplied_def_id)) if supplied_def_id == struct_id => { // OK. @@ -391,7 +392,8 @@ pub fn check_struct_like_enum_variant_pat(pcx: &pat_ctxt, let tcx = pcx.fcx.ccx.tcx; // Find the variant that was specified. - match tcx.def_map.find(&pat_id) { + let def_map = tcx.def_map.borrow(); + match def_map.get().find(&pat_id) { Some(&ast::DefVariant(found_enum_id, variant_id, _)) if found_enum_id == enum_id => { // Get the struct fields from this struct-like enum variant. @@ -461,7 +463,9 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::Pat, expected: ty::t) { } ast::PatEnum(..) | ast::PatIdent(..) if pat_is_const(tcx.def_map, pat) => { - let const_did = ast_util::def_id_of_def(tcx.def_map.get_copy(&pat.id)); + let def_map = tcx.def_map.borrow(); + let const_did = ast_util::def_id_of_def(def_map.get() + .get_copy(&pat.id)); let const_tpt = ty::lookup_item_type(tcx, const_did); demand::suptype(fcx, pat.span, expected, const_tpt.ty); fcx.write_ty(pat.id, const_tpt.ty); @@ -524,14 +528,15 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::Pat, expected: ty::t) { } _ => { // See [Note-Type-error-reporting] in middle/typeck/infer/mod.rs - fcx.infcx().type_error_message_str_with_expected(pat.span, + fcx.infcx().type_error_message_str_with_expected(pat.span, |expected, actual| { expected.map_default(~"", |e| { format!("mismatched types: expected `{}` but found {}", e, actual)})}, Some(expected), ~"a structure pattern", None); - match tcx.def_map.find(&pat.id) { + let def_map = tcx.def_map.borrow(); + match def_map.get().find(&pat.id) { Some(&ast::DefStruct(supplied_def_id)) => { check_struct_pat(pcx, pat.id, pat.span, ty::mk_err(), path, *fields, etc, supplied_def_id, diff --git a/src/librustc/middle/typeck/check/demand.rs b/src/librustc/middle/typeck/check/demand.rs index 5973d791f525c..64b08d481e196 100644 --- a/src/librustc/middle/typeck/check/demand.rs +++ b/src/librustc/middle/typeck/check/demand.rs @@ -20,17 +20,17 @@ use syntax::codemap::Span; // Requires that the two types unify, and prints an error message if they // don't. -pub fn suptype(fcx: @mut FnCtxt, sp: Span, expected: ty::t, actual: ty::t) { +pub fn suptype(fcx: @FnCtxt, sp: Span, expected: ty::t, actual: ty::t) { suptype_with_fn(fcx, sp, false, expected, actual, |sp, e, a, s| { fcx.report_mismatched_types(sp, e, a, s) }) } -pub fn subtype(fcx: @mut FnCtxt, sp: Span, expected: ty::t, actual: ty::t) { +pub fn subtype(fcx: @FnCtxt, sp: Span, expected: ty::t, actual: ty::t) { suptype_with_fn(fcx, sp, true, actual, expected, |sp, a, e, s| { fcx.report_mismatched_types(sp, e, a, s) }) } -pub fn suptype_with_fn(fcx: @mut FnCtxt, +pub fn suptype_with_fn(fcx: @FnCtxt, sp: Span, b_is_expected: bool, ty_a: ty::t, @@ -46,7 +46,7 @@ pub fn suptype_with_fn(fcx: @mut FnCtxt, } } -pub fn eqtype(fcx: @mut FnCtxt, sp: Span, expected: ty::t, actual: ty::t) { +pub fn eqtype(fcx: @FnCtxt, sp: Span, expected: ty::t, actual: ty::t) { match infer::mk_eqty(fcx.infcx(), false, infer::Misc(sp), actual, expected) { Ok(()) => { /* ok */ } Err(ref err) => { @@ -56,10 +56,7 @@ pub fn eqtype(fcx: @mut FnCtxt, sp: Span, expected: ty::t, actual: ty::t) { } // Checks that the type `actual` can be coerced to `expected`. -pub fn coerce(fcx: @mut FnCtxt, - sp: Span, - expected: ty::t, - expr: @ast::Expr) { +pub fn coerce(fcx: @FnCtxt, sp: Span, expected: ty::t, expr: @ast::Expr) { let expr_ty = fcx.expr_ty(expr); match fcx.mk_assignty(expr, expr_ty, expected) { result::Ok(()) => { /* ok */ } diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 22e0a60514fa9..7fc2798c7aa6c 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -95,6 +95,7 @@ use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig; use util::common::indenter; use util::ppaux::Repr; +use std::cell::RefCell; use std::hashmap::HashSet; use std::result; use std::vec; @@ -118,7 +119,7 @@ pub enum AutoderefReceiverFlag { } pub fn lookup( - fcx: @mut FnCtxt, + fcx: @FnCtxt, // In a call `a.b::(...)`: expr: @ast::Expr, // The expression `a.b(...)`. @@ -132,7 +133,7 @@ pub fn lookup( check_traits: CheckTraitsFlag, // Whether we check traits only. autoderef_receiver: AutoderefReceiverFlag) -> Option { - let impl_dups = @mut HashSet::new(); + let impl_dups = @RefCell::new(HashSet::new()); let lcx = LookupContext { fcx: fcx, expr: expr, @@ -141,8 +142,8 @@ pub fn lookup( m_name: m_name, supplied_tps: supplied_tps, impl_dups: impl_dups, - inherent_candidates: @mut ~[], - extension_candidates: @mut ~[], + inherent_candidates: @RefCell::new(~[]), + extension_candidates: @RefCell::new(~[]), deref_args: deref_args, check_traits: check_traits, autoderef_receiver: autoderef_receiver, @@ -168,15 +169,15 @@ pub fn lookup( } pub struct LookupContext<'a> { - fcx: @mut FnCtxt, + fcx: @FnCtxt, expr: @ast::Expr, self_expr: @ast::Expr, callee_id: NodeId, m_name: ast::Name, supplied_tps: &'a [ty::t], - impl_dups: @mut HashSet, - inherent_candidates: @mut ~[Candidate], - extension_candidates: @mut ~[Candidate], + impl_dups: @RefCell>, + inherent_candidates: @RefCell<~[Candidate]>, + extension_candidates: @RefCell<~[Candidate]>, deref_args: check::DerefArgs, check_traits: CheckTraitsFlag, autoderef_receiver: AutoderefReceiverFlag, @@ -278,8 +279,8 @@ impl<'a> LookupContext<'a> { // Candidate collection (see comment at start of file) fn reset_candidates(&self) { - *self.inherent_candidates = ~[]; - *self.extension_candidates = ~[]; + self.inherent_candidates.set(~[]); + self.extension_candidates.set(~[]); } fn push_inherent_candidates(&self, self_ty: ty::t) { @@ -343,20 +344,25 @@ impl<'a> LookupContext<'a> { // If the method being called is associated with a trait, then // find all the impls of that trait. Each of those are // candidates. - let trait_map: &mut resolve::TraitMap = &mut self.fcx.ccx.trait_map; + let trait_map: &resolve::TraitMap = &self.fcx.ccx.trait_map; let opt_applicable_traits = trait_map.find(&self.expr.id); for applicable_traits in opt_applicable_traits.iter() { - for trait_did in applicable_traits.iter() { + let applicable_traits = applicable_traits.borrow(); + for trait_did in applicable_traits.get().iter() { ty::populate_implementations_for_trait_if_necessary( self.tcx(), *trait_did); // Look for explicit implementations. - let opt_impl_infos = self.tcx().trait_impls.find(trait_did); + let trait_impls = self.tcx().trait_impls.borrow(); + let opt_impl_infos = trait_impls.get().find(trait_did); for impl_infos in opt_impl_infos.iter() { - for impl_info in impl_infos.iter() { + let impl_infos = impl_infos.borrow(); + for impl_info in impl_infos.get().iter() { + let mut extension_candidates = + self.extension_candidates.borrow_mut(); self.push_candidates_from_impl( - self.extension_candidates, *impl_info); + extension_candidates.get(), *impl_info); } } @@ -508,7 +514,9 @@ impl<'a> LookupContext<'a> { pos, this_bound_idx); debug!("pushing inherent candidate for param: {:?}", cand); - self.inherent_candidates.push(cand); + let mut inherent_candidates = self.inherent_candidates + .borrow_mut(); + inherent_candidates.get().push(cand); } None => { debug!("trait doesn't contain method: {:?}", @@ -526,11 +534,15 @@ impl<'a> LookupContext<'a> { // metadata if necessary. ty::populate_implementations_for_type_if_necessary(self.tcx(), did); - let opt_impl_infos = self.tcx().inherent_impls.find(&did); + let inherent_impls = self.tcx().inherent_impls.borrow(); + let opt_impl_infos = inherent_impls.get().find(&did); for impl_infos in opt_impl_infos.iter() { - for impl_info in impl_infos.iter() { - self.push_candidates_from_impl( - self.inherent_candidates, *impl_info); + let impl_infos = impl_infos.borrow(); + for impl_info in impl_infos.get().iter() { + let mut inherent_candidates = self.inherent_candidates + .borrow_mut(); + self.push_candidates_from_impl(inherent_candidates.get(), + *impl_info); } } } @@ -538,8 +550,11 @@ impl<'a> LookupContext<'a> { fn push_candidates_from_impl(&self, candidates: &mut ~[Candidate], impl_info: &ty::Impl) { - if !self.impl_dups.insert(impl_info.did) { - return; // already visited + { + let mut impl_dups = self.impl_dups.borrow_mut(); + if !impl_dups.get().insert(impl_info.did) { + return; // already visited + } } debug!("push_candidates_from_impl: {} {} {}", token::interner_get(self.m_name), @@ -821,7 +836,8 @@ impl<'a> LookupContext<'a> { // existing code. debug!("searching inherent candidates"); - match self.consider_candidates(rcvr_ty, self.inherent_candidates) { + let mut inherent_candidates = self.inherent_candidates.borrow_mut(); + match self.consider_candidates(rcvr_ty, inherent_candidates.get()) { None => {} Some(mme) => { return Some(mme); @@ -829,7 +845,8 @@ impl<'a> LookupContext<'a> { } debug!("searching extension candidates"); - match self.consider_candidates(rcvr_ty, self.extension_candidates) { + let mut extension_candidates = self.extension_candidates.borrow_mut(); + match self.consider_candidates(rcvr_ty, extension_candidates.get()) { None => { return None; } @@ -840,9 +857,9 @@ impl<'a> LookupContext<'a> { } fn consider_candidates(&self, - rcvr_ty: ty::t, - candidates: &mut ~[Candidate]) - -> Option { + rcvr_ty: ty::t, + candidates: &mut ~[Candidate]) + -> Option { // XXX(pcwalton): Do we need to clone here? let relevant_candidates: ~[Candidate] = candidates.iter().map(|c| (*c).clone()). @@ -1151,13 +1168,17 @@ impl<'a> LookupContext<'a> { let bad; match candidate.origin { method_static(method_id) => { - bad = self.tcx().destructors.contains(&method_id); + let destructors = self.tcx().destructors.borrow(); + bad = destructors.get().contains(&method_id); } // XXX: does this properly enforce this on everything now // that self has been merged in? -sully method_param(method_param { trait_id: trait_id, .. }) | method_object(method_object { trait_id: trait_id, .. }) => { - bad = self.tcx().destructor_for_type.contains_key(&trait_id); + let destructor_for_type = self.tcx() + .destructor_for_type + .borrow(); + bad = destructor_for_type.get().contains_key(&trait_id); } } @@ -1245,7 +1266,7 @@ impl<'a> LookupContext<'a> { } } - fn rcvr_matches_ty(fcx: @mut FnCtxt, + fn rcvr_matches_ty(fcx: @FnCtxt, rcvr_ty: ty::t, candidate: &Candidate) -> bool { match candidate.rcvr_match_condition { @@ -1320,7 +1341,7 @@ impl<'a> LookupContext<'a> { ty::item_path_str(self.tcx(), did))); } - fn infcx(&self) -> @mut infer::InferCtxt { + fn infcx(&self) -> @infer::InferCtxt { self.fcx.inh.infcx } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 799f1a879da73..74575ba3517fe 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -110,6 +110,7 @@ use util::common::{block_query, indenter, loop_query}; use util::ppaux::UserString; use util::ppaux; +use std::cell::{Cell, RefCell}; use std::hashmap::HashMap; use std::result; use std::util::replace; @@ -156,14 +157,14 @@ pub struct SelfInfo { /// `bar()` will each have their own `FnCtxt`, but they will /// share the inherited fields. pub struct Inherited { - infcx: @mut infer::InferCtxt, - locals: @mut HashMap, + infcx: @infer::InferCtxt, + locals: @RefCell>, param_env: ty::ParameterEnvironment, // Temporary tables: - node_types: @mut HashMap, - node_type_substs: @mut HashMap, - adjustments: @mut HashMap, + node_types: RefCell>, + node_type_substs: RefCell>, + adjustments: RefCell>, method_map: method_map, vtable_map: vtable_map, } @@ -226,7 +227,7 @@ pub struct FnCtxt { err_count_on_creation: uint, ret_ty: ty::t, - ps: PurityState, + ps: RefCell, // Sometimes we generate region pointers where the precise region // to use is not known. For example, an expression like `&x.f` @@ -241,7 +242,7 @@ pub struct FnCtxt { // inference selects the ultimate value. Finally, borrowck is // charged with guaranteeing that the value whose address was taken // can actually be made to live as long as it needs to live. - region_lb: ast::NodeId, + region_lb: Cell, // Says whether we're inside a for loop, in a do block // or neither. Helps with error messages involving the @@ -250,7 +251,7 @@ pub struct FnCtxt { inh: @Inherited, - ccx: @mut CrateCtxt, + ccx: @CrateCtxt, } impl Inherited { @@ -259,32 +260,32 @@ impl Inherited { -> Inherited { Inherited { infcx: infer::new_infer_ctxt(tcx), - locals: @mut HashMap::new(), + locals: @RefCell::new(HashMap::new()), param_env: param_env, - node_types: @mut HashMap::new(), - node_type_substs: @mut HashMap::new(), - adjustments: @mut HashMap::new(), - method_map: @mut HashMap::new(), - vtable_map: @mut HashMap::new(), + node_types: RefCell::new(HashMap::new()), + node_type_substs: RefCell::new(HashMap::new()), + adjustments: RefCell::new(HashMap::new()), + method_map: @RefCell::new(HashMap::new()), + vtable_map: @RefCell::new(HashMap::new()), } } } // Used by check_const and check_enum_variants -pub fn blank_fn_ctxt(ccx: @mut CrateCtxt, +pub fn blank_fn_ctxt(ccx: @CrateCtxt, rty: ty::t, region_bnd: ast::NodeId) - -> @mut FnCtxt { + -> @FnCtxt { // It's kind of a kludge to manufacture a fake function context // and statement context, but we might as well do write the code only once let param_env = ty::ParameterEnvironment { free_substs: substs::empty(), self_param_bound: None, type_param_bounds: ~[] }; - @mut FnCtxt { + @FnCtxt { err_count_on_creation: ccx.tcx.sess.err_count(), ret_ty: rty, - ps: PurityState::function(ast::impure_fn, 0), - region_lb: region_bnd, + ps: RefCell::new(PurityState::function(ast::impure_fn, 0)), + region_lb: Cell::new(region_bnd), fn_kind: Vanilla, inh: @Inherited::new(ccx.tcx, param_env), ccx: ccx @@ -301,7 +302,7 @@ impl ExprTyProvider for FnCtxt { } } -struct CheckItemTypesVisitor { ccx: @mut CrateCtxt } +struct CheckItemTypesVisitor { ccx: @CrateCtxt } impl Visitor<()> for CheckItemTypesVisitor { fn visit_item(&mut self, i:@ast::item, _:()) { @@ -310,12 +311,12 @@ impl Visitor<()> for CheckItemTypesVisitor { } } -pub fn check_item_types(ccx: @mut CrateCtxt, crate: &ast::Crate) { +pub fn check_item_types(ccx: @CrateCtxt, crate: &ast::Crate) { let mut visit = CheckItemTypesVisitor { ccx: ccx }; visit::walk_crate(&mut visit, crate, ()); } -pub fn check_bare_fn(ccx: @mut CrateCtxt, +pub fn check_bare_fn(ccx: @CrateCtxt, decl: &ast::fn_decl, body: ast::P, id: ast::NodeId, @@ -339,7 +340,7 @@ pub fn check_bare_fn(ccx: @mut CrateCtxt, } struct GatherLocalsVisitor { - fcx: @mut FnCtxt, + fcx: @FnCtxt, tcx: ty::ctxt, } @@ -350,11 +351,13 @@ impl GatherLocalsVisitor { // infer the variable's type let var_id = self.fcx.infcx().next_ty_var_id(); let var_ty = ty::mk_var(self.fcx.tcx(), var_id); - self.fcx.inh.locals.insert(nid, var_ty); + let mut locals = self.fcx.inh.locals.borrow_mut(); + locals.get().insert(nid, var_ty); } Some(typ) => { // take type that the user specified - self.fcx.inh.locals.insert(nid, typ); + let mut locals = self.fcx.inh.locals.borrow_mut(); + locals.get().insert(nid, typ); } } } @@ -368,10 +371,13 @@ impl Visitor<()> for GatherLocalsVisitor { _ => Some(self.fcx.to_ty(local.ty)) }; self.assign(local.id, o_ty); - debug!("Local variable {} is assigned type {}", - self.fcx.pat_to_str(local.pat), - self.fcx.infcx().ty_to_str( - self.fcx.inh.locals.get_copy(&local.id))); + { + let locals = self.fcx.inh.locals.borrow(); + debug!("Local variable {} is assigned type {}", + self.fcx.pat_to_str(local.pat), + self.fcx.infcx().ty_to_str( + locals.get().get_copy(&local.id))); + } visit::walk_local(self, local, ()); } @@ -381,10 +387,13 @@ impl Visitor<()> for GatherLocalsVisitor { ast::PatIdent(_, ref path, _) if pat_util::pat_is_binding(self.fcx.ccx.tcx.def_map, p) => { self.assign(p.id, None); - debug!("Pattern binding {} is assigned to {}", - self.tcx.sess.str_of(path.segments[0].identifier), - self.fcx.infcx().ty_to_str( - self.fcx.inh.locals.get_copy(&p.id))); + { + let locals = self.fcx.inh.locals.borrow(); + debug!("Pattern binding {} is assigned to {}", + self.tcx.sess.str_of(path.segments[0].identifier), + self.fcx.infcx().ty_to_str( + locals.get().get_copy(&p.id))); + } } _ => {} } @@ -406,7 +415,7 @@ impl Visitor<()> for GatherLocalsVisitor { } -pub fn check_fn(ccx: @mut CrateCtxt, +pub fn check_fn(ccx: @CrateCtxt, opt_self_info: Option, purity: ast::purity, fn_sig: &ty::FnSig, @@ -414,7 +423,7 @@ pub fn check_fn(ccx: @mut CrateCtxt, id: ast::NodeId, body: ast::P, fn_kind: FnKind, - inherited: @Inherited) -> @mut FnCtxt + inherited: @Inherited) -> @FnCtxt { /*! * Helper used by check_bare_fn and check_expr_fn. Does the @@ -457,12 +466,12 @@ pub fn check_fn(ccx: @mut CrateCtxt, // Create the function context. This is either derived from scratch or, // in the case of function expressions, based on the outer context. - let fcx: @mut FnCtxt = { - @mut FnCtxt { + let fcx: @FnCtxt = { + @FnCtxt { err_count_on_creation: err_count_on_creation, ret_ty: ret_ty, - ps: PurityState::function(purity, id), - region_lb: body.id, + ps: RefCell::new(PurityState::function(purity, id)), + region_lb: Cell::new(body.id), fn_kind: fn_kind, inh: inherited, ccx: ccx @@ -496,7 +505,7 @@ pub fn check_fn(ccx: @mut CrateCtxt, return fcx; - fn gather_locals(fcx: @mut FnCtxt, + fn gather_locals(fcx: @FnCtxt, decl: &ast::fn_decl, body: ast::P, arg_tys: &[ty::t], @@ -508,9 +517,10 @@ pub fn check_fn(ccx: @mut CrateCtxt, // Add the self parameter for self_info in opt_self_info.iter() { visit.assign(self_info.self_id, Some(self_info.self_ty)); + let locals = fcx.inh.locals.borrow(); debug!("self is assigned to {}", fcx.infcx().ty_to_str( - fcx.inh.locals.get_copy(&self_info.self_id))); + locals.get().get_copy(&self_info.self_id))); } // Add formal parameters. @@ -555,7 +565,7 @@ pub fn check_no_duplicate_fields(tcx: ty::ctxt, } } -pub fn check_struct(ccx: @mut CrateCtxt, id: ast::NodeId, span: Span) { +pub fn check_struct(ccx: @CrateCtxt, id: ast::NodeId, span: Span) { let tcx = ccx.tcx; // Check that the class is instantiable @@ -566,7 +576,7 @@ pub fn check_struct(ccx: @mut CrateCtxt, id: ast::NodeId, span: Span) { } } -pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) { +pub fn check_item(ccx: @CrateCtxt, it: @ast::item) { debug!("check_item(it.id={}, it.ident={})", it.id, ty::item_path_str(ccx.tcx, local_def(it.id))); @@ -669,7 +679,7 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) { } } -fn check_method_body(ccx: @mut CrateCtxt, +fn check_method_body(ccx: @CrateCtxt, item_generics: &ty::Generics, self_bound: Option<@ty::TraitRef>, method: @ast::method) { @@ -721,7 +731,7 @@ fn check_method_body(ccx: @mut CrateCtxt, param_env); } -fn check_impl_methods_against_trait(ccx: @mut CrateCtxt, +fn check_impl_methods_against_trait(ccx: @CrateCtxt, impl_span: Span, impl_generics: &ty::Generics, ast_trait_ref: &ast::trait_ref, @@ -1044,7 +1054,7 @@ impl AstConv for FnCtxt { } impl FnCtxt { - pub fn infcx(&self) -> @mut infer::InferCtxt { + pub fn infcx(&self) -> @infer::InferCtxt { self.inh.infcx } @@ -1060,7 +1070,7 @@ impl FnCtxt { } } -impl RegionScope for @mut infer::InferCtxt { +impl RegionScope for @infer::InferCtxt { fn anon_regions(&self, span: Span, count: uint) -> Result<~[ty::Region], ()> { @@ -1078,7 +1088,8 @@ impl FnCtxt { } pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t { - match self.inh.locals.find(&nid) { + let locals = self.inh.locals.borrow(); + match locals.get().find(&nid) { Some(&t) => t, None => { self.tcx().sess.span_bug( @@ -1089,14 +1100,15 @@ impl FnCtxt { } pub fn block_region(&self) -> ty::Region { - ty::ReScope(self.region_lb) + ty::ReScope(self.region_lb.get()) } #[inline] pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) { debug!("write_ty({}, {}) in fcx {}", node_id, ppaux::ty_to_str(self.tcx(), ty), self.tag()); - self.inh.node_types.insert(node_id, ty); + let mut node_types = self.inh.node_types.borrow_mut(); + node_types.get().insert(node_id, ty); } pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::substs) { @@ -1105,7 +1117,9 @@ impl FnCtxt { node_id, ty::substs_to_str(self.tcx(), &substs), self.tag()); - self.inh.node_type_substs.insert(node_id, substs); + + let mut node_type_substs = self.inh.node_type_substs.borrow_mut(); + node_type_substs.get().insert(node_id, substs); } } @@ -1134,7 +1148,8 @@ impl FnCtxt { node_id: ast::NodeId, adj: @ty::AutoAdjustment) { debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj); - self.inh.adjustments.insert(node_id, adj); + let mut adjustments = self.inh.adjustments.borrow_mut(); + adjustments.get().insert(node_id, adj); } pub fn write_nil(&self, node_id: ast::NodeId) { @@ -1143,7 +1158,7 @@ impl FnCtxt { pub fn write_bot(&self, node_id: ast::NodeId) { self.write_ty(node_id, ty::mk_bot()); } - pub fn write_error(@mut self, node_id: ast::NodeId) { + pub fn write_error(&self, node_id: ast::NodeId) { self.write_ty(node_id, ty::mk_err()); } @@ -1156,7 +1171,8 @@ impl FnCtxt { } pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t { - match self.inh.node_types.find(&ex.id) { + let node_types = self.inh.node_types.borrow(); + match node_types.get().find(&ex.id) { Some(&t) => t, None => { self.tcx().sess.bug(format!("no type for expr in fcx {}", @@ -1166,7 +1182,8 @@ impl FnCtxt { } pub fn node_ty(&self, id: ast::NodeId) -> ty::t { - match self.inh.node_types.find(&id) { + let node_types = self.inh.node_types.borrow(); + match node_types.get().find(&id) { Some(&t) => t, None => { self.tcx().sess.bug( @@ -1180,7 +1197,8 @@ impl FnCtxt { } pub fn node_ty_substs(&self, id: ast::NodeId) -> ty::substs { - match self.inh.node_type_substs.find(&id) { + let mut node_type_substs = self.inh.node_type_substs.borrow_mut(); + match node_type_substs.get().find(&id) { Some(ts) => (*ts).clone(), None => { self.tcx().sess.bug( @@ -1196,7 +1214,8 @@ impl FnCtxt { id: ast::NodeId, f: |&ty::substs| -> bool) -> bool { - match self.inh.node_type_substs.find(&id) { + let node_type_substs = self.inh.node_type_substs.borrow(); + match node_type_substs.get().find(&id) { Some(s) => f(s), None => true } @@ -1257,11 +1276,11 @@ impl FnCtxt { infer::mk_subr(self.infcx(), a_is_expected, origin, sub, sup) } - pub fn with_region_lb(@mut self, lb: ast::NodeId, f: || -> R) -> R { - let old_region_lb = self.region_lb; - self.region_lb = lb; + pub fn with_region_lb(&self, lb: ast::NodeId, f: || -> R) -> R { + let old_region_lb = self.region_lb.get(); + self.region_lb.set(lb); let v = f(); - self.region_lb = old_region_lb; + self.region_lb.set(old_region_lb); v } @@ -1294,7 +1313,7 @@ impl FnCtxt { } } -pub fn do_autoderef(fcx: @mut FnCtxt, sp: Span, t: ty::t) -> (ty::t, uint) { +pub fn do_autoderef(fcx: @FnCtxt, sp: Span, t: ty::t) -> (ty::t, uint) { /*! * * Autoderefs the type `t` as many times as possible, returning @@ -1351,7 +1370,7 @@ pub fn do_autoderef(fcx: @mut FnCtxt, sp: Span, t: ty::t) -> (ty::t, uint) { } // AST fragment checking -pub fn check_lit(fcx: @mut FnCtxt, lit: @ast::lit) -> ty::t { +pub fn check_lit(fcx: @FnCtxt, lit: @ast::lit) -> ty::t { let tcx = fcx.ccx.tcx; match lit.node { @@ -1379,7 +1398,7 @@ pub fn check_lit(fcx: @mut FnCtxt, lit: @ast::lit) -> ty::t { } } -pub fn valid_range_bounds(ccx: @mut CrateCtxt, +pub fn valid_range_bounds(ccx: @CrateCtxt, from: @ast::Expr, to: @ast::Expr) -> Option { @@ -1390,7 +1409,7 @@ pub fn valid_range_bounds(ccx: @mut CrateCtxt, } pub fn check_expr_has_type( - fcx: @mut FnCtxt, expr: @ast::Expr, + fcx: @FnCtxt, expr: @ast::Expr, expected: ty::t) { check_expr_with_unifier(fcx, expr, Some(expected), || { demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)); @@ -1398,7 +1417,7 @@ pub fn check_expr_has_type( } pub fn check_expr_coercable_to_type( - fcx: @mut FnCtxt, expr: @ast::Expr, + fcx: @FnCtxt, expr: @ast::Expr, expected: ty::t) { check_expr_with_unifier(fcx, expr, Some(expected), || { demand::coerce(fcx, expr.span, expected, expr) @@ -1406,18 +1425,18 @@ pub fn check_expr_coercable_to_type( } pub fn check_expr_with_hint( - fcx: @mut FnCtxt, expr: @ast::Expr, + fcx: @FnCtxt, expr: @ast::Expr, expected: ty::t) { check_expr_with_unifier(fcx, expr, Some(expected), || ()) } pub fn check_expr_with_opt_hint( - fcx: @mut FnCtxt, expr: @ast::Expr, + fcx: @FnCtxt, expr: @ast::Expr, expected: Option) { check_expr_with_unifier(fcx, expr, expected, || ()) } -pub fn check_expr(fcx: @mut FnCtxt, expr: @ast::Expr) { +pub fn check_expr(fcx: @FnCtxt, expr: @ast::Expr) { check_expr_with_unifier(fcx, expr, None, || ()) } @@ -1489,7 +1508,7 @@ fn generics_of_static_method_container(type_context: ty::ctxt, // Verifies that type parameters supplied in paths are in the right // locations. -fn check_type_parameter_positions_in_path(function_context: @mut FnCtxt, +fn check_type_parameter_positions_in_path(function_context: @FnCtxt, path: &ast::Path, def: ast::Def) { // We only care about checking the case in which the path has two or @@ -1623,14 +1642,14 @@ fn check_type_parameter_positions_in_path(function_context: @mut FnCtxt, /// Note that inspecting a type's structure *directly* may expose the fact /// that there are actually multiple representations for both `ty_err` and /// `ty_bot`, so avoid that when err and bot need to be handled differently. -pub fn check_expr_with_unifier(fcx: @mut FnCtxt, +pub fn check_expr_with_unifier(fcx: @FnCtxt, expr: @ast::Expr, expected: Option, unifier: ||) { debug!(">> typechecking"); fn check_method_argument_types( - fcx: @mut FnCtxt, + fcx: @FnCtxt, sp: Span, method_fn_ty: ty::t, callee_expr: @ast::Expr, @@ -1659,7 +1678,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } - fn check_argument_types(fcx: @mut FnCtxt, + fn check_argument_types(fcx: @FnCtxt, sp: Span, fn_inputs: &[ty::t], callee_expr: @ast::Expr, @@ -1809,7 +1828,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } // A generic function for checking assignment expressions - fn check_assignment(fcx: @mut FnCtxt, + fn check_assignment(fcx: @FnCtxt, lhs: @ast::Expr, rhs: @ast::Expr, id: ast::NodeId) { @@ -1820,7 +1839,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // The callee checks for bot / err, we don't need to } - fn write_call(fcx: @mut FnCtxt, + fn write_call(fcx: @FnCtxt, call_expr: @ast::Expr, output: ty::t, sugar: ast::CallSugar) { @@ -1841,7 +1860,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } // A generic function for doing all of the checking for call expressions - fn check_call(fcx: @mut FnCtxt, + fn check_call(fcx: @FnCtxt, callee_id: ast::NodeId, call_expr: @ast::Expr, f: @ast::Expr, @@ -1903,7 +1922,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } // Checks a method call. - fn check_method_call(fcx: @mut FnCtxt, + fn check_method_call(fcx: @FnCtxt, callee_id: ast::NodeId, expr: @ast::Expr, rcvr: @ast::Expr, @@ -1931,7 +1950,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, AutoderefReceiver) { Some(ref entry) => { let method_map = fcx.inh.method_map; - method_map.insert(expr.id, (*entry)); + let mut method_map = method_map.borrow_mut(); + method_map.get().insert(expr.id, (*entry)); } None => { debug!("(checking method call) failing expr is {}", expr.id); @@ -1963,7 +1983,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // A generic function for checking the then and else in an if // or if-check - fn check_then_else(fcx: @mut FnCtxt, + fn check_then_else(fcx: @FnCtxt, cond_expr: @ast::Expr, then_blk: &ast::Block, opt_else_expr: Option<@ast::Expr>, @@ -2002,7 +2022,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, fcx.write_ty(id, if_ty); } - fn lookup_op_method(fcx: @mut FnCtxt, + fn lookup_op_method(fcx: @FnCtxt, callee_id: ast::NodeId, op_ex: @ast::Expr, self_ex: @ast::Expr, @@ -2021,7 +2041,10 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, Some(ref origin) => { let method_ty = fcx.node_ty(callee_id); let method_map = fcx.inh.method_map; - method_map.insert(op_ex.id, *origin); + { + let mut method_map = method_map.borrow_mut(); + method_map.get().insert(op_ex.id, *origin); + } check_method_argument_types(fcx, op_ex.span, method_ty, op_ex, args, ast::NoSugar, deref_args) @@ -2040,7 +2063,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } // could be either a expr_binop or an expr_assign_binop - fn check_binop(fcx: @mut FnCtxt, + fn check_binop(fcx: @FnCtxt, callee_id: ast::NodeId, expr: @ast::Expr, op: ast::BinOp, @@ -2128,7 +2151,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } - fn check_user_binop(fcx: @mut FnCtxt, + fn check_user_binop(fcx: @FnCtxt, callee_id: ast::NodeId, ex: @ast::Expr, lhs_expr: @ast::Expr, @@ -2170,7 +2193,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, ty::mk_err() } - fn check_user_unop(fcx: @mut FnCtxt, + fn check_user_unop(fcx: @FnCtxt, callee_id: ast::NodeId, op_str: &str, mname: &str, @@ -2196,7 +2219,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // resolution is not possible (e.g., no constraints yet present), just // returns `none`. fn unpack_expected( - fcx: @mut FnCtxt, + fcx: @FnCtxt, expected: Option, unpack: |&ty::sty| -> Option) -> Option { @@ -2211,7 +2234,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } - fn check_expr_fn(fcx: @mut FnCtxt, + fn check_expr_fn(fcx: @FnCtxt, expr: @ast::Expr, ast_sigil_opt: Option, decl: &ast::fn_decl, @@ -2306,7 +2329,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, fcx.write_ty(expr.id, fty); let (inherited_purity, id) = - ty::determine_inherited_purity((fcx.ps.purity, fcx.ps.def), + ty::determine_inherited_purity((fcx.ps.get().purity, + fcx.ps.get().def), (purity, expr.id), sigil); @@ -2316,7 +2340,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // Check field access expressions - fn check_field(fcx: @mut FnCtxt, + fn check_field(fcx: @FnCtxt, expr: @ast::Expr, base: @ast::Expr, field: ast::Name, @@ -2387,7 +2411,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, fcx.write_error(expr.id); } - fn check_struct_or_variant_fields(fcx: @mut FnCtxt, + fn check_struct_or_variant_fields(fcx: @FnCtxt, struct_ty: ty::t, span: Span, class_id: ast::DefId, @@ -2480,7 +2504,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } } - fn check_struct_constructor(fcx: @mut FnCtxt, + fn check_struct_constructor(fcx: @FnCtxt, id: ast::NodeId, span: codemap::Span, class_id: ast::DefId, @@ -2538,7 +2562,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, fcx.write_ty(id, struct_type); } - fn check_struct_enum_variant(fcx: @mut FnCtxt, + fn check_struct_enum_variant(fcx: @FnCtxt, id: ast::NodeId, span: codemap::Span, enum_id: ast::DefId, @@ -3069,7 +3093,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, _ => false } } - fn types_compatible(fcx: @mut FnCtxt, sp: Span, + fn types_compatible(fcx: @FnCtxt, sp: Span, t1: ty::t, t2: ty::t) -> bool { if !is_vec(t1) { false @@ -3176,7 +3200,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } ast::ExprStruct(ref path, ref fields, base_expr) => { // Resolve the path. - match tcx.def_map.find(&id) { + let def_map = tcx.def_map.borrow(); + match def_map.get().find(&id) { Some(&ast::DefStruct(type_def_id)) => { check_struct_constructor(fcx, id, expr.span, type_def_id, *fields, base_expr); @@ -3257,7 +3282,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, unifier(); } -pub fn require_integral(fcx: @mut FnCtxt, sp: Span, t: ty::t) { +pub fn require_integral(fcx: @FnCtxt, sp: Span, t: ty::t) { if !type_is_integral(fcx, sp, t) { fcx.type_error_message(sp, |actual| { format!("mismatched types: expected integral type but found `{}`", @@ -3266,7 +3291,7 @@ pub fn require_integral(fcx: @mut FnCtxt, sp: Span, t: ty::t) { } } -pub fn check_decl_initializer(fcx: @mut FnCtxt, +pub fn check_decl_initializer(fcx: @FnCtxt, nid: ast::NodeId, init: @ast::Expr) { @@ -3274,7 +3299,7 @@ pub fn check_decl_initializer(fcx: @mut FnCtxt, check_expr_coercable_to_type(fcx, init, local_ty) } -pub fn check_decl_local(fcx: @mut FnCtxt, local: @ast::Local) { +pub fn check_decl_local(fcx: @FnCtxt, local: @ast::Local) { let tcx = fcx.ccx.tcx; let t = fcx.local_ty(local.span, local.id); @@ -3302,7 +3327,7 @@ pub fn check_decl_local(fcx: @mut FnCtxt, local: @ast::Local) { } } -pub fn check_stmt(fcx: @mut FnCtxt, stmt: @ast::Stmt) { +pub fn check_stmt(fcx: @FnCtxt, stmt: @ast::Stmt) { let node_id; let mut saw_bot = false; let mut saw_err = false; @@ -3347,7 +3372,7 @@ pub fn check_stmt(fcx: @mut FnCtxt, stmt: @ast::Stmt) { } } -pub fn check_block_no_value(fcx: @mut FnCtxt, blk: &ast::Block) { +pub fn check_block_no_value(fcx: @FnCtxt, blk: &ast::Block) { check_block_with_expected(fcx, blk, Some(ty::mk_nil())); let blkty = fcx.node_ty(blk.id); if ty::type_is_error(blkty) { @@ -3362,15 +3387,18 @@ pub fn check_block_no_value(fcx: @mut FnCtxt, blk: &ast::Block) { } } -pub fn check_block(fcx0: @mut FnCtxt, blk: &ast::Block) { +pub fn check_block(fcx0: @FnCtxt, blk: &ast::Block) { check_block_with_expected(fcx0, blk, None) } -pub fn check_block_with_expected(fcx: @mut FnCtxt, +pub fn check_block_with_expected(fcx: @FnCtxt, blk: &ast::Block, expected: Option) { - let purity_state = fcx.ps.recurse(blk); - let prev = replace(&mut fcx.ps, purity_state); + let prev = { + let mut fcx_ps = fcx.ps.borrow_mut(); + let purity_state = fcx_ps.get().recurse(blk); + replace(fcx_ps.get(), purity_state) + }; fcx.with_region_lb(blk.id, || { let mut warned = false; @@ -3427,20 +3455,23 @@ pub fn check_block_with_expected(fcx: @mut FnCtxt, }; }); - fcx.ps = prev; + fcx.ps.set(prev); } -pub fn check_const(ccx: @mut CrateCtxt, +pub fn check_const(ccx: @CrateCtxt, sp: Span, e: @ast::Expr, id: ast::NodeId) { let rty = ty::node_id_to_type(ccx.tcx, id); let fcx = blank_fn_ctxt(ccx, rty, e.id); - let declty = fcx.ccx.tcx.tcache.get(&local_def(id)).ty; + let declty = { + let tcache = fcx.ccx.tcx.tcache.borrow(); + tcache.get().get(&local_def(id)).ty + }; check_const_with_ty(fcx, sp, e, declty); } -pub fn check_const_with_ty(fcx: @mut FnCtxt, +pub fn check_const_with_ty(fcx: @FnCtxt, _: Span, e: @ast::Expr, declty: ty::t) { @@ -3503,15 +3534,15 @@ pub fn check_simd(tcx: ty::ctxt, sp: Span, id: ast::NodeId) { } } -pub fn check_enum_variants(ccx: @mut CrateCtxt, +pub fn check_enum_variants(ccx: @CrateCtxt, sp: Span, vs: &[ast::P], id: ast::NodeId) { - fn disr_in_range(ccx: @mut CrateCtxt, + fn disr_in_range(ccx: @CrateCtxt, ty: attr::IntType, disr: ty::Disr) -> bool { - fn uint_in_range(ccx: @mut CrateCtxt, ty: ast::uint_ty, disr: ty::Disr) -> bool { + fn uint_in_range(ccx: @CrateCtxt, ty: ast::uint_ty, disr: ty::Disr) -> bool { match ty { ast::ty_u8 => disr as u8 as Disr == disr, ast::ty_u16 => disr as u16 as Disr == disr, @@ -3520,7 +3551,7 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt, ast::ty_u => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr) } } - fn int_in_range(ccx: @mut CrateCtxt, ty: ast::int_ty, disr: ty::Disr) -> bool { + fn int_in_range(ccx: @CrateCtxt, ty: ast::int_ty, disr: ty::Disr) -> bool { match ty { ast::ty_i8 => disr as i8 as Disr == disr, ast::ty_i16 => disr as i16 as Disr == disr, @@ -3535,7 +3566,7 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt, } } - fn do_check(ccx: @mut CrateCtxt, + fn do_check(ccx: @CrateCtxt, vs: &[ast::P], id: ast::NodeId, hint: attr::ReprAttr) @@ -3616,7 +3647,10 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt, let variants = do_check(ccx, vs, id, hint); // cache so that ty::enum_variants won't repeat this work - ccx.tcx.enum_var_cache.insert(local_def(id), @variants); + { + let mut enum_var_cache = ccx.tcx.enum_var_cache.borrow_mut(); + enum_var_cache.get().insert(local_def(id), @variants); + } // Check that it is possible to represent this enum: let mut outer = true; @@ -3642,12 +3676,12 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt, check_instantiable(ccx.tcx, sp, id); } -pub fn lookup_def(fcx: @mut FnCtxt, sp: Span, id: ast::NodeId) -> ast::Def { +pub fn lookup_def(fcx: @FnCtxt, sp: Span, id: ast::NodeId) -> ast::Def { lookup_def_ccx(fcx.ccx, sp, id) } // Returns the type parameter count and the type for the given definition. -pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt, +pub fn ty_param_bounds_and_ty_for_def(fcx: @FnCtxt, sp: Span, defn: ast::Def) -> ty_param_bounds_and_ty { @@ -3697,7 +3731,7 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt, // Instantiates the given path, which must refer to an item with the given // number of type parameters and type. -pub fn instantiate_path(fcx: @mut FnCtxt, +pub fn instantiate_path(fcx: @FnCtxt, pth: &ast::Path, tpt: ty_param_bounds_and_ty, def: ast::Def, @@ -3812,7 +3846,7 @@ pub fn instantiate_path(fcx: @mut FnCtxt, // Resolves `typ` by a single level if `typ` is a type variable. If no // resolution is possible, then an error is reported. -pub fn structurally_resolved_type(fcx: @mut FnCtxt, sp: Span, tp: ty::t) +pub fn structurally_resolved_type(fcx: @FnCtxt, sp: Span, tp: ty::t) -> ty::t { match infer::resolve_type(fcx.infcx(), tp, force_tvar) { Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s, @@ -3827,47 +3861,47 @@ pub fn structurally_resolved_type(fcx: @mut FnCtxt, sp: Span, tp: ty::t) } // Returns the one-level-deep structure of the given type. -pub fn structure_of<'a>(fcx: @mut FnCtxt, sp: Span, typ: ty::t) +pub fn structure_of<'a>(fcx: @FnCtxt, sp: Span, typ: ty::t) -> &'a ty::sty { &ty::get(structurally_resolved_type(fcx, sp, typ)).sty } -pub fn type_is_integral(fcx: @mut FnCtxt, sp: Span, typ: ty::t) -> bool { +pub fn type_is_integral(fcx: @FnCtxt, sp: Span, typ: ty::t) -> bool { let typ_s = structurally_resolved_type(fcx, sp, typ); return ty::type_is_integral(typ_s); } -pub fn type_is_scalar(fcx: @mut FnCtxt, sp: Span, typ: ty::t) -> bool { +pub fn type_is_scalar(fcx: @FnCtxt, sp: Span, typ: ty::t) -> bool { let typ_s = structurally_resolved_type(fcx, sp, typ); return ty::type_is_scalar(typ_s); } -pub fn type_is_char(fcx: @mut FnCtxt, sp: Span, typ: ty::t) -> bool { +pub fn type_is_char(fcx: @FnCtxt, sp: Span, typ: ty::t) -> bool { let typ_s = structurally_resolved_type(fcx, sp, typ); return ty::type_is_char(typ_s); } -pub fn type_is_bare_fn(fcx: @mut FnCtxt, sp: Span, typ: ty::t) -> bool { +pub fn type_is_bare_fn(fcx: @FnCtxt, sp: Span, typ: ty::t) -> bool { let typ_s = structurally_resolved_type(fcx, sp, typ); return ty::type_is_bare_fn(typ_s); } -pub fn type_is_unsafe_ptr(fcx: @mut FnCtxt, sp: Span, typ: ty::t) -> bool { +pub fn type_is_unsafe_ptr(fcx: @FnCtxt, sp: Span, typ: ty::t) -> bool { let typ_s = structurally_resolved_type(fcx, sp, typ); return ty::type_is_unsafe_ptr(typ_s); } -pub fn type_is_region_ptr(fcx: @mut FnCtxt, sp: Span, typ: ty::t) -> bool { +pub fn type_is_region_ptr(fcx: @FnCtxt, sp: Span, typ: ty::t) -> bool { let typ_s = structurally_resolved_type(fcx, sp, typ); return ty::type_is_region_ptr(typ_s); } -pub fn type_is_c_like_enum(fcx: @mut FnCtxt, sp: Span, typ: ty::t) -> bool { +pub fn type_is_c_like_enum(fcx: @FnCtxt, sp: Span, typ: ty::t) -> bool { let typ_s = structurally_resolved_type(fcx, sp, typ); return ty::type_is_c_like_enum(fcx.ccx.tcx, typ_s); } -pub fn ast_expr_vstore_to_vstore(fcx: @mut FnCtxt, +pub fn ast_expr_vstore_to_vstore(fcx: @FnCtxt, e: @ast::Expr, v: ast::ExprVstore) -> ty::vstore { @@ -3895,16 +3929,18 @@ pub fn may_break(cx: ty::ctxt, id: ast::NodeId, b: ast::P) -> bool { // nested anywhere inside the loop? (block_query(b, |e| { match e.node { - ast::ExprBreak(Some(_)) => - match cx.def_map.find(&e.id) { + ast::ExprBreak(Some(_)) => { + let def_map = cx.def_map.borrow(); + match def_map.get().find(&e.id) { Some(&ast::DefLabel(loop_id)) if id == loop_id => true, _ => false, - }, + } + } _ => false }})) } -pub fn check_bounds_are_used(ccx: @mut CrateCtxt, +pub fn check_bounds_are_used(ccx: @CrateCtxt, span: Span, tps: &OptVec, ty: ty::t) { @@ -3934,8 +3970,8 @@ pub fn check_bounds_are_used(ccx: @mut CrateCtxt, } } -pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { - fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t { +pub fn check_intrinsic_type(ccx: @CrateCtxt, it: @ast::foreign_item) { + fn param(ccx: @CrateCtxt, n: uint) -> ty::t { ty::mk_param(ccx.tcx, n, local_def(0)) } diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 10120a69c3196..87947a91ccd5c 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -47,14 +47,14 @@ use syntax::visit; use syntax::visit::Visitor; pub struct Rcx { - fcx: @mut FnCtxt, + fcx: @FnCtxt, errors_reported: uint, // id of innermost fn or loop repeating_scope: ast::NodeId, } -fn encl_region_of_def(fcx: @mut FnCtxt, def: ast::Def) -> ty::Region { +fn encl_region_of_def(fcx: @FnCtxt, def: ast::Def) -> ty::Region { let tcx = fcx.tcx(); match def { DefLocal(node_id, _) | DefArg(node_id, _) | @@ -134,14 +134,16 @@ impl Rcx { ty_unadjusted } else { let tcx = self.fcx.tcx(); - let adjustments = self.fcx.inh.adjustments; - ty::adjust_ty(tcx, expr.span, ty_unadjusted, - adjustments.find_copy(&expr.id)) + let adjustment = { + let adjustments = self.fcx.inh.adjustments.borrow(); + adjustments.get().find_copy(&expr.id) + }; + ty::adjust_ty(tcx, expr.span, ty_unadjusted, adjustment) } } } -pub fn regionck_expr(fcx: @mut FnCtxt, e: @ast::Expr) { +pub fn regionck_expr(fcx: @FnCtxt, e: @ast::Expr) { let mut rcx = Rcx { fcx: fcx, errors_reported: 0, repeating_scope: e.id }; let rcx = &mut rcx; @@ -152,7 +154,7 @@ pub fn regionck_expr(fcx: @mut FnCtxt, e: @ast::Expr) { fcx.infcx().resolve_regions(); } -pub fn regionck_fn(fcx: @mut FnCtxt, blk: ast::P) { +pub fn regionck_fn(fcx: @FnCtxt, blk: ast::P) { let mut rcx = Rcx { fcx: fcx, errors_reported: 0, repeating_scope: blk.id }; let rcx = &mut rcx; @@ -247,7 +249,10 @@ fn visit_expr(rcx: &mut Rcx, expr: @ast::Expr) { debug!("regionck::visit_expr(e={}, repeating_scope={:?})", expr.repr(rcx.fcx.tcx()), rcx.repeating_scope); - let has_method_map = rcx.fcx.inh.method_map.contains_key(&expr.id); + let has_method_map = { + let method_map = rcx.fcx.inh.method_map; + method_map.get().contains_key(&expr.id) + }; // Record cleanup scopes, which are used by borrowck to decide the // maximum lifetime of a temporary rvalue. These were derived by @@ -300,7 +305,8 @@ fn visit_expr(rcx: &mut Rcx, expr: @ast::Expr) { // Check any autoderefs or autorefs that appear. { - let r = rcx.fcx.inh.adjustments.find(&expr.id); + let adjustments = rcx.fcx.inh.adjustments.borrow(); + let r = adjustments.get().find(&expr.id); for &adjustment in r.iter() { debug!("adjustment={:?}", adjustment); match *adjustment { @@ -699,7 +705,10 @@ fn constrain_regions_in_type_of_node( // is going to fail anyway, so just stop here and let typeck // report errors later on in the writeback phase. let ty0 = rcx.resolve_node_type(id); - let adjustment = rcx.fcx.inh.adjustments.find_copy(&id); + let adjustment = { + let adjustments = rcx.fcx.inh.adjustments.borrow(); + adjustments.get().find_copy(&id) + }; let ty = ty::adjust_ty(tcx, origin.span(), ty0, adjustment); debug!("constrain_regions_in_type_of_node(\ ty={}, ty0={}, id={}, minimum_lifetime={:?}, adjustment={:?})", @@ -1055,7 +1064,8 @@ pub mod guarantor { let mut expr_ct = categorize_unadjusted(rcx, expr); debug!("before adjustments, cat={:?}", expr_ct.cat); - match rcx.fcx.inh.adjustments.find(&expr.id) { + let adjustments = rcx.fcx.inh.adjustments.borrow(); + match adjustments.get().find(&expr.id) { Some(&@ty::AutoAddEnv(..)) => { // This is basically an rvalue, not a pointer, no regions // involved. @@ -1106,7 +1116,8 @@ pub mod guarantor { debug!("categorize_unadjusted()"); let guarantor = { - if rcx.fcx.inh.method_map.contains_key(&expr.id) { + let method_map = rcx.fcx.inh.method_map.borrow(); + if method_map.get().contains_key(&expr.id) { None } else { guarantor(rcx, expr) diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 401a0ea898bec..f2899cb634002 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -24,6 +24,7 @@ use middle::subst::Subst; use util::common::indenter; use util::ppaux; +use std::cell::RefCell; use std::hashmap::HashSet; use std::result; use syntax::ast; @@ -70,7 +71,7 @@ pub struct LocationInfo { /// A vtable context includes an inference context, a crate context, and a /// callback function to call in case of type error. pub struct VtableContext<'a> { - infcx: @mut infer::InferCtxt, + infcx: @infer::InferCtxt, param_env: &'a ty::ParameterEnvironment, } @@ -329,9 +330,15 @@ fn search_for_vtable(vcx: &VtableContext, // XXX: this is a bad way to do this, since we do // pointless allocations. - let impls = tcx.trait_impls.find(&trait_ref.def_id).map_default(@mut ~[], |x| *x); + let impls = { + let trait_impls = tcx.trait_impls.borrow(); + trait_impls.get() + .find(&trait_ref.def_id) + .map_default(@RefCell::new(~[]), |x| *x) + }; // impls is the list of all impls in scope for trait_ref. - for im in impls.iter() { + let impls = impls.borrow(); + for im in impls.get().iter() { // im is one specific impl of trait_ref. // First, ensure we haven't processed this impl yet. @@ -528,12 +535,13 @@ fn connect_trait_tps(vcx: &VtableContext, relate_trait_refs(vcx, location_info, impl_trait_ref, trait_ref); } -fn insert_vtables(fcx: @mut FnCtxt, +fn insert_vtables(fcx: @FnCtxt, callee_id: ast::NodeId, vtables: vtable_res) { debug!("insert_vtables(callee_id={}, vtables={:?})", callee_id, vtables.repr(fcx.tcx())); - fcx.inh.vtable_map.insert(callee_id, vtables); + let mut vtable_map = fcx.inh.vtable_map.borrow_mut(); + vtable_map.get().insert(callee_id, vtables); } pub fn location_info_for_expr(expr: @ast::Expr) -> LocationInfo { @@ -550,7 +558,7 @@ pub fn location_info_for_item(item: @ast::item) -> LocationInfo { } pub fn early_resolve_expr(ex: @ast::Expr, - fcx: @mut FnCtxt, + fcx: @FnCtxt, is_early: bool) { debug!("vtable: early_resolve_expr() ex with id {:?} (early: {}): {}", ex.id, is_early, expr_to_str(ex, fcx.tcx().sess.intr())); @@ -562,7 +570,8 @@ pub fn early_resolve_expr(ex: @ast::Expr, fcx.opt_node_ty_substs(ex.id, |substs| { debug!("vtable resolution on parameter bounds for expr {}", ex.repr(fcx.tcx())); - let def = cx.tcx.def_map.get_copy(&ex.id); + let def_map = cx.tcx.def_map.borrow(); + let def = def_map.get().get_copy(&ex.id); let did = ast_util::def_id_of_def(def); let item_ty = ty::lookup_item_type(cx.tcx, did); debug!("early resolve expr: def {:?} {:?}, {:?}, {}", ex.id, did, def, @@ -715,14 +724,14 @@ pub fn early_resolve_expr(ex: @ast::Expr, } } -fn resolve_expr(fcx: @mut FnCtxt, +fn resolve_expr(fcx: @FnCtxt, ex: @ast::Expr) { let mut fcx = fcx; early_resolve_expr(ex, fcx, false); visit::walk_expr(&mut fcx, ex, ()); } -pub fn resolve_impl(ccx: @mut CrateCtxt, +pub fn resolve_impl(ccx: @CrateCtxt, impl_item: @ast::item, impl_generics: &ty::Generics, impl_trait_ref: &ty::TraitRef) { @@ -773,10 +782,12 @@ pub fn resolve_impl(ccx: @mut CrateCtxt, self_vtables: self_vtable_res }; let impl_def_id = ast_util::local_def(impl_item.id); - ccx.tcx.impl_vtables.insert(impl_def_id, res); + + let mut impl_vtables = ccx.tcx.impl_vtables.borrow_mut(); + impl_vtables.get().insert(impl_def_id, res); } -impl visit::Visitor<()> for @mut FnCtxt { +impl visit::Visitor<()> for @FnCtxt { fn visit_expr(&mut self, ex:@ast::Expr, _:()) { resolve_expr(*self, ex); } @@ -787,7 +798,7 @@ impl visit::Visitor<()> for @mut FnCtxt { // Detect points where a trait-bounded type parameter is // instantiated, resolve the impls for the parameters. -pub fn resolve_in_block(fcx: @mut FnCtxt, bl: ast::P) { +pub fn resolve_in_block(fcx: @FnCtxt, bl: ast::P) { let mut fcx = fcx; visit::walk_block(&mut fcx, bl, ()); } diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index f90ae3fdc636d..3f371253e0553 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -32,7 +32,7 @@ use syntax::print::pprust::pat_to_str; use syntax::visit; use syntax::visit::Visitor; -fn resolve_type_vars_in_type(fcx: @mut FnCtxt, sp: Span, typ: ty::t) +fn resolve_type_vars_in_type(fcx: @FnCtxt, sp: Span, typ: ty::t) -> Option { if !ty::type_needs_infer(typ) { return Some(typ); } match resolve_type(fcx.infcx(), typ, resolve_all | force_all) { @@ -50,7 +50,7 @@ fn resolve_type_vars_in_type(fcx: @mut FnCtxt, sp: Span, typ: ty::t) } } -fn resolve_type_vars_in_types(fcx: @mut FnCtxt, sp: Span, tys: &[ty::t]) +fn resolve_type_vars_in_types(fcx: @FnCtxt, sp: Span, tys: &[ty::t]) -> ~[ty::t] { tys.map(|t| { match resolve_type_vars_in_type(fcx, sp, *t) { @@ -60,45 +60,56 @@ fn resolve_type_vars_in_types(fcx: @mut FnCtxt, sp: Span, tys: &[ty::t]) }) } -fn resolve_method_map_entry(fcx: @mut FnCtxt, sp: Span, id: ast::NodeId) { +fn resolve_method_map_entry(fcx: @FnCtxt, sp: Span, id: ast::NodeId) { // Resolve any method map entry - match fcx.inh.method_map.find(&id) { + let method_map_entry_opt = { + let method_map = fcx.inh.method_map.borrow(); + method_map.get().find_copy(&id) + }; + match method_map_entry_opt { None => {} Some(mme) => { { let r = resolve_type_vars_in_type(fcx, sp, mme.self_ty); for t in r.iter() { let method_map = fcx.ccx.method_map; - let new_entry = method_map_entry { self_ty: *t, ..*mme }; + let new_entry = method_map_entry { self_ty: *t, ..mme }; debug!("writeback::resolve_method_map_entry(id={:?}, \ new_entry={:?})", id, new_entry); - method_map.insert(id, new_entry); + let mut method_map = method_map.borrow_mut(); + method_map.get().insert(id, new_entry); } } } } } -fn resolve_vtable_map_entry(fcx: @mut FnCtxt, sp: Span, id: ast::NodeId) { +fn resolve_vtable_map_entry(fcx: @FnCtxt, sp: Span, id: ast::NodeId) { // Resolve any method map entry - match fcx.inh.vtable_map.find(&id) { - None => {} - Some(origins) => { - let r_origins = resolve_origins(fcx, sp, *origins); - let vtable_map = fcx.ccx.vtable_map; - vtable_map.insert(id, r_origins); - debug!("writeback::resolve_vtable_map_entry(id={}, vtables={:?})", - id, r_origins.repr(fcx.tcx())); + { + let origins_opt = { + let vtable_map = fcx.inh.vtable_map.borrow(); + vtable_map.get().find_copy(&id) + }; + match origins_opt { + None => {} + Some(origins) => { + let r_origins = resolve_origins(fcx, sp, origins); + let mut vtable_map = fcx.ccx.vtable_map.borrow_mut(); + vtable_map.get().insert(id, r_origins); + debug!("writeback::resolve_vtable_map_entry(id={}, vtables={:?})", + id, r_origins.repr(fcx.tcx())); + } } } - fn resolve_origins(fcx: @mut FnCtxt, sp: Span, + fn resolve_origins(fcx: @FnCtxt, sp: Span, vtbls: vtable_res) -> vtable_res { @vtbls.map(|os| @os.map(|o| resolve_origin(fcx, sp, o))) } - fn resolve_origin(fcx: @mut FnCtxt, + fn resolve_origin(fcx: @FnCtxt, sp: Span, origin: &vtable_origin) -> vtable_origin { match origin { @@ -120,10 +131,14 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId) let tcx = fcx.ccx.tcx; // Resolve any borrowings for the node with id `id` - match fcx.inh.adjustments.find(&id) { + let adjustment = { + let adjustments = fcx.inh.adjustments.borrow(); + adjustments.get().find_copy(&id) + }; + match adjustment { None => (), - Some(&@ty::AutoAddEnv(r, s)) => { + Some(@ty::AutoAddEnv(r, s)) => { match resolve_region(fcx.infcx(), r, resolve_all | force_all) { Err(e) => { // This should not, I think, happen: @@ -134,12 +149,13 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId) Ok(r1) => { let resolved_adj = @ty::AutoAddEnv(r1, s); debug!("Adjustments for node {}: {:?}", id, resolved_adj); - fcx.tcx().adjustments.insert(id, resolved_adj); + let mut adjustments = fcx.tcx().adjustments.borrow_mut(); + adjustments.get().insert(id, resolved_adj); } } } - Some(&@ty::AutoDerefRef(adj)) => { + Some(@ty::AutoDerefRef(adj)) => { let fixup_region = |r| { match resolve_region(fcx.infcx(), r, resolve_all | force_all) { Ok(r1) => r1, @@ -163,7 +179,8 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId) autoref: resolved_autoref, }); debug!("Adjustments for node {}: {:?}", id, resolved_adj); - fcx.tcx().adjustments.insert(id, resolved_adj); + let mut adjustments = fcx.tcx().adjustments.borrow_mut(); + adjustments.get().insert(id, resolved_adj); } } @@ -200,7 +217,11 @@ fn maybe_resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId) -> Option { - if wbcx.fcx.inh.node_types.contains_key(&id) { + let contained = { + let node_types = wbcx.fcx.inh.node_types.borrow(); + node_types.get().contains_key(&id) + }; + if contained { resolve_type_vars_for_node(wbcx, sp, id) } else { None @@ -208,7 +229,7 @@ fn maybe_resolve_type_vars_for_node(wbcx: &mut WbCtxt, } struct WbCtxt { - fcx: @mut FnCtxt, + fcx: @FnCtxt, // As soon as we hit an error we have to stop resolving // the entire function. @@ -329,14 +350,14 @@ impl Visitor<()> for WbCtxt { fn visit_ty(&mut self, _t: &ast::Ty, _:()) {} } -pub fn resolve_type_vars_in_expr(fcx: @mut FnCtxt, e: @ast::Expr) -> bool { +pub fn resolve_type_vars_in_expr(fcx: @FnCtxt, e: @ast::Expr) -> bool { let mut wbcx = WbCtxt { fcx: fcx, success: true }; let wbcx = &mut wbcx; wbcx.visit_expr(e, ()); return wbcx.success; } -pub fn resolve_type_vars_in_fn(fcx: @mut FnCtxt, +pub fn resolve_type_vars_in_fn(fcx: @FnCtxt, decl: &ast::fn_decl, blk: ast::P, self_info: Option) -> bool { diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index dac5e2e40e6a4..376af7e9d3dfa 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -45,6 +45,7 @@ use syntax::codemap::Span; use syntax::opt_vec; use syntax::visit; +use std::cell::RefCell; use std::hashmap::HashSet; use std::result::Ok; use std::vec; @@ -55,7 +56,7 @@ pub struct UniversalQuantificationResult { type_param_defs: @~[ty::TypeParameterDef] } -pub fn get_base_type(inference_context: @mut InferCtxt, +pub fn get_base_type(inference_context: @InferCtxt, span: Span, original_type: t) -> Option { @@ -118,7 +119,7 @@ pub fn type_is_defined_in_local_crate(original_type: t) -> bool { } // Returns the def ID of the base type, if there is one. -pub fn get_base_type_def_id(inference_context: @mut InferCtxt, +pub fn get_base_type_def_id(inference_context: @InferCtxt, span: Span, original_type: t) -> Option { @@ -142,7 +143,7 @@ pub fn get_base_type_def_id(inference_context: @mut InferCtxt, } } -pub fn CoherenceChecker(crate_context: @mut CrateCtxt) -> CoherenceChecker { +pub fn CoherenceChecker(crate_context: @CrateCtxt) -> CoherenceChecker { CoherenceChecker { crate_context: crate_context, inference_context: new_infer_ctxt(crate_context.tcx), @@ -150,8 +151,8 @@ pub fn CoherenceChecker(crate_context: @mut CrateCtxt) -> CoherenceChecker { } pub struct CoherenceChecker { - crate_context: @mut CrateCtxt, - inference_context: @mut InferCtxt, + crate_context: @CrateCtxt, + inference_context: @InferCtxt, } struct CoherenceCheckVisitor { cc: CoherenceChecker } @@ -313,7 +314,8 @@ impl CoherenceChecker { } } - tcx.impls.insert(implementation.did, implementation); + let mut impls = tcx.impls.borrow_mut(); + impls.get().insert(implementation.did, implementation); } // Creates default method IDs and performs type substitutions for an impl @@ -365,13 +367,20 @@ impl CoherenceChecker { }; debug!("new_polytype={}", new_polytype.repr(tcx)); - tcx.tcache.insert(new_did, new_polytype); - tcx.methods.insert(new_did, new_method_ty); + { + let mut tcache = tcx.tcache.borrow_mut(); + tcache.get().insert(new_did, new_polytype); + } + + let mut methods = tcx.methods.borrow_mut(); + methods.get().insert(new_did, new_method_ty); // Pair the new synthesized ID up with the // ID of the method. - self.crate_context.tcx.provided_method_sources - .insert(new_did, trait_method.def_id); + let mut provided_method_sources = + self.crate_context.tcx.provided_method_sources.borrow_mut(); + provided_method_sources.get().insert(new_did, + trait_method.def_id); } } @@ -380,17 +389,19 @@ impl CoherenceChecker { implementation: @Impl) { let tcx = self.crate_context.tcx; let implementation_list; - match tcx.inherent_impls.find(&base_def_id) { + let mut inherent_impls = tcx.inherent_impls.borrow_mut(); + match inherent_impls.get().find(&base_def_id) { None => { - implementation_list = @mut ~[]; - tcx.inherent_impls.insert(base_def_id, implementation_list); + implementation_list = @RefCell::new(~[]); + inherent_impls.get().insert(base_def_id, implementation_list); } Some(&existing_implementation_list) => { implementation_list = existing_implementation_list; } } - implementation_list.push(implementation); + let mut implementation_list = implementation_list.borrow_mut(); + implementation_list.get().push(implementation); } pub fn add_trait_impl(&self, @@ -398,21 +409,24 @@ impl CoherenceChecker { implementation: @Impl) { let tcx = self.crate_context.tcx; let implementation_list; - match tcx.trait_impls.find(&base_def_id) { + let mut trait_impls = tcx.trait_impls.borrow_mut(); + match trait_impls.get().find(&base_def_id) { None => { - implementation_list = @mut ~[]; - tcx.trait_impls.insert(base_def_id, implementation_list); + implementation_list = @RefCell::new(~[]); + trait_impls.get().insert(base_def_id, implementation_list); } Some(&existing_implementation_list) => { implementation_list = existing_implementation_list; } } - implementation_list.push(implementation); + let mut implementation_list = implementation_list.borrow_mut(); + implementation_list.get().push(implementation); } pub fn check_implementation_coherence(&self) { - self.crate_context.tcx.trait_impls.each_key(|&trait_id| { + let trait_impls = self.crate_context.tcx.trait_impls.borrow(); + trait_impls.get().each_key(|&trait_id| { self.check_implementation_coherence_of(trait_id); true }); @@ -451,9 +465,11 @@ impl CoherenceChecker { } pub fn iter_impls_of_trait(&self, trait_def_id: DefId, f: |@Impl|) { - match self.crate_context.tcx.trait_impls.find(&trait_def_id) { + let trait_impls = self.crate_context.tcx.trait_impls.borrow(); + match trait_impls.get().find(&trait_def_id) { Some(impls) => { - for &im in impls.iter() { + let impls = impls.borrow(); + for &im in impls.get().iter() { f(im); } } @@ -519,7 +535,8 @@ impl CoherenceChecker { pub fn get_self_type_for_implementation(&self, implementation: @Impl) -> ty_param_bounds_and_ty { - return self.crate_context.tcx.tcache.get_copy(&implementation.did); + let tcache = self.crate_context.tcx.tcache.borrow(); + return tcache.get().get_copy(&implementation.did); } // Privileged scope checking @@ -530,7 +547,8 @@ impl CoherenceChecker { pub fn trait_ref_to_trait_def_id(&self, trait_ref: &trait_ref) -> DefId { let def_map = self.crate_context.tcx.def_map; - let trait_def = def_map.get_copy(&trait_ref.ref_id); + let def_map = def_map.borrow(); + let trait_def = def_map.get().get_copy(&trait_ref.ref_id); let trait_id = def_id_of_def(trait_def); return trait_id; } @@ -542,7 +560,8 @@ impl CoherenceChecker { -> bool { match original_type.node { ty_path(_, _, path_id) => { - match self.crate_context.tcx.def_map.get_copy(&path_id) { + let def_map = self.crate_context.tcx.def_map.borrow(); + match def_map.get().get_copy(&path_id) { DefTy(def_id) | DefStruct(def_id) => { if def_id.crate != LOCAL_CRATE { return false; @@ -651,11 +670,14 @@ impl CoherenceChecker { // the map. This is a bit unfortunate. for method in implementation.methods.iter() { for source in method.provided_source.iter() { - tcx.provided_method_sources.insert(method.def_id, *source); + let mut provided_method_sources = tcx.provided_method_sources + .borrow_mut(); + provided_method_sources.get().insert(method.def_id, *source); } } - tcx.impls.insert(implementation.did, implementation); + let mut impls = tcx.impls.borrow_mut(); + impls.get().insert(implementation.did, implementation); } // Adds implementations and traits from external crates to the coherence @@ -681,15 +703,17 @@ impl CoherenceChecker { let drop_trait = match tcx.lang_items.drop_trait() { Some(id) => id, None => { return } }; - let impls_opt = tcx.trait_impls.find(&drop_trait); + let trait_impls = tcx.trait_impls.borrow(); + let impls_opt = trait_impls.get().find(&drop_trait); let impls; match impls_opt { - None => return, // No types with (new-style) destructors present. + None => return, // No types with (new-style) dtors present. Some(found_impls) => impls = found_impls } - for impl_info in impls.iter() { + let impls = impls.borrow(); + for impl_info in impls.get().iter() { if impl_info.methods.len() < 1 { // We'll error out later. For now, just don't ICE. continue; @@ -699,9 +723,12 @@ impl CoherenceChecker { let self_type = self.get_self_type_for_implementation(*impl_info); match ty::get(self_type.ty).sty { ty::ty_struct(type_def_id, _) => { - tcx.destructor_for_type.insert(type_def_id, - method_def_id); - tcx.destructors.insert(method_def_id); + let mut destructor_for_type = tcx.destructor_for_type + .borrow_mut(); + destructor_for_type.get().insert(type_def_id, + method_def_id); + let mut destructors = tcx.destructors.borrow_mut(); + destructors.get().insert(method_def_id); } _ => { // Destructors only work on nominal types. @@ -805,7 +832,7 @@ fn subst_receiver_types_in_method_ty(tcx: ty::ctxt, ) } -pub fn check_coherence(crate_context: @mut CrateCtxt, crate: &Crate) { +pub fn check_coherence(crate_context: @CrateCtxt, crate: &Crate) { let coherence_checker = CoherenceChecker(crate_context); coherence_checker.check_coherence(crate); } diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 343808c2fa7af..3dfcf15e0240b 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -57,7 +57,7 @@ use syntax::opt_vec::OptVec; use syntax::parse::token::special_idents; struct CollectItemTypesVisitor { - ccx: @mut CrateCtxt + ccx: @CrateCtxt } impl visit::Visitor<()> for CollectItemTypesVisitor { @@ -71,12 +71,13 @@ impl visit::Visitor<()> for CollectItemTypesVisitor { } } -pub fn collect_item_types(ccx: @mut CrateCtxt, crate: &ast::Crate) { +pub fn collect_item_types(ccx: @CrateCtxt, crate: &ast::Crate) { fn collect_intrinsic_type(ccx: &CrateCtxt, lang_item: ast::DefId) { let ty::ty_param_bounds_and_ty { ty: ty, .. } = ccx.get_item_ty(lang_item); - ccx.tcx.intrinsic_defs.insert(lang_item, ty); + let mut intrinsic_defs = ccx.tcx.intrinsic_defs.borrow_mut(); + intrinsic_defs.get().insert(lang_item, ty); } match ccx.tcx.lang_items.ty_desc() { @@ -172,7 +173,12 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt, generics: ty_generics(ccx, generics, 0), ty: result_ty }; - tcx.tcache.insert(local_def(variant.node.id), tpt); + + { + let mut tcache = tcx.tcache.borrow_mut(); + tcache.get().insert(local_def(variant.node.id), tpt); + } + write_ty_to_tcx(tcx, variant.node.id, result_ty); } } @@ -213,7 +219,8 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, &trait_ty_generics); } - tcx.methods.insert(ty_method.def_id, ty_method); + let mut methods = tcx.methods.borrow_mut(); + methods.get().insert(ty_method.def_id, ty_method); } // Add an entry mapping @@ -225,7 +232,9 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, }); let trait_def_id = local_def(trait_id); - tcx.trait_method_def_ids.insert(trait_def_id, method_def_ids); + let mut trait_method_def_ids = tcx.trait_method_def_ids + .borrow_mut(); + trait_method_def_ids.get().insert(trait_def_id, method_def_ids); } _ => { /* Ignore things that aren't traits */ } } @@ -346,7 +355,8 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, ty.repr(tcx), substs.repr(tcx)); - tcx.tcache.insert(m.def_id, + let mut tcache = tcx.tcache.borrow_mut(); + tcache.get().insert(m.def_id, ty_param_bounds_and_ty { generics: ty::Generics { type_param_defs: @new_type_param_defs, @@ -397,7 +407,10 @@ pub fn ensure_supertraits(ccx: &CrateCtxt, // Called only the first time trait_def_of_item is called. // Supertraits are ensured at the same time. - assert!(!tcx.supertraits.contains_key(&local_def(id))); + { + let supertraits = tcx.supertraits.borrow(); + assert!(!supertraits.get().contains_key(&local_def(id))); + } let self_ty = ty::mk_self(ccx.tcx, local_def(id)); let mut ty_trait_refs: ~[@ty::TraitRef] = ~[]; @@ -421,7 +434,9 @@ pub fn ensure_supertraits(ccx: &CrateCtxt, } } } - tcx.supertraits.insert(local_def(id), @ty_trait_refs); + + let mut supertraits = tcx.supertraits.borrow_mut(); + supertraits.get().insert(local_def(id), @ty_trait_refs); bounds } @@ -431,7 +446,8 @@ pub fn convert_field(ccx: &CrateCtxt, let tt = ccx.to_ty(&ExplicitRscope, v.node.ty); write_ty_to_tcx(ccx.tcx, v.node.id, tt); /* add the field to the tcache */ - ccx.tcx.tcache.insert(local_def(v.node.id), + let mut tcache = ccx.tcx.tcache.borrow_mut(); + tcache.get().insert(local_def(v.node.id), ty::ty_param_bounds_and_ty { generics: struct_generics.clone(), ty: tt @@ -461,22 +477,29 @@ fn convert_methods(ccx: &CrateCtxt, m.ident.repr(ccx.tcx), m.id, fty.repr(ccx.tcx)); - tcx.tcache.insert( - local_def(m.id), + { + let mut tcache = tcx.tcache.borrow_mut(); + tcache.get().insert( + local_def(m.id), + + // n.b.: the type of a method is parameterized by both + // the parameters on the receiver and those on the method + // itself + ty_param_bounds_and_ty { + generics: ty::Generics { + type_param_defs: @vec::append( + (*rcvr_ty_generics.type_param_defs).clone(), + *m_ty_generics.type_param_defs), + region_param_defs: rcvr_ty_generics.region_param_defs, + }, + ty: fty + }); + } - // n.b.: the type of a method is parameterized by both - // the parameters on the receiver and those on the method itself - ty_param_bounds_and_ty { - generics: ty::Generics { - type_param_defs: @vec::append( - (*rcvr_ty_generics.type_param_defs).clone(), - *m_ty_generics.type_param_defs), - region_param_defs: rcvr_ty_generics.region_param_defs, - }, - ty: fty - }); write_ty_to_tcx(tcx, m.id, fty); - tcx.methods.insert(mty.def_id, mty); + + let mut methods = tcx.methods.borrow_mut(); + methods.get().insert(mty.def_id, mty); } fn ty_of_method(ccx: &CrateCtxt, @@ -546,10 +569,14 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) { let i_ty_generics = ty_generics(ccx, generics, 0); let selfty = ccx.to_ty(&ExplicitRscope, selfty); write_ty_to_tcx(tcx, it.id, selfty); - tcx.tcache.insert(local_def(it.id), - ty_param_bounds_and_ty { - generics: i_ty_generics, - ty: selfty}); + + { + let mut tcache = tcx.tcache.borrow_mut(); + tcache.get().insert(local_def(it.id), + ty_param_bounds_and_ty { + generics: i_ty_generics, + ty: selfty}); + } // If there is a trait reference, treat the methods as always public. // This is to work around some incorrect behavior in privacy checking: @@ -607,7 +634,11 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) { // Write the class type let tpt = ty_of_item(ccx, it); write_ty_to_tcx(tcx, it.id, tpt.ty); - tcx.tcache.insert(local_def(it.id), tpt); + + { + let mut tcache = tcx.tcache.borrow_mut(); + tcache.get().insert(local_def(it.id), tpt); + } convert_struct(ccx, struct_def, tpt, it.id); } @@ -647,19 +678,29 @@ pub fn convert_struct(ccx: &CrateCtxt, if struct_def.fields.len() == 0 { // Enum-like. write_ty_to_tcx(tcx, ctor_id, selfty); - tcx.tcache.insert(local_def(ctor_id), tpt); + + { + let mut tcache = tcx.tcache.borrow_mut(); + tcache.get().insert(local_def(ctor_id), tpt); + } } else if struct_def.fields[0].node.kind == ast::unnamed_field { // Tuple-like. - let inputs = + let inputs = { + let tcache = tcx.tcache.borrow(); struct_def.fields.map( - |field| ccx.tcx.tcache.get( - &local_def(field.node.id)).ty); + |field| tcache.get().get( + &local_def(field.node.id)).ty) + }; let ctor_fn_ty = ty::mk_ctor_fn(tcx, ctor_id, inputs, selfty); write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty); - tcx.tcache.insert(local_def(ctor_id), ty_param_bounds_and_ty { - generics: tpt.generics, - ty: ctor_fn_ty - }); + { + let mut tcache = tcx.tcache.borrow_mut(); + tcache.get().insert(local_def(ctor_id), + ty_param_bounds_and_ty { + generics: tpt.generics, + ty: ctor_fn_ty + }); + } } } } @@ -684,7 +725,9 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::foreign_item) { let tpt = ty_of_foreign_item(ccx, i, abis); write_ty_to_tcx(ccx.tcx, i.id, tpt.ty); - ccx.tcx.tcache.insert(local_def(i.id), tpt); + + let mut tcache = ccx.tcx.tcache.borrow_mut(); + tcache.get().insert(local_def(i.id), tpt); } pub fn instantiate_trait_ref(ccx: &CrateCtxt, @@ -705,8 +748,9 @@ pub fn instantiate_trait_ref(ccx: &CrateCtxt, let trait_ref = astconv::ast_path_to_trait_ref( ccx, &rscope, trait_did, Some(self_ty), &ast_trait_ref.path); - ccx.tcx.trait_refs.insert( - ast_trait_ref.ref_id, trait_ref); + + let mut trait_refs = ccx.tcx.trait_refs.borrow_mut(); + trait_refs.get().insert(ast_trait_ref.ref_id, trait_ref); return trait_ref; } _ => { @@ -734,10 +778,14 @@ fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> @ty::TraitDef { pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::item) -> @ty::TraitDef { let def_id = local_def(it.id); let tcx = ccx.tcx; - match tcx.trait_defs.find(&def_id) { - Some(&def) => return def, - _ => {} + { + let trait_defs = tcx.trait_defs.borrow(); + match trait_defs.get().find(&def_id) { + Some(&def) => return def, + _ => {} + } } + match it.node { ast::item_trait(ref generics, ref supertraits, _) => { let self_ty = ty::mk_self(tcx, def_id); @@ -749,7 +797,8 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::item) -> @ty::TraitDef { let trait_def = @ty::TraitDef {generics: ty_generics, bounds: bounds, trait_ref: trait_ref}; - tcx.trait_defs.insert(def_id, trait_def); + let mut trait_defs = tcx.trait_defs.borrow_mut(); + trait_defs.get().insert(def_id, trait_def); return trait_def; } ref s => { @@ -764,15 +813,20 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::item) -> ty::ty_param_bounds_and_ty { let def_id = local_def(it.id); let tcx = ccx.tcx; - match tcx.tcache.find(&def_id) { - Some(&tpt) => return tpt, - _ => {} + { + let tcache = tcx.tcache.borrow(); + match tcache.get().find(&def_id) { + Some(&tpt) => return tpt, + _ => {} + } } match it.node { ast::item_static(t, _, _) => { let typ = ccx.to_ty(&ExplicitRscope, t); let tpt = no_params(typ); - tcx.tcache.insert(local_def(it.id), tpt); + + let mut tcache = tcx.tcache.borrow_mut(); + tcache.get().insert(local_def(it.id), tpt); return tpt; } ast::item_fn(decl, purity, abi, ref generics, _) => { @@ -793,13 +847,18 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::item) tcx.sess.str_of(it.ident), it.id, ppaux::ty_to_str(tcx, tpt.ty)); - ccx.tcx.tcache.insert(local_def(it.id), tpt); + + let mut tcache = ccx.tcx.tcache.borrow_mut(); + tcache.get().insert(local_def(it.id), tpt); return tpt; } ast::item_ty(t, ref generics) => { - match tcx.tcache.find(&local_def(it.id)) { - Some(&tpt) => return tpt, - None => { } + { + let mut tcache = tcx.tcache.borrow_mut(); + match tcache.get().find(&local_def(it.id)) { + Some(&tpt) => return tpt, + None => { } + } } let tpt = { @@ -810,7 +869,8 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::item) } }; - tcx.tcache.insert(local_def(it.id), tpt); + let mut tcache = tcx.tcache.borrow_mut(); + tcache.get().insert(local_def(it.id), tpt); return tpt; } ast::item_enum(_, ref generics) => { @@ -822,7 +882,9 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::item) generics: ty_generics, ty: t }; - tcx.tcache.insert(local_def(it.id), tpt); + + let mut tcache = tcx.tcache.borrow_mut(); + tcache.get().insert(local_def(it.id), tpt); return tpt; } ast::item_trait(..) => { @@ -838,7 +900,9 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::item) generics: ty_generics, ty: t }; - tcx.tcache.insert(local_def(it.id), tpt); + + let mut tcache = tcx.tcache.borrow_mut(); + tcache.get().insert(local_def(it.id), tpt); return tpt; } ast::item_impl(..) | ast::item_mod(_) | @@ -880,8 +944,12 @@ pub fn ty_generics(ccx: &CrateCtxt, def_id: local_def(l.id) } }).collect(), type_param_defs: @generics.ty_params.mapi_to_vec(|offset, param| { - match ccx.tcx.ty_param_defs.find(¶m.id) { - Some(&def) => def, + let existing_def_opt = { + let ty_param_defs = ccx.tcx.ty_param_defs.borrow(); + ty_param_defs.get().find(¶m.id).map(|def| *def) + }; + match existing_def_opt { + Some(def) => def, None => { let param_ty = ty::param_ty {idx: base_index + offset, def_id: local_def(param.id)}; @@ -892,7 +960,11 @@ pub fn ty_generics(ccx: &CrateCtxt, bounds: bounds }; debug!("def for param: {}", def.repr(ccx.tcx)); - ccx.tcx.ty_param_defs.insert(param.id, def); + + let mut ty_param_defs = ccx.tcx + .ty_param_defs + .borrow_mut(); + ty_param_defs.get().insert(param.id, def); def } } @@ -965,7 +1037,9 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt, generics: ty_generics, ty: t_fn }; - ccx.tcx.tcache.insert(def_id, tpt); + + let mut tcache = ccx.tcx.tcache.borrow_mut(); + tcache.get().insert(def_id, tpt); return tpt; } diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index cdbd70ce3a729..c35852d37c97e 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -67,7 +67,7 @@ use syntax::opt_vec; use syntax::abi::AbiSet; pub trait Combine { - fn infcx(&self) -> @mut InferCtxt; + fn infcx(&self) -> @InferCtxt; fn tag(&self) -> ~str; fn a_is_expected(&self) -> bool; fn trace(&self) -> TypeTrace; @@ -328,7 +328,7 @@ pub trait Combine { } pub struct CombineFields { - infcx: @mut InferCtxt, + infcx: @InferCtxt, a_is_expected: bool, trace: TypeTrace, } diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs index 04ba1bcb31fd6..1744c1176156c 100644 --- a/src/librustc/middle/typeck/infer/error_reporting.rs +++ b/src/librustc/middle/typeck/infer/error_reporting.rs @@ -77,33 +77,33 @@ use util::ppaux::bound_region_to_str; use util::ppaux::note_and_explain_region; pub trait ErrorReporting { - fn report_region_errors(@mut self, + fn report_region_errors(@self, errors: &OptVec); - fn report_and_explain_type_error(@mut self, + fn report_and_explain_type_error(@self, trace: TypeTrace, terr: &ty::type_err); - fn values_str(@mut self, values: &ValuePairs) -> Option<~str>; + fn values_str(@self, values: &ValuePairs) -> Option<~str>; fn expected_found_str( - @mut self, + @self, exp_found: &ty::expected_found) -> Option<~str>; - fn report_concrete_failure(@mut self, + fn report_concrete_failure(@self, origin: SubregionOrigin, sub: Region, sup: Region); - fn report_sub_sup_conflict(@mut self, + fn report_sub_sup_conflict(@self, var_origin: RegionVariableOrigin, sub_origin: SubregionOrigin, sub_region: Region, sup_origin: SubregionOrigin, sup_region: Region); - fn report_sup_sup_conflict(@mut self, + fn report_sup_sup_conflict(@self, var_origin: RegionVariableOrigin, origin1: SubregionOrigin, region1: Region, @@ -112,15 +112,15 @@ pub trait ErrorReporting { } trait ErrorReportingHelpers { - fn report_inference_failure(@mut self, + fn report_inference_failure(@self, var_origin: RegionVariableOrigin); - fn note_region_origin(@mut self, + fn note_region_origin(@self, origin: SubregionOrigin); } impl ErrorReporting for InferCtxt { - fn report_region_errors(@mut self, + fn report_region_errors(@self, errors: &OptVec) { for error in errors.iter() { match *error { @@ -147,7 +147,7 @@ impl ErrorReporting for InferCtxt { } } - fn report_and_explain_type_error(@mut self, + fn report_and_explain_type_error(@self, trace: TypeTrace, terr: &ty::type_err) { let tcx = self.tcx; @@ -179,7 +179,7 @@ impl ErrorReporting for InferCtxt { ty::note_and_explain_type_err(self.tcx, terr); } - fn values_str(@mut self, values: &ValuePairs) -> Option<~str> { + fn values_str(@self, values: &ValuePairs) -> Option<~str> { /*! * Returns a string of the form "expected `{}` but found `{}`", * or None if this is a derived error. @@ -195,7 +195,7 @@ impl ErrorReporting for InferCtxt { } fn expected_found_str( - @mut self, + @self, exp_found: &ty::expected_found) -> Option<~str> { @@ -214,7 +214,7 @@ impl ErrorReporting for InferCtxt { found.user_string(self.tcx))) } - fn report_concrete_failure(@mut self, + fn report_concrete_failure(@self, origin: SubregionOrigin, sub: Region, sup: Region) { @@ -400,7 +400,7 @@ impl ErrorReporting for InferCtxt { } } - fn report_sub_sup_conflict(@mut self, + fn report_sub_sup_conflict(@self, var_origin: RegionVariableOrigin, sub_origin: SubregionOrigin, sub_region: Region, @@ -425,7 +425,7 @@ impl ErrorReporting for InferCtxt { self.note_region_origin(sub_origin); } - fn report_sup_sup_conflict(@mut self, + fn report_sup_sup_conflict(@self, var_origin: RegionVariableOrigin, origin1: SubregionOrigin, region1: Region, @@ -452,7 +452,7 @@ impl ErrorReporting for InferCtxt { } impl ErrorReportingHelpers for InferCtxt { - fn report_inference_failure(@mut self, + fn report_inference_failure(@self, var_origin: RegionVariableOrigin) { let var_description = match var_origin { infer::MiscVariable(_) => ~"", @@ -484,8 +484,7 @@ impl ErrorReportingHelpers for InferCtxt { var_description)); } - fn note_region_origin(@mut self, - origin: SubregionOrigin) { + fn note_region_origin(@self, origin: SubregionOrigin) { match origin { infer::Subtype(ref trace) => { let desc = match trace.origin { @@ -612,12 +611,12 @@ impl ErrorReportingHelpers for InferCtxt { } trait Resolvable { - fn resolve(&self, infcx: @mut InferCtxt) -> Self; + fn resolve(&self, infcx: @InferCtxt) -> Self; fn contains_error(&self) -> bool; } impl Resolvable for ty::t { - fn resolve(&self, infcx: @mut InferCtxt) -> ty::t { + fn resolve(&self, infcx: @InferCtxt) -> ty::t { infcx.resolve_type_vars_if_possible(*self) } fn contains_error(&self) -> bool { @@ -626,7 +625,7 @@ impl Resolvable for ty::t { } impl Resolvable for @ty::TraitRef { - fn resolve(&self, infcx: @mut InferCtxt) -> @ty::TraitRef { + fn resolve(&self, infcx: @InferCtxt) -> @ty::TraitRef { @infcx.resolve_type_vars_in_trait_ref_if_possible(*self) } fn contains_error(&self) -> bool { diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs index af7a23a4dfcdc..a9aaa5df2ca99 100644 --- a/src/librustc/middle/typeck/infer/glb.rs +++ b/src/librustc/middle/typeck/infer/glb.rs @@ -30,7 +30,7 @@ use util::ppaux::mt_to_str; pub struct Glb(CombineFields); // "greatest lower bound" (common subtype) impl Combine for Glb { - fn infcx(&self) -> @mut InferCtxt { self.infcx } + fn infcx(&self) -> @InferCtxt { self.infcx } fn tag(&self) -> ~str { ~"glb" } fn a_is_expected(&self) -> bool { self.a_is_expected } fn trace(&self) -> TypeTrace { self.trace } diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs index b826310df7bff..5af8c5571957d 100644 --- a/src/librustc/middle/typeck/infer/lub.rs +++ b/src/librustc/middle/typeck/infer/lub.rs @@ -36,7 +36,7 @@ impl Lub { } impl Combine for Lub { - fn infcx(&self) -> @mut InferCtxt { self.infcx } + fn infcx(&self) -> @InferCtxt { self.infcx } fn tag(&self) -> ~str { ~"lub" } fn a_is_expected(&self) -> bool { self.a_is_expected } fn trace(&self) -> TypeTrace { self.trace } diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index edac978041b67..8a95f9d1bff3f 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -35,6 +35,7 @@ use middle::typeck::infer::lub::Lub; use middle::typeck::infer::to_str::InferStr; use middle::typeck::infer::unify::{ValsAndBindings, Root}; use middle::typeck::infer::error_reporting::ErrorReporting; +use std::cell::{Cell, RefCell}; use std::hashmap::HashMap; use std::result; use std::vec; @@ -43,8 +44,8 @@ use syntax::ast; use syntax::codemap; use syntax::codemap::Span; use util::common::indent; -use util::ppaux::{bound_region_to_str, ty_to_str, trait_ref_to_str, Repr, - UserString}; +use util::ppaux::{bound_region_to_str, ty_to_str, trait_ref_to_str, Repr}; +use util::ppaux::{UserString}; pub mod doc; pub mod macros; @@ -79,16 +80,18 @@ pub struct InferCtxt { // We instantiate ValsAndBindings with bounds because the // types that might instantiate a general type variable have an // order, represented by its upper and lower bounds. - ty_var_bindings: ValsAndBindings>, - ty_var_counter: uint, + ty_var_bindings: RefCell>>, + ty_var_counter: Cell, // Map from integral variable to the kind of integer it represents - int_var_bindings: ValsAndBindings>, - int_var_counter: uint, + int_var_bindings: RefCell>>, + int_var_counter: Cell, // Map from floating variable to the kind of float it represents - float_var_bindings: ValsAndBindings>, - float_var_counter: uint, + float_var_bindings: RefCell>>, + float_var_counter: Cell, // For region variables. region_vars: RegionVarBindings, @@ -255,24 +258,24 @@ fn new_ValsAndBindings() -> ValsAndBindings { } } -pub fn new_infer_ctxt(tcx: ty::ctxt) -> @mut InferCtxt { - @mut InferCtxt { +pub fn new_infer_ctxt(tcx: ty::ctxt) -> @InferCtxt { + @InferCtxt { tcx: tcx, - ty_var_bindings: new_ValsAndBindings(), - ty_var_counter: 0, + ty_var_bindings: RefCell::new(new_ValsAndBindings()), + ty_var_counter: Cell::new(0), - int_var_bindings: new_ValsAndBindings(), - int_var_counter: 0, + int_var_bindings: RefCell::new(new_ValsAndBindings()), + int_var_counter: Cell::new(0), - float_var_bindings: new_ValsAndBindings(), - float_var_counter: 0, + float_var_bindings: RefCell::new(new_ValsAndBindings()), + float_var_counter: Cell::new(0), region_vars: RegionVarBindings(tcx), } } -pub fn common_supertype(cx: @mut InferCtxt, +pub fn common_supertype(cx: @InferCtxt, origin: TypeOrigin, a_is_expected: bool, a: ty::t, @@ -300,7 +303,7 @@ pub fn common_supertype(cx: @mut InferCtxt, } } -pub fn mk_subty(cx: @mut InferCtxt, +pub fn mk_subty(cx: @InferCtxt, a_is_expected: bool, origin: TypeOrigin, a: ty::t, @@ -318,7 +321,7 @@ pub fn mk_subty(cx: @mut InferCtxt, }).to_ures() } -pub fn can_mk_subty(cx: @mut InferCtxt, a: ty::t, b: ty::t) -> ures { +pub fn can_mk_subty(cx: @InferCtxt, a: ty::t, b: ty::t) -> ures { debug!("can_mk_subty({} <: {})", a.inf_str(cx), b.inf_str(cx)); indent(|| { cx.probe(|| { @@ -331,7 +334,7 @@ pub fn can_mk_subty(cx: @mut InferCtxt, a: ty::t, b: ty::t) -> ures { }).to_ures() } -pub fn mk_subr(cx: @mut InferCtxt, +pub fn mk_subr(cx: @InferCtxt, _a_is_expected: bool, origin: SubregionOrigin, a: ty::Region, @@ -342,7 +345,7 @@ pub fn mk_subr(cx: @mut InferCtxt, cx.region_vars.commit(); } -pub fn mk_eqty(cx: @mut InferCtxt, +pub fn mk_eqty(cx: @InferCtxt, a_is_expected: bool, origin: TypeOrigin, a: ty::t, @@ -361,7 +364,7 @@ pub fn mk_eqty(cx: @mut InferCtxt, }).to_ures() } -pub fn mk_sub_trait_refs(cx: @mut InferCtxt, +pub fn mk_sub_trait_refs(cx: @InferCtxt, a_is_expected: bool, origin: TypeOrigin, a: @ty::TraitRef, @@ -392,7 +395,7 @@ fn expected_found(a_is_expected: bool, } } -pub fn mk_coercety(cx: @mut InferCtxt, +pub fn mk_coercety(cx: @InferCtxt, a_is_expected: bool, origin: TypeOrigin, a: ty::t, @@ -410,7 +413,7 @@ pub fn mk_coercety(cx: @mut InferCtxt, }) } -pub fn can_mk_coercety(cx: @mut InferCtxt, a: ty::t, b: ty::t) -> ures { +pub fn can_mk_coercety(cx: @InferCtxt, a: ty::t, b: ty::t) -> ures { debug!("can_mk_coercety({} -> {})", a.inf_str(cx), b.inf_str(cx)); indent(|| { cx.probe(|| { @@ -424,7 +427,7 @@ pub fn can_mk_coercety(cx: @mut InferCtxt, a: ty::t, b: ty::t) -> ures { } // See comment on the type `resolve_state` below -pub fn resolve_type(cx: @mut InferCtxt, +pub fn resolve_type(cx: @InferCtxt, a: ty::t, modes: uint) -> fres { @@ -432,7 +435,7 @@ pub fn resolve_type(cx: @mut InferCtxt, resolver.resolve_type_chk(a) } -pub fn resolve_region(cx: @mut InferCtxt, r: ty::Region, modes: uint) +pub fn resolve_region(cx: @InferCtxt, r: ty::Region, modes: uint) -> fres { let mut resolver = resolver(cx, modes); resolver.resolve_region_chk(r) @@ -499,20 +502,18 @@ struct Snapshot { } impl InferCtxt { - pub fn combine_fields(@mut self, - a_is_expected: bool, - trace: TypeTrace) + pub fn combine_fields(@self, a_is_expected: bool, trace: TypeTrace) -> CombineFields { CombineFields {infcx: self, a_is_expected: a_is_expected, trace: trace} } - pub fn sub(@mut self, a_is_expected: bool, trace: TypeTrace) -> Sub { + pub fn sub(@self, a_is_expected: bool, trace: TypeTrace) -> Sub { Sub(self.combine_fields(a_is_expected, trace)) } - pub fn lub(@mut self, a_is_expected: bool, trace: TypeTrace) -> Lub { + pub fn lub(@self, a_is_expected: bool, trace: TypeTrace) -> Lub { Lub(self.combine_fields(a_is_expected, trace)) } @@ -520,48 +521,50 @@ impl InferCtxt { self.region_vars.in_snapshot() } - pub fn start_snapshot(&mut self) -> Snapshot { + pub fn start_snapshot(&self) -> Snapshot { + let ty_var_bindings = self.ty_var_bindings.borrow(); + let int_var_bindings = self.int_var_bindings.borrow(); + let float_var_bindings = self.float_var_bindings.borrow(); Snapshot { - ty_var_bindings_len: - self.ty_var_bindings.bindings.len(), - int_var_bindings_len: - self.int_var_bindings.bindings.len(), - float_var_bindings_len: - self.float_var_bindings.bindings.len(), - region_vars_snapshot: - self.region_vars.start_snapshot(), + ty_var_bindings_len: ty_var_bindings.get().bindings.len(), + int_var_bindings_len: int_var_bindings.get().bindings.len(), + float_var_bindings_len: float_var_bindings.get().bindings.len(), + region_vars_snapshot: self.region_vars.start_snapshot(), } } - pub fn rollback_to(&mut self, snapshot: &Snapshot) { + pub fn rollback_to(&self, snapshot: &Snapshot) { debug!("rollback!"); - rollback_to(&mut self.ty_var_bindings, snapshot.ty_var_bindings_len); - - rollback_to(&mut self.int_var_bindings, - snapshot.int_var_bindings_len); - rollback_to(&mut self.float_var_bindings, + let mut ty_var_bindings = self.ty_var_bindings.borrow_mut(); + let mut int_var_bindings = self.int_var_bindings.borrow_mut(); + let mut float_var_bindings = self.float_var_bindings.borrow_mut(); + rollback_to(ty_var_bindings.get(), snapshot.ty_var_bindings_len); + rollback_to(int_var_bindings.get(), snapshot.int_var_bindings_len); + rollback_to(float_var_bindings.get(), snapshot.float_var_bindings_len); self.region_vars.rollback_to(snapshot.region_vars_snapshot); } /// Execute `f` and commit the bindings if successful - pub fn commit(@mut self, f: || -> Result) -> Result { + pub fn commit(@self, f: || -> Result) -> Result { assert!(!self.in_snapshot()); debug!("commit()"); indent(|| { let r = self.try(|| f()); - self.ty_var_bindings.bindings.truncate(0); - self.int_var_bindings.bindings.truncate(0); + let mut ty_var_bindings = self.ty_var_bindings.borrow_mut(); + let mut int_var_bindings = self.int_var_bindings.borrow_mut(); + ty_var_bindings.get().bindings.truncate(0); + int_var_bindings.get().bindings.truncate(0); self.region_vars.commit(); r }) } /// Execute `f`, unroll bindings on failure - pub fn try(@mut self, f: || -> Result) -> Result { + pub fn try(@self, f: || -> Result) -> Result { debug!("try()"); let snapshot = self.start_snapshot(); let r = f(); @@ -576,7 +579,7 @@ impl InferCtxt { } /// Execute `f` then unroll any bindings it creates - pub fn probe(@mut self, f: || -> Result) -> Result { + pub fn probe(@self, f: || -> Result) -> Result { debug!("probe()"); indent(|| { let snapshot = self.start_snapshot(); @@ -598,85 +601,94 @@ fn next_simple_var(counter: &mut uint, } impl InferCtxt { - pub fn next_ty_var_id(&mut self) -> TyVid { - let id = self.ty_var_counter; - self.ty_var_counter += 1; + pub fn next_ty_var_id(&self) -> TyVid { + let id = self.ty_var_counter.get(); + self.ty_var_counter.set(id + 1); { - let vals = &mut self.ty_var_bindings.vals; + let mut ty_var_bindings = self.ty_var_bindings.borrow_mut(); + let vals = &mut ty_var_bindings.get().vals; vals.insert(id, Root(Bounds { lb: None, ub: None }, 0u)); } return TyVid(id); } - pub fn next_ty_var(&mut self) -> ty::t { + pub fn next_ty_var(&self) -> ty::t { ty::mk_var(self.tcx, self.next_ty_var_id()) } - pub fn next_ty_vars(&mut self, n: uint) -> ~[ty::t] { + pub fn next_ty_vars(&self, n: uint) -> ~[ty::t] { vec::from_fn(n, |_i| self.next_ty_var()) } - pub fn next_int_var_id(&mut self) -> IntVid { - IntVid(next_simple_var(&mut self.int_var_counter, - &mut self.int_var_bindings)) + pub fn next_int_var_id(&self) -> IntVid { + let mut int_var_counter = self.int_var_counter.get(); + let mut int_var_bindings = self.int_var_bindings.borrow_mut(); + let result = IntVid(next_simple_var(&mut int_var_counter, + int_var_bindings.get())); + self.int_var_counter.set(int_var_counter); + result } - pub fn next_int_var(&mut self) -> ty::t { + pub fn next_int_var(&self) -> ty::t { ty::mk_int_var(self.tcx, self.next_int_var_id()) } - pub fn next_float_var_id(&mut self) -> FloatVid { - FloatVid(next_simple_var(&mut self.float_var_counter, - &mut self.float_var_bindings)) + pub fn next_float_var_id(&self) -> FloatVid { + let mut float_var_counter = self.float_var_counter.get(); + let mut float_var_bindings = self.float_var_bindings.borrow_mut(); + let result = FloatVid(next_simple_var(&mut float_var_counter, + float_var_bindings.get())); + self.float_var_counter.set(float_var_counter); + result } - pub fn next_float_var(&mut self) -> ty::t { + pub fn next_float_var(&self) -> ty::t { ty::mk_float_var(self.tcx, self.next_float_var_id()) } - pub fn next_region_var(&mut self, origin: RegionVariableOrigin) -> ty::Region { + pub fn next_region_var(&self, origin: RegionVariableOrigin) -> ty::Region { ty::ReInfer(ty::ReVar(self.region_vars.new_region_var(origin))) } - pub fn next_region_vars(&mut self, + pub fn next_region_vars(&self, origin: RegionVariableOrigin, count: uint) -> ~[ty::Region] { vec::from_fn(count, |_| self.next_region_var(origin)) } - pub fn fresh_bound_region(&mut self, binder_id: ast::NodeId) -> ty::Region { + pub fn fresh_bound_region(&self, binder_id: ast::NodeId) -> ty::Region { self.region_vars.new_bound(binder_id) } - pub fn resolve_regions(@mut self) { + pub fn resolve_regions(@self) { let errors = self.region_vars.resolve_regions(); self.report_region_errors(&errors); // see error_reporting.rs } - pub fn ty_to_str(@mut self, t: ty::t) -> ~str { + pub fn ty_to_str(@self, t: ty::t) -> ~str { ty_to_str(self.tcx, self.resolve_type_vars_if_possible(t)) } - pub fn tys_to_str(@mut self, ts: &[ty::t]) -> ~str { + pub fn tys_to_str(@self, ts: &[ty::t]) -> ~str { let tstrs = ts.map(|t| self.ty_to_str(*t)); format!("({})", tstrs.connect(", ")) } - pub fn trait_ref_to_str(@mut self, t: &ty::TraitRef) -> ~str { + pub fn trait_ref_to_str(@self, t: &ty::TraitRef) -> ~str { let t = self.resolve_type_vars_in_trait_ref_if_possible(t); trait_ref_to_str(self.tcx, &t) } - pub fn resolve_type_vars_if_possible(@mut self, typ: ty::t) -> ty::t { + pub fn resolve_type_vars_if_possible(@self, typ: ty::t) -> ty::t { match resolve_type(self, typ, resolve_nested_tvar | resolve_ivar) { result::Ok(new_type) => new_type, result::Err(_) => typ } } - pub fn resolve_type_vars_in_trait_ref_if_possible(@mut self, + pub fn resolve_type_vars_in_trait_ref_if_possible(@self, trait_ref: &ty::TraitRef) -> ty::TraitRef { @@ -716,7 +728,7 @@ impl InferCtxt { // in this case. The typechecker should only ever report type errors involving mismatched // types using one of these four methods, and should not call span_err directly for such // errors. - pub fn type_error_message_str(@mut self, + pub fn type_error_message_str(@self, sp: Span, mk_msg: |Option<~str>, ~str| -> ~str, actual_ty: ~str, @@ -724,7 +736,7 @@ impl InferCtxt { self.type_error_message_str_with_expected(sp, mk_msg, None, actual_ty, err) } - pub fn type_error_message_str_with_expected(@mut self, + pub fn type_error_message_str_with_expected(@self, sp: Span, mk_msg: |Option<~str>, ~str| @@ -755,7 +767,7 @@ impl InferCtxt { } } - pub fn type_error_message(@mut self, + pub fn type_error_message(@self, sp: Span, mk_msg: |~str| -> ~str, actual_ty: ty::t, @@ -770,7 +782,7 @@ impl InferCtxt { self.type_error_message_str(sp, |_e, a| { mk_msg(a) }, self.ty_to_str(actual_ty), err); } - pub fn report_mismatched_types(@mut self, + pub fn report_mismatched_types(@self, sp: Span, e: ty::t, a: ty::t, @@ -791,7 +803,7 @@ impl InferCtxt { self.type_error_message(sp, mk_msg, a, Some(err)); } - pub fn replace_bound_regions_with_fresh_regions(&mut self, + pub fn replace_bound_regions_with_fresh_regions(&self, trace: TypeTrace, fsig: &ty::FnSig) -> (ty::FnSig, diff --git a/src/librustc/middle/typeck/infer/region_inference/mod.rs b/src/librustc/middle/typeck/infer/region_inference/mod.rs index dbbdba520ab93..8d8524e0f512f 100644 --- a/src/librustc/middle/typeck/infer/region_inference/mod.rs +++ b/src/librustc/middle/typeck/infer/region_inference/mod.rs @@ -24,6 +24,7 @@ use middle::graph::{Direction, NodeIndex}; use util::common::indenter; use util::ppaux::{Repr}; +use std::cell::{Cell, RefCell}; use std::hashmap::{HashMap, HashSet}; use std::uint; use std::vec; @@ -87,12 +88,12 @@ type CombineMap = HashMap; pub struct RegionVarBindings { tcx: ty::ctxt, - var_origins: ~[RegionVariableOrigin], - constraints: HashMap, - lubs: CombineMap, - glbs: CombineMap, - skolemization_count: uint, - bound_count: uint, + var_origins: RefCell<~[RegionVariableOrigin]>, + constraints: RefCell>, + lubs: RefCell, + glbs: RefCell, + skolemization_count: Cell, + bound_count: Cell, // The undo log records actions that might later be undone. // @@ -102,96 +103,114 @@ pub struct RegionVarBindings { // actively snapshotting. The reason for this is that otherwise // we end up adding entries for things like the lower bound on // a variable and so forth, which can never be rolled back. - undo_log: ~[UndoLogEntry], + undo_log: RefCell<~[UndoLogEntry]>, // This contains the results of inference. It begins as an empty // option and only acquires a value after inference is complete. - values: Option<~[VarValue]>, + values: RefCell>, } pub fn RegionVarBindings(tcx: ty::ctxt) -> RegionVarBindings { RegionVarBindings { tcx: tcx, - var_origins: ~[], - values: None, - constraints: HashMap::new(), - lubs: HashMap::new(), - glbs: HashMap::new(), - skolemization_count: 0, - bound_count: 0, - undo_log: ~[] + var_origins: RefCell::new(~[]), + values: RefCell::new(None), + constraints: RefCell::new(HashMap::new()), + lubs: RefCell::new(HashMap::new()), + glbs: RefCell::new(HashMap::new()), + skolemization_count: Cell::new(0), + bound_count: Cell::new(0), + undo_log: RefCell::new(~[]) } } impl RegionVarBindings { pub fn in_snapshot(&self) -> bool { - self.undo_log.len() > 0 + let undo_log = self.undo_log.borrow(); + undo_log.get().len() > 0 } - pub fn start_snapshot(&mut self) -> uint { - debug!("RegionVarBindings: snapshot()={}", self.undo_log.len()); + pub fn start_snapshot(&self) -> uint { + debug!("RegionVarBindings: start_snapshot()"); if self.in_snapshot() { - self.undo_log.len() + { + let undo_log = self.undo_log.borrow(); + undo_log.get().len() + } } else { - self.undo_log.push(Snapshot); - 0 + { + let mut undo_log = self.undo_log.borrow_mut(); + undo_log.get().push(Snapshot); + 0 + } } } - pub fn commit(&mut self) { + pub fn commit(&self) { debug!("RegionVarBindings: commit()"); - while self.undo_log.len() > 0 { - self.undo_log.pop(); + let mut undo_log = self.undo_log.borrow_mut(); + while undo_log.get().len() > 0 { + undo_log.get().pop(); } } - pub fn rollback_to(&mut self, snapshot: uint) { + pub fn rollback_to(&self, snapshot: uint) { debug!("RegionVarBindings: rollback_to({})", snapshot); - while self.undo_log.len() > snapshot { - let undo_item = self.undo_log.pop(); + let mut undo_log = self.undo_log.borrow_mut(); + while undo_log.get().len() > snapshot { + let undo_item = undo_log.get().pop(); debug!("undo_item={:?}", undo_item); match undo_item { Snapshot => {} AddVar(vid) => { - assert_eq!(self.var_origins.len(), vid.to_uint() + 1); - self.var_origins.pop(); + let mut var_origins = self.var_origins.borrow_mut(); + assert_eq!(var_origins.get().len(), vid.to_uint() + 1); + var_origins.get().pop(); } AddConstraint(ref constraint) => { - self.constraints.remove(constraint); + let mut constraints = self.constraints.borrow_mut(); + constraints.get().remove(constraint); } AddCombination(Glb, ref regions) => { - self.glbs.remove(regions); + let mut glbs = self.glbs.borrow_mut(); + glbs.get().remove(regions); } AddCombination(Lub, ref regions) => { - self.lubs.remove(regions); + let mut lubs = self.lubs.borrow_mut(); + lubs.get().remove(regions); } } } } pub fn num_vars(&self) -> uint { - self.var_origins.len() + let var_origins = self.var_origins.borrow(); + var_origins.get().len() } - pub fn new_region_var(&mut self, origin: RegionVariableOrigin) -> RegionVid { + pub fn new_region_var(&self, origin: RegionVariableOrigin) -> RegionVid { let id = self.num_vars(); - self.var_origins.push(origin); + let mut var_origins = self.var_origins.borrow_mut(); + var_origins.get().push(origin); let vid = RegionVid { id: id }; if self.in_snapshot() { - self.undo_log.push(AddVar(vid)); + { + let mut undo_log = self.undo_log.borrow_mut(); + undo_log.get().push(AddVar(vid)); + } } debug!("created new region variable {:?} with origin {:?}", vid, origin.repr(self.tcx)); return vid; } - pub fn new_skolemized(&mut self, br: ty::BoundRegion) -> Region { - let sc = self.skolemization_count; - self.skolemization_count += 1; + pub fn new_skolemized(&self, br: ty::BoundRegion) -> Region { + let sc = self.skolemization_count.get(); + self.skolemization_count.set(sc + 1); ReInfer(ReSkolemized(sc, br)) } - pub fn new_bound(&mut self, binder_id: ast::NodeId) -> Region { + pub fn new_bound(&self, binder_id: ast::NodeId) -> Region { // Creates a fresh bound variable for use in GLB computations. // See discussion of GLB computation in the large comment at // the top of this file for more details. @@ -210,37 +229,46 @@ impl RegionVarBindings { // changing the representation of bound regions in a fn // declaration - let sc = self.bound_count; - self.bound_count += 1; + let sc = self.bound_count.get(); + self.bound_count.set(sc + 1); - if sc >= self.bound_count { + if sc >= self.bound_count.get() { self.tcx.sess.bug("Rollover in RegionInference new_bound()"); } ReLateBound(binder_id, BrFresh(sc)) } - pub fn add_constraint(&mut self, + fn values_are_none(&self) -> bool { + let values = self.values.borrow(); + values.get().is_none() + } + + pub fn add_constraint(&self, constraint: Constraint, origin: SubregionOrigin) { // cannot add constraints once regions are resolved - assert!(self.values.is_none()); + assert!(self.values_are_none()); debug!("RegionVarBindings: add_constraint({:?})", constraint); - if self.constraints.insert(constraint, origin) { + let mut constraints = self.constraints.borrow_mut(); + if constraints.get().insert(constraint, origin) { if self.in_snapshot() { - self.undo_log.push(AddConstraint(constraint)); + { + let mut undo_log = self.undo_log.borrow_mut(); + undo_log.get().push(AddConstraint(constraint)); + } } } } - pub fn make_subregion(&mut self, + pub fn make_subregion(&self, origin: SubregionOrigin, sub: Region, sup: Region) { // cannot add constraints once regions are resolved - assert!(self.values.is_none()); + assert!(self.values_are_none()); debug!("RegionVarBindings: make_subregion({:?}, {:?})", sub, sup); match (sub, sup) { @@ -269,13 +297,13 @@ impl RegionVarBindings { } } - pub fn lub_regions(&mut self, + pub fn lub_regions(&self, origin: SubregionOrigin, a: Region, b: Region) -> Region { // cannot add constraints once regions are resolved - assert!(self.values.is_none()); + assert!(self.values_are_none()); debug!("RegionVarBindings: lub_regions({:?}, {:?})", a, b); match (a, b) { @@ -292,13 +320,13 @@ impl RegionVarBindings { } } - pub fn glb_regions(&mut self, + pub fn glb_regions(&self, origin: SubregionOrigin, a: Region, b: Region) -> Region { // cannot add constraints once regions are resolved - assert!(self.values.is_none()); + assert!(self.values_are_none()); debug!("RegionVarBindings: glb_regions({:?}, {:?})", a, b); match (a, b) { @@ -316,12 +344,16 @@ impl RegionVarBindings { } } - pub fn resolve_var(&mut self, rid: RegionVid) -> ty::Region { - let v = match self.values { - None => self.tcx.sess.span_bug( - self.var_origins[rid.to_uint()].span(), - format!("Attempt to resolve region variable before values have \ - been computed!")), + pub fn resolve_var(&self, rid: RegionVid) -> ty::Region { + let values = self.values.borrow(); + let v = match *values.get() { + None => { + let var_origins = self.var_origins.borrow(); + self.tcx.sess.span_bug( + var_origins.get()[rid.to_uint()].span(), + format!("Attempt to resolve region variable before \ + values have been computed!")) + } Some(ref values) => values[rid.to_uint()] }; @@ -342,36 +374,43 @@ impl RegionVarBindings { } } - fn combine_map<'a>(&'a mut self, - t: CombineMapType) - -> &'a mut CombineMap - { + fn combine_map<'a>(&'a self, t: CombineMapType) + -> &'a RefCell { match t { - Glb => &mut self.glbs, - Lub => &mut self.lubs, + Glb => &self.glbs, + Lub => &self.lubs, } } - pub fn combine_vars(&mut self, + pub fn combine_vars(&self, t: CombineMapType, a: Region, b: Region, origin: SubregionOrigin, - relate: |this: &mut RegionVarBindings, + relate: |this: &RegionVarBindings, old_r: Region, new_r: Region|) -> Region { let vars = TwoRegions { a: a, b: b }; - match self.combine_map(t).find(&vars) { - Some(&c) => { - return ReInfer(ReVar(c)); + { + let map = self.combine_map(t).borrow(); + match map.get().find(&vars) { + Some(&c) => { + return ReInfer(ReVar(c)); + } + None => {} } - None => {} } let c = self.new_region_var(infer::MiscVariable(origin.span())); - self.combine_map(t).insert(vars, c); + { + let mut map = self.combine_map(t).borrow_mut(); + map.get().insert(vars, c); + } if self.in_snapshot() { - self.undo_log.push(AddCombination(t, vars)); + { + let mut undo_log = self.undo_log.borrow_mut(); + undo_log.get().push(AddCombination(t, vars)); + } } relate(self, a, ReInfer(ReVar(c))); relate(self, b, ReInfer(ReVar(c))); @@ -379,9 +418,10 @@ impl RegionVarBindings { ReInfer(ReVar(c)) } - pub fn vars_created_since_snapshot(&mut self, snapshot: uint) + pub fn vars_created_since_snapshot(&self, snapshot: uint) -> ~[RegionVid] { - self.undo_log.slice_from(snapshot).iter() + let undo_log = self.undo_log.borrow(); + undo_log.get().slice_from(snapshot).iter() .filter_map(|&elt| match elt { AddVar(vid) => Some(vid), _ => None @@ -389,7 +429,7 @@ impl RegionVarBindings { .collect() } - pub fn tainted(&mut self, snapshot: uint, r0: Region) -> ~[Region] { + pub fn tainted(&self, snapshot: uint, r0: Region) -> ~[Region] { /*! * Computes all regions that have been related to `r0` in any * way since the snapshot `snapshot` was taken---`r0` itself @@ -401,7 +441,10 @@ impl RegionVarBindings { debug!("tainted(snapshot={}, r0={:?})", snapshot, r0); let _indenter = indenter(); - let undo_len = self.undo_log.len(); + let undo_len = { + let undo_log = self.undo_log.borrow(); + undo_log.get().len() + }; // `result_set` acts as a worklist: we explore all outgoing // edges and add any new regions we find to result_set. This @@ -417,22 +460,25 @@ impl RegionVarBindings { let mut undo_index = snapshot; while undo_index < undo_len { // nb: can't use uint::range() here as we move result_set - let regs = match self.undo_log[undo_index] { - AddConstraint(ConstrainVarSubVar(ref a, ref b)) => { - Some((ReInfer(ReVar(*a)), - ReInfer(ReVar(*b)))) - } - AddConstraint(ConstrainRegSubVar(ref a, ref b)) => { - Some((*a, ReInfer(ReVar(*b)))) - } - AddConstraint(ConstrainVarSubReg(ref a, ref b)) => { - Some((ReInfer(ReVar(*a)), *b)) - } - AddConstraint(ConstrainRegSubReg(a, b)) => { - Some((a, b)) - } - _ => { - None + let regs = { + let undo_log = self.undo_log.borrow(); + match undo_log.get()[undo_index] { + AddConstraint(ConstrainVarSubVar(ref a, ref b)) => { + Some((ReInfer(ReVar(*a)), + ReInfer(ReVar(*b)))) + } + AddConstraint(ConstrainRegSubVar(ref a, ref b)) => { + Some((*a, ReInfer(ReVar(*b)))) + } + AddConstraint(ConstrainVarSubReg(ref a, ref b)) => { + Some((ReInfer(ReVar(*a)), *b)) + } + AddConstraint(ConstrainRegSubReg(a, b)) => { + Some((a, b)) + } + _ => { + None + } } }; @@ -476,11 +522,12 @@ impl RegionVarBindings { constraints, assuming such values can be found; if they cannot, errors are reported. */ - pub fn resolve_regions(&mut self) -> OptVec { + pub fn resolve_regions(&self) -> OptVec { debug!("RegionVarBindings: resolve_regions()"); let mut errors = opt_vec::Empty; let v = self.infer_variable_values(&mut errors); - self.values = Some(v); + let mut values = self.values.borrow_mut(); + *values.get() = Some(v); errors } } @@ -512,8 +559,9 @@ impl RegionVarBindings { } (ReInfer(ReVar(v_id)), _) | (_, ReInfer(ReVar(v_id))) => { + let var_origins = self.var_origins.borrow(); self.tcx.sess.span_bug( - self.var_origins[v_id.to_uint()].span(), + var_origins.get()[v_id.to_uint()].span(), format!("lub_concrete_regions invoked with \ non-concrete regions: {:?}, {:?}", a, b)); } @@ -619,8 +667,9 @@ impl RegionVarBindings { (ReInfer(ReVar(v_id)), _) | (_, ReInfer(ReVar(v_id))) => { + let var_origins = self.var_origins.borrow(); self.tcx.sess.span_bug( - self.var_origins[v_id.to_uint()].span(), + var_origins.get()[v_id.to_uint()].span(), format!("glb_concrete_regions invoked with \ non-concrete regions: {:?}, {:?}", a, b)); } @@ -925,7 +974,8 @@ impl RegionVarBindings { &self, errors: &mut OptVec) { - for (constraint, _) in self.constraints.iter() { + let constraints = self.constraints.borrow(); + for (constraint, _) in constraints.get().iter() { let (sub, sup) = match *constraint { ConstrainVarSubVar(..) | ConstrainRegSubVar(..) | @@ -943,7 +993,7 @@ impl RegionVarBindings { debug!("ConcreteFailure: !(sub <= sup): sub={:?}, sup={:?}", sub, sup); - let origin = self.constraints.get_copy(constraint); + let origin = constraints.get().get_copy(constraint); errors.push(ConcreteFailure(origin, sub, sup)); } } @@ -1031,7 +1081,9 @@ impl RegionVarBindings { fn construct_graph(&self) -> RegionGraph { let num_vars = self.num_vars(); - let num_edges = self.constraints.len(); + + let constraints = self.constraints.borrow(); + let num_edges = constraints.get().len(); let mut graph = graph::Graph::with_capacity(num_vars + 1, num_edges); @@ -1041,7 +1093,7 @@ impl RegionVarBindings { } let dummy_idx = graph.add_node(()); - for (constraint, _) in self.constraints.iter() { + for (constraint, _) in constraints.get().iter() { match *constraint { ConstrainVarSubVar(a_id, b_id) => { graph.add_edge(NodeIndex(a_id.to_uint()), @@ -1093,19 +1145,23 @@ impl RegionVarBindings { for upper_bound in upper_bounds.iter() { if !self.is_subregion_of(lower_bound.region, upper_bound.region) { - errors.push(SubSupConflict( - self.var_origins[node_idx.to_uint()], - lower_bound.origin, - lower_bound.region, - upper_bound.origin, - upper_bound.region)); - return; + { + let var_origins = self.var_origins.borrow(); + errors.push(SubSupConflict( + var_origins.get()[node_idx.to_uint()], + lower_bound.origin, + lower_bound.region, + upper_bound.origin, + upper_bound.region)); + return; + } } } } + let var_origins = self.var_origins.borrow(); self.tcx.sess.span_bug( - self.var_origins[node_idx.to_uint()].span(), + var_origins.get()[node_idx.to_uint()].span(), format!("collect_error_for_expanding_node() could not find error \ for var {:?}, lower_bounds={}, upper_bounds={}", node_idx, @@ -1137,8 +1193,9 @@ impl RegionVarBindings { upper_bound_2.region) { Ok(_) => {} Err(_) => { + let var_origins = self.var_origins.borrow(); errors.push(SupSupConflict( - self.var_origins[node_idx.to_uint()], + var_origins.get()[node_idx.to_uint()], upper_bound_1.origin, upper_bound_1.region, upper_bound_2.origin, @@ -1149,8 +1206,9 @@ impl RegionVarBindings { } } + let var_origins = self.var_origins.borrow(); self.tcx.sess.span_bug( - self.var_origins[node_idx.to_uint()].span(), + var_origins.get()[node_idx.to_uint()].span(), format!("collect_error_for_contracting_node() could not find error \ for var {:?}, upper_bounds={}", node_idx, @@ -1230,9 +1288,10 @@ impl RegionVarBindings { ConstrainRegSubVar(region, _) | ConstrainVarSubReg(_, region) => { + let constraints = this.constraints.borrow(); state.result.push(RegionAndOrigin { region: region, - origin: this.constraints.get_copy(&edge.data) + origin: constraints.get().get_copy(&edge.data) }); } @@ -1252,7 +1311,8 @@ impl RegionVarBindings { changed = false; iteration += 1; debug!("---- {} Iteration \\#{}", tag, iteration); - for (constraint, _) in self.constraints.iter() { + let constraints = self.constraints.borrow(); + for (constraint, _) in constraints.get().iter() { let edge_changed = body(constraint); if edge_changed { debug!("Updated due to constraint {}", diff --git a/src/librustc/middle/typeck/infer/resolve.rs b/src/librustc/middle/typeck/infer/resolve.rs index 168d8a57c7fec..93ac3d8c25445 100644 --- a/src/librustc/middle/typeck/infer/resolve.rs +++ b/src/librustc/middle/typeck/infer/resolve.rs @@ -80,14 +80,14 @@ pub static resolve_and_force_all_but_regions: uint = (resolve_all | force_all) & not_regions; pub struct ResolveState { - infcx: @mut InferCtxt, + infcx: @InferCtxt, modes: uint, err: Option, v_seen: ~[TyVid], type_depth: uint } -pub fn resolver(infcx: @mut InferCtxt, modes: uint) -> ResolveState { +pub fn resolver(infcx: @InferCtxt, modes: uint) -> ResolveState { ResolveState { infcx: infcx, modes: modes, diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs index 210d7fd7c80b1..68fa625f08c40 100644 --- a/src/librustc/middle/typeck/infer/sub.rs +++ b/src/librustc/middle/typeck/infer/sub.rs @@ -29,7 +29,7 @@ use syntax::ast::{Onceness, purity}; pub struct Sub(CombineFields); // "subtype", "subregion" etc impl Combine for Sub { - fn infcx(&self) -> @mut InferCtxt { self.infcx } + fn infcx(&self) -> @InferCtxt { self.infcx } fn tag(&self) -> ~str { ~"sub" } fn a_is_expected(&self) -> bool { self.a_is_expected } fn trace(&self) -> TypeTrace { self.trace } diff --git a/src/librustc/middle/typeck/infer/unify.rs b/src/librustc/middle/typeck/infer/unify.rs index b58a526b7ea94..1ec9b49ba4b32 100644 --- a/src/librustc/middle/typeck/infer/unify.rs +++ b/src/librustc/middle/typeck/infer/unify.rs @@ -16,6 +16,7 @@ use middle::ty; use middle::typeck::infer::{Bounds, uok, ures}; use middle::typeck::infer::InferCtxt; use middle::typeck::infer::to_str::InferStr; +use std::cell::RefCell; use syntax::ast; #[deriving(Clone)] @@ -36,24 +37,24 @@ pub struct Node { } pub trait UnifyVid { - fn appropriate_vals_and_bindings<'v>(infcx: &'v mut InferCtxt) - -> &'v mut ValsAndBindings; + fn appropriate_vals_and_bindings<'v>(infcx: &'v InferCtxt) + -> &'v RefCell>; } pub trait UnifyInferCtxtMethods { fn get>( - &mut self, + &self, vid: V) -> Node; fn set>( - &mut self, + &self, vid: V, new_v: VarValue); fn unify>( - &mut self, + &self, node_a: &Node, node_b: &Node) -> (V, uint); @@ -62,7 +63,7 @@ pub trait UnifyInferCtxtMethods { impl UnifyInferCtxtMethods for InferCtxt { fn get>( - &mut self, + &self, vid: V) -> Node { /*! @@ -74,7 +75,8 @@ impl UnifyInferCtxtMethods for InferCtxt { let tcx = self.tcx; let vb = UnifyVid::appropriate_vals_and_bindings(self); - return helper(tcx, vb, vid); + let mut vb = vb.borrow_mut(); + return helper(tcx, vb.get(), vid); fn helper( tcx: ty::ctxt, @@ -108,7 +110,7 @@ impl UnifyInferCtxtMethods for InferCtxt { fn set>( - &mut self, + &self, vid: V, new_v: VarValue) { /*! @@ -120,14 +122,15 @@ impl UnifyInferCtxtMethods for InferCtxt { vid.to_str(), new_v.inf_str(self)); let vb = UnifyVid::appropriate_vals_and_bindings(self); - let old_v = (*vb.vals.get(&vid.to_uint())).clone(); - vb.bindings.push((vid.clone(), old_v)); - vb.vals.insert(vid.to_uint(), new_v); + let mut vb = vb.borrow_mut(); + let old_v = (*vb.get().vals.get(&vid.to_uint())).clone(); + vb.get().bindings.push((vid.clone(), old_v)); + vb.get().vals.insert(vid.to_uint(), new_v); } fn unify>( - &mut self, + &self, node_a: &Node, node_b: &Node) -> (V, uint) { @@ -182,14 +185,14 @@ pub fn mk_err(a_is_expected: bool, pub trait InferCtxtMethods { fn simple_vars>>( - &mut self, + &self, a_is_expected: bool, a_id: V, b_id: V) -> ures; fn simple_var_t>>( - &mut self, + &self, a_is_expected: bool, a_id: V, b: T) @@ -199,7 +202,7 @@ pub trait InferCtxtMethods { impl InferCtxtMethods for InferCtxt { fn simple_vars>>( - &mut self, + &self, a_is_expected: bool, a_id: V, b_id: V) @@ -239,7 +242,7 @@ impl InferCtxtMethods for InferCtxt { fn simple_var_t>>( - &mut self, + &self, a_is_expected: bool, a_id: V, b: T) @@ -274,16 +277,16 @@ impl InferCtxtMethods for InferCtxt { // ______________________________________________________________________ impl UnifyVid> for ty::TyVid { - fn appropriate_vals_and_bindings<'v>(infcx: &'v mut InferCtxt) - -> &'v mut ValsAndBindings> { - return &mut infcx.ty_var_bindings; + fn appropriate_vals_and_bindings<'v>(infcx: &'v InferCtxt) + -> &'v RefCell>> { + return &infcx.ty_var_bindings; } } impl UnifyVid> for ty::IntVid { - fn appropriate_vals_and_bindings<'v>(infcx: &'v mut InferCtxt) - -> &'v mut ValsAndBindings> { - return &mut infcx.int_var_bindings; + fn appropriate_vals_and_bindings<'v>(infcx: &'v InferCtxt) + -> &'v RefCell>> { + return &infcx.int_var_bindings; } } @@ -294,9 +297,10 @@ impl SimplyUnifiable for IntVarValue { } impl UnifyVid> for ty::FloatVid { - fn appropriate_vals_and_bindings<'v>(infcx: &'v mut InferCtxt) - -> &'v mut ValsAndBindings> { - return &mut infcx.float_var_bindings; + fn appropriate_vals_and_bindings<'v>(infcx: &'v InferCtxt) + -> &'v RefCell>> { + return &infcx.float_var_bindings; } } diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index ac7e6940b6070..835c739c0852b 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -68,6 +68,7 @@ use util::common::time; use util::ppaux::Repr; use util::ppaux; +use std::cell::RefCell; use std::hashmap::HashMap; use std::result; use extra::list::List; @@ -159,7 +160,7 @@ pub struct method_map_entry { // maps from an expression id that corresponds to a method call to the details // of the method to be invoked -pub type method_map = @mut HashMap; +pub type method_map = @RefCell>; pub type vtable_param_res = @~[vtable_origin]; // Resolutions for bounds of all parameters, left to right, for a given path. @@ -203,7 +204,7 @@ impl Repr for vtable_origin { } } -pub type vtable_map = @mut HashMap; +pub type vtable_map = @RefCell>; // Information about the vtable resolutions for for a trait impl. @@ -225,7 +226,7 @@ impl Repr for impl_res { } } -pub type impl_vtable_map = @mut HashMap; +pub type impl_vtable_map = RefCell>; pub struct CrateCtxt { // A mapping from method call sites to traits that have that method. @@ -239,7 +240,8 @@ pub struct CrateCtxt { pub fn write_ty_to_tcx(tcx: ty::ctxt, node_id: ast::NodeId, ty: ty::t) { debug!("write_ty_to_tcx({}, {})", node_id, ppaux::ty_to_str(tcx, ty)); assert!(!ty::type_needs_infer(ty)); - tcx.node_types.insert(node_id as uint, ty); + let mut node_types = tcx.node_types.borrow_mut(); + node_types.get().insert(node_id as uint, ty); } pub fn write_substs_to_tcx(tcx: ty::ctxt, node_id: ast::NodeId, @@ -248,7 +250,9 @@ pub fn write_substs_to_tcx(tcx: ty::ctxt, debug!("write_substs_to_tcx({}, {:?})", node_id, substs.map(|t| ppaux::ty_to_str(tcx, *t))); assert!(substs.iter().all(|t| !ty::type_needs_infer(*t))); - tcx.node_type_substs.insert(node_id, substs); + + let mut node_type_substs = tcx.node_type_substs.borrow_mut(); + node_type_substs.get().insert(node_id, substs); } } pub fn write_tpt_to_tcx(tcx: ty::ctxt, @@ -261,7 +265,8 @@ pub fn write_tpt_to_tcx(tcx: ty::ctxt, } pub fn lookup_def_tcx(tcx: ty::ctxt, sp: Span, id: ast::NodeId) -> ast::Def { - match tcx.def_map.find(&id) { + let def_map = tcx.def_map.borrow(); + match def_map.get().find(&id) { Some(&x) => x, _ => { tcx.sess.span_fatal(sp, "internal error looking up a definition") @@ -283,7 +288,7 @@ pub fn no_params(t: ty::t) -> ty::ty_param_bounds_and_ty { } pub fn require_same_types(tcx: ty::ctxt, - maybe_infcx: Option<@mut infer::InferCtxt>, + maybe_infcx: Option<@infer::InferCtxt>, t1_is_expected: bool, span: Span, t1: ty::t, @@ -434,9 +439,9 @@ fn check_start_fn_ty(ccx: &CrateCtxt, fn check_for_entry_fn(ccx: &CrateCtxt) { let tcx = ccx.tcx; - if !*tcx.sess.building_library { - match *tcx.sess.entry_fn { - Some((id, sp)) => match *tcx.sess.entry_type { + if !tcx.sess.building_library.get() { + match tcx.sess.entry_fn.get() { + Some((id, sp)) => match tcx.sess.entry_type.get() { Some(session::EntryMain) => check_main_fn_ty(ccx, id, sp), Some(session::EntryStart) => check_start_fn_ty(ccx, id, sp), Some(session::EntryNone) => {} @@ -452,10 +457,10 @@ pub fn check_crate(tcx: ty::ctxt, crate: &ast::Crate) -> (method_map, vtable_map) { let time_passes = tcx.sess.time_passes(); - let ccx = @mut CrateCtxt { + let ccx = @CrateCtxt { trait_map: trait_map, - method_map: @mut HashMap::new(), - vtable_map: @mut HashMap::new(), + method_map: @RefCell::new(HashMap::new()), + vtable_map: @RefCell::new(HashMap::new()), tcx: tcx }; diff --git a/src/librustc/middle/typeck/rscope.rs b/src/librustc/middle/typeck/rscope.rs index 9a32eafa8e4de..4eb1ad9ab9a43 100644 --- a/src/librustc/middle/typeck/rscope.rs +++ b/src/librustc/middle/typeck/rscope.rs @@ -11,6 +11,7 @@ use middle::ty; +use std::cell::Cell; use std::vec; use syntax::ast; use syntax::codemap::Span; @@ -49,14 +50,14 @@ impl RegionScope for ExplicitRscope { /// omitted regions. This occurs in function signatures. pub struct BindingRscope { binder_id: ast::NodeId, - anon_bindings: @mut uint + anon_bindings: Cell, } impl BindingRscope { pub fn new(binder_id: ast::NodeId) -> BindingRscope { BindingRscope { binder_id: binder_id, - anon_bindings: @mut 0 + anon_bindings: Cell::new(0), } } } @@ -66,8 +67,8 @@ impl RegionScope for BindingRscope { _: Span, count: uint) -> Result<~[ty::Region], ()> { - let idx = *self.anon_bindings; - *self.anon_bindings += count; + let idx = self.anon_bindings.get(); + self.anon_bindings.set(idx + count); Ok(vec::from_fn(count, |i| ty::ReLateBound(self.binder_id, ty::BrAnon(idx + i)))) } diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs index 219f9689a2571..3ae43d606617c 100644 --- a/src/librustc/middle/typeck/variance.rs +++ b/src/librustc/middle/typeck/variance.rs @@ -363,7 +363,10 @@ impl<'a> Visitor<()> for TermsContext<'a> { // "invalid item id" from "item id with no // parameters". if self.num_inferred() == inferreds_on_entry { - let newly_added = self.tcx.item_variance_map.insert( + let mut item_variance_map = self.tcx + .item_variance_map + .borrow_mut(); + let newly_added = item_variance_map.get().insert( ast_util::local_def(item.id), self.empty_variances); assert!(newly_added); @@ -876,7 +879,6 @@ impl<'a> SolveContext<'a> { // item id). let tcx = self.terms_cx.tcx; - let item_variance_map = tcx.item_variance_map; let solutions = &self.solutions; let inferred_infos = &self.terms_cx.inferred_infos; let mut index = 0; @@ -919,8 +921,9 @@ impl<'a> SolveContext<'a> { tcx.sess.span_err(ast_map::node_span(tcx.items, item_id), found); } - let newly_added = item_variance_map.insert(item_def_id, - @item_variances); + let mut item_variance_map = tcx.item_variance_map.borrow_mut(); + let newly_added = item_variance_map.get().insert(item_def_id, + @item_variances); assert!(newly_added); } } diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index ad55c8dcab95f..f3933c5623b26 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -14,7 +14,6 @@ use syntax::codemap::{Span}; use syntax::visit; use syntax::visit::Visitor; -use std::hashmap::HashSet; use std::local_data; use extra; @@ -132,5 +131,3 @@ pub fn pluralize(n: uint, s: ~str) -> ~str { else { format!("{}s", s) } } -// A set of node IDs (used to keep track of which node IDs are for statements) -pub type stmt_set = @mut HashSet; diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index ca17d8aaab432..ac88018a3c41f 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -472,11 +472,10 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { ty_infer(infer_ty) => infer_ty.to_str(), ty_err => ~"[type error]", ty_param(param_ty {idx: id, def_id: did}) => { - let param_def = cx.ty_param_defs.find(&did.node); + let ty_param_defs = cx.ty_param_defs.borrow(); + let param_def = ty_param_defs.get().find(&did.node); let ident = match param_def { - Some(def) => { - cx.sess.str_of(def.ident).to_owned() - } + Some(def) => cx.sess.str_of(def.ident).to_owned(), None => { // This should not happen... format!("BUG[{:?}]", id) diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs index 3500018820bb6..7d80cea23c160 100644 --- a/src/librustdoc/clean.rs +++ b/src/librustdoc/clean.rs @@ -1153,7 +1153,8 @@ fn resolve_type(path: Path, tpbs: Option<~[TyParamBound]>, None => return Bool }; debug!("searching for {:?} in defmap", id); - let d = match tycx.def_map.find(&id) { + let def_map = tycx.def_map.borrow(); + let d = match def_map.get().find(&id) { Some(k) => k, None => { debug!("could not find {:?} in defmap (`{}`)", id, @@ -1210,7 +1211,8 @@ fn resolve_def(id: ast::NodeId) -> Option { let cx = local_data::get(super::ctxtkey, |x| *x.unwrap()); match cx.tycx { Some(tcx) => { - tcx.def_map.find(&id).map(|&d| ast_util::def_id_of_def(d)) + let def_map = tcx.def_map.borrow(); + def_map.get().find(&id).map(|&d| ast_util::def_id_of_def(d)) } None => None } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 5c3d348465734..18891d38d38ec 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -17,6 +17,7 @@ use syntax::diagnostic; use syntax::parse; use syntax; +use std::cell::RefCell; use std::os; use std::local_data; use std::hashmap::{HashSet}; @@ -50,7 +51,7 @@ fn get_ast_and_resolve(cpath: &Path, let sessopts = @driver::session::options { binary: @"rustdoc", maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()), - addl_lib_search_paths: @mut libs, + addl_lib_search_paths: @RefCell::new(libs), outputs: ~[driver::session::OutputDylib], .. (*rustc::driver::session::basic_options()).clone() }; diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 9462f8118ba65..7450abf34158b 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::cell::RefCell; use std::hashmap::HashSet; use std::local_data; use std::os; @@ -34,7 +35,7 @@ pub fn run(input: &str, matches: &getopts::Matches) -> int { let parsesess = parse::new_parse_sess(None); let input = driver::file_input(Path::new(input)); let libs = matches.opt_strs("L").map(|s| Path::new(s.as_slice())); - let libs = @mut libs.move_iter().collect(); + let libs = @RefCell::new(libs.move_iter().collect()); let sessopts = @session::options { binary: @"rustdoc", @@ -99,7 +100,7 @@ fn runtest(test: &str, cratename: &str, libs: HashSet) { let sessopts = @session::options { binary: @"rustdoctest", maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()), - addl_lib_search_paths: @mut libs, + addl_lib_search_paths: @RefCell::new(libs), outputs: ~[session::OutputExecutable], debugging_opts: session::prefer_dynamic, .. (*session::basic_options()).clone() @@ -159,7 +160,7 @@ fn maketest(s: &str, cratename: &str) -> @str { pub struct Collector { priv tests: ~[test::TestDescAndFn], priv names: ~[~str], - priv libs: @mut HashSet, + priv libs: @RefCell>, priv cnt: uint, priv cratename: ~str, } @@ -169,7 +170,8 @@ impl Collector { let test = test.to_owned(); let name = format!("{}_{}", self.names.connect("::"), self.cnt); self.cnt += 1; - let libs = (*self.libs).clone(); + let libs = self.libs.borrow(); + let libs = (*libs.get()).clone(); let cratename = self.cratename.to_owned(); self.tests.push(test::TestDescAndFn { desc: test::TestDesc { diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 7a68ae8b15ca4..eb7dbe4e4a8a7 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -10,6 +10,7 @@ #[allow(dead_code)]; +use std::cell::RefCell; use std::libc; use std::os; use std::io; @@ -244,7 +245,8 @@ pub fn compile_input(context: &BuildContext, optimize: opt, test: what == Test || what == Bench, maybe_sysroot: Some(sysroot_to_use), - addl_lib_search_paths: @mut context.additional_library_paths(), + addl_lib_search_paths: + @RefCell::new(context.additional_library_paths()), output_type: output_type, .. (*driver::build_session_options(binary, &matches, @@ -254,15 +256,20 @@ pub fn compile_input(context: &BuildContext, debug!("Created options..."); - let addl_lib_search_paths = @mut options.addl_lib_search_paths; + let addl_lib_search_paths = @RefCell::new(options.addl_lib_search_paths); // Make sure all the library directories actually exist, since the linker will complain // otherwise - for p in addl_lib_search_paths.iter() { - if p.exists() { - assert!(p.is_dir()) - } - else { - fs::mkdir_recursive(p, io::UserRWX); + { + let mut addl_lib_search_paths = addl_lib_search_paths.borrow_mut(); + let addl_lib_search_paths = addl_lib_search_paths.get(); + let mut addl_lib_search_paths = addl_lib_search_paths.borrow_mut(); + for p in addl_lib_search_paths.get().iter() { + if p.exists() { + assert!(p.is_dir()) + } + else { + fs::mkdir_recursive(p, io::UserRWX); + } } } @@ -285,9 +292,15 @@ pub fn compile_input(context: &BuildContext, find_and_install_dependencies(context, pkg_id, in_file, sess, exec, &crate, deps, |p| { debug!("a dependency: {}", p.display()); + let mut addl_lib_search_paths = + addl_lib_search_paths.borrow_mut(); + let addl_lib_search_paths = + addl_lib_search_paths.get(); + let mut addl_lib_search_paths = + addl_lib_search_paths.borrow_mut(); // Pass the directory containing a dependency // as an additional lib search path - addl_lib_search_paths.insert(p); + addl_lib_search_paths.get().insert(p); }); // Inject the pkgid attribute so we get the right package name and version @@ -376,8 +389,11 @@ pub fn compile_crate_from_input(input: &Path, outputs.obj_filename.display(), sess.opts.output_type); debug!("additional libraries:"); - for lib in sess.opts.addl_lib_search_paths.iter() { - debug!("an additional library: {}", lib.display()); + { + let addl_lib_search_paths = sess.opts.addl_lib_search_paths.borrow(); + for lib in addl_lib_search_paths.get().iter() { + debug!("an additional library: {}", lib.display()); + } } let analysis = driver::phase_3_run_analysis_passes(sess, &crate); if driver::stop_after_phase_3(sess) { return None; } diff --git a/src/libstd/cell.rs b/src/libstd/cell.rs index 62fc08fd9d394..c5fdddfec7625 100644 --- a/src/libstd/cell.rs +++ b/src/libstd/cell.rs @@ -21,6 +21,33 @@ pub struct Cell { priv value: T, } +#[cfg(stage0)] +impl Cell { + /// Creates a new `Cell` containing the given value. + pub fn new(value: T) -> Cell { + Cell { + value: value, + } + } + + /// Returns a copy of the contained value. + #[inline] + pub fn get(&self) -> T { + unsafe { + ::cast::transmute_copy(&self.value) + } + } + + /// Sets the contained value. + #[inline] + pub fn set(&self, value: T) { + unsafe { + *cast::transmute_mut(&self.value) = value + } + } +} + +#[cfg(not(stage0))] impl Cell { /// Creates a new `Cell` containing the given value. pub fn new(value: T) -> Cell {