diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 17781798946ed..218c164a7dc35 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -657,13 +657,13 @@ macro_rules! uninit_array {
     );
 }
 
-/// Built-in macros to the compiler itself.
+/// Definitions of built-in macros.
 ///
-/// These macros do not have any corresponding definition with a `macro_rules!`
-/// macro, but are documented here. Their implementations can be found hardcoded
-/// into libsyntax itself.
-#[cfg(rustdoc)]
-mod builtin {
+/// Most of the macro properties (stability, visibility, etc.) are taken from the source code here,
+/// with exception of expansion functions transforming macro inputs into outputs,
+/// those functions are provided by the compiler.
+#[cfg(not(bootstrap))]
+pub(crate) mod builtin {
 
     /// Causes compilation to fail with the given error message when encountered.
     ///
@@ -950,7 +950,7 @@ mod builtin {
 
     /// Same as `column`, but less likely to be shadowed.
     #[unstable(feature = "__rust_unstable_column", issue = "0",
-               reason = "internal implementation detail of the `column` macro")]
+               reason = "internal implementation detail of the `panic` macro")]
     #[rustc_builtin_macro]
     #[rustc_macro_transparency = "semitransparent"]
     pub macro __rust_unstable_column() { /* compiler built-in */ }
diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs
index 501a41d0d1c76..de79e2fa260ce 100644
--- a/src/libcore/prelude/v1.rs
+++ b/src/libcore/prelude/v1.rs
@@ -44,3 +44,50 @@ pub use crate::option::Option::{self, Some, None};
 #[stable(feature = "core_prelude", since = "1.4.0")]
 #[doc(no_inline)]
 pub use crate::result::Result::{self, Ok, Err};
+
+// Re-exported built-in macros
+#[cfg(not(bootstrap))]
+#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
+#[allow(deprecated)]
+#[doc(no_inline)]
+pub use crate::macros::builtin::{
+    Clone,
+    Copy,
+    Debug,
+    Decodable,
+    Default,
+    Encodable,
+    Eq,
+    Hash,
+    Ord,
+    PartialEq,
+    PartialOrd,
+    RustcDecodable,
+    RustcEncodable,
+    __rust_unstable_column,
+    asm,
+    assert,
+    bench,
+    cfg,
+    column,
+    compile_error,
+    concat,
+    concat_idents,
+    env,
+    file,
+    format_args,
+    format_args_nl,
+    global_allocator,
+    global_asm,
+    include,
+    include_bytes,
+    include_str,
+    line,
+    log_syntax,
+    module_path,
+    option_env,
+    stringify,
+    test,
+    test_case,
+    trace_macros,
+};
diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs
index 6f841bd2adf41..65e293642874c 100644
--- a/src/libcore/task/wake.rs
+++ b/src/libcore/task/wake.rs
@@ -217,7 +217,7 @@ impl fmt::Debug for Context<'_> {
 /// This handle encapsulates a [`RawWaker`] instance, which defines the
 /// executor-specific wakeup behavior.
 ///
-/// Implements [`Clone`], [`Send`], and [`Sync`].
+/// Implements [`Clone`], [`trait@Send`], and [`trait@Sync`].
 ///
 /// [`RawWaker`]: struct.RawWaker.html
 #[repr(transparent)]
diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs
index f3edb5f862117..c0a661908a654 100644
--- a/src/librustc/hir/def_id.rs
+++ b/src/librustc/hir/def_id.rs
@@ -12,10 +12,6 @@ newtype_index! {
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub enum CrateNum {
-    /// Virtual crate for builtin macros
-    // FIXME(jseyfried): this is also used for custom derives until proc-macro crates get
-    // `CrateNum`s.
-    BuiltinMacros,
     /// A special CrateNum that we use for the tcx.rcache when decoding from
     /// the incr. comp. cache.
     ReservedForIncrCompCache,
@@ -26,7 +22,6 @@ impl ::std::fmt::Debug for CrateNum {
     fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
         match self {
             CrateNum::Index(id) => write!(fmt, "crate{}", id.private),
-            CrateNum::BuiltinMacros => write!(fmt, "builtin macros crate"),
             CrateNum::ReservedForIncrCompCache => write!(fmt, "crate for decoding incr comp cache"),
         }
     }
@@ -86,7 +81,6 @@ impl fmt::Display for CrateNum {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             CrateNum::Index(id) => fmt::Display::fmt(&id.private, f),
-            CrateNum::BuiltinMacros => write!(f, "builtin macros crate"),
             CrateNum::ReservedForIncrCompCache => write!(f, "crate for decoding incr comp cache"),
         }
     }
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 288fd2714e251..2d1835514d425 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -4009,8 +4009,7 @@ impl<'a> LoweringContext<'a> {
         let mut vis = self.lower_visibility(&i.vis, None);
         let attrs = self.lower_attrs(&i.attrs);
         if let ItemKind::MacroDef(ref def) = i.node {
-            if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) ||
-                              attr::contains_name(&i.attrs, sym::rustc_builtin_macro) {
+            if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) {
                 let body = self.lower_token_stream(def.stream());
                 let hir_id = self.lower_node_id(i.id);
                 self.exported_macros.push(hir::MacroDef {
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 1cc7cfda0120a..2754c55ea0685 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -372,7 +372,10 @@ fn configure_and_expand_inner<'a>(
         crate_loader,
         &resolver_arenas,
     );
-    syntax_ext::register_builtins(&mut resolver, plugin_info.syntax_exts, sess.edition());
+    syntax_ext::register_builtin_macros(&mut resolver, sess.edition());
+    syntax_ext::plugin_macro_defs::inject(
+        &mut krate, &mut resolver, plugin_info.syntax_exts, sess.edition()
+    );
 
     // Expand all macros
     sess.profiler(|p| p.start_activity("macro expansion"));
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index cfba42580fcef..f52f7d9cfb3c3 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -13,7 +13,7 @@ use crate::{resolve_error, resolve_struct_error, ResolutionError, Determinacy};
 
 use rustc::bug;
 use rustc::hir::def::{self, *};
-use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
+use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
 use rustc::ty;
 use rustc::middle::cstore::CrateStore;
 use rustc_metadata::cstore::LoadedMacro;
@@ -31,7 +31,6 @@ use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, Nod
 use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant};
 use syntax::ext::base::SyntaxExtension;
 use syntax::ext::hygiene::ExpnId;
-use syntax::ext::tt::macro_rules;
 use syntax::feature_gate::is_builtin_attr;
 use syntax::parse::token::{self, Token};
 use syntax::span_err;
@@ -748,7 +747,7 @@ impl<'a> Resolver<'a> {
         };
         if let Some(id) = self.definitions.as_local_node_id(def_id) {
             self.local_macro_def_scopes[&id]
-        } else if def_id.krate == CrateNum::BuiltinMacros {
+        } else if self.is_builtin_macro(Some(def_id)) {
             self.injected_crate.unwrap_or(self.graph_root)
         } else {
             let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
@@ -756,13 +755,16 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    pub fn get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
-        let def_id = match res {
-            Res::Def(DefKind::Macro(..), def_id) => def_id,
+    crate fn get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
+        match res {
+            Res::Def(DefKind::Macro(..), def_id) => self.get_macro_by_def_id(def_id),
             Res::NonMacroAttr(attr_kind) =>
-                return Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)),
-            _ => return None,
-        };
+                Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)),
+            _ => None,
+        }
+    }
+
+    crate fn get_macro_by_def_id(&mut self, def_id: DefId) -> Option<Lrc<SyntaxExtension>> {
         if let Some(ext) = self.macro_map.get(&def_id) {
             return Some(ext.clone());
         }
@@ -772,10 +774,7 @@ impl<'a> Resolver<'a> {
             LoadedMacro::ProcMacro(ext) => return Some(ext),
         };
 
-        let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
-                                               &self.session.features_untracked(),
-                                               &macro_def,
-                                               self.cstore.crate_edition_untracked(def_id.krate)));
+        let ext = self.compile_macro(&macro_def, self.cstore.crate_edition_untracked(def_id.krate));
         self.macro_map.insert(def_id, ext.clone());
         Some(ext)
     }
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 90a4107f773e1..aeb6f23da5aa6 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -35,17 +35,12 @@ enum AssocSuggestion {
 
 struct TypoSuggestion {
     candidate: Symbol,
-
-    /// The kind of the binding ("crate", "module", etc.)
-    kind: &'static str,
-
-    /// An appropriate article to refer to the binding ("a", "an", etc.)
-    article: &'static str,
+    res: Res,
 }
 
 impl TypoSuggestion {
     fn from_res(candidate: Symbol, res: Res) -> TypoSuggestion {
-        TypoSuggestion { candidate, kind: res.descr(), article: res.article() }
+        TypoSuggestion { candidate, res }
     }
 }
 
@@ -59,7 +54,9 @@ fn add_typo_suggestion(
     err: &mut DiagnosticBuilder<'_>, suggestion: Option<TypoSuggestion>, span: Span
 ) -> bool {
     if let Some(suggestion) = suggestion {
-        let msg = format!("{} {} with a similar name exists", suggestion.article, suggestion.kind);
+        let msg = format!(
+            "{} {} with a similar name exists", suggestion.res.article(), suggestion.res.descr()
+        );
         err.span_suggestion(
             span, &msg, suggestion.candidate.to_string(), Applicability::MaybeIncorrect
         );
@@ -566,7 +563,7 @@ impl<'a> Resolver<'a> {
         filter_fn: &impl Fn(Res) -> bool,
     ) -> Option<TypoSuggestion> {
         let mut suggestions = Vec::new();
-        self.visit_scopes(scope_set, parent_scope, ident, |this, scope, _| {
+        self.visit_scopes(scope_set, parent_scope, ident, |this, scope, use_prelude, _| {
             match scope {
                 Scope::DeriveHelpers => {
                     let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
@@ -611,16 +608,6 @@ impl<'a> Resolver<'a> {
                         }
                     }));
                 }
-                Scope::BuiltinMacros => {
-                    suggestions.extend(this.builtin_macros.iter().filter_map(|(name, binding)| {
-                        let res = binding.res();
-                        if filter_fn(res) {
-                            Some(TypoSuggestion::from_res(*name, res))
-                        } else {
-                            None
-                        }
-                    }));
-                }
                 Scope::BuiltinAttrs => {
                     let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin);
                     if filter_fn(res) {
@@ -656,7 +643,11 @@ impl<'a> Resolver<'a> {
                 }
                 Scope::StdLibPrelude => {
                     if let Some(prelude) = this.prelude {
-                        add_module_candidates(prelude, &mut suggestions, filter_fn);
+                        let mut tmp_suggestions = Vec::new();
+                        add_module_candidates(prelude, &mut tmp_suggestions, filter_fn);
+                        suggestions.extend(tmp_suggestions.into_iter().filter(|s| {
+                            use_prelude || this.is_builtin_macro(s.res.opt_def_id())
+                        }));
                     }
                 }
                 Scope::BuiltinTypes => {
@@ -733,11 +724,7 @@ impl<'a> Resolver<'a> {
                                         );
 
                                         if filter_fn(crate_mod) {
-                                            Some(TypoSuggestion {
-                                                candidate: ident.name,
-                                                article: "a",
-                                                kind: "crate",
-                                            })
+                                            Some(TypoSuggestion::from_res(ident.name, crate_mod))
                                         } else {
                                             None
                                         }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index d718d3f78f4e2..a5e498fa75643 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -114,7 +114,6 @@ enum Scope<'a> {
     CrateRoot,
     Module(Module<'a>),
     MacroUsePrelude,
-    BuiltinMacros,
     BuiltinAttrs,
     LegacyPluginHelpers,
     ExternPrelude,
@@ -1679,7 +1678,7 @@ pub struct Resolver<'a> {
 
     crate_loader: &'a mut CrateLoader<'a>,
     macro_names: FxHashSet<Ident>,
-    builtin_macros: FxHashMap<Name, &'a NameBinding<'a>>,
+    builtin_macros: FxHashMap<Name, SyntaxExtension>,
     macro_use_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
     pub all_macros: FxHashMap<Name, Res>,
     macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
@@ -2021,7 +2020,7 @@ impl<'a> Resolver<'a> {
 
             crate_loader,
             macro_names: FxHashSet::default(),
-            builtin_macros: FxHashMap::default(),
+            builtin_macros: Default::default(),
             macro_use_prelude: FxHashMap::default(),
             all_macros: FxHashMap::default(),
             macro_map: FxHashMap::default(),
@@ -2068,6 +2067,11 @@ impl<'a> Resolver<'a> {
         f(self, MacroNS);
     }
 
+    fn is_builtin_macro(&mut self, def_id: Option<DefId>) -> bool {
+        def_id.and_then(|def_id| self.get_macro_by_def_id(def_id))
+              .map_or(false, |ext| ext.is_builtin)
+    }
+
     fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
         loop {
             match self.macro_defs.get(&ctxt.outer_expn()) {
@@ -2146,7 +2150,7 @@ impl<'a> Resolver<'a> {
         scope_set: ScopeSet,
         parent_scope: &ParentScope<'a>,
         ident: Ident,
-        mut visitor: impl FnMut(&mut Self, Scope<'a>, Ident) -> Option<T>,
+        mut visitor: impl FnMut(&mut Self, Scope<'a>, /*use_prelude*/ bool, Ident) -> Option<T>,
     ) -> Option<T> {
         // General principles:
         // 1. Not controlled (user-defined) names should have higher priority than controlled names
@@ -2185,8 +2189,8 @@ impl<'a> Resolver<'a> {
         // 4. `macro_use` prelude (open, the open part is from macro expansions, not controlled).
         // 4a. User-defined prelude from macro-use
         //    (open, the open part is from macro expansions, not controlled).
-        // 4b. Standard library prelude is currently implemented as `macro-use` (closed, controlled)
-        // 5. Language prelude: builtin macros (closed, controlled, except for legacy plugins).
+        // 4b. "Standard library prelude" part implemented through `macro-use` (closed, controlled).
+        // 4c. Standard library prelude (de-facto closed, controlled).
         // 6. Language prelude: builtin attributes (closed, controlled).
         // 4-6. Legacy plugin helpers (open, not controlled). Similar to derive helpers,
         //    but introduced by legacy plugins using `register_attribute`. Priority is somewhere
@@ -2214,17 +2218,16 @@ impl<'a> Resolver<'a> {
                 Scope::CrateRoot => true,
                 Scope::Module(..) => true,
                 Scope::MacroUsePrelude => use_prelude || rust_2015,
-                Scope::BuiltinMacros => true,
                 Scope::BuiltinAttrs => true,
                 Scope::LegacyPluginHelpers => use_prelude || rust_2015,
                 Scope::ExternPrelude => use_prelude || is_absolute_path,
                 Scope::ToolPrelude => use_prelude,
-                Scope::StdLibPrelude => use_prelude,
+                Scope::StdLibPrelude => use_prelude || ns == MacroNS,
                 Scope::BuiltinTypes => true,
             };
 
             if visit {
-                if let break_result @ Some(..) = visitor(self, scope, ident) {
+                if let break_result @ Some(..) = visitor(self, scope, use_prelude, ident) {
                     return break_result;
                 }
             }
@@ -2263,7 +2266,6 @@ impl<'a> Resolver<'a> {
                     }
                 }
                 Scope::MacroUsePrelude => Scope::StdLibPrelude,
-                Scope::BuiltinMacros => Scope::BuiltinAttrs,
                 Scope::BuiltinAttrs => Scope::LegacyPluginHelpers,
                 Scope::LegacyPluginHelpers => break, // nowhere else to search
                 Scope::ExternPrelude if is_absolute_path => break,
@@ -2272,7 +2274,7 @@ impl<'a> Resolver<'a> {
                 Scope::StdLibPrelude => match ns {
                     TypeNS => Scope::BuiltinTypes,
                     ValueNS => break, // nowhere else to search
-                    MacroNS => Scope::BuiltinMacros,
+                    MacroNS => Scope::BuiltinAttrs,
                 }
                 Scope::BuiltinTypes => break, // nowhere else to search
             };
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 3760cabcd898a..88850c5988b7b 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -1,18 +1,19 @@
 use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc, Determinacy};
 use crate::{CrateLint, Resolver, ResolutionError, Scope, ScopeSet, ParentScope, Weak};
-use crate::{Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding};
+use crate::{Module, ModuleKind, NameBinding, PathResult, Segment, ToNameBinding};
 use crate::{resolve_error, KNOWN_TOOLS};
 use crate::ModuleOrUniformRoot;
 use crate::Namespace::*;
 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_id::{DefId, CRATE_DEF_INDEX};
 use rustc::hir::def::{self, DefKind, NonMacroAttrKind};
 use rustc::hir::map::DefCollector;
 use rustc::middle::stability;
 use rustc::{ty, lint, span_bug};
 use syntax::ast::{self, Ident, ItemKind};
 use syntax::attr::{self, StabilityLevel};
+use syntax::edition::Edition;
 use syntax::ext::base::{self, Indeterminate};
 use syntax::ext::base::{MacroKind, SyntaxExtension};
 use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
@@ -182,21 +183,8 @@ impl<'a> base::Resolver for Resolver<'a> {
         invocation.output_legacy_scope.set(Some(visitor.current_legacy_scope));
     }
 
-    fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>) {
-        let def_id = DefId {
-            krate: CrateNum::BuiltinMacros,
-            index: DefIndex::from(self.macro_map.len()),
-        };
-        let kind = ext.macro_kind();
-        self.macro_map.insert(def_id, ext);
-        let binding = self.arenas.alloc_name_binding(NameBinding {
-            kind: NameBindingKind::Res(Res::Def(DefKind::Macro(kind), def_id), false),
-            ambiguity: None,
-            span: DUMMY_SP,
-            vis: ty::Visibility::Public,
-            expansion: ExpnId::root(),
-        });
-        if self.builtin_macros.insert(ident.name, binding).is_some() {
+    fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension) {
+        if self.builtin_macros.insert(ident.name, ext).is_some() {
             self.session.span_err(ident.span,
                                   &format!("built-in macro `{}` was already defined", ident));
         }
@@ -449,8 +437,8 @@ impl<'a> Resolver<'a> {
         let mut determinacy = Determinacy::Determined;
 
         // Go through all the scopes and try to resolve the name.
-        let break_result =
-                self.visit_scopes(scope_set, parent_scope, orig_ident, |this, scope, ident| {
+        let break_result = self.visit_scopes(scope_set, parent_scope, orig_ident,
+                                             |this, scope, use_prelude, ident| {
             let result = match scope {
                 Scope::DeriveHelpers => {
                     let mut result = Err(Determinacy::Determined);
@@ -535,10 +523,6 @@ impl<'a> Resolver<'a> {
                         this.graph_root.unresolved_invocations.borrow().is_empty()
                     ))
                 }
-                Scope::BuiltinMacros => match this.builtin_macros.get(&ident.name).cloned() {
-                    Some(binding) => Ok((binding, Flags::PRELUDE)),
-                    None => Err(Determinacy::Determined),
-                }
                 Scope::BuiltinAttrs => if is_builtin_attr_name(ident.name) {
                     let binding = (Res::NonMacroAttr(NonMacroAttrKind::Builtin),
                                    ty::Visibility::Public, DUMMY_SP, ExpnId::root())
@@ -579,7 +563,9 @@ impl<'a> Resolver<'a> {
                             false,
                             path_span,
                         ) {
-                            result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE));
+                            if use_prelude || this.is_builtin_macro(binding.res().opt_def_id()) {
+                                result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE));
+                            }
                         }
                     }
                     result
@@ -844,18 +830,42 @@ impl<'a> Resolver<'a> {
         }
     }
 
+    /// Compile the macro into a `SyntaxExtension` and possibly replace it with a pre-defined
+    /// extension partially or entirely for built-in macros and legacy plugin macros.
+    crate fn compile_macro(&mut self, item: &ast::Item, edition: Edition) -> Lrc<SyntaxExtension> {
+        let mut result = macro_rules::compile(
+            &self.session.parse_sess, self.session.features_untracked(), item, edition
+        );
+
+        if result.is_builtin {
+            // The macro was marked with `#[rustc_builtin_macro]`.
+            if let Some(ext) = self.builtin_macros.remove(&item.ident.name) {
+                if ext.is_builtin {
+                    // The macro is a built-in, replace only the expander function.
+                    result.kind = ext.kind;
+                    // Also reset its edition to the global one for compatibility.
+                    result.edition = self.session.edition();
+                } else {
+                    // The macro is from a plugin, the in-source definition is dummy,
+                    // take all the data from the resolver.
+                    result = ext;
+                }
+            } else {
+                let msg = format!("cannot find a built-in macro with name `{}`", item.ident);
+                self.session.span_err(item.span, &msg);
+            }
+        }
+
+        Lrc::new(result)
+    }
+
     pub fn define_macro(&mut self,
                         item: &ast::Item,
                         expansion: ExpnId,
                         current_legacy_scope: &mut LegacyScope<'a>) {
         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(),
-                ));
+                let ext = self.compile_macro(item, self.session.edition());
                 (ext, item.ident, item.span, def.legacy)
             }
             ItemKind::Fn(..) => match proc_macro_stub(item) {
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 1960c06e86e4c..59438883d60bc 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -21,8 +21,8 @@ use rustc::lint::builtin::{
     PUB_USE_OF_PRIVATE_EXTERN_CRATE,
     UNUSED_IMPORTS,
 };
-use rustc::hir::def_id::{CrateNum, DefId};
-use rustc::hir::def::{self, DefKind, PartialRes, Export};
+use rustc::hir::def_id::DefId;
+use rustc::hir::def::{self, PartialRes, Export};
 use rustc::session::DiagnosticMessageId;
 use rustc::util::nodemap::FxHashSet;
 use rustc::{bug, span_bug};
@@ -1214,17 +1214,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
         // this may resolve to either a value or a type, but for documentation
         // purposes it's good enough to just favor one over the other.
         self.per_ns(|this, ns| if let Some(binding) = source_bindings[ns].get().ok() {
-            let mut res = binding.res();
-            if let Res::Def(DefKind::Macro(_), def_id) = res {
-                // `DefId`s from the "built-in macro crate" should not leak from resolve because
-                // later stages are not ready to deal with them and produce lots of ICEs. Replace
-                // them with `Res::Err` until some saner scheme is implemented for built-in macros.
-                if def_id.krate == CrateNum::BuiltinMacros {
-                    this.session.span_err(directive.span, "cannot import a built-in macro");
-                    res = Res::Err;
-                }
-            }
-            this.import_res_map.entry(directive.id).or_default()[ns] = Some(res);
+            this.import_res_map.entry(directive.id).or_default()[ns] = Some(binding.res());
         });
 
         self.check_for_redundant_imports(
@@ -1388,7 +1378,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                 let res = binding.res();
                 if res != Res::Err {
                     if let Some(def_id) = res.opt_def_id() {
-                        if !def_id.is_local() && def_id.krate != CrateNum::BuiltinMacros {
+                        if !def_id.is_local() {
                             self.cstore.export_macros_untracked(def_id.krate);
                         }
                     }
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 5b1e78a113917..117a430eec6b9 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -254,8 +254,8 @@ impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
-    /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of dyn [`Error`] +
-    /// [`Send`] + [`Sync`].
+    /// Converts a type of [`Error`] + [`trait@Send`] + [`trait@Sync`] into a box of
+    /// dyn [`Error`] + [`trait@Send`] + [`trait@Sync`].
     ///
     /// [`Error`]: ../error/trait.Error.html
     ///
@@ -298,7 +298,7 @@ impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync +
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<String> for Box<dyn Error + Send + Sync> {
-    /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
+    /// Converts a [`String`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`].
     ///
     /// [`Error`]: ../error/trait.Error.html
     ///
@@ -362,7 +362,7 @@ impl From<String> for Box<dyn Error> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
-    /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
+    /// Converts a [`str`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`].
     ///
     /// [`Error`]: ../error/trait.Error.html
     ///
@@ -405,7 +405,7 @@ impl From<&str> for Box<dyn Error> {
 
 #[stable(feature = "cow_box_error", since = "1.22.0")]
 impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
-    /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
+    /// Converts a [`Cow`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`].
     ///
     /// [`Cow`]: ../borrow/enum.Cow.html
     /// [`Error`]: ../error/trait.Error.html
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index fbc68c610ee39..722c08a22a6b6 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -221,14 +221,15 @@
 
 #![cfg_attr(test, feature(print_internals, set_stdio, test, update_panic_count))]
 #![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"),
-            feature(global_asm, slice_index_methods,
-                    decl_macro, coerce_unsized, sgx_platform, ptr_wrapping_offset_from))]
+            feature(slice_index_methods, decl_macro, coerce_unsized,
+                    sgx_platform, ptr_wrapping_offset_from))]
 #![cfg_attr(all(test, target_vendor = "fortanix", target_env = "sgx"),
             feature(fixed_size_array, maybe_uninit_extra))]
 
 // std is implemented with unstable features, many of which are internal
 // compiler details that will never be stable
 // NB: the following list is sorted to minimize merge conflicts.
+#![cfg_attr(not(bootstrap), feature(__rust_unstable_column))]
 #![feature(alloc_error_handler)]
 #![feature(alloc_layout_extra)]
 #![feature(allocator_api)]
@@ -251,6 +252,7 @@
 #![feature(const_cstr_unchecked)]
 #![feature(const_raw_ptr_deref)]
 #![feature(core_intrinsics)]
+#![feature(custom_test_frameworks)]
 #![feature(doc_alias)]
 #![feature(doc_cfg)]
 #![feature(doc_keyword)]
@@ -262,7 +264,9 @@
 #![feature(exhaustive_patterns)]
 #![feature(external_doc)]
 #![feature(fn_traits)]
+#![feature(format_args_nl)]
 #![feature(generator_trait)]
+#![feature(global_asm)]
 #![feature(hash_raw_entry)]
 #![feature(hashmap_internals)]
 #![feature(int_error_internals)]
@@ -272,6 +276,7 @@
 #![feature(libc)]
 #![feature(link_args)]
 #![feature(linkage)]
+#![feature(log_syntax)]
 #![feature(maybe_uninit_ref)]
 #![feature(maybe_uninit_slice)]
 #![feature(mem_take)]
@@ -303,6 +308,7 @@
 #![feature(thread_local)]
 #![feature(todo_macro)]
 #![feature(toowned_clone_into)]
+#![feature(trace_macros)]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
 #![feature(untagged_unions)]
@@ -510,6 +516,36 @@ mod std_detect;
 #[cfg(not(test))]
 pub use std_detect::detect;
 
+// Document built-in macros in the crate root for consistency with libcore and existing tradition.
+// FIXME: Attribute and derive macros are not reexported because rustdoc renders them
+// as reexports rather than as macros, and that's not what we want.
+#[cfg(rustdoc)]
+#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
+pub use crate::prelude::v1::{
+    __rust_unstable_column,
+    asm,
+    assert,
+    cfg,
+    column,
+    compile_error,
+    concat,
+    concat_idents,
+    env,
+    file,
+    format_args,
+    format_args_nl,
+    global_asm,
+    include,
+    include_bytes,
+    include_str,
+    line,
+    log_syntax,
+    module_path,
+    option_env,
+    stringify,
+    trace_macros,
+};
+
 // Include a number of private modules that exist solely to provide
 // the rustdoc documentation for primitive types. Using `include!`
 // because rustdoc only looks for these modules at the crate level.
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index b3e09d6974229..839b4c5656a09 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -365,534 +365,3 @@ macro_rules! assert_approx_eq {
                 "{} is not approximately equal to {}", *a, *b);
     })
 }
-
-/// Built-in macros to the compiler itself.
-///
-/// These macros do not have any corresponding definition with a `macro_rules!`
-/// macro, but are documented here. Their implementations can be found hardcoded
-/// into libsyntax itself.
-#[cfg(rustdoc)]
-mod builtin {
-
-    /// Causes compilation to fail with the given error message when encountered.
-    ///
-    /// This macro should be used when a crate uses a conditional compilation strategy to provide
-    /// better error messages for erroneous conditions. It's the compiler-level form of [`panic!`],
-    /// which emits an error at *runtime*, rather than during compilation.
-    ///
-    /// # Examples
-    ///
-    /// Two such examples are macros and `#[cfg]` environments.
-    ///
-    /// Emit better compiler error if a macro is passed invalid values. Without the final branch,
-    /// the compiler would still emit an error, but the error's message would not mention the two
-    /// valid values.
-    ///
-    /// ```compile_fail
-    /// macro_rules! give_me_foo_or_bar {
-    ///     (foo) => {};
-    ///     (bar) => {};
-    ///     ($x:ident) => {
-    ///         compile_error!("This macro only accepts `foo` or `bar`");
-    ///     }
-    /// }
-    ///
-    /// give_me_foo_or_bar!(neither);
-    /// // ^ will fail at compile time with message "This macro only accepts `foo` or `bar`"
-    /// ```
-    ///
-    /// Emit compiler error if one of a number of features isn't available.
-    ///
-    /// ```compile_fail
-    /// #[cfg(not(any(feature = "foo", feature = "bar")))]
-    /// compile_error!("Either feature \"foo\" or \"bar\" must be enabled for this crate.");
-    /// ```
-    ///
-    /// [`panic!`]: ../std/macro.panic.html
-    #[stable(feature = "compile_error_macro", since = "1.20.0")]
-    #[rustc_builtin_macro]
-    macro_rules! compile_error {
-        ($msg:expr) => ({ /* compiler built-in */ });
-        ($msg:expr,) => ({ /* compiler built-in */ });
-    }
-
-    /// Constructs parameters for the other string-formatting macros.
-    ///
-    /// This macro functions by taking a formatting string literal containing
-    /// `{}` for each additional argument passed. `format_args!` prepares the
-    /// additional parameters to ensure the output can be interpreted as a string
-    /// and canonicalizes the arguments into a single type. Any value that implements
-    /// the [`Display`] trait can be passed to `format_args!`, as can any
-    /// [`Debug`] implementation be passed to a `{:?}` within the formatting string.
-    ///
-    /// This macro produces a value of type [`fmt::Arguments`]. This value can be
-    /// passed to the macros within [`std::fmt`] for performing useful redirection.
-    /// All other formatting macros ([`format!`], [`write!`], [`println!`], etc) are
-    /// proxied through this one. `format_args!`, unlike its derived macros, avoids
-    /// heap allocations.
-    ///
-    /// You can use the [`fmt::Arguments`] value that `format_args!` returns
-    /// in `Debug` and `Display` contexts as seen below. The example also shows
-    /// that `Debug` and `Display` format to the same thing: the interpolated
-    /// format string in `format_args!`.
-    ///
-    /// ```rust
-    /// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2));
-    /// let display = format!("{}", format_args!("{} foo {:?}", 1, 2));
-    /// assert_eq!("1 foo 2", display);
-    /// assert_eq!(display, debug);
-    /// ```
-    ///
-    /// For more information, see the documentation in [`std::fmt`].
-    ///
-    /// [`Display`]: ../std/fmt/trait.Display.html
-    /// [`Debug`]: ../std/fmt/trait.Debug.html
-    /// [`fmt::Arguments`]: ../std/fmt/struct.Arguments.html
-    /// [`std::fmt`]: ../std/fmt/index.html
-    /// [`format!`]: ../std/macro.format.html
-    /// [`write!`]: ../std/macro.write.html
-    /// [`println!`]: ../std/macro.println.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::fmt;
-    ///
-    /// let s = fmt::format(format_args!("hello {}", "world"));
-    /// assert_eq!(s, format!("hello {}", "world"));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_builtin_macro]
-    macro_rules! format_args {
-        ($fmt:expr) => ({ /* compiler built-in */ });
-        ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ });
-    }
-
-    /// Inspects an environment variable at compile time.
-    ///
-    /// This macro will expand to the value of the named environment variable at
-    /// compile time, yielding an expression of type `&'static str`.
-    ///
-    /// If the environment variable is not defined, then a compilation error
-    /// will be emitted. To not emit a compile error, use the [`option_env!`]
-    /// macro instead.
-    ///
-    /// [`option_env!`]: ../std/macro.option_env.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let path: &'static str = env!("PATH");
-    /// println!("the $PATH variable at the time of compiling was: {}", path);
-    /// ```
-    ///
-    /// You can customize the error message by passing a string as the second
-    /// parameter:
-    ///
-    /// ```compile_fail
-    /// let doc: &'static str = env!("documentation", "what's that?!");
-    /// ```
-    ///
-    /// If the `documentation` environment variable is not defined, you'll get
-    /// the following error:
-    ///
-    /// ```text
-    /// error: what's that?!
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_builtin_macro]
-    macro_rules! env {
-        ($name:expr) => ({ /* compiler built-in */ });
-        ($name:expr,) => ({ /* compiler built-in */ });
-    }
-
-    /// Optionally inspects an environment variable at compile time.
-    ///
-    /// If the named environment variable is present at compile time, this will
-    /// expand into an expression of type `Option<&'static str>` whose value is
-    /// `Some` of the value of the environment variable. If the environment
-    /// variable is not present, then this will expand to `None`. See
-    /// [`Option<T>`][option] for more information on this type.
-    ///
-    /// A compile time error is never emitted when using this macro regardless
-    /// of whether the environment variable is present or not.
-    ///
-    /// [option]: ../std/option/enum.Option.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let key: Option<&'static str> = option_env!("SECRET_KEY");
-    /// println!("the secret key might be: {:?}", key);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_builtin_macro]
-    macro_rules! option_env {
-        ($name:expr) => ({ /* compiler built-in */ });
-        ($name:expr,) => ({ /* compiler built-in */ });
-    }
-
-    /// Concatenates identifiers into one identifier.
-    ///
-    /// This macro takes any number of comma-separated identifiers, and
-    /// concatenates them all into one, yielding an expression which is a new
-    /// identifier. Note that hygiene makes it such that this macro cannot
-    /// capture local variables. Also, as a general rule, macros are only
-    /// allowed in item, statement or expression position. That means while
-    /// you may use this macro for referring to existing variables, functions or
-    /// modules etc, you cannot define a new one with it.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(concat_idents)]
-    ///
-    /// # fn main() {
-    /// fn foobar() -> u32 { 23 }
-    ///
-    /// let f = concat_idents!(foo, bar);
-    /// println!("{}", f());
-    ///
-    /// // fn concat_idents!(new, fun, name) { } // not usable in this way!
-    /// # }
-    /// ```
-    #[unstable(feature = "concat_idents_macro", issue = "29599")]
-    #[rustc_builtin_macro]
-    macro_rules! concat_idents {
-        ($($e:ident),+) => ({ /* compiler built-in */ });
-        ($($e:ident,)+) => ({ /* compiler built-in */ });
-    }
-
-    /// Concatenates literals into a static string slice.
-    ///
-    /// This macro takes any number of comma-separated literals, yielding an
-    /// expression of type `&'static str` which represents all of the literals
-    /// concatenated left-to-right.
-    ///
-    /// Integer and floating point literals are stringified in order to be
-    /// concatenated.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let s = concat!("test", 10, 'b', true);
-    /// assert_eq!(s, "test10btrue");
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_builtin_macro]
-    macro_rules! concat {
-        ($($e:expr),*) => ({ /* compiler built-in */ });
-        ($($e:expr,)*) => ({ /* compiler built-in */ });
-    }
-
-    /// Expands to the line number on which it was invoked.
-    ///
-    /// With [`column!`] and [`file!`], these macros provide debugging information for
-    /// developers about the location within the source.
-    ///
-    /// The expanded expression has type `u32` and is 1-based, so the first line
-    /// in each file evaluates to 1, the second to 2, etc. This is consistent
-    /// with error messages by common compilers or popular editors.
-    /// The returned line is *not necessarily* the line of the `line!` invocation itself,
-    /// but rather the first macro invocation leading up to the invocation
-    /// of the `line!` macro.
-    ///
-    /// [`column!`]: macro.column.html
-    /// [`file!`]: macro.file.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let current_line = line!();
-    /// println!("defined on line: {}", current_line);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_builtin_macro]
-    macro_rules! line { () => ({ /* compiler built-in */ }) }
-
-    /// Expands to the column number at which it was invoked.
-    ///
-    /// With [`line!`] and [`file!`], these macros provide debugging information for
-    /// developers about the location within the source.
-    ///
-    /// The expanded expression has type `u32` and is 1-based, so the first column
-    /// in each line evaluates to 1, the second to 2, etc. This is consistent
-    /// with error messages by common compilers or popular editors.
-    /// The returned column is *not necessarily* the line of the `column!` invocation itself,
-    /// but rather the first macro invocation leading up to the invocation
-    /// of the `column!` macro.
-    ///
-    /// [`line!`]: macro.line.html
-    /// [`file!`]: macro.file.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let current_col = column!();
-    /// println!("defined on column: {}", current_col);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_builtin_macro]
-    macro_rules! column { () => ({ /* compiler built-in */ }) }
-
-    /// Expands to the file name in which it was invoked.
-    ///
-    /// With [`line!`] and [`column!`], these macros provide debugging information for
-    /// developers about the location within the source.
-    ///
-    ///
-    /// The expanded expression has type `&'static str`, and the returned file
-    /// is not the invocation of the `file!` macro itself, but rather the
-    /// first macro invocation leading up to the invocation of the `file!`
-    /// macro.
-    ///
-    /// [`line!`]: macro.line.html
-    /// [`column!`]: macro.column.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let this_file = file!();
-    /// println!("defined in file: {}", this_file);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_builtin_macro]
-    macro_rules! file { () => ({ /* compiler built-in */ }) }
-
-    /// Stringifies its arguments.
-    ///
-    /// This macro will yield an expression of type `&'static str` which is the
-    /// stringification of all the tokens passed to the macro. No restrictions
-    /// are placed on the syntax of the macro invocation itself.
-    ///
-    /// Note that the expanded results of the input tokens may change in the
-    /// future. You should be careful if you rely on the output.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let one_plus_one = stringify!(1 + 1);
-    /// assert_eq!(one_plus_one, "1 + 1");
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_builtin_macro]
-    macro_rules! stringify { ($($t:tt)*) => ({ /* compiler built-in */ }) }
-
-    /// Includes a utf8-encoded file as a string.
-    ///
-    /// The file is located relative to the current file. (similarly to how
-    /// modules are found)
-    ///
-    /// This macro will yield an expression of type `&'static str` which is the
-    /// contents of the file.
-    ///
-    /// # Examples
-    ///
-    /// Assume there are two files in the same directory with the following
-    /// contents:
-    ///
-    /// File 'spanish.in':
-    ///
-    /// ```text
-    /// adiós
-    /// ```
-    ///
-    /// File 'main.rs':
-    ///
-    /// ```ignore (cannot-doctest-external-file-dependency)
-    /// fn main() {
-    ///     let my_str = include_str!("spanish.in");
-    ///     assert_eq!(my_str, "adiós\n");
-    ///     print!("{}", my_str);
-    /// }
-    /// ```
-    ///
-    /// Compiling 'main.rs' and running the resulting binary will print "adiós".
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_builtin_macro]
-    macro_rules! include_str {
-        ($file:expr) => ({ /* compiler built-in */ });
-        ($file:expr,) => ({ /* compiler built-in */ });
-    }
-
-    /// Includes a file as a reference to a byte array.
-    ///
-    /// The file is located relative to the current file. (similarly to how
-    /// modules are found)
-    ///
-    /// This macro will yield an expression of type `&'static [u8; N]` which is
-    /// the contents of the file.
-    ///
-    /// # Examples
-    ///
-    /// Assume there are two files in the same directory with the following
-    /// contents:
-    ///
-    /// File 'spanish.in':
-    ///
-    /// ```text
-    /// adiós
-    /// ```
-    ///
-    /// File 'main.rs':
-    ///
-    /// ```ignore (cannot-doctest-external-file-dependency)
-    /// fn main() {
-    ///     let bytes = include_bytes!("spanish.in");
-    ///     assert_eq!(bytes, b"adi\xc3\xb3s\n");
-    ///     print!("{}", String::from_utf8_lossy(bytes));
-    /// }
-    /// ```
-    ///
-    /// Compiling 'main.rs' and running the resulting binary will print "adiós".
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_builtin_macro]
-    macro_rules! include_bytes {
-        ($file:expr) => ({ /* compiler built-in */ });
-        ($file:expr,) => ({ /* compiler built-in */ });
-    }
-
-    /// Expands to a string that represents the current module path.
-    ///
-    /// The current module path can be thought of as the hierarchy of modules
-    /// leading back up to the crate root. The first component of the path
-    /// returned is the name of the crate currently being compiled.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// mod test {
-    ///     pub fn foo() {
-    ///         assert!(module_path!().ends_with("test"));
-    ///     }
-    /// }
-    ///
-    /// test::foo();
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_builtin_macro]
-    macro_rules! module_path { () => ({ /* compiler built-in */ }) }
-
-    /// Evaluates boolean combinations of configuration flags at compile-time.
-    ///
-    /// In addition to the `#[cfg]` attribute, this macro is provided to allow
-    /// boolean expression evaluation of configuration flags. This frequently
-    /// leads to less duplicated code.
-    ///
-    /// The syntax given to this macro is the same syntax as the [`cfg`]
-    /// attribute.
-    ///
-    /// [`cfg`]: ../reference/conditional-compilation.html#the-cfg-attribute
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let my_directory = if cfg!(windows) {
-    ///     "windows-specific-directory"
-    /// } else {
-    ///     "unix-directory"
-    /// };
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_builtin_macro]
-    macro_rules! cfg { ($($cfg:tt)*) => ({ /* compiler built-in */ }) }
-
-    /// Parses a file as an expression or an item according to the context.
-    ///
-    /// The file is located relative to the current file (similarly to how
-    /// modules are found).
-    ///
-    /// Using this macro is often a bad idea, because if the file is
-    /// parsed as an expression, it is going to be placed in the
-    /// surrounding code unhygienically. This could result in variables
-    /// or functions being different from what the file expected if
-    /// there are variables or functions that have the same name in
-    /// the current file.
-    ///
-    /// # Examples
-    ///
-    /// Assume there are two files in the same directory with the following
-    /// contents:
-    ///
-    /// File 'monkeys.in':
-    ///
-    /// ```ignore (only-for-syntax-highlight)
-    /// ['🙈', '🙊', '🙉']
-    ///     .iter()
-    ///     .cycle()
-    ///     .take(6)
-    ///     .collect::<String>()
-    /// ```
-    ///
-    /// File 'main.rs':
-    ///
-    /// ```ignore (cannot-doctest-external-file-dependency)
-    /// fn main() {
-    ///     let my_string = include!("monkeys.in");
-    ///     assert_eq!("🙈🙊🙉🙈🙊🙉", my_string);
-    ///     println!("{}", my_string);
-    /// }
-    /// ```
-    ///
-    /// Compiling 'main.rs' and running the resulting binary will print
-    /// "🙈🙊🙉🙈🙊🙉".
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_builtin_macro]
-    macro_rules! include {
-        ($file:expr) => ({ /* compiler built-in */ });
-        ($file:expr,) => ({ /* compiler built-in */ });
-    }
-
-    /// Asserts that a boolean expression is `true` at runtime.
-    ///
-    /// This will invoke the [`panic!`] macro if the provided expression cannot be
-    /// evaluated to `true` at runtime.
-    ///
-    /// # Uses
-    ///
-    /// Assertions are always checked in both debug and release builds, and cannot
-    /// be disabled. See [`debug_assert!`] for assertions that are not enabled in
-    /// release builds by default.
-    ///
-    /// Unsafe code relies on `assert!` to enforce run-time invariants that, if
-    /// violated could lead to unsafety.
-    ///
-    /// Other use-cases of `assert!` include testing and enforcing run-time
-    /// invariants in safe code (whose violation cannot result in unsafety).
-    ///
-    /// # Custom Messages
-    ///
-    /// This macro has a second form, where a custom panic message can
-    /// be provided with or without arguments for formatting. See [`std::fmt`]
-    /// for syntax for this form.
-    ///
-    /// [`panic!`]: macro.panic.html
-    /// [`debug_assert!`]: macro.debug_assert.html
-    /// [`std::fmt`]: ../std/fmt/index.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// // the panic message for these assertions is the stringified value of the
-    /// // expression given.
-    /// assert!(true);
-    ///
-    /// fn some_computation() -> bool { true } // a very simple function
-    ///
-    /// assert!(some_computation());
-    ///
-    /// // assert with a custom message
-    /// let x = true;
-    /// assert!(x, "x wasn't true!");
-    ///
-    /// let a = 3; let b = 27;
-    /// assert!(a + b == 30, "a = {}, b = {}", a, b);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_builtin_macro]
-    macro_rules! assert {
-        ($cond:expr) => ({ /* compiler built-in */ });
-        ($cond:expr,) => ({ /* compiler built-in */ });
-        ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ });
-    }
-}
diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs
index a863bebf4a264..7b12d2ee6f081 100644
--- a/src/libstd/prelude/v1.rs
+++ b/src/libstd/prelude/v1.rs
@@ -7,9 +7,13 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 // Re-exported core operators
+#[cfg(bootstrap)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
-pub use crate::marker::{Copy, Send, Sized, Sync, Unpin};
+pub use crate::marker::Copy;
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)]
+pub use crate::marker::{Send, Sized, Sync, Unpin};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
 pub use crate::ops::{Drop, Fn, FnMut, FnOnce};
@@ -20,15 +24,18 @@ pub use crate::ops::{Drop, Fn, FnMut, FnOnce};
 pub use crate::mem::drop;
 
 // Re-exported types and traits
+#[cfg(bootstrap)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
 pub use crate::clone::Clone;
+#[cfg(bootstrap)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
 pub use crate::cmp::{PartialEq, PartialOrd, Eq, Ord};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
 pub use crate::convert::{AsRef, AsMut, Into, From};
+#[cfg(bootstrap)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
 pub use crate::default::Default;
@@ -45,6 +52,60 @@ pub use crate::option::Option::{self, Some, None};
 #[doc(no_inline)]
 pub use crate::result::Result::{self, Ok, Err};
 
+// Re-exported built-in macros
+#[cfg(not(bootstrap))]
+#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
+#[doc(no_inline)]
+pub use core::prelude::v1::{
+    __rust_unstable_column,
+    asm,
+    assert,
+    cfg,
+    column,
+    compile_error,
+    concat,
+    concat_idents,
+    env,
+    file,
+    format_args,
+    format_args_nl,
+    global_asm,
+    include,
+    include_bytes,
+    include_str,
+    line,
+    log_syntax,
+    module_path,
+    option_env,
+    stringify,
+    trace_macros,
+};
+
+// FIXME: Attribute and derive macros are not documented because for them rustdoc generates
+// dead links which fail link checker testing.
+#[cfg(not(bootstrap))]
+#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
+#[allow(deprecated)]
+#[doc(hidden)]
+pub use core::prelude::v1::{
+    Clone,
+    Copy,
+    Debug,
+    Decodable,
+    Default,
+    Encodable,
+    Eq,
+    Hash,
+    Ord,
+    PartialEq,
+    PartialOrd,
+    RustcDecodable,
+    RustcEncodable,
+    bench,
+    global_allocator,
+    test,
+    test_case,
+};
 
 // The file so far is equivalent to src/libcore/prelude/v1.rs,
 // and below to src/liballoc/prelude.rs.
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 11b7a984aaa00..0ab14bee160da 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -592,6 +592,9 @@ pub struct SyntaxExtension {
     pub helper_attrs: Vec<Symbol>,
     /// Edition of the crate in which this macro is defined.
     pub edition: Edition,
+    /// Built-in macros have a couple of special properties (meaning of `$crate`,
+    /// availability in `#[no_implicit_prelude]` modules), so we have to keep this flag.
+    pub is_builtin: bool,
 }
 
 impl SyntaxExtensionKind {
@@ -636,6 +639,7 @@ impl SyntaxExtension {
             deprecation: None,
             helper_attrs: Vec::new(),
             edition,
+            is_builtin: false,
             kind,
         }
     }
@@ -687,7 +691,7 @@ pub trait Resolver {
     fn resolve_dollar_crates(&mut self);
     fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment,
                                             derives: &[ExpnId]);
-    fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);
+    fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension);
 
     fn resolve_imports(&mut self);
 
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 4503cea0f10c8..c76e964b5e7d7 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -437,6 +437,7 @@ pub fn compile(
         deprecation: attr::find_deprecation(&sess, &def.attrs, def.span),
         helper_attrs: Vec::new(),
         edition,
+        is_builtin: attr::contains_name(&def.attrs, sym::rustc_builtin_macro),
     }
 }
 
diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs
index e491e93256d1c..1a86509928841 100644
--- a/src/libsyntax_ext/deriving/mod.rs
+++ b/src/libsyntax_ext/deriving/mod.rs
@@ -1,11 +1,7 @@
 //! The compiler code necessary to implement the `#[derive]` extensions.
 
-use rustc_data_structures::sync::Lrc;
 use syntax::ast::{self, MetaItem};
-use syntax::attr::Deprecation;
-use syntax::edition::Edition;
-use syntax::ext::base::{Annotatable, ExtCtxt, Resolver, MultiItemModifier};
-use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
+use syntax::ext::base::{Annotatable, ExtCtxt, MultiItemModifier};
 use syntax::ext::build::AstBuilder;
 use syntax::ptr::P;
 use syntax::symbol::{Symbol, sym};
@@ -43,8 +39,8 @@ pub mod ord;
 
 pub mod generic;
 
-struct BuiltinDerive(
-    fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable))
+crate struct BuiltinDerive(
+    crate fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable))
 );
 
 impl MultiItemModifier for BuiltinDerive {
@@ -60,82 +56,6 @@ impl MultiItemModifier for BuiltinDerive {
     }
 }
 
-macro_rules! derive_traits {
-    ($( [$deprecation:expr] $name:ident => $func:path, )+) => {
-        pub fn is_builtin_trait(name: ast::Name) -> bool {
-            match name {
-                $( sym::$name )|+ => true,
-                _ => false,
-            }
-        }
-
-        pub fn register_builtin_derives(resolver: &mut dyn Resolver, edition: Edition) {
-            let allow_internal_unstable = Some([
-                sym::core_intrinsics,
-                sym::rustc_attrs,
-                Symbol::intern("derive_clone_copy"),
-                Symbol::intern("derive_eq"),
-                Symbol::intern("libstd_sys_internals"), // RustcDeserialize and RustcSerialize
-            ][..].into());
-
-            $(
-                resolver.add_builtin(
-                    ast::Ident::with_empty_ctxt(sym::$name),
-                    Lrc::new(SyntaxExtension {
-                        deprecation: $deprecation.map(|msg| Deprecation {
-                            since: Some(Symbol::intern("1.0.0")),
-                            note: Some(Symbol::intern(msg)),
-                        }),
-                        allow_internal_unstable: allow_internal_unstable.clone(),
-                        ..SyntaxExtension::default(
-                            SyntaxExtensionKind::LegacyDerive(Box::new(BuiltinDerive($func))),
-                            edition,
-                        )
-                    }),
-                );
-            )+
-        }
-    }
-}
-
-derive_traits! {
-    [None]
-    Clone => clone::expand_deriving_clone,
-
-    [None]
-    Hash => hash::expand_deriving_hash,
-
-    [None]
-    RustcEncodable => encodable::expand_deriving_rustc_encodable,
-
-    [None]
-    RustcDecodable => decodable::expand_deriving_rustc_decodable,
-
-    [None]
-    PartialEq => partial_eq::expand_deriving_partial_eq,
-    [None]
-    Eq => eq::expand_deriving_eq,
-    [None]
-    PartialOrd => partial_ord::expand_deriving_partial_ord,
-    [None]
-    Ord => ord::expand_deriving_ord,
-
-    [None]
-    Debug => debug::expand_deriving_debug,
-
-    [None]
-    Default => default::expand_deriving_default,
-
-    [None]
-    Copy => bounds::expand_deriving_copy,
-
-    // deprecated
-    [Some("derive(Encodable) is deprecated in favor of derive(RustcEncodable)")]
-    Encodable => encodable::expand_deriving_encodable,
-    [Some("derive(Decodable) is deprecated in favor of derive(RustcDecodable)")]
-    Decodable => decodable::expand_deriving_decodable,
-}
-
 /// Construct a name for the inner type parameter that can't collide with any type parameters of
 /// the item. This is achieved by starting with a base and then concatenating the names of all
 /// other type parameters.
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index 400bfe796bb07..7940abed24597 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -5,19 +5,25 @@
 #![deny(rust_2018_idioms)]
 #![deny(unused_lifetimes)]
 
-#![feature(in_band_lifetimes)]
+#![feature(crate_visibility_modifier)]
+#![feature(decl_macro)]
+#![feature(nll)]
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_span)]
-#![feature(decl_macro)]
-#![feature(nll)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(unicode_internals)]
 
-#![recursion_limit="256"]
-
 extern crate proc_macro;
 
+use crate::deriving::*;
+
+use syntax::ast::Ident;
+use syntax::edition::Edition;
+use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, MacroExpanderFn};
+use syntax::ext::source_util;
+use syntax::symbol::sym;
+
 mod error_codes;
 
 mod asm;
@@ -38,147 +44,71 @@ mod test_case;
 mod trace_macros;
 
 pub mod deriving;
+pub mod plugin_macro_defs;
 pub mod proc_macro_decls;
 pub mod proc_macro_impl;
 
-use rustc_data_structures::sync::Lrc;
-use syntax::ast;
-use syntax::attr::Stability;
-use syntax::ext::base::MacroExpanderFn;
-use syntax::ext::base::{NamedSyntaxExtension, SyntaxExtension, SyntaxExtensionKind};
-use syntax::edition::Edition;
-use syntax::symbol::{sym, Symbol};
-
-const EXPLAIN_ASM: &str =
-    "inline assembly is not stable enough for use and is subject to change";
-const EXPLAIN_GLOBAL_ASM: &str =
-    "`global_asm!` is not stable enough for use and is subject to change";
-const EXPLAIN_CUSTOM_TEST_FRAMEWORKS: &str =
-    "custom test frameworks are an unstable feature";
-const EXPLAIN_LOG_SYNTAX: &str =
-    "`log_syntax!` is not stable enough for use and is subject to change";
-const EXPLAIN_CONCAT_IDENTS: &str =
-    "`concat_idents` is not stable enough for use and is subject to change";
-const EXPLAIN_FORMAT_ARGS_NL: &str =
-    "`format_args_nl` is only for internal language use and is subject to change";
-const EXPLAIN_TRACE_MACROS: &str =
-    "`trace_macros` is not stable enough for use and is subject to change";
-const EXPLAIN_UNSTABLE_COLUMN: &str =
-    "internal implementation detail of the `column` macro";
-
-pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
-                         user_exts: Vec<NamedSyntaxExtension>,
-                         edition: Edition) {
-    deriving::register_builtin_derives(resolver, edition);
-
-    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(
-                SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)), edition
-            ));
-        )* }
+pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, edition: Edition) {
+    let mut register = |name, kind| resolver.register_builtin_macro(
+        Ident::with_empty_ctxt(name), SyntaxExtension {
+            is_builtin: true, ..SyntaxExtension::default(kind, edition)
+        },
+    );
+    macro register_bang($($name:ident: $f:expr,)*) {
+        $(register(sym::$name, SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)));)*
+    }
+    macro register_attr($($name:ident: $f:expr,)*) {
+        $(register(sym::$name, SyntaxExtensionKind::LegacyAttr(Box::new($f)));)*
     }
-    macro_rules! register_unstable {
-        ($( [$feature:expr, $reason:expr, $issue:expr] $name:ident: $f:expr, )*) => { $(
-            register(sym::$name, SyntaxExtension {
-                stability: Some(Stability::unstable(
-                    $feature, Some(Symbol::intern($reason)), $issue
-                )),
-                ..SyntaxExtension::default(
-                    SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)), edition
-                )
-            });
-        )* }
+    macro register_derive($($name:ident: $f:expr,)*) {
+        $(register(sym::$name, SyntaxExtensionKind::LegacyDerive(Box::new(BuiltinDerive($f))));)*
     }
 
-    use syntax::ext::source_util::*;
-    register! {
-        line: expand_line,
-        column: expand_column,
-        file: expand_file,
-        stringify: expand_stringify,
-        include: expand_include,
-        include_str: expand_include_str,
-        include_bytes: expand_include_bytes,
-        module_path: expand_mod,
+    register_bang! {
+        __rust_unstable_column: source_util::expand_column,
+        asm: asm::expand_asm,
+        assert: assert::expand_assert,
         cfg: cfg::expand_cfg,
+        column: source_util::expand_column,
+        compile_error: compile_error::expand_compile_error,
+        concat_idents: concat_idents::expand_syntax_ext,
         concat: concat::expand_syntax_ext,
         env: env::expand_env,
-        option_env: env::expand_option_env,
-        compile_error: compile_error::expand_compile_error,
-        assert: assert::expand_assert,
-    }
-
-    register_unstable! {
-        [sym::__rust_unstable_column, EXPLAIN_UNSTABLE_COLUMN, 0]
-        __rust_unstable_column: expand_column,
-        [sym::asm, EXPLAIN_ASM, 29722]
-        asm: asm::expand_asm,
-        [sym::global_asm, EXPLAIN_GLOBAL_ASM, 35119]
+        file: source_util::expand_file,
+        format_args_nl: format::expand_format_args_nl,
+        format_args: format::expand_format_args,
         global_asm: global_asm::expand_global_asm,
-        [sym::concat_idents, EXPLAIN_CONCAT_IDENTS, 29599]
-        concat_idents: concat_idents::expand_syntax_ext,
-        [sym::log_syntax, EXPLAIN_LOG_SYNTAX, 29598]
+        include_bytes: source_util::expand_include_bytes,
+        include_str: source_util::expand_include_str,
+        include: source_util::expand_include,
+        line: source_util::expand_line,
         log_syntax: log_syntax::expand_syntax_ext,
-        [sym::trace_macros, EXPLAIN_TRACE_MACROS, 29598]
+        module_path: source_util::expand_mod,
+        option_env: env::expand_option_env,
+        stringify: source_util::expand_stringify,
         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 {
-        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
-        )
-    });
-    register(sym::global_allocator, SyntaxExtension {
-        allow_internal_unstable: Some([sym::rustc_attrs][..].into()),
-        ..SyntaxExtension::default(
-            SyntaxExtensionKind::LegacyAttr(Box::new(global_allocator::expand)), edition
-        )
-    });
-
-    let allow_internal_unstable = Some([sym::fmt_internals][..].into());
-    register(sym::format_args, SyntaxExtension {
-        allow_internal_unstable: allow_internal_unstable.clone(),
-        ..SyntaxExtension::default(
-            SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args)), edition
-        )
-    });
-    register(sym::format_args_nl, SyntaxExtension {
-        stability: Some(Stability::unstable(
-            sym::format_args_nl,
-            Some(Symbol::intern(EXPLAIN_FORMAT_ARGS_NL)),
-            0,
-        )),
-        allow_internal_unstable,
-        ..SyntaxExtension::default(
-            SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args_nl)), edition
-        )
-    });
+    register_attr! {
+        bench: test::expand_bench,
+        global_allocator: global_allocator::expand,
+        test: test::expand_test,
+        test_case: test_case::expand,
+    }
 
-    for (name, ext) in user_exts {
-        register(name, ext);
+    register_derive! {
+        Clone: clone::expand_deriving_clone,
+        Copy: bounds::expand_deriving_copy,
+        Debug: debug::expand_deriving_debug,
+        Decodable: decodable::expand_deriving_decodable,
+        Default: default::expand_deriving_default,
+        Encodable: encodable::expand_deriving_encodable,
+        Eq: eq::expand_deriving_eq,
+        Hash: hash::expand_deriving_hash,
+        Ord: ord::expand_deriving_ord,
+        PartialEq: partial_eq::expand_deriving_partial_eq,
+        PartialOrd: partial_ord::expand_deriving_partial_ord,
+        RustcDecodable: decodable::expand_deriving_rustc_decodable,
+        RustcEncodable: encodable::expand_deriving_rustc_encodable,
     }
 }
diff --git a/src/libsyntax_ext/plugin_macro_defs.rs b/src/libsyntax_ext/plugin_macro_defs.rs
new file mode 100644
index 0000000000000..2fd1a42db95f3
--- /dev/null
+++ b/src/libsyntax_ext/plugin_macro_defs.rs
@@ -0,0 +1,64 @@
+//! Each macro must have a definition, so `#[plugin]` attributes
+//! inject a dummy `macro_rules` item for each macro they define.
+
+use syntax::ast::*;
+use syntax::attr;
+use syntax::edition::Edition;
+use syntax::ext::base::{Resolver, NamedSyntaxExtension};
+use syntax::parse::token;
+use syntax::ptr::P;
+use syntax::source_map::respan;
+use syntax::symbol::sym;
+use syntax::tokenstream::*;
+use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::hygiene::{ExpnId, ExpnInfo, ExpnKind, MacroKind};
+
+use std::mem;
+
+fn plugin_macro_def(name: Name, span: Span) -> P<Item> {
+    let rustc_builtin_macro = Attribute {
+        id: attr::mk_attr_id(),
+        style: AttrStyle::Outer,
+        path: Path::from_ident(Ident::new(sym::rustc_builtin_macro, span)),
+        tokens: TokenStream::empty(),
+        is_sugared_doc: false,
+        span,
+    };
+
+    let parens: TreeAndJoint = TokenTree::Delimited(
+        DelimSpan::from_single(span), token::Paren, TokenStream::empty()
+    ).into();
+    let trees = vec![parens.clone(), TokenTree::token(token::FatArrow, span).into(), parens];
+
+    P(Item {
+        ident: Ident::new(name, span),
+        attrs: vec![rustc_builtin_macro],
+        id: DUMMY_NODE_ID,
+        node: ItemKind::MacroDef(MacroDef { tokens: TokenStream::new(trees), legacy: true }),
+        vis: respan(span, VisibilityKind::Inherited),
+        span: span,
+        tokens: None,
+    })
+}
+
+pub fn inject(
+    krate: &mut Crate,
+    resolver: &mut dyn Resolver,
+    named_exts: Vec<NamedSyntaxExtension>,
+    edition: Edition,
+) {
+    if !named_exts.is_empty() {
+        let mut extra_items = Vec::new();
+        let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable(
+            ExpnKind::Macro(MacroKind::Attr, sym::plugin), DUMMY_SP, edition,
+            [sym::rustc_attrs][..].into(),
+        ));
+        for (name, ext) in named_exts {
+            resolver.register_builtin_macro(Ident::with_empty_ctxt(name), ext);
+            extra_items.push(plugin_macro_def(name, span));
+        }
+        // The `macro_rules` items must be inserted before any other items.
+        mem::swap(&mut extra_items, &mut krate.module.items);
+        krate.module.items.append(&mut extra_items);
+    }
+}
diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs
index 08c40dde56c85..303d5f00deb1a 100644
--- a/src/libsyntax_ext/proc_macro_decls.rs
+++ b/src/libsyntax_ext/proc_macro_decls.rs
@@ -1,7 +1,5 @@
 use std::mem;
 
-use crate::deriving;
-
 use syntax::ast::{self, Ident};
 use syntax::attr;
 use syntax::source_map::{ExpnInfo, ExpnKind, respan};
@@ -136,10 +134,6 @@ impl<'a> CollectProcMacros<'a> {
             self.handler.span_err(trait_attr.span,
                                   &format!("`{}` cannot be a name of derive macro", trait_ident));
         }
-        if deriving::is_builtin_trait(trait_ident.name) {
-            self.handler.span_err(trait_attr.span,
-                                  "cannot override a built-in derive macro");
-        }
 
         let attributes_attr = list.get(1);
         let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
diff --git a/src/test/run-make-fulldeps/simd-ffi/simd.rs b/src/test/run-make-fulldeps/simd-ffi/simd.rs
index b834e5cc463a4..75d95a4eaf146 100644
--- a/src/test/run-make-fulldeps/simd-ffi/simd.rs
+++ b/src/test/run-make-fulldeps/simd-ffi/simd.rs
@@ -5,7 +5,7 @@
 #![feature(no_core, optin_builtin_traits)]
 #![no_core]
 
-#![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items)]
+#![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items, rustc_attrs)]
 
 
 #[repr(C)]
@@ -74,3 +74,7 @@ pub mod marker {
 
 #[lang = "freeze"]
 auto trait Freeze {}
+
+#[macro_export]
+#[rustc_builtin_macro]
+macro_rules! Copy { () => () }
diff --git a/src/test/rustdoc/intra-link-builtin-macros.rs b/src/test/rustdoc/intra-link-builtin-macros.rs
new file mode 100644
index 0000000000000..4d40eb3b88f1b
--- /dev/null
+++ b/src/test/rustdoc/intra-link-builtin-macros.rs
@@ -0,0 +1,3 @@
+// @has intra_link_builtin_macros/index.html
+// @has - '//a/@href' 'https://doc.rust-lang.org/nightly/core/macro.cfg.html'
+//! [cfg]
diff --git a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs
index 86441b4f73548..c2685c7f74c30 100644
--- a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs
@@ -3,20 +3,21 @@
 #![feature(plugin_registrar)]
 #![feature(rustc_private)]
 
-extern crate syntax;
-
-extern crate rustc;
-extern crate rustc_plugin;
 extern crate rustc_driver;
+extern crate rustc_plugin;
+extern crate syntax;
 
-use syntax::symbol::Symbol;
-use syntax::feature_gate::AttributeType;
 use rustc_plugin::Registry;
-
+use syntax::ext::base::SyntaxExtension;
+use syntax::feature_gate::AttributeType;
+use syntax::symbol::Symbol;
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_attribute(Symbol::intern("foo"), AttributeType::Normal);
     reg.register_attribute(Symbol::intern("bar"), AttributeType::CrateLevel);
     reg.register_attribute(Symbol::intern("baz"), AttributeType::Whitelisted);
+    reg.register_syntax_extension(
+        Symbol::intern("mac"), SyntaxExtension::dummy_bang(reg.sess.edition())
+    );
 }
diff --git a/src/test/ui-fulldeps/deprecated-derive.stderr b/src/test/ui-fulldeps/deprecated-derive.stderr
index efaf82d9be165..1518c0cc541d2 100644
--- a/src/test/ui-fulldeps/deprecated-derive.stderr
+++ b/src/test/ui-fulldeps/deprecated-derive.stderr
@@ -2,7 +2,7 @@ warning: use of deprecated item 'Encodable': derive(Encodable) is deprecated in
   --> $DIR/deprecated-derive.rs:8:10
    |
 LL | #[derive(Encodable)]
-   |          ^^^^^^^^^
+   |          ^^^^^^^^^ help: replace the use of the deprecated item: `RustcEncodable`
    |
    = note: `#[warn(deprecated)]` on by default
 
diff --git a/src/test/ui-fulldeps/plugin-reexport.rs b/src/test/ui-fulldeps/plugin-reexport.rs
new file mode 100644
index 0000000000000..4d8ede1680830
--- /dev/null
+++ b/src/test/ui-fulldeps/plugin-reexport.rs
@@ -0,0 +1,10 @@
+// edition:2018
+// aux-build:attr-plugin-test.rs
+// ignore-stage1
+
+#![feature(plugin)]
+#![plugin(attr_plugin_test)]
+
+pub use mac as reexport; //~ ERROR `mac` is private, and cannot be re-exported
+
+fn main() {}
diff --git a/src/test/ui-fulldeps/plugin-reexport.stderr b/src/test/ui-fulldeps/plugin-reexport.stderr
new file mode 100644
index 0000000000000..4ac64b8d04b87
--- /dev/null
+++ b/src/test/ui-fulldeps/plugin-reexport.stderr
@@ -0,0 +1,15 @@
+error[E0364]: `mac` is private, and cannot be re-exported
+  --> $DIR/plugin-reexport.rs:8:9
+   |
+LL | pub use mac as reexport;
+   |         ^^^^^^^^^^^^^^^
+   |
+note: consider marking `mac` as `pub` in the imported module
+  --> $DIR/plugin-reexport.rs:8:9
+   |
+LL | pub use mac as reexport;
+   |         ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0364`.
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs b/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs
index 2d8868995f435..31eee88d1fac6 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs
@@ -1,17 +1,10 @@
-// error-pattern: `main` function not found
-
-// At time of authorship, a crate-level #![bench] with no `--test`
-// will cause compilation to error unconditionally with "main function
-// not found" (despite having one), similar to #[bench].
-//
-// (The non-crate level cases are in
-// issue-43106-gating-of-builtin-attrs.rs.)
-
+// The non-crate level cases are in issue-43106-gating-of-builtin-attrs.rs.
 // See issue-12997-1.rs and issue-12997-2.rs to see how `#[bench]` is
 // handled in "weird places" when `--test` is passed.
 
 #![feature(custom_inner_attributes)]
 
 #![bench                   = "4100"]
+//~^ ERROR cannot determine resolution for the attribute macro `bench`
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr
index 37b5e792dc239..d0305c5160f7e 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr
@@ -1,17 +1,10 @@
-warning: attribute must be of the form `#[bench]`
-  --> $DIR/issue-43106-gating-of-bench.rs:15:1
+error: cannot determine resolution for the attribute macro `bench`
+  --> $DIR/issue-43106-gating-of-bench.rs:7:4
    |
 LL | #![bench                   = "4100"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |    ^^^^^
    |
-   = note: `#[warn(ill_formed_attribute_input)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
-
-error[E0601]: `main` function not found in crate `issue_43106_gating_of_bench`
-   |
-   = note: consider adding a `main` function to `$DIR/issue-43106-gating-of-bench.rs`
+   = note: import resolution is stuck, try simplifying macro imports
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-test.rs b/src/test/ui/feature-gate/issue-43106-gating-of-test.rs
index c0c49d353007c..d343746955f39 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-test.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-test.rs
@@ -1,12 +1,6 @@
-// error-pattern: `main` function not found
-
-// At time of authorship, crate-level #[test] attribute with no
-// `--test` signals unconditional error complaining of missing main
-// function (despite having one), similar to #[bench].
-//
-// (The non-crate level cases are in
-// issue-43106-gating-of-builtin-attrs.rs.)
+// The non-crate level cases are in issue-43106-gating-of-builtin-attrs.rs.
 
 #![test                    = "4200"]
+//~^ ERROR cannot determine resolution for the attribute macro `test`
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr
index dbffabf3e02f9..a7d3a1e16840e 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr
@@ -1,17 +1,10 @@
-warning: attribute must be of the form `#[test]`
-  --> $DIR/issue-43106-gating-of-test.rs:10:1
+error: cannot determine resolution for the attribute macro `test`
+  --> $DIR/issue-43106-gating-of-test.rs:3:4
    |
 LL | #![test                    = "4200"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |    ^^^^
    |
-   = note: `#[warn(ill_formed_attribute_input)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
-
-error[E0601]: `main` function not found in crate `issue_43106_gating_of_test`
-   |
-   = note: consider adding a `main` function to `$DIR/issue-43106-gating-of-test.rs`
+   = note: import resolution is stuck, try simplifying macro imports
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs
index 827ac3af8f1fa..506b21dc7d544 100644
--- a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs
+++ b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs
@@ -1,4 +1,4 @@
-#![feature(intrinsics, lang_items, no_core)]
+#![feature(intrinsics, lang_items, no_core, rustc_attrs)]
 
 #![crate_type="rlib"]
 #![no_core]
@@ -88,3 +88,7 @@ fn main() {
     cfg!(target_has_atomic = "ptr");
     //~^ ERROR `cfg(target_has_atomic)` is experimental and subject to change
 }
+
+#[macro_export]
+#[rustc_builtin_macro]
+macro_rules! cfg { () => () }
diff --git a/src/test/ui/imports/glob-shadowing.stderr b/src/test/ui/imports/glob-shadowing.stderr
index 7962fcb9aec1d..4ef446f93c860 100644
--- a/src/test/ui/imports/glob-shadowing.stderr
+++ b/src/test/ui/imports/glob-shadowing.stderr
@@ -4,7 +4,7 @@ error[E0659]: `env` is ambiguous (glob import vs any other name from outer scope
 LL |         let x = env!("PATH");
    |                 ^^^ ambiguous name
    |
-   = note: `env` could refer to a built-in macro
+   = note: `env` could refer to a macro from prelude
 note: `env` could also refer to the macro imported here
   --> $DIR/glob-shadowing.rs:9:9
    |
@@ -19,7 +19,7 @@ error[E0659]: `env` is ambiguous (glob import vs any other name from outer scope
 LL |             let x = env!("PATH");
    |                     ^^^ ambiguous name
    |
-   = note: `env` could refer to a built-in macro
+   = note: `env` could refer to a macro from prelude
 note: `env` could also refer to the macro imported here
   --> $DIR/glob-shadowing.rs:17:13
    |
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
index 13d3227d8b38f..5afdd8889ae7d 100644
--- a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
+++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr
@@ -27,7 +27,7 @@ error[E0659]: `include` is ambiguous (macro-expanded name vs less macro-expanded
 LL | include!();
    | ^^^^^^^ ambiguous name
    |
-   = note: `include` could refer to a built-in macro
+   = note: `include` could refer to a macro from prelude
 note: `include` could also refer to the macro defined here
   --> $DIR/local-modularized-tricky-fail-1.rs:17:5
    |
diff --git a/src/test/ui/issues/issue-28134.rs b/src/test/ui/issues/issue-28134.rs
index 2bd4f93791d38..fa692db4bf66c 100644
--- a/src/test/ui/issues/issue-28134.rs
+++ b/src/test/ui/issues/issue-28134.rs
@@ -1,3 +1,3 @@
 // compile-flags: --test
 
-#![test] //~ ERROR only functions may be used as tests
+#![test] //~ ERROR cannot determine resolution for the attribute macro `test`
diff --git a/src/test/ui/issues/issue-28134.stderr b/src/test/ui/issues/issue-28134.stderr
index b9189480048d8..5f8d27dd043b1 100644
--- a/src/test/ui/issues/issue-28134.stderr
+++ b/src/test/ui/issues/issue-28134.stderr
@@ -1,8 +1,10 @@
-error: only functions may be used as tests
-  --> $DIR/issue-28134.rs:3:1
+error: cannot determine resolution for the attribute macro `test`
+  --> $DIR/issue-28134.rs:3:4
    |
 LL | #![test]
-   | ^^^^^^^^
+   |    ^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/unknown-builtin.rs b/src/test/ui/macros/unknown-builtin.rs
new file mode 100644
index 0000000000000..a96b99ae4ff78
--- /dev/null
+++ b/src/test/ui/macros/unknown-builtin.rs
@@ -0,0 +1,14 @@
+// error-pattern: cannot find a built-in macro with name `line`
+
+#![feature(rustc_attrs)]
+
+#[rustc_builtin_macro]
+macro_rules! unknown { () => () } //~ ERROR cannot find a built-in macro with name `unknown`
+
+#[rustc_builtin_macro]
+macro_rules! line { () => () }
+
+fn main() {
+    line!();
+    std::prelude::v1::line!();
+}
diff --git a/src/test/ui/macros/unknown-builtin.stderr b/src/test/ui/macros/unknown-builtin.stderr
new file mode 100644
index 0000000000000..33b7b055b4e4b
--- /dev/null
+++ b/src/test/ui/macros/unknown-builtin.stderr
@@ -0,0 +1,14 @@
+error: cannot find a built-in macro with name `unknown`
+  --> $DIR/unknown-builtin.rs:6:1
+   |
+LL | macro_rules! unknown { () => () }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot find a built-in macro with name `line`
+  --> <::core::macros::builtin::line macros>:1:1
+   |
+LL | () => { }
+   | ^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/proc-macro/attribute.rs b/src/test/ui/proc-macro/attribute.rs
index 04c88dcef50ac..5531b32362125 100644
--- a/src/test/ui/proc-macro/attribute.rs
+++ b/src/test/ui/proc-macro/attribute.rs
@@ -40,8 +40,7 @@ pub fn foo8(input: TokenStream) -> TokenStream { input }
 //~^ ERROR: `self` cannot be a name of derive macro
 pub fn foo9(input: TokenStream) -> TokenStream { input }
 
-#[proc_macro_derive(PartialEq)]
-//~^ ERROR: cannot override a built-in derive macro
+#[proc_macro_derive(PartialEq)] // OK
 pub fn foo10(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d11, a)]
diff --git a/src/test/ui/proc-macro/attribute.stderr b/src/test/ui/proc-macro/attribute.stderr
index e632875cb16e5..1503f62cb6c1a 100644
--- a/src/test/ui/proc-macro/attribute.stderr
+++ b/src/test/ui/proc-macro/attribute.stderr
@@ -40,56 +40,50 @@ error: `self` cannot be a name of derive macro
 LL | #[proc_macro_derive(self)]
    |                     ^^^^
 
-error: cannot override a built-in derive macro
-  --> $DIR/attribute.rs:43:21
-   |
-LL | #[proc_macro_derive(PartialEq)]
-   |                     ^^^^^^^^^
-
 error: second argument must be `attributes`
-  --> $DIR/attribute.rs:47:26
+  --> $DIR/attribute.rs:46:26
    |
 LL | #[proc_macro_derive(d11, a)]
    |                          ^
 
 error: attribute must be of form: `attributes(foo, bar)`
-  --> $DIR/attribute.rs:47:26
+  --> $DIR/attribute.rs:46:26
    |
 LL | #[proc_macro_derive(d11, a)]
    |                          ^
 
 error: attribute must be of form: `attributes(foo, bar)`
-  --> $DIR/attribute.rs:52:26
+  --> $DIR/attribute.rs:51:26
    |
 LL | #[proc_macro_derive(d12, attributes)]
    |                          ^^^^^^^^^^
 
 error: not a meta item
-  --> $DIR/attribute.rs:56:37
+  --> $DIR/attribute.rs:55:37
    |
 LL | #[proc_macro_derive(d13, attributes("a"))]
    |                                     ^^^
 
 error: must only be one word
-  --> $DIR/attribute.rs:60:37
+  --> $DIR/attribute.rs:59:37
    |
 LL | #[proc_macro_derive(d14, attributes(a = ""))]
    |                                     ^^^^^^
 
 error: must only be one word
-  --> $DIR/attribute.rs:64:37
+  --> $DIR/attribute.rs:63:37
    |
 LL | #[proc_macro_derive(d15, attributes(m::a))]
    |                                     ^^^^
 
 error: must only be one word
-  --> $DIR/attribute.rs:68:37
+  --> $DIR/attribute.rs:67:37
    |
 LL | #[proc_macro_derive(d16, attributes(a(b)))]
    |                                     ^^^^
 
 error: `self` cannot be a name of derive helper attribute
-  --> $DIR/attribute.rs:72:37
+  --> $DIR/attribute.rs:71:37
    |
 LL | #[proc_macro_derive(d17, attributes(self))]
    |                                     ^^^^
@@ -106,5 +100,5 @@ error: malformed `proc_macro_derive` attribute input
 LL | #[proc_macro_derive = ""]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
 
-error: aborting due to 18 previous errors
+error: aborting due to 17 previous errors
 
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs
index dd21de75aaf75..acb4bbebe7f53 100644
--- a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs
+++ b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.rs
@@ -3,7 +3,7 @@
 // Tests that arbitrary crates (other than `core`, `std` and `meta`)
 // aren't allowed without `--extern`, even if they're in the sysroot.
 use alloc; //~ ERROR unresolved import `alloc`
-use test; //~ ERROR cannot import a built-in macro
+use test; // OK, imports the built-in attribute macro `#[test]`, but not the `test` crate.
 use proc_macro; // OK, imports the built-in `proc_macro` attribute, but not the `proc_macro` crate.
 
 fn main() {}
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr
index 4e3fff98e6f4b..f324378d4ca68 100644
--- a/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr
+++ b/src/test/ui/rfc-2126-extern-absolute-paths/not-whitelisted.stderr
@@ -1,15 +1,9 @@
-error: cannot import a built-in macro
-  --> $DIR/not-whitelisted.rs:6:5
-   |
-LL | use test;
-   |     ^^^^
-
 error[E0432]: unresolved import `alloc`
   --> $DIR/not-whitelisted.rs:5:5
    |
 LL | use alloc;
    |     ^^^^^ no `alloc` external crate
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/rust-2018/uniform-paths/prelude-fail.rs b/src/test/ui/rust-2018/uniform-paths/prelude-fail.rs
index d717884c901b3..48c33d720dcad 100644
--- a/src/test/ui/rust-2018/uniform-paths/prelude-fail.rs
+++ b/src/test/ui/rust-2018/uniform-paths/prelude-fail.rs
@@ -1,11 +1,6 @@
 // edition:2018
 
-// Built-in macro
-use env as env_imported; //~ ERROR cannot import a built-in macro
-
 // Tool attribute
 use rustfmt::skip as imported_rustfmt_skip; //~ ERROR unresolved import `rustfmt`
 
-fn main() {
-    env_imported!("PATH");
-}
+fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr b/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr
index 42daf7c6fb12f..97d4c736751aa 100644
--- a/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr
+++ b/src/test/ui/rust-2018/uniform-paths/prelude-fail.stderr
@@ -1,15 +1,9 @@
-error: cannot import a built-in macro
-  --> $DIR/prelude-fail.rs:4:5
-   |
-LL | use env as env_imported;
-   |     ^^^^^^^^^^^^^^^^^^^
-
 error[E0432]: unresolved import `rustfmt`
-  --> $DIR/prelude-fail.rs:7:5
+  --> $DIR/prelude-fail.rs:4:5
    |
 LL | use rustfmt::skip as imported_rustfmt_skip;
    |     ^^^^^^^ `rustfmt` is a tool module, not a module
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/rust-2018/uniform-paths/prelude.rs b/src/test/ui/rust-2018/uniform-paths/prelude.rs
index dca9587c5d369..65763614ce028 100644
--- a/src/test/ui/rust-2018/uniform-paths/prelude.rs
+++ b/src/test/ui/rust-2018/uniform-paths/prelude.rs
@@ -10,9 +10,13 @@ use Vec as ImportedVec;
 // Built-in type
 use u8 as imported_u8;
 
+// Built-in macro
+use env as env_imported;
+
 type A = imported_u8;
 
 fn main() {
     imported_vec![0];
     ImportedVec::<u8>::new();
+    env_imported!("PATH");
 }
diff --git a/src/test/ui/rust-unstable-column-gated.stderr b/src/test/ui/rust-unstable-column-gated.stderr
index c581a16dbb038..7db1b01fb0e63 100644
--- a/src/test/ui/rust-unstable-column-gated.stderr
+++ b/src/test/ui/rust-unstable-column-gated.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature '__rust_unstable_column': internal implementation detail of the `column` macro
+error[E0658]: use of unstable library feature '__rust_unstable_column': internal implementation detail of the `panic` macro
   --> $DIR/rust-unstable-column-gated.rs:2:20
    |
 LL |     println!("{}", __rust_unstable_column!());