about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-07-10 05:21:43 +0000
committerbors <bors@rust-lang.org>2019-07-10 05:21:43 +0000
commit0324a2b309cd66cb7bd4a156bd0b84cb136e254f (patch)
treef85538e316a67aca8f749f5ebd1bb93754e6f206
parent3f435f622e0c05a199eb89b71a11181133fdb74c (diff)
parent6c0a406b1c9e4c518586ac3cc2fe96c21840a5dc (diff)
downloadrust-0324a2b309cd66cb7bd4a156bd0b84cb136e254f.tar.gz
rust-0324a2b309cd66cb7bd4a156bd0b84cb136e254f.zip
Auto merge of #62555 - Centril:rollup-ti46adx, r=Centril
Rollup of 5 pull requests

Successful merges:

 - #61853 (Emit warning when trying to use PGO in conjunction with unwinding on …)
 - #62278 (Add Iterator::partition_in_place() and is_partitioned())
 - #62283 (Target::arch can take more than listed options)
 - #62393 (Fix pretty-printing of `$crate` (take 4))
 - #62474 (Prepare for LLVM 9 update)

Failed merges:

r? @ghost
-rw-r--r--src/libcore/iter/traits/iterator.rs100
-rw-r--r--src/libcore/tests/iter.rs36
-rw-r--r--src/libcore/tests/lib.rs2
-rw-r--r--src/librustc/session/mod.rs8
-rw-r--r--src/librustc_codegen_llvm/abi.rs64
-rw-r--r--src/librustc_codegen_llvm/attributes.rs24
-rw-r--r--src/librustc_codegen_llvm/common.rs4
-rw-r--r--src/librustc_codegen_llvm/context.rs23
-rw-r--r--src/librustc_codegen_llvm/declare.rs2
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs5
-rw-r--r--src/librustc_codegen_llvm/llvm/ffi.rs3
-rw-r--r--src/librustc_codegen_ssa/traits/consts.rs1
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs5
-rw-r--r--src/librustc_resolve/macros.rs27
-rw-r--r--src/librustc_target/spec/arm_linux_androideabi.rs2
-rw-r--r--src/librustc_target/spec/arm_unknown_linux_gnueabi.rs2
-rw-r--r--src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs2
-rw-r--r--src/librustc_target/spec/arm_unknown_linux_musleabi.rs2
-rw-r--r--src/librustc_target/spec/arm_unknown_linux_musleabihf.rs2
-rw-r--r--src/librustc_target/spec/armebv7r_none_eabi.rs2
-rw-r--r--src/librustc_target/spec/armebv7r_none_eabihf.rs4
-rw-r--r--src/librustc_target/spec/armv4t_unknown_linux_gnueabi.rs2
-rw-r--r--src/librustc_target/spec/armv5te_unknown_linux_gnueabi.rs2
-rw-r--r--src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs2
-rw-r--r--src/librustc_target/spec/armv6_unknown_freebsd.rs2
-rw-r--r--src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs2
-rw-r--r--src/librustc_target/spec/armv7_apple_ios.rs2
-rw-r--r--src/librustc_target/spec/armv7_linux_androideabi.rs4
-rw-r--r--src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs2
-rw-r--r--src/librustc_target/spec/armv7_unknown_freebsd.rs4
-rw-r--r--src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs4
-rw-r--r--src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs4
-rw-r--r--src/librustc_target/spec/armv7_unknown_netbsd_eabihf.rs4
-rw-r--r--src/librustc_target/spec/armv7r_none_eabi.rs2
-rw-r--r--src/librustc_target/spec/armv7r_none_eabihf.rs4
-rw-r--r--src/librustc_target/spec/armv7s_apple_ios.rs2
-rw-r--r--src/librustc_target/spec/mod.rs4
-rw-r--r--src/librustc_target/spec/thumbv6m_none_eabi.rs2
-rw-r--r--src/librustc_target/spec/thumbv7a_pc_windows_msvc.rs2
-rw-r--r--src/librustc_target/spec/thumbv7em_none_eabi.rs2
-rw-r--r--src/librustc_target/spec/thumbv7em_none_eabihf.rs10
-rw-r--r--src/librustc_target/spec/thumbv7m_none_eabi.rs2
-rw-r--r--src/librustc_target/spec/thumbv7neon_linux_androideabi.rs2
-rw-r--r--src/librustc_target/spec/thumbv7neon_unknown_linux_gnueabihf.rs2
-rw-r--r--src/librustc_target/spec/thumbv8m_base_none_eabi.rs2
-rw-r--r--src/librustc_target/spec/thumbv8m_main_none_eabi.rs2
-rw-r--r--src/librustc_target/spec/thumbv8m_main_none_eabihf.rs4
-rw-r--r--src/libsyntax/ext/base.rs2
-rw-r--r--src/libsyntax/ext/expand.rs2
-rw-r--r--src/libsyntax/print/pprust.rs109
-rw-r--r--src/libsyntax_pos/hygiene.rs30
-rw-r--r--src/rustllvm/PassWrapper.cpp5
-rw-r--r--src/rustllvm/RustWrapper.cpp22
-rw-r--r--src/test/codegen/mainsubprogram.rs2
-rw-r--r--src/test/codegen/mainsubprogramstart.rs2
-rw-r--r--src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs6
-rw-r--r--src/test/ui/proc-macro/dollar-crate-issue-57089.stdout4
-rw-r--r--src/test/ui/proc-macro/dollar-crate-issue-62325.rs27
-rw-r--r--src/test/ui/proc-macro/dollar-crate-issue-62325.stdout112
-rw-r--r--src/test/ui/proc-macro/dollar-crate.stdout12
60 files changed, 551 insertions, 180 deletions
diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs
index b9a98236f18..6eddac672c1 100644
--- a/src/libcore/iter/traits/iterator.rs
+++ b/src/libcore/iter/traits/iterator.rs
@@ -1472,6 +1472,11 @@ pub trait Iterator {
     /// `partition()` returns a pair, all of the elements for which it returned
     /// `true`, and all of the elements for which it returned `false`.
     ///
+    /// See also [`is_partitioned()`] and [`partition_in_place()`].
+    ///
+    /// [`is_partitioned()`]: #method.is_partitioned
+    /// [`partition_in_place()`]: #method.partition_in_place
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -1506,6 +1511,101 @@ pub trait Iterator {
         (left, right)
     }
 
+    /// Reorder the elements of this iterator *in-place* according to the given predicate,
+    /// such that all those that return `true` precede all those that return `false`.
+    /// Returns the number of `true` elements found.
+    ///
+    /// The relative order of partitioned items is not maintained.
+    ///
+    /// See also [`is_partitioned()`] and [`partition()`].
+    ///
+    /// [`is_partitioned()`]: #method.is_partitioned
+    /// [`partition()`]: #method.partition
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(iter_partition_in_place)]
+    ///
+    /// let mut a = [1, 2, 3, 4, 5, 6, 7];
+    ///
+    /// // Partition in-place between evens and odds
+    /// let i = a.iter_mut().partition_in_place(|&n| n % 2 == 0);
+    ///
+    /// assert_eq!(i, 3);
+    /// assert!(a[..i].iter().all(|&n| n % 2 == 0)); // evens
+    /// assert!(a[i..].iter().all(|&n| n % 2 == 1)); // odds
+    /// ```
+    #[unstable(feature = "iter_partition_in_place", reason = "new API", issue = "62543")]
+    fn partition_in_place<'a, T: 'a, P>(mut self, ref mut predicate: P) -> usize
+    where
+        Self: Sized + DoubleEndedIterator<Item = &'a mut T>,
+        P: FnMut(&T) -> bool,
+    {
+        // FIXME: should we worry about the count overflowing? The only way to have more than
+        // `usize::MAX` mutable references is with ZSTs, which aren't useful to partition...
+
+        // These closure "factory" functions exist to avoid genericity in `Self`.
+
+        #[inline]
+        fn is_false<'a, T>(
+            predicate: &'a mut impl FnMut(&T) -> bool,
+            true_count: &'a mut usize,
+        ) -> impl FnMut(&&mut T) -> bool + 'a {
+            move |x| {
+                let p = predicate(&**x);
+                *true_count += p as usize;
+                !p
+            }
+        }
+
+        #[inline]
+        fn is_true<T>(
+            predicate: &mut impl FnMut(&T) -> bool
+        ) -> impl FnMut(&&mut T) -> bool + '_ {
+            move |x| predicate(&**x)
+        }
+
+        // Repeatedly find the first `false` and swap it with the last `true`.
+        let mut true_count = 0;
+        while let Some(head) = self.find(is_false(predicate, &mut true_count)) {
+            if let Some(tail) = self.rfind(is_true(predicate)) {
+                crate::mem::swap(head, tail);
+                true_count += 1;
+            } else {
+                break;
+            }
+        }
+        true_count
+    }
+
+    /// Checks if the elements of this iterator are partitioned according to the given predicate,
+    /// such that all those that return `true` precede all those that return `false`.
+    ///
+    /// See also [`partition()`] and [`partition_in_place()`].
+    ///
+    /// [`partition()`]: #method.partition
+    /// [`partition_in_place()`]: #method.partition_in_place
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(iter_is_partitioned)]
+    ///
+    /// assert!("Iterator".chars().is_partitioned(char::is_uppercase));
+    /// assert!(!"IntoIterator".chars().is_partitioned(char::is_uppercase));
+    /// ```
+    #[unstable(feature = "iter_is_partitioned", reason = "new API", issue = "62544")]
+    fn is_partitioned<P>(mut self, mut predicate: P) -> bool
+    where
+        Self: Sized,
+        P: FnMut(Self::Item) -> bool,
+    {
+        // Either all items test `true`, or the first clause stops at `false`
+        // and we check that there are no more `true` items after that.
+        self.all(&mut predicate) || !self.any(predicate)
+    }
+
     /// An iterator method that applies a function as long as it returns
     /// successfully, producing a single, final value.
     ///
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index 4d840ef24c8..b7b0849e212 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -2460,3 +2460,39 @@ fn test_is_sorted() {
     assert!(!["c", "bb", "aaa"].iter().is_sorted());
     assert!(["c", "bb", "aaa"].iter().is_sorted_by_key(|s| s.len()));
 }
+
+#[test]
+fn test_partition() {
+    fn check(xs: &mut [i32], ref p: impl Fn(&i32) -> bool, expected: usize) {
+        let i = xs.iter_mut().partition_in_place(p);
+        assert_eq!(expected, i);
+        assert!(xs[..i].iter().all(p));
+        assert!(!xs[i..].iter().any(p));
+        assert!(xs.iter().is_partitioned(p));
+        if i == 0 || i == xs.len() {
+            assert!(xs.iter().rev().is_partitioned(p));
+        } else {
+            assert!(!xs.iter().rev().is_partitioned(p));
+        }
+    }
+
+    check(&mut [], |_| true, 0);
+    check(&mut [], |_| false, 0);
+
+    check(&mut [0], |_| true, 1);
+    check(&mut [0], |_| false, 0);
+
+    check(&mut [-1, 1], |&x| x > 0, 1);
+    check(&mut [-1, 1], |&x| x < 0, 1);
+
+    let ref mut xs = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+    check(xs, |_| true, 10);
+    check(xs, |_| false, 0);
+    check(xs, |&x| x % 2 == 0, 5); // evens
+    check(xs, |&x| x % 2 == 1, 5); // odds
+    check(xs, |&x| x % 3 == 0, 4); // multiple of 3
+    check(xs, |&x| x % 4 == 0, 3); // multiple of 4
+    check(xs, |&x| x % 5 == 0, 2); // multiple of 5
+    check(xs, |&x| x < 3, 3); // small
+    check(xs, |&x| x > 6, 3); // large
+}
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 4b48d122590..cbb6423d710 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -31,6 +31,8 @@
 #![feature(slice_partition_dedup)]
 #![feature(int_error_matching)]
 #![feature(const_fn)]
+#![feature(iter_partition_in_place)]
+#![feature(iter_is_partitioned)]
 #![warn(rust_2018_idioms)]
 
 extern crate test;
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 3cbf0ee213a..b17ba8de730 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -1303,15 +1303,15 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
     }
 
     // PGO does not work reliably with panic=unwind on Windows. Let's make it
-    // an error to combine the two for now. It always runs into an assertions
+    // a warning to combine the two for now. It always runs into an assertions
     // if LLVM is built with assertions, but without assertions it sometimes
     // does not crash and will probably generate a corrupted binary.
     if sess.opts.cg.profile_generate.enabled() &&
        sess.target.target.options.is_like_msvc &&
        sess.panic_strategy() == PanicStrategy::Unwind {
-        sess.err("Profile-guided optimization does not yet work in conjunction \
-                  with `-Cpanic=unwind` on Windows when targeting MSVC. \
-                  See https://github.com/rust-lang/rust/issues/61002 for details.");
+        sess.warn("Profile-guided optimization does not yet work in conjunction \
+                   with `-Cpanic=unwind` on Windows when targeting MSVC. \
+                   See https://github.com/rust-lang/rust/issues/61002 for details.");
     }
 }
 
diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs
index 38d4b7e3f9d..ff87afe0c44 100644
--- a/src/librustc_codegen_llvm/abi.rs
+++ b/src/librustc_codegen_llvm/abi.rs
@@ -34,17 +34,17 @@ trait ArgAttributeExt {
 impl ArgAttributeExt for ArgAttribute {
     fn for_each_kind<F>(&self, mut f: F) where F: FnMut(llvm::Attribute) {
         for_each_kind!(self, f,
-                       ByVal, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg)
+                       NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg)
     }
 }
 
 pub trait ArgAttributesExt {
-    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value);
-    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value);
+    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>);
+    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>);
 }
 
 impl ArgAttributesExt for ArgAttributes {
-    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) {
+    fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>) {
         let mut regular = self.regular;
         unsafe {
             let deref = self.pointee_size.bytes();
@@ -65,11 +65,14 @@ impl ArgAttributesExt for ArgAttributes {
                                                idx.as_uint(),
                                                align.bytes() as u32);
             }
+            if regular.contains(ArgAttribute::ByVal) {
+                llvm::LLVMRustAddByValAttr(llfn, idx.as_uint(), ty.unwrap());
+            }
             regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn));
         }
     }
 
-    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) {
+    fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>) {
         let mut regular = self.regular;
         unsafe {
             let deref = self.pointee_size.bytes();
@@ -90,6 +93,9 @@ impl ArgAttributesExt for ArgAttributes {
                                                        idx.as_uint(),
                                                        align.bytes() as u32);
             }
+            if regular.contains(ArgAttribute::ByVal) {
+                llvm::LLVMRustAddByValCallSiteAttr(callsite, idx.as_uint(), ty.unwrap());
+            }
             regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite));
         }
     }
@@ -298,7 +304,7 @@ pub trait FnTypeLlvmExt<'tcx> {
     fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
     fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
     fn llvm_cconv(&self) -> llvm::CallConv;
-    fn apply_attrs_llfn(&self, llfn: &'ll Value);
+    fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value);
     fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value);
 }
 
@@ -384,51 +390,51 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
         }
     }
 
-    fn apply_attrs_llfn(&self, llfn: &'ll Value) {
+    fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
         let mut i = 0;
-        let mut apply = |attrs: &ArgAttributes| {
-            attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn);
+        let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
+            attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn, ty);
             i += 1;
         };
         match self.ret.mode {
             PassMode::Direct(ref attrs) => {
-                attrs.apply_llfn(llvm::AttributePlace::ReturnValue, llfn);
+                attrs.apply_llfn(llvm::AttributePlace::ReturnValue, llfn, None);
             }
-            PassMode::Indirect(ref attrs, _) => apply(attrs),
+            PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(cx))),
             _ => {}
         }
         for arg in &self.args {
             if arg.pad.is_some() {
-                apply(&ArgAttributes::new());
+                apply(&ArgAttributes::new(), None);
             }
             match arg.mode {
                 PassMode::Ignore(_) => {}
                 PassMode::Direct(ref attrs) |
-                PassMode::Indirect(ref attrs, None) => apply(attrs),
+                PassMode::Indirect(ref attrs, None) => apply(attrs, Some(arg.layout.llvm_type(cx))),
                 PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
-                    apply(attrs);
-                    apply(extra_attrs);
+                    apply(attrs, None);
+                    apply(extra_attrs, None);
                 }
                 PassMode::Pair(ref a, ref b) => {
-                    apply(a);
-                    apply(b);
+                    apply(a, None);
+                    apply(b, None);
                 }
-                PassMode::Cast(_) => apply(&ArgAttributes::new()),
+                PassMode::Cast(_) => apply(&ArgAttributes::new(), None),
             }
         }
     }
 
     fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value) {
         let mut i = 0;
-        let mut apply = |attrs: &ArgAttributes| {
-            attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite);
+        let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
+            attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite, ty);
             i += 1;
         };
         match self.ret.mode {
             PassMode::Direct(ref attrs) => {
-                attrs.apply_callsite(llvm::AttributePlace::ReturnValue, callsite);
+                attrs.apply_callsite(llvm::AttributePlace::ReturnValue, callsite, None);
             }
-            PassMode::Indirect(ref attrs, _) => apply(attrs),
+            PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(bx))),
             _ => {}
         }
         if let layout::Abi::Scalar(ref scalar) = self.ret.layout.abi {
@@ -446,21 +452,21 @@ impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
         }
         for arg in &self.args {
             if arg.pad.is_some() {
-                apply(&ArgAttributes::new());
+                apply(&ArgAttributes::new(), None);
             }
             match arg.mode {
                 PassMode::Ignore(_) => {}
                 PassMode::Direct(ref attrs) |
-                PassMode::Indirect(ref attrs, None) => apply(attrs),
+                PassMode::Indirect(ref attrs, None) => apply(attrs, Some(arg.layout.llvm_type(bx))),
                 PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
-                    apply(attrs);
-                    apply(extra_attrs);
+                    apply(attrs, None);
+                    apply(extra_attrs, None);
                 }
                 PassMode::Pair(ref a, ref b) => {
-                    apply(a);
-                    apply(b);
+                    apply(a, None);
+                    apply(b, None);
                 }
-                PassMode::Cast(_) => apply(&ArgAttributes::new()),
+                PassMode::Cast(_) => apply(&ArgAttributes::new(), None),
             }
         }
 
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index 94abf1796d3..33b50401b22 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -119,6 +119,29 @@ pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
         const_cstr!("probe-stack"), const_cstr!("__rust_probestack"));
 }
 
+fn translate_obsolete_target_features(feature: &str) -> &str {
+    const LLVM9_FEATURE_CHANGES: &[(&str, &str)] = &[
+        ("+fp-only-sp", "-fp64"),
+        ("-fp-only-sp", "+fp64"),
+        ("+d16", "-d32"),
+        ("-d16", "+d32"),
+    ];
+    if llvm_util::get_major_version() >= 9 {
+        for &(old, new) in LLVM9_FEATURE_CHANGES {
+            if feature == old {
+                return new;
+            }
+        }
+    } else {
+        for &(old, new) in LLVM9_FEATURE_CHANGES {
+            if feature == new {
+                return old;
+            }
+        }
+    }
+    feature
+}
+
 pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
     const RUSTC_SPECIFIC_FEATURES: &[&str] = &[
         "crt-static",
@@ -129,6 +152,7 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
     sess.target.target.options.features.split(',')
         .chain(cmdline)
         .filter(|l| !l.is_empty())
+        .map(translate_obsolete_target_features)
 }
 
 pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs
index 3b2701b893b..e9f25e6344b 100644
--- a/src/librustc_codegen_llvm/common.rs
+++ b/src/librustc_codegen_llvm/common.rs
@@ -249,6 +249,10 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         self.const_uint(self.type_i8(), i as u64)
     }
 
+    fn const_real(&self, t: &'ll Type, val: f64) -> &'ll Value {
+        unsafe { llvm::LLVMConstReal(t, val) }
+    }
+
     fn const_struct(
         &self,
         elts: &[&'ll Value],
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 6a61b180de4..2b68eb53a4a 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -1,5 +1,6 @@
 use crate::attributes;
 use crate::llvm;
+use crate::llvm_util;
 use crate::debuginfo;
 use crate::value::Value;
 use rustc::dep_graph::DepGraphSafe;
@@ -140,6 +141,11 @@ pub fn is_pie_binary(sess: &Session) -> bool {
     !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC
 }
 
+fn strip_function_ptr_alignment(data_layout: String) -> String {
+    // FIXME: Make this more general.
+    data_layout.replace("-Fi8-", "-")
+}
+
 pub unsafe fn create_module(
     tcx: TyCtxt<'_>,
     llcx: &'ll llvm::Context,
@@ -149,14 +155,19 @@ pub unsafe fn create_module(
     let mod_name = SmallCStr::new(mod_name);
     let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
 
+    let mut target_data_layout = sess.target.target.data_layout.clone();
+    if llvm_util::get_major_version() < 9 {
+        target_data_layout = strip_function_ptr_alignment(target_data_layout);
+    }
+
     // Ensure the data-layout values hardcoded remain the defaults.
     if sess.target.target.options.is_builtin {
         let tm = crate::back::write::create_informational_target_machine(&tcx.sess, false);
         llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm);
         llvm::LLVMRustDisposeTargetMachine(tm);
 
-        let data_layout = llvm::LLVMGetDataLayout(llmod);
-        let data_layout = str::from_utf8(CStr::from_ptr(data_layout).to_bytes())
+        let llvm_data_layout = llvm::LLVMGetDataLayout(llmod);
+        let llvm_data_layout = str::from_utf8(CStr::from_ptr(llvm_data_layout).to_bytes())
             .ok().expect("got a non-UTF8 data-layout from LLVM");
 
         // Unfortunately LLVM target specs change over time, and right now we
@@ -177,16 +188,16 @@ pub unsafe fn create_module(
         let cfg_llvm_root = option_env!("CFG_LLVM_ROOT").unwrap_or("");
         let custom_llvm_used = cfg_llvm_root.trim() != "";
 
-        if !custom_llvm_used && sess.target.target.data_layout != data_layout {
+        if !custom_llvm_used && target_data_layout != llvm_data_layout {
             bug!("data-layout for builtin `{}` target, `{}`, \
                   differs from LLVM default, `{}`",
                  sess.target.target.llvm_target,
-                 sess.target.target.data_layout,
-                 data_layout);
+                 target_data_layout,
+                 llvm_data_layout);
         }
     }
 
-    let data_layout = SmallCStr::new(&sess.target.target.data_layout);
+    let data_layout = SmallCStr::new(&target_data_layout);
     llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
 
     let llvm_target = SmallCStr::new(&sess.target.target.llvm_target);
diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs
index bcb14b8899e..62eab0f3d4e 100644
--- a/src/librustc_codegen_llvm/declare.rs
+++ b/src/librustc_codegen_llvm/declare.rs
@@ -107,7 +107,7 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> {
             llvm::Attribute::NoReturn.apply_llfn(Function, llfn);
         }
 
-        fty.apply_attrs_llfn(llfn);
+        fty.apply_attrs_llfn(self, llfn);
 
         llfn
     }
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 69f8356f669..dd6cfd7e29e 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -1663,9 +1663,10 @@ fn generic_simd_intrinsic(
                             acc
                         } else {
                             // unordered arithmetic reductions do not:
+                            let identity_acc = if $name.contains("mul") { 1.0 } else { 0.0 };
                             match f.bit_width() {
-                                32 => bx.const_undef(bx.type_f32()),
-                                64 => bx.const_undef(bx.type_f64()),
+                                32 => bx.const_real(bx.type_f32(), identity_acc),
+                                64 => bx.const_real(bx.type_f64(), identity_acc),
                                 v => {
                                     return_error!(r#"
 unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index 708ba79ec3a..2b22925f449 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -715,6 +715,7 @@ extern "C" {
     // Operations on scalar constants
     pub fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value;
     pub fn LLVMConstIntOfArbitraryPrecision(IntTy: &Type, Wn: c_uint, Ws: *const u64) -> &Value;
+    pub fn LLVMConstReal(RealTy: &Type, N: f64) -> &Value;
     pub fn LLVMConstIntGetZExtValue(ConstantVal: &Value) -> c_ulonglong;
     pub fn LLVMRustConstInt128Get(ConstantVal: &Value, SExt: bool,
                                   high: &mut u64, low: &mut u64) -> bool;
@@ -794,6 +795,7 @@ extern "C" {
     pub fn LLVMRustAddAlignmentAttr(Fn: &Value, index: c_uint, bytes: u32);
     pub fn LLVMRustAddDereferenceableAttr(Fn: &Value, index: c_uint, bytes: u64);
     pub fn LLVMRustAddDereferenceableOrNullAttr(Fn: &Value, index: c_uint, bytes: u64);
+    pub fn LLVMRustAddByValAttr(Fn: &Value, index: c_uint, ty: &Type);
     pub fn LLVMRustAddFunctionAttribute(Fn: &Value, index: c_uint, attr: Attribute);
     pub fn LLVMRustAddFunctionAttrStringValue(Fn: &Value,
                                               index: c_uint,
@@ -824,6 +826,7 @@ extern "C" {
     pub fn LLVMRustAddDereferenceableOrNullCallSiteAttr(Instr: &Value,
                                                         index: c_uint,
                                                         bytes: u64);
+    pub fn LLVMRustAddByValCallSiteAttr(Instr: &Value, index: c_uint, ty: &Type);
 
     // Operations on load/store instructions (only)
     pub fn LLVMSetVolatile(MemoryAccessInst: &Value, volatile: Bool);
diff --git a/src/librustc_codegen_ssa/traits/consts.rs b/src/librustc_codegen_ssa/traits/consts.rs
index 46286b5329e..248fadfaf0f 100644
--- a/src/librustc_codegen_ssa/traits/consts.rs
+++ b/src/librustc_codegen_ssa/traits/consts.rs
@@ -17,6 +17,7 @@ pub trait ConstMethods<'tcx>: BackendTypes {
     fn const_u64(&self, i: u64) -> Self::Value;
     fn const_usize(&self, i: u64) -> Self::Value;
     fn const_u8(&self, i: u8) -> Self::Value;
+    fn const_real(&self, t: Self::Type, val: f64) -> Self::Value;
 
     fn const_struct(&self, elts: &[Self::Value], packed: bool) -> Self::Value;
 
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 3921bd30df2..49116f3f171 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -758,7 +758,10 @@ impl<'a> Resolver<'a> {
     }
 
     pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {
-        let def_id = self.macro_defs[&expansion];
+        let def_id = match self.macro_defs.get(&expansion) {
+            Some(def_id) => *def_id,
+            None => return self.graph_root,
+        };
         if let Some(id) = self.definitions.as_local_node_id(def_id) {
             self.local_macro_def_scopes[&id]
         } else if def_id.krate == CrateNum::BuiltinMacros {
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index f26c3b8ae6a..8f23c9813f7 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -17,12 +17,11 @@ use syntax::errors::DiagnosticBuilder;
 use syntax::ext::base::{self, Determinacy};
 use syntax::ext::base::{MacroKind, SyntaxExtension};
 use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
-use syntax::ext::hygiene::Mark;
+use syntax::ext::hygiene::{self, Mark};
 use syntax::ext::tt::macro_rules;
 use syntax::feature_gate::{feature_err, emit_feature_err, is_builtin_attr_name};
 use syntax::feature_gate::{AttributeGate, GateIssue, Stability, BUILTIN_ATTRIBUTES};
 use syntax::symbol::{Symbol, kw, sym};
-use syntax::visit::Visitor;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax_pos::{Span, DUMMY_SP};
 use errors::Applicability;
@@ -146,24 +145,14 @@ impl<'a> base::Resolver for Resolver<'a> {
         mark
     }
 
-    fn resolve_dollar_crates(&mut self, fragment: &AstFragment) {
-        struct ResolveDollarCrates<'a, 'b> {
-            resolver: &'a mut Resolver<'b>
-        }
-        impl<'a> Visitor<'a> for ResolveDollarCrates<'a, '_> {
-            fn visit_ident(&mut self, ident: Ident) {
-                if ident.name == kw::DollarCrate {
-                    let name = match self.resolver.resolve_crate_root(ident).kind {
-                        ModuleKind::Def(.., name) if name != kw::Invalid => name,
-                        _ => kw::Crate,
-                    };
-                    ident.span.ctxt().set_dollar_crate_name(name);
-                }
+    fn resolve_dollar_crates(&mut self) {
+        hygiene::update_dollar_crate_names(|ctxt| {
+            let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt));
+            match self.resolve_crate_root(ident).kind {
+                ModuleKind::Def(.., name) if name != kw::Invalid => name,
+                _ => kw::Crate,
             }
-            fn visit_mac(&mut self, _: &ast::Mac) {}
-        }
-
-        fragment.visit_with(&mut ResolveDollarCrates { resolver: self });
+        });
     }
 
     fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
diff --git a/src/librustc_target/spec/arm_linux_androideabi.rs b/src/librustc_target/spec/arm_linux_androideabi.rs
index bb066dc9ad8..c02edabd886 100644
--- a/src/librustc_target/spec/arm_linux_androideabi.rs
+++ b/src/librustc_target/spec/arm_linux_androideabi.rs
@@ -11,7 +11,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "android".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/arm_unknown_linux_gnueabi.rs b/src/librustc_target/spec/arm_unknown_linux_gnueabi.rs
index 2f835420148..1d5751c1f71 100644
--- a/src/librustc_target/spec/arm_unknown_linux_gnueabi.rs
+++ b/src/librustc_target/spec/arm_unknown_linux_gnueabi.rs
@@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs b/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs
index cd4b2e1c922..8eb19a6518a 100644
--- a/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs
+++ b/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs
@@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/arm_unknown_linux_musleabi.rs b/src/librustc_target/spec/arm_unknown_linux_musleabi.rs
index 606c3f19060..5c40b6fb89f 100644
--- a/src/librustc_target/spec/arm_unknown_linux_musleabi.rs
+++ b/src/librustc_target/spec/arm_unknown_linux_musleabi.rs
@@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
diff --git a/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs b/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs
index d22156bc328..496a0c4a43a 100644
--- a/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs
+++ b/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs
@@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
diff --git a/src/librustc_target/spec/armebv7r_none_eabi.rs b/src/librustc_target/spec/armebv7r_none_eabi.rs
index 86c62daa618..0b41b920e58 100644
--- a/src/librustc_target/spec/armebv7r_none_eabi.rs
+++ b/src/librustc_target/spec/armebv7r_none_eabi.rs
@@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
         target_endian: "big".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: "".to_string(),
diff --git a/src/librustc_target/spec/armebv7r_none_eabihf.rs b/src/librustc_target/spec/armebv7r_none_eabihf.rs
index 50ee76414ef..5f1bfdce355 100644
--- a/src/librustc_target/spec/armebv7r_none_eabihf.rs
+++ b/src/librustc_target/spec/armebv7r_none_eabihf.rs
@@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
         target_endian: "big".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: String::new(),
@@ -21,7 +21,7 @@ pub fn target() -> TargetResult {
             linker: Some("rust-lld".to_owned()),
             relocation_model: "static".to_string(),
             panic_strategy: PanicStrategy::Abort,
-            features: "+vfp3,+d16,+fp-only-sp".to_string(),
+            features: "+vfp3,-d32,-fp16".to_string(),
             max_atomic_width: Some(32),
             abi_blacklist: super::arm_base::abi_blacklist(),
             emit_debug_gdb_scripts: false,
diff --git a/src/librustc_target/spec/armv4t_unknown_linux_gnueabi.rs b/src/librustc_target/spec/armv4t_unknown_linux_gnueabi.rs
index e7da24843cc..264bf8d871d 100644
--- a/src/librustc_target/spec/armv4t_unknown_linux_gnueabi.rs
+++ b/src/librustc_target/spec/armv4t_unknown_linux_gnueabi.rs
@@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/armv5te_unknown_linux_gnueabi.rs b/src/librustc_target/spec/armv5te_unknown_linux_gnueabi.rs
index ea586f42c26..d0f1222d87a 100644
--- a/src/librustc_target/spec/armv5te_unknown_linux_gnueabi.rs
+++ b/src/librustc_target/spec/armv5te_unknown_linux_gnueabi.rs
@@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs b/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs
index dae5c8c3d75..9c08a7741a6 100644
--- a/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs
+++ b/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs
@@ -10,7 +10,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
diff --git a/src/librustc_target/spec/armv6_unknown_freebsd.rs b/src/librustc_target/spec/armv6_unknown_freebsd.rs
index a90590a39e7..efbbee959ed 100644
--- a/src/librustc_target/spec/armv6_unknown_freebsd.rs
+++ b/src/librustc_target/spec/armv6_unknown_freebsd.rs
@@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "freebsd".to_string(),
         target_env: "gnueabihf".to_string(),
diff --git a/src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs b/src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs
index b056776bdfb..b76c39ac75b 100644
--- a/src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs
+++ b/src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs
@@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "netbsd".to_string(),
         target_env: "eabihf".to_string(),
diff --git a/src/librustc_target/spec/armv7_apple_ios.rs b/src/librustc_target/spec/armv7_apple_ios.rs
index 2052d17403d..c1e1caf8e2e 100644
--- a/src/librustc_target/spec/armv7_apple_ios.rs
+++ b/src/librustc_target/spec/armv7_apple_ios.rs
@@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(),
+        data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(),
         arch: "arm".to_string(),
         target_os: "ios".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/armv7_linux_androideabi.rs b/src/librustc_target/spec/armv7_linux_androideabi.rs
index 92f1a55e024..e22a853814a 100644
--- a/src/librustc_target/spec/armv7_linux_androideabi.rs
+++ b/src/librustc_target/spec/armv7_linux_androideabi.rs
@@ -10,7 +10,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::android_base::opts();
-    base.features = "+v7,+thumb-mode,+thumb2,+vfp3,+d16,-neon".to_string();
+    base.features = "+v7,+thumb-mode,+thumb2,+vfp3,-d32,-neon".to_string();
     base.max_atomic_width = Some(64);
     base.pre_link_args
         .get_mut(&LinkerFlavor::Gcc).unwrap().push("-march=armv7-a".to_string());
@@ -20,7 +20,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "android".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs b/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs
index c03f4b544ed..7065d30a5be 100644
--- a/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs
+++ b/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs
@@ -13,7 +13,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "cloudabi".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/armv7_unknown_freebsd.rs b/src/librustc_target/spec/armv7_unknown_freebsd.rs
index ca7ab474bef..219b06362f3 100644
--- a/src/librustc_target/spec/armv7_unknown_freebsd.rs
+++ b/src/librustc_target/spec/armv7_unknown_freebsd.rs
@@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "freebsd".to_string(),
         target_env: "gnueabihf".to_string(),
@@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
         linker_flavor: LinkerFlavor::Gcc,
 
         options: TargetOptions {
-            features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
+            features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
             max_atomic_width: Some(64),
             abi_blacklist: super::arm_base::abi_blacklist(),
             target_mcount: "\u{1}__gnu_mcount_nc".to_string(),
diff --git a/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs b/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs
index f0952cccb20..1dd53b1b422 100644
--- a/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs
+++ b/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs
@@ -10,7 +10,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
@@ -19,7 +19,7 @@ pub fn target() -> TargetResult {
 
         options: TargetOptions {
             // Info about features at https://wiki.debian.org/ArmHardFloatPort
-            features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
+            features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
             cpu: "generic".to_string(),
             max_atomic_width: Some(64),
             abi_blacklist: super::arm_base::abi_blacklist(),
diff --git a/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs b/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs
index a9974f6b80c..ee8e48e3e75 100644
--- a/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs
+++ b/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs
@@ -12,7 +12,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
@@ -22,7 +22,7 @@ pub fn target() -> TargetResult {
         // Most of these settings are copied from the armv7_unknown_linux_gnueabihf
         // target.
         options: TargetOptions {
-            features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
+            features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
             cpu: "generic".to_string(),
             max_atomic_width: Some(64),
             abi_blacklist: super::arm_base::abi_blacklist(),
diff --git a/src/librustc_target/spec/armv7_unknown_netbsd_eabihf.rs b/src/librustc_target/spec/armv7_unknown_netbsd_eabihf.rs
index e2d55e9317b..1d63b0261c1 100644
--- a/src/librustc_target/spec/armv7_unknown_netbsd_eabihf.rs
+++ b/src/librustc_target/spec/armv7_unknown_netbsd_eabihf.rs
@@ -7,7 +7,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "netbsd".to_string(),
         target_env: "eabihf".to_string(),
@@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
         linker_flavor: LinkerFlavor::Gcc,
 
         options: TargetOptions {
-            features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
+            features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
             cpu: "generic".to_string(),
             max_atomic_width: Some(64),
             abi_blacklist: super::arm_base::abi_blacklist(),
diff --git a/src/librustc_target/spec/armv7r_none_eabi.rs b/src/librustc_target/spec/armv7r_none_eabi.rs
index 19d332467de..814ca1d77ac 100644
--- a/src/librustc_target/spec/armv7r_none_eabi.rs
+++ b/src/librustc_target/spec/armv7r_none_eabi.rs
@@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: "".to_string(),
diff --git a/src/librustc_target/spec/armv7r_none_eabihf.rs b/src/librustc_target/spec/armv7r_none_eabihf.rs
index 06ef9f3ec4e..decf1a01e0b 100644
--- a/src/librustc_target/spec/armv7r_none_eabihf.rs
+++ b/src/librustc_target/spec/armv7r_none_eabihf.rs
@@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: "".to_string(),
@@ -21,7 +21,7 @@ pub fn target() -> TargetResult {
             linker: Some("rust-lld".to_owned()),
             relocation_model: "static".to_string(),
             panic_strategy: PanicStrategy::Abort,
-            features: "+vfp3,+d16,+fp-only-sp".to_string(),
+            features: "+vfp3,-d32,-fp16".to_string(),
             max_atomic_width: Some(32),
             abi_blacklist: super::arm_base::abi_blacklist(),
             emit_debug_gdb_scripts: false,
diff --git a/src/librustc_target/spec/armv7s_apple_ios.rs b/src/librustc_target/spec/armv7s_apple_ios.rs
index 29e290285e4..55e2a876865 100644
--- a/src/librustc_target/spec/armv7s_apple_ios.rs
+++ b/src/librustc_target/spec/armv7s_apple_ios.rs
@@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(),
+        data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(),
         arch: "arm".to_string(),
         target_os: "ios".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index 75821aba470..3054ffabb4f 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -497,8 +497,8 @@ pub struct Target {
     pub target_env: String,
     /// Vendor name to use for conditional compilation.
     pub target_vendor: String,
-    /// Architecture to use for ABI considerations. Valid options: "x86",
-    /// "x86_64", "arm", "aarch64", "mips", "powerpc", and "powerpc64".
+    /// Architecture to use for ABI considerations. Valid options include: "x86",
+    /// "x86_64", "arm", "aarch64", "mips", "powerpc", "powerpc64", and others.
     pub arch: String,
     /// [Data layout](http://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM.
     pub data_layout: String,
diff --git a/src/librustc_target/spec/thumbv6m_none_eabi.rs b/src/librustc_target/spec/thumbv6m_none_eabi.rs
index 2ab61b57f6b..28353552fc7 100644
--- a/src/librustc_target/spec/thumbv6m_none_eabi.rs
+++ b/src/librustc_target/spec/thumbv6m_none_eabi.rs
@@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/thumbv7a_pc_windows_msvc.rs b/src/librustc_target/spec/thumbv7a_pc_windows_msvc.rs
index 310fac31c0c..886e3188272 100644
--- a/src/librustc_target/spec/thumbv7a_pc_windows_msvc.rs
+++ b/src/librustc_target/spec/thumbv7a_pc_windows_msvc.rs
@@ -22,7 +22,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:w-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "windows".to_string(),
         target_env: "msvc".to_string(),
diff --git a/src/librustc_target/spec/thumbv7em_none_eabi.rs b/src/librustc_target/spec/thumbv7em_none_eabi.rs
index 97114c342cd..4e2f9b91b0d 100644
--- a/src/librustc_target/spec/thumbv7em_none_eabi.rs
+++ b/src/librustc_target/spec/thumbv7em_none_eabi.rs
@@ -17,7 +17,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/thumbv7em_none_eabihf.rs b/src/librustc_target/spec/thumbv7em_none_eabihf.rs
index e4358bdd799..c510be519c0 100644
--- a/src/librustc_target/spec/thumbv7em_none_eabihf.rs
+++ b/src/librustc_target/spec/thumbv7em_none_eabihf.rs
@@ -6,7 +6,7 @@
 // Additionally, this target uses the "hard" floating convention (ABI) where floating point values
 // are passed to/from subroutines via FPU registers (S0, S1, D0, D1, etc.).
 //
-// To opt into double precision hardware support, use the `-C target-feature=-fp-only-sp` flag.
+// To opt into double precision hardware support, use the `-C target-feature=+fp64` flag.
 
 use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetOptions, TargetResult};
 
@@ -16,7 +16,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: String::new(),
@@ -26,14 +26,14 @@ pub fn target() -> TargetResult {
         options: TargetOptions {
             // `+vfp4` is the lowest common denominator between the Cortex-M4 (vfp4-16) and the
             // Cortex-M7 (vfp5)
-            // `+d16` both the Cortex-M4 and the Cortex-M7 only have 16 double-precision registers
+            // `-d32` both the Cortex-M4 and the Cortex-M7 only have 16 double-precision registers
             // available
-            // `+fp-only-sp` The Cortex-M4 only supports single precision floating point operations
+            // `-fp64` The Cortex-M4 only supports single precision floating point operations
             // whereas in the Cortex-M7 double precision is optional
             //
             // Reference:
             // ARMv7-M Architecture Reference Manual - A2.5 The optional floating-point extension
-            features: "+vfp4,+d16,+fp-only-sp".to_string(),
+            features: "+vfp4,-d32,-fp64".to_string(),
             max_atomic_width: Some(32),
             .. super::thumb_base::opts()
         }
diff --git a/src/librustc_target/spec/thumbv7m_none_eabi.rs b/src/librustc_target/spec/thumbv7m_none_eabi.rs
index daf25b16d58..9c9868ef37c 100644
--- a/src/librustc_target/spec/thumbv7m_none_eabi.rs
+++ b/src/librustc_target/spec/thumbv7m_none_eabi.rs
@@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/thumbv7neon_linux_androideabi.rs b/src/librustc_target/spec/thumbv7neon_linux_androideabi.rs
index e248b930e6e..f3142ef6002 100644
--- a/src/librustc_target/spec/thumbv7neon_linux_androideabi.rs
+++ b/src/librustc_target/spec/thumbv7neon_linux_androideabi.rs
@@ -20,7 +20,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "android".to_string(),
         target_env: "".to_string(),
diff --git a/src/librustc_target/spec/thumbv7neon_unknown_linux_gnueabihf.rs b/src/librustc_target/spec/thumbv7neon_unknown_linux_gnueabihf.rs
index bef62b0a2eb..5524bc9ab66 100644
--- a/src/librustc_target/spec/thumbv7neon_unknown_linux_gnueabihf.rs
+++ b/src/librustc_target/spec/thumbv7neon_unknown_linux_gnueabihf.rs
@@ -13,7 +13,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
diff --git a/src/librustc_target/spec/thumbv8m_base_none_eabi.rs b/src/librustc_target/spec/thumbv8m_base_none_eabi.rs
index be8a476db4d..0b4750093cc 100644
--- a/src/librustc_target/spec/thumbv8m_base_none_eabi.rs
+++ b/src/librustc_target/spec/thumbv8m_base_none_eabi.rs
@@ -8,7 +8,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/thumbv8m_main_none_eabi.rs b/src/librustc_target/spec/thumbv8m_main_none_eabi.rs
index 49ab643d484..acce424136d 100644
--- a/src/librustc_target/spec/thumbv8m_main_none_eabi.rs
+++ b/src/librustc_target/spec/thumbv8m_main_none_eabi.rs
@@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: String::new(),
diff --git a/src/librustc_target/spec/thumbv8m_main_none_eabihf.rs b/src/librustc_target/spec/thumbv8m_main_none_eabihf.rs
index 6a3d8e61d7f..455d56b095b 100644
--- a/src/librustc_target/spec/thumbv8m_main_none_eabihf.rs
+++ b/src/librustc_target/spec/thumbv8m_main_none_eabihf.rs
@@ -9,7 +9,7 @@ pub fn target() -> TargetResult {
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         target_c_int_width: "32".to_string(),
-        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
         arch: "arm".to_string(),
         target_os: "none".to_string(),
         target_env: String::new(),
@@ -22,7 +22,7 @@ pub fn target() -> TargetResult {
             // the FPU uses the FPv5 architecture, single-precision instructions
             // and 16 D registers.
             // These parameters map to the following LLVM features.
-            features: "+fp-armv8,+fp-only-sp,+d16".to_string(),
+            features: "+fp-armv8,-fp64,-d32".to_string(),
             max_atomic_width: Some(32),
             .. super::thumb_base::opts()
         },
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 15c0b6ca5aa..c0ba41b8af4 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -701,7 +701,7 @@ pub trait Resolver {
 
     fn get_module_scope(&mut self, id: ast::NodeId) -> Mark;
 
-    fn resolve_dollar_crates(&mut self, fragment: &AstFragment);
+    fn resolve_dollar_crates(&mut self);
     fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
                                             derives: &[Mark]);
     fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 74ef5cbe917..053686b8b1f 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -429,7 +429,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
     fn collect_invocations(&mut self, mut fragment: AstFragment, derives: &[Mark])
                            -> (AstFragment, Vec<Invocation>) {
         // Resolve `$crate`s in the fragment for pretty-printing.
-        self.cx.resolver.resolve_dollar_crates(&fragment);
+        self.cx.resolver.resolve_dollar_crates();
 
         let invocations = {
             let mut collector = InvocationCollector {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 67646cce69b..7e099bc4d50 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -18,7 +18,7 @@ use crate::tokenstream::{self, TokenStream, TokenTree};
 
 use rustc_target::spec::abi::{self, Abi};
 use syntax_pos::{self, BytePos};
-use syntax_pos::{DUMMY_SP, FileName};
+use syntax_pos::{DUMMY_SP, FileName, Span};
 
 use std::borrow::Cow;
 use std::io::Read;
@@ -181,7 +181,46 @@ pub fn literal_to_string(lit: token::Lit) -> String {
     out
 }
 
+fn ident_to_string(ident: ast::Ident, is_raw: bool) -> String {
+    ident_to_string_ext(ident.name, is_raw, Some(ident.span))
+}
+
+// AST pretty-printer is used as a fallback for turning AST structures into token streams for
+// proc macros. Additionally, proc macros may stringify their input and expect it survive the
+// stringification (especially true for proc macro derives written between Rust 1.15 and 1.30).
+// So we need to somehow pretty-print `$crate` in a way preserving at least some of its
+// hygiene data, most importantly name of the crate it refers to.
+// As a result we print `$crate` as `crate` if it refers to the local crate
+// and as `::other_crate_name` if it refers to some other crate.
+// Note, that this is only done if the ident token is printed from inside of AST pretty-pringing,
+// but not otherwise. Pretty-printing is the only way for proc macros to discover token contents,
+// so we should not perform this lossy conversion if the top level call to the pretty-printer was
+// done for a token stream or a single token.
+fn ident_to_string_ext(
+    name: ast::Name, is_raw: bool, convert_dollar_crate: Option<Span>
+) -> String {
+    if is_raw {
+        format!("r#{}", name)
+    } else {
+        if name == kw::DollarCrate {
+            if let Some(span) = convert_dollar_crate {
+                let converted = span.ctxt().dollar_crate_name();
+                return if converted.is_path_segment_keyword() {
+                    converted.to_string()
+                } else {
+                    format!("::{}", converted)
+                }
+            }
+        }
+        name.to_string()
+    }
+}
+
 pub fn token_kind_to_string(tok: &TokenKind) -> String {
+    token_kind_to_string_ext(tok, None)
+}
+
+fn token_kind_to_string_ext(tok: &TokenKind, convert_dollar_crate: Option<Span>) -> String {
     match *tok {
         token::Eq                   => "=".to_string(),
         token::Lt                   => "<".to_string(),
@@ -227,8 +266,7 @@ pub fn token_kind_to_string(tok: &TokenKind) -> String {
         token::Literal(lit) => literal_to_string(lit),
 
         /* Name components */
-        token::Ident(s, false)      => s.to_string(),
-        token::Ident(s, true)       => format!("r#{}", s),
+        token::Ident(s, is_raw)     => ident_to_string_ext(s, is_raw, convert_dollar_crate),
         token::Lifetime(s)          => s.to_string(),
 
         /* Other */
@@ -243,7 +281,12 @@ pub fn token_kind_to_string(tok: &TokenKind) -> String {
 }
 
 pub fn token_to_string(token: &Token) -> String {
-    token_kind_to_string(&token.kind)
+    token_to_string_ext(token, false)
+}
+
+fn token_to_string_ext(token: &Token, convert_dollar_crate: bool) -> String {
+    let convert_dollar_crate = if convert_dollar_crate { Some(token.span) } else { None };
+    token_kind_to_string_ext(&token.kind, convert_dollar_crate)
 }
 
 crate fn nonterminal_to_string(nt: &Nonterminal) -> String {
@@ -256,9 +299,8 @@ crate fn nonterminal_to_string(nt: &Nonterminal) -> String {
         token::NtBlock(ref e)       => block_to_string(e),
         token::NtStmt(ref e)        => stmt_to_string(e),
         token::NtPat(ref e)         => pat_to_string(e),
-        token::NtIdent(e, false)    => ident_to_string(e),
-        token::NtIdent(e, true)     => format!("r#{}", ident_to_string(e)),
-        token::NtLifetime(e)        => ident_to_string(e),
+        token::NtIdent(e, is_raw)   => ident_to_string(e, is_raw),
+        token::NtLifetime(e)        => e.to_string(),
         token::NtLiteral(ref e)     => expr_to_string(e),
         token::NtTT(ref tree)       => tt_to_string(tree.clone()),
         token::NtImplItem(ref e)    => impl_item_to_string(e),
@@ -293,15 +335,15 @@ pub fn lifetime_to_string(lt: &ast::Lifetime) -> String {
 }
 
 pub fn tt_to_string(tt: tokenstream::TokenTree) -> String {
-    to_string(|s| s.print_tt(tt))
+    to_string(|s| s.print_tt(tt, false))
 }
 
 pub fn tts_to_string(tts: &[tokenstream::TokenTree]) -> String {
-    to_string(|s| s.print_tts(tts.iter().cloned().collect()))
+    tokens_to_string(tts.iter().cloned().collect())
 }
 
 pub fn tokens_to_string(tokens: TokenStream) -> String {
-    to_string(|s| s.print_tts(tokens))
+    to_string(|s| s.print_tts_ext(tokens, false))
 }
 
 pub fn stmt_to_string(stmt: &ast::Stmt) -> String {
@@ -344,10 +386,6 @@ pub fn path_segment_to_string(p: &ast::PathSegment) -> String {
     to_string(|s| s.print_path_segment(p, false))
 }
 
-pub fn ident_to_string(id: ast::Ident) -> String {
-    to_string(|s| s.print_ident(id))
-}
-
 pub fn vis_to_string(v: &ast::Visibility) -> String {
     to_string(|s| s.print_visibility(v))
 }
@@ -629,11 +667,7 @@ pub trait PrintState<'a> {
                 self.writer().word("::");
             }
             if segment.ident.name != kw::PathRoot {
-                if segment.ident.name == kw::DollarCrate {
-                    self.print_dollar_crate(segment.ident);
-                } else {
-                    self.writer().word(segment.ident.as_str().to_string());
-                }
+                self.writer().word(ident_to_string(segment.ident, segment.ident.is_raw_guess()));
             }
         }
     }
@@ -707,10 +741,10 @@ pub trait PrintState<'a> {
     /// appropriate macro, transcribe back into the grammar we just parsed from,
     /// and then pretty-print the resulting AST nodes (so, e.g., we print
     /// expression arguments as expressions). It can be done! I think.
-    fn print_tt(&mut self, tt: tokenstream::TokenTree) {
+    fn print_tt(&mut self, tt: tokenstream::TokenTree, convert_dollar_crate: bool) {
         match tt {
             TokenTree::Token(ref token) => {
-                self.writer().word(token_to_string(&token));
+                self.writer().word(token_to_string_ext(&token, convert_dollar_crate));
                 match token.kind {
                     token::DocComment(..) => {
                         self.writer().hardbreak()
@@ -729,12 +763,16 @@ pub trait PrintState<'a> {
     }
 
     fn print_tts(&mut self, tts: tokenstream::TokenStream) {
+        self.print_tts_ext(tts, true)
+    }
+
+    fn print_tts_ext(&mut self, tts: tokenstream::TokenStream, convert_dollar_crate: bool) {
         self.ibox(0);
         for (i, tt) in tts.into_trees().enumerate() {
             if i != 0 {
                 self.writer().space();
             }
-            self.print_tt(tt);
+            self.print_tt(tt, convert_dollar_crate);
         }
         self.end();
     }
@@ -744,21 +782,6 @@ pub trait PrintState<'a> {
     }
 
     fn nbsp(&mut self) { self.writer().word(" ") }
-
-    // AST pretty-printer is used as a fallback for turning AST structures into token streams for
-    // proc macros. Additionally, proc macros may stringify their input and expect it survive the
-    // stringification (especially true for proc macro derives written between Rust 1.15 and 1.30).
-    // So we need to somehow pretty-print `$crate` in paths in a way preserving at least some of
-    // its hygiene data, most importantly name of the crate it refers to.
-    // As a result we print `$crate` as `crate` if it refers to the local crate
-    // and as `::other_crate_name` if it refers to some other crate.
-    fn print_dollar_crate(&mut self, ident: ast::Ident) {
-        let name = ident.span.ctxt().dollar_crate_name();
-        if !ast::Ident::with_empty_ctxt(name).is_path_segment_keyword() {
-            self.writer().word("::");
-        }
-        self.writer().word(name.as_str().to_string())
-    }
 }
 
 impl<'a> PrintState<'a> for State<'a> {
@@ -2287,11 +2310,7 @@ impl<'a> State<'a> {
     }
 
     crate fn print_ident(&mut self, ident: ast::Ident) {
-        if ident.is_raw_guess() {
-            self.s.word(format!("r#{}", ident));
-        } else {
-            self.s.word(ident.as_str().to_string());
-        }
+        self.s.word(ident_to_string(ident, ident.is_raw_guess()));
         self.ann.post(self, AnnNode::Ident(&ident))
     }
 
@@ -2322,11 +2341,7 @@ impl<'a> State<'a> {
                           segment: &ast::PathSegment,
                           colons_before_params: bool) {
         if segment.ident.name != kw::PathRoot {
-            if segment.ident.name == kw::DollarCrate {
-                self.print_dollar_crate(segment.ident);
-            } else {
-                self.print_ident(segment.ident);
-            }
+            self.print_ident(segment.ident);
             if let Some(ref args) = segment.args {
                 self.print_generic_args(args, colons_before_params);
             }
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index a6c8c76cf23..f52952ca402 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -33,7 +33,7 @@ use crate::symbol::{kw, Symbol};
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
-use std::{fmt, mem};
+use std::fmt;
 
 /// A SyntaxContext represents a chain of macro expansions (represented by marks).
 #[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
@@ -387,6 +387,23 @@ pub fn walk_chain(span: Span, to: SyntaxContext) -> Span {
     HygieneData::with(|data| data.walk_chain(span, to))
 }
 
+pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) {
+    // The new contexts that need updating are at the end of the list and have `$crate` as a name.
+    let (len, to_update) = HygieneData::with(|data| (
+        data.syntax_contexts.len(),
+        data.syntax_contexts.iter().rev()
+            .take_while(|scdata| scdata.dollar_crate_name == kw::DollarCrate).count()
+    ));
+    // The callback must be called from outside of the `HygieneData` lock,
+    // since it will try to acquire it too.
+    let range_to_update = len - to_update .. len;
+    let names: Vec<_> =
+        range_to_update.clone().map(|idx| get_name(SyntaxContext::from_u32(idx as u32))).collect();
+    HygieneData::with(|data| range_to_update.zip(names.into_iter()).for_each(|(idx, name)| {
+        data.syntax_contexts[idx].dollar_crate_name = name;
+    }))
+}
+
 impl SyntaxContext {
     #[inline]
     pub const fn empty() -> Self {
@@ -614,17 +631,6 @@ impl SyntaxContext {
     pub fn dollar_crate_name(self) -> Symbol {
         HygieneData::with(|data| data.syntax_contexts[self.0 as usize].dollar_crate_name)
     }
-
-    pub fn set_dollar_crate_name(self, dollar_crate_name: Symbol) {
-        HygieneData::with(|data| {
-            let prev_dollar_crate_name = mem::replace(
-                &mut data.syntax_contexts[self.0 as usize].dollar_crate_name, dollar_crate_name
-            );
-            assert!(dollar_crate_name == prev_dollar_crate_name ||
-                    prev_dollar_crate_name == kw::DollarCrate,
-                    "$crate name is reset for a syntax context");
-        })
-    }
 }
 
 impl fmt::Debug for SyntaxContext {
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 0ebef82d376..cea88f14dcc 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -913,7 +913,10 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
                               GlobalValue::LinkageTypes NewLinkage) {
     ResolvedODR[ModuleIdentifier][GUID] = NewLinkage;
   };
-#if LLVM_VERSION_GE(8, 0)
+#if LLVM_VERSION_GE(9, 0)
+  thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage,
+                                  Ret->GUIDPreservedSymbols);
+#elif LLVM_VERSION_GE(8, 0)
   thinLTOResolvePrevailingInIndex(Ret->Index, isPrevailing, recordNewLinkage);
 #else
   thinLTOResolveWeakForLinkerInIndex(Ret->Index, isPrevailing, recordNewLinkage);
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 66453c08a66..16d08ee534e 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -237,6 +237,17 @@ extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
       Call->getContext(), Index, B));
 }
 
+extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index,
+                                             LLVMTypeRef Ty) {
+  CallSite Call = CallSite(unwrap<Instruction>(Instr));
+#if LLVM_VERSION_GE(9, 0)
+  Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty));
+#else
+  Attribute Attr = Attribute::get(Call->getContext(), Attribute::ByVal);
+#endif
+  Call.addAttribute(Index, Attr);
+}
+
 extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
                                              LLVMRustAttribute RustAttr) {
   Function *A = unwrap<Function>(Fn);
@@ -271,6 +282,17 @@ extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
   A->addAttributes(Index, B);
 }
 
+extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index,
+                                     LLVMTypeRef Ty) {
+  Function *F = unwrap<Function>(Fn);
+#if LLVM_VERSION_GE(9, 0)
+  Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty));
+#else
+  Attribute Attr = Attribute::get(F->getContext(), Attribute::ByVal);
+#endif
+  F->addAttribute(Index, Attr);
+}
+
 extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
                                                    unsigned Index,
                                                    const char *Name,
diff --git a/src/test/codegen/mainsubprogram.rs b/src/test/codegen/mainsubprogram.rs
index 7f1b0e17f87..790db33437b 100644
--- a/src/test/codegen/mainsubprogram.rs
+++ b/src/test/codegen/mainsubprogram.rs
@@ -7,7 +7,7 @@
 // compile-flags: -g -C no-prepopulate-passes
 
 // CHECK-LABEL: @main
-// CHECK: {{.*}}DISubprogram{{.*}}name: "main",{{.*}}DIFlagMainSubprogram{{.*}}
+// CHECK: {{.*}}DISubprogram{{.*}}name: "main",{{.*}}DI{{(SP)?}}FlagMainSubprogram{{.*}}
 
 pub fn main() {
 }
diff --git a/src/test/codegen/mainsubprogramstart.rs b/src/test/codegen/mainsubprogramstart.rs
index b03290af0e3..d4de9f59ac2 100644
--- a/src/test/codegen/mainsubprogramstart.rs
+++ b/src/test/codegen/mainsubprogramstart.rs
@@ -6,7 +6,7 @@
 #![feature(start)]
 
 // CHECK-LABEL: @main
-// CHECK: {{.*}}DISubprogram{{.*}}name: "start",{{.*}}DIFlagMainSubprogram{{.*}}
+// CHECK: {{.*}}DISubprogram{{.*}}name: "start",{{.*}}DI{{(SP)?}}FlagMainSubprogram{{.*}}
 
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {
diff --git a/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs b/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs
index d5d393b5a64..bdcdb7922ca 100644
--- a/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs
+++ b/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs
@@ -14,3 +14,9 @@ macro_rules! external {
         struct D($crate::S);
     };
 }
+
+#[macro_export]
+macro_rules! issue_62325 { () => {
+    #[print_attr]
+    struct B(identity!($crate::S));
+}}
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
index 0611fcb13f2..84821259d7b 100644
--- a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
+++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
@@ -1,4 +1,4 @@
-PRINT-BANG INPUT (DISPLAY): struct M ( $crate :: S ) ;
+PRINT-BANG INPUT (DISPLAY): struct M ( crate :: S ) ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -39,7 +39,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct A(crate::S);
-PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( $crate :: S ) ;
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( crate :: S ) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-62325.rs b/src/test/ui/proc-macro/dollar-crate-issue-62325.rs
new file mode 100644
index 00000000000..b7b152e6692
--- /dev/null
+++ b/src/test/ui/proc-macro/dollar-crate-issue-62325.rs
@@ -0,0 +1,27 @@
+// check-pass
+// edition:2018
+// aux-build:test-macros.rs
+// aux-build:dollar-crate-external.rs
+
+// Anonymize unstable non-dummy spans while still showing dummy spans `0..0`.
+// normalize-stdout-test "bytes\([^0]\w*\.\.(\w+)\)" -> "bytes(LO..$1)"
+// normalize-stdout-test "bytes\((\w+)\.\.[^0]\w*\)" -> "bytes($1..HI)"
+
+#![feature(proc_macro_hygiene)]
+
+#[macro_use]
+extern crate test_macros;
+extern crate dollar_crate_external;
+
+type S = u8;
+
+macro_rules! m { () => {
+    #[print_attr]
+    struct A(identity!($crate::S));
+}}
+
+m!();
+
+dollar_crate_external::issue_62325!();
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout
new file mode 100644
index 00000000000..17ad1a7af70
--- /dev/null
+++ b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout
@@ -0,0 +1,112 @@
+PRINT-ATTR INPUT (DISPLAY): struct A(identity!(crate :: S));
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( identity ! ( crate :: S ) ) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "struct",
+        span: #2 bytes(LO..HI),
+    },
+    Ident {
+        ident: "A",
+        span: #2 bytes(LO..HI),
+    },
+    Group {
+        delimiter: Parenthesis,
+        stream: TokenStream [
+            Ident {
+                ident: "identity",
+                span: #2 bytes(LO..HI),
+            },
+            Punct {
+                ch: '!',
+                spacing: Alone,
+                span: #2 bytes(LO..HI),
+            },
+            Group {
+                delimiter: Parenthesis,
+                stream: TokenStream [
+                    Ident {
+                        ident: "$crate",
+                        span: #2 bytes(LO..HI),
+                    },
+                    Punct {
+                        ch: ':',
+                        spacing: Joint,
+                        span: #2 bytes(LO..HI),
+                    },
+                    Punct {
+                        ch: ':',
+                        spacing: Alone,
+                        span: #2 bytes(LO..HI),
+                    },
+                    Ident {
+                        ident: "S",
+                        span: #2 bytes(LO..HI),
+                    },
+                ],
+                span: #2 bytes(LO..HI),
+            },
+        ],
+        span: #2 bytes(LO..HI),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: #2 bytes(LO..HI),
+    },
+]
+PRINT-ATTR INPUT (DISPLAY): struct B(identity!(::dollar_crate_external :: S));
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct B ( identity ! ( ::dollar_crate_external :: S ) ) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "struct",
+        span: #7 bytes(LO..HI),
+    },
+    Ident {
+        ident: "B",
+        span: #7 bytes(LO..HI),
+    },
+    Group {
+        delimiter: Parenthesis,
+        stream: TokenStream [
+            Ident {
+                ident: "identity",
+                span: #7 bytes(LO..HI),
+            },
+            Punct {
+                ch: '!',
+                spacing: Alone,
+                span: #7 bytes(LO..HI),
+            },
+            Group {
+                delimiter: Parenthesis,
+                stream: TokenStream [
+                    Ident {
+                        ident: "$crate",
+                        span: #7 bytes(LO..HI),
+                    },
+                    Punct {
+                        ch: ':',
+                        spacing: Joint,
+                        span: #7 bytes(LO..HI),
+                    },
+                    Punct {
+                        ch: ':',
+                        spacing: Alone,
+                        span: #7 bytes(LO..HI),
+                    },
+                    Ident {
+                        ident: "S",
+                        span: #7 bytes(LO..HI),
+                    },
+                ],
+                span: #7 bytes(LO..HI),
+            },
+        ],
+        span: #7 bytes(LO..HI),
+    },
+    Punct {
+        ch: ';',
+        spacing: Alone,
+        span: #7 bytes(LO..HI),
+    },
+]
diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout
index 3c88ee99842..9d9677d49e3 100644
--- a/src/test/ui/proc-macro/dollar-crate.stdout
+++ b/src/test/ui/proc-macro/dollar-crate.stdout
@@ -1,4 +1,4 @@
-PRINT-BANG INPUT (DISPLAY): struct M ( $crate :: S ) ;
+PRINT-BANG INPUT (DISPLAY): struct M ( crate :: S ) ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -39,7 +39,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct A(crate::S);
-PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( $crate :: S ) ;
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( crate :: S ) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -80,7 +80,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-DERIVE INPUT (DISPLAY): struct D(crate::S);
-PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ( $crate :: S ) ;
+PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ( crate :: S ) ;
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -120,7 +120,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
         span: #2 bytes(LO..HI),
     },
 ]
-PRINT-BANG INPUT (DISPLAY): struct M ( $crate :: S ) ;
+PRINT-BANG INPUT (DISPLAY): struct M ( ::dollar_crate_external :: S ) ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -161,7 +161,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct A(::dollar_crate_external::S);
-PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( $crate :: S ) ;
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( ::dollar_crate_external :: S ) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -202,7 +202,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-DERIVE INPUT (DISPLAY): struct D(::dollar_crate_external::S);
-PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ( $crate :: S ) ;
+PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ( ::dollar_crate_external :: S ) ;
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",