From da9e9e84079f7d9476506a61b046ece85ca55d4d Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 19 Oct 2016 09:34:19 +0000 Subject: [PATCH 01/14] Remove `CrateReader`, use `CrateLoader` instead. --- src/librustc_driver/driver.rs | 3 +- src/librustc_metadata/creader.rs | 48 ++++++++------------------- src/librustc_metadata/macro_import.rs | 2 +- src/librustc_plugin/load.rs | 6 ++-- 4 files changed, 20 insertions(+), 39 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index e8ab2f3a2405b..9b27f7a29e9a8 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -645,7 +645,8 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session, // its contents but the results of name resolution on those contents. Hopefully we'll push // this back at some point. let _ignore = sess.dep_graph.in_ignore(); - let mut crate_loader = CrateLoader::new(sess, &cstore, &krate, crate_name); + let mut crate_loader = CrateLoader::new(sess, &cstore, crate_name, krate.config.clone()); + crate_loader.preprocess(&krate); let resolver_arenas = Resolver::arenas(); let mut resolver = Resolver::new(sess, &krate, make_glob_map, &mut crate_loader, &resolver_arenas); diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index f97df67c44560..e3a589c6c032b 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -42,12 +42,6 @@ use log; pub struct CrateLoader<'a> { pub sess: &'a Session, - pub creader: CrateReader<'a>, - cstore: &'a CStore, -} - -pub struct CrateReader<'a> { - sess: &'a Session, cstore: &'a CStore, next_crate_num: CrateNum, foreign_item_map: FnvHashMap>, @@ -159,13 +153,13 @@ pub struct Macros { pub dylib: Option, } -impl<'a> CrateReader<'a> { +impl<'a> CrateLoader<'a> { pub fn new(sess: &'a Session, cstore: &'a CStore, local_crate_name: &str, local_crate_config: ast::CrateConfig) - -> CrateReader<'a> { - CrateReader { + -> Self { + CrateLoader { sess: sess, cstore: cstore, next_crate_num: cstore.next_crate_num(), @@ -890,7 +884,7 @@ impl<'a> CrateReader<'a> { } impl ExtensionCrate { - fn register(self, creader: &mut CrateReader) { + fn register(self, loader: &mut CrateLoader) { if !self.should_link { return } @@ -901,31 +895,17 @@ impl ExtensionCrate { }; // Register crate now to avoid double-reading metadata - creader.register_crate(&None, - &self.ident, - &self.name, - self.span, - library, - true); + loader.register_crate(&None, &self.ident, &self.name, self.span, library, true); } } impl<'a> CrateLoader<'a> { - pub fn new(sess: &'a Session, cstore: &'a CStore, krate: &ast::Crate, crate_name: &str) - -> Self { - let loader = CrateLoader { - sess: sess, - cstore: cstore, - creader: CrateReader::new(sess, cstore, crate_name, krate.config.clone()), - }; - + pub fn preprocess(&mut self, krate: &ast::Crate) { for attr in krate.attrs.iter().filter(|m| m.name() == "link_args") { if let Some(ref linkarg) = attr.value_str() { - loader.cstore.add_used_link_args(&linkarg); + self.cstore.add_used_link_args(&linkarg); } } - - loader } fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod) { @@ -982,7 +962,7 @@ impl<'a> CrateLoader<'a> { Some(name) => name, None => continue, }; - let list = self.creader.foreign_item_map.entry(lib_name.to_string()) + let list = self.foreign_item_map.entry(lib_name.to_string()) .or_insert(Vec::new()); list.extend(fm.items.iter().map(|it| it.id)); } @@ -991,8 +971,8 @@ impl<'a> CrateLoader<'a> { impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { fn postprocess(&mut self, krate: &ast::Crate) { - self.creader.inject_allocator_crate(); - self.creader.inject_panic_runtime(krate); + self.inject_allocator_crate(); + self.inject_panic_runtime(krate); if log_enabled!(log::INFO) { dump_crates(&self.cstore); @@ -1001,7 +981,7 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { for &(ref name, kind) in &self.sess.opts.libs { register_native_lib(self.sess, self.cstore, None, name.clone(), kind); } - self.creader.register_statically_included_foreign_items(); + self.register_statically_included_foreign_items(); } fn process_item(&mut self, item: &ast::Item, definitions: &hir_map::Definitions) { @@ -1024,12 +1004,12 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { } } - if let Some(info) = self.creader.extract_crate_info(item) { + if let Some(info) = self.extract_crate_info(item) { if !info.should_link { return; } - let (cnum, ..) = self.creader.resolve_crate( + let (cnum, ..) = self.resolve_crate( &None, &info.ident, &info.name, None, item.span, PathKind::Crate, true, ); @@ -1038,7 +1018,7 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { let extern_crate = ExternCrate { def_id: def_id, span: item.span, direct: true, path_len: len }; - self.creader.update_extern_crate(cnum, extern_crate, &mut FnvHashSet()); + self.update_extern_crate(cnum, extern_crate, &mut FnvHashSet()); self.cstore.add_extern_mod_stmt_cnum(info.id, cnum); } diff --git a/src/librustc_metadata/macro_import.rs b/src/librustc_metadata/macro_import.rs index 3b1b2a4cd27e4..e88494ebe1a3a 100644 --- a/src/librustc_metadata/macro_import.rs +++ b/src/librustc_metadata/macro_import.rs @@ -115,7 +115,7 @@ impl<'a> CrateLoader<'a> { return Vec::new(); } - let mut macros = self.creader.read_macros(vi); + let mut macros = self.read_macros(vi); let mut ret = Vec::new(); let mut seen = HashSet::new(); diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index 9e56397bc99e9..669df3ad95065 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -11,7 +11,7 @@ //! Used by `rustc` when loading a plugin. use rustc::session::Session; -use rustc_metadata::creader::CrateReader; +use rustc_metadata::creader::CrateLoader; use rustc_metadata::cstore::CStore; use registry::Registry; @@ -33,7 +33,7 @@ pub struct PluginRegistrar { struct PluginLoader<'a> { sess: &'a Session, - reader: CrateReader<'a>, + reader: CrateLoader<'a>, plugins: Vec, } @@ -96,7 +96,7 @@ impl<'a> PluginLoader<'a> { -> PluginLoader<'a> { PluginLoader { sess: sess, - reader: CrateReader::new(sess, cstore, crate_name, crate_config), + reader: CrateLoader::new(sess, cstore, crate_name, crate_config), plugins: vec![], } } From feefe77125b3b68d12f08ea5dd606d9542e509e0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 20 Oct 2016 13:08:51 +1100 Subject: [PATCH 02/14] Remove `{in,de}flate_bytes_zlib`. These functions are unused. --- src/libflate/lib.rs | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index 63913f2878c20..89df931da0299 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -95,10 +95,10 @@ extern "C" { } const LZ_NORM: c_int = 0x80; // LZ with 128 probes, "normal" -const TINFL_FLAG_PARSE_ZLIB_HEADER: c_int = 0x1; // parse zlib header and adler32 checksum -const TDEFL_WRITE_ZLIB_HEADER: c_int = 0x01000; // write zlib header and adler32 checksum -fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Bytes { +/// Compress a buffer without writing any sort of header on the output. +pub fn deflate_bytes(bytes: &[u8]) -> Bytes { + let flags = LZ_NORM; unsafe { let mut outsz: size_t = 0; let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _, @@ -113,17 +113,9 @@ fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Bytes { } } -/// Compress a buffer, without writing any sort of header on the output. -pub fn deflate_bytes(bytes: &[u8]) -> Bytes { - deflate_bytes_internal(bytes, LZ_NORM) -} - -/// Compress a buffer, using a header that zlib can understand. -pub fn deflate_bytes_zlib(bytes: &[u8]) -> Bytes { - deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER) -} - -fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Result { +/// Decompress a buffer without parsing any sort of header on the input. +pub fn inflate_bytes(bytes: &[u8]) -> Result { + let flags = 0; unsafe { let mut outsz: size_t = 0; let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _, @@ -141,16 +133,6 @@ fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Result { } } -/// Decompress a buffer, without parsing any sort of header on the input. -pub fn inflate_bytes(bytes: &[u8]) -> Result { - inflate_bytes_internal(bytes, 0) -} - -/// Decompress a buffer that starts with a zlib header. -pub fn inflate_bytes_zlib(bytes: &[u8]) -> Result { - inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER) -} - #[cfg(test)] mod tests { #![allow(deprecated)] From 94771a177ba133bfadd0ffba55d82e7e3989ea06 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 20 Oct 2016 13:53:27 +1100 Subject: [PATCH 03/14] Use fast decompression in `deflate_bytes`. This commit changes the parameters of `deflate` to do faster, lower-quality compression. For the compression of LLVM bytecode -- which is the main use of `deflate_bytes` -- it makes compression almost twice as fast while the size of the compressed files is only ~2% worse. --- src/libflate/lib.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index 89df931da0299..3c608ef9c9268 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -94,11 +94,14 @@ extern "C" { -> *mut c_void; } -const LZ_NORM: c_int = 0x80; // LZ with 128 probes, "normal" +const LZ_FAST: c_int = 0x01; // LZ with 1 probe, "fast" +const TDEFL_GREEDY_PARSING_FLAG: c_int = 0x04000; // fast greedy parsing instead of lazy parsing -/// Compress a buffer without writing any sort of header on the output. +/// Compress a buffer without writing any sort of header on the output. Fast +/// compression is used because it is almost twice as fast as default +/// compression and the compression ratio is only marginally worse. pub fn deflate_bytes(bytes: &[u8]) -> Bytes { - let flags = LZ_NORM; + let flags = LZ_FAST | TDEFL_GREEDY_PARSING_FLAG; unsafe { let mut outsz: size_t = 0; let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _, From b94d2fbc9334577567c7c06660320d8a327e5186 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 19 Oct 2016 09:56:39 +0000 Subject: [PATCH 04/14] Rename `csearch.rs` -> `cstore_impl.rs`. --- src/librustc_metadata/{csearch.rs => cstore_impl.rs} | 0 src/librustc_metadata/lib.rs | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/librustc_metadata/{csearch.rs => cstore_impl.rs} (100%) diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/cstore_impl.rs similarity index 100% rename from src/librustc_metadata/csearch.rs rename to src/librustc_metadata/cstore_impl.rs diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 3d8a10f6c31fc..cc78dafd7ed25 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -53,7 +53,7 @@ mod index_builder; mod index; mod encoder; mod decoder; -mod csearch; +mod cstore_impl; mod schema; pub mod creader; From 63f931456dd337b14aada299c28116c2e9f063de Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 20 Oct 2016 04:21:25 +0000 Subject: [PATCH 05/14] Move `Library` into `creader.rs`. --- src/librustc_metadata/creader.rs | 14 ++++++++++---- src/librustc_metadata/loader.rs | 7 +------ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index e3a589c6c032b..c016f01b505ab 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -40,6 +40,12 @@ use syntax::parse::token::InternedString; use syntax_pos::{self, Span, mk_sp}; use log; +pub struct Library { + pub dylib: Option<(PathBuf, PathKind)>, + pub rlib: Option<(PathBuf, PathKind)>, + pub metadata: MetadataBlob, +} + pub struct CrateLoader<'a> { pub sess: &'a Session, cstore: &'a CStore, @@ -123,7 +129,7 @@ struct ExtensionCrate { enum PMDSource { Registered(Rc), - Owned(loader::Library), + Owned(Library), } impl Deref for PMDSource { @@ -139,7 +145,7 @@ impl Deref for PMDSource { enum LoadResult { Previous(CrateNum), - Loaded(loader::Library), + Loaded(Library), } pub struct Macros { @@ -275,7 +281,7 @@ impl<'a> CrateLoader<'a> { ident: &str, name: &str, span: Span, - lib: loader::Library, + lib: Library, explicitly_linked: bool) -> (CrateNum, Rc, cstore::CrateSource) { @@ -300,7 +306,7 @@ impl<'a> CrateLoader<'a> { // Maintain a reference to the top most crate. let root = if root.is_some() { root } else { &crate_paths }; - let loader::Library { dylib, rlib, metadata } = lib; + let Library { dylib, rlib, metadata } = lib; let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span); diff --git a/src/librustc_metadata/loader.rs b/src/librustc_metadata/loader.rs index 75242fc36db76..a5e08c77eaa7a 100644 --- a/src/librustc_metadata/loader.rs +++ b/src/librustc_metadata/loader.rs @@ -213,6 +213,7 @@ //! metadata::loader or metadata::creader for all the juicy details! use cstore::MetadataBlob; +use creader::Library; use schema::{METADATA_HEADER, rustc_version}; use rustc::hir::svh::Svh; @@ -263,12 +264,6 @@ pub struct Context<'a> { pub should_match_name: bool, } -pub struct Library { - pub dylib: Option<(PathBuf, PathKind)>, - pub rlib: Option<(PathBuf, PathKind)>, - pub metadata: MetadataBlob, -} - pub struct ArchiveMetadata { _archive: ArchiveRO, // points into self._archive From 80fe1d212dcea881e4a9724e7d035b224573c8d4 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 20 Oct 2016 04:31:14 +0000 Subject: [PATCH 06/14] Rename `loader.rs` -> `locator.rs`. --- src/librustc_driver/lib.rs | 5 ++-- src/librustc_metadata/creader.rs | 30 +++++++++---------- src/librustc_metadata/cstore.rs | 4 +-- src/librustc_metadata/cstore_impl.rs | 6 ++-- src/librustc_metadata/lib.rs | 2 +- .../{loader.rs => locator.rs} | 6 ++-- 6 files changed, 26 insertions(+), 27 deletions(-) rename src/librustc_metadata/{loader.rs => locator.rs} (99%) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 6972bdac5e1bc..cb001688da286 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -77,7 +77,7 @@ use rustc::session::config::nightly_options; use rustc::session::early_error; use rustc::lint::Lint; use rustc::lint; -use rustc_metadata::loader; +use rustc_metadata::locator; use rustc_metadata::cstore::CStore; use rustc::util::common::time; @@ -578,8 +578,7 @@ impl RustcDefaultCalls { &Input::File(ref ifile) => { let path = &(*ifile); let mut v = Vec::new(); - loader::list_file_metadata(&sess.target.target, path, &mut v) - .unwrap(); + locator::list_file_metadata(&sess.target.target, path, &mut v).unwrap(); println!("{}", String::from_utf8(v).unwrap()); } &Input::Str { .. } => { diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index c016f01b505ab..7ae3f6f81079e 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -11,7 +11,7 @@ //! Validates all used crates and extern libraries and loads their metadata use cstore::{self, CStore, CrateSource, MetadataBlob}; -use loader::{self, CratePaths}; +use locator::{self, CratePaths}; use macro_import; use schema::CrateRoot; @@ -352,7 +352,7 @@ impl<'a> CrateLoader<'a> { Some(cnum) => LoadResult::Previous(cnum), None => { info!("falling back to a load"); - let mut load_ctxt = loader::Context { + let mut locate_ctxt = locator::Context { sess: self.sess, span: span, ident: ident, @@ -368,9 +368,9 @@ impl<'a> CrateLoader<'a> { rejected_via_version: vec!(), should_match_name: true, }; - match self.load(&mut load_ctxt) { + match self.load(&mut locate_ctxt) { Some(result) => result, - None => load_ctxt.report_load_errs(), + None => locate_ctxt.report_errs(), } } }; @@ -390,8 +390,8 @@ impl<'a> CrateLoader<'a> { } } - fn load(&mut self, loader: &mut loader::Context) -> Option { - let library = match loader.maybe_load_library_crate() { + fn load(&mut self, locate_ctxt: &mut locator::Context) -> Option { + let library = match locate_ctxt.maybe_load_library_crate() { Some(lib) => lib, None => return None, }; @@ -405,11 +405,11 @@ impl<'a> CrateLoader<'a> { // don't want to match a host crate against an equivalent target one // already loaded. let root = library.metadata.get_root(); - if loader.triple == self.sess.opts.target_triple { + if locate_ctxt.triple == self.sess.opts.target_triple { let mut result = LoadResult::Loaded(library); self.cstore.iter_crate_data(|cnum, data| { if data.name() == root.name && root.hash == data.hash() { - assert!(loader.hash.is_none()); + assert!(locate_ctxt.hash.is_none()); info!("load success, going to previous cnum: {}", cnum); result = LoadResult::Previous(cnum); } @@ -494,7 +494,7 @@ impl<'a> CrateLoader<'a> { let mut target_only = false; let ident = info.ident.clone(); let name = info.name.clone(); - let mut load_ctxt = loader::Context { + let mut locate_ctxt = locator::Context { sess: self.sess, span: span, ident: &ident[..], @@ -510,7 +510,7 @@ impl<'a> CrateLoader<'a> { rejected_via_version: vec!(), should_match_name: true, }; - let library = self.load(&mut load_ctxt).or_else(|| { + let library = self.load(&mut locate_ctxt).or_else(|| { if !is_cross { return None } @@ -519,15 +519,15 @@ impl<'a> CrateLoader<'a> { target_only = true; should_link = info.should_link; - load_ctxt.target = &self.sess.target.target; - load_ctxt.triple = target_triple; - load_ctxt.filesearch = self.sess.target_filesearch(PathKind::Crate); + locate_ctxt.target = &self.sess.target.target; + locate_ctxt.triple = target_triple; + locate_ctxt.filesearch = self.sess.target_filesearch(PathKind::Crate); - self.load(&mut load_ctxt) + self.load(&mut locate_ctxt) }); let library = match library { Some(l) => l, - None => load_ctxt.report_load_errs(), + None => locate_ctxt.report_errs(), }; let (dylib, metadata) = match library { diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 038d0f73d5ce8..a87e61c4c944c 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -11,7 +11,7 @@ // The crate store - a central repo for information collected about external // crates and libraries -use loader; +use locator; use schema; use rustc::dep_graph::DepGraph; @@ -43,7 +43,7 @@ pub type CrateNumMap = IndexVec; pub enum MetadataBlob { Inflated(Bytes), - Archive(loader::ArchiveMetadata), + Archive(locator::ArchiveMetadata), } /// Holds information about a syntax_pos::FileMap imported from another crate. diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 54664b9c04046..7637b769f9377 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -10,7 +10,7 @@ use cstore; use encoder; -use loader; +use locator; use schema; use rustc::middle::cstore::{InlinedItem, CrateStore, CrateSource, ExternCrate}; @@ -497,12 +497,12 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn metadata_filename(&self) -> &str { - loader::METADATA_FILENAME + locator::METADATA_FILENAME } fn metadata_section_name(&self, target: &Target) -> &str { - loader::meta_section_name(target) + locator::meta_section_name(target) } fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, Option)> diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index cc78dafd7ed25..c0fc1a7065cc0 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -58,7 +58,7 @@ mod schema; pub mod creader; pub mod cstore; -pub mod loader; +pub mod locator; pub mod macro_import; __build_diagnostic_array! { librustc_metadata, DIAGNOSTICS } diff --git a/src/librustc_metadata/loader.rs b/src/librustc_metadata/locator.rs similarity index 99% rename from src/librustc_metadata/loader.rs rename to src/librustc_metadata/locator.rs index a5e08c77eaa7a..e684cd16366ec 100644 --- a/src/librustc_metadata/loader.rs +++ b/src/librustc_metadata/locator.rs @@ -210,7 +210,7 @@ //! //! That's the general overview of loading crates in the compiler, but it's by //! no means all of the necessary details. Take a look at the rest of -//! metadata::loader or metadata::creader for all the juicy details! +//! metadata::locator or metadata::creader for all the juicy details! use cstore::MetadataBlob; use creader::Library; @@ -310,10 +310,10 @@ impl<'a> Context<'a> { } pub fn load_library_crate(&mut self) -> Library { - self.find_library_crate().unwrap_or_else(|| self.report_load_errs()) + self.find_library_crate().unwrap_or_else(|| self.report_errs()) } - pub fn report_load_errs(&mut self) -> ! { + pub fn report_errs(&mut self) -> ! { let add = match self.root { &None => String::new(), &Some(ref r) => format!(" which `{}` depends on", From 209fe0df24292a69ab4f34d10a5a8c417f64e2e9 Mon Sep 17 00:00:00 2001 From: Vadim Chugunov Date: Wed, 19 Oct 2016 00:25:03 -0700 Subject: [PATCH 07/14] Fix line stepping in debugger. Attribute drop code to block's closing brace, instead of the line where the allocation was done. Attribute function epilogues to function body's closing brace, rather than the function header. --- src/librustc_mir/build/mod.rs | 5 +- src/librustc_mir/build/scope.rs | 6 +- src/test/debuginfo/drop-locations.rs | 91 ++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 src/test/debuginfo/drop-locations.rs diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 353aaaa45e18b..7b3306de7538b 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -176,8 +176,9 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, unpack!(block = builder.in_scope(arg_extent, block, |builder| { builder.args_and_body(block, return_ty, &arguments, arg_extent, ast_block) })); - - let source_info = builder.source_info(span); + // Attribute epilogue to function's closing brace + let fn_end = Span { lo: span.hi, ..span }; + let source_info = builder.source_info(fn_end); let return_block = builder.return_block(); builder.cfg.terminate(block, source_info, TerminatorKind::Goto { target: return_block }); diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 01cce3c7dd794..ae6a1fb473b6d 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -521,8 +521,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if let DropKind::Value { .. } = drop_kind { scope.needs_cleanup = true; } + let tcx = self.hir.tcx(); + let extent_span = extent.span(&tcx.region_maps, &tcx.map).unwrap(); + // Attribute scope exit drops to scope's closing brace + let scope_end = Span { lo: extent_span.hi, .. extent_span}; scope.drops.push(DropData { - span: span, + span: scope_end, location: lvalue.clone(), kind: drop_kind }); diff --git a/src/test/debuginfo/drop-locations.rs b/src/test/debuginfo/drop-locations.rs new file mode 100644 index 0000000000000..3a7c534c13902 --- /dev/null +++ b/src/test/debuginfo/drop-locations.rs @@ -0,0 +1,91 @@ +// Copyright 2013-2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-windows +// ignore-android +// min-lldb-version: 310 + +#![allow(unused)] + +// compile-flags:-g + +// This test checks that drop glue code gets attributed to scope's closing brace, +// and function epilogues - to function's closing brace. + +// === GDB TESTS =================================================================================== + +// gdb-command:run +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#loc1[...] +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#loc2[...] +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#loc3[...] +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#loc4[...] +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#loc5[...] +// gdb-command:next +// gdb-command:frame +// gdb-check:[...]#loc6[...] + +// === LLDB TESTS ================================================================================== + +// lldb-command:set set stop-line-count-before 0 +// lldb-command:set set stop-line-count-after 1 +// Can't set both to zero or lldb will stop printing source at all. So it will output the current +// line and the next. We deal with this by having at least 2 lines between the #loc's + +// lldb-command:run +// lldb-command:next +// lldb-command:frame select +// lldb-check:[...]#loc1[...] +// lldb-command:next +// lldb-command:frame select +// lldb-check:[...]#loc2[...] +// lldb-command:next +// lldb-command:frame select +// lldb-check:[...]#loc3[...] +// lldb-command:next +// lldb-command:frame select +// lldb-check:[...]#loc4[...] +// lldb-command:next +// lldb-command:frame select +// lldb-check:[...]#loc5[...] +// lldb-command:next +// lldb-command:frame select +// lldb-check:[...]#loc6[...] + +fn main() { + + foo(); + + zzz(); // #loc5 + +} // #loc6 + +fn foo() { + { + let s = String::from("s"); // #break + + zzz(); // #loc1 + + } // #loc2 + + zzz(); // #loc3 + +} // #loc4 + +fn zzz() {()} From a935481ae9052d42c39af1d71c8e8e64750c9e02 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 21 Oct 2016 10:31:53 +1100 Subject: [PATCH 08/14] Avoid an unnecessary clone in `macro_parser::parse`. This avoids ~800,000 allocations in html5ever. --- src/libsyntax/ext/tt/macro_parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index ef2e466a04398..a664e115ce4b4 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -425,8 +425,8 @@ pub fn parse(sess: &ParseSess, cur_eis.push(ei); } TokenTree::Token(_, ref t) => { - let mut ei_t = ei.clone(); if token_name_eq(t,&tok) { + let mut ei_t = ei.clone(); ei_t.idx += 1; next_eis.push(ei_t); } From e382267cfb9133ef12d59b66a2935ee45b546a61 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 21 Oct 2016 10:42:30 +1100 Subject: [PATCH 09/14] Avoid an unnecessary clone in `generic_extensions`. This avoids ~800,000 allocations in html5ever. --- src/libsyntax/ext/tt/macro_rules.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index a74d335d6046d..c585c66f9a228 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -139,9 +139,9 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, macro_ident: name }) } - Failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo { + Failure(sp, msg) => if sp.lo >= best_fail_spot.lo { best_fail_spot = sp; - best_fail_msg = (*msg).clone(); + best_fail_msg = msg; }, Error(err_sp, ref msg) => { cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..]) From b817cf8b5730912c558aff811cd34fc3d3fa8637 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 21 Oct 2016 12:01:06 +1100 Subject: [PATCH 10/14] Replace the `String` in `ParseResult::Failure` with `Token`. This lets us delay creation of failure messages until they are needed, which avoids ~1.6M allocations in html5ever. --- src/libsyntax/ext/tt/macro_parser.rs | 19 +++++++++++++------ src/libsyntax/ext/tt/macro_rules.rs | 19 ++++++++++++------- .../auxiliary/procedural_mbe_matching.rs | 8 ++++++-- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index a664e115ce4b4..74def68b18504 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -251,14 +251,22 @@ pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc]) pub enum ParseResult { Success(T), - /// Arm failed to match - Failure(syntax_pos::Span, String), + /// Arm failed to match. If the second parameter is `token::Eof`, it + /// indicates an unexpected end of macro invocation. Otherwise, it + /// indicates that no rules expected the given token. + Failure(syntax_pos::Span, Token), /// Fatal error (malformed macro?). Abort compilation. Error(syntax_pos::Span, String) } +pub fn parse_failure_msg(tok: Token) -> String { + match tok { + token::Eof => "unexpected end of macro invocation".to_string(), + _ => format!("no rules expected the token `{}`", pprust::token_to_string(&tok)), + } +} + pub type NamedParseResult = ParseResult>>; -pub type PositionalParseResult = ParseResult>>; /// Perform a token equality check, ignoring syntax context (that is, an /// unhygienic comparison) @@ -446,7 +454,7 @@ pub fn parse(sess: &ParseSess, } else if eof_eis.len() > 1 { return Error(sp, "ambiguity: multiple successful parses".to_string()); } else { - return Failure(sp, "unexpected end of macro invocation".to_string()); + return Failure(sp, token::Eof); } } else { if (!bb_eis.is_empty() && !next_eis.is_empty()) @@ -467,8 +475,7 @@ pub fn parse(sess: &ParseSess, } )) } else if bb_eis.is_empty() && next_eis.is_empty() { - return Failure(sp, format!("no rules expected the token `{}`", - pprust::token_to_string(&tok))); + return Failure(sp, tok); } else if !next_eis.is_empty() { /* Now process the next token */ while !next_eis.is_empty() { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index c585c66f9a228..06d8dc74788e9 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -16,7 +16,7 @@ use ext::expand::{Expansion, ExpansionKind}; use ext::placeholders; use ext::tt::macro_parser::{Success, Error, Failure}; use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal}; -use ext::tt::macro_parser::parse; +use ext::tt::macro_parser::{parse, parse_failure_msg}; use parse::ParseSess; use parse::lexer::new_tt_reader; use parse::parser::{Parser, Restrictions}; @@ -100,7 +100,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, // Which arm's failure should we report? (the one furthest along) let mut best_fail_spot = DUMMY_SP; - let mut best_fail_msg = "internal error: ran no matchers".to_string(); + let mut best_fail_tok = None; for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers let lhs_tt = match *lhs { @@ -139,9 +139,9 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, macro_ident: name }) } - Failure(sp, msg) => if sp.lo >= best_fail_spot.lo { + Failure(sp, tok) => if sp.lo >= best_fail_spot.lo { best_fail_spot = sp; - best_fail_msg = msg; + best_fail_tok = Some(tok); }, Error(err_sp, ref msg) => { cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..]) @@ -149,7 +149,8 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, } } - cx.span_fatal(best_fail_spot.substitute_dummy(sp), &best_fail_msg[..]); + let best_fail_msg = parse_failure_msg(best_fail_tok.expect("ran no matchers")); + cx.span_fatal(best_fail_spot.substitute_dummy(sp), &best_fail_msg); } pub struct MacroRulesExpander; @@ -227,8 +228,12 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension { let argument_map = match parse(sess, &Vec::new(), arg_reader, &argument_gram) { Success(m) => m, - Failure(sp, str) | Error(sp, str) => { - panic!(sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &str)); + Failure(sp, tok) => { + let s = parse_failure_msg(tok); + panic!(sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s)); + } + Error(sp, s) => { + panic!(sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s)); } }; diff --git a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs index 2b50c4fe11e93..5229d42f1fdd4 100644 --- a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs +++ b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs @@ -25,6 +25,7 @@ use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; use syntax::ext::build::AstBuilder; use syntax::ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal}; use syntax::ext::tt::macro_parser::{Success, Failure, Error}; +use syntax::ext::tt::macro_parser::parse_failure_msg; use syntax::ptr::P; use syntax_pos::Span; use rustc_plugin::Registry; @@ -58,8 +59,11 @@ fn expand_mbe_matches(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) _ => unreachable!() } } - Failure(_, s) | Error(_, s) => { - panic!("expected Success, but got Error/Failure: {}", s); + Failure(_, tok) => { + panic!("expected Success, but got Failure: {}", parse_failure_msg(tok)); + } + Error(_, s) => { + panic!("expected Success, but got Error: {}", s); } }; From 974817d4932fd447f724c4527360a258952ffd48 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 18 Oct 2016 21:32:31 -0400 Subject: [PATCH 11/14] when pop skol, also remove from proj cache --- src/librustc/infer/higher_ranked/mod.rs | 1 + src/librustc/traits/project.rs | 10 +++- .../snapshot_map/mod.rs | 57 ++++++++++++++----- 3 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index c1d9240ba0634..069fb3e796776 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -839,5 +839,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { debug!("pop_skolemized({:?})", skol_map); let skol_regions: FnvHashSet<_> = skol_map.values().cloned().collect(); self.region_vars.pop_skolemized(&skol_regions, &snapshot.region_vars_snapshot); + self.projection_cache.borrow_mut().partial_rollback(&snapshot.projection_cache_snapshot); } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 27554c0d2a44d..71196306121ce 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -167,7 +167,7 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>( infcx.skolemize_late_bound_regions(&obligation.predicate, snapshot); let skol_obligation = obligation.with(skol_predicate); - match project_and_unify_type(selcx, &skol_obligation) { + let r = match project_and_unify_type(selcx, &skol_obligation) { Ok(result) => { let span = obligation.cause.span; match infcx.leak_check(false, span, &skol_map, snapshot) { @@ -178,7 +178,9 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>( Err(e) => { Err(e) } - } + }; + + r }) } @@ -1396,6 +1398,10 @@ impl<'tcx> ProjectionCache<'tcx> { self.map.rollback_to(snapshot.snapshot); } + pub fn partial_rollback(&mut self, snapshot: &ProjectionCacheSnapshot) { + self.map.partial_rollback(&snapshot.snapshot); + } + pub fn commit(&mut self, snapshot: ProjectionCacheSnapshot) { self.map.commit(snapshot.snapshot); } diff --git a/src/librustc_data_structures/snapshot_map/mod.rs b/src/librustc_data_structures/snapshot_map/mod.rs index 0306066d6e784..23a67b3bd93ca 100644 --- a/src/librustc_data_structures/snapshot_map/mod.rs +++ b/src/librustc_data_structures/snapshot_map/mod.rs @@ -11,6 +11,7 @@ use fnv::FnvHashMap; use std::hash::Hash; use std::ops; +use std::mem; #[cfg(test)] mod test; @@ -31,6 +32,7 @@ enum UndoLog { CommittedSnapshot, Inserted(K), Overwrite(K, V), + Noop, } impl SnapshotMap @@ -100,24 +102,29 @@ impl SnapshotMap } } + pub fn partial_rollback(&mut self, snapshot: &Snapshot) { + self.assert_open_snapshot(snapshot); + for i in (snapshot.len + 1..self.undo_log.len()).rev() { + let reverse = match self.undo_log[i] { + UndoLog::OpenSnapshot => false, + UndoLog::CommittedSnapshot => false, + UndoLog::Noop => false, + UndoLog::Inserted(..) => true, + UndoLog::Overwrite(..) => true, + }; + + if reverse { + let entry = mem::replace(&mut self.undo_log[i], UndoLog::Noop); + self.reverse(entry); + } + } + } + pub fn rollback_to(&mut self, snapshot: Snapshot) { self.assert_open_snapshot(&snapshot); while self.undo_log.len() > snapshot.len + 1 { - match self.undo_log.pop().unwrap() { - UndoLog::OpenSnapshot => { - panic!("cannot rollback an uncommitted snapshot"); - } - - UndoLog::CommittedSnapshot => {} - - UndoLog::Inserted(key) => { - self.map.remove(&key); - } - - UndoLog::Overwrite(key, old_value) => { - self.map.insert(key, old_value); - } - } + let entry = self.undo_log.pop().unwrap(); + self.reverse(entry); } let v = self.undo_log.pop().unwrap(); @@ -127,6 +134,26 @@ impl SnapshotMap }); assert!(self.undo_log.len() == snapshot.len); } + + fn reverse(&mut self, entry: UndoLog) { + match entry { + UndoLog::OpenSnapshot => { + panic!("cannot rollback an uncommitted snapshot"); + } + + UndoLog::CommittedSnapshot => {} + + UndoLog::Inserted(key) => { + self.map.remove(&key); + } + + UndoLog::Overwrite(key, old_value) => { + self.map.insert(key, old_value); + } + + UndoLog::Noop => {} + } + } } impl<'k, K, V> ops::Index<&'k K> for SnapshotMap From 567b11fc3a70cdba960bf6037b9d658fafdc5ada Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 19 Oct 2016 18:39:49 -0400 Subject: [PATCH 12/14] only remove keys that mention skolemized regions --- src/librustc/infer/higher_ranked/mod.rs | 5 ++- src/librustc/traits/project.rs | 4 +-- src/librustc/ty/flags.rs | 22 +++---------- src/librustc/ty/fold.rs | 26 ++++++---------- src/librustc/ty/mod.rs | 1 + src/librustc/ty/sty.rs | 31 ++++++++++++++++++- .../snapshot_map/mod.rs | 10 ++++-- 7 files changed, 57 insertions(+), 42 deletions(-) diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index 069fb3e796776..25b899b3c56cd 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -839,6 +839,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { debug!("pop_skolemized({:?})", skol_map); let skol_regions: FnvHashSet<_> = skol_map.values().cloned().collect(); self.region_vars.pop_skolemized(&skol_regions, &snapshot.region_vars_snapshot); - self.projection_cache.borrow_mut().partial_rollback(&snapshot.projection_cache_snapshot); + if !skol_map.is_empty() { + self.projection_cache.borrow_mut().rollback_skolemized( + &snapshot.projection_cache_snapshot); + } } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 71196306121ce..f1f1658cc824d 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1398,8 +1398,8 @@ impl<'tcx> ProjectionCache<'tcx> { self.map.rollback_to(snapshot.snapshot); } - pub fn partial_rollback(&mut self, snapshot: &ProjectionCacheSnapshot) { - self.map.partial_rollback(&snapshot.snapshot); + pub fn rollback_skolemized(&mut self, snapshot: &ProjectionCacheSnapshot) { + self.map.partial_rollback(&snapshot.snapshot, &|k| k.has_re_skol()); } pub fn commit(&mut self, snapshot: ProjectionCacheSnapshot) { diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 1434b0e60e21c..649d78f9d9e2d 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -11,6 +11,7 @@ use ty::subst::Substs; use ty::{self, Ty, TypeFlags, TypeFoldable}; +#[derive(Debug)] pub struct FlagComputation { pub flags: TypeFlags, @@ -182,24 +183,9 @@ impl FlagComputation { } fn add_region(&mut self, r: &ty::Region) { - match *r { - ty::ReVar(..) => { - self.add_flags(TypeFlags::HAS_RE_INFER); - self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX); - } - ty::ReSkolemized(..) => { - self.add_flags(TypeFlags::HAS_RE_INFER); - self.add_flags(TypeFlags::HAS_RE_SKOL); - self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX); - } - ty::ReLateBound(debruijn, _) => { self.add_depth(debruijn.depth); } - ty::ReEarlyBound(..) => { self.add_flags(TypeFlags::HAS_RE_EARLY_BOUND); } - ty::ReStatic | ty::ReErased => {} - _ => { self.add_flags(TypeFlags::HAS_FREE_REGIONS); } - } - - if !r.is_global() { - self.add_flags(TypeFlags::HAS_LOCAL_NAMES); + self.add_flags(r.type_flags()); + if let ty::ReLateBound(debruijn, _) = *r { + self.add_depth(debruijn.depth); } } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 886ad8cd8611d..ae0a4a0e6bd11 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -91,6 +91,9 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { fn needs_subst(&self) -> bool { self.has_type_flags(TypeFlags::NEEDS_SUBST) } + fn has_re_skol(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_SKOL) + } fn has_closure_types(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_CLOSURE) } @@ -632,26 +635,15 @@ struct HasTypeFlagsVisitor { impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { fn visit_ty(&mut self, t: Ty) -> bool { - t.flags.get().intersects(self.flags) + let flags = t.flags.get(); + debug!("HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}", t, flags, self.flags); + flags.intersects(self.flags) } fn visit_region(&mut self, r: &'tcx ty::Region) -> bool { - if self.flags.intersects(ty::TypeFlags::HAS_LOCAL_NAMES) { - // does this represent a region that cannot be named - // in a global way? used in fulfillment caching. - match *r { - ty::ReStatic | ty::ReEmpty | ty::ReErased => {} - _ => return true, - } - } - if self.flags.intersects(ty::TypeFlags::HAS_RE_INFER | - ty::TypeFlags::KEEP_IN_LOCAL_TCX) { - match *r { - ty::ReVar(_) | ty::ReSkolemized(..) => { return true } - _ => {} - } - } - false + let flags = r.type_flags(); + debug!("HasTypeFlagsVisitor: r={:?} r.flags={:?} self.flags={:?}", r, flags, self.flags); + flags.intersects(self.flags) } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 018f01e5913c0..eca699a393dda 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -477,6 +477,7 @@ bitflags! { TypeFlags::HAS_SELF.bits | TypeFlags::HAS_TY_INFER.bits | TypeFlags::HAS_RE_INFER.bits | + TypeFlags::HAS_RE_SKOL.bits | TypeFlags::HAS_RE_EARLY_BOUND.bits | TypeFlags::HAS_FREE_REGIONS.bits | TypeFlags::HAS_TY_ERR.bits | diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 302cab0446cd3..92dfb883ef301 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -406,7 +406,7 @@ impl Binder { impl fmt::Debug for TypeFlags { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.bits) + write!(f, "{:x}", self.bits) } } @@ -866,6 +866,35 @@ impl Region { r => r } } + + pub fn type_flags(&self) -> TypeFlags { + let mut flags = TypeFlags::empty(); + + match *self { + ty::ReVar(..) => { + flags = flags | TypeFlags::HAS_RE_INFER; + flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX; + } + ty::ReSkolemized(..) => { + flags = flags | TypeFlags::HAS_RE_INFER; + flags = flags | TypeFlags::HAS_RE_SKOL; + flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX; + } + ty::ReLateBound(..) => { } + ty::ReEarlyBound(..) => { flags = flags | TypeFlags::HAS_RE_EARLY_BOUND; } + ty::ReStatic | ty::ReErased => { } + _ => { flags = flags | TypeFlags::HAS_FREE_REGIONS; } + } + + match *self { + ty::ReStatic | ty::ReEmpty | ty::ReErased => (), + _ => flags = flags | TypeFlags::HAS_LOCAL_NAMES, + } + + debug!("type_flags({:?}) = {:?}", self, flags); + + flags + } } // Type utilities diff --git a/src/librustc_data_structures/snapshot_map/mod.rs b/src/librustc_data_structures/snapshot_map/mod.rs index 23a67b3bd93ca..a4e6166032d81 100644 --- a/src/librustc_data_structures/snapshot_map/mod.rs +++ b/src/librustc_data_structures/snapshot_map/mod.rs @@ -102,15 +102,19 @@ impl SnapshotMap } } - pub fn partial_rollback(&mut self, snapshot: &Snapshot) { + pub fn partial_rollback(&mut self, + snapshot: &Snapshot, + should_revert_key: &F) + where F: Fn(&K) -> bool + { self.assert_open_snapshot(snapshot); for i in (snapshot.len + 1..self.undo_log.len()).rev() { let reverse = match self.undo_log[i] { UndoLog::OpenSnapshot => false, UndoLog::CommittedSnapshot => false, UndoLog::Noop => false, - UndoLog::Inserted(..) => true, - UndoLog::Overwrite(..) => true, + UndoLog::Inserted(ref k) => should_revert_key(k), + UndoLog::Overwrite(ref k, _) => should_revert_key(k), }; if reverse { From 483bc864cafe871bfeb82e44a804ed7ea49442a0 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 19 Oct 2016 18:43:48 -0400 Subject: [PATCH 13/14] add regression test for #37154 Fixes #37154 --- .../run-pass/project-cache-issue-37154.rs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/test/run-pass/project-cache-issue-37154.rs diff --git a/src/test/run-pass/project-cache-issue-37154.rs b/src/test/run-pass/project-cache-issue-37154.rs new file mode 100644 index 0000000000000..29dc6984e234a --- /dev/null +++ b/src/test/run-pass/project-cache-issue-37154.rs @@ -0,0 +1,28 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #37154: the problem here was that the cache +// results in a false error because it was caching skolemized results +// even after those skolemized regions had been popped. + +trait Foo { + fn method(&self) {} +} + +struct Wrapper(T); + +impl Foo for Wrapper where for<'a> &'a T: IntoIterator {} + +fn f(x: Wrapper>) { + x.method(); // This works. + x.method(); // error: no method named `method` +} + +fn main() { } From 7e603d4e3b2551608a225e115da4e83559b94761 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 21 Oct 2016 16:51:59 +0200 Subject: [PATCH 14/14] Implement `From> for String` and `From> for Vec`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Motivation: the `selectors` crate is generic over a string type, in order to support all of `String`, `string_cache::Atom`, and `gecko_string_cache::Atom`. Multiple trait bounds are used for the various operations done with these strings. One of these operations is creating a string (as efficiently as possible, re-using an existing memory allocation if possible) from `Cow`. The `std::convert::From` trait seems natural for this, but the relevant implementation was missing before this PR. To work around this I’ve added a `FromCowStr` trait in `selectors`, but with trait coherence that means one of `selectors` or `string_cache` needs to depend on the other to implement this trait. Using a trait from `std` would solve this. The `Vec` implementation is just added for consistency. I also tried a more general `impl<'a, O, B: ?Sized + ToOwned> From> for O`, but (the compiler thinks?) it conflicts with `From for T` the impl (after moving all of `collections::borrow` into `core::borrow` to work around trait coherence). --- src/libcollections/string.rs | 7 +++++++ src/libcollections/vec.rs | 7 +++++++ src/libcollectionstest/string.rs | 6 ++++++ src/libcollectionstest/vec.rs | 8 ++++++++ 4 files changed, 28 insertions(+) diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 7a61451b900c0..ce9fec3291724 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1860,6 +1860,13 @@ impl<'a> From<&'a str> for String { } } +#[stable(feature = "string_from_cow_str", since = "1.14.0")] +impl<'a> From> for String { + fn from(s: Cow<'a, str>) -> String { + s.into_owned() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a> From<&'a str> for Cow<'a, str> { #[inline] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index f3d78c20a4d6b..f7c3e8ea1ede4 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1764,6 +1764,13 @@ impl<'a, T: Clone> From<&'a [T]> for Vec { } } +#[stable(feature = "vec_from_cow_slice", since = "1.14.0")] +impl<'a, T> From> for Vec where [T]: ToOwned> { + fn from(s: Cow<'a, [T]>) -> Vec { + s.into_owned() + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a> From<&'a str> for Vec { fn from(s: &'a str) -> Vec { diff --git a/src/libcollectionstest/string.rs b/src/libcollectionstest/string.rs index 1652fb5a88d80..98de33bdaa8e1 100644 --- a/src/libcollectionstest/string.rs +++ b/src/libcollectionstest/string.rs @@ -35,6 +35,12 @@ fn test_from_str() { assert_eq!(owned.as_ref().map(|s| &**s), Some("string")); } +#[test] +fn test_from_cow_str() { + assert_eq!(String::from(Cow::Borrowed("string")), "string"); + assert_eq!(String::from(Cow::Owned(String::from("string"))), "string"); +} + #[test] fn test_unsized_to_string() { let s: &str = "abc"; diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs index 991c456fe7463..9a04673d1da0d 100644 --- a/src/libcollectionstest/vec.rs +++ b/src/libcollectionstest/vec.rs @@ -597,6 +597,14 @@ fn test_cow_from() { } } +#[test] +fn test_from_cow() { + let borrowed: &[_] = &["borrowed", "(slice)"]; + let owned = vec!["owned", "(vec)"]; + assert_eq!(Vec::from(Cow::Borrowed(borrowed)), vec!["borrowed", "(slice)"]); + assert_eq!(Vec::from(Cow::Owned(owned)), vec!["owned", "(vec)"]); +} + #[allow(dead_code)] fn assert_covariance() { fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d }