diff options
Diffstat (limited to 'src/librustc_span/lib.rs')
| -rw-r--r-- | src/librustc_span/lib.rs | 214 |
1 files changed, 134 insertions, 80 deletions
diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 502ea64aab9..0d9f3f214fb 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -6,6 +6,10 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(crate_visibility_modifier)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] +#![cfg_attr(not(bootstrap), feature(negative_impls))] #![feature(nll)] #![feature(optin_builtin_traits)] #![feature(specialization)] @@ -24,7 +28,7 @@ pub mod hygiene; use hygiene::Transparency; pub use hygiene::{DesugaringKind, ExpnData, ExpnId, ExpnKind, MacroKind, SyntaxContext}; pub mod def_id; -use def_id::DefId; +use def_id::{CrateNum, DefId, LOCAL_CRATE}; mod span_encoding; pub use span_encoding::{Span, DUMMY_SP}; @@ -43,9 +47,14 @@ use std::borrow::Cow; use std::cell::RefCell; use std::cmp::{self, Ordering}; use std::fmt; -use std::hash::{Hash, Hasher}; +use std::hash::Hash; use std::ops::{Add, Sub}; use std::path::PathBuf; +use std::str::FromStr; + +use md5::Md5; +use sha1::Digest; +use sha1::Sha1; #[cfg(test)] mod tests; @@ -69,22 +78,10 @@ impl Globals { scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals); /// Differentiates between real files and common virtual files. -#[derive( - Debug, - Eq, - PartialEq, - Clone, - Ord, - PartialOrd, - Hash, - RustcDecodable, - RustcEncodable, - HashStable_Generic -)] +#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)] +#[derive(HashStable_Generic)] pub enum FileName { Real(PathBuf), - /// A macro. This includes the full name of the macro, so that there are no clashes. - Macros(String), /// Call to `quote!`. QuoteExpansion(u64), /// Command line. @@ -107,7 +104,6 @@ impl std::fmt::Display for FileName { use FileName::*; match *self { Real(ref path) => write!(fmt, "{}", path.display()), - Macros(ref name) => write!(fmt, "<{} macros>", name), QuoteExpansion(_) => write!(fmt, "<quote expansion>"), MacroExpansion(_) => write!(fmt, "<macro expansion>"), Anon(_) => write!(fmt, "<anon>"), @@ -132,23 +128,7 @@ impl FileName { use FileName::*; match *self { Real(_) => true, - Macros(_) - | Anon(_) - | MacroExpansion(_) - | ProcMacroSourceCode(_) - | CfgSpec(_) - | CliCrateAttr(_) - | Custom(_) - | QuoteExpansion(_) - | DocTest(_, _) => false, - } - } - - pub fn is_macros(&self) -> bool { - use FileName::*; - match *self { - Real(_) - | Anon(_) + Anon(_) | MacroExpansion(_) | ProcMacroSourceCode(_) | CfgSpec(_) @@ -156,7 +136,6 @@ impl FileName { | Custom(_) | QuoteExpansion(_) | DocTest(_, _) => false, - Macros(_) => true, } } @@ -568,9 +547,9 @@ impl Span { } #[inline] - pub fn modernize_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> { + pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> { let mut span = self.data(); - let mark = span.ctxt.modernize_and_adjust(expn_id); + let mark = span.ctxt.normalize_to_macros_2_0_and_adjust(expn_id); *self = Span::new(span.lo, span.hi, span.ctxt); mark } @@ -596,15 +575,15 @@ impl Span { } #[inline] - pub fn modern(self) -> Span { + pub fn normalize_to_macros_2_0(self) -> Span { let span = self.data(); - span.with_ctxt(span.ctxt.modern()) + span.with_ctxt(span.ctxt.normalize_to_macros_2_0()) } #[inline] - pub fn modern_and_legacy(self) -> Span { + pub fn normalize_to_macro_rules(self) -> Span { let span = self.data(); - span.with_ctxt(span.ctxt.modern_and_legacy()) + span.with_ctxt(span.ctxt.normalize_to_macro_rules()) } } @@ -856,30 +835,42 @@ pub struct NormalizedPos { pub diff: u32, } -/// The state of the lazy external source loading mechanism of a `SourceFile`. -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Eq, Clone, Debug)] pub enum ExternalSource { + /// No external source has to be loaded, since the `SourceFile` represents a local crate. + Unneeded, + Foreign { + kind: ExternalSourceKind, + /// This SourceFile's byte-offset within the source_map of its original crate + original_start_pos: BytePos, + /// The end of this SourceFile within the source_map of its original crate + original_end_pos: BytePos, + }, +} + +/// The state of the lazy external source loading mechanism of a `SourceFile`. +#[derive(PartialEq, Eq, Clone, Debug)] +pub enum ExternalSourceKind { /// The external source has been loaded already. - Present(String), + Present(Lrc<String>), /// No attempt has been made to load the external source. AbsentOk, /// A failed attempt has been made to load the external source. AbsentErr, - /// No external source has to be loaded, since the `SourceFile` represents a local crate. Unneeded, } impl ExternalSource { pub fn is_absent(&self) -> bool { - match *self { - ExternalSource::Present(_) => false, + match self { + ExternalSource::Foreign { kind: ExternalSourceKind::Present(_), .. } => false, _ => true, } } - pub fn get_source(&self) -> Option<&str> { - match *self { - ExternalSource::Present(ref src) => Some(src), + pub fn get_source(&self) -> Option<&Lrc<String>> { + match self { + ExternalSource::Foreign { kind: ExternalSourceKind::Present(ref src), .. } => Some(src), _ => None, } } @@ -888,6 +879,70 @@ impl ExternalSource { #[derive(Debug)] pub struct OffsetOverflowError; +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +pub enum SourceFileHashAlgorithm { + Md5, + Sha1, +} + +impl FromStr for SourceFileHashAlgorithm { + type Err = (); + + fn from_str(s: &str) -> Result<SourceFileHashAlgorithm, ()> { + match s { + "md5" => Ok(SourceFileHashAlgorithm::Md5), + "sha1" => Ok(SourceFileHashAlgorithm::Sha1), + _ => Err(()), + } + } +} + +rustc_data_structures::impl_stable_hash_via_hash!(SourceFileHashAlgorithm); + +/// The hash of the on-disk source file used for debug info. +#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)] +#[derive(HashStable_Generic)] +pub struct SourceFileHash { + pub kind: SourceFileHashAlgorithm, + value: [u8; 20], +} + +impl SourceFileHash { + pub fn new(kind: SourceFileHashAlgorithm, src: &str) -> SourceFileHash { + let mut hash = SourceFileHash { kind, value: Default::default() }; + let len = hash.hash_len(); + let value = &mut hash.value[..len]; + let data = src.as_bytes(); + match kind { + SourceFileHashAlgorithm::Md5 => { + value.copy_from_slice(&Md5::digest(data)); + } + SourceFileHashAlgorithm::Sha1 => { + value.copy_from_slice(&Sha1::digest(data)); + } + } + hash + } + + /// Check if the stored hash matches the hash of the string. + pub fn matches(&self, src: &str) -> bool { + Self::new(self.kind, src) == *self + } + + /// The bytes of the hash. + pub fn hash_bytes(&self) -> &[u8] { + let len = self.hash_len(); + &self.value[..len] + } + + fn hash_len(&self) -> usize { + match self.kind { + SourceFileHashAlgorithm::Md5 => 16, + SourceFileHashAlgorithm::Sha1 => 20, + } + } +} + /// A single source in the `SourceMap`. #[derive(Clone)] pub struct SourceFile { @@ -900,12 +955,10 @@ pub struct SourceFile { /// The unmapped path of the file that the source came from. /// Set to `None` if the `SourceFile` was imported from an external crate. pub unmapped_path: Option<FileName>, - /// Indicates which crate this `SourceFile` was imported from. - pub crate_of_origin: u32, /// The complete source code. pub src: Option<Lrc<String>>, /// The source code's hash. - pub src_hash: u128, + pub src_hash: SourceFileHash, /// The external source code (used for external crates, which will have a `None` /// value as `self.src`. pub external_src: Lock<ExternalSource>, @@ -923,6 +976,8 @@ pub struct SourceFile { pub normalized_pos: Vec<NormalizedPos>, /// A hash of the filename, used for speeding up hashing in incremental compilation. pub name_hash: u128, + /// Indicates which crate this `SourceFile` was imported from. + pub cnum: CrateNum, } impl Encodable for SourceFile { @@ -989,7 +1044,8 @@ impl Encodable for SourceFile { s.emit_struct_field("multibyte_chars", 6, |s| self.multibyte_chars.encode(s))?; s.emit_struct_field("non_narrow_chars", 7, |s| self.non_narrow_chars.encode(s))?; s.emit_struct_field("name_hash", 8, |s| self.name_hash.encode(s))?; - s.emit_struct_field("normalized_pos", 9, |s| self.normalized_pos.encode(s)) + s.emit_struct_field("normalized_pos", 9, |s| self.normalized_pos.encode(s))?; + s.emit_struct_field("cnum", 10, |s| self.cnum.encode(s)) }) } } @@ -1000,7 +1056,8 @@ impl Decodable for SourceFile { let name: FileName = d.read_struct_field("name", 0, |d| Decodable::decode(d))?; let name_was_remapped: bool = d.read_struct_field("name_was_remapped", 1, |d| Decodable::decode(d))?; - let src_hash: u128 = d.read_struct_field("src_hash", 2, |d| Decodable::decode(d))?; + let src_hash: SourceFileHash = + d.read_struct_field("src_hash", 2, |d| Decodable::decode(d))?; let start_pos: BytePos = d.read_struct_field("start_pos", 3, |d| Decodable::decode(d))?; let end_pos: BytePos = d.read_struct_field("end_pos", 4, |d| Decodable::decode(d))?; @@ -1039,24 +1096,24 @@ impl Decodable for SourceFile { let name_hash: u128 = d.read_struct_field("name_hash", 8, |d| Decodable::decode(d))?; let normalized_pos: Vec<NormalizedPos> = d.read_struct_field("normalized_pos", 9, |d| Decodable::decode(d))?; + let cnum: CrateNum = d.read_struct_field("cnum", 10, |d| Decodable::decode(d))?; Ok(SourceFile { name, name_was_remapped, unmapped_path: None, - // `crate_of_origin` has to be set by the importer. - // This value matches up with `rustc_hir::def_id::INVALID_CRATE`. - // That constant is not available here, unfortunately. - crate_of_origin: std::u32::MAX - 1, start_pos, end_pos, src: None, src_hash, - external_src: Lock::new(ExternalSource::AbsentOk), + // Unused - the metadata decoder will construct + // a new SourceFile, filling in `external_src` properly + external_src: Lock::new(ExternalSource::Unneeded), lines, multibyte_chars, non_narrow_chars, normalized_pos, name_hash, + cnum, }) }) } @@ -1075,14 +1132,12 @@ impl SourceFile { unmapped_path: FileName, mut src: String, start_pos: BytePos, + hash_kind: SourceFileHashAlgorithm, ) -> Self { + // Compute the file hash before any normalization. + let src_hash = SourceFileHash::new(hash_kind, &src); let normalized_pos = normalize_src(&mut src, start_pos); - let src_hash = { - let mut hasher: StableHasher = StableHasher::new(); - hasher.write(src.as_bytes()); - hasher.finish::<u128>() - }; let name_hash = { let mut hasher: StableHasher = StableHasher::new(); name.hash(&mut hasher); @@ -1098,7 +1153,6 @@ impl SourceFile { name, name_was_remapped, unmapped_path: Some(unmapped_path), - crate_of_origin: 0, src: Some(Lrc::new(src)), src_hash, external_src: Lock::new(ExternalSource::Unneeded), @@ -1109,6 +1163,7 @@ impl SourceFile { non_narrow_chars, normalized_pos, name_hash, + cnum: LOCAL_CRATE, } } @@ -1126,21 +1181,24 @@ impl SourceFile { where F: FnOnce() -> Option<String>, { - if *self.external_src.borrow() == ExternalSource::AbsentOk { + if matches!( + *self.external_src.borrow(), + ExternalSource::Foreign { kind: ExternalSourceKind::AbsentOk, .. } + ) { let src = get_src(); let mut external_src = self.external_src.borrow_mut(); // Check that no-one else have provided the source while we were getting it - if *external_src == ExternalSource::AbsentOk { + if let ExternalSource::Foreign { + kind: src_kind @ ExternalSourceKind::AbsentOk, .. + } = &mut *external_src + { if let Some(src) = src { - let mut hasher: StableHasher = StableHasher::new(); - hasher.write(src.as_bytes()); - - if hasher.finish::<u128>() == self.src_hash { - *external_src = ExternalSource::Present(src); + if self.src_hash.matches(&src) { + *src_kind = ExternalSourceKind::Present(Lrc::new(src)); return true; } } else { - *external_src = ExternalSource::AbsentErr; + *src_kind = ExternalSourceKind::AbsentErr; } false @@ -1167,11 +1225,7 @@ impl SourceFile { } let begin = { - let line = if let Some(line) = self.lines.get(line_number) { - line - } else { - return None; - }; + let line = self.lines.get(line_number)?; let begin: BytePos = *line - self.start_pos; begin.to_usize() }; @@ -1555,7 +1609,7 @@ fn lookup_line(lines: &[BytePos], pos: BytePos) -> isize { /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro -/// instead of implementing everything in librustc. +/// instead of implementing everything in librustc_middle. pub trait HashStableContext { fn hash_spans(&self) -> bool; fn hash_def_id(&mut self, _: DefId, hasher: &mut StableHasher); |
