about summary refs log tree commit diff
path: root/src/librustc_span
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustc_span')
-rw-r--r--src/librustc_span/Cargo.toml2
-rw-r--r--src/librustc_span/caching_source_map_view.rs6
-rw-r--r--src/librustc_span/def_id.rs48
-rw-r--r--src/librustc_span/edition.rs14
-rw-r--r--src/librustc_span/hygiene.rs59
-rw-r--r--src/librustc_span/lib.rs214
-rw-r--r--src/librustc_span/source_map.rs90
-rw-r--r--src/librustc_span/symbol.rs56
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.