about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-07-13 17:11:36 +0000
committerbors <bors@rust-lang.org>2019-07-13 17:11:36 +0000
commit69656fa4cbafc378fd63f9186d93b0df3cdd9320 (patch)
tree690b6c3c570374a457a346b7462c8c7c9061d6c3 /src
parentec30876f30082a7b32876bd78a8da01f11dcde1e (diff)
parent791ceb6a9c5dfeeeb5fc6098db2022a99c2eec18 (diff)
downloadrust-69656fa4cbafc378fd63f9186d93b0df3cdd9320.tar.gz
rust-69656fa4cbafc378fd63f9186d93b0df3cdd9320.zip
Auto merge of #62659 - Centril:rollup-90oz643, r=Centril
Rollup of 5 pull requests

Successful merges:

 - #62577 (Add an AtomicCell abstraction)
 - #62585 (Make struct_tail normalize when possible)
 - #62604 (Handle errors during error recovery gracefully)
 - #62636 (rustbuild: Improve assert about building tools once)
 - #62651 (Make some rustc macros more hygienic)

Failed merges:

r? @ghost
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/tool.rs69
-rw-r--r--src/librustc/lib.rs2
-rw-r--r--src/librustc/ty/layout.rs6
-rw-r--r--src/librustc/ty/util.rs102
-rw-r--r--src/librustc_codegen_ssa/base.rs3
-rw-r--r--src/librustc_codegen_ssa/traits/type_.rs5
-rw-r--r--src/librustc_data_structures/Cargo.toml1
-rw-r--r--src/librustc_data_structures/indexed_vec.rs33
-rw-r--r--src/librustc_data_structures/sync.rs55
-rw-r--r--src/librustc_lint/error_codes.rs2
-rw-r--r--src/librustc_metadata/error_codes.rs2
-rw-r--r--src/librustc_mir/interpret/cast.rs3
-rw-r--r--src/librustc_mir/interpret/intern.rs4
-rw-r--r--src/librustc_mir/interpret/validity.rs3
-rw-r--r--src/librustc_mir/lib.rs2
-rw-r--r--src/librustc_mir/monomorphize/collector.rs7
-rw-r--r--src/librustc_passes/error_codes.rs2
-rw-r--r--src/librustc_plugin/error_codes.rs2
-rw-r--r--src/librustc_resolve/error_codes.rs2
-rw-r--r--src/librustc_target/abi/mod.rs1
-rw-r--r--src/librustc_target/lib.rs5
-rw-r--r--src/librustc_typeck/check/mod.rs2
-rw-r--r--src/librustc_typeck/check/wfcheck.rs3
-rw-r--r--src/libsyntax/diagnostics/macros.rs8
-rw-r--r--src/libsyntax/lib.rs2
-rw-r--r--src/libsyntax/parse/parser.rs11
-rw-r--r--src/libsyntax_ext/error_codes.rs2
-rw-r--r--src/test/run-pass-fulldeps/newtype_index.rs6
-rw-r--r--src/test/ui/layout/issue-60431-unsized-tail-behind-projection.rs35
-rw-r--r--src/test/ui/parser/issue-62546.rs3
-rw-r--r--src/test/ui/parser/issue-62546.stderr17
31 files changed, 312 insertions, 88 deletions
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index bd77f7a91d9..a9269a7ad24 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -109,36 +109,63 @@ impl Step for ToolBuild {
                     continue
                 }
 
-                // Don't worry about libs that turn out to be host dependencies
-                // or build scripts, we only care about target dependencies that
-                // are in `deps`.
-                if let Some(maybe_target) = val.1
-                    .parent()                   // chop off file name
-                    .and_then(|p| p.parent())   // chop off `deps`
-                    .and_then(|p| p.parent())   // chop off `release`
-                    .and_then(|p| p.file_name())
-                    .and_then(|p| p.to_str())
-                {
-                    if maybe_target != &*target {
-                        continue
+                // Don't worry about compiles that turn out to be host
+                // dependencies or build scripts. To skip these we look for
+                // anything that goes in `.../release/deps` but *doesn't* go in
+                // `$target/release/deps`. This ensure that outputs in
+                // `$target/release` are still considered candidates for
+                // deduplication.
+                if let Some(parent) = val.1.parent() {
+                    if parent.ends_with("release/deps") {
+                        let maybe_target = parent
+                            .parent()
+                            .and_then(|p| p.parent())
+                            .and_then(|p| p.file_name())
+                            .and_then(|p| p.to_str())
+                            .unwrap();
+                        if maybe_target != &*target {
+                            continue;
+                        }
                     }
                 }
 
+                // Record that we've built an artifact for `id`, and if one was
+                // already listed then we need to see if we reused the same
+                // artifact or produced a duplicate.
                 let mut artifacts = builder.tool_artifacts.borrow_mut();
                 let prev_artifacts = artifacts
                     .entry(target)
                     .or_default();
-                if let Some(prev) = prev_artifacts.get(&*id) {
-                    if prev.1 != val.1 {
-                        duplicates.push((
-                            id.to_string(),
-                            val,
-                            prev.clone(),
-                        ));
+                let prev = match prev_artifacts.get(&*id) {
+                    Some(prev) => prev,
+                    None => {
+                        prev_artifacts.insert(id.to_string(), val);
+                        continue;
                     }
-                    return
+                };
+                if prev.1 == val.1 {
+                    return; // same path, same artifact
                 }
-                prev_artifacts.insert(id.to_string(), val);
+
+                // If the paths are different and one of them *isn't* inside of
+                // `release/deps`, then it means it's probably in
+                // `$target/release`, or it's some final artifact like
+                // `libcargo.rlib`. In these situations Cargo probably just
+                // copied it up from `$target/release/deps/libcargo-xxxx.rlib`,
+                // so if the features are equal we can just skip it.
+                let prev_no_hash = prev.1.parent().unwrap().ends_with("release/deps");
+                let val_no_hash = val.1.parent().unwrap().ends_with("release/deps");
+                if prev.2 == val.2 || !prev_no_hash || !val_no_hash {
+                    return;
+                }
+
+                // ... and otherwise this looks like we duplicated some sort of
+                // compilation, so record it to generate an error later.
+                duplicates.push((
+                    id.to_string(),
+                    val,
+                    prev.clone(),
+                ));
             }
         });
 
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index dc26140ace5..63e0107a4d8 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -49,7 +49,6 @@
 #![feature(optin_builtin_traits)]
 #![feature(range_is_empty)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(rustc_attrs)]
 #![feature(slice_patterns)]
 #![feature(specialization)]
 #![feature(unboxed_closures)]
@@ -57,7 +56,6 @@
 #![feature(trace_macros)]
 #![feature(trusted_len)]
 #![feature(vec_remove_item)]
-#![feature(step_trait)]
 #![feature(stmt_expr_attributes)]
 #![feature(integer_atomics)]
 #![feature(test)]
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 4af26e19b37..4ed52a1e966 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -543,7 +543,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                     return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr)));
                 }
 
-                let unsized_part = tcx.struct_tail(pointee);
+                let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
                 let metadata = match unsized_part.sty {
                     ty::Foreign(..) => {
                         return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr)));
@@ -1664,7 +1664,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
             ty::Ref(_, pointee, _) |
             ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
                 let non_zero = !ty.is_unsafe_ptr();
-                let tail = tcx.struct_tail(pointee);
+                let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
                 match tail.sty {
                     ty::Param(_) | ty::Projection(_) => {
                         debug_assert!(tail.has_param_types() || tail.has_self_ty());
@@ -2015,7 +2015,7 @@ where
                     }));
                 }
 
-                match tcx.struct_tail(pointee).sty {
+                match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).sty {
                     ty::Slice(_) |
                     ty::Str => tcx.types.usize,
                     ty::Dynamic(_, _) => {
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 56cb89b5144..c3ecc04b12e 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -257,10 +257,46 @@ impl<'tcx> TyCtxt<'tcx> {
         false
     }
 
-    /// Returns the deeply last field of nested structures, or the same type,
-    /// if not a structure at all. Corresponds to the only possible unsized
-    /// field, and its type can be used to determine unsizing strategy.
-    pub fn struct_tail(self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
+    /// Attempts to returns the deeply last field of nested structures, but
+    /// does not apply any normalization in its search. Returns the same type
+    /// if input `ty` is not a structure at all.
+    pub fn struct_tail_without_normalization(self, ty: Ty<'tcx>) -> Ty<'tcx>
+    {
+        let tcx = self;
+        tcx.struct_tail_with_normalize(ty, |ty| ty)
+    }
+
+    /// Returns the deeply last field of nested structures, or the same type if
+    /// not a structure at all. Corresponds to the only possible unsized field,
+    /// and its type can be used to determine unsizing strategy.
+    ///
+    /// Should only be called if `ty` has no inference variables and does not
+    /// need its lifetimes preserved (e.g. as part of codegen); otherwise
+    /// normalization attempt may cause compiler bugs.
+    pub fn struct_tail_erasing_lifetimes(self,
+                                         ty: Ty<'tcx>,
+                                         param_env: ty::ParamEnv<'tcx>)
+                                         -> Ty<'tcx>
+    {
+        let tcx = self;
+        tcx.struct_tail_with_normalize(ty, |ty| tcx.normalize_erasing_regions(param_env, ty))
+    }
+
+    /// Returns the deeply last field of nested structures, or the same type if
+    /// not a structure at all. Corresponds to the only possible unsized field,
+    /// and its type can be used to determine unsizing strategy.
+    ///
+    /// This is parameterized over the normalization strategy (i.e. how to
+    /// handle `<T as Trait>::Assoc` and `impl Trait`); pass the identity
+    /// function to indicate no normalization should take place.
+    ///
+    /// See also `struct_tail_erasing_lifetimes`, which is suitable for use
+    /// during codegen.
+    pub fn struct_tail_with_normalize(self,
+                                      mut ty: Ty<'tcx>,
+                                      normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>)
+                                      -> Ty<'tcx>
+    {
         loop {
             match ty.sty {
                 ty::Adt(def, substs) => {
@@ -281,6 +317,15 @@ impl<'tcx> TyCtxt<'tcx> {
                     }
                 }
 
+                ty::Projection(_) | ty::Opaque(..) => {
+                    let normalized = normalize(ty);
+                    if ty == normalized {
+                        return ty;
+                    } else {
+                        ty = normalized;
+                    }
+                }
+
                 _ => {
                     break;
                 }
@@ -294,10 +339,35 @@ impl<'tcx> TyCtxt<'tcx> {
     /// structure definitions.
     /// For `(Foo<Foo<T>>, Foo<dyn Trait>)`, the result will be `(Foo<T>, Trait)`,
     /// whereas struct_tail produces `T`, and `Trait`, respectively.
-    pub fn struct_lockstep_tails(self,
-                                 source: Ty<'tcx>,
-                                 target: Ty<'tcx>)
-                                 -> (Ty<'tcx>, Ty<'tcx>) {
+    ///
+    /// Should only be called if the types have no inference variables and do
+    /// not need their lifetimes preserved (e.g. as part of codegen); otherwise
+    /// normalization attempt may cause compiler bugs.
+    pub fn struct_lockstep_tails_erasing_lifetimes(self,
+                                                   source: Ty<'tcx>,
+                                                   target: Ty<'tcx>,
+                                                   param_env: ty::ParamEnv<'tcx>)
+                                                   -> (Ty<'tcx>, Ty<'tcx>)
+    {
+        let tcx = self;
+        tcx.struct_lockstep_tails_with_normalize(
+            source, target, |ty| tcx.normalize_erasing_regions(param_env, ty))
+    }
+
+    /// Same as applying struct_tail on `source` and `target`, but only
+    /// keeps going as long as the two types are instances of the same
+    /// structure definitions.
+    /// For `(Foo<Foo<T>>, Foo<dyn Trait>)`, the result will be `(Foo<T>, Trait)`,
+    /// whereas struct_tail produces `T`, and `Trait`, respectively.
+    ///
+    /// See also `struct_lockstep_tails_erasing_lifetimes`, which is suitable for use
+    /// during codegen.
+    pub fn struct_lockstep_tails_with_normalize(self,
+                                                source: Ty<'tcx>,
+                                                target: Ty<'tcx>,
+                                                normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>)
+                                                -> (Ty<'tcx>, Ty<'tcx>)
+    {
         let (mut a, mut b) = (source, target);
         loop {
             match (&a.sty, &b.sty) {
@@ -319,6 +389,22 @@ impl<'tcx> TyCtxt<'tcx> {
                         break;
                     }
                 },
+                (ty::Projection(_), _) | (ty::Opaque(..), _) |
+                (_, ty::Projection(_)) | (_, ty::Opaque(..)) => {
+                    // If either side is a projection, attempt to
+                    // progress via normalization. (Should be safe to
+                    // apply to both sides as normalization is
+                    // idempotent.)
+                    let a_norm = normalize(a);
+                    let b_norm = normalize(b);
+                    if a == a_norm && b == b_norm {
+                        break;
+                    } else {
+                        a = a_norm;
+                        b = b_norm;
+                    }
+                }
+
                 _ => break,
             }
         }
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index ca7e17ec97a..00471095f2f 100644
--- a/src/librustc_codegen_ssa/base.rs
+++ b/src/librustc_codegen_ssa/base.rs
@@ -128,7 +128,8 @@ pub fn unsized_info<'tcx, Cx: CodegenMethods<'tcx>>(
     target: Ty<'tcx>,
     old_info: Option<Cx::Value>,
 ) -> Cx::Value {
-    let (source, target) = cx.tcx().struct_lockstep_tails(source, target);
+    let (source, target) =
+        cx.tcx().struct_lockstep_tails_erasing_lifetimes(source, target, cx.param_env());
     match (&source.sty, &target.sty) {
         (&ty::Array(_, len), &ty::Slice(_)) => {
             cx.const_usize(len.unwrap_usize(cx.tcx()))
diff --git a/src/librustc_codegen_ssa/traits/type_.rs b/src/librustc_codegen_ssa/traits/type_.rs
index aa38d8d5184..13f72e23819 100644
--- a/src/librustc_codegen_ssa/traits/type_.rs
+++ b/src/librustc_codegen_ssa/traits/type_.rs
@@ -77,11 +77,12 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
     }
 
     fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
-        if ty.is_sized(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all()) {
+        let param_env = ty::ParamEnv::reveal_all();
+        if ty.is_sized(self.tcx().at(DUMMY_SP), param_env) {
             return false;
         }
 
-        let tail = self.tcx().struct_tail(ty);
+        let tail = self.tcx().struct_tail_erasing_lifetimes(ty, param_env);
         match tail.sty {
             ty::Foreign(..) => false,
             ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index acddb3448ca..79cbe26e73e 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -18,6 +18,7 @@ lazy_static = "1"
 serialize = { path = "../libserialize" }
 graphviz = { path = "../libgraphviz" }
 cfg-if = "0.1.2"
+crossbeam-utils = { version = "0.6.5", features = ["nightly"] }
 stable_deref_trait = "1.0.0"
 rayon = { version = "0.2.0", package = "rustc-rayon" }
 rayon-core = { version = "0.2.0", package = "rustc-rayon-core" }
diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs
index b3a810a622d..c3c76e81606 100644
--- a/src/librustc_data_structures/indexed_vec.rs
+++ b/src/librustc_data_structures/indexed_vec.rs
@@ -57,12 +57,13 @@ impl Idx for u32 {
 /// `u32::MAX`. You can also customize things like the `Debug` impl,
 /// what traits are derived, and so forth via the macro.
 #[macro_export]
+#[allow_internal_unstable(step_trait, rustc_attrs)]
 macro_rules! newtype_index {
     // ---- public rules ----
 
     // Use default constants
     ($(#[$attrs:meta])* $v:vis struct $name:ident { .. }) => (
-        newtype_index!(
+        $crate::newtype_index!(
             // Leave out derives marker so we can use its absence to ensure it comes first
             @attrs        [$(#[$attrs])*]
             @type         [$name]
@@ -74,7 +75,7 @@ macro_rules! newtype_index {
 
     // Define any constants
     ($(#[$attrs:meta])* $v:vis struct $name:ident { $($tokens:tt)+ }) => (
-        newtype_index!(
+        $crate::newtype_index!(
             // Leave out derives marker so we can use its absence to ensure it comes first
             @attrs        [$(#[$attrs])*]
             @type         [$name]
@@ -258,7 +259,7 @@ macro_rules! newtype_index {
             }
         }
 
-        newtype_index!(
+        $crate::newtype_index!(
             @handle_debug
             @derives      [$($derives,)*]
             @type         [$type]
@@ -294,7 +295,7 @@ macro_rules! newtype_index {
      @derives      [$_derive:ident, $($derives:ident,)*]
      @type         [$type:ident]
      @debug_format [$debug_format:tt]) => (
-        newtype_index!(
+        $crate::newtype_index!(
             @handle_debug
             @derives      [$($derives,)*]
             @type         [$type]
@@ -309,7 +310,7 @@ macro_rules! newtype_index {
      @debug_format [$debug_format:tt]
                    derive [$($derives:ident),*]
                    $($tokens:tt)*) => (
-        newtype_index!(
+        $crate::newtype_index!(
             @attrs        [$(#[$attrs])*]
             @type         [$type]
             @max          [$max]
@@ -329,7 +330,7 @@ macro_rules! newtype_index {
                    derive [$($derives:ident,)+]
                    ENCODABLE = custom
                    $($tokens:tt)*) => (
-        newtype_index!(
+        $crate::newtype_index!(
             @attrs        [$(#[$attrs])*]
             @derives      [$($derives,)+]
             @type         [$type]
@@ -348,7 +349,7 @@ macro_rules! newtype_index {
      @debug_format [$debug_format:tt]
                    derive [$($derives:ident,)+]
                    $($tokens:tt)*) => (
-        newtype_index!(
+        $crate::newtype_index!(
             @derives      [$($derives,)+ RustcEncodable,]
             @attrs        [$(#[$attrs])*]
             @type         [$type]
@@ -356,7 +357,7 @@ macro_rules! newtype_index {
             @vis          [$v]
             @debug_format [$debug_format]
                           $($tokens)*);
-        newtype_index!(@decodable $type);
+        $crate::newtype_index!(@decodable $type);
     );
 
     // The case where no derives are added, but encodable is overridden. Don't
@@ -368,7 +369,7 @@ macro_rules! newtype_index {
      @debug_format [$debug_format:tt]
                    ENCODABLE = custom
                    $($tokens:tt)*) => (
-        newtype_index!(
+        $crate::newtype_index!(
             @derives      []
             @attrs        [$(#[$attrs])*]
             @type         [$type]
@@ -385,7 +386,7 @@ macro_rules! newtype_index {
      @vis          [$v:vis]
      @debug_format [$debug_format:tt]
                    $($tokens:tt)*) => (
-        newtype_index!(
+        $crate::newtype_index!(
             @derives      [RustcEncodable,]
             @attrs        [$(#[$attrs])*]
             @type         [$type]
@@ -393,7 +394,7 @@ macro_rules! newtype_index {
             @vis          [$v]
             @debug_format [$debug_format]
                           $($tokens)*);
-        newtype_index!(@decodable $type);
+        $crate::newtype_index!(@decodable $type);
     );
 
     (@decodable $type:ident) => (
@@ -420,7 +421,7 @@ macro_rules! newtype_index {
      @vis          [$v:vis]
      @debug_format [$debug_format:tt]
                    $name:ident = $constant:expr) => (
-        newtype_index!(
+        $crate::newtype_index!(
             @derives      [$($derives,)*]
             @attrs        [$(#[$attrs])*]
             @type         [$type]
@@ -439,7 +440,7 @@ macro_rules! newtype_index {
      @debug_format [$debug_format:tt]
                    $(#[doc = $doc:expr])*
                    const $name:ident = $constant:expr) => (
-        newtype_index!(
+        $crate::newtype_index!(
             @derives      [$($derives,)*]
             @attrs        [$(#[$attrs])*]
             @type         [$type]
@@ -458,7 +459,7 @@ macro_rules! newtype_index {
      @debug_format [$debug_format:tt]
                    MAX = $max:expr,
                    $($tokens:tt)*) => (
-        newtype_index!(
+        $crate::newtype_index!(
             @derives      [$($derives,)*]
             @attrs        [$(#[$attrs])*]
             @type         [$type]
@@ -477,7 +478,7 @@ macro_rules! newtype_index {
      @debug_format [$_debug_format:tt]
                    DEBUG_FORMAT = $debug_format:tt,
                    $($tokens:tt)*) => (
-        newtype_index!(
+        $crate::newtype_index!(
             @derives      [$($derives,)*]
             @attrs        [$(#[$attrs])*]
             @type         [$type]
@@ -499,7 +500,7 @@ macro_rules! newtype_index {
                    $($tokens:tt)*) => (
         $(#[doc = $doc])*
         pub const $name: $type = $type::from_u32_const($constant);
-        newtype_index!(
+        $crate::newtype_index!(
             @derives      [$($derives,)*]
             @attrs        [$(#[$attrs])*]
             @type         [$type]
diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs
index 73247c1469e..3277b85c281 100644
--- a/src/librustc_data_structures/sync.rs
+++ b/src/librustc_data_structures/sync.rs
@@ -67,6 +67,51 @@ cfg_if! {
         use std::ops::Add;
         use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe};
 
+        /// This is a single threaded variant of AtomicCell provided by crossbeam.
+        /// Unlike `Atomic` this is intended for all `Copy` types,
+        /// but it lacks the explicit ordering arguments.
+        #[derive(Debug)]
+        pub struct AtomicCell<T: Copy>(Cell<T>);
+
+        impl<T: Copy> AtomicCell<T> {
+            #[inline]
+            pub fn new(v: T) -> Self {
+                AtomicCell(Cell::new(v))
+            }
+
+            #[inline]
+            pub fn get_mut(&mut self) -> &mut T {
+                self.0.get_mut()
+            }
+        }
+
+        impl<T: Copy> AtomicCell<T> {
+            #[inline]
+            pub fn into_inner(self) -> T {
+                self.0.into_inner()
+            }
+
+            #[inline]
+            pub fn load(&self) -> T {
+                self.0.get()
+            }
+
+            #[inline]
+            pub fn store(&self, val: T) {
+                self.0.set(val)
+            }
+
+            #[inline]
+            pub fn swap(&self, val: T) -> T {
+                self.0.replace(val)
+            }
+        }
+
+        /// This is a single threaded variant of `AtomicU64`, `AtomicUsize`, etc.
+        /// It differs from `AtomicCell` in that it has explicit ordering arguments
+        /// and is only intended for use with the native atomic types.
+        /// You should use this type through the `AtomicU64`, `AtomicUsize`, etc, type aliases
+        /// as it's not intended to be used separately.
         #[derive(Debug)]
         pub struct Atomic<T: Copy>(Cell<T>);
 
@@ -77,7 +122,8 @@ cfg_if! {
             }
         }
 
-        impl<T: Copy + PartialEq> Atomic<T> {
+        impl<T: Copy> Atomic<T> {
+            #[inline]
             pub fn into_inner(self) -> T {
                 self.0.into_inner()
             }
@@ -92,10 +138,14 @@ cfg_if! {
                 self.0.set(val)
             }
 
+            #[inline]
             pub fn swap(&self, val: T, _: Ordering) -> T {
                 self.0.replace(val)
             }
+        }
 
+        impl<T: Copy + PartialEq> Atomic<T> {
+            #[inline]
             pub fn compare_exchange(&self,
                                     current: T,
                                     new: T,
@@ -113,6 +163,7 @@ cfg_if! {
         }
 
         impl<T: Add<Output=T> + Copy> Atomic<T> {
+            #[inline]
             pub fn fetch_add(&self, val: T, _: Ordering) -> T {
                 let old = self.0.get();
                 self.0.set(old + val);
@@ -271,6 +322,8 @@ cfg_if! {
 
         pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64};
 
+        pub use crossbeam_utils::atomic::AtomicCell;
+
         pub use std::sync::Arc as Lrc;
         pub use std::sync::Weak as Weak;
 
diff --git a/src/librustc_lint/error_codes.rs b/src/librustc_lint/error_codes.rs
index 3165673111c..d7c39b780bf 100644
--- a/src/librustc_lint/error_codes.rs
+++ b/src/librustc_lint/error_codes.rs
@@ -1,4 +1,4 @@
-use syntax::{register_diagnostic, register_diagnostics};
+use syntax::register_diagnostics;
 
 register_diagnostics! {
     E0721, // `await` keyword
diff --git a/src/librustc_metadata/error_codes.rs b/src/librustc_metadata/error_codes.rs
index 9ac582ebc42..7c631736591 100644
--- a/src/librustc_metadata/error_codes.rs
+++ b/src/librustc_metadata/error_codes.rs
@@ -1,6 +1,6 @@
 #![allow(non_snake_case)]
 
-use syntax::{register_diagnostic, register_diagnostics, register_long_diagnostics};
+use syntax::{register_diagnostics, register_long_diagnostics};
 
 register_long_diagnostics! {
 E0454: r##"
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 3ef525979f8..980697360eb 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -270,7 +270,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         dty: Ty<'tcx>,
     ) -> InterpResult<'tcx> {
         // A<Struct> -> A<Trait> conversion
-        let (src_pointee_ty, dest_pointee_ty) = self.tcx.struct_lockstep_tails(sty, dty);
+        let (src_pointee_ty, dest_pointee_ty) =
+            self.tcx.struct_lockstep_tails_erasing_lifetimes(sty, dty, self.param_env);
 
         match (&src_pointee_ty.sty, &dest_pointee_ty.sty) {
             (&ty::Array(_, length), &ty::Slice(_)) => {
diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs
index f0d64e217a2..bcd36ac547c 100644
--- a/src/librustc_mir/interpret/intern.rs
+++ b/src/librustc_mir/interpret/intern.rs
@@ -146,7 +146,9 @@ for
             let value = self.ecx.read_immediate(mplace.into())?;
             // Handle trait object vtables
             if let Ok(meta) = value.to_meta() {
-                if let ty::Dynamic(..) = self.ecx.tcx.struct_tail(referenced_ty).sty {
+                if let ty::Dynamic(..) =
+                    self.ecx.tcx.struct_tail_erasing_lifetimes(referenced_ty, self.param_env).sty
+                {
                     if let Ok(vtable) = meta.unwrap().to_ptr() {
                         // explitly choose `Immutable` here, since vtables are immutable, even
                         // if the reference of the fat pointer is mutable
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index 00107a536ba..b1b8e975138 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -361,7 +361,8 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
                     "uninitialized data in fat pointer metadata", self.path);
                 let layout = self.ecx.layout_of(value.layout.ty.builtin_deref(true).unwrap().ty)?;
                 if layout.is_unsized() {
-                    let tail = self.ecx.tcx.struct_tail(layout.ty);
+                    let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(layout.ty,
+                                                                          self.ecx.param_env);
                     match tail.sty {
                         ty::Dynamic(..) => {
                             let vtable = meta.unwrap();
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 4a80534503a..f5e4661afa6 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -15,12 +15,10 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![feature(decl_macro)]
 #![feature(exhaustive_patterns)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(rustc_attrs)]
 #![feature(never_type)]
 #![feature(specialization)]
 #![feature(try_trait)]
 #![feature(unicode_internals)]
-#![feature(step_trait)]
 #![feature(slice_concat_ext)]
 #![feature(trusted_len)]
 #![feature(try_blocks)]
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index bcc6ad4eac2..6e9390f7750 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -851,12 +851,13 @@ fn find_vtable_types_for_unsizing<'tcx>(
     target_ty: Ty<'tcx>,
 ) -> (Ty<'tcx>, Ty<'tcx>) {
     let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| {
+        let param_env = ty::ParamEnv::reveal_all();
         let type_has_metadata = |ty: Ty<'tcx>| -> bool {
             use syntax_pos::DUMMY_SP;
-            if ty.is_sized(tcx.at(DUMMY_SP), ty::ParamEnv::reveal_all()) {
+            if ty.is_sized(tcx.at(DUMMY_SP), param_env) {
                 return false;
             }
-            let tail = tcx.struct_tail(ty);
+            let tail = tcx.struct_tail_erasing_lifetimes(ty, param_env);
             match tail.sty {
                 ty::Foreign(..) => false,
                 ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
@@ -866,7 +867,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
         if type_has_metadata(inner_source) {
             (inner_source, inner_target)
         } else {
-            tcx.struct_lockstep_tails(inner_source, inner_target)
+            tcx.struct_lockstep_tails_erasing_lifetimes(inner_source, inner_target, param_env)
         }
     };
 
diff --git a/src/librustc_passes/error_codes.rs b/src/librustc_passes/error_codes.rs
index e3c6b16703a..36ebe5cf455 100644
--- a/src/librustc_passes/error_codes.rs
+++ b/src/librustc_passes/error_codes.rs
@@ -1,6 +1,6 @@
 #![allow(non_snake_case)]
 
-use syntax::{register_diagnostic, register_diagnostics, register_long_diagnostics};
+use syntax::{register_diagnostics, register_long_diagnostics};
 
 register_long_diagnostics! {
 /*
diff --git a/src/librustc_plugin/error_codes.rs b/src/librustc_plugin/error_codes.rs
index 68462bd83ef..9e76f52a111 100644
--- a/src/librustc_plugin/error_codes.rs
+++ b/src/librustc_plugin/error_codes.rs
@@ -1,6 +1,6 @@
 #![allow(non_snake_case)]
 
-use syntax::{register_diagnostic, register_diagnostics, register_long_diagnostics};
+use syntax::{register_diagnostics, register_long_diagnostics};
 
 register_long_diagnostics! {
 
diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs
index 7cd26dce144..15194a5d146 100644
--- a/src/librustc_resolve/error_codes.rs
+++ b/src/librustc_resolve/error_codes.rs
@@ -1,6 +1,6 @@
 #![allow(non_snake_case)]
 
-use syntax::{register_diagnostic, register_diagnostics, register_long_diagnostics};
+use syntax::{register_diagnostics, register_long_diagnostics};
 
 // Error messages for EXXXX errors.  Each message should start and end with a
 // new line, and be wrapped to 80 characters.  In vim you can `:set tw=80` and
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
index 55cb1791443..01586e92aeb 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -6,6 +6,7 @@ use crate::spec::Target;
 use std::fmt;
 use std::ops::{Add, Deref, Sub, Mul, AddAssign, Range, RangeInclusive};
 
+use rustc_data_structures::newtype_index;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use syntax_pos::symbol::{sym, Symbol};
 
diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs
index c1ec4e59ef2..dcd1eb5acdc 100644
--- a/src/librustc_target/lib.rs
+++ b/src/librustc_target/lib.rs
@@ -11,9 +11,7 @@
 
 #![feature(box_syntax)]
 #![feature(nll)]
-#![feature(rustc_attrs)]
 #![feature(slice_patterns)]
-#![feature(step_trait)]
 
 #![deny(rust_2018_idioms)]
 #![deny(unused_lifetimes)]
@@ -23,8 +21,5 @@
 #[allow(unused_extern_crates)]
 extern crate serialize as rustc_serialize; // used by deriving
 
-#[macro_use]
-extern crate rustc_data_structures;
-
 pub mod abi;
 pub mod spec;
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index d32ee67f745..77d45cfa63c 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -315,7 +315,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
     /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
     /// for examples of where this comes up,.
     fn rvalue_hint(fcx: &FnCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
-        match fcx.tcx.struct_tail(ty).sty {
+        match fcx.tcx.struct_tail_without_normalization(ty).sty {
             ty::Slice(_) | ty::Str | ty::Dynamic(..) => {
                 ExpectRvalueLikeUnsized(ty)
             }
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index a41f4ec91a4..68e5e7d4fd2 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -366,7 +366,8 @@ fn check_item_type(
 
         let mut forbid_unsized = true;
         if allow_foreign_ty {
-            if let ty::Foreign(_) = fcx.tcx.struct_tail(item_ty).sty {
+            let tail = fcx.tcx.struct_tail_erasing_lifetimes(item_ty, fcx.param_env);
+            if let ty::Foreign(_) = tail.sty {
                 forbid_unsized = false;
             }
         }
diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs
index 6f7493ad597..b754d083376 100644
--- a/src/libsyntax/diagnostics/macros.rs
+++ b/src/libsyntax/diagnostics/macros.rs
@@ -170,19 +170,19 @@ macro_rules! help {
 #[macro_export]
 macro_rules! register_diagnostics {
     ($($code:tt),*) => (
-        $(register_diagnostic! { $code })*
+        $($crate::register_diagnostic! { $code })*
     );
     ($($code:tt),*,) => (
-        $(register_diagnostic! { $code })*
+        $($crate::register_diagnostic! { $code })*
     )
 }
 
 #[macro_export]
 macro_rules! register_long_diagnostics {
     ($($code:tt: $description:tt),*) => (
-        $(register_diagnostic! { $code, $description })*
+        $($crate::register_diagnostic! { $code, $description })*
     );
     ($($code:tt: $description:tt),*,) => (
-        $(register_diagnostic! { $code, $description })*
+        $($crate::register_diagnostic! { $code, $description })*
     )
 }
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index ee7fb97ffd7..591f2fb599b 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -18,9 +18,7 @@
 #![feature(label_break_value)]
 #![feature(mem_take)]
 #![feature(nll)]
-#![feature(rustc_attrs)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(step_trait)]
 #![feature(try_trait)]
 #![feature(unicode_internals)]
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index e0633f73ac4..83030e89af3 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -7410,10 +7410,13 @@ impl<'a> Parser<'a> {
             } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) {
                 let ident = self.parse_ident().unwrap();
                 self.bump();  // `(`
-                let kw_name = if let Ok(Some(_)) = self.parse_self_arg_with_attrs() {
-                    "method"
-                } else {
-                    "function"
+                let kw_name = match self.parse_self_arg_with_attrs() {
+                    Ok(Some(_)) => "method",
+                    Ok(None) => "function",
+                    Err(mut err) => {
+                        err.cancel();
+                        "function"
+                    }
                 };
                 self.consume_block(token::Paren);
                 let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) {
diff --git a/src/libsyntax_ext/error_codes.rs b/src/libsyntax_ext/error_codes.rs
index 9bbd9fdec17..9ec551b4395 100644
--- a/src/libsyntax_ext/error_codes.rs
+++ b/src/libsyntax_ext/error_codes.rs
@@ -1,6 +1,6 @@
 #![allow(non_snake_case)]
 
-use syntax::{register_diagnostic, register_long_diagnostics};
+use syntax::register_long_diagnostics;
 
 // Error messages for EXXXX errors.
 // Each message should start and end with a new line, and be wrapped to 80 characters.
diff --git a/src/test/run-pass-fulldeps/newtype_index.rs b/src/test/run-pass-fulldeps/newtype_index.rs
index 18b845eeecb..1192a44a6ee 100644
--- a/src/test/run-pass-fulldeps/newtype_index.rs
+++ b/src/test/run-pass-fulldeps/newtype_index.rs
@@ -1,9 +1,9 @@
-#![feature(rustc_attrs, rustc_private, step_trait)]
+#![feature(rustc_private)]
 
-#[macro_use] extern crate rustc_data_structures;
+extern crate rustc_data_structures;
 extern crate serialize as rustc_serialize;
 
-use rustc_data_structures::indexed_vec::Idx;
+use rustc_data_structures::{newtype_index, indexed_vec::Idx};
 
 newtype_index!(struct MyIdx { MAX = 0xFFFF_FFFA });
 
diff --git a/src/test/ui/layout/issue-60431-unsized-tail-behind-projection.rs b/src/test/ui/layout/issue-60431-unsized-tail-behind-projection.rs
new file mode 100644
index 00000000000..65845d2c9fe
--- /dev/null
+++ b/src/test/ui/layout/issue-60431-unsized-tail-behind-projection.rs
@@ -0,0 +1,35 @@
+// rust-lang/rust#60431: This is a scenario where to determine the size of
+// `&Ref<Obstack>`, we need to know the concrete type of the last field in
+// `Ref<Obstack>` (i.e. its "struct tail"), and determining that concrete type
+// requires normalizing `Obstack::Dyn`.
+//
+// The old "struct tail" computation did not perform such normalization, and so
+// the compiler would ICE when trying to figure out if `Ref<Obstack>` is a
+// dynamically-sized type (DST).
+
+// run-pass
+
+use std::mem;
+
+pub trait Arena {
+    type Dyn : ?Sized;
+}
+
+pub struct DynRef {
+    _dummy: [()],
+}
+
+pub struct Ref<A: Arena> {
+    _value: u8,
+    _dyn_arena: A::Dyn,
+}
+
+pub struct Obstack;
+
+impl Arena for Obstack {
+    type Dyn = DynRef;
+}
+
+fn main() {
+    assert_eq!(mem::size_of::<&Ref<Obstack>>(), mem::size_of::<&[()]>());
+}
diff --git a/src/test/ui/parser/issue-62546.rs b/src/test/ui/parser/issue-62546.rs
new file mode 100644
index 00000000000..75b95e74073
--- /dev/null
+++ b/src/test/ui/parser/issue-62546.rs
@@ -0,0 +1,3 @@
+pub t(#
+//~^ ERROR missing `fn` or `struct` for function or struct definition
+//~ ERROR this file contains an un-closed delimiter
diff --git a/src/test/ui/parser/issue-62546.stderr b/src/test/ui/parser/issue-62546.stderr
new file mode 100644
index 00000000000..631aac95505
--- /dev/null
+++ b/src/test/ui/parser/issue-62546.stderr
@@ -0,0 +1,17 @@
+error: this file contains an un-closed delimiter
+  --> $DIR/issue-62546.rs:3:53
+   |
+LL | pub t(#
+   |      - un-closed delimiter
+LL |
+LL |
+   |                                                     ^
+
+error: missing `fn` or `struct` for function or struct definition
+  --> $DIR/issue-62546.rs:1:4
+   |
+LL | pub t(#
+   | ---^- help: if you meant to call a macro, try: `t!`
+
+error: aborting due to 2 previous errors
+