about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--src/liballoc/rc.rs30
-rw-r--r--src/liballoc/sync.rs30
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/macros.rs719
-rwxr-xr-xsrc/libcore/unicode/unicode.py1092
-rw-r--r--src/librustc/hir/lowering.rs2
-rw-r--r--src/librustc_codegen_llvm/common.rs3
-rw-r--r--src/librustc_mir/build/matches/mod.rs2
-rw-r--r--src/librustc_mir/hair/pattern/check_match.rs4
-rw-r--r--src/librustc_mir/interpret/place.rs2
-rw-r--r--src/librustc_mir/monomorphize/collector.rs4
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs4
-rw-r--r--src/librustc_mir/transform/copy_prop.rs4
-rw-r--r--src/librustc_mir/transform/inline.rs12
-rw-r--r--src/librustc_mir/transform/instcombine.rs4
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs2
-rw-r--r--src/librustc_privacy/lib.rs3
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs16
-rw-r--r--src/librustc_resolve/macros.rs21
-rw-r--r--src/librustc_resolve/resolve_imports.rs20
-rw-r--r--src/libstd/macros.rs32
-rw-r--r--src/libsyntax/attr/builtin.rs33
-rw-r--r--src/libsyntax/attr/mod.rs6
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs23
-rw-r--r--src/libsyntax/feature_gate.rs8
-rw-r--r--src/libsyntax_pos/symbol.rs4
-rw-r--r--src/libterm/win.rs38
-rw-r--r--src/test/ui/bind-by-move/bind-by-move-no-guards.stderr2
-rw-r--r--src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr2
-rw-r--r--src/test/ui/borrowck/borrowck-mutate-in-guard.stderr2
-rw-r--r--src/test/ui/consts/const_let_refutable.nll.stderr2
-rw-r--r--src/test/ui/consts/const_let_refutable.stderr2
-rw-r--r--src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr2
-rw-r--r--src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr2
-rw-r--r--src/test/ui/consts/min_const_fn/cast_errors.stderr10
-rw-r--r--src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr2
-rw-r--r--src/test/ui/consts/min_const_fn/loop_ice.stderr2
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr66
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.stderr66
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr4
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr4
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr4
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr8
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr8
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr6
-rw-r--r--src/test/ui/consts/min_const_fn/mutable_borrow.stderr4
-rw-r--r--src/test/ui/consts/single_variant_match_ice.stderr2
-rw-r--r--src/test/ui/derives/deriving-with-repr-packed.rs8
-rw-r--r--src/test/ui/derives/deriving-with-repr-packed.stderr8
-rw-r--r--src/test/ui/error-codes/E0008.stderr2
-rw-r--r--src/test/ui/error-codes/E0301.stderr2
-rw-r--r--src/test/ui/hygiene/auxiliary/transparent-basic.rs2
-rw-r--r--src/test/ui/hygiene/generate-mod.rs2
-rw-r--r--src/test/ui/hygiene/rustc-macro-transparency.rs31
-rw-r--r--src/test/ui/hygiene/rustc-macro-transparency.stderr21
-rw-r--r--src/test/ui/hygiene/transparent-basic.rs4
-rw-r--r--src/test/ui/issues/issue-37550.stderr2
-rw-r--r--src/test/ui/macros/restricted-shadowing-modern.rs24
-rw-r--r--src/test/ui/proc-macro/reserved-macro-names.rs6
-rw-r--r--src/test/ui/proc-macro/reserved-macro-names.stderr6
-rw-r--r--src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr2
-rw-r--r--src/test/ui/unsafe/ranged_ints2_const.stderr4
-rw-r--r--src/tools/tidy/src/libcoretest.rs3
64 files changed, 1745 insertions, 702 deletions
diff --git a/.gitignore b/.gitignore
index d34ed114972..87fec414152 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,6 +36,7 @@ __pycache__/
 /src/libcore/unicode/Scripts.txt
 /src/libcore/unicode/SpecialCasing.txt
 /src/libcore/unicode/UnicodeData.txt
+/src/libcore/unicode/downloaded
 /stage[0-9]+/
 /target
 target/
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index ee78839f7f0..45a8b4a25c8 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -1291,26 +1291,26 @@ impl<T> Weak<T> {
     /// ```
     /// #![feature(weak_into_raw)]
     ///
-    /// use std::rc::{Rc, Weak};
+    /// use std::rc::Rc;
     /// use std::ptr;
     ///
     /// let strong = Rc::new("hello".to_owned());
     /// let weak = Rc::downgrade(&strong);
     /// // Both point to the same object
-    /// assert!(ptr::eq(&*strong, Weak::as_raw(&weak)));
+    /// assert!(ptr::eq(&*strong, weak.as_raw()));
     /// // The strong here keeps it alive, so we can still access the object.
-    /// assert_eq!("hello", unsafe { &*Weak::as_raw(&weak) });
+    /// assert_eq!("hello", unsafe { &*weak.as_raw() });
     ///
     /// drop(strong);
-    /// // But not any more. We can do Weak::as_raw(&weak), but accessing the pointer would lead to
+    /// // But not any more. We can do weak.as_raw(), but accessing the pointer would lead to
     /// // undefined behaviour.
-    /// // assert_eq!("hello", unsafe { &*Weak::as_raw(&weak) });
+    /// // assert_eq!("hello", unsafe { &*weak.as_raw() });
     /// ```
     ///
     /// [`null`]: ../../std/ptr/fn.null.html
     #[unstable(feature = "weak_into_raw", issue = "60728")]
-    pub fn as_raw(this: &Self) -> *const T {
-        match this.inner() {
+    pub fn as_raw(&self) -> *const T {
+        match self.inner() {
             None => ptr::null(),
             Some(inner) => {
                 let offset = data_offset_sized::<T>();
@@ -1341,7 +1341,7 @@ impl<T> Weak<T> {
     ///
     /// let strong = Rc::new("hello".to_owned());
     /// let weak = Rc::downgrade(&strong);
-    /// let raw = Weak::into_raw(weak);
+    /// let raw = weak.into_raw();
     ///
     /// assert_eq!(1, Rc::weak_count(&strong));
     /// assert_eq!("hello", unsafe { &*raw });
@@ -1353,9 +1353,9 @@ impl<T> Weak<T> {
     /// [`from_raw`]: struct.Weak.html#method.from_raw
     /// [`as_raw`]: struct.Weak.html#method.as_raw
     #[unstable(feature = "weak_into_raw", issue = "60728")]
-    pub fn into_raw(this: Self) -> *const T {
-        let result = Self::as_raw(&this);
-        mem::forget(this);
+    pub fn into_raw(self) -> *const T {
+        let result = self.as_raw();
+        mem::forget(self);
         result
     }
 
@@ -1382,18 +1382,18 @@ impl<T> Weak<T> {
     ///
     /// let strong = Rc::new("hello".to_owned());
     ///
-    /// let raw_1 = Weak::into_raw(Rc::downgrade(&strong));
-    /// let raw_2 = Weak::into_raw(Rc::downgrade(&strong));
+    /// let raw_1 = Rc::downgrade(&strong).into_raw();
+    /// let raw_2 = Rc::downgrade(&strong).into_raw();
     ///
     /// assert_eq!(2, Rc::weak_count(&strong));
     ///
-    /// assert_eq!("hello", &*Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap());
+    /// assert_eq!("hello", &*unsafe { Weak::from_raw(raw_1) }.upgrade().unwrap());
     /// assert_eq!(1, Rc::weak_count(&strong));
     ///
     /// drop(strong);
     ///
     /// // Decrement the last weak count.
-    /// assert!(Weak::upgrade(&unsafe { Weak::from_raw(raw_2) }).is_none());
+    /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none());
     /// ```
     ///
     /// [`null`]: ../../std/ptr/fn.null.html
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index 6c23b3179ed..126169b5c82 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -1080,26 +1080,26 @@ impl<T> Weak<T> {
     /// ```
     /// #![feature(weak_into_raw)]
     ///
-    /// use std::sync::{Arc, Weak};
+    /// use std::sync::Arc;
     /// use std::ptr;
     ///
     /// let strong = Arc::new("hello".to_owned());
     /// let weak = Arc::downgrade(&strong);
     /// // Both point to the same object
-    /// assert!(ptr::eq(&*strong, Weak::as_raw(&weak)));
+    /// assert!(ptr::eq(&*strong, weak.as_raw()));
     /// // The strong here keeps it alive, so we can still access the object.
-    /// assert_eq!("hello", unsafe { &*Weak::as_raw(&weak) });
+    /// assert_eq!("hello", unsafe { &*weak.as_raw() });
     ///
     /// drop(strong);
-    /// // But not any more. We can do Weak::as_raw(&weak), but accessing the pointer would lead to
+    /// // But not any more. We can do weak.as_raw(), but accessing the pointer would lead to
     /// // undefined behaviour.
-    /// // assert_eq!("hello", unsafe { &*Weak::as_raw(&weak) });
+    /// // assert_eq!("hello", unsafe { &*weak.as_raw() });
     /// ```
     ///
     /// [`null`]: ../../std/ptr/fn.null.html
     #[unstable(feature = "weak_into_raw", issue = "60728")]
-    pub fn as_raw(this: &Self) -> *const T {
-        match this.inner() {
+    pub fn as_raw(&self) -> *const T {
+        match self.inner() {
             None => ptr::null(),
             Some(inner) => {
                 let offset = data_offset_sized::<T>();
@@ -1130,7 +1130,7 @@ impl<T> Weak<T> {
     ///
     /// let strong = Arc::new("hello".to_owned());
     /// let weak = Arc::downgrade(&strong);
-    /// let raw = Weak::into_raw(weak);
+    /// let raw = weak.into_raw();
     ///
     /// assert_eq!(1, Arc::weak_count(&strong));
     /// assert_eq!("hello", unsafe { &*raw });
@@ -1142,9 +1142,9 @@ impl<T> Weak<T> {
     /// [`from_raw`]: struct.Weak.html#method.from_raw
     /// [`as_raw`]: struct.Weak.html#method.as_raw
     #[unstable(feature = "weak_into_raw", issue = "60728")]
-    pub fn into_raw(this: Self) -> *const T {
-        let result = Self::as_raw(&this);
-        mem::forget(this);
+    pub fn into_raw(self) -> *const T {
+        let result = self.as_raw();
+        mem::forget(self);
         result
     }
 
@@ -1172,18 +1172,18 @@ impl<T> Weak<T> {
     ///
     /// let strong = Arc::new("hello".to_owned());
     ///
-    /// let raw_1 = Weak::into_raw(Arc::downgrade(&strong));
-    /// let raw_2 = Weak::into_raw(Arc::downgrade(&strong));
+    /// let raw_1 = Arc::downgrade(&strong).into_raw();
+    /// let raw_2 = Arc::downgrade(&strong).into_raw();
     ///
     /// assert_eq!(2, Arc::weak_count(&strong));
     ///
-    /// assert_eq!("hello", &*Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap());
+    /// assert_eq!("hello", &*unsafe { Weak::from_raw(raw_1) }.upgrade().unwrap());
     /// assert_eq!(1, Arc::weak_count(&strong));
     ///
     /// drop(strong);
     ///
     /// // Decrement the last weak count.
-    /// assert!(Weak::upgrade(&unsafe { Weak::from_raw(raw_2) }).is_none());
+    /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none());
     /// ```
     ///
     /// [`null`]: ../../std/ptr/fn.null.html
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 6ab64a11237..782627431cb 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -75,6 +75,7 @@
 #![feature(const_fn)]
 #![feature(const_fn_union)]
 #![feature(custom_inner_attributes)]
+#![feature(decl_macro)]
 #![feature(doc_cfg)]
 #![feature(doc_spotlight)]
 #![feature(extern_types)]
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 589061b2826..33ffd84e521 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -642,183 +642,720 @@ macro_rules! uninitialized_array {
 /// 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.
-///
-/// For more information, see documentation for `std`'s macros.
 #[cfg(rustdoc)]
 mod builtin {
 
     /// Causes compilation to fail with the given error message when encountered.
     ///
-    /// For more information, see the documentation for [`std::compile_error!`].
+    /// 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.");
+    /// ```
     ///
-    /// [`std::compile_error!`]: ../std/macro.compile_error.html
+    /// [`panic!`]: ../std/macro.panic.html
     #[stable(feature = "compile_error_macro", since = "1.20.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! compile_error {
-        ($msg:expr) => ({ /* compiler built-in */ });
-        ($msg:expr,) => ({ /* compiler built-in */ });
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro compile_error {
+        ($msg:expr) => ({ /* compiler built-in */ }),
+        ($msg:expr,) => ({ /* compiler built-in */ })
     }
 
     /// Constructs parameters for the other string-formatting macros.
     ///
-    /// For more information, see the documentation for [`std::format_args!`].
+    /// 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;
     ///
-    /// [`std::format_args!`]: ../std/macro.format_args.html
+    /// let s = fmt::format(format_args!("hello {}", "world"));
+    /// assert_eq!(s, format!("hello {}", "world"));
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! format_args {
-        ($fmt:expr) => ({ /* compiler built-in */ });
-        ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ });
+    #[allow_internal_unstable(fmt_internals)]
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro format_args {
+        ($fmt:expr) => ({ /* compiler built-in */ }),
+        ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
+    }
+
+    /// Same as `format_args`, but adds a newline in the end.
+    #[unstable(feature = "format_args_nl", issue = "0",
+               reason = "`format_args_nl` is only for internal \
+                         language use and is subject to change")]
+    #[allow_internal_unstable(fmt_internals)]
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro format_args_nl {
+        ($fmt:expr) => ({ /* compiler built-in */ }),
+        ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
     }
 
     /// Inspects an environment variable at compile time.
     ///
-    /// For more information, see the documentation for [`std::env!`].
+    /// 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?!");
+    /// ```
     ///
-    /// [`std::env!`]: ../std/macro.env.html
+    /// 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_doc_only_macro]
-    macro_rules! env {
-        ($name:expr) => ({ /* compiler built-in */ });
-        ($name:expr,) => ({ /* compiler built-in */ });
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro env {
+        ($name:expr) => ({ /* compiler built-in */ }),
+        ($name:expr,) => ({ /* compiler built-in */ })
     }
 
     /// Optionally inspects an environment variable at compile time.
     ///
-    /// For more information, see the documentation for [`std::option_env!`].
+    /// 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
     ///
-    /// [`std::option_env!`]: ../std/macro.option_env.html
+    /// ```
+    /// let key: Option<&'static str> = option_env!("SECRET_KEY");
+    /// println!("the secret key might be: {:?}", key);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! option_env {
-        ($name:expr) => ({ /* compiler built-in */ });
-        ($name:expr,) => ({ /* compiler built-in */ });
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro option_env {
+        ($name:expr) => ({ /* compiler built-in */ }),
+        ($name:expr,) => ({ /* compiler built-in */ })
     }
 
     /// Concatenates identifiers into one identifier.
     ///
-    /// For more information, see the documentation for [`std::concat_idents!`].
+    /// 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 }
     ///
-    /// [`std::concat_idents!`]: ../std/macro.concat_idents.html
-    #[unstable(feature = "concat_idents_macro", issue = "29599")]
-    #[rustc_doc_only_macro]
-    macro_rules! concat_idents {
-        ($($e:ident),+) => ({ /* compiler built-in */ });
-        ($($e:ident,)+) => ({ /* compiler built-in */ });
+    /// let f = concat_idents!(foo, bar);
+    /// println!("{}", f());
+    ///
+    /// // fn concat_idents!(new, fun, name) { } // not usable in this way!
+    /// # }
+    /// ```
+    #[unstable(feature = "concat_idents", issue = "29599",
+               reason = "`concat_idents` is not stable enough for use and is subject to change")]
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro concat_idents {
+        ($($e:ident),+) => ({ /* compiler built-in */ }),
+        ($($e:ident,)+) => ({ /* compiler built-in */ })
     }
 
     /// Concatenates literals into a static string slice.
     ///
-    /// For more information, see the documentation for [`std::concat!`].
+    /// 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.
     ///
-    /// [`std::concat!`]: ../std/macro.concat.html
+    /// # Examples
+    ///
+    /// ```
+    /// let s = concat!("test", 10, 'b', true);
+    /// assert_eq!(s, "test10btrue");
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! concat {
-        ($($e:expr),*) => ({ /* compiler built-in */ });
-        ($($e:expr,)*) => ({ /* compiler built-in */ });
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro concat {
+        ($($e:expr),*) => ({ /* compiler built-in */ }),
+        ($($e:expr,)*) => ({ /* compiler built-in */ })
     }
 
     /// Expands to the line number on which it was invoked.
     ///
-    /// For more information, see the documentation for [`std::line!`].
+    /// 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.
     ///
-    /// [`std::line!`]: ../std/macro.line.html
+    /// [`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_doc_only_macro]
-    macro_rules! line { () => ({ /* compiler built-in */ }) }
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro line() { /* compiler built-in */ }
 
-    /// Expands to the column number on which it was invoked.
+    /// 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.
     ///
-    /// For more information, see the documentation for [`std::column!`].
+    /// [`line!`]: macro.line.html
+    /// [`file!`]: macro.file.html
     ///
-    /// [`std::column!`]: ../std/macro.column.html
+    /// # Examples
+    ///
+    /// ```
+    /// let current_col = column!();
+    /// println!("defined on column: {}", current_col);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! column { () => ({ /* compiler built-in */ }) }
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro column() { /* compiler built-in */ }
+
+    /// Same as `column`, but less likely to be shadowed.
+    #[unstable(feature = "__rust_unstable_column", issue = "0",
+               reason = "internal implementation detail of the `column` macro")]
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro __rust_unstable_column() { /* compiler built-in */ }
 
-    /// Expands to the file name from which it was invoked.
+    /// 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.
+    ///
     ///
-    /// For more information, see the documentation for [`std::file!`].
+    /// 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.
     ///
-    /// [`std::file!`]: ../std/macro.file.html
+    /// [`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_doc_only_macro]
-    macro_rules! file { () => ({ /* compiler built-in */ }) }
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro file() { /* compiler built-in */ }
 
     /// Stringifies its arguments.
     ///
-    /// For more information, see the documentation for [`std::stringify!`].
+    /// 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.
     ///
-    /// [`std::stringify!`]: ../std/macro.stringify.html
+    /// # Examples
+    ///
+    /// ```
+    /// let one_plus_one = stringify!(1 + 1);
+    /// assert_eq!(one_plus_one, "1 + 1");
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! stringify { ($($t:tt)*) => ({ /* compiler built-in */ }) }
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro stringify($($t:tt)*) { /* compiler built-in */ }
 
     /// Includes a utf8-encoded file as a string.
     ///
-    /// For more information, see the documentation for [`std::include_str!`].
+    /// 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);
+    /// }
+    /// ```
     ///
-    /// [`std::include_str!`]: ../std/macro.include_str.html
+    /// Compiling 'main.rs' and running the resulting binary will print "adiós".
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! include_str {
-        ($file:expr) => ({ /* compiler built-in */ });
-        ($file:expr,) => ({ /* compiler built-in */ });
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro include_str {
+        ($file:expr) => ({ /* compiler built-in */ }),
+        ($file:expr,) => ({ /* compiler built-in */ })
     }
 
     /// Includes a file as a reference to a byte array.
     ///
-    /// For more information, see the documentation for [`std::include_bytes!`].
+    /// 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));
+    /// }
+    /// ```
     ///
-    /// [`std::include_bytes!`]: ../std/macro.include_bytes.html
+    /// Compiling 'main.rs' and running the resulting binary will print "adiós".
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! include_bytes {
-        ($file:expr) => ({ /* compiler built-in */ });
-        ($file:expr,) => ({ /* compiler built-in */ });
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro include_bytes {
+        ($file:expr) => ({ /* compiler built-in */ }),
+        ($file:expr,) => ({ /* compiler built-in */ })
     }
 
     /// Expands to a string that represents the current module path.
     ///
-    /// For more information, see the documentation for [`std::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.
     ///
-    /// [`std::module_path!`]: ../std/macro.module_path.html
+    /// # Examples
+    ///
+    /// ```
+    /// mod test {
+    ///     pub fn foo() {
+    ///         assert!(module_path!().ends_with("test"));
+    ///     }
+    /// }
+    ///
+    /// test::foo();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! module_path { () => ({ /* compiler built-in */ }) }
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro module_path() { /* compiler built-in */ }
 
-    /// Evaluates boolean combinations of configuration flags, at compile-time.
+    /// 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.
     ///
-    /// For more information, see the documentation for [`std::cfg!`].
+    /// [`cfg`]: ../reference/conditional-compilation.html#the-cfg-attribute
     ///
-    /// [`std::cfg!`]: ../std/macro.cfg.html
+    /// # Examples
+    ///
+    /// ```
+    /// let my_directory = if cfg!(windows) {
+    ///     "windows-specific-directory"
+    /// } else {
+    ///     "unix-directory"
+    /// };
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
-    macro_rules! cfg { ($($cfg:tt)*) => ({ /* compiler built-in */ }) }
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro cfg($($cfg:tt)*) { /* compiler built-in */ }
 
     /// Parses a file as an expression or an item according to the context.
     ///
-    /// For more information, see the documentation for [`std::include!`].
+    /// 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:
     ///
-    /// [`std::include!`]: ../std/macro.include.html
+    /// 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_doc_only_macro]
-    macro_rules! include {
-        ($file:expr) => ({ /* compiler built-in */ });
-        ($file:expr,) => ({ /* compiler built-in */ });
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro include {
+        ($file:expr) => ({ /* compiler built-in */ }),
+        ($file:expr,) => ({ /* compiler built-in */ })
     }
 
     /// Asserts that a boolean expression is `true` at runtime.
     ///
-    /// For more information, see the documentation for [`std::assert!`].
+    /// 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.
     ///
-    /// [`std::assert!`]: ../std/macro.assert.html
-    #[rustc_doc_only_macro]
+    /// 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")]
-    macro_rules! assert {
-        ($cond:expr) => ({ /* compiler built-in */ });
-        ($cond:expr,) => ({ /* compiler built-in */ });
-        ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ });
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro assert {
+        ($cond:expr) => ({ /* compiler built-in */ }),
+        ($cond:expr,) => ({ /* compiler built-in */ }),
+        ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ })
     }
+
+    /// Inline assembly.
+    #[unstable(feature = "asm", issue = "29722",
+               reason = "inline assembly is not stable enough for use and is subject to change")]
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro asm("assembly template"
+                  : $("output"(operand),)*
+                  : $("input"(operand),)*
+                  : $("clobbers",)*
+                  : $("options",)*) { /* compiler built-in */ }
+
+    /// Module-level inline assembly.
+    #[unstable(feature = "global_asm", issue = "35119",
+               reason = "`global_asm!` is not stable enough for use and is subject to change")]
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro global_asm("assembly") { /* compiler built-in */ }
+
+    /// Prints passed tokens into the standard output.
+    #[unstable(feature = "log_syntax", issue = "29598",
+               reason = "`log_syntax!` is not stable enough for use and is subject to change")]
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro log_syntax($($arg:tt)*) { /* compiler built-in */ }
+
+    /// Enables or disables tracing functionality used for debugging other macros.
+    #[unstable(feature = "trace_macros", issue = "29598",
+               reason = "`trace_macros` is not stable enough for use and is subject to change")]
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro trace_macros {
+        (true) => ({ /* compiler built-in */ }),
+        (false) => ({ /* compiler built-in */ })
+    }
+
+    /// Attribute macro applied to a function to turn it into a unit test.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro test($item:item) { /* compiler built-in */ }
+
+    /// Attribute macro applied to a function to turn it into a benchmark test.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro bench($item:item) { /* compiler built-in */ }
+
+    /// An implementation detail of the `#[test]` and `#[bench]` macros.
+    #[unstable(feature = "custom_test_frameworks", issue = "50297",
+               reason = "custom test frameworks are an unstable feature")]
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    pub macro test_case($item:item) { /* compiler built-in */ }
+
+    /// Derive macro generating an impl of the trait `Clone`.
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow_internal_unstable(core_intrinsics, derive_clone_copy)]
+    pub macro Clone($item:item) { /* compiler built-in */ }
+
+    /// Derive macro generating an impl of the trait `Copy`.
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow_internal_unstable(core_intrinsics, derive_clone_copy)]
+    pub macro Copy($item:item) { /* compiler built-in */ }
+
+    /// Derive macro generating an impl of the trait `Debug`.
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow_internal_unstable(core_intrinsics)]
+    pub macro Debug($item:item) { /* compiler built-in */ }
+
+    /// Unstable implementation detail of the `rustc` compiler, do not use.
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_deprecated(
+        since = "1.0.0",
+        reason = "derive(Decodable) is deprecated in favor of derive(RustcDecodable)",
+        suggestion = "RustcDecodable",
+    )]
+    #[allow_internal_unstable(core_intrinsics, libstd_sys_internals)]
+    pub macro Decodable($item:item) { /* compiler built-in */ }
+
+    /// Derive macro generating an impl of the trait `Default`.
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow_internal_unstable(core_intrinsics)]
+    pub macro Default($item:item) { /* compiler built-in */ }
+
+    /// Unstable implementation detail of the `rustc` compiler, do not use.
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_deprecated(
+        since = "1.0.0",
+        reason = "derive(Encodable) is deprecated in favor of derive(RustcEncodable)",
+        suggestion = "RustcEncodable",
+    )]
+    #[allow_internal_unstable(core_intrinsics)]
+    pub macro Encodable($item:item) { /* compiler built-in */ }
+
+    /// Derive macro generating an impl of the trait `Eq`.
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow_internal_unstable(core_intrinsics, derive_eq)]
+    pub macro Eq($item:item) { /* compiler built-in */ }
+
+    /// Derive macro generating an impl of the trait `Hash`.
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow_internal_unstable(core_intrinsics)]
+    pub macro Hash($item:item) { /* compiler built-in */ }
+
+    /// Derive macro generating an impl of the trait `Ord`.
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow_internal_unstable(core_intrinsics)]
+    pub macro Ord($item:item) { /* compiler built-in */ }
+
+    /// Derive macro generating an impl of the trait `PartialEq`.
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow_internal_unstable(core_intrinsics)]
+    pub macro PartialEq($item:item) { /* compiler built-in */ }
+
+    /// Derive macro generating an impl of the trait `PartialOrd`.
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow_internal_unstable(core_intrinsics)]
+    pub macro PartialOrd($item:item) { /* compiler built-in */ }
+
+    /// Unstable implementation detail of the `rustc` compiler, do not use.
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow_internal_unstable(core_intrinsics, libstd_sys_internals)]
+    pub macro RustcDecodable($item:item) { /* compiler built-in */ }
+
+    /// Unstable implementation detail of the `rustc` compiler, do not use.
+    #[rustc_builtin_macro]
+    #[rustc_macro_transparency = "semitransparent"]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow_internal_unstable(core_intrinsics)]
+    pub macro RustcEncodable($item:item) { /* compiler built-in */ }
 }
diff --git a/src/libcore/unicode/unicode.py b/src/libcore/unicode/unicode.py
index ae356c3ff44..a0539cd9ca9 100755
--- a/src/libcore/unicode/unicode.py
+++ b/src/libcore/unicode/unicode.py
@@ -1,147 +1,350 @@
 #!/usr/bin/env python
 
-# This script uses the following Unicode tables:
-# - DerivedCoreProperties.txt
-# - DerivedNormalizationProps.txt
-# - EastAsianWidth.txt
-# - auxiliary/GraphemeBreakProperty.txt
-# - PropList.txt
-# - ReadMe.txt
-# - Scripts.txt
-# - UnicodeData.txt
-#
-# Since this should not require frequent updates, we just store this
-# out-of-line and check the tables.rs file into git.
+"""
+Regenerate Unicode tables (tables.rs).
+"""
 
-import fileinput, re, os, sys, operator, math, datetime
+# This script uses the Unicode tables as defined
+# in the UnicodeFiles class.
 
-# The directory in which this file resides.
-fdir = os.path.dirname(os.path.realpath(__file__)) + "/"
+# Since this should not require frequent updates, we just store this
+# out-of-line and check the tables.rs file into git.
 
-preamble = '''
+# Note that the "curl" program is required for operation.
+# This script is compatible with Python 2.7 and 3.x.
+
+import argparse
+import datetime
+import fileinput
+import itertools
+import os
+import re
+import textwrap
+import subprocess
+
+from collections import defaultdict, namedtuple
+
+try:
+    # Python 3
+    from itertools import zip_longest
+    from io import StringIO
+except ImportError:
+    # Python 2 compatibility
+    zip_longest = itertools.izip_longest
+    from StringIO import StringIO
+
+try:
+    # Completely optional type hinting
+    # (Python 2 compatible using comments,
+    # see: https://mypy.readthedocs.io/en/latest/python2.html)
+    # This is very helpful in typing-aware IDE like PyCharm.
+    from typing import Any, Callable, Dict, Iterable, Iterator, List, Optional, Set, Tuple
+except ImportError:
+    pass
+
+
+# We don't use enum.Enum because of Python 2.7 compatibility.
+class UnicodeFiles(object):
+    # ReadMe does not contain any Unicode data, we
+    # only use it to extract versions.
+    README = "ReadMe.txt"
+
+    DERIVED_CORE_PROPERTIES = "DerivedCoreProperties.txt"
+    DERIVED_NORMALIZATION_PROPS = "DerivedNormalizationProps.txt"
+    PROPS = "PropList.txt"
+    SCRIPTS = "Scripts.txt"
+    SPECIAL_CASING = "SpecialCasing.txt"
+    UNICODE_DATA = "UnicodeData.txt"
+
+
+# The order doesn't really matter (Python < 3.6 won't preserve it),
+# we only want to aggregate all the file names.
+ALL_UNICODE_FILES = tuple(
+    value for name, value in UnicodeFiles.__dict__.items()
+    if not name.startswith("_")
+)
+
+assert len(ALL_UNICODE_FILES) == 7, "Unexpected number of unicode files"
+
+# The directory this file is located in.
+THIS_DIR = os.path.dirname(os.path.realpath(__file__))
+
+# Where to download the Unicode data.  The downloaded files
+# will be placed in sub-directories named after Unicode version.
+FETCH_DIR = os.path.join(THIS_DIR, "downloaded")
+
+FETCH_URL_LATEST = "ftp://ftp.unicode.org/Public/UNIDATA/{filename}"
+FETCH_URL_VERSION = "ftp://ftp.unicode.org/Public/{version}/ucd/{filename}"
+
+PREAMBLE = """\
 // NOTE: The following code was generated by "./unicode.py", do not edit directly
 
 #![allow(missing_docs, non_upper_case_globals, non_snake_case)]
 
 use unicode::version::UnicodeVersion;
 use unicode::bool_trie::{{BoolTrie, SmallBoolTrie}};
-'''.format(year = datetime.datetime.now().year)
+""".format(year=datetime.datetime.now().year)
 
 # Mapping taken from Table 12 from:
 # http://www.unicode.org/reports/tr44/#General_Category_Values
-expanded_categories = {
-    'Lu': ['LC', 'L'], 'Ll': ['LC', 'L'], 'Lt': ['LC', 'L'],
-    'Lm': ['L'], 'Lo': ['L'],
-    'Mn': ['M'], 'Mc': ['M'], 'Me': ['M'],
-    'Nd': ['N'], 'Nl': ['N'], 'No': ['N'],
-    'Pc': ['P'], 'Pd': ['P'], 'Ps': ['P'], 'Pe': ['P'],
-    'Pi': ['P'], 'Pf': ['P'], 'Po': ['P'],
-    'Sm': ['S'], 'Sc': ['S'], 'Sk': ['S'], 'So': ['S'],
-    'Zs': ['Z'], 'Zl': ['Z'], 'Zp': ['Z'],
-    'Cc': ['C'], 'Cf': ['C'], 'Cs': ['C'], 'Co': ['C'], 'Cn': ['C'],
+EXPANDED_CATEGORIES = {
+    "Lu": ["LC", "L"], "Ll": ["LC", "L"], "Lt": ["LC", "L"],
+    "Lm": ["L"], "Lo": ["L"],
+    "Mn": ["M"], "Mc": ["M"], "Me": ["M"],
+    "Nd": ["N"], "Nl": ["N"], "No": ["N"],
+    "Pc": ["P"], "Pd": ["P"], "Ps": ["P"], "Pe": ["P"],
+    "Pi": ["P"], "Pf": ["P"], "Po": ["P"],
+    "Sm": ["S"], "Sc": ["S"], "Sk": ["S"], "So": ["S"],
+    "Zs": ["Z"], "Zl": ["Z"], "Zp": ["Z"],
+    "Cc": ["C"], "Cf": ["C"], "Cs": ["C"], "Co": ["C"], "Cn": ["C"],
 }
 
-# these are the surrogate codepoints, which are not valid rust characters
-surrogate_codepoints = (0xd800, 0xdfff)
+# This is the (inclusive) range of surrogate codepoints.
+# These are not valid Rust characters.
+SURROGATE_CODEPOINTS_RANGE = (0xd800, 0xdfff)
+
+UnicodeData = namedtuple(
+    "UnicodeData", (
+        # Conversions:
+        "to_upper", "to_lower", "to_title",
+
+        # Decompositions: canonical decompositions, compatibility decomp
+        "canon_decomp", "compat_decomp",
+
+        # Grouped: general categories and combining characters
+        "general_categories", "combines",
+    )
+)
+
+UnicodeVersion = namedtuple(
+    "UnicodeVersion", ("major", "minor", "micro", "as_str")
+)
+
+
+def fetch_files(version=None):
+    # type: (str) -> UnicodeVersion
+    """
+    Fetch all the Unicode files from unicode.org.
+
+    This will use cached files (stored in `FETCH_DIR`) if they exist,
+    creating them if they don't.  In any case, the Unicode version
+    is always returned.
+
+    :param version: The desired Unicode version, as string.
+        (If None, defaults to latest final release available,
+         querying the unicode.org service).
+    """
+    have_version = check_stored_version(version)
+    if have_version:
+        return have_version
+
+    if version:
+        # Check if the desired version exists on the server.
+        get_fetch_url = lambda name: FETCH_URL_VERSION.format(version=version, filename=name)
+    else:
+        # Extract the latest version.
+        get_fetch_url = lambda name: FETCH_URL_LATEST.format(filename=name)
+
+    readme_url = get_fetch_url(UnicodeFiles.README)
+
+    print("Fetching: {}".format(readme_url))
+    readme_content = subprocess.check_output(("curl", readme_url))
+
+    unicode_version = parse_readme_unicode_version(
+        readme_content.decode("utf8")
+    )
+
+    download_dir = get_unicode_dir(unicode_version)
+    if not os.path.exists(download_dir):
+        # For 2.7 compat, we don't use `exist_ok=True`.
+        os.makedirs(download_dir)
+
+    for filename in ALL_UNICODE_FILES:
+        file_path = get_unicode_file_path(unicode_version, filename)
+
+        if os.path.exists(file_path):
+            # Assume file on the server didn't change if it's been saved before.
+            continue
+
+        if filename == UnicodeFiles.README:
+            with open(file_path, "wb") as fd:
+                fd.write(readme_content)
+        else:
+            url = get_fetch_url(filename)
+            print("Fetching: {}".format(url))
+            subprocess.check_call(("curl", "-o", file_path, url))
+
+    return unicode_version
+
+
+def check_stored_version(version):
+    # type: (Optional[str]) -> Optional[UnicodeVersion]
+    """
+    Given desired Unicode version, return the version
+    if stored files are all present, and `None` otherwise.
+    """
+    if not version:
+        # If no desired version specified, we should check what's the latest
+        # version, skipping stored version checks.
+        return None
+
+    fetch_dir = os.path.join(FETCH_DIR, version)
 
-def fetch(f):
-    path = fdir + os.path.basename(f)
-    if not os.path.exists(path):
-        os.system("curl -o {0}{1} ftp://ftp.unicode.org/Public/UNIDATA/{1}".format(fdir, f))
+    for filename in ALL_UNICODE_FILES:
+        file_path = os.path.join(fetch_dir, filename)
+
+        if not os.path.exists(file_path):
+            return None
+
+    with open(os.path.join(fetch_dir, UnicodeFiles.README)) as fd:
+        return parse_readme_unicode_version(fd.read())
+
+
+def parse_readme_unicode_version(readme_content):
+    # type: (str) -> UnicodeVersion
+    """
+    Parse the Unicode version contained in their `ReadMe.txt` file.
+    """
+    # "Raw string" is necessary for \d not being treated as escape char
+    # (for the sake of compat with future Python versions).
+    # See: https://docs.python.org/3.6/whatsnew/3.6.html#deprecated-python-behavior
+    pattern = r"for Version (\d+)\.(\d+)\.(\d+) of the Unicode"
+    groups = re.search(pattern, readme_content).groups()
+
+    return UnicodeVersion(*map(int, groups), as_str=".".join(groups))
+
+
+def get_unicode_dir(unicode_version):
+    # type: (UnicodeVersion) -> str
+    """
+    Indicate in which parent dir the Unicode data files should be stored.
+
+    This returns a full, absolute path.
+    """
+    return os.path.join(FETCH_DIR, unicode_version.as_str)
+
+
+def get_unicode_file_path(unicode_version, filename):
+    # type: (UnicodeVersion, str) -> str
+    """
+    Indicate where the Unicode data file should be stored.
+    """
+    return os.path.join(get_unicode_dir(unicode_version), filename)
 
-    if not os.path.exists(path):
-        sys.stderr.write("cannot load %s" % f)
-        exit(1)
 
 def is_surrogate(n):
-    return surrogate_codepoints[0] <= n <= surrogate_codepoints[1]
-
-def load_unicode_data(f):
-    fetch(f)
-    gencats = {}
-    to_lower = {}
-    to_upper = {}
-    to_title = {}
-    combines = {}
-    canon_decomp = {}
-    compat_decomp = {}
-
-    udict = {}
+    # type: (int) -> bool
+    """
+    Tell if given codepoint is a surrogate (not a valid Rust character).
+    """
+    return SURROGATE_CODEPOINTS_RANGE[0] <= n <= SURROGATE_CODEPOINTS_RANGE[1]
+
+
+def load_unicode_data(file_path):
+    # type: (str) -> UnicodeData
+    """
+    Load main Unicode data.
+    """
+    # Conversions
+    to_lower = {}   # type: Dict[int, Tuple[int, int, int]]
+    to_upper = {}   # type: Dict[int, Tuple[int, int, int]]
+    to_title = {}   # type: Dict[int, Tuple[int, int, int]]
+
+    # Decompositions
+    compat_decomp = {}   # type: Dict[int, List[int]]
+    canon_decomp = {}    # type: Dict[int, List[int]]
+
+    # Combining characters
+    # FIXME: combines are not used
+    combines = defaultdict(set)   # type: Dict[str, Set[int]]
+
+    # Categories
+    general_categories = defaultdict(set)   # type: Dict[str, Set[int]]
+    category_assigned_codepoints = set()    # type: Set[int]
+
+    all_codepoints = {}
+
     range_start = -1
-    for line in fileinput.input(fdir + f):
-        data = line.split(';')
+
+    for line in fileinput.input(file_path):
+        data = line.split(";")
         if len(data) != 15:
             continue
-        cp = int(data[0], 16)
-        if is_surrogate(cp):
+        codepoint = int(data[0], 16)
+        if is_surrogate(codepoint):
             continue
         if range_start >= 0:
-            for i in range(range_start, cp):
-                udict[i] = data
+            for i in range(range_start, codepoint):
+                all_codepoints[i] = data
             range_start = -1
         if data[1].endswith(", First>"):
-            range_start = cp
+            range_start = codepoint
             continue
-        udict[cp] = data
+        all_codepoints[codepoint] = data
 
-    for code in udict:
+    for code, data in all_codepoints.items():
         (code_org, name, gencat, combine, bidi,
          decomp, deci, digit, num, mirror,
-         old, iso, upcase, lowcase, titlecase) = udict[code]
+         old, iso, upcase, lowcase, titlecase) = data
+
+        # Generate char to char direct common and simple conversions:
 
-        # generate char to char direct common and simple conversions
-        # uppercase to lowercase
+        # Uppercase to lowercase
         if lowcase != "" and code_org != lowcase:
             to_lower[code] = (int(lowcase, 16), 0, 0)
 
-        # lowercase to uppercase
+        # Lowercase to uppercase
         if upcase != "" and code_org != upcase:
             to_upper[code] = (int(upcase, 16), 0, 0)
 
-        # title case
+        # Title case
         if titlecase.strip() != "" and code_org != titlecase:
             to_title[code] = (int(titlecase, 16), 0, 0)
 
-        # store decomposition, if given
-        if decomp != "":
-            if decomp.startswith('<'):
-                seq = []
-                for i in decomp.split()[1:]:
-                    seq.append(int(i, 16))
-                compat_decomp[code] = seq
+        # Store decomposition, if given
+        if decomp:
+            decompositions = decomp.split()[1:]
+            decomp_code_points = [int(i, 16) for i in decompositions]
+
+            if decomp.startswith("<"):
+                # Compatibility decomposition
+                compat_decomp[code] = decomp_code_points
             else:
-                seq = []
-                for i in decomp.split():
-                    seq.append(int(i, 16))
-                canon_decomp[code] = seq
-
-        # place letter in categories as appropriate
-        for cat in [gencat, "Assigned"] + expanded_categories.get(gencat, []):
-            if cat not in gencats:
-                gencats[cat] = []
-            gencats[cat].append(code)
-
-        # record combining class, if any
+                # Canonical decomposition
+                canon_decomp[code] = decomp_code_points
+
+        # Place letter in categories as appropriate.
+        for cat in itertools.chain((gencat, ), EXPANDED_CATEGORIES.get(gencat, [])):
+            general_categories[cat].add(code)
+            category_assigned_codepoints.add(code)
+
+        # Record combining class, if any.
         if combine != "0":
-            if combine not in combines:
-                combines[combine] = []
-            combines[combine].append(code)
-
-    # generate Not_Assigned from Assigned
-    gencats["Cn"] = gen_unassigned(gencats["Assigned"])
-    # Assigned is not a real category
-    del(gencats["Assigned"])
+            combines[combine].add(code)
+
+    # Generate Not_Assigned from Assigned.
+    general_categories["Cn"] = get_unassigned_codepoints(category_assigned_codepoints)
+
     # Other contains Not_Assigned
-    gencats["C"].extend(gencats["Cn"])
-    gencats = group_cats(gencats)
-    combines = to_combines(group_cats(combines))
+    general_categories["C"].update(general_categories["Cn"])
+
+    grouped_categories = group_categories(general_categories)
 
-    return (canon_decomp, compat_decomp, gencats, combines, to_upper, to_lower, to_title)
+    # FIXME: combines are not used
+    return UnicodeData(
+        to_lower=to_lower, to_upper=to_upper, to_title=to_title,
+        compat_decomp=compat_decomp, canon_decomp=canon_decomp,
+        general_categories=grouped_categories, combines=combines,
+    )
 
-def load_special_casing(f, to_upper, to_lower, to_title):
-    fetch(f)
-    for line in fileinput.input(fdir + f):
-        data = line.split('#')[0].split(';')
+
+def load_special_casing(file_path, unicode_data):
+    # type: (str, UnicodeData) -> None
+    """
+    Load special casing data and enrich given Unicode data.
+    """
+    for line in fileinput.input(file_path):
+        data = line.split("#")[0].split(";")
         if len(data) == 5:
             code, lower, title, upper, _comment = data
         elif len(data) == 6:
@@ -155,243 +358,399 @@ def load_special_casing(f, to_upper, to_lower, to_title):
         title = title.strip()
         upper = upper.strip()
         key = int(code, 16)
-        for (map_, values) in [(to_lower, lower), (to_upper, upper), (to_title, title)]:
+        for (map_, values) in ((unicode_data.to_lower, lower),
+                               (unicode_data.to_upper, upper),
+                               (unicode_data.to_title, title)):
             if values != code:
-                values = [int(i, 16) for i in values.split()]
-                for _ in range(len(values), 3):
-                    values.append(0)
-                assert len(values) == 3
-                map_[key] = values
-
-def group_cats(cats):
-    cats_out = {}
-    for cat in cats:
-        cats_out[cat] = group_cat(cats[cat])
-    return cats_out
-
-def group_cat(cat):
-    cat_out = []
-    letters = sorted(set(cat))
-    cur_start = letters.pop(0)
-    cur_end = cur_start
-    for letter in letters:
-        assert letter > cur_end, \
-            "cur_end: %s, letter: %s" % (hex(cur_end), hex(letter))
-        if letter == cur_end + 1:
-            cur_end = letter
-        else:
-            cat_out.append((cur_start, cur_end))
-            cur_start = cur_end = letter
-    cat_out.append((cur_start, cur_end))
-    return cat_out
-
-def ungroup_cat(cat):
-    cat_out = []
-    for (lo, hi) in cat:
-        while lo <= hi:
-            cat_out.append(lo)
-            lo += 1
-    return cat_out
-
-def gen_unassigned(assigned):
-    assigned = set(assigned)
-    return ([i for i in range(0, 0xd800) if i not in assigned] +
-            [i for i in range(0xe000, 0x110000) if i not in assigned])
-
-def to_combines(combs):
-    combs_out = []
-    for comb in combs:
-        for (lo, hi) in combs[comb]:
-            combs_out.append((lo, hi, comb))
-    combs_out.sort(key=lambda comb: comb[0])
-    return combs_out
-
-def format_table_content(f, content, indent):
-    line = " "*indent
+                split = values.split()
+
+                codepoints = list(itertools.chain(
+                    (int(i, 16) for i in split),
+                    (0 for _ in range(len(split), 3))
+                ))
+
+                assert len(codepoints) == 3
+                map_[key] = codepoints
+
+
+def group_categories(mapping):
+    # type: (Dict[Any, Iterable[int]]) -> Dict[str, List[Tuple[int, int]]]
+    """
+    Group codepoints mapped in "categories".
+    """
+    return {category: group_codepoints(codepoints)
+            for category, codepoints in mapping.items()}
+
+
+def group_codepoints(codepoints):
+    # type: (Iterable[int]) -> List[Tuple[int, int]]
+    """
+    Group integral values into continuous, disjoint value ranges.
+
+    Performs value deduplication.
+
+    :return: sorted list of pairs denoting start and end of codepoint
+        group values, both ends inclusive.
+
+    >>> group_codepoints([1, 2, 10, 11, 12, 3, 4])
+    [(1, 4), (10, 12)]
+    >>> group_codepoints([1])
+    [(1, 1)]
+    >>> group_codepoints([1, 5, 6])
+    [(1, 1), (5, 6)]
+    >>> group_codepoints([])
+    []
+    """
+    sorted_codes = sorted(set(codepoints))
+    result = []     # type: List[Tuple[int, int]]
+
+    if not sorted_codes:
+        return result
+
+    next_codes = sorted_codes[1:]
+    start_code = sorted_codes[0]
+
+    for code, next_code in zip_longest(sorted_codes, next_codes, fillvalue=None):
+        if next_code is None or next_code - code != 1:
+            result.append((start_code, code))
+            start_code = next_code
+
+    return result
+
+
+def ungroup_codepoints(codepoint_pairs):
+    # type: (Iterable[Tuple[int, int]]) -> List[int]
+    """
+    The inverse of group_codepoints -- produce a flat list of values
+    from value range pairs.
+
+    >>> ungroup_codepoints([(1, 4), (10, 12)])
+    [1, 2, 3, 4, 10, 11, 12]
+    >>> ungroup_codepoints([(1, 1), (5, 6)])
+    [1, 5, 6]
+    >>> ungroup_codepoints(group_codepoints([1, 2, 7, 8]))
+    [1, 2, 7, 8]
+    >>> ungroup_codepoints([])
+    []
+    """
+    return list(itertools.chain.from_iterable(
+        range(lo, hi + 1) for lo, hi in codepoint_pairs
+    ))
+
+
+def get_unassigned_codepoints(assigned_codepoints):
+    # type: (Set[int]) -> Set[int]
+    """
+    Given a set of "assigned" codepoints, return a set
+    of these that are not in assigned and not surrogate.
+    """
+    return {i for i in range(0, 0x110000)
+            if i not in assigned_codepoints and not is_surrogate(i)}
+
+
+def generate_table_lines(items, indent, wrap=98):
+    # type: (Iterable[str], int, int) -> Iterator[str]
+    """
+    Given table items, generate wrapped lines of text with comma-separated items.
+
+    This is a generator function.
+
+    :param wrap: soft wrap limit (characters per line), integer.
+    """
+    line = " " * indent
     first = True
-    for chunk in content.split(","):
-        if len(line) + len(chunk) < 98:
+    for item in items:
+        if len(line) + len(item) < wrap:
             if first:
-                line += chunk
+                line += item
             else:
-                line += ", " + chunk
+                line += ", " + item
             first = False
         else:
-            f.write(line + ",\n")
-            line = " "*indent + chunk
-    f.write(line)
-
-def load_properties(f, interestingprops):
-    fetch(f)
-    props = {}
-    re1 = re.compile("^ *([0-9A-F]+) *; *(\w+)")
-    re2 = re.compile("^ *([0-9A-F]+)\.\.([0-9A-F]+) *; *(\w+)")
-
-    for line in fileinput.input(fdir + os.path.basename(f)):
-        prop = None
-        d_lo = 0
-        d_hi = 0
-        m = re1.match(line)
-        if m:
-            d_lo = m.group(1)
-            d_hi = m.group(1)
-            prop = m.group(2)
-        else:
-            m = re2.match(line)
-            if m:
-                d_lo = m.group(1)
-                d_hi = m.group(2)
-                prop = m.group(3)
+            yield line + ",\n"
+            line = " " * indent + item
+
+    yield line
+
+
+def load_properties(file_path, interesting_props):
+    # type: (str, Iterable[str]) -> Dict[str, List[Tuple[int, int]]]
+    """
+    Load properties data and return in grouped form.
+    """
+    props = defaultdict(list)   # type: Dict[str, List[Tuple[int, int]]]
+    # "Raw string" is necessary for `\.` and `\w` not to be treated as escape chars
+    # (for the sake of compat with future Python versions).
+    # See: https://docs.python.org/3.6/whatsnew/3.6.html#deprecated-python-behavior
+    re1 = re.compile(r"^ *([0-9A-F]+) *; *(\w+)")
+    re2 = re.compile(r"^ *([0-9A-F]+)\.\.([0-9A-F]+) *; *(\w+)")
+
+    for line in fileinput.input(file_path):
+        match = re1.match(line) or re2.match(line)
+        if match:
+            groups = match.groups()
+
+            if len(groups) == 2:
+                # `re1` matched (2 groups).
+                d_lo, prop = groups
+                d_hi = d_lo
             else:
-                continue
-        if interestingprops and prop not in interestingprops:
+                d_lo, d_hi, prop = groups
+        else:
+            continue
+
+        if interesting_props and prop not in interesting_props:
             continue
-        d_lo = int(d_lo, 16)
-        d_hi = int(d_hi, 16)
-        if prop not in props:
-            props[prop] = []
-        props[prop].append((d_lo, d_hi))
 
-    # optimize if possible
+        lo_value = int(d_lo, 16)
+        hi_value = int(d_hi, 16)
+
+        props[prop].append((lo_value, hi_value))
+
+    # Optimize if possible.
     for prop in props:
-        props[prop] = group_cat(ungroup_cat(props[prop]))
+        props[prop] = group_codepoints(ungroup_codepoints(props[prop]))
 
     return props
 
-def escape_char(c):
-    return "'\\u{%x}'" % c if c != 0 else "'\\0'"
 
-def emit_table(f, name, t_data, t_type = "&[(char, char)]", is_pub=True,
-        pfun=lambda x: "(%s,%s)" % (escape_char(x[0]), escape_char(x[1]))):
+def escape_char(c):
+    # type: (int) -> str
+    r"""
+    Escape a codepoint for use as Rust char literal.
+
+    Outputs are OK to use as Rust source code as char literals
+    and they also include necessary quotes.
+
+    >>> escape_char(97)
+    "'\\u{61}'"
+    >>> escape_char(0)
+    "'\\0'"
+    """
+    return r"'\u{%x}'" % c if c != 0 else r"'\0'"
+
+
+def format_char_pair(pair):
+    # type: (Tuple[int, int]) -> str
+    """
+    Format a pair of two Rust chars.
+    """
+    return "(%s,%s)" % (escape_char(pair[0]), escape_char(pair[1]))
+
+
+def generate_table(
+    name,   # type: str
+    items,  # type: List[Tuple[int, int]]
+    decl_type="&[(char, char)]",    # type: str
+    is_pub=True,                    # type: bool
+    format_item=format_char_pair,   # type: Callable[[Tuple[int, int]], str]
+):
+    # type: (...) -> Iterator[str]
+    """
+    Generate a nicely formatted Rust constant "table" array.
+
+    This generates actual Rust code.
+    """
     pub_string = ""
     if is_pub:
         pub_string = "pub "
-    f.write("    %sconst %s: %s = &[\n" % (pub_string, name, t_type))
-    data = ""
+
+    yield "    %sconst %s: %s = &[\n" % (pub_string, name, decl_type)
+
+    data = []
     first = True
-    for dat in t_data:
+    for item in items:
         if not first:
-            data += ","
+            data.append(",")
         first = False
-        data += pfun(dat)
-    format_table_content(f, data, 8)
-    f.write("\n    ];\n\n")
+        data.extend(format_item(item))
 
-def compute_trie(rawdata, chunksize):
+    for table_line in generate_table_lines("".join(data).split(","), 8):
+        yield table_line
+
+    yield "\n    ];\n\n"
+
+
+def compute_trie(raw_data, chunk_size):
+    # type: (List[int], int) -> Tuple[List[int], List[int]]
+    """
+    Compute postfix-compressed trie.
+
+    See: bool_trie.rs for more details.
+
+    >>> compute_trie([1, 2, 3, 1, 2, 3, 4, 5, 6], 3)
+    ([0, 0, 1], [1, 2, 3, 4, 5, 6])
+    >>> compute_trie([1, 2, 3, 1, 2, 4, 4, 5, 6], 3)
+    ([0, 1, 2], [1, 2, 3, 1, 2, 4, 4, 5, 6])
+    """
     root = []
-    childmap = {}
+    childmap = {}       # type: Dict[Tuple[int, ...], int]
     child_data = []
-    for i in range(len(rawdata) // chunksize):
-        data = rawdata[i * chunksize: (i + 1) * chunksize]
-        child = '|'.join(map(str, data))
+
+    assert len(raw_data) % chunk_size == 0, "Chunks must be equally sized"
+
+    for i in range(len(raw_data) // chunk_size):
+        data = raw_data[i * chunk_size : (i + 1) * chunk_size]
+
+        # Postfix compression of child nodes (data chunks)
+        # (identical child nodes are shared).
+
+        # Make a tuple out of the list so it's hashable.
+        child = tuple(data)
         if child not in childmap:
             childmap[child] = len(childmap)
             child_data.extend(data)
+
         root.append(childmap[child])
-    return (root, child_data)
 
-def emit_bool_trie(f, name, t_data, is_pub=True):
-    CHUNK = 64
+    return root, child_data
+
+
+def generate_bool_trie(name, codepoint_ranges, is_pub=True):
+    # type: (str, List[Tuple[int, int]], bool) -> Iterator[str]
+    """
+    Generate Rust code for BoolTrie struct.
+
+    This yields string fragments that should be joined to produce
+    the final string.
+
+    See: `bool_trie.rs`.
+    """
+    chunk_size = 64
     rawdata = [False] * 0x110000
-    for (lo, hi) in t_data:
+    for (lo, hi) in codepoint_ranges:
         for cp in range(lo, hi + 1):
             rawdata[cp] = True
 
-    # convert to bitmap chunks of 64 bits each
+    # Convert to bitmap chunks of `chunk_size` bits each.
     chunks = []
-    for i in range(0x110000 // CHUNK):
+    for i in range(0x110000 // chunk_size):
         chunk = 0
-        for j in range(64):
-            if rawdata[i * 64 + j]:
+        for j in range(chunk_size):
+            if rawdata[i * chunk_size + j]:
                 chunk |= 1 << j
         chunks.append(chunk)
 
     pub_string = ""
     if is_pub:
         pub_string = "pub "
-    f.write("    %sconst %s: &super::BoolTrie = &super::BoolTrie {\n" % (pub_string, name))
-    f.write("        r1: [\n")
-    data = ','.join('0x%016x' % chunk for chunk in chunks[0:0x800 // CHUNK])
-    format_table_content(f, data, 12)
-    f.write("\n        ],\n")
+    yield "    %sconst %s: &super::BoolTrie = &super::BoolTrie {\n" % (pub_string, name)
+    yield "        r1: [\n"
+    data = ("0x%016x" % chunk for chunk in chunks[:0x800 // chunk_size])
+    for fragment in generate_table_lines(data, 12):
+        yield fragment
+    yield "\n        ],\n"
 
     # 0x800..0x10000 trie
-    (r2, r3) = compute_trie(chunks[0x800 // CHUNK : 0x10000 // CHUNK], 64 // CHUNK)
-    f.write("        r2: [\n")
-    data = ','.join(str(node) for node in r2)
-    format_table_content(f, data, 12)
-    f.write("\n        ],\n")
-    f.write("        r3: &[\n")
-    data = ','.join('0x%016x' % chunk for chunk in r3)
-    format_table_content(f, data, 12)
-    f.write("\n        ],\n")
+    (r2, r3) = compute_trie(chunks[0x800 // chunk_size : 0x10000 // chunk_size], 64 // chunk_size)
+    yield "        r2: [\n"
+    data = map(str, r2)
+    for fragment in generate_table_lines(data, 12):
+        yield fragment
+    yield "\n        ],\n"
+
+    yield "        r3: &[\n"
+    data = ("0x%016x" % node for node in r3)
+    for fragment in generate_table_lines(data, 12):
+        yield fragment
+    yield "\n        ],\n"
 
     # 0x10000..0x110000 trie
-    (mid, r6) = compute_trie(chunks[0x10000 // CHUNK : 0x110000 // CHUNK], 64 // CHUNK)
+    (mid, r6) = compute_trie(chunks[0x10000 // chunk_size : 0x110000 // chunk_size],
+                             64 // chunk_size)
     (r4, r5) = compute_trie(mid, 64)
-    f.write("        r4: [\n")
-    data = ','.join(str(node) for node in r4)
-    format_table_content(f, data, 12)
-    f.write("\n        ],\n")
-    f.write("        r5: &[\n")
-    data = ','.join(str(node) for node in r5)
-    format_table_content(f, data, 12)
-    f.write("\n        ],\n")
-    f.write("        r6: &[\n")
-    data = ','.join('0x%016x' % chunk for chunk in r6)
-    format_table_content(f, data, 12)
-    f.write("\n        ],\n")
-
-    f.write("    };\n\n")
-
-def emit_small_bool_trie(f, name, t_data, is_pub=True):
-    last_chunk = max(hi // 64 for (lo, hi) in t_data)
+
+    yield "        r4: [\n"
+    data = map(str, r4)
+    for fragment in generate_table_lines(data, 12):
+        yield fragment
+    yield "\n        ],\n"
+
+    yield "        r5: &[\n"
+    data = map(str, r5)
+    for fragment in generate_table_lines(data, 12):
+        yield fragment
+    yield "\n        ],\n"
+
+    yield "        r6: &[\n"
+    data = ("0x%016x" % node for node in r6)
+    for fragment in generate_table_lines(data, 12):
+        yield fragment
+    yield "\n        ],\n"
+
+    yield "    };\n\n"
+
+
+def generate_small_bool_trie(name, codepoint_ranges, is_pub=True):
+    # type: (str, List[Tuple[int, int]], bool) -> Iterator[str]
+    """
+    Generate Rust code for `SmallBoolTrie` struct.
+
+    See: `bool_trie.rs`.
+    """
+    last_chunk = max(hi // 64 for (lo, hi) in codepoint_ranges)
     n_chunks = last_chunk + 1
     chunks = [0] * n_chunks
-    for (lo, hi) in t_data:
+    for (lo, hi) in codepoint_ranges:
         for cp in range(lo, hi + 1):
-            if cp // 64 >= len(chunks):
-                print(cp, cp // 64, len(chunks), lo, hi)
+            assert cp // 64 < len(chunks)
             chunks[cp // 64] |= 1 << (cp & 63)
 
     pub_string = ""
     if is_pub:
         pub_string = "pub "
-    f.write("    %sconst %s: &super::SmallBoolTrie = &super::SmallBoolTrie {\n"
-            % (pub_string, name))
+
+    yield ("    %sconst %s: &super::SmallBoolTrie = &super::SmallBoolTrie {\n"
+           % (pub_string, name))
 
     (r1, r2) = compute_trie(chunks, 1)
 
-    f.write("        r1: &[\n")
-    data = ','.join(str(node) for node in r1)
-    format_table_content(f, data, 12)
-    f.write("\n        ],\n")
-
-    f.write("        r2: &[\n")
-    data = ','.join('0x%016x' % node for node in r2)
-    format_table_content(f, data, 12)
-    f.write("\n        ],\n")
-
-    f.write("    };\n\n")
-
-def emit_property_module(f, mod, tbl, emit):
-    f.write("pub mod %s {\n" % mod)
-    for cat in sorted(emit):
-        if cat in ["Cc", "White_Space", "Pattern_White_Space"]:
-            emit_small_bool_trie(f, "%s_table" % cat, tbl[cat])
-            f.write("    pub fn %s(c: char) -> bool {\n" % cat)
-            f.write("        %s_table.lookup(c)\n" % cat)
-            f.write("    }\n\n")
+    yield "        r1: &[\n"
+    data = (str(node) for node in r1)
+    for fragment in generate_table_lines(data, 12):
+        yield fragment
+    yield "\n        ],\n"
+
+    yield "        r2: &[\n"
+    data = ("0x%016x" % node for node in r2)
+    for fragment in generate_table_lines(data, 12):
+        yield fragment
+    yield "\n        ],\n"
+
+    yield "    };\n\n"
+
+
+def generate_property_module(mod, grouped_categories, category_subset):
+    # type: (str, Dict[str, List[Tuple[int, int]]], Iterable[str]) -> Iterator[str]
+    """
+    Generate Rust code for module defining properties.
+    """
+
+    yield "pub mod %s {\n" % mod
+    for cat in sorted(category_subset):
+        if cat in ("Cc", "White_Space", "Pattern_White_Space"):
+            generator = generate_small_bool_trie("%s_table" % cat, grouped_categories[cat])
         else:
-            emit_bool_trie(f, "%s_table" % cat, tbl[cat])
-            f.write("    pub fn %s(c: char) -> bool {\n" % cat)
-            f.write("        %s_table.lookup(c)\n" % cat)
-            f.write("    }\n\n")
-    f.write("}\n\n")
-
-def emit_conversions_module(f, to_upper, to_lower, to_title):
-    f.write("pub mod conversions {")
-    f.write("""
+            generator = generate_bool_trie("%s_table" % cat, grouped_categories[cat])
+
+        for fragment in generator:
+            yield fragment
+
+        yield "    pub fn %s(c: char) -> bool {\n" % cat
+        yield "        %s_table.lookup(c)\n" % cat
+        yield "    }\n\n"
+
+    yield "}\n\n"
+
+
+def generate_conversions_module(unicode_data):
+    # type: (UnicodeData) -> Iterator[str]
+    """
+    Generate Rust code for module defining conversions.
+    """
+
+    yield "pub mod conversions {"
+    yield """
     pub fn to_lower(c: char) -> [char; 3] {
         match bsearch_case_table(c, to_lowercase_table) {
             None        => [c, '\\0', '\\0'],
@@ -408,80 +767,109 @@ def emit_conversions_module(f, to_upper, to_lower, to_title):
 
     fn bsearch_case_table(c: char, table: &[(char, [char; 3])]) -> Option<usize> {
         table.binary_search_by(|&(key, _)| key.cmp(&c)).ok()
-    }
+    }\n\n"""
+
+    decl_type = "&[(char, [char; 3])]"
+    format_conversion = lambda x: "({},[{},{},{}])".format(*(
+        escape_char(c) for c in (x[0], x[1][0], x[1][1], x[1][2])
+    ))
+
+    for fragment in generate_table(
+        name="to_lowercase_table",
+        items=sorted(unicode_data.to_lower.items(), key=lambda x: x[0]),
+        decl_type=decl_type,
+        is_pub=False,
+        format_item=format_conversion
+    ):
+        yield fragment
+
+    for fragment in generate_table(
+        name="to_uppercase_table",
+        items=sorted(unicode_data.to_upper.items(), key=lambda x: x[0]),
+        decl_type=decl_type,
+        is_pub=False,
+        format_item=format_conversion
+    ):
+        yield fragment
+
+    yield "}\n"
+
+
+def parse_args():
+    # type: () -> argparse.Namespace
+    """
+    Parse command line arguments.
+    """
+    parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument("-v", "--version", default=None, type=str,
+                        help="Unicode version to use (if not specified,"
+                             " defaults to latest release).")
+
+    return parser.parse_args()
+
+
+def main():
+    # type: () -> None
+    """
+    Script entry point.
+    """
+    args = parse_args()
+
+    unicode_version = fetch_files(args.version)
+    print("Using Unicode version: {}".format(unicode_version.as_str))
+
+    # All the writing happens entirely in memory, we only write to file
+    # once we have generated the file content (it's not very large, <1 MB).
+    buf = StringIO()
+    buf.write(PREAMBLE)
+
+    unicode_version_notice = textwrap.dedent("""
+    /// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of
+    /// `char` and `str` methods are based on.
+    #[unstable(feature = "unicode_version", issue = "49726")]
+    pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion {{
+        major: {version.major},
+        minor: {version.minor},
+        micro: {version.micro},
+        _priv: (),
+    }};
+    """).format(version=unicode_version)
+    buf.write(unicode_version_notice)
+
+    get_path = lambda f: get_unicode_file_path(unicode_version, f)
+
+    unicode_data = load_unicode_data(get_path(UnicodeFiles.UNICODE_DATA))
+    load_special_casing(get_path(UnicodeFiles.SPECIAL_CASING), unicode_data)
+
+    want_derived = {"XID_Start", "XID_Continue", "Alphabetic", "Lowercase", "Uppercase",
+                    "Cased", "Case_Ignorable", "Grapheme_Extend"}
+    derived = load_properties(get_path(UnicodeFiles.DERIVED_CORE_PROPERTIES), want_derived)
+
+    props = load_properties(get_path(UnicodeFiles.PROPS),
+                            {"White_Space", "Join_Control", "Noncharacter_Code_Point",
+                             "Pattern_White_Space"})
+
+    # Category tables
+    for (name, categories, category_subset) in (
+            ("general_category", unicode_data.general_categories, ["N", "Cc"]),
+            ("derived_property", derived, want_derived),
+            ("property", props, ["White_Space", "Pattern_White_Space"])
+    ):
+        for fragment in generate_property_module(name, categories, category_subset):
+            buf.write(fragment)
+
+    for fragment in generate_conversions_module(unicode_data):
+        buf.write(fragment)
+
+    tables_rs_path = os.path.join(THIS_DIR, "tables.rs")
+
+    # Actually write out the file content.
+    # Will overwrite the file if it exists.
+    with open(tables_rs_path, "w") as fd:
+        fd.write(buf.getvalue())
+
+    print("Regenerated tables.rs.")
 
-""")
-    t_type = "&[(char, [char; 3])]"
-    pfun = lambda x: "(%s,[%s,%s,%s])" % (
-        escape_char(x[0]), escape_char(x[1][0]), escape_char(x[1][1]), escape_char(x[1][2]))
-    emit_table(f, "to_lowercase_table",
-        sorted(to_lower.items(), key=operator.itemgetter(0)),
-        is_pub=False, t_type = t_type, pfun=pfun)
-    emit_table(f, "to_uppercase_table",
-        sorted(to_upper.items(), key=operator.itemgetter(0)),
-        is_pub=False, t_type = t_type, pfun=pfun)
-    f.write("}\n\n")
-
-def emit_norm_module(f, canon, compat, combine, norm_props):
-    canon_keys = sorted(canon.keys())
-
-    compat_keys = sorted(compat.keys())
-
-    canon_comp = {}
-    comp_exclusions = norm_props["Full_Composition_Exclusion"]
-    for char in canon_keys:
-        if any(lo <= char <= hi for lo, hi in comp_exclusions):
-            continue
-        decomp = canon[char]
-        if len(decomp) == 2:
-            if decomp[0] not in canon_comp:
-                canon_comp[decomp[0]] = []
-            canon_comp[decomp[0]].append( (decomp[1], char) )
-    canon_comp_keys = sorted(canon_comp.keys())
 
 if __name__ == "__main__":
-    r = fdir + "tables.rs"
-    if os.path.exists(r):
-        os.remove(r)
-    with open(r, "w") as rf:
-        # write the file's preamble
-        rf.write(preamble)
-
-        # download and parse all the data
-        fetch("ReadMe.txt")
-        with open(fdir + "ReadMe.txt") as readme:
-            pattern = "for Version (\d+)\.(\d+)\.(\d+) of the Unicode"
-            unicode_version = re.search(pattern, readme.read()).groups()
-        rf.write("""
-/// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of
-/// `char` and `str` methods are based on.
-#[unstable(feature = "unicode_version", issue = "49726")]
-pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion {
-    major: %s,
-    minor: %s,
-    micro: %s,
-    _priv: (),
-};
-""" % unicode_version)
-        (canon_decomp, compat_decomp, gencats, combines,
-                to_upper, to_lower, to_title) = load_unicode_data("UnicodeData.txt")
-        load_special_casing("SpecialCasing.txt", to_upper, to_lower, to_title)
-        want_derived = ["XID_Start", "XID_Continue", "Alphabetic", "Lowercase", "Uppercase",
-                        "Cased", "Case_Ignorable", "Grapheme_Extend"]
-        derived = load_properties("DerivedCoreProperties.txt", want_derived)
-        scripts = load_properties("Scripts.txt", [])
-        props = load_properties("PropList.txt",
-                ["White_Space", "Join_Control", "Noncharacter_Code_Point", "Pattern_White_Space"])
-        norm_props = load_properties("DerivedNormalizationProps.txt",
-                     ["Full_Composition_Exclusion"])
-
-        # category tables
-        for (name, cat, pfuns) in ("general_category", gencats, ["N", "Cc"]), \
-                                  ("derived_property", derived, want_derived), \
-                                  ("property", props, ["White_Space", "Pattern_White_Space"]):
-            emit_property_module(rf, name, cat, pfuns)
-
-        # normalizations and conversions module
-        emit_norm_module(rf, canon_decomp, compat_decomp, combines, norm_props)
-        emit_conversions_module(rf, to_upper, to_lower, to_title)
-    print("Regenerated tables.rs.")
+    main()
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 3c967fa6d83..271fac544a4 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -4010,7 +4010,7 @@ impl<'a> LoweringContext<'a> {
         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_doc_only_macro) {
+                              attr::contains_name(&i.attrs, sym::rustc_builtin_macro) {
                 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_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs
index 9fdc93c3ff0..3b2701b893b 100644
--- a/src/librustc_codegen_llvm/common.rs
+++ b/src/librustc_codegen_llvm/common.rs
@@ -170,8 +170,7 @@ impl CodegenCx<'ll, 'tcx> {
     pub fn const_get_real(&self, v: &'ll Value) -> Option<(f64, bool)> {
         unsafe {
             if self.is_const_real(v) {
-                #[allow(deprecated)]
-                let mut loses_info: llvm::Bool = ::std::mem::uninitialized();
+                let mut loses_info: llvm::Bool = 0;
                 let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info);
                 let loses_info = if loses_info == 1 { true } else { false };
                 Some((r, loses_info))
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 75c64bb2644..dafb8c5f8f7 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -1465,7 +1465,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     .map(|b| GuardFrameLocal::new(b.var_id, b.binding_mode))
                     .collect(),
             };
-            debug!("Entering guard building context: {:?}", guard_frame);
+            debug!("entering guard building context: {:?}", guard_frame);
             self.guard_context.push(guard_frame);
 
             let re_erased = tcx.lifetimes.re_erased;
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index d822a26ce59..42bbe88283b 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -577,7 +577,7 @@ fn check_legality_of_move_bindings(
                                            "cannot bind by-move into a pattern guard");
             err.span_label(p.span, "moves value into pattern guard");
             if cx.tcx.sess.opts.unstable_features.is_nightly_build() {
-                err.help("add #![feature(bind_by_move_pattern_guards)] to the \
+                err.help("add `#![feature(bind_by_move_pattern_guards)]` to the \
                           crate attributes to enable");
             }
             err.emit();
@@ -664,7 +664,7 @@ impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> {
                           "cannot mutably borrow in a pattern guard");
                 err.span_label(span, "borrowed mutably in pattern guard");
                 if self.cx.tcx.sess.opts.unstable_features.is_nightly_build() {
-                    err.help("add #![feature(bind_by_move_pattern_guards)] to the \
+                    err.help("add `#![feature(bind_by_move_pattern_guards)]` to the \
                               crate attributes to enable");
                 }
                 err.emit();
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 4f3727fbd8d..3dee02989c9 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -351,7 +351,7 @@ where
                 if field >= len {
                     // This can be violated because this runs during promotion on code where the
                     // type system has not yet ensured that such things don't happen.
-                    debug!("Tried to access element {} of array/slice with length {}", field, len);
+                    debug!("tried to access element {} of array/slice with length {}", field, len);
                     return err!(BoundsCheck { len, index: field });
                 }
                 stride * field
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index da8fdb5082a..bcc6ad4eac2 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -289,7 +289,7 @@ pub fn collect_crate_mono_items(
         collect_roots(tcx, mode)
     });
 
-    debug!("Building mono item graph, beginning at roots");
+    debug!("building mono item graph, beginning at roots");
 
     let mut visited = MTLock::new(FxHashSet::default());
     let mut inlining_map = MTLock::new(InliningMap::new());
@@ -316,7 +316,7 @@ pub fn collect_crate_mono_items(
 // Find all non-generic items by walking the HIR. These items serve as roots to
 // start monomorphizing from.
 fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<'_>> {
-    debug!("Collecting roots");
+    debug!("collecting roots");
     let mut roots = Vec::new();
 
     {
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 9898ba89773..0c48531e345 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -552,10 +552,10 @@ fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: DefId) {
     // FIXME: when we make this a hard error, this should have its
     // own error code.
     let message = if tcx.generics_of(def_id).own_requires_monomorphization() {
-        "#[derive] can't be used on a #[repr(packed)] struct with \
+        "`#[derive]` can't be used on a `#[repr(packed)]` struct with \
          type or const parameters (error E0133)".to_string()
     } else {
-        "#[derive] can't be used on a #[repr(packed)] struct that \
+        "`#[derive]` can't be used on a `#[repr(packed)]` struct that \
          does not derive Copy (error E0133)".to_string()
     };
     tcx.lint_hir(SAFE_PACKED_BORROWS,
diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs
index c850b48e074..88a46b1012b 100644
--- a/src/librustc_mir/transform/copy_prop.rs
+++ b/src/librustc_mir/transform/copy_prop.rs
@@ -47,7 +47,7 @@ impl MirPass for CopyPropagation {
 
             let mut changed = false;
             for dest_local in body.local_decls.indices() {
-                debug!("Considering destination local: {:?}", dest_local);
+                debug!("considering destination local: {:?}", dest_local);
 
                 let action;
                 let location;
@@ -159,7 +159,7 @@ fn eliminate_self_assignments(
             } else {
                 continue;
             }
-            debug!("Deleting a self-assignment for {:?}", dest_local);
+            debug!("deleting a self-assignment for {:?}", dest_local);
             body.make_statement_nop(location);
             changed = true;
         }
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index dc73e58d15c..04ee14f5f59 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -159,7 +159,7 @@ impl Inliner<'tcx> {
 
         // Simplify if we inlined anything.
         if changed {
-            debug!("Running simplify cfg on {:?}", self.source);
+            debug!("running simplify cfg on {:?}", self.source);
             CfgSimplifier::new(caller_body).simplify();
             remove_dead_blocks(caller_body);
         }
@@ -247,7 +247,7 @@ impl Inliner<'tcx> {
             // need to check for first.
             attr::InlineAttr::Always => true,
             attr::InlineAttr::Never => {
-                debug!("#[inline(never)] present - not inlining");
+                debug!("`#[inline(never)]` present - not inlining");
                 return false
             }
             attr::InlineAttr::Hint => true,
@@ -397,7 +397,7 @@ impl Inliner<'tcx> {
         match terminator.kind {
             // FIXME: Handle inlining of diverging calls
             TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => {
-                debug!("Inlined {:?} into {:?}", callsite.callee, self.source);
+                debug!("inlined {:?} into {:?}", callsite.callee, self.source);
 
                 let mut local_map = IndexVec::with_capacity(callee_body.local_decls.len());
                 let mut scope_map = IndexVec::with_capacity(callee_body.source_scopes.len());
@@ -456,7 +456,7 @@ impl Inliner<'tcx> {
                 }
 
                 let dest = if dest_needs_borrow(&destination.0) {
-                    debug!("Creating temp for return destination");
+                    debug!("creating temp for return destination");
                     let dest = Rvalue::Ref(
                         self.tcx.lifetimes.re_erased,
                         BorrowKind::Mut { allow_two_phase_borrow: false },
@@ -610,7 +610,7 @@ impl Inliner<'tcx> {
             }
         }
 
-        debug!("Creating temp for argument {:?}", arg);
+        debug!("creating temp for argument {:?}", arg);
         // Otherwise, create a temporary for the arg
         let arg = Rvalue::Use(arg);
 
@@ -659,7 +659,7 @@ struct Integrator<'a, 'tcx> {
 impl<'a, 'tcx> Integrator<'a, 'tcx> {
     fn update_target(&self, tgt: BasicBlock) -> BasicBlock {
         let new = BasicBlock::new(tgt.index() + self.block_idx);
-        debug!("Updating target `{:?}`, new: `{:?}`", tgt, new);
+        debug!("updating target `{:?}`, new: `{:?}`", tgt, new);
         new
     }
 }
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index c338e1ebe93..40563ad4167 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -39,7 +39,7 @@ pub struct InstCombineVisitor<'tcx> {
 impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> {
     fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
         if self.optimizations.and_stars.remove(&location) {
-            debug!("Replacing `&*`: {:?}", rvalue);
+            debug!("replacing `&*`: {:?}", rvalue);
             let new_place = match *rvalue {
                 Rvalue::Ref(_, _, Place::Projection(ref mut projection)) => {
                     // Replace with dummy
@@ -51,7 +51,7 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> {
         }
 
         if let Some(constant) = self.optimizations.arrays_lengths.remove(&location) {
-            debug!("Replacing `Len([_; N])`: {:?}", rvalue);
+            debug!("replacing `Len([_; N])`: {:?}", rvalue);
             *rvalue = Rvalue::Use(Operand::Constant(box constant));
         }
 
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 3e52d3ee9bb..2dffafd6e54 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -1545,7 +1545,7 @@ impl MirPass for QualifyAndPromoteConstants {
                             diag.note("for more information, see issue \
                                        https://github.com/rust-lang/rust/issues/57563");
                             diag.help(
-                                "add #![feature(const_fn)] to the crate attributes to enable",
+                                "add `#![feature(const_fn)]` to the crate attributes to enable",
                             );
                             diag.emit();
                         } else {
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 052f1526f0c..05df3a6f6bc 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -28,6 +28,7 @@ use rustc_data_structures::fx::FxHashSet;
 use syntax::ast::Ident;
 use syntax::attr;
 use syntax::symbol::{kw, sym};
+use syntax_pos::hygiene::Transparency;
 use syntax_pos::Span;
 
 use std::{cmp, fmt, mem};
@@ -743,7 +744,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
     }
 
     fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
-        if md.legacy {
+        if attr::find_transparency(&md.attrs, md.legacy).0 != Transparency::Opaque {
             self.update(md.hir_id, Some(AccessLevel::Public));
             return
         }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 616728d5418..3921bd30df2 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -770,19 +770,25 @@ impl<'a> Resolver<'a> {
     }
 
     pub fn get_macro(&mut self, res: Res) -> Lrc<SyntaxExtension> {
+        self.opt_get_macro(res).expect("expected `DefKind::Macro` or `Res::NonMacroAttr`")
+    }
+
+    crate fn opt_get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
         let def_id = match res {
+            Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) =>
+                return Some(self.non_macro_attr(true)), // some dummy extension
             Res::Def(DefKind::Macro(..), def_id) => def_id,
             Res::NonMacroAttr(attr_kind) =>
-                return self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool),
-            _ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"),
+                return Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)),
+            _ => return None,
         };
         if let Some(ext) = self.macro_map.get(&def_id) {
-            return ext.clone();
+            return Some(ext.clone());
         }
 
         let macro_def = match self.cstore.load_macro_untracked(def_id, &self.session) {
             LoadedMacro::MacroDef(macro_def) => macro_def,
-            LoadedMacro::ProcMacro(ext) => return ext,
+            LoadedMacro::ProcMacro(ext) => return Some(ext),
         };
 
         let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
@@ -790,7 +796,7 @@ impl<'a> Resolver<'a> {
                                                &macro_def,
                                                self.cstore.crate_edition_untracked(def_id.krate)));
         self.macro_map.insert(def_id, ext.clone());
-        ext
+        Some(ext)
     }
 
     /// Ensures that the reduced graph rooted at the given external module
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index dd0beee2104..0955c425f2f 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -1106,6 +1106,19 @@ impl<'a> Resolver<'a> {
         });
     }
 
+    crate fn check_reserved_macro_name(&mut self, ident: Ident, res: Res) {
+        // Reserve some names that are not quite covered by the general check
+        // performed on `Resolver::builtin_attrs`.
+        if ident.name == sym::cfg || ident.name == sym::cfg_attr || ident.name == sym::derive {
+            let macro_kind = self.opt_get_macro(res).map(|ext| ext.macro_kind());
+            if macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr)) {
+                self.session.span_err(
+                    ident.span, &format!("name `{}` is reserved in attribute namespace", ident)
+                );
+            }
+        }
+    }
+
     pub fn define_macro(&mut self,
                         item: &ast::Item,
                         expansion: Mark,
@@ -1117,13 +1130,14 @@ impl<'a> Resolver<'a> {
         let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
                                                &self.session.features_untracked(),
                                                item, self.session.edition()));
+        let macro_kind = ext.macro_kind();
+        let res = Res::Def(DefKind::Macro(macro_kind), def_id);
         self.macro_map.insert(def_id, ext);
 
         let def = match item.node { ast::ItemKind::MacroDef(ref def) => def, _ => unreachable!() };
         if def.legacy {
             let ident = ident.modern();
             self.macro_names.insert(ident);
-            let res = Res::Def(DefKind::Macro(MacroKind::Bang), def_id);
             let is_macro_export = attr::contains_name(&item.attrs, sym::macro_export);
             let vis = if is_macro_export {
                 ty::Visibility::Public
@@ -1142,14 +1156,11 @@ impl<'a> Resolver<'a> {
                 self.define(module, ident, MacroNS,
                             (res, vis, item.span, expansion, IsMacroExport));
             } else {
-                if !attr::contains_name(&item.attrs, sym::rustc_doc_only_macro) {
-                    self.check_reserved_macro_name(ident, MacroNS);
-                }
+                self.check_reserved_macro_name(ident, res);
                 self.unused_macros.insert(def_id);
             }
         } else {
             let module = self.current_module;
-            let res = Res::Def(DefKind::Macro(MacroKind::Bang), def_id);
             let vis = self.resolve_visibility(&item.vis);
             if vis != ty::Visibility::Public {
                 self.unused_macros.insert(def_id);
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 404d728d880..7de1cd29a9c 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -29,7 +29,7 @@ use rustc::{bug, span_bug};
 use syntax::ast::{self, Ident, Name, NodeId, CRATE_NODE_ID};
 use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
 use syntax::ext::hygiene::Mark;
-use syntax::symbol::{kw, sym};
+use syntax::symbol::kw;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax::{struct_span_err, unwrap_or};
 use syntax_pos::{MultiSpan, Span};
@@ -492,17 +492,6 @@ impl<'a> Resolver<'a> {
         })
     }
 
-    crate fn check_reserved_macro_name(&self, ident: Ident, ns: Namespace) {
-        // Reserve some names that are not quite covered by the general check
-        // performed on `Resolver::builtin_attrs`.
-        if ns == MacroNS &&
-           (ident.name == sym::cfg || ident.name == sym::cfg_attr ||
-            ident.name == sym::derive) {
-            self.session.span_err(ident.span,
-                                  &format!("name `{}` is reserved in macro namespace", ident));
-        }
-    }
-
     // Define the name or return the existing binding if there is a collision.
     pub fn try_define(&mut self,
                       module: Module<'a>,
@@ -510,17 +499,18 @@ impl<'a> Resolver<'a> {
                       ns: Namespace,
                       binding: &'a NameBinding<'a>)
                       -> Result<(), &'a NameBinding<'a>> {
-        self.check_reserved_macro_name(ident, ns);
+        let res = binding.res();
+        self.check_reserved_macro_name(ident, res);
         self.set_binding_parent_module(binding, module);
         self.update_resolution(module, ident, ns, |this, resolution| {
             if let Some(old_binding) = resolution.binding {
-                if binding.res() == Res::Err {
+                if res == Res::Err {
                     // Do not override real bindings with `Res::Err`s from error recovery.
                     return Ok(());
                 }
                 match (old_binding.is_glob_import(), binding.is_glob_import()) {
                     (true, true) => {
-                        if binding.res() != old_binding.res() {
+                        if res != old_binding.res() {
                             resolution.binding = Some(this.ambiguity(AmbiguityKind::GlobVsGlob,
                                                                      old_binding, binding));
                         } else if !old_binding.vis.is_at_least(binding.vis, &*this) {
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index d695141bef0..b3e09d69742 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -410,7 +410,7 @@ mod builtin {
     ///
     /// [`panic!`]: ../std/macro.panic.html
     #[stable(feature = "compile_error_macro", since = "1.20.0")]
-    #[rustc_doc_only_macro]
+    #[rustc_builtin_macro]
     macro_rules! compile_error {
         ($msg:expr) => ({ /* compiler built-in */ });
         ($msg:expr,) => ({ /* compiler built-in */ });
@@ -462,7 +462,7 @@ mod builtin {
     /// assert_eq!(s, format!("hello {}", "world"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
+    #[rustc_builtin_macro]
     macro_rules! format_args {
         ($fmt:expr) => ({ /* compiler built-in */ });
         ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ });
@@ -500,7 +500,7 @@ mod builtin {
     /// error: what's that?!
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
+    #[rustc_builtin_macro]
     macro_rules! env {
         ($name:expr) => ({ /* compiler built-in */ });
         ($name:expr,) => ({ /* compiler built-in */ });
@@ -526,7 +526,7 @@ mod builtin {
     /// println!("the secret key might be: {:?}", key);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
+    #[rustc_builtin_macro]
     macro_rules! option_env {
         ($name:expr) => ({ /* compiler built-in */ });
         ($name:expr,) => ({ /* compiler built-in */ });
@@ -557,7 +557,7 @@ mod builtin {
     /// # }
     /// ```
     #[unstable(feature = "concat_idents_macro", issue = "29599")]
-    #[rustc_doc_only_macro]
+    #[rustc_builtin_macro]
     macro_rules! concat_idents {
         ($($e:ident),+) => ({ /* compiler built-in */ });
         ($($e:ident,)+) => ({ /* compiler built-in */ });
@@ -579,7 +579,7 @@ mod builtin {
     /// assert_eq!(s, "test10btrue");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
+    #[rustc_builtin_macro]
     macro_rules! concat {
         ($($e:expr),*) => ({ /* compiler built-in */ });
         ($($e:expr,)*) => ({ /* compiler built-in */ });
@@ -607,7 +607,7 @@ mod builtin {
     /// println!("defined on line: {}", current_line);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
+    #[rustc_builtin_macro]
     macro_rules! line { () => ({ /* compiler built-in */ }) }
 
     /// Expands to the column number at which it was invoked.
@@ -632,7 +632,7 @@ mod builtin {
     /// println!("defined on column: {}", current_col);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
+    #[rustc_builtin_macro]
     macro_rules! column { () => ({ /* compiler built-in */ }) }
 
     /// Expands to the file name in which it was invoked.
@@ -656,7 +656,7 @@ mod builtin {
     /// println!("defined in file: {}", this_file);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
+    #[rustc_builtin_macro]
     macro_rules! file { () => ({ /* compiler built-in */ }) }
 
     /// Stringifies its arguments.
@@ -675,7 +675,7 @@ mod builtin {
     /// assert_eq!(one_plus_one, "1 + 1");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
+    #[rustc_builtin_macro]
     macro_rules! stringify { ($($t:tt)*) => ({ /* compiler built-in */ }) }
 
     /// Includes a utf8-encoded file as a string.
@@ -709,7 +709,7 @@ mod builtin {
     ///
     /// Compiling 'main.rs' and running the resulting binary will print "adiós".
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
+    #[rustc_builtin_macro]
     macro_rules! include_str {
         ($file:expr) => ({ /* compiler built-in */ });
         ($file:expr,) => ({ /* compiler built-in */ });
@@ -746,7 +746,7 @@ mod builtin {
     ///
     /// Compiling 'main.rs' and running the resulting binary will print "adiós".
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
+    #[rustc_builtin_macro]
     macro_rules! include_bytes {
         ($file:expr) => ({ /* compiler built-in */ });
         ($file:expr,) => ({ /* compiler built-in */ });
@@ -770,7 +770,7 @@ mod builtin {
     /// test::foo();
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
+    #[rustc_builtin_macro]
     macro_rules! module_path { () => ({ /* compiler built-in */ }) }
 
     /// Evaluates boolean combinations of configuration flags at compile-time.
@@ -794,7 +794,7 @@ mod builtin {
     /// };
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
+    #[rustc_builtin_macro]
     macro_rules! cfg { ($($cfg:tt)*) => ({ /* compiler built-in */ }) }
 
     /// Parses a file as an expression or an item according to the context.
@@ -837,7 +837,7 @@ mod builtin {
     /// Compiling 'main.rs' and running the resulting binary will print
     /// "🙈🙊🙉🙈🙊🙉".
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
+    #[rustc_builtin_macro]
     macro_rules! include {
         ($file:expr) => ({ /* compiler built-in */ });
         ($file:expr,) => ({ /* compiler built-in */ });
@@ -889,7 +889,7 @@ mod builtin {
     /// assert!(a + b == 30, "a = {}, b = {}", a, b);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_doc_only_macro]
+    #[rustc_builtin_macro]
     macro_rules! assert {
         ($cond:expr) => ({ /* compiler built-in */ });
         ($cond:expr,) => ({ /* compiler built-in */ });
diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs
index bf6eab4ec91..752ab5d474d 100644
--- a/src/libsyntax/attr/builtin.rs
+++ b/src/libsyntax/attr/builtin.rs
@@ -5,6 +5,7 @@ use crate::feature_gate::{Features, GatedCfg};
 use crate::parse::ParseSess;
 
 use errors::{Applicability, Handler};
+use syntax_pos::hygiene::Transparency;
 use syntax_pos::{symbol::Symbol, symbol::sym, Span};
 
 use super::{mark_used, MetaItemKind};
@@ -854,3 +855,35 @@ fn int_type_of_word(s: Symbol) -> Option<IntType> {
         _ => None
     }
 }
+
+pub enum TransparencyError {
+    UnknownTransparency(Symbol, Span),
+    MultipleTransparencyAttrs(Span, Span),
+}
+
+pub fn find_transparency(
+    attrs: &[Attribute], is_legacy: bool
+) -> (Transparency, Option<TransparencyError>) {
+    let mut transparency = None;
+    let mut error = None;
+    for attr in attrs {
+        if attr.check_name(sym::rustc_macro_transparency) {
+            if let Some((_, old_span)) = transparency {
+                error = Some(TransparencyError::MultipleTransparencyAttrs(old_span, attr.span));
+                break;
+            } else if let Some(value) = attr.value_str() {
+                transparency = Some((match &*value.as_str() {
+                    "transparent" => Transparency::Transparent,
+                    "semitransparent" => Transparency::SemiTransparent,
+                    "opaque" => Transparency::Opaque,
+                    _ => {
+                        error = Some(TransparencyError::UnknownTransparency(value, attr.span));
+                        continue;
+                    }
+                }, attr.span));
+            }
+        }
+    }
+    let fallback = if is_legacy { Transparency::SemiTransparent } else { Transparency::Opaque };
+    (transparency.map_or(fallback, |t| t.0), error)
+}
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index a0c298010b6..a9f2429560a 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -2,11 +2,7 @@
 
 mod builtin;
 
-pub use builtin::{
-    cfg_matches, contains_feature_attr, eval_condition, find_crate_name, find_deprecation,
-    find_repr_attrs, find_stability, find_unwind_attr, Deprecation, InlineAttr, OptimizeAttr,
-    IntType, ReprAttr, RustcDeprecation, Stability, StabilityLevel, UnwindAttr,
-};
+pub use builtin::*;
 pub use IntType::*;
 pub use ReprAttr::*;
 pub use StabilityLevel::*;
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 1a448cb2a43..cf3c748cd82 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -2,7 +2,6 @@ use crate::edition::Edition;
 use crate::ext::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander};
 use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind};
 use crate::ext::expand::{AstFragment, AstFragmentKind};
-use crate::ext::hygiene::Transparency;
 use crate::ext::tt::macro_parser::{parse, parse_failure_msg};
 use crate::ext::tt::macro_parser::{Error, Failure, Success};
 use crate::ext::tt::macro_parser::{MatchedNonterminal, MatchedSeq};
@@ -15,7 +14,7 @@ use crate::parse::token::{self, NtTT, Token};
 use crate::parse::{Directory, ParseSess};
 use crate::symbol::{kw, sym, Symbol};
 use crate::tokenstream::{DelimSpan, TokenStream, TokenTree};
-use crate::{ast, attr};
+use crate::{ast, attr, attr::TransparencyError};
 
 use errors::FatalError;
 use log::debug;
@@ -380,13 +379,19 @@ pub fn compile(
     let expander: Box<_> =
         Box::new(MacroRulesMacroExpander { name: def.ident, lhses, rhses, valid });
 
-    let default_transparency = if attr::contains_name(&def.attrs, sym::rustc_transparent_macro) {
-        Transparency::Transparent
-    } else if body.legacy {
-        Transparency::SemiTransparent
-    } else {
-        Transparency::Opaque
-    };
+    let (default_transparency, transparency_error) =
+        attr::find_transparency(&def.attrs, body.legacy);
+    match transparency_error {
+        Some(TransparencyError::UnknownTransparency(value, span)) =>
+            sess.span_diagnostic.span_err(
+                span, &format!("unknown macro transparency: `{}`", value)
+            ),
+        Some(TransparencyError::MultipleTransparencyAttrs(old_span, new_span)) =>
+            sess.span_diagnostic.span_err(
+                vec![old_span, new_span], "multiple macro transparency attributes"
+            ),
+        None => {}
+    }
 
     let allow_internal_unstable =
         attr::find_by_name(&def.attrs, sym::allow_internal_unstable).map(|attr| {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index e1e39faaad4..2b242a71ad4 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -245,7 +245,7 @@ declare_features! (
     (active, allocator_internals, "1.20.0", None, None),
 
     // Allows using the `format_args_nl` macro.
-    (active, format_args_nl, "1.29.0", None, None),
+    (active, format_args_nl, "1.29.0", Some(0), None),
 
     // no-tracking-issue-end
 
@@ -1313,7 +1313,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
                                     "the `#[rustc_test_marker]` attribute \
                                     is used internally to track tests",
                                     cfg_fn!(rustc_attrs))),
-    (sym::rustc_transparent_macro, Whitelisted, template!(Word), Gated(Stability::Unstable,
+    (sym::rustc_macro_transparency, Whitelisted, template!(NameValueStr:
+                                                           "transparent|semitransparent|opaque"),
+                                                Gated(Stability::Unstable,
                                                 sym::rustc_attrs,
                                                 "used internally for testing macro hygiene",
                                                     cfg_fn!(rustc_attrs))),
@@ -1374,7 +1376,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
                                                 "internal implementation detail",
                                                 cfg_fn!(rustc_attrs))),
 
-    (sym::rustc_doc_only_macro, Whitelisted, template!(Word), Gated(Stability::Unstable,
+    (sym::rustc_builtin_macro, Whitelisted, template!(Word), Gated(Stability::Unstable,
                                                 sym::rustc_attrs,
                                                 "internal implementation detail",
                                                 cfg_fn!(rustc_attrs))),
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 6a97e5f2127..410f4b36b67 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -537,6 +537,7 @@ symbols! {
         rustc_allow_const_fn_ptr,
         rustc_args_required_const,
         rustc_attrs,
+        rustc_builtin_macro,
         rustc_clean,
         rustc_const_unstable,
         rustc_conversion_suggestion,
@@ -545,7 +546,6 @@ symbols! {
         rustc_deprecated,
         rustc_diagnostic_macros,
         rustc_dirty,
-        rustc_doc_only_macro,
         rustc_dummy,
         rustc_dump_env_program_clauses,
         rustc_dump_program_clauses,
@@ -557,6 +557,7 @@ symbols! {
         rustc_layout,
         rustc_layout_scalar_valid_range_end,
         rustc_layout_scalar_valid_range_start,
+        rustc_macro_transparency,
         rustc_mir,
         rustc_nonnull_optimization_guaranteed,
         rustc_object_lifetime_default,
@@ -579,7 +580,6 @@ symbols! {
         rustc_synthetic,
         rustc_test_marker,
         rustc_then_this_would_need,
-        rustc_transparent_macro,
         rustc_variance,
         rustdoc,
         rust_eh_personality,
diff --git a/src/libterm/win.rs b/src/libterm/win.rs
index 14ea68d3788..e5911de8396 100644
--- a/src/libterm/win.rs
+++ b/src/libterm/win.rs
@@ -2,8 +2,6 @@
 
 // FIXME (#13400): this is only a tiny fraction of the Windows console api
 
-extern crate libc;
-
 use std::io;
 use std::io::prelude::*;
 
@@ -20,6 +18,7 @@ pub struct WinConsole<T> {
     background: color::Color,
 }
 
+type SHORT = i16;
 type WORD = u16;
 type DWORD = u32;
 type BOOL = i32;
@@ -27,12 +26,28 @@ type HANDLE = *mut u8;
 
 #[allow(non_snake_case)]
 #[repr(C)]
+struct SMALL_RECT {
+    Left: SHORT,
+    Top: SHORT,
+    Right: SHORT,
+    Bottom: SHORT,
+}
+
+#[allow(non_snake_case)]
+#[repr(C)]
+struct COORD {
+    X: SHORT,
+    Y: SHORT,
+}
+
+#[allow(non_snake_case)]
+#[repr(C)]
 struct CONSOLE_SCREEN_BUFFER_INFO {
-    dwSize: [libc::c_short; 2],
-    dwCursorPosition: [libc::c_short; 2],
+    dwSize: COORD,
+    dwCursorPosition: COORD,
     wAttributes: WORD,
-    srWindow: [libc::c_short; 4],
-    dwMaximumWindowSize: [libc::c_short; 2],
+    srWindow: SMALL_RECT,
+    dwMaximumWindowSize: COORD,
 }
 
 #[allow(non_snake_case)]
@@ -105,12 +120,17 @@ impl<T: Write + Send + 'static> WinConsole<T> {
 
     /// Returns `None` whenever the terminal cannot be created for some reason.
     pub fn new(out: T) -> io::Result<WinConsole<T>> {
+        use std::mem::MaybeUninit;
+
         let fg;
         let bg;
         unsafe {
-            #[allow(deprecated)]
-            let mut buffer_info = ::std::mem::uninitialized();
-            if GetConsoleScreenBufferInfo(GetStdHandle(-11i32 as DWORD), &mut buffer_info) != 0 {
+            let mut buffer_info = MaybeUninit::<CONSOLE_SCREEN_BUFFER_INFO>::uninit();
+            if GetConsoleScreenBufferInfo(
+                GetStdHandle(-11i32 as DWORD),
+                buffer_info.as_mut_ptr()
+            ) != 0 {
+                let buffer_info = buffer_info.assume_init() ;
                 fg = bits_to_color(buffer_info.wAttributes);
                 bg = bits_to_color(buffer_info.wAttributes >> 4);
             } else {
diff --git a/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr b/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr
index 5f8b7007f30..c5f0256c2c9 100644
--- a/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr
+++ b/src/test/ui/bind-by-move/bind-by-move-no-guards.stderr
@@ -4,7 +4,7 @@ error[E0008]: cannot bind by-move into a pattern guard
 LL |         Some(z) if z.recv().unwrap() => { panic!() },
    |              ^ moves value into pattern guard
    |
-   = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable
+   = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr b/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr
index 7e4a6322d5f..43b578e9f1e 100644
--- a/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.nll.stderr
@@ -10,7 +10,7 @@ error[E0301]: cannot mutably borrow in a pattern guard
 LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
    |                                      ^ borrowed mutably in pattern guard
    |
-   = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable
+   = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable
 
 error[E0302]: cannot assign in a pattern guard
   --> $DIR/borrowck-mutate-in-guard.rs:15:41
diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
index ac6bed6137f..d39f535d8e2 100644
--- a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
+++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
@@ -10,7 +10,7 @@ error[E0301]: cannot mutably borrow in a pattern guard
 LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
    |                                      ^ borrowed mutably in pattern guard
    |
-   = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable
+   = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable
 
 error[E0302]: cannot assign in a pattern guard
   --> $DIR/borrowck-mutate-in-guard.rs:15:41
diff --git a/src/test/ui/consts/const_let_refutable.nll.stderr b/src/test/ui/consts/const_let_refutable.nll.stderr
index 3cc6de5bc42..a61c9b0c9fe 100644
--- a/src/test/ui/consts/const_let_refutable.nll.stderr
+++ b/src/test/ui/consts/const_let_refutable.nll.stderr
@@ -11,7 +11,7 @@ LL |     a + b
    |     ^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0381]: use of possibly uninitialized variable: `a`
   --> $DIR/const_let_refutable.rs:4:5
diff --git a/src/test/ui/consts/const_let_refutable.stderr b/src/test/ui/consts/const_let_refutable.stderr
index cdd696ee7fb..a848b20ed98 100644
--- a/src/test/ui/consts/const_let_refutable.stderr
+++ b/src/test/ui/consts/const_let_refutable.stderr
@@ -11,7 +11,7 @@ LL |     a + b
    |     ^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 warning[E0381]: use of possibly uninitialized variable: `a`
   --> $DIR/const_let_refutable.rs:4:5
diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr
index e6e1ced6592..6228b012dde 100644
--- a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr
+++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr
@@ -5,7 +5,7 @@ LL | const fn error(_: fn()) {}
    |                ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr
index ac8d082fc19..ecfd30e7b44 100644
--- a/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr
+++ b/src/test/ui/consts/min_const_fn/bad_const_fn_body_ice.stderr
@@ -5,7 +5,7 @@ LL |     vec![1, 2, 3]
    |     ^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/src/test/ui/consts/min_const_fn/cast_errors.stderr b/src/test/ui/consts/min_const_fn/cast_errors.stderr
index b1a50be9983..9919c17a042 100644
--- a/src/test/ui/consts/min_const_fn/cast_errors.stderr
+++ b/src/test/ui/consts/min_const_fn/cast_errors.stderr
@@ -5,7 +5,7 @@ LL | const fn unsize(x: &[u8; 3]) -> &[u8] { x }
    |                                         ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: function pointers in const fn are unstable
   --> $DIR/cast_errors.rs:5:23
@@ -14,7 +14,7 @@ LL | const fn closure() -> fn() { || {} }
    |                       ^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: function pointers in const fn are unstable
   --> $DIR/cast_errors.rs:8:5
@@ -23,7 +23,7 @@ LL |     (|| {}) as fn();
    |     ^^^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: function pointers in const fn are unstable
   --> $DIR/cast_errors.rs:11:28
@@ -32,7 +32,7 @@ LL | const fn reify(f: fn()) -> unsafe fn() { f }
    |                            ^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: function pointers in const fn are unstable
   --> $DIR/cast_errors.rs:13:21
@@ -41,7 +41,7 @@ LL | const fn reify2() { main as unsafe fn(); }
    |                     ^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr
index 7f6132ce9cd..82ed1d45226 100644
--- a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr
+++ b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr
@@ -5,7 +5,7 @@ LL | const fn cmp(x: fn(), y: fn()) -> bool {
    |              ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/min_const_fn/loop_ice.stderr b/src/test/ui/consts/min_const_fn/loop_ice.stderr
index cb85956266b..edf983fc56b 100644
--- a/src/test/ui/consts/min_const_fn/loop_ice.stderr
+++ b/src/test/ui/consts/min_const_fn/loop_ice.stderr
@@ -5,7 +5,7 @@ LL |     loop {}
    |     ^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
index afe48ee9ae5..4b43a0d0a1a 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
@@ -11,7 +11,7 @@ LL |     const fn get_mut(&mut self) -> &mut T { &mut self.0 }
    |                                    ^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0493]: destructors cannot be evaluated at compile-time
   --> $DIR/min_const_fn.rs:44:28
@@ -26,7 +26,7 @@ LL |     const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
    |                                          ^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0493]: destructors cannot be evaluated at compile-time
   --> $DIR/min_const_fn.rs:51:27
@@ -41,7 +41,7 @@ LL |     const fn get_mut_s(&mut self) -> &mut T { &mut self.0 }
    |                                      ^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: mutable references in const fn are unstable
   --> $DIR/min_const_fn.rs:58:39
@@ -50,7 +50,7 @@ LL |     const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 }
    |                                       ^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:76:16
@@ -59,7 +59,7 @@ LL | const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
    |                ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:78:18
@@ -68,7 +68,7 @@ LL | const fn foo11_2<T: Send>(t: T) -> T { t }
    |                  ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: only int, `bool` and `char` operations are stable in const fn
   --> $DIR/min_const_fn.rs:80:33
@@ -77,7 +77,7 @@ LL | const fn foo19(f: f32) -> f32 { f * 2.0 }
    |                                 ^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: only int, `bool` and `char` operations are stable in const fn
   --> $DIR/min_const_fn.rs:82:35
@@ -86,7 +86,7 @@ LL | const fn foo19_2(f: f32) -> f32 { 2.0 - f }
    |                                   ^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: only int and `bool` operations are stable in const fn
   --> $DIR/min_const_fn.rs:84:35
@@ -95,7 +95,7 @@ LL | const fn foo19_3(f: f32) -> f32 { -f }
    |                                   ^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: only int, `bool` and `char` operations are stable in const fn
   --> $DIR/min_const_fn.rs:86:43
@@ -104,7 +104,7 @@ LL | const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
    |                                           ^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: cannot access `static` items in const fn
   --> $DIR/min_const_fn.rs:90:27
@@ -113,7 +113,7 @@ LL | const fn foo25() -> u32 { BAR }
    |                           ^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: cannot access `static` items in const fn
   --> $DIR/min_const_fn.rs:91:36
@@ -122,7 +122,7 @@ LL | const fn foo26() -> &'static u32 { &BAR }
    |                                    ^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: casting pointers to ints is unstable in const fn
   --> $DIR/min_const_fn.rs:92:42
@@ -131,7 +131,7 @@ LL | const fn foo30(x: *const u32) -> usize { x as usize }
    |                                          ^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: casting pointers to ints is unstable in const fn
   --> $DIR/min_const_fn.rs:94:63
@@ -140,7 +140,7 @@ LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize }
    |                                                               ^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: casting pointers to ints is unstable in const fn
   --> $DIR/min_const_fn.rs:96:42
@@ -149,7 +149,7 @@ LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
    |                                          ^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: casting pointers to ints is unstable in const fn
   --> $DIR/min_const_fn.rs:98:63
@@ -158,7 +158,7 @@ LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize }
    |                                                               ^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: loops and conditional expressions are not stable in const fn
   --> $DIR/min_const_fn.rs:100:38
@@ -167,7 +167,7 @@ LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
    |                                      ^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: loops are not allowed in const fn
   --> $DIR/min_const_fn.rs:102:29
@@ -176,7 +176,7 @@ LL | const fn foo30_5(b: bool) { while b { } }
    |                             ^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: loops and conditional expressions are not stable in const fn
   --> $DIR/min_const_fn.rs:105:44
@@ -185,7 +185,7 @@ LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
    |                                            ^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: loops and conditional expressions are not stable in const fn
   --> $DIR/min_const_fn.rs:107:44
@@ -194,7 +194,7 @@ LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
    |                                            ^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: mutable references in const fn are unstable
   --> $DIR/min_const_fn.rs:109:14
@@ -203,7 +203,7 @@ LL | const fn inc(x: &mut i32) { *x += 1 }
    |              ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:114:6
@@ -212,7 +212,7 @@ LL | impl<T: std::fmt::Debug> Foo<T> {
    |      ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:119:6
@@ -221,7 +221,7 @@ LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
    |      ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:124:6
@@ -230,7 +230,7 @@ LL | impl<T: Sync + Sized> Foo<T> {
    |      ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: `impl Trait` in const fn is unstable
   --> $DIR/min_const_fn.rs:130:24
@@ -239,7 +239,7 @@ LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:132:34
@@ -248,7 +248,7 @@ LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
    |                                  ^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:134:22
@@ -257,7 +257,7 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {}
    |                      ^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: `impl Trait` in const fn is unstable
   --> $DIR/min_const_fn.rs:135:23
@@ -266,7 +266,7 @@ LL | const fn no_rpit() -> impl std::fmt::Debug {}
    |                       ^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:136:23
@@ -275,7 +275,7 @@ LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {}
    |                       ^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:137:32
@@ -284,7 +284,7 @@ LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0515]: cannot return reference to temporary value
   --> $DIR/min_const_fn.rs:137:63
@@ -302,7 +302,7 @@ LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: function pointers in const fn are unstable
   --> $DIR/min_const_fn.rs:148:21
@@ -311,7 +311,7 @@ LL | const fn no_fn_ptrs(_x: fn()) {}
    |                     ^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: function pointers in const fn are unstable
   --> $DIR/min_const_fn.rs:150:27
@@ -320,7 +320,7 @@ LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
    |                           ^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error: aborting due to 37 previous errors
 
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
index 66cfe7fa024..211902b687b 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
@@ -11,7 +11,7 @@ LL |     const fn get_mut(&mut self) -> &mut T { &mut self.0 }
    |                                    ^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0493]: destructors cannot be evaluated at compile-time
   --> $DIR/min_const_fn.rs:44:28
@@ -26,7 +26,7 @@ LL |     const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
    |                                          ^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0493]: destructors cannot be evaluated at compile-time
   --> $DIR/min_const_fn.rs:51:27
@@ -41,7 +41,7 @@ LL |     const fn get_mut_s(&mut self) -> &mut T { &mut self.0 }
    |                                      ^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: mutable references in const fn are unstable
   --> $DIR/min_const_fn.rs:58:39
@@ -50,7 +50,7 @@ LL |     const fn get_mut_sq(&mut self) -> &mut T { &mut self.0 }
    |                                       ^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:76:16
@@ -59,7 +59,7 @@ LL | const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
    |                ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:78:18
@@ -68,7 +68,7 @@ LL | const fn foo11_2<T: Send>(t: T) -> T { t }
    |                  ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: only int, `bool` and `char` operations are stable in const fn
   --> $DIR/min_const_fn.rs:80:33
@@ -77,7 +77,7 @@ LL | const fn foo19(f: f32) -> f32 { f * 2.0 }
    |                                 ^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: only int, `bool` and `char` operations are stable in const fn
   --> $DIR/min_const_fn.rs:82:35
@@ -86,7 +86,7 @@ LL | const fn foo19_2(f: f32) -> f32 { 2.0 - f }
    |                                   ^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: only int and `bool` operations are stable in const fn
   --> $DIR/min_const_fn.rs:84:35
@@ -95,7 +95,7 @@ LL | const fn foo19_3(f: f32) -> f32 { -f }
    |                                   ^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: only int, `bool` and `char` operations are stable in const fn
   --> $DIR/min_const_fn.rs:86:43
@@ -104,7 +104,7 @@ LL | const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
    |                                           ^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: cannot access `static` items in const fn
   --> $DIR/min_const_fn.rs:90:27
@@ -113,7 +113,7 @@ LL | const fn foo25() -> u32 { BAR }
    |                           ^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: cannot access `static` items in const fn
   --> $DIR/min_const_fn.rs:91:36
@@ -122,7 +122,7 @@ LL | const fn foo26() -> &'static u32 { &BAR }
    |                                    ^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: casting pointers to ints is unstable in const fn
   --> $DIR/min_const_fn.rs:92:42
@@ -131,7 +131,7 @@ LL | const fn foo30(x: *const u32) -> usize { x as usize }
    |                                          ^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: casting pointers to ints is unstable in const fn
   --> $DIR/min_const_fn.rs:94:63
@@ -140,7 +140,7 @@ LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize }
    |                                                               ^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: casting pointers to ints is unstable in const fn
   --> $DIR/min_const_fn.rs:96:42
@@ -149,7 +149,7 @@ LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
    |                                          ^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: casting pointers to ints is unstable in const fn
   --> $DIR/min_const_fn.rs:98:63
@@ -158,7 +158,7 @@ LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize }
    |                                                               ^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: loops and conditional expressions are not stable in const fn
   --> $DIR/min_const_fn.rs:100:38
@@ -167,7 +167,7 @@ LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
    |                                      ^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: loops are not allowed in const fn
   --> $DIR/min_const_fn.rs:102:29
@@ -176,7 +176,7 @@ LL | const fn foo30_5(b: bool) { while b { } }
    |                             ^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: loops and conditional expressions are not stable in const fn
   --> $DIR/min_const_fn.rs:105:44
@@ -185,7 +185,7 @@ LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
    |                                            ^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: loops and conditional expressions are not stable in const fn
   --> $DIR/min_const_fn.rs:107:44
@@ -194,7 +194,7 @@ LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
    |                                            ^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: mutable references in const fn are unstable
   --> $DIR/min_const_fn.rs:109:14
@@ -203,7 +203,7 @@ LL | const fn inc(x: &mut i32) { *x += 1 }
    |              ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:114:6
@@ -212,7 +212,7 @@ LL | impl<T: std::fmt::Debug> Foo<T> {
    |      ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:119:6
@@ -221,7 +221,7 @@ LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
    |      ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:124:6
@@ -230,7 +230,7 @@ LL | impl<T: Sync + Sized> Foo<T> {
    |      ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: `impl Trait` in const fn is unstable
   --> $DIR/min_const_fn.rs:130:24
@@ -239,7 +239,7 @@ LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:132:34
@@ -248,7 +248,7 @@ LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
    |                                  ^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:134:22
@@ -257,7 +257,7 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {}
    |                      ^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: `impl Trait` in const fn is unstable
   --> $DIR/min_const_fn.rs:135:23
@@ -266,7 +266,7 @@ LL | const fn no_rpit() -> impl std::fmt::Debug {}
    |                       ^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:136:23
@@ -275,7 +275,7 @@ LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {}
    |                       ^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:137:32
@@ -284,7 +284,7 @@ LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 warning[E0515]: cannot return reference to temporary value
   --> $DIR/min_const_fn.rs:137:63
@@ -306,7 +306,7 @@ LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: function pointers in const fn are unstable
   --> $DIR/min_const_fn.rs:148:21
@@ -315,7 +315,7 @@ LL | const fn no_fn_ptrs(_x: fn()) {}
    |                     ^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: function pointers in const fn are unstable
   --> $DIR/min_const_fn.rs:150:27
@@ -324,7 +324,7 @@ LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
    |                           ^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error: aborting due to 36 previous errors
 
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr
index 9ffb549057b..0ea950d678f 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.nll.stderr
@@ -5,7 +5,7 @@ LL |     x.0.field;
    |     ^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn_dyn.rs:12:66
@@ -14,7 +14,7 @@ LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
    |                                                                  ^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0716]: temporary value dropped while borrowed
   --> $DIR/min_const_fn_dyn.rs:12:67
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
index 9ded93c1672..02ddb039529 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
@@ -5,7 +5,7 @@ LL |     x.0.field;
    |     ^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn_dyn.rs:12:66
@@ -14,7 +14,7 @@ LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
    |                                                                  ^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 warning[E0716]: temporary value dropped while borrowed
   --> $DIR/min_const_fn_dyn.rs:12:67
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr
index 5316d07afa4..085ad1aad3a 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr
@@ -5,7 +5,7 @@ LL |     x.0.field;
    |     ^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: function pointers in const fn are unstable
   --> $DIR/min_const_fn_fn_ptr.rs:14:59
@@ -14,7 +14,7 @@ LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) }
    |                                                           ^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr
index c52d7c85115..0af5bdca815 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr
@@ -5,7 +5,7 @@ LL | const fn bar() -> u32 { foo() }
    |                         ^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2` is not stable as `const fn`
   --> $DIR/min_const_fn_libstd_stability.rs:22:26
@@ -14,7 +14,7 @@ LL | const fn bar2() -> u32 { foo2() }
    |                          ^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: only int, `bool` and `char` operations are stable in const fn
   --> $DIR/min_const_fn_libstd_stability.rs:26:26
@@ -23,7 +23,7 @@ LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 }
    |                          ^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2_gated` is not stable as `const fn`
   --> $DIR/min_const_fn_libstd_stability.rs:34:32
@@ -32,7 +32,7 @@ LL | const fn bar2_gated() -> u32 { foo2_gated() }
    |                                ^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr
index af39b99e90c..bc6f8c59606 100644
--- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr
@@ -5,7 +5,7 @@ LL | const unsafe fn bar() -> u32 { unsafe { foo() } }
    |                                         ^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2` is not stable as `const fn`
   --> $DIR/min_const_unsafe_fn_libstd_stability.rs:22:42
@@ -14,7 +14,7 @@ LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } }
    |                                          ^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: only int, `bool` and `char` operations are stable in const fn
   --> $DIR/min_const_unsafe_fn_libstd_stability.rs:26:33
@@ -23,7 +23,7 @@ LL | const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 }
    |                                 ^^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2_gated` is not stable as `const fn`
   --> $DIR/min_const_unsafe_fn_libstd_stability.rs:34:48
@@ -32,7 +32,7 @@ LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
    |                                                ^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr
index e4534d9ab98..a14fd740c67 100644
--- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr
@@ -5,7 +5,7 @@ LL | const unsafe fn bar() -> u32 { foo() }
    |                                ^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2` is not stable as `const fn`
   --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:22:33
@@ -14,7 +14,7 @@ LL | const unsafe fn bar2() -> u32 { foo2() }
    |                                 ^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2_gated` is not stable as `const fn`
   --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:30:39
@@ -23,7 +23,7 @@ LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() }
    |                                       ^^^^^^^^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/consts/min_const_fn/mutable_borrow.stderr b/src/test/ui/consts/min_const_fn/mutable_borrow.stderr
index ed55849124f..7c121be0d55 100644
--- a/src/test/ui/consts/min_const_fn/mutable_borrow.stderr
+++ b/src/test/ui/consts/min_const_fn/mutable_borrow.stderr
@@ -5,7 +5,7 @@ LL |     let b = &mut a;
    |         ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: mutable references in const fn are unstable
   --> $DIR/mutable_borrow.rs:12:13
@@ -14,7 +14,7 @@ LL |         let b = &mut a;
    |             ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/consts/single_variant_match_ice.stderr b/src/test/ui/consts/single_variant_match_ice.stderr
index 851733726ac..3f37a6c6450 100644
--- a/src/test/ui/consts/single_variant_match_ice.stderr
+++ b/src/test/ui/consts/single_variant_match_ice.stderr
@@ -17,7 +17,7 @@ LL |         match *self {
    |               ^^^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/derives/deriving-with-repr-packed.rs b/src/test/ui/derives/deriving-with-repr-packed.rs
index 66b0f85c85d..d354cef66bc 100644
--- a/src/test/ui/derives/deriving-with-repr-packed.rs
+++ b/src/test/ui/derives/deriving-with-repr-packed.rs
@@ -6,15 +6,15 @@
 // not be aligned.
 
 #[derive(Copy, Clone, PartialEq, Eq)]
-//~^ ERROR #[derive] can't be used
+//~^ ERROR `#[derive]` can't be used
 //~| hard error
-//~^^^ ERROR #[derive] can't be used
+//~^^^ ERROR `#[derive]` can't be used
 //~| hard error
 #[repr(packed)]
 pub struct Foo<T>(T, T, T);
 
 #[derive(PartialEq, Eq)]
-//~^ ERROR #[derive] can't be used
+//~^ ERROR `#[derive]` can't be used
 //~| hard error
 #[repr(packed)]
 pub struct Bar(u32, u32, u32);
@@ -23,7 +23,7 @@ pub struct Bar(u32, u32, u32);
 struct Y(usize);
 
 #[derive(PartialEq)]
-//~^ ERROR #[derive] can't be used
+//~^ ERROR `#[derive]` can't be used
 //~| hard error
 #[repr(packed)]
 struct X(Y);
diff --git a/src/test/ui/derives/deriving-with-repr-packed.stderr b/src/test/ui/derives/deriving-with-repr-packed.stderr
index 9d96908a056..8093c58a67e 100644
--- a/src/test/ui/derives/deriving-with-repr-packed.stderr
+++ b/src/test/ui/derives/deriving-with-repr-packed.stderr
@@ -1,4 +1,4 @@
-error: #[derive] can't be used on a #[repr(packed)] struct with type or const parameters (error E0133)
+error: `#[derive]` can't be used on a `#[repr(packed)]` struct with type or const parameters (error E0133)
   --> $DIR/deriving-with-repr-packed.rs:8:16
    |
 LL | #[derive(Copy, Clone, PartialEq, Eq)]
@@ -12,7 +12,7 @@ LL | #![deny(safe_packed_borrows)]
    = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
 
-error: #[derive] can't be used on a #[repr(packed)] struct with type or const parameters (error E0133)
+error: `#[derive]` can't be used on a `#[repr(packed)]` struct with type or const parameters (error E0133)
   --> $DIR/deriving-with-repr-packed.rs:8:23
    |
 LL | #[derive(Copy, Clone, PartialEq, Eq)]
@@ -21,7 +21,7 @@ LL | #[derive(Copy, Clone, PartialEq, Eq)]
    = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
 
-error: #[derive] can't be used on a #[repr(packed)] struct that does not derive Copy (error E0133)
+error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133)
   --> $DIR/deriving-with-repr-packed.rs:16:10
    |
 LL | #[derive(PartialEq, Eq)]
@@ -30,7 +30,7 @@ LL | #[derive(PartialEq, Eq)]
    = 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 #46043 <https://github.com/rust-lang/rust/issues/46043>
 
-error: #[derive] can't be used on a #[repr(packed)] struct that does not derive Copy (error E0133)
+error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133)
   --> $DIR/deriving-with-repr-packed.rs:25:10
    |
 LL | #[derive(PartialEq)]
diff --git a/src/test/ui/error-codes/E0008.stderr b/src/test/ui/error-codes/E0008.stderr
index 2505c03a148..6b45439c4b5 100644
--- a/src/test/ui/error-codes/E0008.stderr
+++ b/src/test/ui/error-codes/E0008.stderr
@@ -4,7 +4,7 @@ error[E0008]: cannot bind by-move into a pattern guard
 LL |         Some(s) if s.len() == 0 => {},
    |              ^ moves value into pattern guard
    |
-   = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable
+   = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0301.stderr b/src/test/ui/error-codes/E0301.stderr
index 44e823631b5..4f12fd3850e 100644
--- a/src/test/ui/error-codes/E0301.stderr
+++ b/src/test/ui/error-codes/E0301.stderr
@@ -4,7 +4,7 @@ error[E0301]: cannot mutably borrow in a pattern guard
 LL |         option if option.take().is_none() => {},
    |                   ^^^^^^ borrowed mutably in pattern guard
    |
-   = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable
+   = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable
 
 error[E0596]: cannot borrow `option` as mutable, as it is immutable for the pattern guard
   --> $DIR/E0301.rs:4:19
diff --git a/src/test/ui/hygiene/auxiliary/transparent-basic.rs b/src/test/ui/hygiene/auxiliary/transparent-basic.rs
index 0d045d09d2c..37de27ee800 100644
--- a/src/test/ui/hygiene/auxiliary/transparent-basic.rs
+++ b/src/test/ui/hygiene/auxiliary/transparent-basic.rs
@@ -1,6 +1,6 @@
 #![feature(decl_macro, rustc_attrs)]
 
-#[rustc_transparent_macro]
+#[rustc_macro_transparency = "transparent"]
 pub macro dollar_crate() {
     let s = $crate::S;
 }
diff --git a/src/test/ui/hygiene/generate-mod.rs b/src/test/ui/hygiene/generate-mod.rs
index 089d74f123e..8826293542c 100644
--- a/src/test/ui/hygiene/generate-mod.rs
+++ b/src/test/ui/hygiene/generate-mod.rs
@@ -11,7 +11,7 @@ macro genmod($FromOutside: ident, $Outer: ident) {
     }
 }
 
-#[rustc_transparent_macro]
+#[rustc_macro_transparency = "transparent"]
 macro genmod_transparent() {
     type A = FromOutside;
     struct Outer;
diff --git a/src/test/ui/hygiene/rustc-macro-transparency.rs b/src/test/ui/hygiene/rustc-macro-transparency.rs
new file mode 100644
index 00000000000..a0a3d411d28
--- /dev/null
+++ b/src/test/ui/hygiene/rustc-macro-transparency.rs
@@ -0,0 +1,31 @@
+#![feature(decl_macro, rustc_attrs)]
+
+#[rustc_macro_transparency = "transparent"]
+macro transparent() {
+    struct Transparent;
+    let transparent = 0;
+}
+#[rustc_macro_transparency = "semitransparent"]
+macro semitransparent() {
+    struct SemiTransparent;
+    let semitransparent = 0;
+}
+#[rustc_macro_transparency = "opaque"]
+macro opaque() {
+    struct Opaque;
+    let opaque = 0;
+}
+
+fn main() {
+    transparent!();
+    semitransparent!();
+    opaque!();
+
+    Transparent; // OK
+    SemiTransparent; // OK
+    Opaque; //~ ERROR cannot find value `Opaque` in this scope
+
+    transparent; // OK
+    semitransparent; //~ ERROR cannot find value `semitransparent` in this scope
+    opaque; //~ ERROR cannot find value `opaque` in this scope
+}
diff --git a/src/test/ui/hygiene/rustc-macro-transparency.stderr b/src/test/ui/hygiene/rustc-macro-transparency.stderr
new file mode 100644
index 00000000000..2a9df221e2c
--- /dev/null
+++ b/src/test/ui/hygiene/rustc-macro-transparency.stderr
@@ -0,0 +1,21 @@
+error[E0425]: cannot find value `Opaque` in this scope
+  --> $DIR/rustc-macro-transparency.rs:26:5
+   |
+LL |     Opaque;
+   |     ^^^^^^ help: a local variable with a similar name exists: `opaque`
+
+error[E0425]: cannot find value `semitransparent` in this scope
+  --> $DIR/rustc-macro-transparency.rs:29:5
+   |
+LL |     semitransparent;
+   |     ^^^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `opaque` in this scope
+  --> $DIR/rustc-macro-transparency.rs:30:5
+   |
+LL |     opaque;
+   |     ^^^^^^ not found in this scope
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/hygiene/transparent-basic.rs b/src/test/ui/hygiene/transparent-basic.rs
index 23ee558cc17..69dfc524989 100644
--- a/src/test/ui/hygiene/transparent-basic.rs
+++ b/src/test/ui/hygiene/transparent-basic.rs
@@ -5,12 +5,12 @@
 
 extern crate transparent_basic;
 
-#[rustc_transparent_macro]
+#[rustc_macro_transparency = "transparent"]
 macro binding() {
     let x = 10;
 }
 
-#[rustc_transparent_macro]
+#[rustc_macro_transparency = "transparent"]
 macro label() {
     break 'label
 }
diff --git a/src/test/ui/issues/issue-37550.stderr b/src/test/ui/issues/issue-37550.stderr
index 609043942b7..c1523e911fd 100644
--- a/src/test/ui/issues/issue-37550.stderr
+++ b/src/test/ui/issues/issue-37550.stderr
@@ -5,7 +5,7 @@ LL |     let x = || t;
    |         ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/restricted-shadowing-modern.rs b/src/test/ui/macros/restricted-shadowing-modern.rs
index 448f623c220..a8818507d75 100644
--- a/src/test/ui/macros/restricted-shadowing-modern.rs
+++ b/src/test/ui/macros/restricted-shadowing-modern.rs
@@ -80,17 +80,17 @@
 struct Right;
 // struct Wrong; // not defined
 
-#[rustc_transparent_macro]
+#[rustc_macro_transparency = "transparent"]
 macro include() {
-    #[rustc_transparent_macro]
+    #[rustc_macro_transparency = "transparent"]
     macro gen_outer() {
         macro m() { Wrong }
     }
-    #[rustc_transparent_macro]
+    #[rustc_macro_transparency = "transparent"]
     macro gen_inner() {
         macro m() { Right }
     }
-    #[rustc_transparent_macro]
+    #[rustc_macro_transparency = "transparent"]
     macro gen_invoc() {
         m!()
     }
@@ -100,7 +100,7 @@ macro include() {
     fn check1() {
         macro m() {}
         {
-            #[rustc_transparent_macro]
+            #[rustc_macro_transparency = "transparent"]
             macro gen_gen_inner_invoc() {
                 gen_inner!();
                 m!(); //~ ERROR `m` is ambiguous
@@ -112,7 +112,7 @@ macro include() {
     fn check5() {
         macro m() { Wrong }
         {
-            #[rustc_transparent_macro]
+            #[rustc_macro_transparency = "transparent"]
             macro gen_inner_invoc() {
                 macro m() { Right }
                 m!(); // OK
@@ -124,7 +124,7 @@ macro include() {
     fn check9() {
         macro m() { Wrong }
         {
-            #[rustc_transparent_macro]
+            #[rustc_macro_transparency = "transparent"]
             macro gen_inner_gen_invoc() {
                 macro m() { Right }
                 gen_invoc!(); // OK
@@ -145,7 +145,7 @@ macro include() {
         macro m() {}
         {
             gen_inner!();
-            #[rustc_transparent_macro]
+            #[rustc_macro_transparency = "transparent"]
             macro gen_invoc() { m!() } //~ ERROR `m` is ambiguous
             gen_invoc!();
         }
@@ -186,7 +186,7 @@ macro include() {
     fn check52() {
         gen_outer!();
         {
-            #[rustc_transparent_macro]
+            #[rustc_macro_transparency = "transparent"]
             macro gen_gen_inner_invoc() {
                 gen_inner!();
                 m!(); //~ ERROR `m` is ambiguous
@@ -198,7 +198,7 @@ macro include() {
     fn check56() {
         gen_outer!();
         {
-            #[rustc_transparent_macro]
+            #[rustc_macro_transparency = "transparent"]
             macro gen_inner_invoc() {
                 macro m() { Right }
                 m!(); // OK
@@ -218,7 +218,7 @@ macro include() {
     fn check60() {
         gen_outer!();
         {
-            #[rustc_transparent_macro]
+            #[rustc_macro_transparency = "transparent"]
             macro gen_inner_gen_invoc() {
                 macro m() { Right }
                 gen_invoc!(); // OK
@@ -231,7 +231,7 @@ macro include() {
         gen_outer!();
         {
             gen_inner!();
-            #[rustc_transparent_macro]
+            #[rustc_macro_transparency = "transparent"]
             macro gen_invoc() { m!() } //~ ERROR `m` is ambiguous
             gen_invoc!();
         }
diff --git a/src/test/ui/proc-macro/reserved-macro-names.rs b/src/test/ui/proc-macro/reserved-macro-names.rs
index 7c66af172fd..9f56eccb7a6 100644
--- a/src/test/ui/proc-macro/reserved-macro-names.rs
+++ b/src/test/ui/proc-macro/reserved-macro-names.rs
@@ -8,18 +8,18 @@ use proc_macro::*;
 
 #[proc_macro_attribute]
 pub fn cfg(_: TokenStream, input: TokenStream) -> TokenStream {
-    //~^ ERROR name `cfg` is reserved in macro namespace
+    //~^ ERROR name `cfg` is reserved in attribute namespace
     input
 }
 
 #[proc_macro_attribute]
 pub fn cfg_attr(_: TokenStream, input: TokenStream) -> TokenStream {
-    //~^ ERROR name `cfg_attr` is reserved in macro namespace
+    //~^ ERROR name `cfg_attr` is reserved in attribute namespace
     input
 }
 
 #[proc_macro_attribute]
 pub fn derive(_: TokenStream, input: TokenStream) -> TokenStream {
-    //~^ ERROR name `derive` is reserved in macro namespace
+    //~^ ERROR name `derive` is reserved in attribute namespace
     input
 }
diff --git a/src/test/ui/proc-macro/reserved-macro-names.stderr b/src/test/ui/proc-macro/reserved-macro-names.stderr
index 5ebe62a4969..f871e43ce51 100644
--- a/src/test/ui/proc-macro/reserved-macro-names.stderr
+++ b/src/test/ui/proc-macro/reserved-macro-names.stderr
@@ -1,16 +1,16 @@
-error: name `cfg` is reserved in macro namespace
+error: name `cfg` is reserved in attribute namespace
   --> $DIR/reserved-macro-names.rs:10:8
    |
 LL | pub fn cfg(_: TokenStream, input: TokenStream) -> TokenStream {
    |        ^^^
 
-error: name `cfg_attr` is reserved in macro namespace
+error: name `cfg_attr` is reserved in attribute namespace
   --> $DIR/reserved-macro-names.rs:16:8
    |
 LL | pub fn cfg_attr(_: TokenStream, input: TokenStream) -> TokenStream {
    |        ^^^^^^^^
 
-error: name `derive` is reserved in macro namespace
+error: name `derive` is reserved in attribute namespace
   --> $DIR/reserved-macro-names.rs:22:8
    |
 LL | pub fn derive(_: TokenStream, input: TokenStream) -> TokenStream {
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr
index 2a1a04b3f49..c2f6edee05f 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/feature-gate.no_gate.stderr
@@ -4,7 +4,7 @@ error[E0008]: cannot bind by-move into a pattern guard
 LL |         A { a: v } if *v == 42 => v,
    |                ^ moves value into pattern guard
    |
-   = help: add #![feature(bind_by_move_pattern_guards)] to the crate attributes to enable
+   = help: add `#![feature(bind_by_move_pattern_guards)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unsafe/ranged_ints2_const.stderr b/src/test/ui/unsafe/ranged_ints2_const.stderr
index 6a47c5b1414..e99155ee101 100644
--- a/src/test/ui/unsafe/ranged_ints2_const.stderr
+++ b/src/test/ui/unsafe/ranged_ints2_const.stderr
@@ -5,7 +5,7 @@ LL |     let y = &mut x.0;
    |         ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: mutable references in const fn are unstable
   --> $DIR/ranged_ints2_const.rs:18:9
@@ -14,7 +14,7 @@ LL |     let y = unsafe { &mut x.0 };
    |         ^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
-   = help: add #![feature(const_fn)] to the crate attributes to enable
+   = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
   --> $DIR/ranged_ints2_const.rs:11:13
diff --git a/src/tools/tidy/src/libcoretest.rs b/src/tools/tidy/src/libcoretest.rs
index ea92f989ada..58c6aa12dc4 100644
--- a/src/tools/tidy/src/libcoretest.rs
+++ b/src/tools/tidy/src/libcoretest.rs
@@ -13,7 +13,8 @@ pub fn check(path: &Path, bad: &mut bool) {
         &mut |entry, contents| {
             let subpath = entry.path();
             if let Some("rs") = subpath.extension().and_then(|e| e.to_str()) {
-                if contents.contains("#[test]") {
+                let contents = contents.trim();
+                if !contents.starts_with("//") && contents.contains("#[test]") {
                     tidy_error!(
                         bad,
                         "{} contains #[test]; libcore tests must be placed inside \