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 f41f9b2c45a28..df76140f687a7 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1797,6 +1797,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 } diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index 63913f2878c20..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 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 +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 -fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Bytes { +/// 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_FAST | TDEFL_GREEDY_PARSING_FLAG; unsafe { let mut outsz: size_t = 0; let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _, @@ -113,17 +116,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 +136,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)] diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index c1d9240ba0634..25b899b3c56cd 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -839,5 +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); + 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 27554c0d2a44d..f1f1658cc824d 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 rollback_skolemized(&mut self, snapshot: &ProjectionCacheSnapshot) { + self.map.partial_rollback(&snapshot.snapshot, &|k| k.has_re_skol()); + } + pub fn commit(&mut self, snapshot: ProjectionCacheSnapshot) { self.map.commit(snapshot.snapshot); } 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 0306066d6e784..a4e6166032d81 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,33 @@ impl SnapshotMap } } + 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(ref k) => should_revert_key(k), + UndoLog::Overwrite(ref k, _) => should_revert_key(k), + }; + + 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 +138,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 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_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 f97df67c44560..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; @@ -40,14 +40,14 @@ use syntax::parse::token::InternedString; use syntax_pos::{self, Span, mk_sp}; use log; -pub struct CrateLoader<'a> { - pub sess: &'a Session, - pub creader: CrateReader<'a>, - cstore: &'a CStore, +pub struct Library { + pub dylib: Option<(PathBuf, PathKind)>, + pub rlib: Option<(PathBuf, PathKind)>, + pub metadata: MetadataBlob, } -pub struct CrateReader<'a> { - sess: &'a Session, +pub struct CrateLoader<'a> { + pub sess: &'a Session, cstore: &'a CStore, next_crate_num: CrateNum, foreign_item_map: FnvHashMap>, @@ -129,7 +129,7 @@ struct ExtensionCrate { enum PMDSource { Registered(Rc), - Owned(loader::Library), + Owned(Library), } impl Deref for PMDSource { @@ -145,7 +145,7 @@ impl Deref for PMDSource { enum LoadResult { Previous(CrateNum), - Loaded(loader::Library), + Loaded(Library), } pub struct Macros { @@ -159,13 +159,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(), @@ -281,7 +281,7 @@ impl<'a> CrateReader<'a> { ident: &str, name: &str, span: Span, - lib: loader::Library, + lib: Library, explicitly_linked: bool) -> (CrateNum, Rc, cstore::CrateSource) { @@ -306,7 +306,7 @@ impl<'a> CrateReader<'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); @@ -352,7 +352,7 @@ impl<'a> CrateReader<'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> CrateReader<'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> CrateReader<'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> CrateReader<'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> CrateReader<'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> CrateReader<'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> CrateReader<'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 { @@ -890,7 +890,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 +901,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 +968,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 +977,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 +987,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 +1010,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 +1024,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/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/csearch.rs b/src/librustc_metadata/cstore_impl.rs similarity index 99% rename from src/librustc_metadata/csearch.rs rename to src/librustc_metadata/cstore_impl.rs index 54664b9c04046..7637b769f9377 100644 --- a/src/librustc_metadata/csearch.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 3d8a10f6c31fc..c0fc1a7065cc0 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -53,12 +53,12 @@ mod index_builder; mod index; mod encoder; mod decoder; -mod csearch; +mod cstore_impl; 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 75242fc36db76..e684cd16366ec 100644 --- a/src/librustc_metadata/loader.rs +++ b/src/librustc_metadata/locator.rs @@ -210,9 +210,10 @@ //! //! 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; 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 @@ -315,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", diff --git a/src/librustc_metadata/macro_import.rs b/src/librustc_metadata/macro_import.rs index 41e14ea9f406f..455bc4b7d2be9 100644 --- a/src/librustc_metadata/macro_import.rs +++ b/src/librustc_metadata/macro_import.rs @@ -122,7 +122,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_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/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![], } } diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index ef2e466a04398..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) @@ -425,8 +433,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); } @@ -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 5496d27c08740..61911e0d3b3d5 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}; @@ -97,7 +97,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 { @@ -134,9 +134,9 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, macro_ident: name }) } - Failure(sp, ref 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).clone(); + best_fail_tok = Some(tok); }, Error(err_sp, ref msg) => { cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..]) @@ -144,7 +144,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; @@ -222,8 +223,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/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() {()} 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); } }; 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() { }