about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/doc/unstable-book/src/language-features/on-unimplemented.md3
-rw-r--r--src/libcore/intrinsics.rs3
-rw-r--r--src/libcore/macros.rs3
-rw-r--r--src/libcore/ops/try.rs4
-rw-r--r--src/libcore/slice/mod.rs23
-rw-r--r--src/librustc/dep_graph/graph.rs86
-rw-r--r--src/librustc/hir/lowering.rs45
-rw-r--r--src/librustc/hir/map/def_collector.rs77
-rw-r--r--src/librustc/hir/map/definitions.rs13
-rw-r--r--src/librustc/hir/map/mod.rs2
-rw-r--r--src/librustc/ich/impls_syntax.rs13
-rw-r--r--src/librustc/infer/error_reporting/need_type_info.rs6
-rw-r--r--src/librustc/lint/internal.rs4
-rw-r--r--src/librustc/lint/mod.rs39
-rw-r--r--src/librustc/mir/mod.rs2
-rw-r--r--src/librustc/traits/error_reporting.rs15
-rw-r--r--src/librustc/ty/query/on_disk_cache.rs44
-rw-r--r--src/librustc_allocator/expand.rs17
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs6
-rw-r--r--src/librustc_errors/emitter.rs64
-rw-r--r--src/librustc_mir/borrow_check/conflict_errors.rs4
-rw-r--r--src/librustc_mir/borrow_check/mod.rs2
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs56
-rw-r--r--src/librustc_resolve/lib.rs41
-rw-r--r--src/librustc_resolve/macros.rs348
-rw-r--r--src/librustc_resolve/resolve_imports.rs2
-rw-r--r--src/librustc_save_analysis/lib.rs11
-rw-r--r--src/librustc_typeck/check/_match.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs4
-rw-r--r--src/librustdoc/clean/mod.rs1
-rw-r--r--src/librustdoc/html/item_type.rs1
-rw-r--r--src/librustdoc/html/render.rs2
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs14
-rw-r--r--src/librustdoc/visit_ast.rs7
-rw-r--r--src/libstd/sys/unix/fd.rs2
-rw-r--r--src/libsyntax/ext/base.rs90
-rw-r--r--src/libsyntax/ext/derive.rs15
-rw-r--r--src/libsyntax/ext/expand.rs400
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs14
-rw-r--r--src/libsyntax/json.rs9
-rw-r--r--src/libsyntax/source_map.rs4
-rw-r--r--src/libsyntax/std_inject.rs23
-rw-r--r--src/libsyntax/test.rs27
-rw-r--r--src/libsyntax_ext/lib.rs24
-rw-r--r--src/libsyntax_ext/proc_macro_decls.rs12
-rw-r--r--src/libsyntax_ext/test.rs14
-rw-r--r--src/libsyntax_ext/test_case.rs14
-rw-r--r--src/libsyntax_pos/hygiene.rs234
-rw-r--r--src/libsyntax_pos/lib.rs34
-rw-r--r--src/libsyntax_pos/symbol.rs2
-rw-r--r--src/test/run-pass-fulldeps/auxiliary/plugin-args.rs3
-rw-r--r--src/test/run-pass/auxiliary/arc_wake.rs64
-rw-r--r--src/test/rustdoc/proc-macro.rs2
-rw-r--r--src/test/ui/async-await/async-fn-size-moved-locals.rs (renamed from src/test/run-pass/async-await/async-fn-size-moved-locals.rs)3
-rw-r--r--src/test/ui/async-await/async-fn-size.rs (renamed from src/test/run-pass/async-await/async-fn-size.rs)5
-rw-r--r--src/test/ui/async-await/futures-api.rs (renamed from src/test/run-pass/futures-api.rs)2
-rw-r--r--src/test/ui/async-await/issue-60709.rs (renamed from src/test/run-pass/async-await/issue-60709.rs)2
-rw-r--r--src/test/ui/derives/auxiliary/derive-marker-tricky.rs15
-rw-r--r--src/test/ui/derives/derive-marker-tricky.rs16
-rw-r--r--src/test/ui/feature-gates/feature-gate-asm.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-asm2.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-concat_idents.stderr4
-rw-r--r--src/test/ui/feature-gates/feature-gate-concat_idents2.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-concat_idents3.stderr4
-rw-r--r--src/test/ui/feature-gates/feature-gate-custom_test_frameworks.stderr4
-rw-r--r--src/test/ui/feature-gates/feature-gate-format_args_nl.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-global_asm.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-log_syntax.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-log_syntax2.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-rustc-attrs.rs4
-rw-r--r--src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr12
-rw-r--r--src/test/ui/feature-gates/feature-gate-trace_macros.stderr2
-rw-r--r--src/test/ui/hrtb/issue-30786.migrate.stderr11
-rw-r--r--src/test/ui/hrtb/issue-30786.nll.stderr14
-rw-r--r--src/test/ui/hrtb/issue-30786.rs115
-rw-r--r--src/test/ui/hygiene/auxiliary/stdlib-prelude.rs3
-rw-r--r--src/test/ui/hygiene/extern-prelude-from-opaque-fail.rs28
-rw-r--r--src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr37
-rw-r--r--src/test/ui/hygiene/stdlib-prelude-from-opaque-early.rs21
-rw-r--r--src/test/ui/hygiene/stdlib-prelude-from-opaque-late.rs16
-rw-r--r--src/test/ui/macros/derive-in-eager-expansion-hang.rs14
-rw-r--r--src/test/ui/macros/derive-in-eager-expansion-hang.stderr17
-rw-r--r--src/test/ui/macros/macro-deprecation.stderr4
-rw-r--r--src/test/ui/macros/macro-error.stderr2
-rw-r--r--src/test/ui/macros/macro-path-prelude-fail-4.rs2
-rw-r--r--src/test/ui/macros/macro-path-prelude-fail-4.stderr4
-rw-r--r--src/test/ui/macros/macro-stability.stderr10
-rw-r--r--src/test/ui/macros/trace_faulty_macros.stderr2
-rw-r--r--src/test/ui/proc-macro/macro-namespace-reserved-2.rs18
-rw-r--r--src/test/ui/proc-macro/macro-namespace-reserved-2.stderr100
-rw-r--r--src/test/ui/rust-unstable-column-gated.stderr2
-rw-r--r--src/test/ui/tool-attributes/tool-attributes-misplaced-2.rs4
-rw-r--r--src/test/ui/tool-attributes/tool-attributes-misplaced-2.stderr8
-rw-r--r--src/test/ui/trace_macros-gate.stderr8
94 files changed, 1338 insertions, 1142 deletions
diff --git a/src/doc/unstable-book/src/language-features/on-unimplemented.md b/src/doc/unstable-book/src/language-features/on-unimplemented.md
index a770ab65c26..8db241e4b4e 100644
--- a/src/doc/unstable-book/src/language-features/on-unimplemented.md
+++ b/src/doc/unstable-book/src/language-features/on-unimplemented.md
@@ -98,7 +98,8 @@ application of these fields based on a variety of attributes when using
    `crate_local`) or matching against a particular method. Currently used
    for `try`.
  - `from_desugaring`: usable both as boolean (whether the flag is present)
-   or matching against a particular desugaring.
+   or matching against a particular desugaring. The desugaring is identified
+   with its variant name in the `DesugaringKind` enum.
 
 For example, the `Iterator` trait can be annotated in the following way:
 
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 67430e5bbda..513e22a788c 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -705,7 +705,8 @@ extern "rust-intrinsic" {
                          they should be used through stabilized interfaces \
                          in the rest of the standard library",
                issue = "0")]
-    #[rustc_deprecated(reason = "no longer used by rustc, will be removed - use MaybeUnint instead",
+    #[rustc_deprecated(reason = "no longer used by rustc, will be removed - use MaybeUninit \
+                                 instead",
                        since = "1.38.0")]
     pub fn init<T>() -> T;
 
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 2e999a0682b..293a2dd9492 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -1244,12 +1244,14 @@ mod builtin {
 
     /// Attribute macro applied to a function to turn it into a unit test.
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow_internal_unstable(test, rustc_attrs)]
     #[rustc_builtin_macro]
     #[rustc_macro_transparency = "semitransparent"]
     pub macro test($item:item) { /* compiler built-in */ }
 
     /// Attribute macro applied to a function to turn it into a benchmark test.
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow_internal_unstable(test, rustc_attrs)]
     #[rustc_builtin_macro]
     #[rustc_macro_transparency = "semitransparent"]
     pub macro bench($item:item) { /* compiler built-in */ }
@@ -1257,6 +1259,7 @@ mod builtin {
     /// An implementation detail of the `#[test]` and `#[bench]` macros.
     #[unstable(feature = "custom_test_frameworks", issue = "50297",
                reason = "custom test frameworks are an unstable feature")]
+    #[allow_internal_unstable(test, rustc_attrs)]
     #[rustc_builtin_macro]
     #[rustc_macro_transparency = "semitransparent"]
     pub macro test_case($item:item) { /* compiler built-in */ }
diff --git a/src/libcore/ops/try.rs b/src/libcore/ops/try.rs
index 9fa2c81954e..76fec1020f1 100644
--- a/src/libcore/ops/try.rs
+++ b/src/libcore/ops/try.rs
@@ -8,12 +8,12 @@
 #[rustc_on_unimplemented(
    on(all(
        any(from_method="from_error", from_method="from_ok"),
-       from_desugaring="?"),
+       from_desugaring="QuestionMark"),
       message="the `?` operator can only be used in a \
                function that returns `Result` or `Option` \
                (or another type that implements `{Try}`)",
       label="cannot use the `?` operator in a function that returns `{Self}`"),
-   on(all(from_method="into_result", from_desugaring="?"),
+   on(all(from_method="into_result", from_desugaring="QuestionMark"),
       message="the `?` operator can only be applied to values \
                that implement `{Try}`",
       label="the `?` operator cannot be applied to type `{Self}`")
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index fdf3cc8e006..363ae088275 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -5342,13 +5342,24 @@ impl<A, B> SlicePartialEq<B> for [A]
             return false;
         }
 
-        for i in 0..self.len() {
-            if !self[i].eq(&other[i]) {
-                return false;
-            }
+        self.iter().zip(other.iter()).all(|(x, y)| x == y)
+    }
+}
+
+// Use an equal-pointer optimization when types are `Eq`
+impl<A> SlicePartialEq<A> for [A]
+    where A: PartialEq<A> + Eq
+{
+    default fn equal(&self, other: &[A]) -> bool {
+        if self.len() != other.len() {
+            return false;
+        }
+
+        if self.as_ptr() == other.as_ptr() {
+            return true;
         }
 
-        true
+        self.iter().zip(other.iter()).all(|(x, y)| x == y)
     }
 }
 
@@ -5457,7 +5468,7 @@ impl SliceOrd<u8> for [u8] {
 #[doc(hidden)]
 /// Trait implemented for types that can be compared for equality using
 /// their bytewise representation
-trait BytewiseEquality { }
+trait BytewiseEquality: Eq + Copy { }
 
 macro_rules! impl_marker_for {
     ($traitname:ident, $($ty:ty)*) => {
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index b8c6c1e3723..7eea336cbbf 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -7,6 +7,7 @@ use rustc_data_structures::sync::{Lrc, Lock, AtomicU32, Ordering};
 use std::env;
 use std::hash::Hash;
 use std::collections::hash_map::Entry;
+use std::mem;
 use crate::ty::{self, TyCtxt};
 use crate::util::common::{ProfileQueriesMsg, profq_msg};
 use parking_lot::{Mutex, Condvar};
@@ -61,11 +62,11 @@ struct DepGraphData {
 
     colors: DepNodeColorMap,
 
-    /// A set of loaded diagnostics that have been emitted.
-    emitted_diagnostics: Mutex<FxHashSet<DepNodeIndex>>,
+    /// A set of loaded diagnostics that is in the progress of being emitted.
+    emitting_diagnostics: Mutex<FxHashSet<DepNodeIndex>>,
 
     /// Used to wait for diagnostics to be emitted.
-    emitted_diagnostics_cond_var: Condvar,
+    emitting_diagnostics_cond_var: Condvar,
 
     /// When we load, there may be `.o` files, cached MIR, or other such
     /// things available to us. If we find that they are not dirty, we
@@ -99,8 +100,8 @@ impl DepGraph {
                 previous_work_products: prev_work_products,
                 dep_node_debug: Default::default(),
                 current: Lock::new(CurrentDepGraph::new(prev_graph_node_count)),
-                emitted_diagnostics: Default::default(),
-                emitted_diagnostics_cond_var: Condvar::new(),
+                emitting_diagnostics: Default::default(),
+                emitting_diagnostics_cond_var: Condvar::new(),
                 previous: prev_graph,
                 colors: DepNodeColorMap::new(prev_graph_node_count),
                 loaded_from_cache: Default::default(),
@@ -744,7 +745,7 @@ impl DepGraph {
 
         // There may be multiple threads trying to mark the same dep node green concurrently
 
-        let (dep_node_index, did_allocation) = {
+        let dep_node_index = {
             let mut current = data.current.borrow_mut();
 
             // Copy the fingerprint from the previous graph,
@@ -758,34 +759,36 @@ impl DepGraph {
 
         // ... emitting any stored diagnostic ...
 
+        // FIXME: Store the fact that a node has diagnostics in a bit in the dep graph somewhere
+        // Maybe store a list on disk and encode this fact in the DepNodeState
         let diagnostics = tcx.queries.on_disk_cache
-                                .load_diagnostics(tcx, prev_dep_node_index);
+                             .load_diagnostics(tcx, prev_dep_node_index);
+
+        #[cfg(not(parallel_compiler))]
+        debug_assert!(data.colors.get(prev_dep_node_index).is_none(),
+                      "DepGraph::try_mark_previous_green() - Duplicate DepNodeColor \
+                      insertion for {:?}", dep_node);
 
         if unlikely!(diagnostics.len() > 0) {
             self.emit_diagnostics(
                 tcx,
                 data,
                 dep_node_index,
-                did_allocation,
+                prev_dep_node_index,
                 diagnostics
             );
         }
 
         // ... and finally storing a "Green" entry in the color map.
         // Multiple threads can all write the same color here
-        #[cfg(not(parallel_compiler))]
-        debug_assert!(data.colors.get(prev_dep_node_index).is_none(),
-                      "DepGraph::try_mark_previous_green() - Duplicate DepNodeColor \
-                      insertion for {:?}", dep_node);
-
         data.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
 
         debug!("try_mark_previous_green({:?}) - END - successfully marked as green", dep_node);
         Some(dep_node_index)
     }
 
-    /// Atomically emits some loaded diagnotics, assuming that this only gets called with
-    /// `did_allocation` set to `true` on a single thread.
+    /// Atomically emits some loaded diagnostics.
+    /// This may be called concurrently on multiple threads for the same dep node.
     #[cold]
     #[inline(never)]
     fn emit_diagnostics<'tcx>(
@@ -793,36 +796,49 @@ impl DepGraph {
         tcx: TyCtxt<'tcx>,
         data: &DepGraphData,
         dep_node_index: DepNodeIndex,
-        did_allocation: bool,
+        prev_dep_node_index: SerializedDepNodeIndex,
         diagnostics: Vec<Diagnostic>,
     ) {
-        if did_allocation || !cfg!(parallel_compiler) {
-            // Only the thread which did the allocation emits the error messages
-            let handle = tcx.sess.diagnostic();
+        let mut emitting = data.emitting_diagnostics.lock();
+
+        if data.colors.get(prev_dep_node_index) == Some(DepNodeColor::Green(dep_node_index)) {
+            // The node is already green so diagnostics must have been emitted already
+            return;
+        }
+
+        if emitting.insert(dep_node_index) {
+            // We were the first to insert the node in the set so this thread
+            // must emit the diagnostics and signal other potentially waiting
+            // threads after.
+            mem::drop(emitting);
 
             // Promote the previous diagnostics to the current session.
             tcx.queries.on_disk_cache
-                .store_diagnostics(dep_node_index, diagnostics.clone().into());
+               .store_diagnostics(dep_node_index, diagnostics.clone().into());
+
+            let handle = tcx.sess.diagnostic();
 
             for diagnostic in diagnostics {
                 DiagnosticBuilder::new_diagnostic(handle, diagnostic).emit();
             }
 
-            #[cfg(parallel_compiler)]
-            {
-                // Mark the diagnostics and emitted and wake up waiters
-                data.emitted_diagnostics.lock().insert(dep_node_index);
-                data.emitted_diagnostics_cond_var.notify_all();
-            }
+            // Mark the node as green now that diagnostics are emitted
+            data.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
+
+            // Remove the node from the set
+            data.emitting_diagnostics.lock().remove(&dep_node_index);
+
+            // Wake up waiters
+            data.emitting_diagnostics_cond_var.notify_all();
         } else {
-            // The other threads will wait for the diagnostics to be emitted
+            // We must wait for the other thread to finish emitting the diagnostic
 
-            let mut emitted_diagnostics = data.emitted_diagnostics.lock();
             loop {
-                if emitted_diagnostics.contains(&dep_node_index) {
+                data.emitting_diagnostics_cond_var.wait(&mut emitting);
+                if data.colors
+                       .get(prev_dep_node_index) == Some(DepNodeColor::Green(dep_node_index)) {
                     break;
                 }
-                data.emitted_diagnostics_cond_var.wait(&mut emitted_diagnostics);
             }
         }
     }
@@ -1027,7 +1043,7 @@ impl CurrentDepGraph {
             hash: self.anon_id_seed.combine(hasher.finish()),
         };
 
-        self.intern_node(target_dep_node, task_deps.reads, Fingerprint::ZERO).0
+        self.intern_node(target_dep_node, task_deps.reads, Fingerprint::ZERO)
     }
 
     fn alloc_node(
@@ -1037,7 +1053,7 @@ impl CurrentDepGraph {
         fingerprint: Fingerprint
     ) -> DepNodeIndex {
         debug_assert!(!self.node_to_node_index.contains_key(&dep_node));
-        self.intern_node(dep_node, edges, fingerprint).0
+        self.intern_node(dep_node, edges, fingerprint)
     }
 
     fn intern_node(
@@ -1045,11 +1061,11 @@ impl CurrentDepGraph {
         dep_node: DepNode,
         edges: SmallVec<[DepNodeIndex; 8]>,
         fingerprint: Fingerprint
-    ) -> (DepNodeIndex, bool) {
+    ) -> DepNodeIndex {
         debug_assert_eq!(self.node_to_node_index.len(), self.data.len());
 
         match self.node_to_node_index.entry(dep_node) {
-            Entry::Occupied(entry) => (*entry.get(), false),
+            Entry::Occupied(entry) => *entry.get(),
             Entry::Vacant(entry) => {
                 let dep_node_index = DepNodeIndex::new(self.data.len());
                 self.data.push(DepNodeData {
@@ -1058,7 +1074,7 @@ impl CurrentDepGraph {
                     fingerprint
                 });
                 entry.insert(dep_node_index);
-                (dep_node_index, true)
+                dep_node_index
             }
         }
     }
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 2a9fd58f84b..7e7bb5f61a3 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -60,10 +60,9 @@ use syntax::attr;
 use syntax::ast;
 use syntax::ast::*;
 use syntax::errors;
-use syntax::ext::hygiene::{Mark, SyntaxContext};
+use syntax::ext::hygiene::Mark;
 use syntax::print::pprust;
-use syntax::source_map::{self, respan, ExpnInfo, CompilerDesugaringKind, Spanned};
-use syntax::source_map::CompilerDesugaringKind::CondTemporary;
+use syntax::source_map::{respan, ExpnInfo, ExpnKind, DesugaringKind, Spanned};
 use syntax::std_inject;
 use syntax::symbol::{kw, sym, Symbol};
 use syntax::tokenstream::{TokenStream, TokenTree};
@@ -872,17 +871,15 @@ impl<'a> LoweringContext<'a> {
     /// allowed inside this span.
     fn mark_span_with_reason(
         &self,
-        reason: CompilerDesugaringKind,
+        reason: DesugaringKind,
         span: Span,
         allow_internal_unstable: Option<Lrc<[Symbol]>>,
     ) -> Span {
-        let mark = Mark::fresh(Mark::root());
-        mark.set_expn_info(ExpnInfo {
-            def_site: Some(span),
+        span.fresh_expansion(Mark::root(), ExpnInfo {
+            def_site: span,
             allow_internal_unstable,
-            ..ExpnInfo::default(source_map::CompilerDesugaring(reason), span, self.sess.edition())
-        });
-        span.with_ctxt(SyntaxContext::empty().apply_mark(mark))
+            ..ExpnInfo::default(ExpnKind::Desugaring(reason), span, self.sess.edition())
+        })
     }
 
     fn with_anonymous_lifetime_mode<R>(
@@ -1188,7 +1185,7 @@ impl<'a> LoweringContext<'a> {
         };
 
         let unstable_span = self.mark_span_with_reason(
-            CompilerDesugaringKind::Async,
+            DesugaringKind::Async,
             span,
             self.allow_gen_future.clone(),
         );
@@ -1733,7 +1730,7 @@ impl<'a> LoweringContext<'a> {
         // Not tracking it makes lints in rustc and clippy very fragile, as
         // frequently opened issues show.
         let exist_ty_span = self.mark_span_with_reason(
-            CompilerDesugaringKind::ExistentialType,
+            DesugaringKind::ExistentialType,
             span,
             None,
         );
@@ -2603,7 +2600,7 @@ impl<'a> LoweringContext<'a> {
         let span = output.span();
 
         let exist_ty_span = self.mark_span_with_reason(
-            CompilerDesugaringKind::Async,
+            DesugaringKind::Async,
             span,
             None,
         );
@@ -3275,7 +3272,7 @@ impl<'a> LoweringContext<'a> {
                 };
 
                 let desugared_span =
-                    this.mark_span_with_reason(CompilerDesugaringKind::Async, span, None);
+                    this.mark_span_with_reason(DesugaringKind::Async, span, None);
 
                 // Construct an argument representing `__argN: <ty>` to replace the argument of the
                 // async function.
@@ -4410,7 +4407,9 @@ impl<'a> LoweringContext<'a> {
                     _ => {
                         // Lower condition:
                         let cond = self.lower_expr(cond);
-                        let span_block = self.mark_span_with_reason(CondTemporary, cond.span, None);
+                        let span_block = self.mark_span_with_reason(
+                            DesugaringKind::CondTemporary, cond.span, None
+                        );
                         // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
                         // to preserve drop semantics since `if cond { ... }` does not
                         // let temporaries live outside of `cond`.
@@ -4469,7 +4468,9 @@ impl<'a> LoweringContext<'a> {
 
                         // Lower condition:
                         let cond = this.with_loop_condition_scope(|this| this.lower_expr(cond));
-                        let span_block = this.mark_span_with_reason(CondTemporary, cond.span, None);
+                        let span_block = this.mark_span_with_reason(
+                            DesugaringKind::CondTemporary, cond.span, None
+                        );
                         // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
                         // to preserve drop semantics since `while cond { ... }` does not
                         // let temporaries live outside of `cond`.
@@ -4508,7 +4509,7 @@ impl<'a> LoweringContext<'a> {
             ExprKind::TryBlock(ref body) => {
                 self.with_catch_scope(body.id, |this| {
                     let unstable_span = this.mark_span_with_reason(
-                        CompilerDesugaringKind::TryBlock,
+                        DesugaringKind::TryBlock,
                         body.span,
                         this.allow_try_trait.clone(),
                     );
@@ -4836,7 +4837,7 @@ impl<'a> LoweringContext<'a> {
                 let mut head = self.lower_expr(head);
                 let head_sp = head.span;
                 let desugared_span = self.mark_span_with_reason(
-                    CompilerDesugaringKind::ForLoop,
+                    DesugaringKind::ForLoop,
                     head_sp,
                     None,
                 );
@@ -4990,13 +4991,13 @@ impl<'a> LoweringContext<'a> {
                 // }
 
                 let unstable_span = self.mark_span_with_reason(
-                    CompilerDesugaringKind::QuestionMark,
+                    DesugaringKind::QuestionMark,
                     e.span,
                     self.allow_try_trait.clone(),
                 );
                 let try_span = self.sess.source_map().end_point(e.span);
                 let try_span = self.mark_span_with_reason(
-                    CompilerDesugaringKind::QuestionMark,
+                    DesugaringKind::QuestionMark,
                     try_span,
                     self.allow_try_trait.clone(),
                 );
@@ -5811,12 +5812,12 @@ impl<'a> LoweringContext<'a> {
             }
         }
         let span = self.mark_span_with_reason(
-            CompilerDesugaringKind::Await,
+            DesugaringKind::Await,
             await_span,
             None,
         );
         let gen_future_span = self.mark_span_with_reason(
-            CompilerDesugaringKind::Await,
+            DesugaringKind::Await,
             await_span,
             self.allow_gen_future.clone(),
         );
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index 41073773e9f..6b93bd96a27 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -1,6 +1,5 @@
 use crate::hir::map::definitions::*;
-use crate::hir::def_id::{CRATE_DEF_INDEX, DefIndex};
-use crate::session::CrateDisambiguator;
+use crate::hir::def_id::DefIndex;
 
 use syntax::ast::*;
 use syntax::ext::hygiene::Mark;
@@ -12,33 +11,14 @@ use syntax_pos::Span;
 /// Creates `DefId`s for nodes in the AST.
 pub struct DefCollector<'a> {
     definitions: &'a mut Definitions,
-    parent_def: Option<DefIndex>,
+    parent_def: DefIndex,
     expansion: Mark,
-    pub visit_macro_invoc: Option<&'a mut dyn FnMut(MacroInvocationData)>,
-}
-
-pub struct MacroInvocationData {
-    pub mark: Mark,
-    pub def_index: DefIndex,
 }
 
 impl<'a> DefCollector<'a> {
     pub fn new(definitions: &'a mut Definitions, expansion: Mark) -> Self {
-        DefCollector {
-            definitions,
-            expansion,
-            parent_def: None,
-            visit_macro_invoc: None,
-        }
-    }
-
-    pub fn collect_root(&mut self,
-                        crate_name: &str,
-                        crate_disambiguator: CrateDisambiguator) {
-        let root = self.definitions.create_root_def(crate_name,
-                                                    crate_disambiguator);
-        assert_eq!(root, CRATE_DEF_INDEX);
-        self.parent_def = Some(root);
+        let parent_def = definitions.invocation_parent(expansion);
+        DefCollector { definitions, parent_def, expansion }
     }
 
     fn create_def(&mut self,
@@ -46,17 +26,15 @@ impl<'a> DefCollector<'a> {
                   data: DefPathData,
                   span: Span)
                   -> DefIndex {
-        let parent_def = self.parent_def.unwrap();
+        let parent_def = self.parent_def;
         debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
-        self.definitions
-            .create_def_with_parent(parent_def, node_id, data, self.expansion, span)
+        self.definitions.create_def_with_parent(parent_def, node_id, data, self.expansion, span)
     }
 
     pub fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
-        let parent = self.parent_def;
-        self.parent_def = Some(parent_def);
+        let orig_parent_def = std::mem::replace(&mut self.parent_def, parent_def);
         f(self);
-        self.parent_def = parent;
+        self.parent_def = orig_parent_def;
     }
 
     fn visit_async_fn(
@@ -97,12 +75,7 @@ impl<'a> DefCollector<'a> {
     }
 
     fn visit_macro_invoc(&mut self, id: NodeId) {
-        if let Some(ref mut visit) = self.visit_macro_invoc {
-            visit(MacroInvocationData {
-                mark: id.placeholder_to_mark(),
-                def_index: self.parent_def.unwrap(),
-            })
-        }
+        self.definitions.set_invocation_parent(id.placeholder_to_mark(), self.parent_def);
     }
 }
 
@@ -275,36 +248,24 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
     }
 
     fn visit_expr(&mut self, expr: &'a Expr) {
-        let parent_def = self.parent_def;
-
-        match expr.node {
+        let parent_def = match expr.node {
             ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id),
             ExprKind::Closure(_, asyncness, ..) => {
-                let closure_def = self.create_def(expr.id,
-                                          DefPathData::ClosureExpr,
-                                          expr.span);
-                self.parent_def = Some(closure_def);
-
                 // Async closures desugar to closures inside of closures, so
                 // we must create two defs.
-                if let IsAsync::Async { closure_id, .. } = asyncness {
-                    let async_def = self.create_def(closure_id,
-                                                    DefPathData::ClosureExpr,
-                                                    expr.span);
-                    self.parent_def = Some(async_def);
+                let closure_def = self.create_def(expr.id, DefPathData::ClosureExpr, expr.span);
+                match asyncness {
+                    IsAsync::Async { closure_id, .. } =>
+                        self.create_def(closure_id, DefPathData::ClosureExpr, expr.span),
+                    IsAsync::NotAsync => closure_def,
                 }
             }
-            ExprKind::Async(_, async_id, _) => {
-                let async_def = self.create_def(async_id,
-                                                DefPathData::ClosureExpr,
-                                                expr.span);
-                self.parent_def = Some(async_def);
-            }
-            _ => {}
+            ExprKind::Async(_, async_id, _) =>
+                self.create_def(async_id, DefPathData::ClosureExpr, expr.span),
+            _ => self.parent_def,
         };
 
-        visit::walk_expr(self, expr);
-        self.parent_def = parent_def;
+        self.with_parent(parent_def, |this| visit::walk_expr(this, expr));
     }
 
     fn visit_ty(&mut self, ty: &'a Ty) {
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index 9e7898e10b0..9188a78e489 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -100,6 +100,9 @@ pub struct Definitions {
     expansions_that_defined: FxHashMap<DefIndex, Mark>,
     next_disambiguator: FxHashMap<(DefIndex, DefPathData), u32>,
     def_index_to_span: FxHashMap<DefIndex, Span>,
+    /// When collecting definitions from an AST fragment produced by a macro invocation `Mark`
+    /// we know what parent node that fragment should be attached to thanks to this table.
+    invocation_parents: FxHashMap<Mark, DefIndex>,
 }
 
 /// A unique identifier that we can use to lookup a definition
@@ -434,6 +437,7 @@ impl Definitions {
         assert!(self.def_index_to_node.is_empty());
         self.def_index_to_node.push(ast::CRATE_NODE_ID);
         self.node_to_def_index.insert(ast::CRATE_NODE_ID, root_index);
+        self.set_invocation_parent(Mark::root(), root_index);
 
         // Allocate some other DefIndices that always must exist.
         GlobalMetaDataKind::allocate_def_indices(self);
@@ -526,6 +530,15 @@ impl Definitions {
     pub fn add_parent_module_of_macro_def(&mut self, mark: Mark, module: DefId) {
         self.parent_modules_of_macro_defs.insert(mark, module);
     }
+
+    pub fn invocation_parent(&self, invoc_id: Mark) -> DefIndex {
+        self.invocation_parents[&invoc_id]
+    }
+
+    pub fn set_invocation_parent(&mut self, invoc_id: Mark, parent: DefIndex) {
+        let old_parent = self.invocation_parents.insert(invoc_id, parent);
+        assert!(old_parent.is_none(), "parent def-index is reset for an invocation");
+    }
 }
 
 impl DefPathData {
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 9fb85410fc7..43b1dbb6216 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -1,5 +1,5 @@
 use self::collector::NodeCollector;
-pub use self::def_collector::{DefCollector, MacroInvocationData};
+pub use self::def_collector::DefCollector;
 pub use self::definitions::{
     Definitions, DefKey, DefPath, DefPathData, DisambiguatedDefPathData, DefPathHash
 };
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 1db18d30282..e0e7988a744 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -89,7 +89,6 @@ impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind {
     Bang,
     Attr,
     Derive,
-    ProcMacroStub,
 });
 
 
@@ -399,7 +398,7 @@ impl_stable_hash_for!(enum ::syntax_pos::hygiene::Transparency {
 
 impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
     call_site,
-    format,
+    kind,
     def_site,
     default_transparency,
     allow_internal_unstable,
@@ -408,13 +407,13 @@ impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
     edition
 });
 
-impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat {
-    MacroAttribute(sym),
-    MacroBang(sym),
-    CompilerDesugaring(kind)
+impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnKind {
+    Root,
+    Macro(kind, descr),
+    Desugaring(kind)
 });
 
-impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
+impl_stable_hash_for!(enum ::syntax_pos::hygiene::DesugaringKind {
     CondTemporary,
     Async,
     Await,
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs
index 4426b5c0e85..770d5155777 100644
--- a/src/librustc/infer/error_reporting/need_type_info.rs
+++ b/src/librustc/infer/error_reporting/need_type_info.rs
@@ -5,7 +5,7 @@ use crate::infer::InferCtxt;
 use crate::infer::type_variable::TypeVariableOriginKind;
 use crate::ty::{self, Ty, Infer, TyVar};
 use crate::ty::print::Print;
-use syntax::source_map::CompilerDesugaringKind;
+use syntax::source_map::DesugaringKind;
 use syntax_pos::Span;
 use errors::DiagnosticBuilder;
 
@@ -194,12 +194,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             ));
         } else if let Some(pattern) = local_visitor.found_local_pattern {
             if let Some(simple_ident) = pattern.simple_ident() {
-                match pattern.span.compiler_desugaring_kind() {
+                match pattern.span.desugaring_kind() {
                     None => labels.push((
                         pattern.span,
                         format!("consider giving `{}` {}", simple_ident, suffix),
                     )),
-                    Some(CompilerDesugaringKind::ForLoop) => labels.push((
+                    Some(DesugaringKind::ForLoop) => labels.push((
                         pattern.span,
                         "the element type for this iterator is not specified".to_owned(),
                     )),
diff --git a/src/librustc/lint/internal.rs b/src/librustc/lint/internal.rs
index 34899736949..0b514f5927d 100644
--- a/src/librustc/lint/internal.rs
+++ b/src/librustc/lint/internal.rs
@@ -247,10 +247,10 @@ impl EarlyLintPass for LintPassImpl {
 }
 
 fn is_lint_pass_expansion(expn_info: &ExpnInfo) -> bool {
-    if expn_info.format.name() == sym::impl_lint_pass {
+    if expn_info.kind.descr() == sym::impl_lint_pass {
         true
     } else if let Some(info) = expn_info.call_site.ctxt().outer_expn_info() {
-        info.format.name() == sym::declare_lint_pass
+        info.kind.descr() == sym::declare_lint_pass
     } else {
         false
     }
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 59b08b832d2..e76c2493200 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -35,9 +35,10 @@ use crate::util::nodemap::NodeMap;
 use errors::{DiagnosticBuilder, DiagnosticId};
 use std::{hash, ptr};
 use syntax::ast;
-use syntax::source_map::{MultiSpan, ExpnFormat, CompilerDesugaringKind};
+use syntax::source_map::{MultiSpan, ExpnKind, DesugaringKind};
 use syntax::early_buffered_lints::BufferedEarlyLintId;
 use syntax::edition::Edition;
+use syntax::ext::base::MacroKind;
 use syntax::symbol::{Symbol, sym};
 use syntax_pos::Span;
 
@@ -883,36 +884,30 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool {
         None => return false,
     };
 
-    match info.format {
-        ExpnFormat::MacroAttribute(..) => true, // definitely a plugin
-        ExpnFormat::CompilerDesugaring(CompilerDesugaringKind::ForLoop) => false,
-        ExpnFormat::CompilerDesugaring(_) => true, // well, it's "external"
-        ExpnFormat::MacroBang(..) => {
-            let def_site = match info.def_site {
-                Some(span) => span,
-                // no span for the def_site means it's an external macro
-                None => return true,
-            };
-
-            match sess.source_map().span_to_snippet(def_site) {
+    match info.kind {
+        ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
+        ExpnKind::Desugaring(_) => true, // well, it's "external"
+        ExpnKind::Macro(MacroKind::Bang, _) => {
+            if info.def_site.is_dummy() {
+                // dummy span for the def_site means it's an external macro
+                return true;
+            }
+            match sess.source_map().span_to_snippet(info.def_site) {
                 Ok(code) => !code.starts_with("macro_rules"),
                 // no snippet = external macro or compiler-builtin expansion
                 Err(_) => true,
             }
         }
+        ExpnKind::Macro(..) => true, // definitely a plugin
     }
 }
 
 /// Returns whether `span` originates in a derive macro's expansion
 pub fn in_derive_expansion(span: Span) -> bool {
-    let info = match span.ctxt().outer_expn_info() {
-        Some(info) => info,
-        // no ExpnInfo means this span doesn't come from a macro
-        None => return false,
-    };
-
-    match info.format {
-        ExpnFormat::MacroAttribute(symbol) => symbol.as_str().starts_with("derive("),
-        _ => false,
+    if let Some(info) = span.ctxt().outer_expn_info() {
+        if let ExpnKind::Macro(MacroKind::Derive, _) = info.kind {
+            return true;
+        }
     }
+    false
 }
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 59a032d53cf..ff868bf2a2a 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -928,7 +928,7 @@ impl<'tcx> LocalDecl<'tcx> {
     /// `__next` from a `for` loop.
     #[inline]
     pub fn from_compiler_desugaring(&self) -> bool {
-        self.source_info.span.compiler_desugaring_kind().is_some()
+        self.source_info.span.desugaring_kind().is_some()
     }
 
     /// Creates a new `LocalDecl` for a temporary.
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index d6cc68bcdab..352d318ba79 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -36,7 +36,7 @@ use errors::{Applicability, DiagnosticBuilder};
 use std::fmt;
 use syntax::ast;
 use syntax::symbol::sym;
-use syntax_pos::{DUMMY_SP, Span, ExpnInfo, ExpnFormat};
+use syntax_pos::{DUMMY_SP, Span, ExpnInfo, ExpnKind};
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn report_fulfillment_errors(&self,
@@ -61,12 +61,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             // We want to ignore desugarings here: spans are equivalent even
             // if one is the result of a desugaring and the other is not.
             let mut span = error.obligation.cause.span;
-            if let Some(ExpnInfo {
-                format: ExpnFormat::CompilerDesugaring(_),
-                def_site: Some(def_span),
-                ..
-            }) = span.ctxt().outer_expn_info() {
-                span = def_span;
+            if let Some(ExpnInfo { kind: ExpnKind::Desugaring(_), def_site, .. })
+                    = span.ctxt().outer_expn_info() {
+                span = def_site;
             }
 
             error_map.entry(span).or_default().push(
@@ -373,9 +370,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             flags.push((sym::parent_trait, Some(t)));
         }
 
-        if let Some(k) = obligation.cause.span.compiler_desugaring_kind() {
+        if let Some(k) = obligation.cause.span.desugaring_kind() {
             flags.push((sym::from_desugaring, None));
-            flags.push((sym::from_desugaring, Some(k.name().to_string())));
+            flags.push((sym::from_desugaring, Some(format!("{:?}", k))));
         }
         let generics = self.tcx.generics_of(def_id);
         let self_ty = trait_ref.self_ty();
diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs
index 56c9474170c..a508d9846bc 100644
--- a/src/librustc/ty/query/on_disk_cache.rs
+++ b/src/librustc/ty/query/on_disk_cache.rs
@@ -588,41 +588,41 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx> {
 
         let expn_info_tag = u8::decode(self)?;
 
-        let ctxt = match expn_info_tag {
+        // FIXME(mw): This method does not restore `MarkData::parent` or
+        // `SyntaxContextData::prev_ctxt` or `SyntaxContextData::opaque`. These things
+        // don't seem to be used after HIR lowering, so everything should be fine
+        // as long as incremental compilation does not kick in before that.
+        let location = || Span::new(lo, hi, SyntaxContext::empty());
+        let recover_from_expn_info = |this: &Self, expn_info, pos| {
+            let span = location().fresh_expansion(Mark::root(), expn_info);
+            this.synthetic_expansion_infos.borrow_mut().insert(pos, span.ctxt());
+            span
+        };
+        Ok(match expn_info_tag {
             TAG_NO_EXPANSION_INFO => {
-                SyntaxContext::empty()
+                location()
             }
             TAG_EXPANSION_INFO_INLINE => {
-                let pos = AbsoluteBytePos::new(self.opaque.position());
-                let expn_info: ExpnInfo = Decodable::decode(self)?;
-                let ctxt = SyntaxContext::allocate_directly(expn_info);
-                self.synthetic_expansion_infos.borrow_mut().insert(pos, ctxt);
-                ctxt
+                let expn_info = Decodable::decode(self)?;
+                recover_from_expn_info(
+                    self, expn_info, AbsoluteBytePos::new(self.opaque.position())
+                )
             }
             TAG_EXPANSION_INFO_SHORTHAND => {
                 let pos = AbsoluteBytePos::decode(self)?;
-                let cached_ctxt = self.synthetic_expansion_infos
-                                      .borrow()
-                                      .get(&pos)
-                                      .cloned();
-
+                let cached_ctxt = self.synthetic_expansion_infos.borrow().get(&pos).cloned();
                 if let Some(ctxt) = cached_ctxt {
-                    ctxt
+                    Span::new(lo, hi, ctxt)
                 } else {
-                    let expn_info = self.with_position(pos.to_usize(), |this| {
-                         ExpnInfo::decode(this)
-                    })?;
-                    let ctxt = SyntaxContext::allocate_directly(expn_info);
-                    self.synthetic_expansion_infos.borrow_mut().insert(pos, ctxt);
-                    ctxt
+                    let expn_info =
+                        self.with_position(pos.to_usize(), |this| ExpnInfo::decode(this))?;
+                    recover_from_expn_info(self, expn_info, pos)
                 }
             }
             _ => {
                 unreachable!()
             }
-        };
-
-        Ok(Span::new(lo, hi, ctxt))
+        })
     }
 }
 
diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs
index d402b0ddf6e..9803ee99f1a 100644
--- a/src/librustc_allocator/expand.rs
+++ b/src/librustc_allocator/expand.rs
@@ -8,13 +8,13 @@ use syntax::{
     },
     attr,
     source_map::{
-        respan, ExpnInfo, MacroAttribute,
+        respan, ExpnInfo, ExpnKind,
     },
     ext::{
-        base::{ExtCtxt, Resolver},
+        base::{ExtCtxt, MacroKind, Resolver},
         build::AstBuilder,
         expand::ExpansionConfig,
-        hygiene::{Mark, SyntaxContext},
+        hygiene::Mark,
     },
     mut_visit::{self, MutVisitor},
     parse::ParseSess,
@@ -84,15 +84,12 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> {
         }
         self.found = true;
 
-        // Create a fresh Mark for the new macro expansion we are about to do
-        let mark = Mark::fresh(Mark::root());
-        mark.set_expn_info(ExpnInfo::with_unstable(
-            MacroAttribute(sym::global_allocator), item.span, self.sess.edition, &[sym::rustc_attrs]
+        // Create a new expansion for the generated allocator code.
+        let span = item.span.fresh_expansion(Mark::root(), ExpnInfo::allow_unstable(
+            ExpnKind::Macro(MacroKind::Attr, sym::global_allocator), item.span, self.sess.edition,
+            [sym::rustc_attrs][..].into(),
         ));
 
-        // Tie the span to the macro expansion info we just created
-        let span = item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark));
-
         // Create an expansion config
         let ecfg = ExpansionConfig::default(self.crate_name.take().unwrap());
 
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index 34db080ef66..9a581cb03ec 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -33,7 +33,7 @@ use std::cell::{Cell, RefCell};
 use std::fmt;
 use std::rc::Rc;
 use std::hash::{Hash, Hasher};
-use syntax::source_map::CompilerDesugaringKind;
+use syntax::source_map::DesugaringKind;
 use syntax_pos::{MultiSpan, Span};
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use log::debug;
@@ -734,8 +734,8 @@ impl BorrowckCtxt<'_, 'tcx> {
                 },
                 moved_lp.ty));
         }
-        if let (Some(CompilerDesugaringKind::ForLoop), Ok(snippet)) = (
-            move_span.compiler_desugaring_kind(),
+        if let (Some(DesugaringKind::ForLoop), Ok(snippet)) = (
+            move_span.desugaring_kind(),
             self.tcx.sess.source_map().span_to_snippet(move_span),
          ) {
             if !snippet.starts_with("&") {
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 83a0fb486fd..361b5cd9357 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -723,39 +723,37 @@ impl EmitterWriter {
                 for (i, trace) in sp.macro_backtrace().iter().rev().enumerate() {
                     // Only show macro locations that are local
                     // and display them like a span_note
-                    if let Some(def_site) = trace.def_site_span {
-                        if def_site.is_dummy() {
-                            continue;
-                        }
-                        if always_backtrace {
-                            new_labels.push((def_site,
-                                             format!("in this expansion of `{}`{}",
-                                                     trace.macro_decl_name,
-                                                     if backtrace_len > 2 {
-                                                         // if backtrace_len == 1 it'll be pointed
-                                                         // at by "in this macro invocation"
-                                                         format!(" (#{})", i + 1)
-                                                     } else {
-                                                         String::new()
-                                                     })));
-                        }
-                        // Check to make sure we're not in any <*macros>
-                        if !sm.span_to_filename(def_site).is_macros() &&
-                           !trace.macro_decl_name.starts_with("desugaring of ") &&
-                           !trace.macro_decl_name.starts_with("#[") ||
-                           always_backtrace {
-                            new_labels.push((trace.call_site,
-                                             format!("in this macro invocation{}",
-                                                     if backtrace_len > 2 && always_backtrace {
-                                                         // only specify order when the macro
-                                                         // backtrace is multiple levels deep
-                                                         format!(" (#{})", i + 1)
-                                                     } else {
-                                                         String::new()
-                                                     })));
-                            if !always_backtrace {
-                                break;
-                            }
+                    if trace.def_site_span.is_dummy() {
+                        continue;
+                    }
+                    if always_backtrace {
+                        new_labels.push((trace.def_site_span,
+                                            format!("in this expansion of `{}`{}",
+                                                    trace.macro_decl_name,
+                                                    if backtrace_len > 2 {
+                                                        // if backtrace_len == 1 it'll be pointed
+                                                        // at by "in this macro invocation"
+                                                        format!(" (#{})", i + 1)
+                                                    } else {
+                                                        String::new()
+                                                    })));
+                    }
+                    // Check to make sure we're not in any <*macros>
+                    if !sm.span_to_filename(trace.def_site_span).is_macros() &&
+                        !trace.macro_decl_name.starts_with("desugaring of ") &&
+                        !trace.macro_decl_name.starts_with("#[") ||
+                        always_backtrace {
+                        new_labels.push((trace.call_site,
+                                            format!("in this macro invocation{}",
+                                                    if backtrace_len > 2 && always_backtrace {
+                                                        // only specify order when the macro
+                                                        // backtrace is multiple levels deep
+                                                        format!(" (#{})", i + 1)
+                                                    } else {
+                                                        String::new()
+                                                    })));
+                        if !always_backtrace {
+                            break;
                         }
                     }
                 }
diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs
index f23cffeda68..7b5fce4abbc 100644
--- a/src/librustc_mir/borrow_check/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/conflict_errors.rs
@@ -10,7 +10,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use syntax_pos::Span;
-use syntax::source_map::CompilerDesugaringKind;
+use syntax::source_map::DesugaringKind;
 
 use super::nll::explain_borrow::BorrowExplanation;
 use super::nll::region_infer::{RegionName, RegionNameSource};
@@ -174,7 +174,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         format!("variable moved due to use{}", move_spans.describe()),
                     );
                 }
-                if Some(CompilerDesugaringKind::ForLoop) == move_span.compiler_desugaring_kind() {
+                if Some(DesugaringKind::ForLoop) == move_span.desugaring_kind() {
                     if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
                         err.span_suggestion(
                             move_span,
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 25ac93cc242..31a9766af30 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -335,7 +335,7 @@ fn do_mir_borrowck<'a, 'tcx>(
             }
 
             let span = local_decl.source_info.span;
-            if span.compiler_desugaring_kind().is_some() {
+            if span.desugaring_kind().is_some() {
                 // If the `mut` arises as part of a desugaring, we should ignore it.
                 continue;
             }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 49116f3f171..16fd8cccc89 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -9,7 +9,7 @@ use crate::resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleIm
 use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding};
 use crate::{ModuleOrUniformRoot, PerNS, Resolver, ResolverArenas, ExternPreludeEntry};
 use crate::Namespace::{self, TypeNS, ValueNS, MacroNS};
-use crate::{resolve_error, resolve_struct_error, ResolutionError};
+use crate::{resolve_error, resolve_struct_error, ResolutionError, Determinacy};
 
 use rustc::bug;
 use rustc::hir::def::{self, *};
@@ -29,8 +29,7 @@ use syntax::attr;
 
 use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
 use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant};
-use syntax::ext::base::{MacroKind, SyntaxExtension};
-use syntax::ext::base::Determinacy::Undetermined;
+use syntax::ext::base::SyntaxExtension;
 use syntax::ext::hygiene::Mark;
 use syntax::ext::tt::macro_rules;
 use syntax::feature_gate::is_builtin_attr;
@@ -231,9 +230,9 @@ impl<'a> Resolver<'a> {
                     source: source.ident,
                     target: ident,
                     source_bindings: PerNS {
-                        type_ns: Cell::new(Err(Undetermined)),
-                        value_ns: Cell::new(Err(Undetermined)),
-                        macro_ns: Cell::new(Err(Undetermined)),
+                        type_ns: Cell::new(Err(Determinacy::Undetermined)),
+                        value_ns: Cell::new(Err(Determinacy::Undetermined)),
+                        macro_ns: Cell::new(Err(Determinacy::Undetermined)),
                     },
                     target_bindings: PerNS {
                         type_ns: Cell::new(None),
@@ -456,23 +455,7 @@ impl<'a> Resolver<'a> {
 
                 // Functions introducing procedural macros reserve a slot
                 // in the macro namespace as well (see #52225).
-                if attr::contains_name(&item.attrs, sym::proc_macro) ||
-                   attr::contains_name(&item.attrs, sym::proc_macro_attribute) {
-                    let res = Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), res.def_id());
-                    self.define(parent, ident, MacroNS, (res, vis, sp, expansion));
-                }
-                if let Some(attr) = attr::find_by_name(&item.attrs, sym::proc_macro_derive) {
-                    if let Some(trait_attr) =
-                            attr.meta_item_list().and_then(|list| list.get(0).cloned()) {
-                        if let Some(ident) = trait_attr.ident() {
-                            let res = Res::Def(
-                                DefKind::Macro(MacroKind::ProcMacroStub),
-                                res.def_id(),
-                            );
-                            self.define(parent, ident, MacroNS, (res, vis, ident.span, expansion));
-                        }
-                    }
-                }
+                self.define_macro(item, expansion, &mut LegacyScope::Empty);
             }
 
             // These items live in the type namespace.
@@ -772,14 +755,8 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    pub fn get_macro(&mut self, res: Res) -> Lrc<SyntaxExtension> {
-        self.opt_get_macro(res).expect("expected `DefKind::Macro` or `Res::NonMacroAttr`")
-    }
-
-    crate fn opt_get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
+    pub fn get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
         let def_id = match res {
-            Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) =>
-                return Some(self.non_macro_attr(true)), // some dummy extension
             Res::Def(DefKind::Macro(..), def_id) => def_id,
             Res::NonMacroAttr(attr_kind) =>
                 return Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)),
@@ -946,12 +923,19 @@ pub struct BuildReducedGraphVisitor<'a, 'b> {
 
 impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
     fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> {
-        let mark = id.placeholder_to_mark();
-        self.resolver.current_module.unresolved_invocations.borrow_mut().insert(mark);
-        let invocation = self.resolver.invocations[&mark];
-        invocation.module.set(self.resolver.current_module);
-        invocation.parent_legacy_scope.set(self.current_legacy_scope);
-        invocation
+        let invoc_id = id.placeholder_to_mark();
+
+        self.resolver.current_module.unresolved_invocations.borrow_mut().insert(invoc_id);
+
+        let invocation_data = self.resolver.arenas.alloc_invocation_data(InvocationData {
+            module: self.resolver.current_module,
+            parent_legacy_scope: self.current_legacy_scope,
+            output_legacy_scope: Cell::new(None),
+        });
+        let old_invocation_data = self.resolver.invocations.insert(invoc_id, invocation_data);
+        assert!(old_invocation_data.is_none(), "invocation data is reset for an invocation");
+
+        invocation_data
     }
 }
 
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 207b0b3754a..1216a083700 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -15,11 +15,12 @@
 
 pub use rustc::hir::def::{Namespace, PerNS};
 
+use Determinacy::*;
 use GenericParameters::*;
 use RibKind::*;
 use smallvec::smallvec;
 
-use rustc::hir::map::{Definitions, DefCollector};
+use rustc::hir::map::Definitions;
 use rustc::hir::{self, PrimTy, Bool, Char, Float, Int, Uint, Str};
 use rustc::middle::cstore::CrateStore;
 use rustc::session::Session;
@@ -40,8 +41,7 @@ use rustc_metadata::cstore::CStore;
 use syntax::source_map::SourceMap;
 use syntax::ext::hygiene::{Mark, Transparency, SyntaxContext};
 use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
-use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
-use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
+use syntax::ext::base::SyntaxExtension;
 use syntax::ext::base::MacroKind;
 use syntax::symbol::{Symbol, kw, sym};
 use syntax::util::lev_distance::find_best_match_for_name;
@@ -93,6 +93,18 @@ enum Weak {
     No,
 }
 
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub enum Determinacy {
+    Determined,
+    Undetermined,
+}
+
+impl Determinacy {
+    fn determined(determined: bool) -> Determinacy {
+        if determined { Determinacy::Determined } else { Determinacy::Undetermined }
+    }
+}
+
 enum ScopeSet {
     Import(Namespace),
     AbsolutePath(Namespace),
@@ -1663,10 +1675,13 @@ pub struct Resolver<'a> {
     macro_use_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
     pub all_macros: FxHashMap<Name, Res>,
     macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
+    dummy_ext_bang: Lrc<SyntaxExtension>,
+    dummy_ext_derive: Lrc<SyntaxExtension>,
     non_macro_attrs: [Lrc<SyntaxExtension>; 2],
     macro_defs: FxHashMap<Mark, DefId>,
     local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
     unused_macros: NodeMap<Span>,
+    proc_macro_stubs: NodeSet,
 
     /// Maps the `Mark` of an expansion to its containing module or block.
     invocations: FxHashMap<Mark, &'a InvocationData<'a>>,
@@ -1901,8 +1916,7 @@ impl<'a> Resolver<'a> {
         module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root);
 
         let mut definitions = Definitions::default();
-        DefCollector::new(&mut definitions, Mark::root())
-            .collect_root(crate_name, session.local_crate_disambiguator());
+        definitions.create_root_def(crate_name, session.local_crate_disambiguator());
 
         let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> =
             session.opts.externs.iter().map(|kv| (Ident::from_str(kv.0), Default::default()))
@@ -1926,9 +1940,8 @@ impl<'a> Resolver<'a> {
         macro_defs.insert(Mark::root(), root_def_id);
 
         let features = session.features_untracked();
-        let non_macro_attr = |mark_used| Lrc::new(SyntaxExtension::default(
-            SyntaxExtensionKind::NonMacroAttr { mark_used }, session.edition()
-        ));
+        let non_macro_attr =
+            |mark_used| Lrc::new(SyntaxExtension::non_macro_attr(mark_used, session.edition()));
 
         Resolver {
             session,
@@ -2003,6 +2016,8 @@ impl<'a> Resolver<'a> {
             macro_use_prelude: FxHashMap::default(),
             all_macros: FxHashMap::default(),
             macro_map: FxHashMap::default(),
+            dummy_ext_bang: Lrc::new(SyntaxExtension::dummy_bang(session.edition())),
+            dummy_ext_derive: Lrc::new(SyntaxExtension::dummy_derive(session.edition())),
             non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)],
             invocations,
             macro_defs,
@@ -2011,6 +2026,7 @@ impl<'a> Resolver<'a> {
             potentially_unused_imports: Vec::new(),
             struct_constructors: Default::default(),
             unused_macros: Default::default(),
+            proc_macro_stubs: Default::default(),
             current_type_ascription: Vec::new(),
             injected_crate: None,
             active_features:
@@ -2028,6 +2044,14 @@ impl<'a> Resolver<'a> {
         self.non_macro_attrs[mark_used as usize].clone()
     }
 
+    fn dummy_ext(&self, macro_kind: MacroKind) -> Lrc<SyntaxExtension> {
+        match macro_kind {
+            MacroKind::Bang => self.dummy_ext_bang.clone(),
+            MacroKind::Derive => self.dummy_ext_derive.clone(),
+            MacroKind::Attr => self.non_macro_attr(true),
+        }
+    }
+
     /// Runs the function on each namespace.
     fn per_ns<F: FnMut(&mut Self, Namespace)>(&mut self, mut f: F) {
         f(self, TypeNS);
@@ -2223,6 +2247,7 @@ impl<'a> Resolver<'a> {
         }
 
         if !module.no_implicit_prelude {
+            ident.span.adjust(Mark::root());
             if ns == TypeNS {
                 if let Some(binding) = self.extern_prelude_get(ident, !record_used) {
                     return Some(LexicalScopeBinding::Item(binding));
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 8f23c9813f7..fc1becfe309 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -1,4 +1,4 @@
-use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
+use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc, Determinacy};
 use crate::{CrateLint, Resolver, ResolutionError, ScopeSet, Weak};
 use crate::{Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding};
 use crate::{is_known_tool, resolve_error};
@@ -8,16 +8,16 @@ use crate::build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
 use crate::resolve_imports::ImportResolver;
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
 use rustc::hir::def::{self, DefKind, NonMacroAttrKind};
-use rustc::hir::map::{self, DefCollector};
+use rustc::hir::map::DefCollector;
 use rustc::middle::stability;
 use rustc::{ty, lint, span_bug};
-use syntax::ast::{self, Ident};
+use syntax::ast::{self, Ident, ItemKind};
 use syntax::attr::{self, StabilityLevel};
 use syntax::errors::DiagnosticBuilder;
-use syntax::ext::base::{self, Determinacy};
+use syntax::ext::base::{self, Indeterminate};
 use syntax::ext::base::{MacroKind, SyntaxExtension};
 use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
-use syntax::ext::hygiene::{self, Mark};
+use syntax::ext::hygiene::{self, Mark, ExpnInfo, ExpnKind};
 use syntax::ext::tt::macro_rules;
 use syntax::feature_gate::{feature_err, emit_feature_err, is_builtin_attr_name};
 use syntax::feature_gate::{AttributeGate, GateIssue, Stability, BUILTIN_ATTRIBUTES};
@@ -32,14 +32,14 @@ use rustc_data_structures::sync::Lrc;
 
 type Res = def::Res<ast::NodeId>;
 
+// FIXME: Merge this with `ParentScope`.
 #[derive(Clone, Debug)]
 pub struct InvocationData<'a> {
-    def_index: DefIndex,
     /// The module in which the macro was invoked.
-    crate module: Cell<Module<'a>>,
+    crate module: Module<'a>,
     /// The legacy scope in which the macro was invoked.
     /// The invocation path is resolved in this scope.
-    crate parent_legacy_scope: Cell<LegacyScope<'a>>,
+    crate parent_legacy_scope: LegacyScope<'a>,
     /// The legacy scope *produced* by expanding this macro invocation,
     /// includes all the macro_rules items, other invocations, etc generated by it.
     /// `None` if the macro is not expanded yet.
@@ -49,10 +49,9 @@ pub struct InvocationData<'a> {
 impl<'a> InvocationData<'a> {
     pub fn root(graph_root: Module<'a>) -> Self {
         InvocationData {
-            module: Cell::new(graph_root),
-            def_index: CRATE_DEF_INDEX,
-            parent_legacy_scope: Cell::new(LegacyScope::Empty),
-            output_legacy_scope: Cell::new(Some(LegacyScope::Empty)),
+            module: graph_root,
+            parent_legacy_scope: LegacyScope::Empty,
+            output_legacy_scope: Cell::new(None),
         }
     }
 }
@@ -74,9 +73,6 @@ pub struct LegacyBinding<'a> {
 /// can potentially expand into macro definitions.
 #[derive(Copy, Clone, Debug)]
 pub enum LegacyScope<'a> {
-    /// Created when invocation data is allocated in the arena;
-    /// must be replaced with a proper scope later.
-    Uninitialized,
     /// Empty "root" scope at the crate start containing no names.
     Empty,
     /// The scope introduced by a `macro_rules!` macro definition.
@@ -102,12 +98,11 @@ fn sub_namespace_match(candidate: Option<MacroKind>, requirement: Option<MacroKi
     #[derive(PartialEq)]
     enum SubNS { Bang, AttrLike }
     let sub_ns = |kind| match kind {
-        MacroKind::Bang => Some(SubNS::Bang),
-        MacroKind::Attr | MacroKind::Derive => Some(SubNS::AttrLike),
-        MacroKind::ProcMacroStub => None,
+        MacroKind::Bang => SubNS::Bang,
+        MacroKind::Attr | MacroKind::Derive => SubNS::AttrLike,
     };
-    let requirement = requirement.and_then(|kind| sub_ns(kind));
-    let candidate = candidate.and_then(|kind| sub_ns(kind));
+    let candidate = candidate.map(sub_ns);
+    let requirement = requirement.map(sub_ns);
     // "No specific sub-namespace" means "matches anything" for both requirements and candidates.
     candidate.is_none() || requirement.is_none() || candidate == requirement
 }
@@ -115,17 +110,36 @@ fn sub_namespace_match(candidate: Option<MacroKind>, requirement: Option<MacroKi
 // We don't want to format a path using pretty-printing,
 // `format!("{}", path)`, because that tries to insert
 // line-breaks and is slow.
-fn fast_print_path(path: &ast::Path) -> String {
-    let mut path_str = String::with_capacity(64);
-    for (i, segment) in path.segments.iter().enumerate() {
-        if i != 0 {
-            path_str.push_str("::");
+fn fast_print_path(path: &ast::Path) -> Symbol {
+    if path.segments.len() == 1 {
+        return path.segments[0].ident.name
+    } else {
+        let mut path_str = String::with_capacity(64);
+        for (i, segment) in path.segments.iter().enumerate() {
+            if i != 0 {
+                path_str.push_str("::");
+            }
+            if segment.ident.name != kw::PathRoot {
+                path_str.push_str(&segment.ident.as_str())
+            }
         }
-        if segment.ident.name != kw::PathRoot {
-            path_str.push_str(&segment.ident.as_str())
+        Symbol::intern(&path_str)
+    }
+}
+
+fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> {
+    if attr::contains_name(&item.attrs, sym::proc_macro) {
+        return Some((MacroKind::Bang, item.ident, item.span));
+    } else if attr::contains_name(&item.attrs, sym::proc_macro_attribute) {
+        return Some((MacroKind::Attr, item.ident, item.span));
+    } else if let Some(attr) = attr::find_by_name(&item.attrs, sym::proc_macro_derive) {
+        if let Some(nested_meta) = attr.meta_item_list().and_then(|list| list.get(0).cloned()) {
+            if let Some(ident) = nested_meta.ident() {
+                return Some((MacroKind::Derive, ident, ident.span));
+            }
         }
     }
-    path_str
+    None
 }
 
 impl<'a> base::Resolver for Resolver<'a> {
@@ -134,13 +148,16 @@ impl<'a> base::Resolver for Resolver<'a> {
     }
 
     fn get_module_scope(&mut self, id: ast::NodeId) -> Mark {
-        let mark = Mark::fresh(Mark::root());
+        let span = DUMMY_SP.fresh_expansion(Mark::root(), ExpnInfo::default(
+            ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, self.session.edition()
+        ));
+        let mark = span.ctxt().outer();
         let module = self.module_map[&self.definitions.local_def_id(id)];
+        self.definitions.set_invocation_parent(mark, module.def_id().unwrap().index);
         self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData {
-            module: Cell::new(module),
-            def_index: module.def_id().unwrap().index,
-            parent_legacy_scope: Cell::new(LegacyScope::Empty),
-            output_legacy_scope: Cell::new(Some(LegacyScope::Empty)),
+            module,
+            parent_legacy_scope: LegacyScope::Empty,
+            output_legacy_scope: Cell::new(None),
         }));
         mark
     }
@@ -157,16 +174,20 @@ impl<'a> base::Resolver for Resolver<'a> {
 
     fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
                                             derives: &[Mark]) {
-        let invocation = self.invocations[&mark];
-        self.collect_def_ids(mark, invocation, fragment);
+        fragment.visit_with(&mut DefCollector::new(&mut self.definitions, mark));
 
-        self.current_module = invocation.module.get();
+        let invocation = self.invocations[&mark];
+        self.current_module = invocation.module;
         self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
         self.current_module.unresolved_invocations.borrow_mut().extend(derives);
+        let parent_def = self.definitions.invocation_parent(mark);
+        for &derive_invoc_id in derives {
+            self.definitions.set_invocation_parent(derive_invoc_id, parent_def);
+        }
         self.invocations.extend(derives.iter().map(|&derive| (derive, invocation)));
         let mut visitor = BuildReducedGraphVisitor {
             resolver: self,
-            current_legacy_scope: invocation.parent_legacy_scope.get(),
+            current_legacy_scope: invocation.parent_legacy_scope,
             expansion: mark,
         };
         fragment.visit_with(&mut visitor);
@@ -198,36 +219,23 @@ impl<'a> base::Resolver for Resolver<'a> {
     }
 
     fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool)
-                                -> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
+                                -> Result<Option<Lrc<SyntaxExtension>>, Indeterminate> {
         let (path, kind, derives_in_scope, after_derive) = match invoc.kind {
-            InvocationKind::Attr { attr: None, .. } =>
-                return Ok(None),
-            InvocationKind::Attr { attr: Some(ref attr), ref traits, after_derive, .. } =>
-                (&attr.path, MacroKind::Attr, traits.clone(), after_derive),
+            InvocationKind::Attr { ref attr, ref derives, after_derive, .. } =>
+                (&attr.path, MacroKind::Attr, derives.clone(), after_derive),
             InvocationKind::Bang { ref mac, .. } =>
                 (&mac.node.path, MacroKind::Bang, Vec::new(), false),
             InvocationKind::Derive { ref path, .. } =>
                 (path, MacroKind::Derive, Vec::new(), false),
+            InvocationKind::DeriveContainer { .. } =>
+                return Ok(None),
         };
 
         let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
-        let (res, ext) = match self.resolve_macro_to_res(path, kind, &parent_scope, true, force) {
-            Ok((res, ext)) => (res, ext),
-            // Replace unresolved attributes with used inert attributes for better recovery.
-            Err(Determinacy::Determined) if kind == MacroKind::Attr =>
-                (Res::Err, self.non_macro_attr(true)),
-            Err(determinacy) => return Err(determinacy),
-        };
+        let (ext, res) = self.smart_resolve_macro_path(path, kind, &parent_scope, true, force)?;
 
         let span = invoc.span();
-        let path = fast_print_path(path);
-        let format = match kind {
-            MacroKind::Derive => format!("derive({})", path),
-            _ => path.clone(),
-        };
-        invoc.expansion_data.mark.set_expn_info(ext.expn_info(span, &format));
-
-        self.check_stability_and_deprecation(&ext, &path, span);
+        invoc.expansion_data.mark.set_expn_info(ext.expn_info(span, fast_print_path(path)));
 
         if let Res::Def(_, def_id) = res {
             if after_derive {
@@ -243,13 +251,6 @@ impl<'a> base::Resolver for Resolver<'a> {
         Ok(Some(ext))
     }
 
-    fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, invoc_id: Mark,
-                          derives_in_scope: Vec<ast::Path>, force: bool)
-                          -> Result<Lrc<SyntaxExtension>, Determinacy> {
-        let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
-        Ok(self.resolve_macro_to_res(path, kind, &parent_scope, false, force)?.1)
-    }
-
     fn check_unused_macros(&self) {
         for (&node_id, &span) in self.unused_macros.iter() {
             self.session.buffer_lint(
@@ -267,91 +268,95 @@ impl<'a> Resolver<'a> {
     fn invoc_parent_scope(&self, invoc_id: Mark, derives: Vec<ast::Path>) -> ParentScope<'a> {
         let invoc = self.invocations[&invoc_id];
         ParentScope {
-            module: invoc.module.get().nearest_item_scope(),
+            module: invoc.module.nearest_item_scope(),
             expansion: invoc_id.parent(),
-            legacy: invoc.parent_legacy_scope.get(),
+            legacy: invoc.parent_legacy_scope,
             derives,
         }
     }
 
-    fn resolve_macro_to_res(
+    /// Resolve macro path with error reporting and recovery.
+    fn smart_resolve_macro_path(
         &mut self,
         path: &ast::Path,
         kind: MacroKind,
         parent_scope: &ParentScope<'a>,
         trace: bool,
         force: bool,
-    ) -> Result<(Res, Lrc<SyntaxExtension>), Determinacy> {
-        let res = self.resolve_macro_to_res_inner(path, kind, parent_scope, trace, force);
+    ) -> Result<(Lrc<SyntaxExtension>, Res), Indeterminate> {
+        let (ext, res) = match self.resolve_macro_path(path, kind, parent_scope, trace, force) {
+            Ok((Some(ext), res)) => (ext, res),
+            // Use dummy syntax extensions for unresolved macros for better recovery.
+            Ok((None, res)) => (self.dummy_ext(kind), res),
+            Err(Determinacy::Determined) => (self.dummy_ext(kind), Res::Err),
+            Err(Determinacy::Undetermined) => return Err(Indeterminate),
+        };
 
         // Report errors and enforce feature gates for the resolved macro.
         let features = self.session.features_untracked();
-        if res != Err(Determinacy::Undetermined) {
-            // Do not report duplicated errors on every undetermined resolution.
-            for segment in &path.segments {
-                if let Some(args) = &segment.args {
-                    self.session.span_err(args.span(), "generic arguments in macro path");
-                }
-                if kind == MacroKind::Attr && !features.rustc_attrs &&
-                   segment.ident.as_str().starts_with("rustc") {
-                    let msg = "attributes starting with `rustc` are \
-                               reserved for use by the `rustc` compiler";
-                    emit_feature_err(
-                        &self.session.parse_sess,
-                        sym::rustc_attrs,
-                        segment.ident.span,
-                        GateIssue::Language,
-                        msg,
-                    );
-                }
+        for segment in &path.segments {
+            if let Some(args) = &segment.args {
+                self.session.span_err(args.span(), "generic arguments in macro path");
+            }
+            if kind == MacroKind::Attr && !features.rustc_attrs &&
+               segment.ident.as_str().starts_with("rustc") {
+                let msg =
+                    "attributes starting with `rustc` are reserved for use by the `rustc` compiler";
+                emit_feature_err(
+                    &self.session.parse_sess,
+                    sym::rustc_attrs,
+                    segment.ident.span,
+                    GateIssue::Language,
+                    msg,
+                );
             }
         }
 
-        let res = res?;
-
         match res {
-            Res::Def(DefKind::Macro(macro_kind), def_id) => {
+            Res::Def(DefKind::Macro(_), def_id) => {
                 if let Some(node_id) = self.definitions.as_local_node_id(def_id) {
                     self.unused_macros.remove(&node_id);
-                }
-                if macro_kind == MacroKind::ProcMacroStub {
-                    let msg = "can't use a procedural macro from the same crate that defines it";
-                    self.session.span_err(path.span, msg);
-                    return Err(Determinacy::Determined);
+                    if self.proc_macro_stubs.contains(&node_id) {
+                        self.session.span_err(
+                            path.span,
+                            "can't use a procedural macro from the same crate that defines it",
+                        );
+                    }
                 }
             }
             Res::NonMacroAttr(attr_kind) => {
-                if kind == MacroKind::Attr {
-                    if attr_kind == NonMacroAttrKind::Custom {
-                        assert!(path.segments.len() == 1);
-                        if !features.custom_attribute {
-                            let msg = format!("The attribute `{}` is currently unknown to the \
-                                               compiler and may have meaning added to it in the \
-                                               future", path);
-                            self.report_unknown_attribute(
-                                path.span,
-                                &path.segments[0].ident.as_str(),
-                                &msg,
-                                sym::custom_attribute,
-                            );
-                        }
+                if attr_kind == NonMacroAttrKind::Custom {
+                    assert!(path.segments.len() == 1);
+                    if !features.custom_attribute {
+                        let msg = format!("The attribute `{}` is currently unknown to the \
+                                            compiler and may have meaning added to it in the \
+                                            future", path);
+                        self.report_unknown_attribute(
+                            path.span,
+                            &path.segments[0].ident.as_str(),
+                            &msg,
+                            sym::custom_attribute,
+                        );
                     }
-                } else {
-                    // Not only attributes, but anything in macro namespace can result in
-                    // `Res::NonMacroAttr` definition (e.g., `inline!()`), so we must report
-                    // an error for those cases.
-                    let msg = format!("expected a macro, found {}", res.descr());
-                    self.session.span_err(path.span, &msg);
-                    return Err(Determinacy::Determined);
                 }
             }
-            Res::Err => {
-                return Err(Determinacy::Determined);
-            }
+            Res::Err => {}
             _ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"),
-        }
+        };
+
+        self.check_stability_and_deprecation(&ext, path);
 
-        Ok((res, self.get_macro(res)))
+        Ok(if ext.macro_kind() != kind {
+            let expected = if kind == MacroKind::Attr { "attribute" } else  { kind.descr() };
+            let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path);
+            self.session.struct_span_err(path.span, &msg)
+                        .span_label(path.span, format!("not {} {}", kind.article(), expected))
+                        .emit();
+            // Use dummy syntax extensions for unexpected macro kinds for better recovery.
+            (self.dummy_ext(kind), Res::Err)
+        } else {
+            (ext, res)
+        })
     }
 
     fn report_unknown_attribute(&self, span: Span, name: &str, msg: &str, feature: Symbol) {
@@ -408,14 +413,14 @@ impl<'a> Resolver<'a> {
         err.emit();
     }
 
-    pub fn resolve_macro_to_res_inner(
+    pub fn resolve_macro_path(
         &mut self,
         path: &ast::Path,
         kind: MacroKind,
         parent_scope: &ParentScope<'a>,
         trace: bool,
         force: bool,
-    ) -> Result<Res, Determinacy> {
+    ) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> {
         let path_span = path.span;
         let mut path = Segment::from_path(path);
 
@@ -427,7 +432,7 @@ impl<'a> Resolver<'a> {
             path.insert(0, Segment::from_ident(root));
         }
 
-        if path.len() > 1 {
+        let res = if path.len() > 1 {
             let res = match self.resolve_path(&path, Some(MacroNS), parent_scope,
                                               false, path_span, CrateLint::No) {
                 PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {
@@ -463,7 +468,9 @@ impl<'a> Resolver<'a> {
             let res = binding.map(|binding| binding.res());
             self.prohibit_imported_non_macro_attrs(binding.ok(), res.ok(), path_span);
             res
-        }
+        };
+
+        res.map(|res| (self.get_macro(res), res))
     }
 
     // Resolve an identifier in lexical scope.
@@ -592,16 +599,16 @@ impl<'a> Resolver<'a> {
                     let mut result = Err(Determinacy::Determined);
                     for derive in &parent_scope.derives {
                         let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
-                        match self.resolve_macro_to_res(derive, MacroKind::Derive,
-                                                        &parent_scope, true, force) {
-                            Ok((_, ext)) => if ext.helper_attrs.contains(&ident.name) {
+                        match self.resolve_macro_path(derive, MacroKind::Derive,
+                                                      &parent_scope, true, force) {
+                            Ok((Some(ext), _)) => if ext.helper_attrs.contains(&ident.name) {
                                 let binding = (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
                                                ty::Visibility::Public, derive.span, Mark::root())
                                                .to_name_binding(self.arenas);
                                 result = Ok((binding, Flags::empty()));
                                 break;
                             }
-                            Err(Determinacy::Determined) => {}
+                            Ok(_) | Err(Determinacy::Determined) => {}
                             Err(Determinacy::Undetermined) =>
                                 result = Err(Determinacy::Undetermined),
                         }
@@ -837,10 +844,9 @@ impl<'a> Resolver<'a> {
                         binding.parent_legacy_scope
                     ),
                     LegacyScope::Invocation(invoc) => WhereToResolve::MacroRules(
-                        invoc.output_legacy_scope.get().unwrap_or(invoc.parent_legacy_scope.get())
+                        invoc.output_legacy_scope.get().unwrap_or(invoc.parent_legacy_scope)
                     ),
                     LegacyScope::Empty => WhereToResolve::Module(parent_scope.module),
-                    LegacyScope::Uninitialized => unreachable!(),
                 }
                 WhereToResolve::CrateRoot => match ns {
                     TypeNS => {
@@ -853,6 +859,7 @@ impl<'a> Resolver<'a> {
                     match self.hygienic_lexical_parent(module, &mut ident.span) {
                         Some(parent_module) => WhereToResolve::Module(parent_module),
                         None => {
+                            ident.span.adjust(Mark::root());
                             use_prelude = !module.no_implicit_prelude;
                             match ns {
                                 TypeNS => WhereToResolve::ExternPrelude,
@@ -862,7 +869,7 @@ impl<'a> Resolver<'a> {
                         }
                     }
                 }
-                WhereToResolve::MacroUsePrelude => WhereToResolve::BuiltinMacros,
+                WhereToResolve::MacroUsePrelude => WhereToResolve::StdLibPrelude,
                 WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs,
                 WhereToResolve::BuiltinAttrs => WhereToResolve::LegacyPluginHelpers,
                 WhereToResolve::LegacyPluginHelpers => break, // nowhere else to search
@@ -872,7 +879,7 @@ impl<'a> Resolver<'a> {
                 WhereToResolve::StdLibPrelude => match ns {
                     TypeNS => WhereToResolve::BuiltinTypes,
                     ValueNS => break, // nowhere else to search
-                    MacroNS => unreachable!(),
+                    MacroNS => WhereToResolve::BuiltinMacros,
                 }
                 WhereToResolve::BuiltinTypes => break, // nowhere else to search
             };
@@ -999,7 +1006,8 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    fn check_stability_and_deprecation(&self, ext: &SyntaxExtension, path: &str, span: Span) {
+    fn check_stability_and_deprecation(&self, ext: &SyntaxExtension, path: &ast::Path) {
+        let span = path.span;
         if let Some(stability) = &ext.stability {
             if let StabilityLevel::Unstable { reason, issue } = stability.level {
                 let feature = stability.feature;
@@ -1008,14 +1016,14 @@ impl<'a> Resolver<'a> {
                 }
             }
             if let Some(depr) = &stability.rustc_depr {
-                let (message, lint) = stability::rustc_deprecation_message(depr, path);
+                let (message, lint) = stability::rustc_deprecation_message(depr, &path.to_string());
                 stability::early_report_deprecation(
                     self.session, &message, depr.suggestion, lint, span
                 );
             }
         }
         if let Some(depr) = &ext.deprecation {
-            let (message, lint) = stability::deprecation_message(depr, path);
+            let (message, lint) = stability::deprecation_message(depr, &path.to_string());
             stability::early_report_deprecation(self.session, &message, None, lint, span);
         }
     }
@@ -1092,36 +1100,11 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    fn collect_def_ids(&mut self,
-                       mark: Mark,
-                       invocation: &'a InvocationData<'a>,
-                       fragment: &AstFragment) {
-        let Resolver { ref mut invocations, arenas, graph_root, .. } = *self;
-        let InvocationData { def_index, .. } = *invocation;
-
-        let visit_macro_invoc = &mut |invoc: map::MacroInvocationData| {
-            invocations.entry(invoc.mark).or_insert_with(|| {
-                arenas.alloc_invocation_data(InvocationData {
-                    def_index: invoc.def_index,
-                    module: Cell::new(graph_root),
-                    parent_legacy_scope: Cell::new(LegacyScope::Uninitialized),
-                    output_legacy_scope: Cell::new(None),
-                })
-            });
-        };
-
-        let mut def_collector = DefCollector::new(&mut self.definitions, mark);
-        def_collector.visit_macro_invoc = Some(visit_macro_invoc);
-        def_collector.with_parent(def_index, |def_collector| {
-            fragment.visit_with(def_collector)
-        });
-    }
-
     crate fn check_reserved_macro_name(&mut self, ident: Ident, res: Res) {
         // Reserve some names that are not quite covered by the general check
         // performed on `Resolver::builtin_attrs`.
         if ident.name == sym::cfg || ident.name == sym::cfg_attr || ident.name == sym::derive {
-            let macro_kind = self.opt_get_macro(res).map(|ext| ext.macro_kind());
+            let macro_kind = self.get_macro(res).map(|ext| ext.macro_kind());
             if macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr)) {
                 self.session.span_err(
                     ident.span, &format!("name `{}` is reserved in attribute namespace", ident)
@@ -1134,19 +1117,32 @@ impl<'a> Resolver<'a> {
                         item: &ast::Item,
                         expansion: Mark,
                         current_legacy_scope: &mut LegacyScope<'a>) {
-        self.local_macro_def_scopes.insert(item.id, self.current_module);
-        let ident = item.ident;
+        let (ext, ident, span, is_legacy) = match &item.node {
+            ItemKind::MacroDef(def) => {
+                let ext = Lrc::new(macro_rules::compile(
+                    &self.session.parse_sess,
+                    &self.session.features_untracked(),
+                    item,
+                    self.session.edition(),
+                ));
+                (ext, item.ident, item.span, def.legacy)
+            }
+            ItemKind::Fn(..) => match proc_macro_stub(item) {
+                Some((macro_kind, ident, span)) => {
+                    self.proc_macro_stubs.insert(item.id);
+                    (self.dummy_ext(macro_kind), ident, span, false)
+                }
+                None => return,
+            }
+            _ => unreachable!(),
+        };
 
         let def_id = self.definitions.local_def_id(item.id);
-        let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
-                                               &self.session.features_untracked(),
-                                               item, self.session.edition()));
-        let macro_kind = ext.macro_kind();
-        let res = Res::Def(DefKind::Macro(macro_kind), def_id);
+        let res = Res::Def(DefKind::Macro(ext.macro_kind()), def_id);
         self.macro_map.insert(def_id, ext);
+        self.local_macro_def_scopes.insert(item.id, self.current_module);
 
-        let def = match item.node { ast::ItemKind::MacroDef(ref def) => def, _ => unreachable!() };
-        if def.legacy {
+        if is_legacy {
             let ident = ident.modern();
             self.macro_names.insert(ident);
             let is_macro_export = attr::contains_name(&item.attrs, sym::macro_export);
@@ -1155,7 +1151,7 @@ impl<'a> Resolver<'a> {
             } else {
                 ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
             };
-            let binding = (res, vis, item.span, expansion).to_name_binding(self.arenas);
+            let binding = (res, vis, span, expansion).to_name_binding(self.arenas);
             self.set_binding_parent_module(binding, self.current_module);
             let legacy_binding = self.arenas.alloc_legacy_binding(LegacyBinding {
                 parent_legacy_scope: *current_legacy_scope, binding, ident
@@ -1165,18 +1161,18 @@ impl<'a> Resolver<'a> {
             if is_macro_export {
                 let module = self.graph_root;
                 self.define(module, ident, MacroNS,
-                            (res, vis, item.span, expansion, IsMacroExport));
+                            (res, vis, span, expansion, IsMacroExport));
             } else {
                 self.check_reserved_macro_name(ident, res);
-                self.unused_macros.insert(item.id, item.span);
+                self.unused_macros.insert(item.id, span);
             }
         } else {
             let module = self.current_module;
             let vis = self.resolve_visibility(&item.vis);
             if vis != ty::Visibility::Public {
-                self.unused_macros.insert(item.id, item.span);
+                self.unused_macros.insert(item.id, span);
             }
-            self.define(module, ident, MacroNS, (res, vis, item.span, expansion));
+            self.define(module, ident, MacroNS, (res, vis, span, expansion));
         }
     }
 }
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 7de1cd29a9c..5edfe923e68 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -2,6 +2,7 @@ use ImportDirectiveSubclass::*;
 
 use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
 use crate::{CrateLint, Module, ModuleOrUniformRoot, PerNS, ScopeSet, Weak};
+use crate::Determinacy::{self, *};
 use crate::Namespace::{self, TypeNS, MacroNS};
 use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
 use crate::{Resolver, Segment};
@@ -27,7 +28,6 @@ use rustc::util::nodemap::FxHashSet;
 use rustc::{bug, span_bug};
 
 use syntax::ast::{self, Ident, Name, NodeId, CRATE_NODE_ID};
-use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
 use syntax::ext::hygiene::Mark;
 use syntax::symbol::kw;
 use syntax::util::lev_distance::find_best_match_for_name;
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index effd69dc61d..2c8f7a44f5a 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -37,7 +37,6 @@ use syntax::parse::lexer::comments::strip_doc_comment_decoration;
 use syntax::print::pprust;
 use syntax::visit::{self, Visitor};
 use syntax::print::pprust::{arg_to_string, ty_to_string};
-use syntax::source_map::MacroAttribute;
 use syntax_pos::*;
 
 use json_dumper::JsonDumper;
@@ -842,10 +841,10 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
         let callsite = span.source_callsite();
         let callsite_span = self.span_from_span(callsite);
         let callee = span.source_callee()?;
-        let callee_span = callee.def_site?;
 
         // Ignore attribute macros, their spans are usually mangled
-        if let MacroAttribute(_) = callee.format {
+        if let ExpnKind::Macro(MacroKind::Attr, _) |
+               ExpnKind::Macro(MacroKind::Derive, _) = callee.kind {
             return None;
         }
 
@@ -856,7 +855,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
             .sess
             .imported_macro_spans
             .borrow()
-            .get(&callee_span)
+            .get(&callee.def_site)
         {
             let &(ref mac_name, mac_span) = mac;
             let mac_span = self.span_from_span(mac_span);
@@ -867,10 +866,10 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
             });
         }
 
-        let callee_span = self.span_from_span(callee_span);
+        let callee_span = self.span_from_span(callee.def_site);
         Some(MacroRef {
             span: callsite_span,
-            qualname: callee.format.name().to_string(), // FIXME: generate the real qualname
+            qualname: callee.kind.descr().to_string(), // FIXME: generate the real qualname
             callee_span,
         })
     }
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index d24f92a6faf..de42a6a35c8 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -15,7 +15,7 @@ use syntax::ast;
 use syntax::source_map::Spanned;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax_pos::Span;
-use syntax_pos::hygiene::CompilerDesugaringKind;
+use syntax_pos::hygiene::DesugaringKind;
 
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 use std::cmp;
@@ -184,7 +184,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             // In the case of `if`- and `while`-expressions we've already checked
                             // that `scrutinee: bool`. We know that the pattern is `true`,
                             // so an error here would be a duplicate and from the wrong POV.
-                            s.is_compiler_desugaring(CompilerDesugaringKind::CondTemporary)
+                            s.is_desugaring(DesugaringKind::CondTemporary)
                         })
                         .is_some());
                 }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 4acba6d38fa..d32ee67f745 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -119,7 +119,7 @@ use rustc::ty::subst::{UnpackedKind, Subst, InternalSubsts, SubstsRef, UserSelfT
 use rustc::ty::util::{Representability, IntTypeExt, Discr};
 use rustc::ty::layout::VariantIdx;
 use syntax_pos::{self, BytePos, Span, MultiSpan};
-use syntax_pos::hygiene::CompilerDesugaringKind;
+use syntax_pos::hygiene::DesugaringKind;
 use syntax::ast;
 use syntax::attr;
 use syntax::feature_gate::{GateIssue, emit_feature_err};
@@ -2165,7 +2165,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // If span arose from a desugaring of `if` or `while`, then it is the condition itself,
             // which diverges, that we are about to lint on. This gives suboptimal diagnostics.
             // Instead, stop here so that the `if`- or `while`-expression's block is linted instead.
-            !span.is_compiler_desugaring(CompilerDesugaringKind::CondTemporary) {
+            !span.is_desugaring(DesugaringKind::CondTemporary) {
             self.diverges.set(Diverges::WarnedAlways);
 
             debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 350bcc9dbc6..72e6614dc06 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -4199,7 +4199,6 @@ pub fn register_res(cx: &DocContext<'_>, res: Res) -> DefId {
             MacroKind::Bang => (i, TypeKind::Macro),
             MacroKind::Attr => (i, TypeKind::Attr),
             MacroKind::Derive => (i, TypeKind::Derive),
-            MacroKind::ProcMacroStub => unreachable!(),
         },
         Res::Def(DefKind::TraitAlias, i) => (i, TypeKind::TraitAlias),
         Res::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs
index 5f1a1b31616..9affc08141d 100644
--- a/src/librustdoc/html/item_type.rs
+++ b/src/librustdoc/html/item_type.rs
@@ -92,7 +92,6 @@ impl<'a> From<&'a clean::Item> for ItemType {
                 MacroKind::Bang            => ItemType::Macro,
                 MacroKind::Attr            => ItemType::ProcAttribute,
                 MacroKind::Derive          => ItemType::ProcDerive,
-                MacroKind::ProcMacroStub   => unreachable!(),
             }
             clean::StrippedItem(..)        => unreachable!(),
         }
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 2d69c29dfae..5c6847b4141 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -2471,7 +2471,6 @@ impl<'a> fmt::Display for Item<'a> {
                 MacroKind::Bang => write!(fmt, "Macro ")?,
                 MacroKind::Attr => write!(fmt, "Attribute Macro ")?,
                 MacroKind::Derive => write!(fmt, "Derive Macro ")?,
-                MacroKind::ProcMacroStub => unreachable!(),
             }
             clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?,
             clean::StaticItem(..) | clean::ForeignStaticItem(..) => write!(fmt, "Static ")?,
@@ -5092,7 +5091,6 @@ fn item_proc_macro(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, m
             }
             write!(w, "</pre>")?;
         }
-        _ => {}
     }
     document(w, cx, it)
 }
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index bb85fe898da..c527ed02bc0 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -429,15 +429,11 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
     let segment = ast::PathSegment::from_ident(Ident::from_str(path_str));
     let path = ast::Path { segments: vec![segment], span: DUMMY_SP };
     cx.enter_resolver(|resolver| {
-        let parent_scope = resolver.dummy_parent_scope();
-        if let Ok(res) = resolver.resolve_macro_to_res_inner(&path, MacroKind::Bang,
-                                                            &parent_scope, false, false) {
-            if let Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) = res {
-                // skip proc-macro stubs, they'll cause `get_macro` to crash
-            } else {
-                if let SyntaxExtensionKind::LegacyBang(..) = resolver.get_macro(res).kind {
-                    return Some(res.map_id(|_| panic!("unexpected id")));
-                }
+        if let Ok((Some(ext), res)) = resolver.resolve_macro_path(
+            &path, MacroKind::Bang, &resolver.dummy_parent_scope(), false, false
+        ) {
+            if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind {
+                return Some(res.map_id(|_| panic!("unexpected id")));
             }
         }
         if let Some(res) = resolver.all_macros.get(&Symbol::intern(path_str)) {
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index fa5faaf3ff5..009d681ed83 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -406,11 +406,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
 
                 // Struct and variant constructors and proc macro stubs always show up alongside
                 // their definitions, we've already processed them so just discard these.
-                match path.res {
-                    Res::Def(DefKind::Ctor(..), _)
-                    | Res::SelfCtor(..)
-                    | Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) => return,
-                    _ => {}
+                if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = path.res {
+                    return;
                 }
 
                 // If there was a private module in the current path then don't bother inlining
diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs
index 6d23963e141..0cecdd7ffa0 100644
--- a/src/libstd/sys/unix/fd.rs
+++ b/src/libstd/sys/unix/fd.rs
@@ -175,6 +175,7 @@ impl FileDesc {
                   target_os = "emscripten",
                   target_os = "fuchsia",
                   target_os = "l4re",
+                  target_os = "linux",
                   target_os = "haiku")))]
     pub fn set_cloexec(&self) -> io::Result<()> {
         unsafe {
@@ -187,6 +188,7 @@ impl FileDesc {
               target_os = "emscripten",
               target_os = "fuchsia",
               target_os = "l4re",
+              target_os = "linux",
               target_os = "haiku"))]
     pub fn set_cloexec(&self) -> io::Result<()> {
         unsafe {
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index c0ba41b8af4..37d5885db60 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -10,12 +10,12 @@ use crate::parse::token;
 use crate::ptr::P;
 use crate::symbol::{kw, sym, Ident, Symbol};
 use crate::{ThinVec, MACRO_ARGUMENTS};
-use crate::tokenstream::{self, TokenStream};
+use crate::tokenstream::{self, TokenStream, TokenTree};
 
 use errors::{DiagnosticBuilder, DiagnosticId};
 use smallvec::{smallvec, SmallVec};
 use syntax_pos::{Span, MultiSpan, DUMMY_SP};
-use syntax_pos::hygiene::{ExpnInfo, ExpnFormat};
+use syntax_pos::hygiene::{ExpnInfo, ExpnKind};
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{self, Lrc};
@@ -24,6 +24,7 @@ use std::path::PathBuf;
 use std::rc::Rc;
 use std::default::Default;
 
+pub use syntax_pos::hygiene::MacroKind;
 
 #[derive(Debug,Clone)]
 pub enum Annotatable {
@@ -218,7 +219,6 @@ pub trait TTMacroExpander {
         ecx: &'cx mut ExtCtxt<'_>,
         span: Span,
         input: TokenStream,
-        def_span: Option<Span>,
     ) -> Box<dyn MacResult+'cx>;
 }
 
@@ -235,7 +235,6 @@ impl<F> TTMacroExpander for F
         ecx: &'cx mut ExtCtxt<'_>,
         span: Span,
         input: TokenStream,
-        _def_span: Option<Span>,
     ) -> Box<dyn MacResult+'cx> {
         struct AvoidInterpolatedIdents;
 
@@ -518,37 +517,6 @@ impl MacResult for DummyResult {
     }
 }
 
-/// Represents different kinds of macro invocations that can be resolved.
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum MacroKind {
-    /// A bang macro - foo!()
-    Bang,
-    /// An attribute macro - #[foo]
-    Attr,
-    /// A derive attribute macro - #[derive(Foo)]
-    Derive,
-    /// A view of a procedural macro from the same crate that defines it.
-    ProcMacroStub,
-}
-
-impl MacroKind {
-    pub fn descr(self) -> &'static str {
-        match self {
-            MacroKind::Bang => "macro",
-            MacroKind::Attr => "attribute macro",
-            MacroKind::Derive => "derive macro",
-            MacroKind::ProcMacroStub => "crate-local procedural macro",
-        }
-    }
-
-    pub fn article(self) -> &'static str {
-        match self {
-            MacroKind::Attr => "an",
-            _ => "a",
-        }
-    }
-}
-
 /// A syntax extension kind.
 pub enum SyntaxExtensionKind {
     /// A token-based function-like macro.
@@ -672,19 +640,31 @@ impl SyntaxExtension {
         }
     }
 
-    fn expn_format(&self, symbol: Symbol) -> ExpnFormat {
-        match self.kind {
-            SyntaxExtensionKind::Bang(..) |
-            SyntaxExtensionKind::LegacyBang(..) => ExpnFormat::MacroBang(symbol),
-            _ => ExpnFormat::MacroAttribute(symbol),
+    pub fn dummy_bang(edition: Edition) -> SyntaxExtension {
+        fn expander<'cx>(_: &'cx mut ExtCtxt<'_>, span: Span, _: &[TokenTree])
+                         -> Box<dyn MacResult + 'cx> {
+            DummyResult::any(span)
+        }
+        SyntaxExtension::default(SyntaxExtensionKind::LegacyBang(Box::new(expander)), edition)
+    }
+
+    pub fn dummy_derive(edition: Edition) -> SyntaxExtension {
+        fn expander(_: &mut ExtCtxt<'_>, _: Span, _: &ast::MetaItem, _: Annotatable)
+                    -> Vec<Annotatable> {
+            Vec::new()
         }
+        SyntaxExtension::default(SyntaxExtensionKind::Derive(Box::new(expander)), edition)
+    }
+
+    pub fn non_macro_attr(mark_used: bool, edition: Edition) -> SyntaxExtension {
+        SyntaxExtension::default(SyntaxExtensionKind::NonMacroAttr { mark_used }, edition)
     }
 
-    pub fn expn_info(&self, call_site: Span, format: &str) -> ExpnInfo {
+    pub fn expn_info(&self, call_site: Span, descr: Symbol) -> ExpnInfo {
         ExpnInfo {
             call_site,
-            format: self.expn_format(Symbol::intern(format)),
-            def_site: Some(self.span),
+            kind: ExpnKind::Macro(self.macro_kind(), descr),
+            def_site: self.span,
             default_transparency: self.default_transparency,
             allow_internal_unstable: self.allow_internal_unstable.clone(),
             allow_internal_unsafe: self.allow_internal_unsafe,
@@ -696,6 +676,9 @@ impl SyntaxExtension {
 
 pub type NamedSyntaxExtension = (Name, SyntaxExtension);
 
+/// Error type that denotes indeterminacy.
+pub struct Indeterminate;
+
 pub trait Resolver {
     fn next_node_id(&mut self) -> ast::NodeId;
 
@@ -709,26 +692,11 @@ pub trait Resolver {
     fn resolve_imports(&mut self);
 
     fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool)
-                                -> Result<Option<Lrc<SyntaxExtension>>, Determinacy>;
-    fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, invoc_id: Mark,
-                          derives_in_scope: Vec<ast::Path>, force: bool)
-                          -> Result<Lrc<SyntaxExtension>, Determinacy>;
+                                -> Result<Option<Lrc<SyntaxExtension>>, Indeterminate>;
 
     fn check_unused_macros(&self);
 }
 
-#[derive(Copy, Clone, PartialEq, Debug)]
-pub enum Determinacy {
-    Determined,
-    Undetermined,
-}
-
-impl Determinacy {
-    pub fn determined(determined: bool) -> Determinacy {
-        if determined { Determinacy::Determined } else { Determinacy::Undetermined }
-    }
-}
-
 #[derive(Clone)]
 pub struct ModuleData {
     pub mod_path: Vec<ast::Ident>,
@@ -753,6 +721,7 @@ pub struct ExtCtxt<'a> {
     pub resolver: &'a mut dyn Resolver,
     pub current_expansion: ExpansionData,
     pub expansions: FxHashMap<Span, Vec<String>>,
+    pub allow_derive_markers: Lrc<[Symbol]>,
 }
 
 impl<'a> ExtCtxt<'a> {
@@ -772,6 +741,7 @@ impl<'a> ExtCtxt<'a> {
                 directory_ownership: DirectoryOwnership::Owned { relative: None },
             },
             expansions: FxHashMap::default(),
+            allow_derive_markers: [sym::rustc_attrs, sym::structural_match][..].into(),
         }
     }
 
@@ -810,7 +780,7 @@ impl<'a> ExtCtxt<'a> {
         let mut last_macro = None;
         loop {
             if ctxt.outer_expn_info().map_or(None, |info| {
-                if info.format.name() == sym::include {
+                if info.kind.descr() == sym::include {
                     // Stop going up the backtrace once include! is encountered
                     return None;
                 }
diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs
index 2a56f3dd756..1c15deab373 100644
--- a/src/libsyntax/ext/derive.rs
+++ b/src/libsyntax/ext/derive.rs
@@ -1,14 +1,13 @@
 use crate::attr::HasAttrs;
 use crate::ast;
-use crate::source_map::{ExpnInfo, ExpnFormat};
-use crate::ext::base::ExtCtxt;
+use crate::source_map::{ExpnInfo, ExpnKind};
+use crate::ext::base::{ExtCtxt, MacroKind};
 use crate::ext::build::AstBuilder;
 use crate::parse::parser::PathStyle;
 use crate::symbol::{Symbol, sym};
 use crate::errors::Applicability;
 
 use syntax_pos::Span;
-
 use rustc_data_structures::fx::FxHashSet;
 
 pub fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>) -> Vec<ast::Path> {
@@ -46,7 +45,7 @@ pub fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>) ->
 pub fn add_derived_markers<T>(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::Path], item: &mut T)
     where T: HasAttrs,
 {
-    let (mut names, mut pretty_name) = (FxHashSet::default(), "derive(".to_owned());
+    let (mut names, mut pretty_name) = (FxHashSet::default(), String::new());
     for (i, path) in traits.iter().enumerate() {
         if i > 0 {
             pretty_name.push_str(", ");
@@ -54,14 +53,12 @@ pub fn add_derived_markers<T>(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::P
         pretty_name.push_str(&path.to_string());
         names.insert(unwrap_or!(path.segments.get(0), continue).ident.name);
     }
-    pretty_name.push(')');
 
-    cx.current_expansion.mark.set_expn_info(ExpnInfo::with_unstable(
-        ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)), span, cx.parse_sess.edition,
-        &[sym::rustc_attrs, sym::structural_match],
+    let span = span.fresh_expansion(cx.current_expansion.mark, ExpnInfo::allow_unstable(
+        ExpnKind::Macro(MacroKind::Derive, Symbol::intern(&pretty_name)), span,
+        cx.parse_sess.edition, cx.allow_derive_markers.clone(),
     ));
 
-    let span = span.with_ctxt(cx.backtrace());
     item.visit_attrs(|attrs| {
         if names.contains(&sym::Eq) && names.contains(&sym::PartialEq) {
             let meta = cx.meta_word(span, sym::structural_match);
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 053686b8b1f..7fc62e357c5 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -5,7 +5,7 @@ use crate::source_map::{dummy_spanned, respan};
 use crate::config::StripUnconfigured;
 use crate::ext::base::*;
 use crate::ext::derive::{add_derived_markers, collect_derives};
-use crate::ext::hygiene::{Mark, SyntaxContext};
+use crate::ext::hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnKind};
 use crate::ext::placeholders::{placeholder, PlaceholderExpander};
 use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
 use crate::mut_visit::*;
@@ -158,8 +158,8 @@ ast_fragments! {
 }
 
 impl AstFragmentKind {
-    fn dummy(self, span: Span) -> Option<AstFragment> {
-        self.make_from(DummyResult::any(span))
+    fn dummy(self, span: Span) -> AstFragment {
+        self.make_from(DummyResult::any(span)).expect("couldn't create a dummy AST fragment")
     }
 
     fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(self, items: I)
@@ -199,25 +199,34 @@ pub enum InvocationKind {
         span: Span,
     },
     Attr {
-        attr: Option<ast::Attribute>,
-        traits: Vec<Path>,
+        attr: ast::Attribute,
         item: Annotatable,
+        // Required for resolving derive helper attributes.
+        derives: Vec<Path>,
         // We temporarily report errors for attribute macros placed after derives
         after_derive: bool,
     },
     Derive {
         path: Path,
         item: Annotatable,
+        item_with_markers: Annotatable,
+    },
+    /// "Invocation" that contains all derives from an item,
+    /// broken into multiple `Derive` invocations when expanded.
+    /// FIXME: Find a way to remove it.
+    DeriveContainer {
+        derives: Vec<Path>,
+        item: Annotatable,
     },
 }
 
 impl Invocation {
     pub fn span(&self) -> Span {
-        match self.kind {
-            InvocationKind::Bang { span, .. } => span,
-            InvocationKind::Attr { attr: Some(ref attr), .. } => attr.span,
-            InvocationKind::Attr { attr: None, .. } => DUMMY_SP,
-            InvocationKind::Derive { ref path, .. } => path.span,
+        match &self.kind {
+            InvocationKind::Bang { span, .. } => *span,
+            InvocationKind::Attr { attr, .. } => attr.span,
+            InvocationKind::Derive { path, .. } => path.span,
+            InvocationKind::DeriveContainer { item, .. } => item.span(),
         }
     }
 }
@@ -312,9 +321,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             let scope =
                 if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark };
             let ext = match self.cx.resolver.resolve_macro_invocation(&invoc, scope, force) {
-                Ok(ext) => Some(ext),
-                Err(Determinacy::Determined) => None,
-                Err(Determinacy::Undetermined) => {
+                Ok(ext) => ext,
+                Err(Indeterminate) => {
                     undetermined_invocations.push(invoc);
                     continue
                 }
@@ -323,73 +331,62 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             progress = true;
             let ExpansionData { depth, mark, .. } = invoc.expansion_data;
             self.cx.current_expansion = invoc.expansion_data.clone();
-
             self.cx.current_expansion.mark = scope;
+
             // FIXME(jseyfried): Refactor out the following logic
             let (expanded_fragment, new_invocations) = if let Some(ext) = ext {
-                if let Some(ext) = ext {
-                    let (invoc_fragment_kind, invoc_span) = (invoc.fragment_kind, invoc.span());
-                    let fragment = self.expand_invoc(invoc, &*ext).unwrap_or_else(|| {
-                        invoc_fragment_kind.dummy(invoc_span).unwrap()
-                    });
-                    self.collect_invocations(fragment, &[])
-                } else if let InvocationKind::Attr { attr: None, traits, item, .. } = invoc.kind {
-                    if !item.derive_allowed() {
-                        let attr = attr::find_by_name(item.attrs(), sym::derive)
-                            .expect("`derive` attribute should exist");
-                        let span = attr.span;
-                        let mut err = self.cx.mut_span_err(span,
-                                                           "`derive` may only be applied to \
-                                                            structs, enums and unions");
-                        if let ast::AttrStyle::Inner = attr.style {
-                            let trait_list = traits.iter()
-                                .map(|t| t.to_string()).collect::<Vec<_>>();
-                            let suggestion = format!("#[derive({})]", trait_list.join(", "));
-                            err.span_suggestion(
-                                span, "try an outer attribute", suggestion,
-                                // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
-                                Applicability::MaybeIncorrect
-                            );
-                        }
-                        err.emit();
+                let fragment = self.expand_invoc(invoc, &ext.kind);
+                self.collect_invocations(fragment, &[])
+            } else if let InvocationKind::DeriveContainer { derives: traits, item } = invoc.kind {
+                if !item.derive_allowed() {
+                    let attr = attr::find_by_name(item.attrs(), sym::derive)
+                        .expect("`derive` attribute should exist");
+                    let span = attr.span;
+                    let mut err = self.cx.mut_span_err(span,
+                                                        "`derive` may only be applied to \
+                                                        structs, enums and unions");
+                    if let ast::AttrStyle::Inner = attr.style {
+                        let trait_list = traits.iter()
+                            .map(|t| t.to_string()).collect::<Vec<_>>();
+                        let suggestion = format!("#[derive({})]", trait_list.join(", "));
+                        err.span_suggestion(
+                            span, "try an outer attribute", suggestion,
+                            // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
+                            Applicability::MaybeIncorrect
+                        );
                     }
+                    err.emit();
+                }
 
-                    let mut item = self.fully_configure(item);
-                    item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive));
-                    let mut item_with_markers = item.clone();
-                    add_derived_markers(&mut self.cx, item.span(), &traits, &mut item_with_markers);
-                    let derives = derives.entry(invoc.expansion_data.mark).or_default();
-
-                    derives.reserve(traits.len());
-                    invocations.reserve(traits.len());
-                    for path in &traits {
-                        let mark = Mark::fresh(self.cx.current_expansion.mark);
-                        derives.push(mark);
-                        let item = match self.cx.resolver.resolve_macro_path(
-                                path, MacroKind::Derive, Mark::root(), Vec::new(), false) {
-                            Ok(ext) => match ext.kind {
-                                SyntaxExtensionKind::LegacyDerive(..) => item_with_markers.clone(),
-                                _ => item.clone(),
-                            },
-                            _ => item.clone(),
-                        };
-                        invocations.push(Invocation {
-                            kind: InvocationKind::Derive { path: path.clone(), item },
-                            fragment_kind: invoc.fragment_kind,
-                            expansion_data: ExpansionData {
-                                mark,
-                                ..invoc.expansion_data.clone()
-                            },
-                        });
-                    }
-                    let fragment = invoc.fragment_kind
-                        .expect_from_annotatables(::std::iter::once(item_with_markers));
-                    self.collect_invocations(fragment, derives)
-                } else {
-                    unreachable!()
+                let mut item = self.fully_configure(item);
+                item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive));
+                let mut item_with_markers = item.clone();
+                add_derived_markers(&mut self.cx, item.span(), &traits, &mut item_with_markers);
+                let derives = derives.entry(invoc.expansion_data.mark).or_default();
+
+                derives.reserve(traits.len());
+                invocations.reserve(traits.len());
+                for path in traits {
+                    let mark = Mark::fresh(self.cx.current_expansion.mark, None);
+                    derives.push(mark);
+                    invocations.push(Invocation {
+                        kind: InvocationKind::Derive {
+                            path,
+                            item: item.clone(),
+                            item_with_markers: item_with_markers.clone(),
+                        },
+                        fragment_kind: invoc.fragment_kind,
+                        expansion_data: ExpansionData {
+                            mark,
+                            ..invoc.expansion_data.clone()
+                        },
+                    });
                 }
+                let fragment = invoc.fragment_kind
+                    .expect_from_annotatables(::std::iter::once(item_with_markers));
+                self.collect_invocations(fragment, derives)
             } else {
-                self.collect_invocations(invoc.fragment_kind.dummy(invoc.span()).unwrap(), &[])
+                unreachable!()
             };
 
             if expanded_fragments.len() < depth {
@@ -485,28 +482,22 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         }
     }
 
-    fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option<AstFragment> {
-        if invoc.fragment_kind == AstFragmentKind::ForeignItems &&
-           !self.cx.ecfg.macros_in_extern() {
-            if let SyntaxExtensionKind::NonMacroAttr { .. } = ext.kind {} else {
+    fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment {
+        let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
+        if fragment_kind == AstFragmentKind::ForeignItems && !self.cx.ecfg.macros_in_extern() {
+            if let SyntaxExtensionKind::NonMacroAttr { .. } = ext {} else {
                 emit_feature_err(&self.cx.parse_sess, sym::macros_in_extern,
-                                 invoc.span(), GateIssue::Language,
+                                 span, GateIssue::Language,
                                  "macro invocations in `extern {}` blocks are experimental");
             }
         }
 
-        let result = match invoc.kind {
-            InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext)?,
-            InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext)?,
-            InvocationKind::Derive { .. } => self.expand_derive_invoc(invoc, ext)?,
-        };
-
         if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit {
             let info = self.cx.current_expansion.mark.expn_info().unwrap();
             let suggested_limit = self.cx.ecfg.recursion_limit * 2;
             let mut err = self.cx.struct_span_err(info.call_site,
                 &format!("recursion limit reached while expanding the macro `{}`",
-                         info.format.name()));
+                         info.kind.descr()));
             err.help(&format!(
                 "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
                 suggested_limit));
@@ -515,61 +506,87 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             FatalError.raise();
         }
 
-        Some(result)
-    }
-
-    fn expand_attr_invoc(&mut self,
-                         invoc: Invocation,
-                         ext: &SyntaxExtension)
-                         -> Option<AstFragment> {
-        let (attr, mut item) = match invoc.kind {
-            InvocationKind::Attr { attr, item, .. } => (attr?, item),
-            _ => unreachable!(),
-        };
-
-        match &ext.kind {
-            SyntaxExtensionKind::NonMacroAttr { mark_used } => {
-                attr::mark_known(&attr);
-                if *mark_used {
-                    attr::mark_used(&attr);
+        match invoc.kind {
+            InvocationKind::Bang { mac, .. } => match ext {
+                SyntaxExtensionKind::Bang(expander) => {
+                    self.gate_proc_macro_expansion_kind(span, fragment_kind);
+                    let tok_result = expander.expand(self.cx, span, mac.node.stream());
+                    let result =
+                        self.parse_ast_fragment(tok_result, fragment_kind, &mac.node.path, span);
+                    self.gate_proc_macro_expansion(span, &result);
+                    result
                 }
-                item.visit_attrs(|attrs| attrs.push(attr));
-                Some(invoc.fragment_kind.expect_from_annotatables(iter::once(item)))
-            }
-            SyntaxExtensionKind::LegacyAttr(expander) => {
-                let meta = attr.parse_meta(self.cx.parse_sess)
-                               .map_err(|mut e| { e.emit(); }).ok()?;
-                let item = expander.expand(self.cx, attr.span, &meta, item);
-                Some(invoc.fragment_kind.expect_from_annotatables(item))
-            }
-            SyntaxExtensionKind::Attr(expander) => {
-                self.gate_proc_macro_attr_item(attr.span, &item);
-                let item_tok = TokenTree::token(token::Interpolated(Lrc::new(match item {
-                    Annotatable::Item(item) => token::NtItem(item),
-                    Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()),
-                    Annotatable::ImplItem(item) => token::NtImplItem(item.into_inner()),
-                    Annotatable::ForeignItem(item) => token::NtForeignItem(item.into_inner()),
-                    Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
-                    Annotatable::Expr(expr) => token::NtExpr(expr),
-                })), DUMMY_SP).into();
-                let input = self.extract_proc_macro_attr_input(attr.tokens, attr.span);
-                let tok_result = expander.expand(self.cx, attr.span, input, item_tok);
-                let res = self.parse_ast_fragment(tok_result, invoc.fragment_kind,
-                                                  &attr.path, attr.span);
-                self.gate_proc_macro_expansion(attr.span, &res);
-                res
+                SyntaxExtensionKind::LegacyBang(expander) => {
+                    let tok_result = expander.expand(self.cx, span, mac.node.stream());
+                    if let Some(result) = fragment_kind.make_from(tok_result) {
+                        result
+                    } else {
+                        let msg = format!("non-{kind} macro in {kind} position: {path}",
+                                          kind = fragment_kind.name(), path = mac.node.path);
+                        self.cx.span_err(span, &msg);
+                        self.cx.trace_macros_diag();
+                        fragment_kind.dummy(span)
+                    }
+                }
+                _ => unreachable!()
             }
-            SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => {
-                self.cx.span_err(attr.span, &format!("`{}` is a derive macro", attr.path));
-                self.cx.trace_macros_diag();
-                invoc.fragment_kind.dummy(attr.span)
+            InvocationKind::Attr { attr, mut item, .. } => match ext {
+                SyntaxExtensionKind::Attr(expander) => {
+                    self.gate_proc_macro_attr_item(span, &item);
+                    let item_tok = TokenTree::token(token::Interpolated(Lrc::new(match item {
+                        Annotatable::Item(item) => token::NtItem(item),
+                        Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()),
+                        Annotatable::ImplItem(item) => token::NtImplItem(item.into_inner()),
+                        Annotatable::ForeignItem(item) => token::NtForeignItem(item.into_inner()),
+                        Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
+                        Annotatable::Expr(expr) => token::NtExpr(expr),
+                    })), DUMMY_SP).into();
+                    let input = self.extract_proc_macro_attr_input(attr.tokens, span);
+                    let tok_result = expander.expand(self.cx, span, input, item_tok);
+                    let res = self.parse_ast_fragment(tok_result, fragment_kind, &attr.path, span);
+                    self.gate_proc_macro_expansion(span, &res);
+                    res
+                }
+                SyntaxExtensionKind::LegacyAttr(expander) => {
+                    match attr.parse_meta(self.cx.parse_sess) {
+                        Ok(meta) => {
+                            let item = expander.expand(self.cx, span, &meta, item);
+                            fragment_kind.expect_from_annotatables(item)
+                        }
+                        Err(mut err) => {
+                            err.emit();
+                            fragment_kind.dummy(span)
+                        }
+                    }
+                }
+                SyntaxExtensionKind::NonMacroAttr { mark_used } => {
+                    attr::mark_known(&attr);
+                    if *mark_used {
+                        attr::mark_used(&attr);
+                    }
+                    item.visit_attrs(|attrs| attrs.push(attr));
+                    fragment_kind.expect_from_annotatables(iter::once(item))
+                }
+                _ => unreachable!()
             }
-            _ => {
-                let msg = &format!("macro `{}` may not be used in attributes", attr.path);
-                self.cx.span_err(attr.span, msg);
-                self.cx.trace_macros_diag();
-                invoc.fragment_kind.dummy(attr.span)
+            InvocationKind::Derive { path, item, item_with_markers } => match ext {
+                SyntaxExtensionKind::Derive(expander) |
+                SyntaxExtensionKind::LegacyDerive(expander) => {
+                    let (path, item) = match ext {
+                        SyntaxExtensionKind::LegacyDerive(..) => (path, item_with_markers),
+                        _ => (path, item),
+                    };
+                    if !item.derive_allowed() {
+                        return fragment_kind.dummy(span);
+                    }
+                    let meta = ast::MetaItem { node: ast::MetaItemKind::Word, span, path };
+                    let span = span.with_ctxt(self.cx.backtrace());
+                    let items = expander.expand(self.cx, span, &meta, item);
+                    fragment_kind.expect_from_annotatables(items)
+                }
+                _ => unreachable!()
             }
+            InvocationKind::DeriveContainer { .. } => unreachable!()
         }
     }
 
@@ -616,14 +633,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         );
     }
 
-    fn gate_proc_macro_expansion(&self, span: Span, fragment: &Option<AstFragment>) {
+    fn gate_proc_macro_expansion(&self, span: Span, fragment: &AstFragment) {
         if self.cx.ecfg.proc_macro_hygiene() {
             return
         }
-        let fragment = match fragment {
-            Some(fragment) => fragment,
-            None => return,
-        };
 
         fragment.visit_with(&mut DisallowMacros {
             span,
@@ -655,58 +668,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         }
     }
 
-    /// Expand a macro invocation. Returns the resulting expanded AST fragment.
-    fn expand_bang_invoc(&mut self,
-                         invoc: Invocation,
-                         ext: &SyntaxExtension)
-                         -> Option<AstFragment> {
-        let kind = invoc.fragment_kind;
-        let (mac, span) = match invoc.kind {
-            InvocationKind::Bang { mac, span } => (mac, span),
-            _ => unreachable!(),
-        };
-        let path = &mac.node.path;
-
-        let opt_expanded = match &ext.kind {
-            SyntaxExtensionKind::Bang(expander) => {
-                self.gate_proc_macro_expansion_kind(span, kind);
-                let tok_result = expander.expand(self.cx, span, mac.node.stream());
-                let result = self.parse_ast_fragment(tok_result, kind, path, span);
-                self.gate_proc_macro_expansion(span, &result);
-                result
-            }
-            SyntaxExtensionKind::LegacyBang(expander) => {
-                let tok_result = expander.expand(self.cx, span, mac.node.stream(), Some(ext.span));
-                kind.make_from(tok_result)
-            }
-
-            SyntaxExtensionKind::Attr(..) |
-            SyntaxExtensionKind::LegacyAttr(..) |
-            SyntaxExtensionKind::NonMacroAttr { .. } => {
-                self.cx.span_err(path.span,
-                                 &format!("`{}` can only be used in attributes", path));
-                self.cx.trace_macros_diag();
-                kind.dummy(span)
-            }
-
-            SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => {
-                self.cx.span_err(path.span, &format!("`{}` is a derive macro", path));
-                self.cx.trace_macros_diag();
-                kind.dummy(span)
-            }
-        };
-
-        if opt_expanded.is_some() {
-            opt_expanded
-        } else {
-            let msg = format!("non-{kind} macro in {kind} position: {name}",
-                              name = path.segments[0].ident.name, kind = kind.name());
-            self.cx.span_err(path.span, &msg);
-            self.cx.trace_macros_diag();
-            kind.dummy(span)
-        }
-    }
-
     fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
         let kind = match kind {
             AstFragmentKind::Expr => "expressions",
@@ -731,47 +692,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         );
     }
 
-    /// Expand a derive invocation. Returns the resulting expanded AST fragment.
-    fn expand_derive_invoc(&mut self,
-                           invoc: Invocation,
-                           ext: &SyntaxExtension)
-                           -> Option<AstFragment> {
-        let (path, item) = match invoc.kind {
-            InvocationKind::Derive { path, item } => (path, item),
-            _ => unreachable!(),
-        };
-        if !item.derive_allowed() {
-            return None;
-        }
-
-        match &ext.kind {
-            SyntaxExtensionKind::Derive(expander) |
-            SyntaxExtensionKind::LegacyDerive(expander) => {
-                let meta = ast::MetaItem { node: ast::MetaItemKind::Word, span: path.span, path };
-                let span = meta.span.with_ctxt(self.cx.backtrace());
-                let items = expander.expand(self.cx, span, &meta, item);
-                Some(invoc.fragment_kind.expect_from_annotatables(items))
-            }
-            _ => {
-                let msg = &format!("macro `{}` may not be used for derive attributes", path);
-                self.cx.span_err(path.span, msg);
-                self.cx.trace_macros_diag();
-                invoc.fragment_kind.dummy(path.span)
-            }
-        }
-    }
-
     fn parse_ast_fragment(&mut self,
                           toks: TokenStream,
                           kind: AstFragmentKind,
                           path: &Path,
                           span: Span)
-                          -> Option<AstFragment> {
+                          -> AstFragment {
         let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::<Vec<_>>());
         match parser.parse_ast_fragment(kind, false) {
             Ok(fragment) => {
                 parser.ensure_complete_parse(path, kind.name(), span);
-                Some(fragment)
+                fragment
             }
             Err(mut err) => {
                 err.set_span(span);
@@ -881,7 +812,17 @@ struct InvocationCollector<'a, 'b> {
 
 impl<'a, 'b> InvocationCollector<'a, 'b> {
     fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
-        let mark = Mark::fresh(self.cx.current_expansion.mark);
+        // Expansion info for all the collected invocations is set upon their resolution,
+        // with exception of the derive container case which is not resolved and can get
+        // its expansion info immediately.
+        let expn_info = match &kind {
+            InvocationKind::DeriveContainer { item, .. } => Some(ExpnInfo::default(
+                ExpnKind::Macro(MacroKind::Attr, sym::derive),
+                item.span(), self.cx.parse_sess.edition,
+            )),
+            _ => None,
+        };
+        let mark = Mark::fresh(self.cx.current_expansion.mark, expn_info);
         self.invocations.push(Invocation {
             kind,
             fragment_kind,
@@ -900,12 +841,15 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
 
     fn collect_attr(&mut self,
                     attr: Option<ast::Attribute>,
-                    traits: Vec<Path>,
+                    derives: Vec<Path>,
                     item: Annotatable,
                     kind: AstFragmentKind,
                     after_derive: bool)
                     -> AstFragment {
-        self.collect(kind, InvocationKind::Attr { attr, traits, item, after_derive })
+        self.collect(kind, match attr {
+            Some(attr) => InvocationKind::Attr { attr, item, derives, after_derive },
+            None => InvocationKind::DeriveContainer { derives, item },
+        })
     }
 
     fn find_attr_invoc(&self, attrs: &mut Vec<ast::Attribute>, after_derive: &mut bool)
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 665c794422d..5c6438a7ef5 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -88,6 +88,7 @@ impl<'a> ParserAnyMacro<'a> {
 
 struct MacroRulesMacroExpander {
     name: ast::Ident,
+    span: Span,
     lhses: Vec<quoted::TokenTree>,
     rhses: Vec<quoted::TokenTree>,
     valid: bool,
@@ -99,12 +100,11 @@ impl TTMacroExpander for MacroRulesMacroExpander {
         cx: &'cx mut ExtCtxt<'_>,
         sp: Span,
         input: TokenStream,
-        def_span: Option<Span>,
     ) -> Box<dyn MacResult + 'cx> {
         if !self.valid {
             return DummyResult::any(sp);
         }
-        generic_extension(cx, sp, def_span, self.name, input, &self.lhses, &self.rhses)
+        generic_extension(cx, sp, self.span, self.name, input, &self.lhses, &self.rhses)
     }
 }
 
@@ -117,7 +117,7 @@ fn trace_macros_note(cx: &mut ExtCtxt<'_>, sp: Span, message: String) {
 fn generic_extension<'cx>(
     cx: &'cx mut ExtCtxt<'_>,
     sp: Span,
-    def_span: Option<Span>,
+    def_span: Span,
     name: ast::Ident,
     arg: TokenStream,
     lhses: &[quoted::TokenTree],
@@ -199,10 +199,8 @@ fn generic_extension<'cx>(
     let span = token.span.substitute_dummy(sp);
     let mut err = cx.struct_span_err(span, &parse_failure_msg(&token));
     err.span_label(span, label);
-    if let Some(sp) = def_span {
-        if cx.source_map().span_to_filename(sp).is_real() && !sp.is_dummy() {
-            err.span_label(cx.source_map().def_span(sp), "when calling this macro");
-        }
+    if !def_span.is_dummy() && cx.source_map().span_to_filename(def_span).is_real() {
+        err.span_label(cx.source_map().def_span(def_span), "when calling this macro");
     }
 
     // Check whether there's a missing comma in this macro call, like `println!("{}" a);`
@@ -377,7 +375,7 @@ pub fn compile(
     }
 
     let expander: Box<_> =
-        Box::new(MacroRulesMacroExpander { name: def.ident, lhses, rhses, valid });
+        Box::new(MacroRulesMacroExpander { name: def.ident, span: def.span, lhses, rhses, valid });
 
     let (default_transparency, transparency_error) =
         attr::find_transparency(&def.attrs, body.legacy);
diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs
index 767ab74355e..ec0222d90eb 100644
--- a/src/libsyntax/json.rs
+++ b/src/libsyntax/json.rs
@@ -170,7 +170,7 @@ struct DiagnosticSpanMacroExpansion {
     macro_decl_name: String,
 
     /// span where macro was defined (if known)
-    def_site_span: Option<DiagnosticSpan>,
+    def_site_span: DiagnosticSpan,
 }
 
 #[derive(RustcEncodable)]
@@ -300,14 +300,13 @@ impl DiagnosticSpan {
                                      None,
                                      backtrace,
                                      je);
-            let def_site_span = bt.def_site_span.map(|sp| {
-                Self::from_span_full(sp,
+            let def_site_span =
+                Self::from_span_full(bt.def_site_span,
                                      false,
                                      None,
                                      None,
                                      vec![].into_iter(),
-                                     je)
-            });
+                                     je);
             Box::new(DiagnosticSpanMacroExpansion {
                 span: call_site,
                 macro_decl_name: bt.macro_decl_name,
diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs
index ac30cbb471a..bbf62ef1e23 100644
--- a/src/libsyntax/source_map.rs
+++ b/src/libsyntax/source_map.rs
@@ -7,10 +7,8 @@
 //! within the SourceMap, which upon request can be converted to line and column
 //! information, source code snippets, etc.
 
-
 pub use syntax_pos::*;
-pub use syntax_pos::hygiene::{ExpnFormat, ExpnInfo};
-pub use ExpnFormat::*;
+pub use syntax_pos::hygiene::{ExpnKind, ExpnInfo};
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::StableHasher;
diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs
index 6630bf90815..d86b76f71ec 100644
--- a/src/libsyntax/std_inject.rs
+++ b/src/libsyntax/std_inject.rs
@@ -1,26 +1,15 @@
 use crate::ast;
 use crate::attr;
 use crate::edition::Edition;
-use crate::ext::hygiene::{Mark, SyntaxContext};
+use crate::ext::hygiene::{Mark, MacroKind};
 use crate::symbol::{Ident, Symbol, kw, sym};
-use crate::source_map::{ExpnInfo, MacroAttribute, dummy_spanned, respan};
+use crate::source_map::{ExpnInfo, ExpnKind, dummy_spanned, respan};
 use crate::ptr::P;
 use crate::tokenstream::TokenStream;
 
 use std::cell::Cell;
 use std::iter;
-use syntax_pos::{DUMMY_SP, Span};
-
-/// Craft a span that will be ignored by the stability lint's
-/// call to source_map's `is_internal` check.
-/// The expanded code uses the unstable `#[prelude_import]` attribute.
-fn ignored_span(sp: Span, edition: Edition) -> Span {
-    let mark = Mark::fresh(Mark::root());
-    mark.set_expn_info(ExpnInfo::with_unstable(
-        MacroAttribute(Symbol::intern("std_inject")), sp, edition, &[sym::prelude_import]
-    ));
-    sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))
-}
+use syntax_pos::DUMMY_SP;
 
 pub fn injected_crate_name() -> Option<&'static str> {
     INJECTED_CRATE_NAME.with(|name| name.get())
@@ -86,7 +75,11 @@ pub fn maybe_inject_crates_ref(
 
     INJECTED_CRATE_NAME.with(|opt_name| opt_name.set(Some(name)));
 
-    let span = ignored_span(DUMMY_SP, edition);
+    let span = DUMMY_SP.fresh_expansion(Mark::root(), ExpnInfo::allow_unstable(
+        ExpnKind::Macro(MacroKind::Attr, sym::std_inject), DUMMY_SP, edition,
+        [sym::prelude_import][..].into(),
+    ));
+
     krate.module.items.insert(0, P(ast::Item {
         attrs: vec![ast::Attribute {
             style: ast::AttrStyle::Outer,
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index c717f140ca3..799d64a9962 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -15,13 +15,13 @@ use smallvec::{smallvec, SmallVec};
 use syntax_pos::{DUMMY_SP, NO_EXPANSION, Span, SourceFile, BytePos};
 
 use crate::attr::{self, HasAttrs};
-use crate::source_map::{self, SourceMap, ExpnInfo, MacroAttribute, dummy_spanned, respan};
+use crate::source_map::{self, SourceMap, ExpnInfo, ExpnKind, dummy_spanned, respan};
 use crate::config;
 use crate::entry::{self, EntryPointType};
 use crate::ext::base::{ExtCtxt, Resolver};
 use crate::ext::build::AstBuilder;
 use crate::ext::expand::ExpansionConfig;
-use crate::ext::hygiene::{self, Mark, SyntaxContext};
+use crate::ext::hygiene::{self, Mark, SyntaxContext, MacroKind};
 use crate::mut_visit::{*, ExpectOne};
 use crate::feature_gate::Features;
 use crate::util::map_in_place::MapInPlace;
@@ -43,7 +43,6 @@ struct TestCtxt<'a> {
     test_cases: Vec<Test>,
     reexport_test_harness_main: Option<Symbol>,
     is_libtest: bool,
-    ctxt: SyntaxContext,
     features: &'a Features,
     test_runner: Option<ast::Path>,
 
@@ -259,8 +258,6 @@ fn generate_test_harness(sess: &ParseSess,
     let mut cleaner = EntryPointCleaner { depth: 0 };
     cleaner.visit_crate(krate);
 
-    let mark = Mark::fresh(Mark::root());
-
     let mut econfig = ExpansionConfig::default("test".to_string());
     econfig.features = Some(features);
 
@@ -274,16 +271,10 @@ fn generate_test_harness(sess: &ParseSess,
         is_libtest: attr::find_crate_name(&krate.attrs)
             .map(|s| s == sym::test).unwrap_or(false),
         toplevel_reexport: None,
-        ctxt: SyntaxContext::empty().apply_mark(mark),
         features,
         test_runner
     };
 
-    mark.set_expn_info(ExpnInfo::with_unstable(
-        MacroAttribute(sym::test_case), DUMMY_SP, sess.edition,
-        &[sym::main, sym::test, sym::rustc_attrs],
-    ));
-
     TestHarnessGenerator {
         cx,
         tests: Vec::new(),
@@ -291,13 +282,6 @@ fn generate_test_harness(sess: &ParseSess,
     }.visit_crate(krate);
 }
 
-/// Craft a span that will be ignored by the stability lint's
-/// call to source_map's `is_internal` check.
-/// The expanded code calls some unstable functions in the test crate.
-fn ignored_span(cx: &TestCtxt<'_>, sp: Span) -> Span {
-    sp.with_ctxt(cx.ctxt)
-}
-
 enum HasTestSignature {
     Yes,
     No(BadTestSignature),
@@ -314,12 +298,15 @@ enum BadTestSignature {
 /// Creates a function item for use as the main function of a test build.
 /// This function will call the `test_runner` as specified by the crate attribute
 fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
-    // Writing this out by hand with 'ignored_span':
+    // Writing this out by hand:
     //        pub fn main() {
     //            #![main]
     //            test::test_main_static(&[..tests]);
     //        }
-    let sp = ignored_span(cx, DUMMY_SP);
+    let sp = DUMMY_SP.fresh_expansion(Mark::root(), ExpnInfo::allow_unstable(
+        ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, cx.ext_cx.parse_sess.edition,
+        [sym::main, sym::test, sym::rustc_attrs][..].into(),
+    ));
     let ecx = &cx.ext_cx;
     let test_id = Ident::with_empty_ctxt(sym::test);
 
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index 62530f4fe7b..da0f8ca6da0 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -72,6 +72,7 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
     let mut register = |name, ext| {
         resolver.add_builtin(ast::Ident::with_empty_ctxt(name), Lrc::new(ext));
     };
+
     macro_rules! register {
         ($( $name:ident: $f:expr, )*) => { $(
             register(sym::$name, SyntaxExtension::default(
@@ -125,24 +126,31 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
         trace_macros: trace_macros::expand_trace_macros,
     }
 
+    let allow_internal_unstable = Some([sym::test, sym::rustc_attrs][..].into());
     register(sym::test_case, SyntaxExtension {
         stability: Some(Stability::unstable(
             sym::custom_test_frameworks,
             Some(Symbol::intern(EXPLAIN_CUSTOM_TEST_FRAMEWORKS)),
             50297,
         )),
+        allow_internal_unstable: allow_internal_unstable.clone(),
         ..SyntaxExtension::default(
             SyntaxExtensionKind::LegacyAttr(Box::new(test_case::expand)), edition
         )
     });
-    register(sym::test, SyntaxExtension::default(
-        SyntaxExtensionKind::LegacyAttr(Box::new(test::expand_test)), edition
-    ));
-    register(sym::bench, SyntaxExtension::default(
-        SyntaxExtensionKind::LegacyAttr(Box::new(test::expand_bench)), edition
-    ));
-
-    // format_args uses `unstable` things internally.
+    register(sym::test, SyntaxExtension {
+        allow_internal_unstable: allow_internal_unstable.clone(),
+        ..SyntaxExtension::default(
+            SyntaxExtensionKind::LegacyAttr(Box::new(test::expand_test)), edition
+        )
+    });
+    register(sym::bench, SyntaxExtension {
+        allow_internal_unstable,
+        ..SyntaxExtension::default(
+            SyntaxExtensionKind::LegacyAttr(Box::new(test::expand_bench)), edition
+        )
+    });
+
     let allow_internal_unstable = Some([sym::fmt_internals][..].into());
     register(sym::format_args, SyntaxExtension {
         allow_internal_unstable: allow_internal_unstable.clone(),
diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs
index 45e65288a24..2f78644dff2 100644
--- a/src/libsyntax_ext/proc_macro_decls.rs
+++ b/src/libsyntax_ext/proc_macro_decls.rs
@@ -4,8 +4,8 @@ use crate::deriving;
 
 use syntax::ast::{self, Ident};
 use syntax::attr;
-use syntax::source_map::{ExpnInfo, MacroAttribute, respan};
-use syntax::ext::base::ExtCtxt;
+use syntax::source_map::{ExpnInfo, ExpnKind, respan};
+use syntax::ext::base::{ExtCtxt, MacroKind};
 use syntax::ext::build::AstBuilder;
 use syntax::ext::expand::ExpansionConfig;
 use syntax::ext::hygiene::Mark;
@@ -346,12 +346,10 @@ fn mk_decls(
     custom_attrs: &[ProcMacroDef],
     custom_macros: &[ProcMacroDef],
 ) -> P<ast::Item> {
-    let mark = Mark::fresh(Mark::root());
-    mark.set_expn_info(ExpnInfo::with_unstable(
-        MacroAttribute(sym::proc_macro), DUMMY_SP, cx.parse_sess.edition,
-        &[sym::rustc_attrs, Symbol::intern("proc_macro_internals")],
+    let span = DUMMY_SP.fresh_expansion(Mark::root(), ExpnInfo::allow_unstable(
+        ExpnKind::Macro(MacroKind::Attr, sym::proc_macro), DUMMY_SP, cx.parse_sess.edition,
+        [sym::rustc_attrs, sym::proc_macro_internals][..].into(),
     ));
-    let span = DUMMY_SP.apply_mark(mark);
 
     let hidden = cx.meta_list_item_word(span, sym::hidden);
     let doc = cx.meta_list(span, sym::doc, vec![hidden]);
diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs
index 24d3055e711..c5c5ef57b31 100644
--- a/src/libsyntax_ext/test.rs
+++ b/src/libsyntax_ext/test.rs
@@ -3,13 +3,12 @@
 
 use syntax::ext::base::*;
 use syntax::ext::build::AstBuilder;
-use syntax::ext::hygiene::{Mark, SyntaxContext};
+use syntax::ext::hygiene::SyntaxContext;
 use syntax::attr;
 use syntax::ast;
 use syntax::print::pprust;
 use syntax::symbol::{Symbol, sym};
 use syntax_pos::Span;
-use syntax::source_map::{ExpnInfo, MacroAttribute};
 use std::iter;
 
 pub fn expand_test(
@@ -60,15 +59,8 @@ pub fn expand_test_or_bench(
         return vec![Annotatable::Item(item)];
     }
 
-    let (sp, attr_sp) = {
-        let mark = Mark::fresh(Mark::root());
-        mark.set_expn_info(ExpnInfo::with_unstable(
-            MacroAttribute(sym::test), attr_sp, cx.parse_sess.edition,
-            &[sym::rustc_attrs, sym::test],
-        ));
-        (item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark)),
-         attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(mark)))
-    };
+    let ctxt = SyntaxContext::empty().apply_mark(cx.current_expansion.mark);
+    let (sp, attr_sp) = (item.span.with_ctxt(ctxt), attr_sp.with_ctxt(ctxt));
 
     // Gensym "test" so we can extern crate without conflicting with any local names
     let test_id = cx.ident_of("test").gensym();
diff --git a/src/libsyntax_ext/test_case.rs b/src/libsyntax_ext/test_case.rs
index 186673c142f..af2cf42e04b 100644
--- a/src/libsyntax_ext/test_case.rs
+++ b/src/libsyntax_ext/test_case.rs
@@ -11,12 +11,11 @@
 
 use syntax::ext::base::*;
 use syntax::ext::build::AstBuilder;
-use syntax::ext::hygiene::{Mark, SyntaxContext};
+use syntax::ext::hygiene::SyntaxContext;
 use syntax::ast;
 use syntax::source_map::respan;
 use syntax::symbol::sym;
 use syntax_pos::Span;
-use syntax::source_map::{ExpnInfo, MacroAttribute};
 
 pub fn expand(
     ecx: &mut ExtCtxt<'_>,
@@ -26,17 +25,8 @@ pub fn expand(
 ) -> Vec<Annotatable> {
     if !ecx.ecfg.should_test { return vec![]; }
 
-    let sp = {
-        let mark = Mark::fresh(Mark::root());
-        mark.set_expn_info(ExpnInfo::with_unstable(
-            MacroAttribute(sym::test_case), attr_sp, ecx.parse_sess.edition,
-            &[sym::test, sym::rustc_attrs],
-        ));
-        attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))
-    };
-
+    let sp = attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(ecx.current_expansion.mark));
     let mut item = anno_item.expect_item();
-
     item = item.map(|mut item| {
         item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
         item.ident = item.ident.gensym();
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index f52952ca402..5df14439230 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -26,20 +26,20 @@
 // trigger runtime aborts. (Fortunately these are obvious and easy to fix.)
 
 use crate::GLOBALS;
-use crate::Span;
+use crate::{Span, DUMMY_SP};
 use crate::edition::Edition;
 use crate::symbol::{kw, Symbol};
 
 use serialize::{Encodable, Decodable, Encoder, Decoder};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use std::fmt;
 
 /// A SyntaxContext represents a chain of macro expansions (represented by marks).
-#[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct SyntaxContext(u32);
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Debug)]
 struct SyntaxContextData {
     outer_mark: Mark,
     transparency: Transparency,
@@ -53,12 +53,15 @@ struct SyntaxContextData {
 }
 
 /// A mark is a unique ID associated with a macro expansion.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
 pub struct Mark(u32);
 
-#[derive(Clone, Debug)]
+#[derive(Debug)]
 struct MarkData {
     parent: Mark,
+    /// Each mark should have an associated expansion info, but sometimes there's a delay between
+    /// creation of a mark and obtaining its info (e.g. macros are collected first and then
+    /// resolved later), so we use an `Option` here.
     expn_info: Option<ExpnInfo>,
 }
 
@@ -82,11 +85,8 @@ pub enum Transparency {
 }
 
 impl Mark {
-    pub fn fresh(parent: Mark) -> Self {
-        HygieneData::with(|data| {
-            data.marks.push(MarkData { parent, expn_info: None });
-            Mark(data.marks.len() as u32 - 1)
-        })
+    pub fn fresh(parent: Mark, expn_info: Option<ExpnInfo>) -> Self {
+        HygieneData::with(|data| data.fresh_mark(parent, expn_info))
     }
 
     /// The mark of the theoretical expansion that generates freshly parsed, unexpanded AST.
@@ -117,7 +117,11 @@ impl Mark {
 
     #[inline]
     pub fn set_expn_info(self, info: ExpnInfo) {
-        HygieneData::with(|data| data.marks[self.0 as usize].expn_info = Some(info))
+        HygieneData::with(|data| {
+            let old_info = &mut data.marks[self.0 as usize].expn_info;
+            assert!(old_info.is_none(), "expansion info is reset for a mark");
+            *old_info = Some(info);
+        })
     }
 
     pub fn is_descendant_of(self, ancestor: Mark) -> bool {
@@ -130,42 +134,14 @@ impl Mark {
         HygieneData::with(|data| data.is_descendant_of(self, data.outer(ctxt)))
     }
 
-    /// Computes a mark such that both input marks are descendants of (or equal to) the returned
-    /// mark. That is, the following holds:
-    ///
-    /// ```rust
-    /// let la = least_ancestor(a, b);
-    /// assert!(a.is_descendant_of(la))
-    /// assert!(b.is_descendant_of(la))
-    /// ```
-    pub fn least_ancestor(mut a: Mark, mut b: Mark) -> Mark {
-        HygieneData::with(|data| {
-            // Compute the path from a to the root
-            let mut a_path = FxHashSet::<Mark>::default();
-            while a != Mark::root() {
-                a_path.insert(a);
-                a = data.marks[a.0 as usize].parent;
-            }
-
-            // While the path from b to the root hasn't intersected, move up the tree
-            while !a_path.contains(&b) {
-                b = data.marks[b.0 as usize].parent;
-            }
-
-            b
-        })
-    }
-
     // Used for enabling some compatibility fallback in resolve.
     #[inline]
     pub fn looks_like_proc_macro_derive(self) -> bool {
         HygieneData::with(|data| {
             if data.default_transparency(self) == Transparency::Opaque {
-                if let Some(expn_info) = &data.marks[self.0 as usize].expn_info {
-                    if let ExpnFormat::MacroAttribute(name) = expn_info.format {
-                        if name.as_str().starts_with("derive(") {
-                            return true;
-                        }
+                if let Some(expn_info) = data.expn_info(self) {
+                    if let ExpnKind::Macro(MacroKind::Derive, _) = expn_info.kind {
+                        return true;
                     }
                 }
             }
@@ -182,11 +158,11 @@ crate struct HygieneData {
 }
 
 impl HygieneData {
-    crate fn new() -> Self {
+    crate fn new(edition: Edition) -> Self {
         HygieneData {
             marks: vec![MarkData {
                 parent: Mark::root(),
-                expn_info: None,
+                expn_info: Some(ExpnInfo::default(ExpnKind::Root, DUMMY_SP, edition)),
             }],
             syntax_contexts: vec![SyntaxContextData {
                 outer_mark: Mark::root(),
@@ -204,8 +180,21 @@ impl HygieneData {
         GLOBALS.with(|globals| f(&mut *globals.hygiene_data.borrow_mut()))
     }
 
+    fn fresh_mark(&mut self, parent: Mark, expn_info: Option<ExpnInfo>) -> Mark {
+        self.marks.push(MarkData { parent, expn_info });
+        Mark(self.marks.len() as u32 - 1)
+    }
+
     fn expn_info(&self, mark: Mark) -> Option<&ExpnInfo> {
-        self.marks[mark.0 as usize].expn_info.as_ref()
+        if mark != Mark::root() {
+            Some(self.marks[mark.0 as usize].expn_info.as_ref()
+                     .expect("no expansion info for a mark"))
+        } else {
+            // FIXME: Some code relies on `expn_info().is_none()` meaning "no expansion".
+            // Introduce a method for checking for "no expansion" instead and always return
+            // `ExpnInfo` from this function instead of the `Option`.
+            None
+        }
     }
 
     fn is_descendant_of(&self, mut mark: Mark, ancestor: Mark) -> bool {
@@ -219,7 +208,7 @@ impl HygieneData {
     }
 
     fn default_transparency(&self, mark: Mark) -> Transparency {
-        self.marks[mark.0 as usize].expn_info.as_ref().map_or(
+        self.expn_info(mark).map_or(
             Transparency::SemiTransparent, |einfo| einfo.default_transparency
         )
     }
@@ -420,33 +409,6 @@ impl SyntaxContext {
         SyntaxContext(raw)
     }
 
-    // Allocate a new SyntaxContext with the given ExpnInfo. This is used when
-    // deserializing Spans from the incr. comp. cache.
-    // FIXME(mw): This method does not restore MarkData::parent or
-    // SyntaxContextData::prev_ctxt or SyntaxContextData::opaque. These things
-    // don't seem to be used after HIR lowering, so everything should be fine
-    // as long as incremental compilation does not kick in before that.
-    pub fn allocate_directly(expansion_info: ExpnInfo) -> Self {
-        HygieneData::with(|data| {
-            data.marks.push(MarkData {
-                parent: Mark::root(),
-                expn_info: Some(expansion_info),
-            });
-
-            let mark = Mark(data.marks.len() as u32 - 1);
-
-            data.syntax_contexts.push(SyntaxContextData {
-                outer_mark: mark,
-                transparency: Transparency::SemiTransparent,
-                prev_ctxt: SyntaxContext::empty(),
-                opaque: SyntaxContext::empty(),
-                opaque_and_semitransparent: SyntaxContext::empty(),
-                dollar_crate_name: kw::DollarCrate,
-            });
-            SyntaxContext(data.syntax_contexts.len() as u32 - 1)
-        })
-    }
-
     /// Extend a syntax context with a given mark and default transparency for that mark.
     pub fn apply_mark(self, mark: Mark) -> SyntaxContext {
         HygieneData::with(|data| data.apply_mark(self, mark))
@@ -639,8 +601,23 @@ impl fmt::Debug for SyntaxContext {
     }
 }
 
-/// Extra information for tracking spans of macro and syntax sugar expansion
-#[derive(Clone, Hash, Debug, RustcEncodable, RustcDecodable)]
+impl Span {
+    /// Creates a fresh expansion with given properties.
+    /// Expansions are normally created by macros, but in some cases expansions are created for
+    /// other compiler-generated code to set per-span properties like allowed unstable features.
+    /// The returned span belongs to the created expansion and has the new properties,
+    /// but its location is inherited from the current span.
+    pub fn fresh_expansion(self, parent: Mark, expn_info: ExpnInfo) -> Span {
+        HygieneData::with(|data| {
+            let mark = data.fresh_mark(parent, Some(expn_info));
+            self.with_ctxt(data.apply_mark(SyntaxContext::empty(), mark))
+        })
+    }
+}
+
+/// A subset of properties from both macro definition and macro call available through global data.
+/// Avoid using this if you have access to the original definition or call structures.
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub struct ExpnInfo {
     // --- The part unique to each expansion.
     /// The location of the actual macro invocation or syntax sugar , e.g.
@@ -653,16 +630,14 @@ pub struct ExpnInfo {
     /// call_site span would have its own ExpnInfo, with the call_site
     /// pointing to the `foo!` invocation.
     pub call_site: Span,
-    /// The format with which the macro was invoked.
-    pub format: ExpnFormat,
+    /// The kind of this expansion - macro or compiler desugaring.
+    pub kind: ExpnKind,
 
     // --- The part specific to the macro/desugaring definition.
     // --- FIXME: Share it between expansions with the same definition.
-    /// The span of the macro definition itself. The macro may not
-    /// have a sensible definition span (e.g., something defined
-    /// completely inside libsyntax) in which case this is None.
+    /// The span of the macro definition (possibly dummy).
     /// This span serves only informational purpose and is not used for resolution.
-    pub def_site: Option<Span>,
+    pub def_site: Span,
     /// Transparency used by `apply_mark` for mark with this expansion info by default.
     pub default_transparency: Transparency,
     /// List of #[unstable]/feature-gated features that the macro is allowed to use
@@ -681,11 +656,11 @@ pub struct ExpnInfo {
 
 impl ExpnInfo {
     /// Constructs an expansion info with default properties.
-    pub fn default(format: ExpnFormat, call_site: Span, edition: Edition) -> ExpnInfo {
+    pub fn default(kind: ExpnKind, call_site: Span, edition: Edition) -> ExpnInfo {
         ExpnInfo {
             call_site,
-            format,
-            def_site: None,
+            kind,
+            def_site: DUMMY_SP,
             default_transparency: Transparency::SemiTransparent,
             allow_internal_unstable: None,
             allow_internal_unsafe: false,
@@ -694,38 +669,68 @@ impl ExpnInfo {
         }
     }
 
-    pub fn with_unstable(format: ExpnFormat, call_site: Span, edition: Edition,
-                         allow_internal_unstable: &[Symbol]) -> ExpnInfo {
+    pub fn allow_unstable(kind: ExpnKind, call_site: Span, edition: Edition,
+                          allow_internal_unstable: Lrc<[Symbol]>) -> ExpnInfo {
         ExpnInfo {
-            allow_internal_unstable: Some(allow_internal_unstable.into()),
-            ..ExpnInfo::default(format, call_site, edition)
+            allow_internal_unstable: Some(allow_internal_unstable),
+            ..ExpnInfo::default(kind, call_site, edition)
         }
     }
 }
 
-/// The source of expansion.
-#[derive(Clone, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
-pub enum ExpnFormat {
-    /// e.g., #[derive(...)] <item>
-    MacroAttribute(Symbol),
-    /// e.g., `format!()`
-    MacroBang(Symbol),
+/// Expansion kind.
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+pub enum ExpnKind {
+    /// No expansion, aka root expansion. Only `Mark::root()` has this kind.
+    Root,
+    /// Expansion produced by a macro.
+    /// FIXME: Some code injected by the compiler before HIR lowering also gets this kind.
+    Macro(MacroKind, Symbol),
     /// Desugaring done by the compiler during HIR lowering.
-    CompilerDesugaring(CompilerDesugaringKind)
+    Desugaring(DesugaringKind)
 }
 
-impl ExpnFormat {
-    pub fn name(&self) -> Symbol {
+impl ExpnKind {
+    pub fn descr(&self) -> Symbol {
         match *self {
-            ExpnFormat::MacroBang(name) | ExpnFormat::MacroAttribute(name) => name,
-            ExpnFormat::CompilerDesugaring(kind) => kind.name(),
+            ExpnKind::Root => kw::PathRoot,
+            ExpnKind::Macro(_, descr) => descr,
+            ExpnKind::Desugaring(kind) => Symbol::intern(kind.descr()),
+        }
+    }
+}
+
+/// The kind of macro invocation or definition.
+#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum MacroKind {
+    /// A bang macro `foo!()`.
+    Bang,
+    /// An attribute macro `#[foo]`.
+    Attr,
+    /// A derive macro `#[derive(Foo)]`
+    Derive,
+}
+
+impl MacroKind {
+    pub fn descr(self) -> &'static str {
+        match self {
+            MacroKind::Bang => "macro",
+            MacroKind::Attr => "attribute macro",
+            MacroKind::Derive => "derive macro",
+        }
+    }
+
+    pub fn article(self) -> &'static str {
+        match self {
+            MacroKind::Attr => "an",
+            _ => "a",
         }
     }
 }
 
 /// The kind of compiler desugaring.
-#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
-pub enum CompilerDesugaringKind {
+#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable)]
+pub enum DesugaringKind {
     /// We desugar `if c { i } else { e }` to `match $ExprKind::Use(c) { true => i, _ => e }`.
     /// However, we do not want to blame `c` for unreachability but rather say that `i`
     /// is unreachable. This desugaring kind allows us to avoid blaming `c`.
@@ -742,17 +747,18 @@ pub enum CompilerDesugaringKind {
     ForLoop,
 }
 
-impl CompilerDesugaringKind {
-    pub fn name(self) -> Symbol {
-        Symbol::intern(match self {
-            CompilerDesugaringKind::CondTemporary => "if and while condition",
-            CompilerDesugaringKind::Async => "async",
-            CompilerDesugaringKind::Await => "await",
-            CompilerDesugaringKind::QuestionMark => "?",
-            CompilerDesugaringKind::TryBlock => "try block",
-            CompilerDesugaringKind::ExistentialType => "existential type",
-            CompilerDesugaringKind::ForLoop => "for loop",
-        })
+impl DesugaringKind {
+    /// The description wording should combine well with "desugaring of {}".
+    fn descr(self) -> &'static str {
+        match self {
+            DesugaringKind::CondTemporary => "`if` or `while` condition",
+            DesugaringKind::Async => "`async` block or function",
+            DesugaringKind::Await => "`await` expression",
+            DesugaringKind::QuestionMark => "operator `?`",
+            DesugaringKind::TryBlock => "`try` block",
+            DesugaringKind::ExistentialType => "`existential type`",
+            DesugaringKind::ForLoop => "`for` loop",
+        }
     }
 }
 
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 07b9f609320..5ccfe5f0b8b 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -27,7 +27,7 @@ extern crate serialize as rustc_serialize; // used by deriving
 pub mod edition;
 use edition::Edition;
 pub mod hygiene;
-pub use hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnFormat, CompilerDesugaringKind};
+pub use hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnKind, MacroKind, DesugaringKind};
 
 mod span_encoding;
 pub use span_encoding::{Span, DUMMY_SP};
@@ -60,7 +60,7 @@ impl Globals {
         Globals {
             symbol_interner: Lock::new(symbol::Interner::fresh()),
             span_interner: Lock::new(span_encoding::SpanInterner::default()),
-            hygiene_data: Lock::new(hygiene::HygieneData::new()),
+            hygiene_data: Lock::new(hygiene::HygieneData::new(edition)),
             edition,
         }
     }
@@ -403,10 +403,10 @@ impl Span {
     }
 
     /// Checks if this span arises from a compiler desugaring of kind `kind`.
-    pub fn is_compiler_desugaring(&self, kind: CompilerDesugaringKind) -> bool {
+    pub fn is_desugaring(&self, kind: DesugaringKind) -> bool {
         match self.ctxt().outer_expn_info() {
-            Some(info) => match info.format {
-                ExpnFormat::CompilerDesugaring(k) => k == kind,
+            Some(info) => match info.kind {
+                ExpnKind::Desugaring(k) => k == kind,
                 _ => false,
             },
             None => false,
@@ -415,10 +415,10 @@ impl Span {
 
     /// Returns the compiler desugaring that created this span, or `None`
     /// if this span is not from a desugaring.
-    pub fn compiler_desugaring_kind(&self) -> Option<CompilerDesugaringKind> {
+    pub fn desugaring_kind(&self) -> Option<DesugaringKind> {
         match self.ctxt().outer_expn_info() {
-            Some(info) => match info.format {
-                ExpnFormat::CompilerDesugaring(k) => Some(k),
+            Some(info) => match info.kind {
+                ExpnKind::Desugaring(k) => Some(k),
                 _ => None
             },
             None => None
@@ -441,14 +441,18 @@ impl Span {
         while let Some(info) = self.ctxt().outer_expn_info() {
             // Don't print recursive invocations.
             if !info.call_site.source_equal(&prev_span) {
-                let (pre, post) = match info.format {
-                    ExpnFormat::MacroAttribute(..) => ("#[", "]"),
-                    ExpnFormat::MacroBang(..) => ("", "!"),
-                    ExpnFormat::CompilerDesugaring(..) => ("desugaring of `", "`"),
+                let (pre, post) = match info.kind {
+                    ExpnKind::Root => break,
+                    ExpnKind::Desugaring(..) => ("desugaring of ", ""),
+                    ExpnKind::Macro(macro_kind, _) => match macro_kind {
+                        MacroKind::Bang => ("", "!"),
+                        MacroKind::Attr => ("#[", "]"),
+                        MacroKind::Derive => ("#[derive(", ")]"),
+                    }
                 };
                 result.push(MacroBacktrace {
                     call_site: info.call_site,
-                    macro_decl_name: format!("{}{}{}", pre, info.format.name(), post),
+                    macro_decl_name: format!("{}{}{}", pre, info.kind.descr(), post),
                     def_site_span: info.def_site,
                 });
             }
@@ -1363,8 +1367,8 @@ pub struct MacroBacktrace {
     /// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]")
     pub macro_decl_name: String,
 
-    /// span where macro was defined (if known)
-    pub def_site_span: Option<Span>,
+    /// span where macro was defined (possibly dummy)
+    pub def_site_span: Span,
 }
 
 // _____________________________________________________________________________
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 89fcf3b1f8f..581fd47c4b3 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -508,6 +508,7 @@ symbols! {
         proc_macro_expr,
         proc_macro_gen,
         proc_macro_hygiene,
+        proc_macro_internals,
         proc_macro_mod,
         proc_macro_non_items,
         proc_macro_path_invoc,
@@ -631,6 +632,7 @@ symbols! {
         static_nobundle,
         static_recursion,
         std,
+        std_inject,
         str,
         stringify,
         stmt,
diff --git a/src/test/run-pass-fulldeps/auxiliary/plugin-args.rs b/src/test/run-pass-fulldeps/auxiliary/plugin-args.rs
index 7cbfef52b4a..36cee82893a 100644
--- a/src/test/run-pass-fulldeps/auxiliary/plugin-args.rs
+++ b/src/test/run-pass-fulldeps/auxiliary/plugin-args.rs
@@ -28,8 +28,7 @@ impl TTMacroExpander for Expander {
     fn expand<'cx>(&self,
                    ecx: &'cx mut ExtCtxt,
                    sp: Span,
-                   _: TokenStream,
-                   _: Option<Span>) -> Box<dyn MacResult+'cx> {
+                   _: TokenStream) -> Box<dyn MacResult+'cx> {
         let args = self.args.iter().map(|i| pprust::meta_list_item_to_string(i))
             .collect::<Vec<_>>().join(", ");
         MacEager::expr(ecx.expr_str(sp, Symbol::intern(&args)))
diff --git a/src/test/run-pass/auxiliary/arc_wake.rs b/src/test/run-pass/auxiliary/arc_wake.rs
deleted file mode 100644
index c21886f26f4..00000000000
--- a/src/test/run-pass/auxiliary/arc_wake.rs
+++ /dev/null
@@ -1,64 +0,0 @@
-// edition:2018
-
-use std::sync::Arc;
-use std::task::{
-    Waker, RawWaker, RawWakerVTable,
-};
-
-macro_rules! waker_vtable {
-    ($ty:ident) => {
-        &RawWakerVTable::new(
-            clone_arc_raw::<$ty>,
-            wake_arc_raw::<$ty>,
-            wake_by_ref_arc_raw::<$ty>,
-            drop_arc_raw::<$ty>,
-        )
-    };
-}
-
-pub trait ArcWake {
-    fn wake(self: Arc<Self>);
-
-    fn wake_by_ref(arc_self: &Arc<Self>) {
-        arc_self.clone().wake()
-    }
-
-    fn into_waker(wake: Arc<Self>) -> Waker where Self: Sized
-    {
-        let ptr = Arc::into_raw(wake) as *const ();
-
-        unsafe {
-            Waker::from_raw(RawWaker::new(ptr, waker_vtable!(Self)))
-        }
-    }
-}
-
-unsafe fn increase_refcount<T: ArcWake>(data: *const ()) {
-    // Retain Arc by creating a copy
-    let arc: Arc<T> = Arc::from_raw(data as *const T);
-    let arc_clone = arc.clone();
-    // Forget the Arcs again, so that the refcount isn't decrased
-    let _ = Arc::into_raw(arc);
-    let _ = Arc::into_raw(arc_clone);
-}
-
-unsafe fn clone_arc_raw<T: ArcWake>(data: *const ()) -> RawWaker {
-    increase_refcount::<T>(data);
-    RawWaker::new(data, waker_vtable!(T))
-}
-
-unsafe fn drop_arc_raw<T: ArcWake>(data: *const ()) {
-    // Drop Arc
-    let _: Arc<T> = Arc::from_raw(data as *const T);
-}
-
-unsafe fn wake_arc_raw<T: ArcWake>(data: *const ()) {
-    let arc: Arc<T> = Arc::from_raw(data as *const T);
-    ArcWake::wake(arc);
-}
-
-unsafe fn wake_by_ref_arc_raw<T: ArcWake>(data: *const ()) {
-    let arc: Arc<T> = Arc::from_raw(data as *const T);
-    ArcWake::wake_by_ref(&arc);
-    let _ = Arc::into_raw(arc);
-}
diff --git a/src/test/rustdoc/proc-macro.rs b/src/test/rustdoc/proc-macro.rs
index 1e396f1be0e..4bd0b092b55 100644
--- a/src/test/rustdoc/proc-macro.rs
+++ b/src/test/rustdoc/proc-macro.rs
@@ -7,7 +7,7 @@
 // @has some_macros/index.html
 // @has - '//a/[@href="attr.some_proc_attr.html"]' 'some_proc_attr'
 
-//! include a link to [some_proc_attr] to make sure it works.
+//! include a link to [some_proc_macro] to make sure it works.
 
 extern crate proc_macro;
 
diff --git a/src/test/run-pass/async-await/async-fn-size-moved-locals.rs b/src/test/ui/async-await/async-fn-size-moved-locals.rs
index 139be7fe013..d0d4eb032fc 100644
--- a/src/test/run-pass/async-await/async-fn-size-moved-locals.rs
+++ b/src/test/ui/async-await/async-fn-size-moved-locals.rs
@@ -7,6 +7,9 @@
 //
 // See issue #59123 for a full explanation.
 
+// ignore-wasm32-bare (sizes don't match)
+// run-pass
+
 // edition:2018
 
 #![feature(async_await)]
diff --git a/src/test/run-pass/async-await/async-fn-size.rs b/src/test/ui/async-await/async-fn-size.rs
index 7396918196c..c6b2ed13b0a 100644
--- a/src/test/run-pass/async-await/async-fn-size.rs
+++ b/src/test/ui/async-await/async-fn-size.rs
@@ -1,9 +1,10 @@
+// run-pass
+// aux-build:arc_wake.rs
 // edition:2018
 
 #![feature(async_await)]
 
-#[path = "../auxiliary/arc_wake.rs"]
-mod arc_wake;
+extern crate arc_wake;
 
 use std::pin::Pin;
 use std::future::Future;
diff --git a/src/test/run-pass/futures-api.rs b/src/test/ui/async-await/futures-api.rs
index ee77053fd5b..a7da058de30 100644
--- a/src/test/run-pass/futures-api.rs
+++ b/src/test/ui/async-await/futures-api.rs
@@ -1,3 +1,5 @@
+// run-pass
+
 // aux-build:arc_wake.rs
 
 extern crate arc_wake;
diff --git a/src/test/run-pass/async-await/issue-60709.rs b/src/test/ui/async-await/issue-60709.rs
index 5ebb18b999a..ad0b49fa4a2 100644
--- a/src/test/run-pass/async-await/issue-60709.rs
+++ b/src/test/ui/async-await/issue-60709.rs
@@ -2,6 +2,8 @@
 // handled incorrectly in generators.
 // compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018
 
+// run-pass
+
 #![feature(async_await)]
 #![allow(unused)]
 
diff --git a/src/test/ui/derives/auxiliary/derive-marker-tricky.rs b/src/test/ui/derives/auxiliary/derive-marker-tricky.rs
new file mode 100644
index 00000000000..70345351bd0
--- /dev/null
+++ b/src/test/ui/derives/auxiliary/derive-marker-tricky.rs
@@ -0,0 +1,15 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_derive(NoMarker)]
+pub fn f(input: TokenStream) -> TokenStream {
+    if input.to_string().contains("rustc_copy_clone_marker") {
+        panic!("found `#[rustc_copy_clone_marker]`");
+    }
+    TokenStream::new()
+}
diff --git a/src/test/ui/derives/derive-marker-tricky.rs b/src/test/ui/derives/derive-marker-tricky.rs
new file mode 100644
index 00000000000..730ea4714c7
--- /dev/null
+++ b/src/test/ui/derives/derive-marker-tricky.rs
@@ -0,0 +1,16 @@
+// Test that `#[rustc_copy_clone_marker]` is not injected when a user-defined derive shadows
+// a built-in derive in non-trivial scope (e.g. in a nested module).
+
+// check-pass
+// aux-build:derive-marker-tricky.rs
+
+extern crate derive_marker_tricky;
+
+mod m {
+    use derive_marker_tricky::NoMarker as Copy;
+
+    #[derive(Copy)]
+    struct S;
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-asm.stderr b/src/test/ui/feature-gates/feature-gate-asm.stderr
index 0d7f8d819ab..ab5cda43bfc 100644
--- a/src/test/ui/feature-gates/feature-gate-asm.stderr
+++ b/src/test/ui/feature-gates/feature-gate-asm.stderr
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'asm': inline assembly is not stab
   --> $DIR/feature-gate-asm.rs:3:9
    |
 LL |         asm!("");
-   |         ^^^^^^^^^
+   |         ^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/29722
    = help: add `#![feature(asm)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-asm2.stderr b/src/test/ui/feature-gates/feature-gate-asm2.stderr
index b60a34be434..7519cad9a96 100644
--- a/src/test/ui/feature-gates/feature-gate-asm2.stderr
+++ b/src/test/ui/feature-gates/feature-gate-asm2.stderr
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'asm': inline assembly is not stab
   --> $DIR/feature-gate-asm2.rs:5:26
    |
 LL |         println!("{:?}", asm!(""));
-   |                          ^^^^^^^^
+   |                          ^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/29722
    = help: add `#![feature(asm)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-concat_idents.stderr b/src/test/ui/feature-gates/feature-gate-concat_idents.stderr
index 4dc687451df..8639f622cd7 100644
--- a/src/test/ui/feature-gates/feature-gate-concat_idents.stderr
+++ b/src/test/ui/feature-gates/feature-gate-concat_idents.stderr
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` i
   --> $DIR/feature-gate-concat_idents.rs:5:13
    |
 LL |     let a = concat_idents!(X, Y_1);
-   |             ^^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/29599
    = help: add `#![feature(concat_idents)]` to the crate attributes to enable
@@ -11,7 +11,7 @@ error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` i
   --> $DIR/feature-gate-concat_idents.rs:6:13
    |
 LL |     let b = concat_idents!(X, Y_2);
-   |             ^^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/29599
    = help: add `#![feature(concat_idents)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr b/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr
index 4eb038b4a55..4ae5e3e7308 100644
--- a/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr
+++ b/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` i
   --> $DIR/feature-gate-concat_idents2.rs:4:5
    |
 LL |     concat_idents!(a, b);
-   |     ^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/29599
    = help: add `#![feature(concat_idents)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-concat_idents3.stderr b/src/test/ui/feature-gates/feature-gate-concat_idents3.stderr
index e96cd4734d8..367638693d7 100644
--- a/src/test/ui/feature-gates/feature-gate-concat_idents3.stderr
+++ b/src/test/ui/feature-gates/feature-gate-concat_idents3.stderr
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` i
   --> $DIR/feature-gate-concat_idents3.rs:7:20
    |
 LL |     assert_eq!(10, concat_idents!(X, Y_1));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^
+   |                    ^^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/29599
    = help: add `#![feature(concat_idents)]` to the crate attributes to enable
@@ -11,7 +11,7 @@ error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` i
   --> $DIR/feature-gate-concat_idents3.rs:8:20
    |
 LL |     assert_eq!(20, concat_idents!(X, Y_2));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^
+   |                    ^^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/29599
    = help: add `#![feature(concat_idents)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-custom_test_frameworks.stderr b/src/test/ui/feature-gates/feature-gate-custom_test_frameworks.stderr
index 1cc53db2c36..38304e7f3f9 100644
--- a/src/test/ui/feature-gates/feature-gate-custom_test_frameworks.stderr
+++ b/src/test/ui/feature-gates/feature-gate-custom_test_frameworks.stderr
@@ -1,8 +1,8 @@
 error[E0658]: use of unstable library feature 'custom_test_frameworks': custom test frameworks are an unstable feature
-  --> $DIR/feature-gate-custom_test_frameworks.rs:3:1
+  --> $DIR/feature-gate-custom_test_frameworks.rs:3:3
    |
 LL | #[test_case]
-   | ^^^^^^^^^^^^
+   |   ^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/50297
    = help: add `#![feature(custom_test_frameworks)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-format_args_nl.stderr b/src/test/ui/feature-gates/feature-gate-format_args_nl.stderr
index b836a508f7b..b211e2f8ed8 100644
--- a/src/test/ui/feature-gates/feature-gate-format_args_nl.stderr
+++ b/src/test/ui/feature-gates/feature-gate-format_args_nl.stderr
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'format_args_nl': `format_args_nl`
   --> $DIR/feature-gate-format_args_nl.rs:2:5
    |
 LL |     format_args_nl!("");
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^
    |
    = help: add `#![feature(format_args_nl)]` to the crate attributes to enable
 
diff --git a/src/test/ui/feature-gates/feature-gate-global_asm.stderr b/src/test/ui/feature-gates/feature-gate-global_asm.stderr
index 416078489f1..733b8d08f77 100644
--- a/src/test/ui/feature-gates/feature-gate-global_asm.stderr
+++ b/src/test/ui/feature-gates/feature-gate-global_asm.stderr
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'global_asm': `global_asm!` is not
   --> $DIR/feature-gate-global_asm.rs:1:1
    |
 LL | global_asm!("");
-   | ^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/35119
    = help: add `#![feature(global_asm)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-log_syntax.stderr b/src/test/ui/feature-gates/feature-gate-log_syntax.stderr
index 58f522cf823..fa57c20ecd5 100644
--- a/src/test/ui/feature-gates/feature-gate-log_syntax.stderr
+++ b/src/test/ui/feature-gates/feature-gate-log_syntax.stderr
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'log_syntax': `log_syntax!` is not
   --> $DIR/feature-gate-log_syntax.rs:2:5
    |
 LL |     log_syntax!()
-   |     ^^^^^^^^^^^^^
+   |     ^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/29598
    = help: add `#![feature(log_syntax)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-log_syntax2.stderr b/src/test/ui/feature-gates/feature-gate-log_syntax2.stderr
index 3228b9c3013..0443b988b41 100644
--- a/src/test/ui/feature-gates/feature-gate-log_syntax2.stderr
+++ b/src/test/ui/feature-gates/feature-gate-log_syntax2.stderr
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'log_syntax': `log_syntax!` is not
   --> $DIR/feature-gate-log_syntax2.rs:4:22
    |
 LL |     println!("{:?}", log_syntax!());
-   |                      ^^^^^^^^^^^^^
+   |                      ^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/29598
    = help: add `#![feature(log_syntax)]` to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs
index d3a2e486416..9ce2fb58ab0 100644
--- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs
+++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs
@@ -7,12 +7,12 @@ mod unknown { pub macro rustc() {} }
 
 #[rustc::unknown]
 //~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
-//~| ERROR macro `rustc::unknown` may not be used in attributes
+//~| ERROR expected attribute, found macro `rustc::unknown`
 fn f() {}
 
 #[unknown::rustc]
 //~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
-//~| ERROR macro `unknown::rustc` may not be used in attributes
+//~| ERROR expected attribute, found macro `unknown::rustc`
 fn g() {}
 
 #[rustc_dummy]
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
index f098635c702..7c5aa5381e8 100644
--- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
+++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr
@@ -7,11 +7,11 @@ LL | #[rustc::unknown]
    = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
-error: macro `rustc::unknown` may not be used in attributes
-  --> $DIR/feature-gate-rustc-attrs.rs:8:1
+error: expected attribute, found macro `rustc::unknown`
+  --> $DIR/feature-gate-rustc-attrs.rs:8:3
    |
 LL | #[rustc::unknown]
-   | ^^^^^^^^^^^^^^^^^
+   |   ^^^^^^^^^^^^^^ not an attribute
 
 error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler
   --> $DIR/feature-gate-rustc-attrs.rs:13:12
@@ -22,11 +22,11 @@ LL | #[unknown::rustc]
    = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
 
-error: macro `unknown::rustc` may not be used in attributes
-  --> $DIR/feature-gate-rustc-attrs.rs:13:1
+error: expected attribute, found macro `unknown::rustc`
+  --> $DIR/feature-gate-rustc-attrs.rs:13:3
    |
 LL | #[unknown::rustc]
-   | ^^^^^^^^^^^^^^^^^
+   |   ^^^^^^^^^^^^^^ not an attribute
 
 error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler
   --> $DIR/feature-gate-rustc-attrs.rs:20:3
diff --git a/src/test/ui/feature-gates/feature-gate-trace_macros.stderr b/src/test/ui/feature-gates/feature-gate-trace_macros.stderr
index eb41ee45d22..cca08187527 100644
--- a/src/test/ui/feature-gates/feature-gate-trace_macros.stderr
+++ b/src/test/ui/feature-gates/feature-gate-trace_macros.stderr
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is
   --> $DIR/feature-gate-trace_macros.rs:2:5
    |
 LL |     trace_macros!(true);
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/29598
    = help: add `#![feature(trace_macros)]` to the crate attributes to enable
diff --git a/src/test/ui/hrtb/issue-30786.migrate.stderr b/src/test/ui/hrtb/issue-30786.migrate.stderr
new file mode 100644
index 00000000000..9a4f8772822
--- /dev/null
+++ b/src/test/ui/hrtb/issue-30786.migrate.stderr
@@ -0,0 +1,11 @@
+error: implementation of `Stream` is not general enough
+  --> $DIR/issue-30786.rs:107:22
+   |
+LL |     let map = source.map(|x: &_| x);
+   |                      ^^^
+   |
+   = note: `Stream` would have to be implemented for the type `&'0 mut Map<Repeat, [closure@$DIR/issue-30786.rs:107:26: 107:35]>`, for any lifetime `'0`
+   = note: but `Stream` is actually implemented for the type `&'1 mut Map<Repeat, [closure@$DIR/issue-30786.rs:107:26: 107:35]>`, for some specific lifetime `'1`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/hrtb/issue-30786.nll.stderr b/src/test/ui/hrtb/issue-30786.nll.stderr
new file mode 100644
index 00000000000..5c865d76851
--- /dev/null
+++ b/src/test/ui/hrtb/issue-30786.nll.stderr
@@ -0,0 +1,14 @@
+error: higher-ranked subtype error
+  --> $DIR/issue-30786.rs:111:18
+   |
+LL |     let filter = map.filter(|x: &_| true);
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: higher-ranked subtype error
+  --> $DIR/issue-30786.rs:113:17
+   |
+LL |     let count = filter.count(); // Assert that we still have a valid stream.
+   |                 ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/hrtb/issue-30786.rs b/src/test/ui/hrtb/issue-30786.rs
new file mode 100644
index 00000000000..321b83c3459
--- /dev/null
+++ b/src/test/ui/hrtb/issue-30786.rs
@@ -0,0 +1,115 @@
+// rust-lang/rust#30786: the use of `for<'b> &'b mut A: Stream<Item=T`
+// should act as assertion that item does not borrow from its stream;
+// but an earlier buggy rustc allowed `.map(|x: &_| x)` which does
+// have such an item.
+//
+// This tests double-checks that we do not allow such behavior to leak
+// through again.
+
+// revisions: migrate nll
+
+// Since we are testing nll (and migration) explicitly as a separate
+// revisions, don't worry about the --compare-mode=nll on this test.
+
+// ignore-compare-mode-nll
+
+//[nll]compile-flags: -Z borrowck=mir
+
+pub trait Stream {
+    type Item;
+    fn next(self) -> Option<Self::Item>;
+}
+
+// Example stream
+pub struct Repeat(u64);
+
+impl<'a> Stream for &'a mut Repeat {
+    type Item = &'a u64;
+    fn next(self) -> Option<Self::Item> {
+        Some(&self.0)
+    }
+}
+
+pub struct Map<S, F> {
+    stream: S,
+    func: F,
+}
+
+impl<'a, A, F, T> Stream for &'a mut Map<A, F>
+where &'a mut A: Stream,
+      F: FnMut(<&'a mut A as Stream>::Item) -> T,
+{
+    type Item = T;
+    fn next(self) -> Option<T> {
+        match self.stream.next() {
+            Some(item) => Some((self.func)(item)),
+            None => None,
+        }
+    }
+}
+
+pub struct Filter<S, F> {
+    stream: S,
+    func: F,
+}
+
+impl<'a, A, F, T> Stream for &'a mut Filter<A, F>
+where for<'b> &'b mut A: Stream<Item=T>, // <---- BAD
+      F: FnMut(&T) -> bool,
+{
+    type Item = <&'a mut A as Stream>::Item;
+    fn next(self) -> Option<Self::Item> {
+        while let Some(item) = self.stream.next() {
+            if (self.func)(&item) {
+                return Some(item);
+            }
+        }
+        None
+    }
+}
+
+pub trait StreamExt where for<'b> &'b mut Self: Stream {
+    fn map<F>(self, func: F) -> Map<Self, F>
+    where Self: Sized,
+    for<'a> &'a mut Map<Self, F>: Stream,
+    {
+        Map {
+            func: func,
+            stream: self,
+        }
+    }
+
+    fn filter<F>(self, func: F) -> Filter<Self, F>
+    where Self: Sized,
+    for<'a> &'a mut Filter<Self, F>: Stream,
+    {
+        Filter {
+            func: func,
+            stream: self,
+        }
+    }
+
+    fn count(mut self) -> usize
+    where Self: Sized,
+    {
+        let mut count = 0;
+        while let Some(_) = self.next() {
+            count += 1;
+        }
+        count
+    }
+}
+
+impl<T> StreamExt for T where for<'a> &'a mut T: Stream { }
+
+fn main() {
+    let source = Repeat(10);
+    let map = source.map(|x: &_| x);
+    //[migrate]~^ ERROR implementation of `Stream` is not general enough
+    //[migrate]~| NOTE  `Stream` would have to be implemented for the type `&'0 mut Map
+    //[migrate]~| NOTE  but `Stream` is actually implemented for the type `&'1
+    let filter = map.filter(|x: &_| true);
+    //[nll]~^ ERROR higher-ranked subtype error
+    let count = filter.count(); // Assert that we still have a valid stream.
+    //[nll]~^ ERROR higher-ranked subtype error
+}
diff --git a/src/test/ui/hygiene/auxiliary/stdlib-prelude.rs b/src/test/ui/hygiene/auxiliary/stdlib-prelude.rs
new file mode 100644
index 00000000000..81b0b7faa5b
--- /dev/null
+++ b/src/test/ui/hygiene/auxiliary/stdlib-prelude.rs
@@ -0,0 +1,3 @@
+#![feature(decl_macro)]
+
+pub macro stdlib_macro() {}
diff --git a/src/test/ui/hygiene/extern-prelude-from-opaque-fail.rs b/src/test/ui/hygiene/extern-prelude-from-opaque-fail.rs
new file mode 100644
index 00000000000..06d62656e95
--- /dev/null
+++ b/src/test/ui/hygiene/extern-prelude-from-opaque-fail.rs
@@ -0,0 +1,28 @@
+#![feature(decl_macro)]
+
+macro a() {
+    extern crate core as my_core;
+    mod v {
+        // Early resolution.
+        use my_core; //~ ERROR unresolved import `my_core`
+    }
+    mod u {
+        // Late resolution.
+        fn f() { my_core::mem::drop(0); }
+        //~^ ERROR failed to resolve: use of undeclared type or module `my_core`
+    }
+}
+
+a!();
+
+mod v {
+    // Early resolution.
+    use my_core; //~ ERROR unresolved import `my_core`
+}
+mod u {
+    // Late resolution.
+    fn f() { my_core::mem::drop(0); }
+    //~^ ERROR failed to resolve: use of undeclared type or module `my_core`
+}
+
+fn main() {}
diff --git a/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr b/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr
new file mode 100644
index 00000000000..65133eb1e18
--- /dev/null
+++ b/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr
@@ -0,0 +1,37 @@
+error[E0432]: unresolved import `my_core`
+  --> $DIR/extern-prelude-from-opaque-fail.rs:20:9
+   |
+LL |     use my_core;
+   |         ^^^^^^^
+   |         |
+   |         no `my_core` in the root
+   |         help: a similar name exists in the module: `my_core`
+
+error[E0432]: unresolved import `my_core`
+  --> $DIR/extern-prelude-from-opaque-fail.rs:7:13
+   |
+LL |         use my_core;
+   |             ^^^^^^^ no `my_core` in the root
+...
+LL | a!();
+   | ----- in this macro invocation
+
+error[E0433]: failed to resolve: use of undeclared type or module `my_core`
+  --> $DIR/extern-prelude-from-opaque-fail.rs:11:18
+   |
+LL |         fn f() { my_core::mem::drop(0); }
+   |                  ^^^^^^^ use of undeclared type or module `my_core`
+...
+LL | a!();
+   | ----- in this macro invocation
+
+error[E0433]: failed to resolve: use of undeclared type or module `my_core`
+  --> $DIR/extern-prelude-from-opaque-fail.rs:24:14
+   |
+LL |     fn f() { my_core::mem::drop(0); }
+   |              ^^^^^^^ use of undeclared type or module `my_core`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0432, E0433.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/hygiene/stdlib-prelude-from-opaque-early.rs b/src/test/ui/hygiene/stdlib-prelude-from-opaque-early.rs
new file mode 100644
index 00000000000..c8c5c72bf95
--- /dev/null
+++ b/src/test/ui/hygiene/stdlib-prelude-from-opaque-early.rs
@@ -0,0 +1,21 @@
+// check-pass
+// aux-build:stdlib-prelude.rs
+
+#![feature(decl_macro)]
+#![feature(prelude_import)]
+
+extern crate stdlib_prelude;
+
+#[prelude_import]
+use stdlib_prelude::*;
+
+macro mac() {
+    mod m {
+        use std::mem; // OK (extern prelude)
+        stdlib_macro!(); // OK (stdlib prelude)
+    }
+}
+
+mac!();
+
+fn main() {}
diff --git a/src/test/ui/hygiene/stdlib-prelude-from-opaque-late.rs b/src/test/ui/hygiene/stdlib-prelude-from-opaque-late.rs
new file mode 100644
index 00000000000..cf65de2bc23
--- /dev/null
+++ b/src/test/ui/hygiene/stdlib-prelude-from-opaque-late.rs
@@ -0,0 +1,16 @@
+// check-pass
+
+#![feature(decl_macro)]
+
+macro mac() {
+    mod m {
+        fn f() {
+            std::mem::drop(0); // OK (extern prelude)
+            drop(0); // OK (stdlib prelude)
+        }
+    }
+}
+
+mac!();
+
+fn main() {}
diff --git a/src/test/ui/macros/derive-in-eager-expansion-hang.rs b/src/test/ui/macros/derive-in-eager-expansion-hang.rs
new file mode 100644
index 00000000000..0729e14d5b2
--- /dev/null
+++ b/src/test/ui/macros/derive-in-eager-expansion-hang.rs
@@ -0,0 +1,14 @@
+// Regression test for the issue #44692
+
+macro_rules! hang { () => {
+    { //~ ERROR format argument must be a string literal
+        #[derive(Clone)]
+        struct S;
+
+        ""
+    }
+}}
+
+fn main() {
+    format_args!(hang!());
+}
diff --git a/src/test/ui/macros/derive-in-eager-expansion-hang.stderr b/src/test/ui/macros/derive-in-eager-expansion-hang.stderr
new file mode 100644
index 00000000000..1ef9427666b
--- /dev/null
+++ b/src/test/ui/macros/derive-in-eager-expansion-hang.stderr
@@ -0,0 +1,17 @@
+error: format argument must be a string literal
+  --> $DIR/derive-in-eager-expansion-hang.rs:4:5
+   |
+LL | /     {
+LL | |         #[derive(Clone)]
+LL | |         struct S;
+LL | |
+LL | |         ""
+LL | |     }
+   | |_____^
+help: you might be missing a string literal to format with
+   |
+LL |     format_args!("{}", hang!());
+   |                  ^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/macro-deprecation.stderr b/src/test/ui/macros/macro-deprecation.stderr
index e5f4df52237..4c2ad7d2fe9 100644
--- a/src/test/ui/macros/macro-deprecation.stderr
+++ b/src/test/ui/macros/macro-deprecation.stderr
@@ -2,7 +2,7 @@ warning: use of deprecated item 'local_deprecated': local deprecation note
   --> $DIR/macro-deprecation.rs:11:5
    |
 LL |     local_deprecated!();
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^
    |
    = note: #[warn(deprecated)] on by default
 
@@ -10,5 +10,5 @@ warning: use of deprecated item 'deprecated_macro': deprecation note
   --> $DIR/macro-deprecation.rs:12:5
    |
 LL |     deprecated_macro!();
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^
 
diff --git a/src/test/ui/macros/macro-error.stderr b/src/test/ui/macros/macro-error.stderr
index b3aed8c2cef..2539a6d5156 100644
--- a/src/test/ui/macros/macro-error.stderr
+++ b/src/test/ui/macros/macro-error.stderr
@@ -8,7 +8,7 @@ error: non-type macro in type position: cfg
   --> $DIR/macro-error.rs:8:12
    |
 LL |     let _: cfg!(foo) = ();
-   |            ^^^
+   |            ^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/macros/macro-path-prelude-fail-4.rs b/src/test/ui/macros/macro-path-prelude-fail-4.rs
index 283427b9ace..0f93fcdaa5f 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-4.rs
+++ b/src/test/ui/macros/macro-path-prelude-fail-4.rs
@@ -1,4 +1,4 @@
-#[derive(inline)] //~ ERROR expected a macro, found built-in attribute
+#[derive(inline)] //~ ERROR expected derive macro, found built-in attribute `inline`
 struct S;
 
 fn main() {}
diff --git a/src/test/ui/macros/macro-path-prelude-fail-4.stderr b/src/test/ui/macros/macro-path-prelude-fail-4.stderr
index f08445e1f77..dfd6818b678 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-4.stderr
+++ b/src/test/ui/macros/macro-path-prelude-fail-4.stderr
@@ -1,8 +1,8 @@
-error: expected a macro, found built-in attribute
+error: expected derive macro, found built-in attribute `inline`
   --> $DIR/macro-path-prelude-fail-4.rs:1:10
    |
 LL | #[derive(inline)]
-   |          ^^^^^^
+   |          ^^^^^^ not a derive macro
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/macro-stability.stderr b/src/test/ui/macros/macro-stability.stderr
index 6f84c450a2e..21c48bfe5e7 100644
--- a/src/test/ui/macros/macro-stability.stderr
+++ b/src/test/ui/macros/macro-stability.stderr
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'local_unstable'
   --> $DIR/macro-stability.rs:19:5
    |
 LL |     local_unstable!();
-   |     ^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^
    |
    = help: add `#![feature(local_unstable)]` to the crate attributes to enable
 
@@ -10,7 +10,7 @@ error[E0658]: use of unstable library feature 'local_unstable'
   --> $DIR/macro-stability.rs:20:5
    |
 LL |     local_unstable_modern!();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add `#![feature(local_unstable)]` to the crate attributes to enable
 
@@ -18,7 +18,7 @@ error[E0658]: use of unstable library feature 'unstable_macros'
   --> $DIR/macro-stability.rs:21:5
    |
 LL |     unstable_macro!();
-   |     ^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^
    |
    = help: add `#![feature(unstable_macros)]` to the crate attributes to enable
 
@@ -26,7 +26,7 @@ warning: use of deprecated item 'deprecated_macro': deprecation reason
   --> $DIR/macro-stability.rs:24:5
    |
 LL |     deprecated_macro!();
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^
    |
    = note: #[warn(deprecated)] on by default
 
@@ -34,7 +34,7 @@ warning: use of deprecated item 'local_deprecated': local deprecation reason
   --> $DIR/macro-stability.rs:26:5
    |
 LL |     local_deprecated!();
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/macros/trace_faulty_macros.stderr b/src/test/ui/macros/trace_faulty_macros.stderr
index 233d3dcfcb6..fc05012377b 100644
--- a/src/test/ui/macros/trace_faulty_macros.stderr
+++ b/src/test/ui/macros/trace_faulty_macros.stderr
@@ -45,8 +45,6 @@ LL |     my_recursive_macro!();
    = note: to `my_recursive_macro ! (  ) ;`
    = note: expanding `my_recursive_macro! {  }`
    = note: to `my_recursive_macro ! (  ) ;`
-   = note: expanding `my_recursive_macro! {  }`
-   = note: to `my_recursive_macro ! (  ) ;`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.rs b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
index 583640aa817..7a9e472c6c3 100644
--- a/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
@@ -25,22 +25,32 @@ fn check_bang1() {
     my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it
 }
 fn check_bang2() {
-    my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines it
+    my_macro_attr!(); //~ ERROR cannot find macro `my_macro_attr!` in this scope
+    crate::my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines
+                             //~| ERROR expected macro, found attribute macro `crate::my_macro_attr`
 }
 fn check_bang3() {
-    MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it
+    MyTrait!(); //~ ERROR cannot find macro `MyTrait!` in this scope
+    crate::MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it
+                       //~| ERROR expected macro, found derive macro `crate::MyTrait`
 }
 
-#[my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
+#[my_macro] //~ ERROR attribute `my_macro` is currently unknown
+#[crate::my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
+                   //~| ERROR expected attribute, found macro `crate::my_macro`
 fn check_attr1() {}
 #[my_macro_attr] //~ ERROR can't use a procedural macro from the same crate that defines it
 fn check_attr2() {}
 #[MyTrait] //~ ERROR can't use a procedural macro from the same crate that defines it
+           //~| ERROR expected attribute, found derive macro `MyTrait`
 fn check_attr3() {}
 
-#[derive(my_macro)] //~ ERROR can't use a procedural macro from the same crate that defines it
+#[derive(my_macro)] //~ ERROR cannot find derive macro `my_macro` in this scope
+#[derive(crate::my_macro)] //~ ERROR can't use a procedural macro from the same crate that defines
+                           //~| ERROR expected derive macro, found macro `crate::my_macro`
 struct CheckDerive1;
 #[derive(my_macro_attr)] //~ ERROR can't use a procedural macro from the same crate that defines it
+                         //~| ERROR expected derive macro, found attribute macro `my_macro_attr`
 struct CheckDerive2;
 #[derive(MyTrait)] //~ ERROR can't use a procedural macro from the same crate that defines it
 struct CheckDerive3;
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
index 548f9e3051d..8a5e346c2b5 100644
--- a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
@@ -5,52 +5,116 @@ LL |     my_macro!();
    |     ^^^^^^^^
 
 error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:28:5
+  --> $DIR/macro-namespace-reserved-2.rs:29:5
    |
-LL |     my_macro_attr!();
-   |     ^^^^^^^^^^^^^
+LL |     crate::my_macro_attr!();
+   |     ^^^^^^^^^^^^^^^^^^^^
 
-error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:31:5
+error: expected macro, found attribute macro `crate::my_macro_attr`
+  --> $DIR/macro-namespace-reserved-2.rs:29:5
    |
-LL |     MyTrait!();
-   |     ^^^^^^^
+LL |     crate::my_macro_attr!();
+   |     ^^^^^^^^^^^^^^^^^^^^ not a macro
 
 error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:34:3
+  --> $DIR/macro-namespace-reserved-2.rs:34:5
    |
-LL | #[my_macro]
-   |   ^^^^^^^^
+LL |     crate::MyTrait!();
+   |     ^^^^^^^^^^^^^^
+
+error: expected macro, found derive macro `crate::MyTrait`
+  --> $DIR/macro-namespace-reserved-2.rs:34:5
+   |
+LL |     crate::MyTrait!();
+   |     ^^^^^^^^^^^^^^ not a macro
 
 error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:36:3
+  --> $DIR/macro-namespace-reserved-2.rs:42:3
    |
 LL | #[my_macro_attr]
    |   ^^^^^^^^^^^^^
 
 error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:38:3
+  --> $DIR/macro-namespace-reserved-2.rs:44:3
    |
 LL | #[MyTrait]
    |   ^^^^^^^
 
+error: expected attribute, found derive macro `MyTrait`
+  --> $DIR/macro-namespace-reserved-2.rs:44:3
+   |
+LL | #[MyTrait]
+   |   ^^^^^^^ not an attribute
+
 error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:41:10
+  --> $DIR/macro-namespace-reserved-2.rs:49:10
    |
-LL | #[derive(my_macro)]
-   |          ^^^^^^^^
+LL | #[derive(crate::my_macro)]
+   |          ^^^^^^^^^^^^^^^
+
+error: expected derive macro, found macro `crate::my_macro`
+  --> $DIR/macro-namespace-reserved-2.rs:49:10
+   |
+LL | #[derive(crate::my_macro)]
+   |          ^^^^^^^^^^^^^^^ not a derive macro
 
 error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:43:10
+  --> $DIR/macro-namespace-reserved-2.rs:52:10
    |
 LL | #[derive(my_macro_attr)]
    |          ^^^^^^^^^^^^^
 
+error: expected derive macro, found attribute macro `my_macro_attr`
+  --> $DIR/macro-namespace-reserved-2.rs:52:10
+   |
+LL | #[derive(my_macro_attr)]
+   |          ^^^^^^^^^^^^^ not a derive macro
+
 error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:45:10
+  --> $DIR/macro-namespace-reserved-2.rs:55:10
    |
 LL | #[derive(MyTrait)]
    |          ^^^^^^^
 
-error: aborting due to 9 previous errors
+error[E0658]: The attribute `my_macro` is currently unknown to the compiler and may have meaning added to it in the future
+  --> $DIR/macro-namespace-reserved-2.rs:38:3
+   |
+LL | #[my_macro]
+   |   ^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
+   = help: add `#![feature(custom_attribute)]` to the crate attributes to enable
+
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:39:3
+   |
+LL | #[crate::my_macro]
+   |   ^^^^^^^^^^^^^^^
+
+error: expected attribute, found macro `crate::my_macro`
+  --> $DIR/macro-namespace-reserved-2.rs:39:3
+   |
+LL | #[crate::my_macro]
+   |   ^^^^^^^^^^^^^^^ not an attribute
+
+error: cannot find derive macro `my_macro` in this scope
+  --> $DIR/macro-namespace-reserved-2.rs:48:10
+   |
+LL | #[derive(my_macro)]
+   |          ^^^^^^^^
+
+error: cannot find macro `my_macro_attr!` in this scope
+  --> $DIR/macro-namespace-reserved-2.rs:28:5
+   |
+LL |     my_macro_attr!();
+   |     ^^^^^^^^^^^^^
+
+error: cannot find macro `MyTrait!` in this scope
+  --> $DIR/macro-namespace-reserved-2.rs:33:5
+   |
+LL |     MyTrait!();
+   |     ^^^^^^^
+
+error: aborting due to 19 previous errors
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rust-unstable-column-gated.stderr b/src/test/ui/rust-unstable-column-gated.stderr
index f85122922c8..c581a16dbb0 100644
--- a/src/test/ui/rust-unstable-column-gated.stderr
+++ b/src/test/ui/rust-unstable-column-gated.stderr
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature '__rust_unstable_column': internal
   --> $DIR/rust-unstable-column-gated.rs:2:20
    |
 LL |     println!("{}", __rust_unstable_column!());
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                    ^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add `#![feature(__rust_unstable_column)]` to the crate attributes to enable
 
diff --git a/src/test/ui/tool-attributes/tool-attributes-misplaced-2.rs b/src/test/ui/tool-attributes/tool-attributes-misplaced-2.rs
index 56b908d94cc..b5666e4ea70 100644
--- a/src/test/ui/tool-attributes/tool-attributes-misplaced-2.rs
+++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-2.rs
@@ -1,6 +1,6 @@
-#[derive(rustfmt::skip)] //~ ERROR expected a macro, found tool attribute
+#[derive(rustfmt::skip)] //~ ERROR expected derive macro, found tool attribute `rustfmt::skip`
 struct S;
 
 fn main() {
-    rustfmt::skip!(); //~ ERROR expected a macro, found tool attribute
+    rustfmt::skip!(); //~ ERROR expected macro, found tool attribute `rustfmt::skip`
 }
diff --git a/src/test/ui/tool-attributes/tool-attributes-misplaced-2.stderr b/src/test/ui/tool-attributes/tool-attributes-misplaced-2.stderr
index c5f5f59c32c..6d0f826e621 100644
--- a/src/test/ui/tool-attributes/tool-attributes-misplaced-2.stderr
+++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-2.stderr
@@ -1,14 +1,14 @@
-error: expected a macro, found tool attribute
+error: expected derive macro, found tool attribute `rustfmt::skip`
   --> $DIR/tool-attributes-misplaced-2.rs:1:10
    |
 LL | #[derive(rustfmt::skip)]
-   |          ^^^^^^^^^^^^^
+   |          ^^^^^^^^^^^^^ not a derive macro
 
-error: expected a macro, found tool attribute
+error: expected macro, found tool attribute `rustfmt::skip`
   --> $DIR/tool-attributes-misplaced-2.rs:5:5
    |
 LL |     rustfmt::skip!();
-   |     ^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^ not a macro
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/trace_macros-gate.stderr b/src/test/ui/trace_macros-gate.stderr
index adf813c162a..7b954273071 100644
--- a/src/test/ui/trace_macros-gate.stderr
+++ b/src/test/ui/trace_macros-gate.stderr
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is
   --> $DIR/trace_macros-gate.rs:4:5
    |
 LL |     trace_macros!();
-   |     ^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/29598
    = help: add `#![feature(trace_macros)]` to the crate attributes to enable
@@ -17,7 +17,7 @@ error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is
   --> $DIR/trace_macros-gate.rs:6:5
    |
 LL |     trace_macros!(true);
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/29598
    = help: add `#![feature(trace_macros)]` to the crate attributes to enable
@@ -26,7 +26,7 @@ error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is
   --> $DIR/trace_macros-gate.rs:7:5
    |
 LL |     trace_macros!(false);
-   |     ^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/29598
    = help: add `#![feature(trace_macros)]` to the crate attributes to enable
@@ -35,7 +35,7 @@ error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is
   --> $DIR/trace_macros-gate.rs:10:26
    |
 LL |         ($x: ident) => { trace_macros!($x) }
-   |                          ^^^^^^^^^^^^^^^^^
+   |                          ^^^^^^^^^^^^
 ...
 LL |     expando!(true);
    |     --------------- in this macro invocation