diff options
Diffstat (limited to 'src/librustc_span')
| -rw-r--r-- | src/librustc_span/Cargo.toml | 2 | ||||
| -rw-r--r-- | src/librustc_span/caching_source_map_view.rs | 6 | ||||
| -rw-r--r-- | src/librustc_span/def_id.rs | 48 | ||||
| -rw-r--r-- | src/librustc_span/edition.rs | 14 | ||||
| -rw-r--r-- | src/librustc_span/hygiene.rs | 59 | ||||
| -rw-r--r-- | src/librustc_span/lib.rs | 214 | ||||
| -rw-r--r-- | src/librustc_span/source_map.rs | 90 | ||||
| -rw-r--r-- | src/librustc_span/symbol.rs | 56 |
8 files changed, 303 insertions, 186 deletions
diff --git a/src/librustc_span/Cargo.toml b/src/librustc_span/Cargo.toml index c3fa2331d2b..1c2721260d6 100644 --- a/src/librustc_span/Cargo.toml +++ b/src/librustc_span/Cargo.toml @@ -19,3 +19,5 @@ scoped-tls = "1.0" unicode-width = "0.1.4" cfg-if = "0.1.2" log = "0.4" +sha-1 = "0.8" +md-5 = "0.8" diff --git a/src/librustc_span/caching_source_map_view.rs b/src/librustc_span/caching_source_map_view.rs index d6725160a5d..68b0bd1a574 100644 --- a/src/librustc_span/caching_source_map_view.rs +++ b/src/librustc_span/caching_source_map_view.rs @@ -99,10 +99,6 @@ impl<'sm> CachingSourceMapView<'sm> { cache_entry.line_end = line_bounds.1; cache_entry.time_stamp = self.time_stamp; - return Some(( - cache_entry.file.clone(), - cache_entry.line_number, - pos - cache_entry.line_start, - )); + Some((cache_entry.file.clone(), cache_entry.line_number, pos - cache_entry.line_start)) } } diff --git a/src/librustc_span/def_id.rs b/src/librustc_span/def_id.rs index 6cdfd0500ca..3551220c5c5 100644 --- a/src/librustc_span/def_id.rs +++ b/src/librustc_span/def_id.rs @@ -1,8 +1,11 @@ use crate::HashStableContext; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::AtomicRef; use rustc_index::vec::Idx; +use rustc_macros::HashStable_Generic; use rustc_serialize::{Decoder, Encoder}; +use std::borrow::Borrow; use std::fmt; use std::{u32, u64}; @@ -22,7 +25,7 @@ pub enum CrateNum { /// Item definitions in the currently-compiled crate would have the `CrateNum` /// `LOCAL_CRATE` in their `DefId`. -pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32_const(0)); +pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32(0)); impl Idx for CrateNum { #[inline] @@ -102,6 +105,17 @@ impl ::std::fmt::Debug for CrateNum { } } +#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, RustcEncodable, RustcDecodable)] +#[derive(HashStable_Generic)] +pub struct DefPathHash(pub Fingerprint); + +impl Borrow<Fingerprint> for DefPathHash { + #[inline] + fn borrow(&self) -> &Fingerprint { + &self.0 + } +} + rustc_index::newtype_index! { /// A DefIndex is an index into the hir-map for a crate, identifying a /// particular definition. It should really be considered an interned @@ -130,7 +144,7 @@ impl DefId { /// Makes a local `DefId` from the given `DefIndex`. #[inline] pub fn local(index: DefIndex) -> DefId { - DefId { krate: LOCAL_CRATE, index: index } + DefId { krate: LOCAL_CRATE, index } } #[inline] @@ -139,8 +153,13 @@ impl DefId { } #[inline] - pub fn to_local(self) -> LocalDefId { - LocalDefId::from_def_id(self) + pub fn as_local(self) -> Option<LocalDefId> { + if self.is_local() { Some(LocalDefId { local_def_index: self.index }) } else { None } + } + + #[inline] + pub fn expect_local(self) -> LocalDefId { + self.as_local().unwrap_or_else(|| panic!("DefId::expect_local: `{:?}` isn't local", self)) } pub fn is_top_level_module(self) -> bool { @@ -185,19 +204,26 @@ rustc_data_structures::define_id_collections!(DefIdMap, DefIdSet, DefId); /// few cases where we know that only DefIds from the local crate are expected /// and a DefId from a different crate would signify a bug somewhere. This /// is when LocalDefId comes in handy. -#[derive(Clone, Copy, PartialEq, Eq, Hash)] -pub struct LocalDefId(DefIndex); +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct LocalDefId { + pub local_def_index: DefIndex, +} -impl LocalDefId { +impl Idx for LocalDefId { #[inline] - pub fn from_def_id(def_id: DefId) -> LocalDefId { - assert!(def_id.is_local()); - LocalDefId(def_id.index) + fn new(idx: usize) -> Self { + LocalDefId { local_def_index: Idx::new(idx) } } + #[inline] + fn index(self) -> usize { + self.local_def_index.index() + } +} +impl LocalDefId { #[inline] pub fn to_def_id(self) -> DefId { - DefId { krate: LOCAL_CRATE, index: self.0 } + DefId { krate: LOCAL_CRATE, index: self.local_def_index } } } diff --git a/src/librustc_span/edition.rs b/src/librustc_span/edition.rs index 3017191563b..b1ac7f04321 100644 --- a/src/librustc_span/edition.rs +++ b/src/librustc_span/edition.rs @@ -5,18 +5,8 @@ use std::str::FromStr; use rustc_macros::HashStable_Generic; /// The edition of the compiler (RFC 2052) -#[derive( - Clone, - Copy, - Hash, - PartialEq, - PartialOrd, - Debug, - RustcEncodable, - RustcDecodable, - Eq, - HashStable_Generic -)] +#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, RustcEncodable, RustcDecodable, Eq)] +#[derive(HashStable_Generic)] pub enum Edition { // editions must be kept in order, oldest to newest /// The 2015 edition diff --git a/src/librustc_span/hygiene.rs b/src/librustc_span/hygiene.rs index a368a881674..0afa2333e06 100644 --- a/src/librustc_span/hygiene.rs +++ b/src/librustc_span/hygiene.rs @@ -59,18 +59,8 @@ pub struct ExpnId(u32); /// A property of a macro expansion that determines how identifiers /// produced by that expansion are resolved. -#[derive( - Copy, - Clone, - PartialEq, - Eq, - PartialOrd, - Hash, - Debug, - RustcEncodable, - RustcDecodable, - HashStable_Generic -)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(HashStable_Generic)] pub enum Transparency { /// Identifier produced by a transparent expansion is always resolved at call-site. /// Call-site spans in procedural macros, hygiene opt-out in `macro` should use this. @@ -201,11 +191,11 @@ impl HygieneData { true } - fn modern(&self, ctxt: SyntaxContext) -> SyntaxContext { + fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext { self.syntax_context_data[ctxt.0 as usize].opaque } - fn modern_and_legacy(&self, ctxt: SyntaxContext) -> SyntaxContext { + fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext { self.syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent } @@ -266,9 +256,9 @@ impl HygieneData { let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt(); let mut call_site_ctxt = if transparency == Transparency::SemiTransparent { - self.modern(call_site_ctxt) + self.normalize_to_macros_2_0(call_site_ctxt) } else { - self.modern_and_legacy(call_site_ctxt) + self.normalize_to_macro_rules(call_site_ctxt) }; if call_site_ctxt == SyntaxContext::root() { @@ -491,10 +481,10 @@ impl SyntaxContext { HygieneData::with(|data| data.adjust(self, expn_id)) } - /// Like `SyntaxContext::adjust`, but also modernizes `self`. - pub fn modernize_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> { + /// Like `SyntaxContext::adjust`, but also normalizes `self` to macros 2.0. + pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> { HygieneData::with(|data| { - *self = data.modern(*self); + *self = data.normalize_to_macros_2_0(*self); data.adjust(self, expn_id) }) } @@ -527,7 +517,7 @@ impl SyntaxContext { pub fn glob_adjust(&mut self, expn_id: ExpnId, glob_span: Span) -> Option<Option<ExpnId>> { HygieneData::with(|data| { let mut scope = None; - let mut glob_ctxt = data.modern(glob_span.ctxt()); + let mut glob_ctxt = data.normalize_to_macros_2_0(glob_span.ctxt()); while !data.is_descendant_of(expn_id, data.outer_expn(glob_ctxt)) { scope = Some(data.remove_mark(&mut glob_ctxt).0); if data.remove_mark(self).0 != scope.unwrap() { @@ -558,7 +548,7 @@ impl SyntaxContext { return None; } - let mut glob_ctxt = data.modern(glob_span.ctxt()); + let mut glob_ctxt = data.normalize_to_macros_2_0(glob_span.ctxt()); let mut marks = Vec::new(); while !data.is_descendant_of(expn_id, data.outer_expn(glob_ctxt)) { marks.push(data.remove_mark(&mut glob_ctxt)); @@ -574,20 +564,20 @@ impl SyntaxContext { pub fn hygienic_eq(self, other: SyntaxContext, expn_id: ExpnId) -> bool { HygieneData::with(|data| { - let mut self_modern = data.modern(self); - data.adjust(&mut self_modern, expn_id); - self_modern == data.modern(other) + let mut self_normalized = data.normalize_to_macros_2_0(self); + data.adjust(&mut self_normalized, expn_id); + self_normalized == data.normalize_to_macros_2_0(other) }) } #[inline] - pub fn modern(self) -> SyntaxContext { - HygieneData::with(|data| data.modern(self)) + pub fn normalize_to_macros_2_0(self) -> SyntaxContext { + HygieneData::with(|data| data.normalize_to_macros_2_0(self)) } #[inline] - pub fn modern_and_legacy(self) -> SyntaxContext { - HygieneData::with(|data| data.modern_and_legacy(self)) + pub fn normalize_to_macro_rules(self) -> SyntaxContext { + HygieneData::with(|data| data.normalize_to_macro_rules(self)) } #[inline] @@ -747,17 +737,8 @@ impl ExpnKind { } /// The kind of macro invocation or definition. -#[derive( - Clone, - Copy, - PartialEq, - Eq, - RustcEncodable, - RustcDecodable, - Hash, - Debug, - HashStable_Generic -)] +#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +#[derive(HashStable_Generic)] pub enum MacroKind { /// A bang macro `foo!()`. Bang, 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); diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index e0bbaf730a5..49e2144b3e3 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -141,27 +141,31 @@ pub struct SourceMap { // This is used to apply the file path remapping as specified via // `--remap-path-prefix` to all `SourceFile`s allocated within this `SourceMap`. path_mapping: FilePathMapping, + + /// The algorithm used for hashing the contents of each source file. + hash_kind: SourceFileHashAlgorithm, } impl SourceMap { pub fn new(path_mapping: FilePathMapping) -> SourceMap { - SourceMap { - used_address_space: AtomicU32::new(0), - files: Default::default(), - file_loader: Box::new(RealFileLoader), + Self::with_file_loader_and_hash_kind( + Box::new(RealFileLoader), path_mapping, - } + SourceFileHashAlgorithm::Md5, + ) } - pub fn with_file_loader( + pub fn with_file_loader_and_hash_kind( file_loader: Box<dyn FileLoader + Sync + Send>, path_mapping: FilePathMapping, + hash_kind: SourceFileHashAlgorithm, ) -> SourceMap { SourceMap { used_address_space: AtomicU32::new(0), files: Default::default(), file_loader, path_mapping, + hash_kind, } } @@ -275,6 +279,7 @@ impl SourceMap { unmapped_path, src, Pos::from_usize(start_pos), + self.hash_kind, )); let mut files = self.files.borrow_mut(); @@ -296,14 +301,16 @@ impl SourceMap { &self, filename: FileName, name_was_remapped: bool, - crate_of_origin: u32, - src_hash: u128, + src_hash: SourceFileHash, name_hash: u128, source_len: usize, + cnum: CrateNum, mut file_local_lines: Vec<BytePos>, mut file_local_multibyte_chars: Vec<MultiByteChar>, mut file_local_non_narrow_chars: Vec<NonNarrowChar>, mut file_local_normalized_pos: Vec<NormalizedPos>, + original_start_pos: BytePos, + original_end_pos: BytePos, ) -> Lrc<SourceFile> { let start_pos = self .allocate_address_space(source_len) @@ -332,10 +339,13 @@ impl SourceMap { name: filename, name_was_remapped, unmapped_path: None, - crate_of_origin, src: None, src_hash, - external_src: Lock::new(ExternalSource::AbsentOk), + external_src: Lock::new(ExternalSource::Foreign { + kind: ExternalSourceKind::AbsentOk, + original_start_pos, + original_end_pos, + }), start_pos, end_pos, lines: file_local_lines, @@ -343,6 +353,7 @@ impl SourceMap { non_narrow_chars: file_local_non_narrow_chars, normalized_pos: file_local_normalized_pos, name_hash, + cnum, }); let mut files = self.files.borrow_mut(); @@ -362,16 +373,16 @@ impl SourceMap { // If there is a doctest offset, applies it to the line. pub fn doctest_offset_line(&self, file: &FileName, orig: usize) -> usize { - return match file { + match file { FileName::DocTest(_, offset) => { - return if *offset >= 0 { - orig + *offset as usize - } else { + if *offset < 0 { orig - (-(*offset)) as usize - }; + } else { + orig + *offset as usize + } } _ => orig, - }; + } } /// Looks up source information about a `BytePos`. @@ -517,11 +528,22 @@ impl SourceMap { Ok((lo, hi)) } + pub fn is_line_before_span_empty(&self, sp: Span) -> bool { + match self.span_to_prev_source(sp) { + Ok(s) => s.split('\n').last().map(|l| l.trim_start().is_empty()).unwrap_or(false), + Err(_) => false, + } + } + pub fn span_to_lines(&self, sp: Span) -> FileLinesResult { debug!("span_to_lines(sp={:?})", sp); let (lo, hi) = self.is_valid_span(sp)?; assert!(hi.line >= lo.line); + if sp.is_dummy() { + return Ok(FileLines { file: lo.file, lines: Vec::new() }); + } + let mut lines = Vec::with_capacity(hi.line - lo.line + 1); // The span starts partway through the first line, @@ -532,6 +554,9 @@ impl SourceMap { // and to the end of the line. Be careful because the line // numbers in Loc are 1-based, so we subtract 1 to get 0-based // lines. + // + // FIXME: now that we handle DUMMY_SP up above, we should consider + // asserting that the line numbers here are all indeed 1-based. let hi_line = hi.line.saturating_sub(1); for line_index in lo.line.saturating_sub(1)..hi_line { let line_len = lo.file.get_line(line_index).map(|s| s.chars().count()).unwrap_or(0); @@ -556,10 +581,10 @@ impl SourceMap { let local_end = self.lookup_byte_offset(sp.hi()); if local_begin.sf.start_pos != local_end.sf.start_pos { - return Err(SpanSnippetError::DistinctSources(DistinctSources { + Err(SpanSnippetError::DistinctSources(DistinctSources { begin: (local_begin.sf.name.clone(), local_begin.sf.start_pos), end: (local_end.sf.name.clone(), local_end.sf.start_pos), - })); + })) } else { self.ensure_source_file_source_present(local_begin.sf.clone()); @@ -577,13 +602,11 @@ impl SourceMap { } if let Some(ref src) = local_begin.sf.src { - return extract_source(src, start_index, end_index); + extract_source(src, start_index, end_index) } else if let Some(src) = local_begin.sf.external_src.borrow().get_source() { - return extract_source(src, start_index, end_index); + extract_source(src, start_index, end_index) } else { - return Err(SpanSnippetError::SourceNotAvailable { - filename: local_begin.sf.name.clone(), - }); + Err(SpanSnippetError::SourceNotAvailable { filename: local_begin.sf.name.clone() }) } } } @@ -620,7 +643,7 @@ impl SourceMap { /// if no character could be found or if an error occurred while retrieving the code snippet. pub fn span_extend_to_prev_char(&self, sp: Span, c: char) -> Span { if let Ok(prev_source) = self.span_to_prev_source(sp) { - let prev_source = prev_source.rsplit(c).nth(0).unwrap_or("").trim_start(); + let prev_source = prev_source.rsplit(c).next().unwrap_or("").trim_start(); if !prev_source.is_empty() && !prev_source.contains('\n') { return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32)); } @@ -640,7 +663,7 @@ impl SourceMap { for ws in &[" ", "\t", "\n"] { let pat = pat.to_owned() + ws; if let Ok(prev_source) = self.span_to_prev_source(sp) { - let prev_source = prev_source.rsplit(&pat).nth(0).unwrap_or("").trim_start(); + let prev_source = prev_source.rsplit(&pat).next().unwrap_or("").trim_start(); if !prev_source.is_empty() && (!prev_source.contains('\n') || accept_newlines) { return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32)); } @@ -655,7 +678,7 @@ impl SourceMap { pub fn span_until_char(&self, sp: Span, c: char) -> Span { match self.span_to_snippet(sp) { Ok(snippet) => { - let snippet = snippet.split(c).nth(0).unwrap_or("").trim_end(); + let snippet = snippet.split(c).next().unwrap_or("").trim_end(); if !snippet.is_empty() && !snippet.contains('\n') { sp.with_hi(BytePos(sp.lo().0 + snippet.len() as u32)) } else { @@ -715,7 +738,14 @@ impl SourceMap { } } - pub fn def_span(&self, sp: Span) -> Span { + /// Given a `Span`, return a span ending in the closest `{`. This is useful when you have a + /// `Span` enclosing a whole item but we need to point at only the head (usually the first + /// line) of that item. + /// + /// *Only suitable for diagnostics.* + pub fn guess_head_span(&self, sp: Span) -> Span { + // FIXME: extend the AST items to have a head span, or replace callers with pointing at + // the item's ident when appropriate. self.span_until_char(sp, '{') } @@ -975,6 +1005,12 @@ impl SourceMap { _ => None, }) } + + pub fn is_imported(&self, sp: Span) -> bool { + let source_file_index = self.lookup_source_file_idx(sp.lo()); + let source_file = &self.files()[source_file_index]; + source_file.is_imported() + } } #[derive(Clone)] diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index d6232f32f4c..54b404e1161 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -120,6 +120,7 @@ symbols! { abi_unadjusted, abi_vectorcall, abi_x86_interrupt, + abort, aborts, address, add_with_overflow, @@ -181,6 +182,7 @@ symbols! { caller_location, cdylib, cfg, + cfg_accessible, cfg_attr, cfg_attr_multi, cfg_doctest, @@ -208,6 +210,7 @@ symbols! { console, const_compare_raw_pointers, const_constructor, + const_eval_limit, const_extern_fn, const_fn, const_fn_union, @@ -250,6 +253,7 @@ symbols! { debug_trait, declare_lint_pass, decl_macro, + debug, Debug, Decodable, Default, @@ -264,12 +268,12 @@ symbols! { derive, diagnostic, direct, + discriminant_value, doc, doc_alias, doc_cfg, doc_keyword, doc_masked, - doc_spotlight, doctest, document_private_items, dotdoteq_in_patterns, @@ -287,7 +291,6 @@ symbols! { dylib, dyn_trait, eh_personality, - eh_unwind_resume, enable, Encodable, env, @@ -421,6 +424,7 @@ symbols! { LintPass, lint_reasons, literal, + llvm_asm, local_inner_macros, log_syntax, loop_break_value, @@ -452,6 +456,7 @@ symbols! { min_align_of, min_const_fn, min_const_unsafe_fn, + min_specialization, mips_target_feature, mmx_target_feature, module, @@ -469,6 +474,7 @@ symbols! { needs_drop, needs_panic_runtime, negate_unsigned, + negative_impls, never, never_type, never_type_fallback, @@ -541,7 +547,7 @@ symbols! { plugin_registrar, plugins, Poll, - poll_with_tls_context, + poll_with_context, powerpc_target_feature, precise_pointer_size_matching, pref_align_of, @@ -653,6 +659,8 @@ symbols! { rustc_proc_macro_decls, rustc_promotable, rustc_regions, + rustc_unsafe_specialization_marker, + rustc_specialization_trait, rustc_stable, rustc_std_internal_symbol, rustc_symbol_name, @@ -663,7 +671,6 @@ symbols! { rustc_variance, rustfmt, rust_eh_personality, - rust_eh_unwind_resume, rust_oom, rvalue_static_promotion, sanitize, @@ -688,7 +695,6 @@ symbols! { Some, specialization, speed, - spotlight, sse4a_target_feature, stable, staged_api, @@ -717,6 +723,7 @@ symbols! { target_has_atomic_load_store, target_thread_local, task, + _task_context, tbm_target_feature, termination_trait, termination_trait_test, @@ -854,12 +861,12 @@ impl Ident { } /// "Normalize" ident for use in comparisons using "item hygiene". - /// Identifiers with same string value become same if they came from the same "modern" macro + /// Identifiers with same string value become same if they came from the same macro 2.0 macro /// (e.g., `macro` item, but not `macro_rules` item) and stay different if they came from - /// different "modern" macros. + /// different macro 2.0 macros. /// Technically, this operation strips all non-opaque marks from ident's syntactic context. - pub fn modern(self) -> Ident { - Ident::new(self.name, self.span.modern()) + pub fn normalize_to_macros_2_0(self) -> Ident { + Ident::new(self.name, self.span.normalize_to_macros_2_0()) } /// "Normalize" ident for use in comparisons using "local variable hygiene". @@ -867,8 +874,8 @@ impl Ident { /// macro (e.g., `macro` or `macro_rules!` items) and stay different if they came from different /// non-transparent macros. /// Technically, this operation strips all transparent marks from ident's syntactic context. - pub fn modern_and_legacy(self) -> Ident { - Ident::new(self.name, self.span.modern_and_legacy()) + pub fn normalize_to_macro_rules(self) -> Ident { + Ident::new(self.name, self.span.normalize_to_macro_rules()) } /// Convert the name to a `SymbolStr`. This is a slowish operation because @@ -980,6 +987,31 @@ impl fmt::Display for IdentPrinter { } } +/// An newtype around `Ident` that calls [Ident::normalize_to_macro_rules] on +/// construction. +// FIXME(matthewj, petrochenkov) Use this more often, add a similar +// `ModernIdent` struct and use that as well. +#[derive(Copy, Clone, Eq, PartialEq, Hash)] +pub struct MacroRulesNormalizedIdent(Ident); + +impl MacroRulesNormalizedIdent { + pub fn new(ident: Ident) -> Self { + Self(ident.normalize_to_macro_rules()) + } +} + +impl fmt::Debug for MacroRulesNormalizedIdent { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } +} + +impl fmt::Display for MacroRulesNormalizedIdent { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } +} + /// An interned string. /// /// Internally, a `Symbol` is implemented as an index, and all operations @@ -998,7 +1030,7 @@ rustc_index::newtype_index! { impl Symbol { const fn new(n: u32) -> Self { - Symbol(SymbolIndex::from_u32_const(n)) + Symbol(SymbolIndex::from_u32(n)) } /// Maps a string to its interned representation. |
