diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 8dad5f2ef4632..f0054c36c0c88 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -754,76 +754,20 @@ impl<'a> Builder<'a> {
         let mut cargo = Command::new(&self.initial_cargo);
         let out_dir = self.stage_out(compiler, mode);
 
-        // command specific path, we call clear_if_dirty with this
-        let mut my_out = match cmd {
-            "build" => self.cargo_out(compiler, mode, target),
-
-            // This is the intended out directory for crate documentation.
-            "doc" | "rustdoc" =>  self.crate_doc_out(target),
-
-            _ => self.stage_out(compiler, mode),
-        };
-
-        // This is for the original compiler, but if we're forced to use stage 1, then
-        // std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since
-        // we copy the libs forward.
-        let cmp = self.compiler_for(compiler.stage, compiler.host, target);
-
-        let libstd_stamp = match cmd {
-            "check" | "clippy" | "fix" => check::libstd_stamp(self, cmp, target),
-            _ => compile::libstd_stamp(self, cmp, target),
-        };
-
-        let libtest_stamp = match cmd {
-            "check" | "clippy" | "fix" => check::libtest_stamp(self, cmp, target),
-            _ => compile::libtest_stamp(self, cmp, target),
-        };
-
-        let librustc_stamp = match cmd {
-            "check" | "clippy" | "fix" => check::librustc_stamp(self, cmp, target),
-            _ => compile::librustc_stamp(self, cmp, target),
-        };
+        // Codegen backends are not yet tracked by -Zbinary-dep-depinfo,
+        // so we need to explicitly clear out if they've been updated.
+        for backend in self.codegen_backends(compiler) {
+            self.clear_if_dirty(&out_dir, &backend);
+        }
 
         if cmd == "doc" || cmd == "rustdoc" {
-            if mode == Mode::Rustc || mode == Mode::ToolRustc || mode == Mode::Codegen {
+            let my_out = match mode {
                 // This is the intended out directory for compiler documentation.
-                my_out = self.compiler_doc_out(target);
-            }
+                Mode::Rustc | Mode::ToolRustc | Mode::Codegen => self.compiler_doc_out(target),
+                _ => self.crate_doc_out(target),
+            };
             let rustdoc = self.rustdoc(compiler);
             self.clear_if_dirty(&my_out, &rustdoc);
-        } else if cmd != "test" {
-            match mode {
-                Mode::Std => {
-                    self.clear_if_dirty(&my_out, &self.rustc(compiler));
-                    for backend in self.codegen_backends(compiler) {
-                        self.clear_if_dirty(&my_out, &backend);
-                    }
-                },
-                Mode::Test => {
-                    self.clear_if_dirty(&my_out, &libstd_stamp);
-                },
-                Mode::Rustc => {
-                    self.clear_if_dirty(&my_out, &self.rustc(compiler));
-                    self.clear_if_dirty(&my_out, &libstd_stamp);
-                    self.clear_if_dirty(&my_out, &libtest_stamp);
-                },
-                Mode::Codegen => {
-                    self.clear_if_dirty(&my_out, &librustc_stamp);
-                },
-                Mode::ToolBootstrap => { },
-                Mode::ToolStd => {
-                    self.clear_if_dirty(&my_out, &libstd_stamp);
-                },
-                Mode::ToolTest => {
-                    self.clear_if_dirty(&my_out, &libstd_stamp);
-                    self.clear_if_dirty(&my_out, &libtest_stamp);
-                },
-                Mode::ToolRustc => {
-                    self.clear_if_dirty(&my_out, &libstd_stamp);
-                    self.clear_if_dirty(&my_out, &libtest_stamp);
-                    self.clear_if_dirty(&my_out, &librustc_stamp);
-                },
-            }
         }
 
         cargo
@@ -861,6 +805,19 @@ impl<'a> Builder<'a> {
             },
         }
 
+        // This tells Cargo (and in turn, rustc) to output more complete
+        // dependency information.  Most importantly for rustbuild, this
+        // includes sysroot artifacts, like libstd, which means that we don't
+        // need to track those in rustbuild (an error prone process!). This
+        // feature is currently unstable as there may be some bugs and such, but
+        // it represents a big improvement in rustbuild's reliability on
+        // rebuilds, so we're using it here.
+        //
+        // For some additional context, see #63470 (the PR originally adding
+        // this), as well as #63012 which is the tracking issue for this
+        // feature on the rustc side.
+        cargo.arg("-Zbinary-dep-depinfo");
+
         cargo.arg("-j").arg(self.jobs().to_string());
         // Remove make-related flags to ensure Cargo can correctly set things up
         cargo.env_remove("MAKEFLAGS");
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index 11b082ac3f6d8..6e6fea6b831a7 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -245,7 +245,6 @@ impl Step for Rustdoc {
         let libdir = builder.sysroot_libdir(compiler, target);
         let hostdir = builder.sysroot_libdir(compiler, compiler.host);
         add_to_sysroot(&builder, &libdir, &hostdir, &rustdoc_stamp(builder, compiler, target));
-        builder.cargo(compiler, Mode::ToolRustc, target, "clean");
     }
 }
 
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 4b4b072cc1c96..12eb2c882ad1a 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -15,7 +15,7 @@ use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio, exit};
 use std::str;
 
-use build_helper::{output, mtime, t, up_to_date};
+use build_helper::{output, t, up_to_date};
 use filetime::FileTime;
 use serde::Deserialize;
 use serde_json;
@@ -274,8 +274,6 @@ impl Step for StdLink {
             // for reason why the sanitizers are not built in stage0.
             copy_apple_sanitizer_dylibs(builder, &builder.native_dir(target), "osx", &libdir);
         }
-
-        builder.cargo(target_compiler, Mode::ToolStd, target, "clean");
     }
 }
 
@@ -480,8 +478,6 @@ impl Step for TestLink {
             &builder.sysroot_libdir(target_compiler, compiler.host),
             &libtest_stamp(builder, compiler, target)
         );
-
-        builder.cargo(target_compiler, Mode::ToolTest, target, "clean");
     }
 }
 
@@ -639,7 +635,6 @@ impl Step for RustcLink {
             &builder.sysroot_libdir(target_compiler, compiler.host),
             &librustc_stamp(builder, compiler, target)
         );
-        builder.cargo(target_compiler, Mode::ToolRustc, target, "clean");
     }
 }
 
@@ -1202,41 +1197,13 @@ pub fn run_cargo(builder: &Builder<'_>,
         deps.push((path_to_add.into(), false));
     }
 
-    // Now we want to update the contents of the stamp file, if necessary. First
-    // we read off the previous contents along with its mtime. If our new
-    // contents (the list of files to copy) is different or if any dep's mtime
-    // is newer then we rewrite the stamp file.
     deps.sort();
-    let stamp_contents = fs::read(stamp);
-    let stamp_mtime = mtime(&stamp);
     let mut new_contents = Vec::new();
-    let mut max = None;
-    let mut max_path = None;
     for (dep, proc_macro) in deps.iter() {
-        let mtime = mtime(dep);
-        if Some(mtime) > max {
-            max = Some(mtime);
-            max_path = Some(dep.clone());
-        }
         new_contents.extend(if *proc_macro { b"h" } else { b"t" });
         new_contents.extend(dep.to_str().unwrap().as_bytes());
         new_contents.extend(b"\0");
     }
-    let max = max.unwrap();
-    let max_path = max_path.unwrap();
-    let contents_equal = stamp_contents
-        .map(|contents| contents == new_contents)
-        .unwrap_or_default();
-    if contents_equal && max <= stamp_mtime {
-        builder.verbose(&format!("not updating {:?}; contents equal and {:?} <= {:?}",
-                stamp, max, stamp_mtime));
-        return deps.into_iter().map(|(d, _)| d).collect()
-    }
-    if max > stamp_mtime {
-        builder.verbose(&format!("updating {:?} as {:?} changed", stamp, max_path));
-    } else {
-        builder.verbose(&format!("updating {:?} as deps changed", stamp));
-    }
     t!(fs::write(&stamp, &new_contents));
     deps.into_iter().map(|(d, _)| d).collect()
 }
diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs
index ec22a7ccfe4c3..14d947ccf2402 100644
--- a/src/libcore/clone.rs
+++ b/src/libcore/clone.rs
@@ -135,7 +135,6 @@ pub trait Clone : Sized {
 
 /// Derive macro generating an impl of the trait `Clone`.
 #[rustc_builtin_macro]
-#[rustc_macro_transparency = "semitransparent"]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow_internal_unstable(core_intrinsics, derive_clone_copy)]
 pub macro Clone($item:item) { /* compiler built-in */ }
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index b802216036b93..6a50bad06f52a 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -202,7 +202,6 @@ pub trait PartialEq<Rhs: ?Sized = Self> {
 
 /// Derive macro generating an impl of the trait `PartialEq`.
 #[rustc_builtin_macro]
-#[rustc_macro_transparency = "semitransparent"]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow_internal_unstable(core_intrinsics)]
 pub macro PartialEq($item:item) { /* compiler built-in */ }
@@ -265,7 +264,6 @@ pub trait Eq: PartialEq<Self> {
 
 /// Derive macro generating an impl of the trait `Eq`.
 #[rustc_builtin_macro]
-#[rustc_macro_transparency = "semitransparent"]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow_internal_unstable(core_intrinsics, derive_eq)]
 pub macro Eq($item:item) { /* compiler built-in */ }
@@ -616,7 +614,6 @@ pub trait Ord: Eq + PartialOrd<Self> {
 
 /// Derive macro generating an impl of the trait `Ord`.
 #[rustc_builtin_macro]
-#[rustc_macro_transparency = "semitransparent"]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow_internal_unstable(core_intrinsics)]
 pub macro Ord($item:item) { /* compiler built-in */ }
@@ -865,7 +862,6 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
 
 /// Derive macro generating an impl of the trait `PartialOrd`.
 #[rustc_builtin_macro]
-#[rustc_macro_transparency = "semitransparent"]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow_internal_unstable(core_intrinsics)]
 pub macro PartialOrd($item:item) { /* compiler built-in */ }
diff --git a/src/libcore/default.rs b/src/libcore/default.rs
index 9b1616ccce448..1aadc77cfb8da 100644
--- a/src/libcore/default.rs
+++ b/src/libcore/default.rs
@@ -117,7 +117,6 @@ pub trait Default: Sized {
 
 /// Derive macro generating an impl of the trait `Default`.
 #[rustc_builtin_macro]
-#[rustc_macro_transparency = "semitransparent"]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow_internal_unstable(core_intrinsics)]
 pub macro Default($item:item) { /* compiler built-in */ }
diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs
index cb4e32622ff1f..15ce2277fa00d 100644
--- a/src/libcore/fmt/builders.rs
+++ b/src/libcore/fmt/builders.rs
@@ -98,7 +98,7 @@ pub struct DebugStruct<'a, 'b: 'a> {
     has_fields: bool,
 }
 
-pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>,
+pub(super) fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>,
                                 name: &str)
                                 -> DebugStruct<'a, 'b> {
     let result = fmt.write_str(name);
@@ -251,7 +251,10 @@ pub struct DebugTuple<'a, 'b: 'a> {
     empty_name: bool,
 }
 
-pub fn debug_tuple_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugTuple<'a, 'b> {
+pub(super) fn debug_tuple_new<'a, 'b>(
+    fmt: &'a mut fmt::Formatter<'b>,
+    name: &str,
+) -> DebugTuple<'a, 'b> {
     let result = fmt.write_str(name);
     DebugTuple {
         fmt,
@@ -418,7 +421,7 @@ pub struct DebugSet<'a, 'b: 'a> {
     inner: DebugInner<'a, 'b>,
 }
 
-pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> {
+pub(super) fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> {
     let result = fmt.write_str("{");
     DebugSet {
         inner: DebugInner {
@@ -555,7 +558,7 @@ pub struct DebugList<'a, 'b: 'a> {
     inner: DebugInner<'a, 'b>,
 }
 
-pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> {
+pub(super) fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> {
     let result = fmt.write_str("[");
     DebugList {
         inner: DebugInner {
@@ -697,7 +700,7 @@ pub struct DebugMap<'a, 'b: 'a> {
     state: PadAdapterState,
 }
 
-pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> {
+pub(super) fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> {
     let result = fmt.write_str("{");
     DebugMap {
         fmt,
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index d5fae9e740136..2d482481cdb7f 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -549,7 +549,6 @@ pub trait Debug {
 pub(crate) mod macros {
     /// Derive macro generating an impl of the trait `Debug`.
     #[rustc_builtin_macro]
-    #[rustc_macro_transparency = "semitransparent"]
     #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
     #[allow_internal_unstable(core_intrinsics)]
     pub macro Debug($item:item) { /* compiler built-in */ }
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index b397119112390..020e085abf8a8 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -202,7 +202,6 @@ pub trait Hash {
 pub(crate) mod macros {
     /// Derive macro generating an impl of the trait `Hash`.
     #[rustc_builtin_macro]
-    #[rustc_macro_transparency = "semitransparent"]
     #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
     #[allow_internal_unstable(core_intrinsics)]
     pub macro Hash($item:item) { /* compiler built-in */ }
diff --git a/src/libcore/iter/adapters/flatten.rs b/src/libcore/iter/adapters/flatten.rs
index e3c85656116c0..a45173f614ded 100644
--- a/src/libcore/iter/adapters/flatten.rs
+++ b/src/libcore/iter/adapters/flatten.rs
@@ -72,8 +72,7 @@ impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
 impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F>
 where
     F: FnMut(I::Item) -> U,
-    U: IntoIterator,
-    U::IntoIter: DoubleEndedIterator,
+    U: IntoIterator<IntoIter: DoubleEndedIterator>,
 {
     #[inline]
     fn next_back(&mut self) -> Option<U::Item> { self.inner.next_back() }
@@ -107,10 +106,7 @@ impl<I, U, F> FusedIterator for FlatMap<I, U, F>
 /// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "iterator_flatten", since = "1.29.0")]
-pub struct Flatten<I: Iterator>
-where
-    I::Item: IntoIterator,
-{
+pub struct Flatten<I: Iterator<Item: IntoIterator>> {
     inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>,
 }
 
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index bbed95167161d..a645fd2cd5709 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -1270,14 +1270,12 @@ pub(crate) mod builtin {
 
     /// Unstable implementation detail of the `rustc` compiler, do not use.
     #[rustc_builtin_macro]
-    #[rustc_macro_transparency = "semitransparent"]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[allow_internal_unstable(core_intrinsics, libstd_sys_internals)]
     pub macro RustcDecodable($item:item) { /* compiler built-in */ }
 
     /// Unstable implementation detail of the `rustc` compiler, do not use.
     #[rustc_builtin_macro]
-    #[rustc_macro_transparency = "semitransparent"]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[allow_internal_unstable(core_intrinsics)]
     pub macro RustcEncodable($item:item) { /* compiler built-in */ }
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index 3befd421b0125..3c9874dd9a337 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -290,7 +290,6 @@ pub trait Copy : Clone {
 
 /// Derive macro generating an impl of the trait `Copy`.
 #[rustc_builtin_macro]
-#[rustc_macro_transparency = "semitransparent"]
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow_internal_unstable(core_intrinsics, derive_clone_copy)]
 pub macro Copy($item:item) { /* compiler built-in */ }
diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs
index e3a5400942d1a..a732cd48cc2fe 100644
--- a/src/librustc/hir/lowering/expr.rs
+++ b/src/librustc/hir/lowering/expr.rs
@@ -984,7 +984,6 @@ impl LoweringContext<'_> {
             volatile: asm.volatile,
             alignstack: asm.alignstack,
             dialect: asm.dialect,
-            ctxt: asm.ctxt,
         };
 
         let outputs = asm.outputs
diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs
index 51a0c4184f9ef..4f9a9ed5673c7 100644
--- a/src/librustc/hir/lowering/item.rs
+++ b/src/librustc/hir/lowering/item.rs
@@ -750,10 +750,7 @@ impl LoweringContext<'_> {
     }
 
     fn lower_global_asm(&mut self, ga: &GlobalAsm) -> P<hir::GlobalAsm> {
-        P(hir::GlobalAsm {
-            asm: ga.asm,
-            ctxt: ga.ctxt,
-        })
+        P(hir::GlobalAsm { asm: ga.asm })
     }
 
     fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 7c2f9907217cb..46a0f2c7f26f0 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -23,7 +23,6 @@ use rustc_target::spec::abi::Abi;
 use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect};
 use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy};
 use syntax::attr::{InlineAttr, OptimizeAttr};
-use syntax::ext::hygiene::SyntaxContext;
 use syntax::symbol::{Symbol, kw};
 use syntax::tokenstream::TokenStream;
 use syntax::util::parser::ExprPrecedence;
@@ -2004,8 +2003,6 @@ pub struct InlineAsm {
     pub volatile: bool,
     pub alignstack: bool,
     pub dialect: AsmDialect,
-    #[stable_hasher(ignore)] // This is used for error reporting
-    pub ctxt: SyntaxContext,
 }
 
 /// Represents an argument in a function header.
@@ -2184,8 +2181,6 @@ pub struct ForeignMod {
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct GlobalAsm {
     pub asm: Symbol,
-    #[stable_hasher(ignore)] // This is used for error reporting
-    pub ctxt: SyntaxContext,
 }
 
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs
index 9763d523a2ac4..b68ee2cb44d4b 100644
--- a/src/librustc_codegen_llvm/asm.rs
+++ b/src/librustc_codegen_llvm/asm.rs
@@ -6,9 +6,9 @@ use crate::value::Value;
 
 use rustc::hir;
 use rustc_codegen_ssa::traits::*;
-
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::mir::operand::OperandValue;
+use syntax_pos::Span;
 
 use std::ffi::{CStr, CString};
 use libc::{c_uint, c_char};
@@ -19,7 +19,8 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
         &mut self,
         ia: &hir::InlineAsm,
         outputs: Vec<PlaceRef<'tcx, &'ll Value>>,
-        mut inputs: Vec<&'ll Value>
+        mut inputs: Vec<&'ll Value>,
+        span: Span,
     ) -> bool {
         let mut ext_constraints = vec![];
         let mut output_types = vec![];
@@ -102,7 +103,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
             let kind = llvm::LLVMGetMDKindIDInContext(self.llcx,
                 key.as_ptr() as *const c_char, key.len() as c_uint);
 
-            let val: &'ll Value = self.const_i32(ia.ctxt.outer_expn().as_u32() as i32);
+            let val: &'ll Value = self.const_i32(span.ctxt().outer_expn().as_u32() as i32);
 
             llvm::LLVMSetMetadata(r, kind,
                 llvm::LLVMMDNodeInContext(self.llcx, &val, 1));
diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs
index 3717be4b41753..3617f3afaae41 100644
--- a/src/librustc_codegen_ssa/mir/statement.rs
+++ b/src/librustc_codegen_ssa/mir/statement.rs
@@ -89,7 +89,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 });
 
                 if input_vals.len() == asm.inputs.len() {
-                    let res = bx.codegen_inline_asm(&asm.asm, outputs, input_vals);
+                    let res = bx.codegen_inline_asm(
+                        &asm.asm,
+                        outputs,
+                        input_vals,
+                        statement.source_info.span,
+                    );
                     if !res {
                         span_err!(bx.sess(), statement.source_info.span, E0668,
                                   "malformed inline assembly");
diff --git a/src/librustc_codegen_ssa/traits/asm.rs b/src/librustc_codegen_ssa/traits/asm.rs
index fd3c868bbc507..c9e1ed86e97e0 100644
--- a/src/librustc_codegen_ssa/traits/asm.rs
+++ b/src/librustc_codegen_ssa/traits/asm.rs
@@ -1,6 +1,7 @@
 use super::BackendTypes;
 use crate::mir::place::PlaceRef;
 use rustc::hir::{GlobalAsm, InlineAsm};
+use syntax_pos::Span;
 
 pub trait AsmBuilderMethods<'tcx>: BackendTypes {
     /// Take an inline assembly expression and splat it out via LLVM
@@ -9,6 +10,7 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes {
         ia: &InlineAsm,
         outputs: Vec<PlaceRef<'tcx, Self::Value>>,
         inputs: Vec<Self::Value>,
+        span: Span,
     ) -> bool;
 }
 
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 935187dd0667b..cfef4a39cd749 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -348,6 +348,14 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
     }
 }
 
+impl SpecializedDecoder<Ident> for DecodeContext<'_, '_> {
+    fn specialized_decode(&mut self) -> Result<Ident, Self::Error> {
+        // FIXME(jseyfried): intercrate hygiene
+
+        Ok(Ident::with_empty_ctxt(Symbol::decode(self)?))
+    }
+}
+
 impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
         Fingerprint::decode_opaque(&mut self.opaque)
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index fb675d7d841e1..e2de0552cd651 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -31,7 +31,7 @@ use std::u32;
 use syntax::ast;
 use syntax::attr;
 use syntax::source_map::Spanned;
-use syntax::symbol::{kw, sym};
+use syntax::symbol::{kw, sym, Ident};
 use syntax_pos::{self, FileName, SourceFile, Span};
 use log::{debug, trace};
 
@@ -173,6 +173,13 @@ impl<'tcx> SpecializedEncoder<Span> for EncodeContext<'tcx> {
     }
 }
 
+impl SpecializedEncoder<Ident> for EncodeContext<'tcx> {
+    fn specialized_encode(&mut self, ident: &Ident) -> Result<(), Self::Error> {
+        // FIXME(jseyfried): intercrate hygiene
+        ident.name.encode(self)
+    }
+}
+
 impl<'tcx> SpecializedEncoder<LocalDefId> for EncodeContext<'tcx> {
     #[inline]
     fn specialized_encode(&mut self, def_id: &LocalDefId) -> Result<(), Self::Error> {
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 1de67edb95c08..f7da0120506f9 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -166,12 +166,14 @@ impl<'a> Resolver<'a> {
                 err
             }
             ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => {
-                let mut err = struct_span_err!(self.session,
-                                                span,
-                                                E0403,
-                                                "the name `{}` is already used for a generic \
-                                                parameter in this list of generic parameters",
-                                                name);
+                let mut err = struct_span_err!(
+                    self.session,
+                    span,
+                    E0403,
+                    "the name `{}` is already used for a generic \
+                     parameter in this item's generic parameters",
+                    name,
+                );
                 err.span_label(span, "already used");
                 err.span_label(first_use_span, format!("first use of `{}`", name));
                 err
diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs
index e01f53786edab..1faaf97e981c1 100644
--- a/src/librustc_resolve/error_codes.rs
+++ b/src/librustc_resolve/error_codes.rs
@@ -526,15 +526,25 @@ Some type parameters have the same name.
 Erroneous code example:
 
 ```compile_fail,E0403
-fn foo<T, T>(s: T, u: T) {} // error: the name `T` is already used for a type
-                            //        parameter in this type parameter list
+fn f<T, T>(s: T, u: T) {} // error: the name `T` is already used for a generic
+                          //        parameter in this item's generic parameters
 ```
 
 Please verify that none of the type parameters are misspelled, and rename any
 clashing parameters. Example:
 
 ```
-fn foo<T, Y>(s: T, u: Y) {} // ok!
+fn f<T, Y>(s: T, u: Y) {} // ok!
+```
+
+Type parameters in an associated item also cannot shadow parameters from the
+containing item:
+
+```compile_fail,E0403
+trait Foo<T> {
+    fn do_something(&self) -> T;
+    fn do_something_else<T: Clone>(&self, bar: T);
+}
 ```
 "##,
 
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 358eaae11e712..5b16ed1d114e0 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -104,6 +104,24 @@ crate enum RibKind<'a> {
     TyParamAsConstParamTy,
 }
 
+impl RibKind<'_> {
+    // Whether this rib kind contains generic parameters, as opposed to local
+    // variables.
+    crate fn contains_params(&self) -> bool {
+        match self {
+            NormalRibKind
+            | FnItemRibKind
+            | ConstantItemRibKind
+            | ModuleRibKind(_)
+            | MacroDefinition(_) => false,
+            AssocItemRibKind
+            | ItemRibKind
+            | ForwardTyParamBanRibKind
+            | TyParamAsConstParamTy => true,
+        }
+    }
+}
+
 /// A single local scope.
 ///
 /// A rib represents a scope names can live in. Note that these appear in many places, not just
@@ -792,6 +810,19 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> {
                 let mut function_type_rib = Rib::new(rib_kind);
                 let mut function_value_rib = Rib::new(rib_kind);
                 let mut seen_bindings = FxHashMap::default();
+                // We also can't shadow bindings from the parent item
+                if let AssocItemRibKind = rib_kind {
+                    let mut add_bindings_for_ns = |ns| {
+                        let parent_rib = self.ribs[ns].iter()
+                            .rfind(|rib| if let ItemRibKind = rib.kind { true } else { false })
+                            .expect("associated item outside of an item");
+                        seen_bindings.extend(
+                            parent_rib.bindings.iter().map(|(ident, _)| (*ident, ident.span)),
+                        );
+                    };
+                    add_bindings_for_ns(ValueNS);
+                    add_bindings_for_ns(TypeNS);
+                }
                 for param in &generics.params {
                     match param.kind {
                         GenericParamKind::Lifetime { .. } => {}
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 8a4a60c16b0fe..ec3d98f8fdf23 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1448,7 +1448,7 @@ impl<'a> Resolver<'a> {
             debug!("walk rib\n{:?}", ribs[i].bindings);
             // Use the rib kind to determine whether we are resolving parameters
             // (modern hygiene) or local variables (legacy hygiene).
-            let rib_ident = if let AssocItemRibKind | ItemRibKind = ribs[i].kind {
+            let rib_ident = if ribs[i].kind.contains_params() {
                 modern_ident
             } else {
                 ident
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 9680f61d69903..d139cd4264c86 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -24,6 +24,7 @@ use syntax::source_map::Span;
 use syntax::util::lev_distance::find_best_match_for_name;
 use rustc::hir;
 use rustc::hir::{ExprKind, QPath};
+use rustc::hir::def_id::DefId;
 use rustc::hir::def::{CtorKind, Res, DefKind};
 use rustc::hir::ptr::P;
 use rustc::infer;
@@ -1336,116 +1337,182 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         autoderef.unambiguous_final_ty(self);
 
         if let Some((did, field_ty)) = private_candidate {
-            let struct_path = self.tcx().def_path_str(did);
-            let mut err = struct_span_err!(self.tcx().sess, expr.span, E0616,
-                                           "field `{}` of struct `{}` is private",
-                                           field, struct_path);
-            // Also check if an accessible method exists, which is often what is meant.
-            if self.method_exists(field, expr_t, expr.hir_id, false)
-                && !self.expr_in_place(expr.hir_id)
-            {
-                self.suggest_method_call(
-                    &mut err,
-                    &format!("a method `{}` also exists, call it with parentheses", field),
-                    field,
-                    expr_t,
-                    expr.hir_id,
-                );
-            }
-            err.emit();
-            field_ty
-        } else if field.name == kw::Invalid {
-            self.tcx().types.err
+            self.ban_private_field_access(expr, expr_t, field, did);
+            return field_ty;
+        }
+
+        if field.name == kw::Invalid {
         } else if self.method_exists(field, expr_t, expr.hir_id, true) {
-            let mut err = type_error_struct!(self.tcx().sess, field.span, expr_t, E0615,
-                               "attempted to take value of method `{}` on type `{}`",
-                               field, expr_t);
-
-            if !self.expr_in_place(expr.hir_id) {
-                self.suggest_method_call(
-                    &mut err,
-                    "use parentheses to call the method",
-                    field,
-                    expr_t,
-                    expr.hir_id
-                );
-            } else {
-                err.help("methods are immutable and cannot be assigned to");
+            self.ban_take_value_of_method(expr, expr_t, field);
+        } else if !expr_t.is_primitive_ty() {
+            let mut err = self.no_such_field_err(field.span, field, expr_t);
+
+            match expr_t.sty {
+                ty::Adt(def, _) if !def.is_enum() => {
+                    self.suggest_fields_on_recordish(&mut err, def, field);
+                }
+                ty::Array(_, len) => {
+                    self.maybe_suggest_array_indexing(&mut err, expr, base, field, len);
+                }
+                ty::RawPtr(..) => {
+                    self.suggest_first_deref_field(&mut err, expr, base, field);
+                }
+                _ => {}
+            }
+
+            if field.name == kw::Await {
+                // We know by construction that `<expr>.await` is either on Rust 2015
+                // or results in `ExprKind::Await`. Suggest switching the edition to 2018.
+                err.note("to `.await` a `Future`, switch to Rust 2018");
+                err.help("set `edition = \"2018\"` in `Cargo.toml`");
+                err.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
             }
 
             err.emit();
-            self.tcx().types.err
         } else {
-            if !expr_t.is_primitive_ty() {
-                let mut err = self.no_such_field_err(field.span, field, expr_t);
-
-                match expr_t.sty {
-                    ty::Adt(def, _) if !def.is_enum() => {
-                        if let Some(suggested_field_name) =
-                            Self::suggest_field_name(def.non_enum_variant(),
-                                                     &field.as_str(), vec![]) {
-                                err.span_suggestion(
-                                    field.span,
-                                    "a field with a similar name exists",
-                                    suggested_field_name.to_string(),
-                                    Applicability::MaybeIncorrect,
-                                );
-                            } else {
-                                err.span_label(field.span, "unknown field");
-                                let struct_variant_def = def.non_enum_variant();
-                                let field_names = self.available_field_names(struct_variant_def);
-                                if !field_names.is_empty() {
-                                    err.note(&format!("available fields are: {}",
-                                                      self.name_series_display(field_names)));
-                                }
-                            };
-                    }
-                    ty::Array(_, len) => {
-                        if let (Some(len), Ok(user_index)) = (
-                            len.try_eval_usize(self.tcx, self.param_env),
-                            field.as_str().parse::<u64>()
-                        ) {
-                            let base = self.tcx.sess.source_map()
-                                .span_to_snippet(base.span)
-                                .unwrap_or_else(|_|
-                                    self.tcx.hir().hir_to_pretty_string(base.hir_id));
-                            let help = "instead of using tuple indexing, use array indexing";
-                            let suggestion = format!("{}[{}]", base, field);
-                            let applicability = if len < user_index {
-                                Applicability::MachineApplicable
-                            } else {
-                                Applicability::MaybeIncorrect
-                            };
-                            err.span_suggestion(
-                                expr.span, help, suggestion, applicability
-                            );
-                        }
-                    }
-                    ty::RawPtr(..) => {
-                        let base = self.tcx.sess.source_map()
-                            .span_to_snippet(base.span)
-                            .unwrap_or_else(|_| self.tcx.hir().hir_to_pretty_string(base.hir_id));
-                        let msg = format!("`{}` is a raw pointer; try dereferencing it", base);
-                        let suggestion = format!("(*{}).{}", base, field);
-                        err.span_suggestion(
-                            expr.span,
-                            &msg,
-                            suggestion,
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                    _ => {}
-                }
-                err
+            type_error_struct!(
+                self.tcx().sess,
+                field.span,
+                expr_t,
+                E0610,
+                "`{}` is a primitive type and therefore doesn't have fields",
+                expr_t
+            )
+            .emit();
+        }
+
+        self.tcx().types.err
+    }
+
+    fn ban_private_field_access(
+        &self,
+        expr: &hir::Expr,
+        expr_t: Ty<'tcx>,
+        field: ast::Ident,
+        base_did: DefId,
+    ) {
+        let struct_path = self.tcx().def_path_str(base_did);
+        let mut err = struct_span_err!(
+            self.tcx().sess,
+            expr.span,
+            E0616,
+            "field `{}` of struct `{}` is private",
+            field,
+            struct_path
+        );
+        // Also check if an accessible method exists, which is often what is meant.
+        if self.method_exists(field, expr_t, expr.hir_id, false)
+            && !self.expr_in_place(expr.hir_id)
+        {
+            self.suggest_method_call(
+                &mut err,
+                &format!("a method `{}` also exists, call it with parentheses", field),
+                field,
+                expr_t,
+                expr.hir_id,
+            );
+        }
+        err.emit();
+    }
+
+    fn ban_take_value_of_method(&self, expr: &hir::Expr, expr_t: Ty<'tcx>, field: ast::Ident) {
+        let mut err = type_error_struct!(
+            self.tcx().sess,
+            field.span,
+            expr_t,
+            E0615,
+            "attempted to take value of method `{}` on type `{}`",
+            field,
+            expr_t
+        );
+
+        if !self.expr_in_place(expr.hir_id) {
+            self.suggest_method_call(
+                &mut err,
+                "use parentheses to call the method",
+                field,
+                expr_t,
+                expr.hir_id
+            );
+        } else {
+            err.help("methods are immutable and cannot be assigned to");
+        }
+
+        err.emit();
+    }
+
+    fn suggest_fields_on_recordish(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        def: &'tcx ty::AdtDef,
+        field: ast::Ident,
+    ) {
+        if let Some(suggested_field_name) =
+            Self::suggest_field_name(def.non_enum_variant(), &field.as_str(), vec![])
+        {
+            err.span_suggestion(
+                field.span,
+                "a field with a similar name exists",
+                suggested_field_name.to_string(),
+                Applicability::MaybeIncorrect,
+            );
+        } else {
+            err.span_label(field.span, "unknown field");
+            let struct_variant_def = def.non_enum_variant();
+            let field_names = self.available_field_names(struct_variant_def);
+            if !field_names.is_empty() {
+                err.note(&format!("available fields are: {}",
+                                    self.name_series_display(field_names)));
+            }
+        }
+    }
+
+    fn maybe_suggest_array_indexing(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        expr: &hir::Expr,
+        base: &hir::Expr,
+        field: ast::Ident,
+        len: &ty::Const<'tcx>,
+    ) {
+        if let (Some(len), Ok(user_index)) = (
+            len.try_eval_usize(self.tcx, self.param_env),
+            field.as_str().parse::<u64>()
+        ) {
+            let base = self.tcx.sess.source_map()
+                .span_to_snippet(base.span)
+                .unwrap_or_else(|_| self.tcx.hir().hir_to_pretty_string(base.hir_id));
+            let help = "instead of using tuple indexing, use array indexing";
+            let suggestion = format!("{}[{}]", base, field);
+            let applicability = if len < user_index {
+                Applicability::MachineApplicable
             } else {
-                type_error_struct!(self.tcx().sess, field.span, expr_t, E0610,
-                                   "`{}` is a primitive type and therefore doesn't have fields",
-                                   expr_t)
-            }.emit();
-            self.tcx().types.err
+                Applicability::MaybeIncorrect
+            };
+            err.span_suggestion(expr.span, help, suggestion, applicability);
         }
     }
 
+    fn suggest_first_deref_field(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        expr: &hir::Expr,
+        base: &hir::Expr,
+        field: ast::Ident,
+    ) {
+        let base = self.tcx.sess.source_map()
+            .span_to_snippet(base.span)
+            .unwrap_or_else(|_| self.tcx.hir().hir_to_pretty_string(base.hir_id));
+        let msg = format!("`{}` is a raw pointer; try dereferencing it", base);
+        let suggestion = format!("(*{}).{}", base, field);
+        err.span_suggestion(
+            expr.span,
+            &msg,
+            suggestion,
+            Applicability::MaybeIncorrect,
+        );
+    }
+
     fn no_such_field_err<T: Display>(&self, span: Span, field: T, expr_t: &ty::TyS<'_>)
         -> DiagnosticBuilder<'_> {
         type_error_struct!(self.tcx().sess, span, expr_t, E0609,
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index b2c0e34d6fad7..28a1ccda4d841 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -203,7 +203,6 @@ fn check_associated_item(
                 fcx.register_wf_obligation(ty, span, code.clone());
             }
             ty::AssocKind::Method => {
-                reject_shadowing_parameters(fcx.tcx, item.def_id);
                 let sig = fcx.tcx.fn_sig(item.def_id);
                 let sig = fcx.normalize_associated_types_in(span, &sig);
                 check_fn_or_method(tcx, fcx, span, sig,
@@ -998,34 +997,6 @@ fn report_bivariance(tcx: TyCtxt<'_>, span: Span, param_name: ast::Name) {
     err.emit();
 }
 
-fn reject_shadowing_parameters(tcx: TyCtxt<'_>, def_id: DefId) {
-    let generics = tcx.generics_of(def_id);
-    let parent = tcx.generics_of(generics.parent.unwrap());
-    let impl_params: FxHashMap<_, _> = parent.params.iter().flat_map(|param| match param.kind {
-        GenericParamDefKind::Lifetime => None,
-        GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
-            Some((param.name, param.def_id))
-        }
-    }).collect();
-
-    for method_param in &generics.params {
-        // Shadowing is checked in `resolve_lifetime`.
-        if let GenericParamDefKind::Lifetime = method_param.kind {
-            continue
-        }
-        if impl_params.contains_key(&method_param.name) {
-            // Tighten up the span to focus on only the shadowing type.
-            let type_span = tcx.def_span(method_param.def_id);
-
-            // The expectation here is that the original trait declaration is
-            // local so it should be okay to just unwrap everything.
-            let trait_def_id = impl_params[&method_param.name];
-            let trait_decl_span = tcx.def_span(trait_def_id);
-            error_194(tcx, type_span, trait_decl_span, &method_param.name.as_str()[..]);
-        }
-    }
-}
-
 /// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that
 /// aren't true.
 fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) {
@@ -1152,12 +1123,3 @@ fn error_392(
     err.span_label(span, "unused parameter");
     err
 }
-
-fn error_194(tcx: TyCtxt<'_>, span: Span, trait_decl_span: Span, name: &str) {
-    struct_span_err!(tcx.sess, span, E0194,
-                     "type parameter `{}` shadows another type parameter of the same name",
-                     name)
-        .span_label(span, "shadows another type parameter")
-        .span_label(trait_decl_span, format!("first `{}` declared here", name))
-        .emit();
-}
diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs
index 90118a9f191d9..ca9ce3d22b5cb 100644
--- a/src/librustc_typeck/error_codes.rs
+++ b/src/librustc_typeck/error_codes.rs
@@ -1718,22 +1718,6 @@ Since we know for certain that `Wrapper<u32>` implements `Clone`, there's no
 reason to also specify it in a `where` clause.
 "##,
 
-E0194: r##"
-A type parameter was declared which shadows an existing one. An example of this
-error:
-
-```compile_fail,E0194
-trait Foo<T> {
-    fn do_something(&self) -> T;
-    fn do_something_else<T: Clone>(&self, bar: T);
-}
-```
-
-In this example, the trait `Foo` and the trait method `do_something_else` both
-define a type parameter `T`. This is not allowed: if the method wishes to
-define a type parameter, it must use a different name for it.
-"##,
-
 E0195: r##"
 Your method's lifetime parameters do not match the trait declaration.
 Erroneous code example:
@@ -4837,6 +4821,7 @@ register_diagnostics! {
 //  E0188, // can not cast an immutable reference to a mutable pointer
 //  E0189, // deprecated: can only cast a boxed pointer to a boxed object
 //  E0190, // deprecated: can only cast a &-pointer to an &-object
+//  E0194, // merged into E0403
 //  E0196, // cannot determine a type for this closure
     E0203, // type parameter has more than one relaxed default bound,
            // and only one is supported
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 3ae37f734b77e..9091607629e0f 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -5,7 +5,7 @@ pub use UnsafeSource::*;
 pub use crate::symbol::{Ident, Symbol as Name};
 pub use crate::util::parser::ExprPrecedence;
 
-use crate::ext::hygiene::{ExpnId, SyntaxContext};
+use crate::ext::hygiene::ExpnId;
 use crate::parse::token::{self, DelimToken};
 use crate::print::pprust;
 use crate::ptr::P;
@@ -1782,7 +1782,6 @@ pub struct InlineAsm {
     pub volatile: bool,
     pub alignstack: bool,
     pub dialect: AsmDialect,
-    pub ctxt: SyntaxContext,
 }
 
 /// An argument in a function header.
@@ -2030,7 +2029,6 @@ pub struct ForeignMod {
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)]
 pub struct GlobalAsm {
     pub asm: Symbol,
-    pub ctxt: SyntaxContext,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 8a56ae13b6f6e..1a87a903156d2 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -30,7 +30,6 @@ use crate::tokenstream::TokenTree;
 
 use errors::{Applicability, DiagnosticBuilder, Handler};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::Lock;
 use rustc_target::spec::abi::Abi;
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
 use log::debug;
@@ -2088,11 +2087,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                                        "type ascription is experimental");
                 }
             }
-            ast::ExprKind::Yield(..) => {
-                gate_feature_post!(&self, generators,
-                                  e.span,
-                                  "yield syntax is experimental");
-            }
             ast::ExprKind::TryBlock(_) => {
                 gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
             }
@@ -2427,10 +2421,6 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
     features
 }
 
-fn for_each_in_lock<T>(vec: &Lock<Vec<T>>, f: impl Fn(&T)) {
-    vec.borrow().iter().for_each(f);
-}
-
 pub fn check_crate(krate: &ast::Crate,
                    sess: &ParseSess,
                    features: &Features,
@@ -2443,26 +2433,16 @@ pub fn check_crate(krate: &ast::Crate,
         plugin_attributes,
     };
 
-    for_each_in_lock(&sess.param_attr_spans, |span| gate_feature!(
-        &ctx,
-        param_attrs,
-        *span,
-        "attributes on function parameters are unstable"
-    ));
-
-    for_each_in_lock(&sess.let_chains_spans, |span| gate_feature!(
-        &ctx,
-        let_chains,
-        *span,
-        "`let` expressions in this position are experimental"
-    ));
-
-    for_each_in_lock(&sess.async_closure_spans, |span| gate_feature!(
-        &ctx,
-        async_closure,
-        *span,
-        "async closures are unstable"
-    ));
+    macro_rules! gate_all {
+        ($spans:ident, $gate:ident, $msg:literal) => {
+            for span in &*sess.$spans.borrow() { gate_feature!(&ctx, $gate, *span, $msg); }
+        }
+    }
+
+    gate_all!(param_attr_spans, param_attrs, "attributes on function parameters are unstable");
+    gate_all!(let_chains_spans, let_chains, "`let` expressions in this position are experimental");
+    gate_all!(async_closure_spans, async_closure, "async closures are unstable");
+    gate_all!(yield_spans, generators, "yield syntax is experimental");
 
     let visitor = &mut PostExpansionVisitor {
         context: &ctx,
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index acafe327640d0..18d4a6463558d 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -1182,7 +1182,7 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { node, id, span, attrs }: &mut Expr,
         }
         ExprKind::InlineAsm(asm) => {
             let InlineAsm { asm: _, asm_str_style: _, outputs, inputs, clobbers: _, volatile: _,
-                            alignstack: _, dialect: _, ctxt: _ } = asm.deref_mut();
+                            alignstack: _, dialect: _ } = asm.deref_mut();
             for out in outputs {
                 let InlineAsmOutput { constraint: _, expr, is_rw: _, is_indirect: _ } = out;
                 vis.visit_expr(expr);
diff --git a/src/libsyntax/parse/lexer/tests.rs b/src/libsyntax/parse/lexer/tests.rs
index fc47e4f0b185a..7f66d012356a3 100644
--- a/src/libsyntax/parse/lexer/tests.rs
+++ b/src/libsyntax/parse/lexer/tests.rs
@@ -34,6 +34,7 @@ fn mk_sess(sm: Lrc<SourceMap>) -> ParseSess {
         param_attr_spans: Lock::new(Vec::new()),
         let_chains_spans: Lock::new(Vec::new()),
         async_closure_spans: Lock::new(Vec::new()),
+        yield_spans: Lock::new(Vec::new()),
         injected_crate_name: Once::new(),
     }
 }
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 80aa7a35266eb..31757130df18b 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -62,6 +62,8 @@ pub struct ParseSess {
     pub let_chains_spans: Lock<Vec<Span>>,
     // Places where `async || ..` exprs were used and should be feature gated.
     pub async_closure_spans: Lock<Vec<Span>>,
+    // Places where `yield e?` exprs were used and should be feature gated.
+    pub yield_spans: Lock<Vec<Span>>,
     pub injected_crate_name: Once<Symbol>,
 }
 
@@ -91,6 +93,7 @@ impl ParseSess {
             param_attr_spans: Lock::new(Vec::new()),
             let_chains_spans: Lock::new(Vec::new()),
             async_closure_spans: Lock::new(Vec::new()),
+            yield_spans: Lock::new(Vec::new()),
             injected_crate_name: Once::new(),
         }
     }
diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs
index f4b6a926734fb..ccc6bd1506709 100644
--- a/src/libsyntax/parse/parser/expr.rs
+++ b/src/libsyntax/parse/parser/expr.rs
@@ -997,6 +997,9 @@ impl<'a> Parser<'a> {
                     } else {
                         ex = ExprKind::Yield(None);
                     }
+
+                    let span = lo.to(hi);
+                    self.sess.yield_spans.borrow_mut().push(span);
                 } else if self.eat_keyword(kw::Let) {
                     return self.parse_let_expr(attrs);
                 } else if is_span_rust_2018 && self.eat_keyword(kw::Await) {
diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs
index 950166f9260e2..644a44f1989db 100644
--- a/src/libsyntax_ext/asm.rs
+++ b/src/libsyntax_ext/asm.rs
@@ -63,7 +63,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>,
     MacEager::expr(P(ast::Expr {
         id: ast::DUMMY_NODE_ID,
         node: ast::ExprKind::InlineAsm(P(inline_asm)),
-        span: sp,
+        span: sp.with_ctxt(cx.backtrace()),
         attrs: ThinVec::new(),
     }))
 }
@@ -277,6 +277,5 @@ fn parse_inline_asm<'a>(
         volatile,
         alignstack,
         dialect,
-        ctxt: cx.backtrace(),
     }))
 }
diff --git a/src/libsyntax_ext/deriving/cmp/ord.rs b/src/libsyntax_ext/deriving/cmp/ord.rs
index 885cfee35658a..55687c3175b9d 100644
--- a/src/libsyntax_ext/deriving/cmp/ord.rs
+++ b/src/libsyntax_ext/deriving/cmp/ord.rs
@@ -43,17 +43,18 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt<'_>,
 }
 
 
-pub fn ordering_collapsed(cx: &mut ExtCtxt<'_>,
-                          span: Span,
-                          self_arg_tags: &[ast::Ident])
-                          -> P<ast::Expr> {
+pub fn ordering_collapsed(
+    cx: &mut ExtCtxt<'_>,
+    span: Span,
+    self_arg_tags: &[ast::Ident],
+) -> P<ast::Expr> {
     let lft = cx.expr_ident(span, self_arg_tags[0]);
     let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1]));
-    cx.expr_method_call(span, lft, cx.ident_of("cmp"), vec![rgt])
+    cx.expr_method_call(span, lft, ast::Ident::new(sym::cmp, span), vec![rgt])
 }
 
 pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> {
-    let test_id = cx.ident_of("cmp").gensym();
+    let test_id = ast::Ident::new(sym::cmp, span);
     let equals_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
 
     let cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]);
@@ -75,34 +76,34 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<
             // as the outermost one, and the last as the innermost.
             false,
             |cx, span, old, self_f, other_fs| {
-        // match new {
-        //     ::std::cmp::Ordering::Equal => old,
-        //     cmp => cmp
-        // }
+                // match new {
+                //     ::std::cmp::Ordering::Equal => old,
+                //     cmp => cmp
+                // }
 
-        let new = {
-            let other_f = match other_fs {
-                [o_f] => o_f,
-                _ => cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`"),
-            };
+                let new = {
+                    let other_f = match other_fs {
+                        [o_f] => o_f,
+                        _ => cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`"),
+                    };
 
-            let args = vec![
-                    cx.expr_addr_of(span, self_f),
-                    cx.expr_addr_of(span, other_f.clone()),
-                ];
+                    let args = vec![
+                            cx.expr_addr_of(span, self_f),
+                            cx.expr_addr_of(span, other_f.clone()),
+                        ];
 
-            cx.expr_call_global(span, cmp_path.clone(), args)
-        };
+                    cx.expr_call_global(span, cmp_path.clone(), args)
+                };
 
-        let eq_arm = cx.arm(span,
-                            vec![cx.pat_path(span, equals_path.clone())],
-                            old);
-        let neq_arm = cx.arm(span,
-                             vec![cx.pat_ident(span, test_id)],
-                             cx.expr_ident(span, test_id));
+                let eq_arm = cx.arm(span,
+                                    vec![cx.pat_path(span, equals_path.clone())],
+                                    old);
+                let neq_arm = cx.arm(span,
+                                     vec![cx.pat_ident(span, test_id)],
+                                     cx.expr_ident(span, test_id));
 
-        cx.expr_match(span, new, vec![eq_arm, neq_arm])
-    },
+                cx.expr_match(span, new, vec![eq_arm, neq_arm])
+            },
             cx.expr_path(equals_path.clone()),
             Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
         if self_args.len() != 2 {
diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
index 0ec30f5924fbe..740b92a9b7978 100644
--- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs
+++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
@@ -94,11 +94,12 @@ pub enum OrderingOp {
     GeOp,
 }
 
-pub fn some_ordering_collapsed(cx: &mut ExtCtxt<'_>,
-                               span: Span,
-                               op: OrderingOp,
-                               self_arg_tags: &[ast::Ident])
-                               -> P<ast::Expr> {
+pub fn some_ordering_collapsed(
+    cx: &mut ExtCtxt<'_>,
+    span: Span,
+    op: OrderingOp,
+    self_arg_tags: &[ast::Ident],
+) -> P<ast::Expr> {
     let lft = cx.expr_ident(span, self_arg_tags[0]);
     let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1]));
     let op_str = match op {
@@ -108,11 +109,11 @@ pub fn some_ordering_collapsed(cx: &mut ExtCtxt<'_>,
         GtOp => "gt",
         GeOp => "ge",
     };
-    cx.expr_method_call(span, lft, cx.ident_of(op_str), vec![rgt])
+    cx.expr_method_call(span, lft, ast::Ident::from_str_and_span(op_str, span), vec![rgt])
 }
 
 pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> {
-    let test_id = cx.ident_of("cmp").gensym();
+    let test_id = ast::Ident::new(sym::cmp, span);
     let ordering = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
     let ordering_expr = cx.expr_path(ordering.clone());
     let equals_expr = cx.expr_some(span, ordering_expr);
diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs
index 15e93f2843a12..441535410480b 100644
--- a/src/libsyntax_ext/deriving/debug.rs
+++ b/src/libsyntax_ext/deriving/debug.rs
@@ -62,7 +62,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
     // We want to make sure we have the ctxt set so that we can use unstable methods
     let span = span.with_ctxt(cx.backtrace());
     let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
-    let builder = Ident::from_str("debug_trait_builder").gensym();
+    let builder = Ident::from_str_and_span("debug_trait_builder", span);
     let builder_expr = cx.expr_ident(span, builder.clone());
 
     let fmt = substr.nonself_args[0].clone();
@@ -73,7 +73,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
             // tuple struct/"normal" variant
             let expr =
                 cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]);
-            stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
+            stmts.push(cx.stmt_let(span, true, builder, expr));
 
             for field in fields {
                 // Use double indirection to make sure this works for unsized types
@@ -82,7 +82,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
 
                 let expr = cx.expr_method_call(span,
                                                 builder_expr.clone(),
-                                                Ident::with_empty_ctxt(sym::field),
+                                                Ident::new(sym::field, span),
                                                 vec![field]);
 
                 // Use `let _ = expr;` to avoid triggering the
@@ -106,7 +106,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
                 let field = cx.expr_addr_of(field.span, field);
                 let expr = cx.expr_method_call(span,
                                                 builder_expr.clone(),
-                                                Ident::with_empty_ctxt(sym::field),
+                                                Ident::new(sym::field, span),
                                                 vec![name, field]);
                 stmts.push(stmt_let_undescore(cx, span, expr));
             }
diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs
index 293c5a1e7e71b..9b6f8518de046 100644
--- a/src/libsyntax_ext/deriving/decodable.rs
+++ b/src/libsyntax_ext/deriving/decodable.rs
@@ -1,6 +1,6 @@
-//! The compiler code necessary for `#[derive(Decodable)]`. See encodable.rs for more.
+//! The compiler code necessary for `#[derive(RustcDecodable)]`. See encodable.rs for more.
 
-use crate::deriving::{self, pathvec_std};
+use crate::deriving::pathvec_std;
 use crate::deriving::generic::*;
 use crate::deriving::generic::ty::*;
 
@@ -17,7 +17,7 @@ pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt<'_>,
                                        item: &Annotatable,
                                        push: &mut dyn FnMut(Annotatable)) {
     let krate = "rustc_serialize";
-    let typaram = &*deriving::hygienic_type_parameter(item, "__D");
+    let typaram = "__D";
 
     let trait_def = TraitDef {
         span,
diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs
index 52e74a7c57e8c..8b18fb25e90c1 100644
--- a/src/libsyntax_ext/deriving/encodable.rs
+++ b/src/libsyntax_ext/deriving/encodable.rs
@@ -1,11 +1,12 @@
-//! The compiler code necessary to implement the `#[derive(Encodable)]`
-//! (and `Decodable`, in `decodable.rs`) extension. The idea here is that
-//! type-defining items may be tagged with `#[derive(Encodable, Decodable)]`.
+//! The compiler code necessary to implement the `#[derive(RustcEncodable)]`
+//! (and `RustcDecodable`, in `decodable.rs`) extension. The idea here is that
+//! type-defining items may be tagged with
+//! `#[derive(RustcEncodable, RustcDecodable)]`.
 //!
 //! For example, a type like:
 //!
 //! ```
-//! #[derive(Encodable, Decodable)]
+//! #[derive(RustcEncodable, RustcDecodable)]
 //! struct Node { id: usize }
 //! ```
 //!
@@ -40,15 +41,17 @@
 //! references other non-built-in types. A type definition like:
 //!
 //! ```
-//! # #[derive(Encodable, Decodable)] struct Span;
-//! #[derive(Encodable, Decodable)]
+//! # #[derive(RustcEncodable, RustcDecodable)]
+//! # struct Span;
+//! #[derive(RustcEncodable, RustcDecodable)]
 //! struct Spanned<T> { node: T, span: Span }
 //! ```
 //!
 //! would yield functions like:
 //!
 //! ```
-//! # #[derive(Encodable, Decodable)] struct Span;
+//! # #[derive(RustcEncodable, RustcDecodable)]
+//! # struct Span;
 //! # struct Spanned<T> { node: T, span: Span }
 //! impl<
 //!     S: Encoder<E>,
@@ -82,7 +85,7 @@
 //! }
 //! ```
 
-use crate::deriving::{self, pathvec_std};
+use crate::deriving::pathvec_std;
 use crate::deriving::generic::*;
 use crate::deriving::generic::ty::*;
 
@@ -98,7 +101,7 @@ pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt<'_>,
                                        item: &Annotatable,
                                        push: &mut dyn FnMut(Annotatable)) {
     let krate = "rustc_serialize";
-    let typaram = &*deriving::hygienic_type_parameter(item, "__S");
+    let typaram = "__S";
 
     let trait_def = TraitDef {
         span,
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index d080dc37a9268..6497c19f78362 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -890,7 +890,7 @@ impl<'a> MethodDef<'a> {
 
         for (ty, name) in self.args.iter() {
             let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics);
-            let ident = cx.ident_of(name).gensym();
+            let ident = ast::Ident::from_str_and_span(name, trait_.span);
             arg_tys.push((ident, ast_ty));
 
             let arg_expr = cx.expr_ident(trait_.span, ident);
@@ -1210,7 +1210,7 @@ impl<'a> MethodDef<'a> {
         let vi_idents = self_arg_names.iter()
             .map(|name| {
                 let vi_suffix = format!("{}_vi", &name[..]);
-                cx.ident_of(&vi_suffix[..]).gensym()
+                ast::Ident::from_str_and_span(&vi_suffix[..], trait_.span)
             })
             .collect::<Vec<ast::Ident>>();
 
@@ -1387,7 +1387,10 @@ impl<'a> MethodDef<'a> {
                 let variant_value =
                     deriving::call_intrinsic(cx, sp, "discriminant_value", vec![self_addr]);
 
-                let target_ty = cx.ty_ident(sp, cx.ident_of(target_type_name));
+                let target_ty = cx.ty_ident(
+                    sp,
+                    ast::Ident::from_str_and_span(target_type_name, sp),
+                );
                 let variant_disr = cx.expr_cast(sp, variant_value, target_ty);
                 let let_stmt = cx.stmt_let(sp, false, ident, variant_disr);
                 index_let_stmts.push(let_stmt);
@@ -1588,7 +1591,7 @@ impl<'a> TraitDef<'a> {
         let mut ident_exprs = Vec::new();
         for (i, struct_field) in struct_def.fields().iter().enumerate() {
             let sp = struct_field.span.with_ctxt(self.span.ctxt());
-            let ident = cx.ident_of(&format!("{}_{}", prefix, i)).gensym();
+            let ident = ast::Ident::from_str_and_span(&format!("{}_{}", prefix, i), self.span);
             paths.push(ident.with_span_pos(sp));
             let val = cx.expr_path(cx.path_ident(sp, ident));
             let val = if use_temporaries {
diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs
index 399829eaefd14..7fcf036fc8176 100644
--- a/src/libsyntax_ext/deriving/generic/ty.rs
+++ b/src/libsyntax_ext/deriving/generic/ty.rs
@@ -72,7 +72,7 @@ impl<'a> Path<'a> {
                    self_ty: Ident,
                    self_generics: &Generics)
                    -> ast::Path {
-        let mut idents = self.path.iter().map(|s| cx.ident_of(*s)).collect();
+        let mut idents = self.path.iter().map(|s| Ident::from_str_and_span(*s, span)).collect();
         let lt = mk_lifetimes(cx, span, &self.lifetime);
         let tys: Vec<P<ast::Ty>> =
             self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
@@ -209,7 +209,7 @@ fn mk_ty_param(cx: &ExtCtxt<'_>,
             cx.trait_bound(path)
         })
         .collect();
-    cx.typaram(span, cx.ident_of(name), attrs.to_owned(), bounds, None)
+    cx.typaram(span, ast::Ident::from_str_and_span(name, span), attrs.to_owned(), bounds, None)
 }
 
 fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics {
diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs
index 9787722e81dd0..2fc594abd705e 100644
--- a/src/libsyntax_ext/deriving/hash.rs
+++ b/src/libsyntax_ext/deriving/hash.rs
@@ -16,7 +16,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt<'_>,
 
     let path = Path::new_(pathvec_std!(cx, hash::Hash), None, vec![], PathKind::Std);
 
-    let typaram = &*deriving::hygienic_type_parameter(item, "__H");
+    let typaram = "__H";
 
     let arg = Path::new_local(typaram);
     let hash_trait_def = TraitDef {
diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs
index 8cd2853e5383d..da68eea0c50e7 100644
--- a/src/libsyntax_ext/deriving/mod.rs
+++ b/src/libsyntax_ext/deriving/mod.rs
@@ -54,33 +54,6 @@ impl MultiItemModifier for BuiltinDerive {
     }
 }
 
-/// Construct a name for the inner type parameter that can't collide with any type parameters of
-/// the item. This is achieved by starting with a base and then concatenating the names of all
-/// other type parameters.
-// FIXME(aburka): use real hygiene when that becomes possible
-fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String {
-    let mut typaram = String::from(base);
-    if let Annotatable::Item(ref item) = *item {
-        match item.node {
-            ast::ItemKind::Struct(_, ast::Generics { ref params, .. }) |
-            ast::ItemKind::Enum(_, ast::Generics { ref params, .. }) => {
-                for param in params {
-                    match param.kind {
-                        ast::GenericParamKind::Type { .. } => {
-                            typaram.push_str(&param.ident.as_str());
-                        }
-                        _ => {}
-                    }
-                }
-            }
-
-            _ => {}
-        }
-    }
-
-    typaram
-}
-
 /// Constructs an expression that calls an intrinsic
 fn call_intrinsic(cx: &ExtCtxt<'_>,
                   span: Span,
diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs
index 112192fac5d26..73ebeaec45497 100644
--- a/src/libsyntax_ext/global_asm.rs
+++ b/src/libsyntax_ext/global_asm.rs
@@ -30,7 +30,7 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt<'_>,
                 id: ast::DUMMY_NODE_ID,
                 node: ast::ItemKind::GlobalAsm(P(global_asm)),
                 vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
-                span: sp,
+                span: sp.with_ctxt(cx.backtrace()),
                 tokens: None,
             })])
         }
@@ -61,8 +61,5 @@ fn parse_global_asm<'a>(
         None => return Ok(None),
     };
 
-    Ok(Some(ast::GlobalAsm {
-        asm,
-        ctxt: cx.backtrace(),
-    }))
+    Ok(Some(ast::GlobalAsm { asm }))
 }
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index f91a22915445c..df7bda8412f5d 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -30,7 +30,6 @@ use crate::{Span, DUMMY_SP};
 use crate::edition::Edition;
 use crate::symbol::{kw, Symbol};
 
-use rustc_serialize::{Encodable, Decodable, Encoder, Decoder};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use std::fmt;
@@ -766,15 +765,3 @@ impl DesugaringKind {
         }
     }
 }
-
-impl Encodable for SyntaxContext {
-    fn encode<E: Encoder>(&self, _: &mut E) -> Result<(), E::Error> {
-        Ok(()) // FIXME(jseyfried) intercrate hygiene
-    }
-}
-
-impl Decodable for SyntaxContext {
-    fn decode<D: Decoder>(_: &mut D) -> Result<SyntaxContext, D::Error> {
-        Ok(SyntaxContext::empty()) // FIXME(jseyfried) intercrate hygiene
-    }
-}
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 2d9556233d15f..ce0be7c715a16 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -8,13 +8,13 @@ use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::newtype_index;
 use rustc_macros::symbols;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+use rustc_serialize::{UseSpecializedDecodable, UseSpecializedEncodable};
 
 use std::cmp::{PartialEq, Ordering, PartialOrd, Ord};
 use std::fmt;
 use std::hash::{Hash, Hasher};
 use std::str;
 
-use crate::hygiene::SyntaxContext;
 use crate::{Span, DUMMY_SP, GLOBALS};
 
 #[cfg(test)]
@@ -849,28 +849,9 @@ impl fmt::Display for Ident {
     }
 }
 
-impl Encodable for Ident {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        if self.span.ctxt().modern() == SyntaxContext::empty() {
-            s.emit_str(&self.as_str())
-        } else { // FIXME(jseyfried): intercrate hygiene
-            let mut string = "#".to_owned();
-            string.push_str(&self.as_str());
-            s.emit_str(&string)
-        }
-    }
-}
+impl UseSpecializedEncodable for Ident {}
 
-impl Decodable for Ident {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
-        let string = d.read_str()?;
-        Ok(if !string.starts_with('#') {
-            Ident::from_str(&string)
-        } else { // FIXME(jseyfried): intercrate hygiene
-            Ident::from_str(&string[1..]).gensym()
-        })
-    }
-}
+impl UseSpecializedDecodable for Ident {}
 
 /// A symbol is an interned or gensymed string. A gensym is a symbol that is
 /// never equal to any other symbol.
diff --git a/src/test/ui/async-await/suggest-switching-edition-on-await.rs b/src/test/ui/async-await/suggest-switching-edition-on-await.rs
new file mode 100644
index 0000000000000..1402f1ca92ba8
--- /dev/null
+++ b/src/test/ui/async-await/suggest-switching-edition-on-await.rs
@@ -0,0 +1,45 @@
+use std::pin::Pin;
+use std::future::Future;
+
+fn main() {}
+
+fn await_on_struct_missing() {
+    struct S;
+    let x = S;
+    x.await;
+    //~^ ERROR no field `await` on type
+    //~| NOTE unknown field
+    //~| NOTE to `.await` a `Future`, switch to Rust 2018
+    //~| HELP set `edition = "2018"` in `Cargo.toml`
+    //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
+
+fn await_on_struct_similar() {
+    struct S {
+        awai: u8,
+    }
+    let x = S { awai: 42 };
+    x.await;
+    //~^ ERROR no field `await` on type
+    //~| HELP a field with a similar name exists
+    //~| NOTE to `.await` a `Future`, switch to Rust 2018
+    //~| HELP set `edition = "2018"` in `Cargo.toml`
+    //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
+
+fn await_on_63533(x: Pin<&mut dyn Future<Output = ()>>) {
+    x.await;
+    //~^ ERROR no field `await` on type
+    //~| NOTE unknown field
+    //~| NOTE to `.await` a `Future`, switch to Rust 2018
+    //~| HELP set `edition = "2018"` in `Cargo.toml`
+    //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
+
+fn await_on_apit(x: impl Future<Output = ()>) {
+    x.await;
+    //~^ ERROR no field `await` on type
+    //~| NOTE to `.await` a `Future`, switch to Rust 2018
+    //~| HELP set `edition = "2018"` in `Cargo.toml`
+    //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
+}
diff --git a/src/test/ui/async-await/suggest-switching-edition-on-await.stderr b/src/test/ui/async-await/suggest-switching-edition-on-await.stderr
new file mode 100644
index 0000000000000..f623511c0eb23
--- /dev/null
+++ b/src/test/ui/async-await/suggest-switching-edition-on-await.stderr
@@ -0,0 +1,43 @@
+error[E0609]: no field `await` on type `await_on_struct_missing::S`
+  --> $DIR/suggest-switching-edition-on-await.rs:9:7
+   |
+LL |     x.await;
+   |       ^^^^^ unknown field
+   |
+   = note: to `.await` a `Future`, switch to Rust 2018
+   = help: set `edition = "2018"` in `Cargo.toml`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0609]: no field `await` on type `await_on_struct_similar::S`
+  --> $DIR/suggest-switching-edition-on-await.rs:22:7
+   |
+LL |     x.await;
+   |       ^^^^^ help: a field with a similar name exists: `awai`
+   |
+   = note: to `.await` a `Future`, switch to Rust 2018
+   = help: set `edition = "2018"` in `Cargo.toml`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0609]: no field `await` on type `std::pin::Pin<&mut dyn std::future::Future<Output = ()>>`
+  --> $DIR/suggest-switching-edition-on-await.rs:31:7
+   |
+LL |     x.await;
+   |       ^^^^^ unknown field
+   |
+   = note: to `.await` a `Future`, switch to Rust 2018
+   = help: set `edition = "2018"` in `Cargo.toml`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0609]: no field `await` on type `impl Future<Output = ()>`
+  --> $DIR/suggest-switching-edition-on-await.rs:40:7
+   |
+LL |     x.await;
+   |       ^^^^^
+   |
+   = note: to `.await` a `Future`, switch to Rust 2018
+   = help: set `edition = "2018"` in `Cargo.toml`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/derives/derive-hygiene.rs b/src/test/ui/derives/derive-hygiene.rs
new file mode 100644
index 0000000000000..0681b1e3efbf3
--- /dev/null
+++ b/src/test/ui/derives/derive-hygiene.rs
@@ -0,0 +1,119 @@
+// Make sure that built-in derives don't rely on the user not declaring certain
+// names to work properly.
+
+// check-pass
+
+#![allow(nonstandard_style)]
+#![feature(decl_macro)]
+
+static f: () = ();
+static cmp: () = ();
+static other: () = ();
+static state: () = ();
+static __self_0_0: () = ();
+static __self_1_0: () = ();
+static __self_vi: () = ();
+static __arg_1_0: () = ();
+static debug_trait_builder: () = ();
+
+struct isize;
+trait i16 {}
+
+trait MethodsInDerives: Sized {
+    fn debug_tuple(self) {}
+    fn debug_struct(self) {}
+    fn field(self) {}
+    fn finish(self) {}
+    fn clone(self) {}
+    fn cmp(self) {}
+    fn partial_cmp(self) {}
+    fn eq(self) {}
+    fn ne(self) {}
+    fn le(self) {}
+    fn lt(self) {}
+    fn ge(self) {}
+    fn gt(self) {}
+    fn hash(self) {}
+}
+
+trait GenericAny<T, U> {}
+impl<S, T, U> GenericAny<T, U> for S {}
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+enum __H { V(i32), }
+
+#[repr(i16)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+enum W { A, B }
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
+struct X<A: GenericAny<A, self::X<i32>>> {
+    A: A,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
+struct Y<B>(B)
+where
+    B: From<B>;
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+enum Z<C> {
+    C(C),
+    B { C: C },
+}
+
+// Make sure that we aren't using `self::` in paths, since it doesn't work in
+// non-module scopes.
+const NON_MODULE: () = {
+    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+    enum __H { V(i32), }
+
+    #[repr(i16)]
+    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+    enum W { A, B }
+
+    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
+    struct X<A: Fn(A) -> self::X<i32>> {
+        A: A,
+    }
+
+    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
+    struct Y<B>(B)
+    where
+        B: From<B>;
+
+    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+    enum Z<C> {
+        C(C),
+        B { C: C },
+    }
+};
+
+macro m() {
+    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+    enum __H { V(i32), }
+
+    #[repr(i16)]
+    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+    enum W { A, B }
+
+    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
+    struct X<A: GenericAny<A, self::X<i32>>> {
+        A: A,
+    }
+
+    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)]
+    struct Y<B>(B)
+    where
+        B: From<B>;
+
+    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+    enum Z<C> {
+        C(C),
+        B { C: C },
+    }
+}
+
+m!();
+
+fn main() {}
diff --git a/src/test/ui/duplicate/duplicate-type-parameter.stderr b/src/test/ui/duplicate/duplicate-type-parameter.stderr
index 8606479ff6863..6754574f0b953 100644
--- a/src/test/ui/duplicate/duplicate-type-parameter.stderr
+++ b/src/test/ui/duplicate/duplicate-type-parameter.stderr
@@ -1,4 +1,4 @@
-error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
   --> $DIR/duplicate-type-parameter.rs:1:12
    |
 LL | type Foo<T,T> = Option<T>;
@@ -6,7 +6,7 @@ LL | type Foo<T,T> = Option<T>;
    |          |
    |          first use of `T`
 
-error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
   --> $DIR/duplicate-type-parameter.rs:4:14
    |
 LL | struct Bar<T,T>(T);
@@ -14,7 +14,7 @@ LL | struct Bar<T,T>(T);
    |            |
    |            first use of `T`
 
-error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
   --> $DIR/duplicate-type-parameter.rs:7:14
    |
 LL | struct Baz<T,T> {
@@ -22,7 +22,7 @@ LL | struct Baz<T,T> {
    |            |
    |            first use of `T`
 
-error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
   --> $DIR/duplicate-type-parameter.rs:12:12
    |
 LL | enum Boo<T,T> {
@@ -30,7 +30,7 @@ LL | enum Boo<T,T> {
    |          |
    |          first use of `T`
 
-error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
   --> $DIR/duplicate-type-parameter.rs:18:11
    |
 LL | fn quux<T,T>(x: T) {}
@@ -38,7 +38,7 @@ LL | fn quux<T,T>(x: T) {}
    |         |
    |         first use of `T`
 
-error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
   --> $DIR/duplicate-type-parameter.rs:21:13
    |
 LL | trait Qux<T,T> {}
@@ -46,7 +46,7 @@ LL | trait Qux<T,T> {}
    |           |
    |           first use of `T`
 
-error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
   --> $DIR/duplicate-type-parameter.rs:24:8
    |
 LL | impl<T,T> Qux<T,T> for Option<T> {}
diff --git a/src/test/ui/error-codes/E0194.rs b/src/test/ui/error-codes/E0194.rs
index 71eff0e7465a5..8a43f38fcfd5f 100644
--- a/src/test/ui/error-codes/E0194.rs
+++ b/src/test/ui/error-codes/E0194.rs
@@ -1,7 +1,7 @@
 trait Foo<T> {
     fn do_something(&self) -> T;
     fn do_something_else<T: Clone>(&self, bar: T);
-    //~^ ERROR E0194
+    //~^ ERROR E0403
 }
 
 fn main() {
diff --git a/src/test/ui/error-codes/E0194.stderr b/src/test/ui/error-codes/E0194.stderr
index ab4918a4e27d5..f2c908eea0bb0 100644
--- a/src/test/ui/error-codes/E0194.stderr
+++ b/src/test/ui/error-codes/E0194.stderr
@@ -1,12 +1,12 @@
-error[E0194]: type parameter `T` shadows another type parameter of the same name
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
   --> $DIR/E0194.rs:3:26
    |
 LL | trait Foo<T> {
-   |           - first `T` declared here
+   |           - first use of `T`
 LL |     fn do_something(&self) -> T;
 LL |     fn do_something_else<T: Clone>(&self, bar: T);
-   |                          ^ shadows another type parameter
+   |                          ^ already used
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0194`.
+For more information about this error, try `rustc --explain E0403`.
diff --git a/src/test/ui/error-codes/E0403.stderr b/src/test/ui/error-codes/E0403.stderr
index 2bd7de6c24614..d76a58a7c80de 100644
--- a/src/test/ui/error-codes/E0403.stderr
+++ b/src/test/ui/error-codes/E0403.stderr
@@ -1,4 +1,4 @@
-error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
   --> $DIR/E0403.rs:1:11
    |
 LL | fn foo<T, T>(s: T, u: T) {}
diff --git a/src/test/ui/feature-gates/feature-gate-generators.rs b/src/test/ui/feature-gates/feature-gate-generators.rs
index cee930fd785b9..382d891feed84 100644
--- a/src/test/ui/feature-gates/feature-gate-generators.rs
+++ b/src/test/ui/feature-gates/feature-gate-generators.rs
@@ -2,3 +2,9 @@ fn main() {
     yield true; //~ ERROR yield syntax is experimental
                 //~^ ERROR yield statement outside of generator literal
 }
+
+#[cfg(FALSE)]
+fn foo() {
+    yield; //~ ERROR yield syntax is experimental
+    yield 0; //~ ERROR yield syntax is experimental
+}
diff --git a/src/test/ui/feature-gates/feature-gate-generators.stderr b/src/test/ui/feature-gates/feature-gate-generators.stderr
index cdb056012542b..24b814b410c9d 100644
--- a/src/test/ui/feature-gates/feature-gate-generators.stderr
+++ b/src/test/ui/feature-gates/feature-gate-generators.stderr
@@ -7,12 +7,30 @@ LL |     yield true;
    = note: for more information, see https://github.com/rust-lang/rust/issues/43122
    = help: add `#![feature(generators)]` to the crate attributes to enable
 
+error[E0658]: yield syntax is experimental
+  --> $DIR/feature-gate-generators.rs:8:5
+   |
+LL |     yield;
+   |     ^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/43122
+   = help: add `#![feature(generators)]` to the crate attributes to enable
+
+error[E0658]: yield syntax is experimental
+  --> $DIR/feature-gate-generators.rs:9:5
+   |
+LL |     yield 0;
+   |     ^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/43122
+   = help: add `#![feature(generators)]` to the crate attributes to enable
+
 error[E0627]: yield statement outside of generator literal
   --> $DIR/feature-gate-generators.rs:2:5
    |
 LL |     yield true;
    |     ^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/hygiene/auxiliary/codegen-attrs.rs b/src/test/ui/hygiene/auxiliary/codegen-attrs.rs
new file mode 100644
index 0000000000000..74afedbeb77ce
--- /dev/null
+++ b/src/test/ui/hygiene/auxiliary/codegen-attrs.rs
@@ -0,0 +1,10 @@
+#![feature(decl_macro)]
+
+macro m($f:ident) {
+    #[export_name = "export_function_name"]
+    pub fn $f() -> i32 {
+        2
+    }
+}
+
+m!(rust_function_name);
diff --git a/src/test/ui/hygiene/cross-crate-codegen-attrs.rs b/src/test/ui/hygiene/cross-crate-codegen-attrs.rs
new file mode 100644
index 0000000000000..af6b1334387ea
--- /dev/null
+++ b/src/test/ui/hygiene/cross-crate-codegen-attrs.rs
@@ -0,0 +1,12 @@
+// Make sure that macro expanded codegen attributes work across crates.
+// We used to gensym the identifiers in attributes, which stopped dependent
+// crates from seeing them, resulting in linker errors in cases like this one.
+
+// run-pass
+// aux-build:codegen-attrs.rs
+
+extern crate codegen_attrs;
+
+fn main() {
+    assert_eq!(codegen_attrs::rust_function_name(), 2);
+}
diff --git a/src/test/ui/rfc1598-generic-associated-types/shadowing.rs b/src/test/ui/rfc1598-generic-associated-types/shadowing.rs
index 03492631cb7c8..f5197fd01bfd6 100644
--- a/src/test/ui/rfc1598-generic-associated-types/shadowing.rs
+++ b/src/test/ui/rfc1598-generic-associated-types/shadowing.rs
@@ -1,12 +1,9 @@
+#![allow(incomplete_features)]
 #![feature(generic_associated_types)]
 
-//FIXME(#44265): The lifetime shadowing and type parameter shadowing
-// should cause an error. Now it compiles (erroneously) and this will be addressed
-// by a future PR. Then remove the following:
-// build-pass (FIXME(62277): could be check-pass?)
-
 trait Shadow<'a> {
-    type Bar<'a>; // Error: shadowed lifetime
+    //FIXME(#44265): The lifetime parameter shadowing should cause an error.
+    type Bar<'a>;
 }
 
 trait NoShadow<'a> {
@@ -14,11 +11,12 @@ trait NoShadow<'a> {
 }
 
 impl<'a> NoShadow<'a> for &'a u32 {
-    type Bar<'a> = i32; // Error: shadowed lifetime
+    //FIXME(#44265): The lifetime parameter shadowing should cause an error.
+    type Bar<'a> = i32;
 }
 
 trait ShadowT<T> {
-    type Bar<T>; // Error: shadowed type parameter
+    type Bar<T>; //~ ERROR the name `T` is already used
 }
 
 trait NoShadowT<T> {
@@ -26,7 +24,7 @@ trait NoShadowT<T> {
 }
 
 impl<T> NoShadowT<T> for Option<T> {
-    type Bar<T> = i32; // Error: shadowed type parameter
+    type Bar<T> = i32; //~ ERROR the name `T` is already used
 }
 
 fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr b/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr
index 9526df258c497..a06c635084525 100644
--- a/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr
+++ b/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr
@@ -1,8 +1,19 @@
-warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
-  --> $DIR/shadowing.rs:1:12
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
+  --> $DIR/shadowing.rs:19:14
    |
-LL | #![feature(generic_associated_types)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+LL | trait ShadowT<T> {
+   |               - first use of `T`
+LL |     type Bar<T>;
+   |              ^ already used
+
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
+  --> $DIR/shadowing.rs:27:14
    |
-   = note: `#[warn(incomplete_features)]` on by default
+LL | impl<T> NoShadowT<T> for Option<T> {
+   |      - first use of `T`
+LL |     type Bar<T> = i32;
+   |              ^ already used
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0403`.
diff --git a/src/test/ui/shadowed/shadowed-type-parameter.rs b/src/test/ui/shadowed/shadowed-type-parameter.rs
index ba9f3abcf7ade..e74620f8900c0 100644
--- a/src/test/ui/shadowed/shadowed-type-parameter.rs
+++ b/src/test/ui/shadowed/shadowed-type-parameter.rs
@@ -6,7 +6,7 @@ struct Foo<T>(T);
 
 impl<T> Foo<T> {
     fn shadow_in_method<T>(&self) {}
-    //~^ ERROR type parameter `T` shadows another type parameter
+    //~^ ERROR the name `T` is already used
 
     fn not_shadow_in_item<U>(&self) {
         struct Bar<T, U>(T,U); // not a shadow, separate item
@@ -18,10 +18,10 @@ trait Bar<T> {
     fn dummy(&self) -> T;
 
     fn shadow_in_required<T>(&self);
-    //~^ ERROR type parameter `T` shadows another type parameter
+    //~^ ERROR the name `T` is already used
 
     fn shadow_in_provided<T>(&self) {}
-    //~^ ERROR type parameter `T` shadows another type parameter
+    //~^ ERROR the name `T` is already used
 
     fn not_shadow_in_required<U>(&self);
     fn not_shadow_in_provided<U>(&self) {}
diff --git a/src/test/ui/shadowed/shadowed-type-parameter.stderr b/src/test/ui/shadowed/shadowed-type-parameter.stderr
index 6b4d1fae3de18..0ea82f983f1a7 100644
--- a/src/test/ui/shadowed/shadowed-type-parameter.stderr
+++ b/src/test/ui/shadowed/shadowed-type-parameter.stderr
@@ -1,29 +1,29 @@
-error[E0194]: type parameter `T` shadows another type parameter of the same name
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
+  --> $DIR/shadowed-type-parameter.rs:8:25
+   |
+LL | impl<T> Foo<T> {
+   |      - first use of `T`
+LL |     fn shadow_in_method<T>(&self) {}
+   |                         ^ already used
+
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
   --> $DIR/shadowed-type-parameter.rs:20:27
    |
 LL | trait Bar<T> {
-   |           - first `T` declared here
+   |           - first use of `T`
 ...
 LL |     fn shadow_in_required<T>(&self);
-   |                           ^ shadows another type parameter
+   |                           ^ already used
 
-error[E0194]: type parameter `T` shadows another type parameter of the same name
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
   --> $DIR/shadowed-type-parameter.rs:23:27
    |
 LL | trait Bar<T> {
-   |           - first `T` declared here
+   |           - first use of `T`
 ...
 LL |     fn shadow_in_provided<T>(&self) {}
-   |                           ^ shadows another type parameter
-
-error[E0194]: type parameter `T` shadows another type parameter of the same name
-  --> $DIR/shadowed-type-parameter.rs:8:25
-   |
-LL | impl<T> Foo<T> {
-   |      - first `T` declared here
-LL |     fn shadow_in_method<T>(&self) {}
-   |                         ^ shadows another type parameter
+   |                           ^ already used
 
 error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0194`.
+For more information about this error, try `rustc --explain E0403`.