about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock2
-rw-r--r--src/liballoc/vec.rs7
-rw-r--r--src/libcore/macros/mod.rs (renamed from src/libcore/macros.rs)4
-rw-r--r--src/libcore/macros/panic.md47
-rw-r--r--src/libcore/mem/mod.rs10
-rw-r--r--src/libpanic_unwind/lib.rs5
-rw-r--r--src/libpanic_unwind/miri.rs21
-rw-r--r--src/librustc/hir/def.rs6
-rw-r--r--src/librustc/hir/lowering.rs2
-rw-r--r--src/librustc/hir/lowering/item.rs18
-rw-r--r--src/librustc/session/mod.rs14
-rw-r--r--src/librustc_driver/Cargo.toml1
-rw-r--r--src/librustc_driver/lib.rs16
-rw-r--r--src/librustc_error_codes/error_codes.rs3
-rw-r--r--src/librustc_error_codes/lib.rs11
-rw-r--r--src/librustc_interface/Cargo.toml1
-rw-r--r--src/librustc_interface/interface.rs28
-rw-r--r--src/librustc_interface/passes.rs9
-rw-r--r--src/librustc_interface/util.rs13
-rw-r--r--src/librustc_lint/unused.rs20
-rw-r--r--src/librustc_parse/parser/expr.rs50
-rw-r--r--src/librustc_parse/parser/item.rs41
-rw-r--r--src/librustc_parse/parser/mod.rs64
-rw-r--r--src/librustc_parse/parser/ty.rs4
-rw-r--r--src/librustc_passes/dead.rs2
-rw-r--r--src/librustc_plugin/registry.rs13
-rw-r--r--src/librustc_resolve/diagnostics.rs9
-rw-r--r--src/librustc_resolve/lib.rs8
-rw-r--r--src/librustc_resolve/macros.rs7
-rw-r--r--src/librustc_save_analysis/sig.rs17
-rw-r--r--src/librustdoc/core.rs2
-rw-r--r--src/librustdoc/lib.rs3
-rw-r--r--src/librustdoc/test.rs1
-rw-r--r--src/libstd/keyword_docs.rs2
-rw-r--r--src/libstd/macros.rs48
-rw-r--r--src/libsyntax/ast.rs60
-rw-r--r--src/libsyntax/attr/builtin.rs5
-rw-r--r--src/libsyntax/feature_gate/check.rs22
-rw-r--r--src/libsyntax/mut_visit.rs4
-rw-r--r--src/libsyntax/print/pprust.rs28
-rw-r--r--src/libsyntax_ext/asm.rs38
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs7
-rw-r--r--src/libsyntax_pos/symbol.rs1
-rw-r--r--src/test/run-make-fulldeps/issue-19371/foo.rs3
-rw-r--r--src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs3
-rw-r--r--src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs15
-rw-r--r--src/test/ui-fulldeps/issue-40001.rs5
-rw-r--r--src/test/ui-fulldeps/plugin-attr-register-deny.rs21
-rw-r--r--src/test/ui-fulldeps/plugin-attr-register-deny.stderr34
-rw-r--r--src/test/ui/asm/asm-literal-escaping.rs12
-rw-r--r--src/test/ui/asm/asm-parse-errors.stderr10
-rw-r--r--src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs11
-rw-r--r--src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr8
-rw-r--r--src/test/ui/lint/dead-code/lint-dead-code-4.rs10
-rw-r--r--src/test/ui/lint/dead-code/lint-dead-code-4.stderr10
-rw-r--r--src/test/ui/parser/issue-63116.rs3
-rw-r--r--src/test/ui/parser/issue-63116.stderr24
-rw-r--r--src/test/ui/proc-macro/span-preservation.rs20
-rw-r--r--src/test/ui/proc-macro/span-preservation.stderr50
-rw-r--r--src/test/ui/union/union-fields-1.rs8
-rw-r--r--src/test/ui/union/union-fields-1.stderr8
-rw-r--r--src/test/ui/union/union-lint-dead-code.rs2
-rw-r--r--src/test/ui/union/union-lint-dead-code.stderr2
63 files changed, 472 insertions, 461 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f135a94ef7d..2ecb38851e7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3522,6 +3522,7 @@ dependencies = [
  "rustc",
  "rustc_codegen_utils",
  "rustc_data_structures",
+ "rustc_error_codes",
  "rustc_errors",
  "rustc_interface",
  "rustc_lint",
@@ -3595,7 +3596,6 @@ dependencies = [
  "rustc_codegen_ssa",
  "rustc_codegen_utils",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_incremental",
  "rustc_lint",
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index 4363314dc45..07e4358d644 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -1333,10 +1333,9 @@ impl<T> Vec<T> {
 
     /// Splits the collection into two at the given index.
     ///
-    /// Returns a newly allocated `Self`. `self` contains elements `[0, at)`,
-    /// and the returned `Self` contains elements `[at, len)`.
-    ///
-    /// Note that the capacity of `self` does not change.
+    /// Returns a newly allocated vector containing the elements in the range
+    /// `[at, len)`. After the call, the original vector will be left containing
+    /// the elements `[0, at)` with its previous capacity unchanged.
     ///
     /// # Panics
     ///
diff --git a/src/libcore/macros.rs b/src/libcore/macros/mod.rs
index d6b6e26436f..7f27e62fb15 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros/mod.rs
@@ -1,6 +1,4 @@
-/// Panics the current thread.
-///
-/// For details, see `std::macros`.
+#[doc(include = "panic.md")]
 #[macro_export]
 #[allow_internal_unstable(core_panic,
     // FIXME(anp, eddyb) `core_intrinsics` is used here to allow calling
diff --git a/src/libcore/macros/panic.md b/src/libcore/macros/panic.md
new file mode 100644
index 00000000000..3ecfc43be04
--- /dev/null
+++ b/src/libcore/macros/panic.md
@@ -0,0 +1,47 @@
+Panics the current thread.
+
+This allows a program to terminate immediately and provide feedback
+to the caller of the program. `panic!` should be used when a program reaches
+an unrecoverable state.
+
+This macro is the perfect way to assert conditions in example code and in
+tests. `panic!` is closely tied with the `unwrap` method of both [`Option`]
+and [`Result`][runwrap] enums. Both implementations call `panic!` when they are set
+to None or Err variants.
+
+This macro is used to inject panic into a Rust thread, causing the thread to
+panic entirely. Each thread's panic can be reaped as the `Box<Any>` type,
+and the single-argument form of the `panic!` macro will be the value which
+is transmitted.
+
+[`Result`] enum is often a better solution for recovering from errors than
+using the `panic!` macro. This macro should be used to avoid proceeding using
+incorrect values, such as from external sources. Detailed information about
+error handling is found in the [book].
+
+The multi-argument form of this macro panics with a string and has the
+[`format!`] syntax for building a string.
+
+See also the macro [`compile_error!`], for raising errors during compilation.
+
+[runwrap]: ../std/result/enum.Result.html#method.unwrap
+[`Option`]: ../std/option/enum.Option.html#method.unwrap
+[`Result`]: ../std/result/enum.Result.html
+[`format!`]: ../std/macro.format.html
+[`compile_error!`]: ../std/macro.compile_error.html
+[book]: ../book/ch09-00-error-handling.html
+
+# Current implementation
+
+If the main thread panics it will terminate all your threads and end your
+program with code `101`.
+
+# Examples
+
+```should_panic
+# #![allow(unreachable_code)]
+panic!();
+panic!("this is a terrible mistake!");
+panic!(4); // panic with the value of 4 to be collected elsewhere
+panic!("this is a {} {message}", "fancy", message = "message");
+```
diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs
index dc7c36ff03c..fff010385c3 100644
--- a/src/libcore/mem/mod.rs
+++ b/src/libcore/mem/mod.rs
@@ -744,11 +744,11 @@ pub fn drop<T>(_x: T) { }
 ///     bar: u8,
 /// }
 ///
-/// let foo_slice = [10u8];
+/// let foo_array = [10u8];
 ///
 /// unsafe {
-///     // Copy the data from 'foo_slice' and treat it as a 'Foo'
-///     let mut foo_struct: Foo = mem::transmute_copy(&foo_slice);
+///     // Copy the data from 'foo_array' and treat it as a 'Foo'
+///     let mut foo_struct: Foo = mem::transmute_copy(&foo_array);
 ///     assert_eq!(foo_struct.bar, 10);
 ///
 ///     // Modify the copied data
@@ -756,8 +756,8 @@ pub fn drop<T>(_x: T) { }
 ///     assert_eq!(foo_struct.bar, 20);
 /// }
 ///
-/// // The contents of 'foo_slice' should not have changed
-/// assert_eq!(foo_slice, [10]);
+/// // The contents of 'foo_array' should not have changed
+/// assert_eq!(foo_array, [10]);
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs
index 5f345c2133f..d97a7a8a87d 100644
--- a/src/libpanic_unwind/lib.rs
+++ b/src/libpanic_unwind/lib.rs
@@ -39,11 +39,6 @@ cfg_if::cfg_if! {
     if #[cfg(miri)] {
         #[path = "miri.rs"]
         mod imp;
-        // On MSVC we need the SEH lang items as well...
-        // This should match the conditions of the `seh.rs` import below.
-        #[cfg(all(target_env = "msvc", not(target_arch = "aarch64")))]
-        #[allow(unused)]
-        mod seh;
     } else if #[cfg(target_os = "emscripten")] {
         #[path = "emcc.rs"]
         mod imp;
diff --git a/src/libpanic_unwind/miri.rs b/src/libpanic_unwind/miri.rs
index 254a9383b42..f26c42fd4bc 100644
--- a/src/libpanic_unwind/miri.rs
+++ b/src/libpanic_unwind/miri.rs
@@ -1,3 +1,5 @@
+#![allow(nonstandard_style)]
+
 use core::any::Any;
 use alloc::boxed::Box;
 
@@ -13,7 +15,6 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
     Box::from_raw(ptr)
 }
 
-
 // This is required by the compiler to exist (e.g., it's a lang item),
 // but is never used by Miri. Therefore, we just use a stub here
 #[lang = "eh_personality"]
@@ -21,3 +22,21 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
 fn rust_eh_personality() {
     unsafe { core::intrinsics::abort() }
 }
+
+// The rest is required on *some* targets to exist (specifically, MSVC targets that use SEH).
+// We just add it on all targets. Copied from `seh.rs`.
+#[repr(C)]
+pub struct _TypeDescriptor {
+    pub pVFTable: *const u8,
+    pub spare: *mut u8,
+    pub name: [u8; 11],
+}
+
+const TYPE_NAME: [u8; 11] = *b"rust_panic\0";
+
+#[cfg_attr(not(test), lang = "eh_catch_typeinfo")]
+static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
+    pVFTable: core::ptr::null(),
+    spare: core::ptr::null_mut(),
+    name: TYPE_NAME,
+};
diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs
index 025494e3fd7..a1ad11580db 100644
--- a/src/librustc/hir/def.rs
+++ b/src/librustc/hir/def.rs
@@ -42,8 +42,6 @@ pub enum NonMacroAttrKind {
     DeriveHelper,
     /// Single-segment custom attribute registered with `#[register_attr]`.
     Registered,
-    /// Single-segment custom attribute registered by a legacy plugin (`register_attribute`).
-    LegacyPluginHelper,
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
@@ -330,7 +328,6 @@ impl NonMacroAttrKind {
             NonMacroAttrKind::Tool => "tool attribute",
             NonMacroAttrKind::DeriveHelper => "derive helper attribute",
             NonMacroAttrKind::Registered => "explicitly registered attribute",
-            NonMacroAttrKind::LegacyPluginHelper => "legacy plugin helper attribute",
         }
     }
 
@@ -345,8 +342,7 @@ impl NonMacroAttrKind {
     pub fn is_used(self) -> bool {
         match self {
             NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper => true,
-            NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered |
-            NonMacroAttrKind::LegacyPluginHelper => false,
+            NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered  => false,
         }
     }
 }
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index ef6a6ae23dc..12f6f66e96b 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1219,7 +1219,7 @@ impl<'a> LoweringContext<'a> {
                                     ImplTraitContext::disallowed(),
                                 ),
                                 unsafety: f.unsafety,
-                                abi: this.lower_abi(f.abi),
+                                abi: this.lower_extern(f.ext),
                                 decl: this.lower_fn_decl(&f.decl, None, false, None),
                                 param_names: this.lower_fn_params_to_names(&f.decl),
                             }))
diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs
index 4cd42927868..f689e7f9622 100644
--- a/src/librustc/hir/lowering/item.rs
+++ b/src/librustc/hir/lowering/item.rs
@@ -735,7 +735,7 @@ impl LoweringContext<'_> {
 
     fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod {
         hir::ForeignMod {
-            abi: self.lower_abi(fm.abi),
+            abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
             items: fm.items
                 .iter()
                 .map(|x| self.lower_foreign_item(x))
@@ -1283,18 +1283,26 @@ impl LoweringContext<'_> {
             unsafety: h.unsafety,
             asyncness: self.lower_asyncness(h.asyncness.node),
             constness: h.constness.node,
-            abi: self.lower_abi(h.abi),
+            abi: self.lower_extern(h.ext),
         }
     }
 
-    pub(super) fn lower_abi(&mut self, abi: Abi) -> abi::Abi {
-        abi::lookup(&abi.symbol.as_str()).unwrap_or_else(|| {
+    pub(super) fn lower_abi(&mut self, abi: StrLit) -> abi::Abi {
+        abi::lookup(&abi.symbol_unescaped.as_str()).unwrap_or_else(|| {
             self.error_on_invalid_abi(abi);
             abi::Abi::Rust
         })
     }
 
-    fn error_on_invalid_abi(&self, abi: Abi) {
+    pub(super) fn lower_extern(&mut self, ext: Extern) -> abi::Abi {
+        match ext {
+            Extern::None => abi::Abi::Rust,
+            Extern::Implicit => abi::Abi::C,
+            Extern::Explicit(abi) => self.lower_abi(abi),
+        }
+    }
+
+    fn error_on_invalid_abi(&self, abi: StrLit) {
         struct_span_err!(
             self.sess,
             abi.span,
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 4fbc8da9cbf..1af20188ab5 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -21,11 +21,10 @@ use errors::emitter::{Emitter, EmitterWriter};
 use errors::emitter::HumanReadableErrorType;
 use errors::annotate_snippet_emitter_writer::{AnnotateSnippetEmitterWriter};
 use syntax::edition::Edition;
-use syntax::feature_gate::{self, AttributeType};
+use syntax::feature_gate;
 use errors::json::JsonEmitter;
 use syntax::source_map;
 use syntax::sess::{ParseSess, ProcessCfgMod};
-use syntax::symbol::Symbol;
 use syntax_pos::{MultiSpan, Span};
 
 use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple};
@@ -79,7 +78,6 @@ pub struct Session {
     /// in order to avoid redundantly verbose output (Issue #24690, #44953).
     pub one_time_diagnostics: Lock<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
     pub plugin_llvm_passes: OneThread<RefCell<Vec<String>>>,
-    pub plugin_attributes: Lock<Vec<(Symbol, AttributeType)>>,
     pub crate_types: Once<Vec<config::CrateType>>,
     /// The `crate_disambiguator` is constructed out of all the `-C metadata`
     /// arguments passed to the compiler. Its value together with the crate-name
@@ -1039,12 +1037,11 @@ pub fn build_session_with_source_map(
 
     let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace;
 
-    let emitter = match diagnostics_output {
-        DiagnosticOutput::Default => default_emitter(&sopts, registry, &source_map, None),
-        DiagnosticOutput::Raw(write) => {
-            default_emitter(&sopts, registry, &source_map, Some(write))
-        }
+    let write_dest = match diagnostics_output {
+        DiagnosticOutput::Default => None,
+        DiagnosticOutput::Raw(write) => Some(write),
     };
+    let emitter = default_emitter(&sopts, registry, &source_map, write_dest);
 
     let diagnostic_handler = errors::Handler::with_emitter_and_flags(
         emitter,
@@ -1166,7 +1163,6 @@ fn build_session_(
         working_dir,
         one_time_diagnostics: Default::default(),
         plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())),
-        plugin_attributes: Lock::new(Vec::new()),
         crate_types: Once::new(),
         crate_disambiguator: Once::new(),
         features: Once::new(),
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index f1565a2bd0a..ff673e52b60 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -26,6 +26,7 @@ rustc_plugin = { path = "../librustc_plugin/deprecated" } # To get this in the s
 rustc_plugin_impl = { path = "../librustc_plugin" }
 rustc_save_analysis = { path = "../librustc_save_analysis" }
 rustc_codegen_utils = { path = "../librustc_codegen_utils" }
+rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_interface = { path = "../librustc_interface" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 rustc_resolve = { path = "../librustc_resolve" }
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index d4f796ee3a7..ef638464adc 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -40,7 +40,7 @@ use rustc::ty::TyCtxt;
 use rustc::util::common::{set_time_depth, time, print_time_passes_entry, ErrorReported};
 use rustc_metadata::locator;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
-use errors::PResult;
+use errors::{PResult, registry::Registry};
 use rustc_interface::interface;
 use rustc_interface::util::get_codegen_sysroot;
 use rustc_data_structures::sync::SeqCst;
@@ -140,6 +140,10 @@ impl Callbacks for TimePassesCallbacks {
     }
 }
 
+pub fn diagnostics_registry() -> Registry {
+    Registry::new(&rustc_error_codes::DIAGNOSTICS)
+}
+
 // Parse args and run the compiler. This is the primary entry point for rustc.
 // See comments on CompilerCalls below for details about the callbacks argument.
 // The FileLoader provides a way to load files from sources other than the file system.
@@ -182,13 +186,14 @@ pub fn run_compiler(
             lint_caps: Default::default(),
             register_lints: None,
             override_queries: None,
+            registry: diagnostics_registry(),
         };
         callbacks.config(&mut config);
         config
     };
 
     if let Some(ref code) = matches.opt_str("explain") {
-        handle_explain(code, sopts.error_format);
+        handle_explain(diagnostics_registry(), code, sopts.error_format);
         return Ok(());
     }
 
@@ -261,6 +266,7 @@ pub fn run_compiler(
         lint_caps: Default::default(),
         register_lints: None,
         override_queries: None,
+        registry: diagnostics_registry(),
     };
 
     callbacks.config(&mut config);
@@ -510,15 +516,13 @@ fn stdout_isatty() -> bool {
     }
 }
 
-fn handle_explain(code: &str,
-                  output: ErrorOutputType) {
-    let descriptions = rustc_interface::util::diagnostics_registry();
+fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
     let normalised = if code.starts_with("E") {
         code.to_string()
     } else {
         format!("E{0:0>4}", code)
     };
-    match descriptions.find_description(&normalised) {
+    match registry.find_description(&normalised) {
         Some(ref description) => {
             let mut is_in_code_block = false;
             let mut text = String::new();
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index ffefe51f854..428cecf13a3 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -7,8 +7,7 @@
 // Error messages' format must follow the RFC 1567 available here:
 // https://github.com/rust-lang/rfcs/pull/1567
 
-crate::register_diagnostics! {
-
+register_diagnostics! {
 E0001: include_str!("./error_codes/E0001.md"),
 E0002: include_str!("./error_codes/E0002.md"),
 E0004: include_str!("./error_codes/E0004.md"),
diff --git a/src/librustc_error_codes/lib.rs b/src/librustc_error_codes/lib.rs
index 36b1518c869..14210fd69ad 100644
--- a/src/librustc_error_codes/lib.rs
+++ b/src/librustc_error_codes/lib.rs
@@ -1,19 +1,14 @@
-//! This library is used to gather all error codes into one place. The goal
-//! being to make their maintenance easier.
+//! This library is used to gather all error codes into one place,
+//! the goal being to make their maintenance easier.
 
-#[macro_export]
 macro_rules! register_diagnostics {
-    ($($ecode:ident: $message:expr,)*) => (
-        $crate::register_diagnostics!{$($ecode:$message,)* ;}
-    );
-
     ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => (
         pub static DIAGNOSTICS: &[(&str, &str)] = &[
             $( (stringify!($ecode), $message), )*
         ];
 
         $(
-            pub const $ecode: &str = $message;
+            pub const $ecode: () = ();
         )*
         $(
             pub const $code: () = ();
diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml
index b16cfe9efa7..de59882bbdf 100644
--- a/src/librustc_interface/Cargo.toml
+++ b/src/librustc_interface/Cargo.toml
@@ -34,7 +34,6 @@ rustc_errors = { path = "../librustc_errors" }
 rustc_plugin = { path = "../librustc_plugin", package = "rustc_plugin_impl" }
 rustc_privacy = { path = "../librustc_privacy" }
 rustc_resolve = { path = "../librustc_resolve" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 tempfile = "3.0.5"
 once_cell = "1"
 
diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs
index fae4eb48c4a..c153de7103a 100644
--- a/src/librustc_interface/interface.rs
+++ b/src/librustc_interface/interface.rs
@@ -11,6 +11,7 @@ use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_data_structures::OnDrop;
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
+use rustc_errors::registry::Registry;
 use rustc_parse::new_parser_from_source_str;
 use rustc::ty;
 use std::path::PathBuf;
@@ -141,12 +142,16 @@ pub struct Config {
     /// The second parameter is local providers and the third parameter is external providers.
     pub override_queries:
         Option<fn(&Session, &mut ty::query::Providers<'_>, &mut ty::query::Providers<'_>)>,
+
+    /// Registry of diagnostics codes.
+    pub registry: Registry,
 }
 
-pub fn run_compiler_in_existing_thread_pool<F, R>(config: Config, f: F) -> R
-where
-    F: FnOnce(&Compiler) -> R,
-{
+pub fn run_compiler_in_existing_thread_pool<R>(
+    config: Config,
+    f: impl FnOnce(&Compiler) -> R,
+) -> R {
+    let registry = &config.registry;
     let (sess, codegen_backend, source_map) = util::create_session(
         config.opts,
         config.crate_cfg,
@@ -154,6 +159,7 @@ where
         config.file_loader,
         config.input_path.clone(),
         config.lint_caps,
+        registry.clone(),
     );
 
     let compiler = Compiler {
@@ -171,17 +177,13 @@ where
     };
 
     let _sess_abort_error = OnDrop(|| {
-        compiler.sess.diagnostic().print_error_count(&util::diagnostics_registry());
+        compiler.sess.diagnostic().print_error_count(registry);
     });
 
     f(&compiler)
 }
 
-pub fn run_compiler<F, R>(mut config: Config, f: F) -> R
-where
-    F: FnOnce(&Compiler) -> R + Send,
-    R: Send,
-{
+pub fn run_compiler<R: Send>(mut config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R {
     let stderr = config.stderr.take();
     util::spawn_thread_pool(
         config.opts.edition,
@@ -191,11 +193,7 @@ where
     )
 }
 
-pub fn default_thread_pool<F, R>(edition: edition::Edition, f: F) -> R
-where
-    F: FnOnce() -> R + Send,
-    R: Send,
-{
+pub fn default_thread_pool<R: Send>(edition: edition::Edition, f: impl FnOnce() -> R + Send) -> R {
     // the 1 here is duplicating code in config.opts.debugging_opts.threads
     // which also defaults to 1; it ultimately doesn't matter as the default
     // isn't threaded, and just ignores this parameter
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 83b936dd7aa..86d58bfe8bd 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -240,15 +240,8 @@ pub fn register_plugins<'a>(
         }
     });
 
-    let Registry {
-        syntax_exts,
-        llvm_passes,
-        attributes,
-        ..
-    } = registry;
-
+    let Registry { syntax_exts, llvm_passes, .. } = registry;
     *sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
-    *sess.plugin_attributes.borrow_mut() = attributes;
 
     Ok((krate, PluginInfo { syntax_exts }, Lrc::new(lint_store)))
 }
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index a5653a21b31..2b4320c04e6 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -15,7 +15,6 @@ use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 use rustc_errors::registry::Registry;
 use rustc_metadata::dynamic_lib::DynamicLibrary;
 use rustc_resolve::{self, Resolver};
-use rustc_error_codes;
 use std::env;
 use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
 use std::io::{self, Write};
@@ -37,15 +36,6 @@ use syntax_pos::edition::Edition;
 #[cfg(not(parallel_compiler))]
 use std::{thread, panic};
 
-pub fn diagnostics_registry() -> Registry {
-    let mut all_errors = Vec::new();
-    all_errors.extend_from_slice(&rustc_error_codes::DIAGNOSTICS);
-    // FIXME: need to figure out a way to get these back in here
-    // all_errors.extend_from_slice(get_codegen_backend(sess).diagnostics());
-
-    Registry::new(&all_errors)
-}
-
 /// Adds `target_feature = "..."` cfgs for a variety of platform
 /// specific features (SSE, NEON etc.).
 ///
@@ -77,9 +67,8 @@ pub fn create_session(
     file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
     input_path: Option<PathBuf>,
     lint_caps: FxHashMap<lint::LintId, lint::Level>,
+    descriptions: Registry,
 ) -> (Lrc<Session>, Lrc<Box<dyn CodegenBackend>>, Lrc<SourceMap>) {
-    let descriptions = diagnostics_registry();
-
     let loader = file_loader.unwrap_or(box RealFileLoader);
     let source_map = Lrc::new(SourceMap::with_file_loader(
         loader,
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 642b8e3279d..9f293bdaa10 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -309,29 +309,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
             }
         }
 
-        let plugin_attributes = cx.sess().plugin_attributes.borrow();
-        for &(name, ty) in plugin_attributes.iter() {
-            if ty == AttributeType::Whitelisted && attr.check_name(name) {
-                debug!("{:?} (plugin attr) is whitelisted with ty {:?}", name, ty);
-                break;
-            }
-        }
-
-        let name = attr.name_or_empty();
         if !attr::is_used(attr) {
             debug!("emitting warning for: {:?}", attr);
             cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
             // Is it a builtin attribute that must be used at the crate level?
-            let known_crate = attr_info.map(|&&(_, ty, ..)| {
-                    ty == AttributeType::CrateLevel
-            }).unwrap_or(false);
-
-            // Has a plugin registered this attribute as one that must be used at
-            // the crate level?
-            let plugin_crate = plugin_attributes.iter()
-                .find(|&&(x, t)| name == x && AttributeType::CrateLevel == t)
-                .is_some();
-            if known_crate || plugin_crate {
+            if attr_info.map_or(false, |(_, ty, ..)| ty == &AttributeType::CrateLevel) {
                 let msg = match attr.style {
                     ast::AttrStyle::Outer => {
                         "crate-level attribute should be an inner attribute: add an exclamation \
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index dadb91f8b3c..a56a7bf1802 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -778,13 +778,12 @@ impl<'a> Parser<'a> {
 
         macro_rules! parse_lit {
             () => {
-                match self.parse_lit() {
-                    Ok(literal) => {
+                match self.parse_opt_lit() {
+                    Some(literal) => {
                         hi = self.prev_span;
                         ex = ExprKind::Lit(literal);
                     }
-                    Err(mut err) => {
-                        err.cancel();
+                    None => {
                         return Err(self.expected_expression_found());
                     }
                 }
@@ -1074,11 +1073,39 @@ impl<'a> Parser<'a> {
         self.maybe_recover_from_bad_qpath(expr, true)
     }
 
-    /// Matches `lit = true | false | token_lit`.
+    /// Returns a string literal if the next token is a string literal.
+    /// In case of error returns `Some(lit)` if the next token is a literal with a wrong kind,
+    /// and returns `None` if the next token is not literal at all.
+    pub fn parse_str_lit(&mut self) -> Result<ast::StrLit, Option<Lit>> {
+        match self.parse_opt_lit() {
+            Some(lit) => match lit.kind {
+                ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit {
+                    style,
+                    symbol: lit.token.symbol,
+                    suffix: lit.token.suffix,
+                    span: lit.span,
+                    symbol_unescaped,
+                }),
+                _ => Err(Some(lit)),
+            }
+            None => Err(None),
+        }
+    }
+
     pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> {
+        self.parse_opt_lit().ok_or_else(|| {
+            let msg = format!("unexpected token: {}", self.this_token_descr());
+            self.span_fatal(self.token.span, &msg)
+        })
+    }
+
+    /// Matches `lit = true | false | token_lit`.
+    /// Returns `None` if the next token is not a literal.
+    pub(super) fn parse_opt_lit(&mut self) -> Option<Lit> {
         let mut recovered = None;
         if self.token == token::Dot {
-            // Attempt to recover `.4` as `0.4`.
+            // Attempt to recover `.4` as `0.4`. We don't currently have any syntax where
+            // dot would follow an optional literal, so we do this unconditionally.
             recovered = self.look_ahead(1, |next_token| {
                 if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix })
                         = next_token.kind {
@@ -1107,11 +1134,10 @@ impl<'a> Parser<'a> {
         match Lit::from_token(token) {
             Ok(lit) => {
                 self.bump();
-                Ok(lit)
+                Some(lit)
             }
             Err(LitError::NotLiteral) => {
-                let msg = format!("unexpected token: {}", self.this_token_descr());
-                Err(self.span_fatal(token.span, &msg))
+                None
             }
             Err(err) => {
                 let span = token.span;
@@ -1120,18 +1146,18 @@ impl<'a> Parser<'a> {
                     _ => unreachable!(),
                 };
                 self.bump();
-                self.error_literal_from_token(err, lit, span);
+                self.report_lit_error(err, lit, span);
                 // Pack possible quotes and prefixes from the original literal into
                 // the error literal's symbol so they can be pretty-printed faithfully.
                 let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None);
                 let symbol = Symbol::intern(&suffixless_lit.to_string());
                 let lit = token::Lit::new(token::Err, symbol, lit.suffix);
-                Lit::from_lit_token(lit, span).map_err(|_| unreachable!())
+                Some(Lit::from_lit_token(lit, span).unwrap_or_else(|_| unreachable!()))
             }
         }
     }
 
-    fn error_literal_from_token(&self, err: LitError, lit: token::Lit, span: Span) {
+    fn report_lit_error(&self, err: LitError, lit: token::Lit, span: Span) {
         // Checks if `s` looks like i32 or u1234 etc.
         fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
             s.len() > 1
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 73099169879..20b96d5cd62 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -3,9 +3,9 @@ use super::diagnostics::{Error, dummy_arg, ConsumeClosingDelim};
 
 use crate::maybe_whole;
 
-use syntax::ast::{self, Abi, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item};
+use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item};
 use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind};
-use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness};
+use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit};
 use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
 use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, VariantData, StructField};
 use syntax::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
@@ -105,7 +105,7 @@ impl<'a> Parser<'a> {
                 return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?));
             }
 
-            let abi = self.parse_opt_abi()?;
+            let abi = self.parse_abi();
 
             if self.eat_keyword(kw::Fn) {
                 // EXTERN FUNCTION ITEM
@@ -114,7 +114,7 @@ impl<'a> Parser<'a> {
                     unsafety: Unsafety::Normal,
                     asyncness: respan(fn_span, IsAsync::NotAsync),
                     constness: respan(fn_span, Constness::NotConst),
-                    abi,
+                    ext: Extern::from_abi(abi),
                 };
                 return self.parse_item_fn(lo, vis, attrs, header);
             } else if self.check(&token::OpenDelim(token::Brace)) {
@@ -143,14 +143,14 @@ impl<'a> Parser<'a> {
                 if self.check_keyword(kw::Extern) {
                     self.sess.gated_spans.gate(sym::const_extern_fn, lo.to(self.token.span));
                 }
-                let abi = self.parse_extern_abi()?;
+                let ext = self.parse_extern()?;
                 self.bump(); // `fn`
 
                 let header = FnHeader {
                     unsafety,
                     asyncness: respan(const_span, IsAsync::NotAsync),
                     constness: respan(const_span, Constness::Const),
-                    abi,
+                    ext,
                 };
                 return self.parse_item_fn(lo, vis, attrs, header);
             }
@@ -193,7 +193,7 @@ impl<'a> Parser<'a> {
                     unsafety,
                     asyncness,
                     constness: respan(fn_span, Constness::NotConst),
-                    abi: Abi::new(sym::Rust, fn_span),
+                    ext: Extern::None,
                 };
                 return self.parse_item_fn(lo, vis, attrs, header);
             }
@@ -230,7 +230,7 @@ impl<'a> Parser<'a> {
                 unsafety: Unsafety::Normal,
                 asyncness: respan(fn_span, IsAsync::NotAsync),
                 constness: respan(fn_span, Constness::NotConst),
-                abi: Abi::new(sym::Rust, fn_span),
+                ext: Extern::None,
             };
             return self.parse_item_fn(lo, vis, attrs, header);
         }
@@ -242,14 +242,14 @@ impl<'a> Parser<'a> {
             self.bump(); // `unsafe`
             // `{` is also expected after `unsafe`; in case of error, include it in the diagnostic.
             self.check(&token::OpenDelim(token::Brace));
-            let abi = self.parse_extern_abi()?;
+            let ext = self.parse_extern()?;
             self.expect_keyword(kw::Fn)?;
             let fn_span = self.prev_span;
             let header = FnHeader {
                 unsafety: Unsafety::Unsafe,
                 asyncness: respan(fn_span, IsAsync::NotAsync),
                 constness: respan(fn_span, Constness::NotConst),
-                abi,
+                ext,
             };
             return self.parse_item_fn(lo, vis, attrs, header);
         }
@@ -1100,7 +1100,7 @@ impl<'a> Parser<'a> {
     fn parse_item_foreign_mod(
         &mut self,
         lo: Span,
-        abi: Abi,
+        abi: Option<StrLit>,
         visibility: Visibility,
         mut attrs: Vec<Attribute>,
         extern_sp: Span,
@@ -1775,9 +1775,16 @@ impl<'a> Parser<'a> {
         attrs: Vec<Attribute>,
         header: FnHeader,
     ) -> PResult<'a, Option<P<Item>>> {
+        let is_c_abi = match header.ext {
+            ast::Extern::None => false,
+            ast::Extern::Implicit => true,
+            ast::Extern::Explicit(abi) => abi.symbol_unescaped == sym::C,
+        };
         let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
             is_self_allowed: false,
-            allow_c_variadic: header.abi.symbol == sym::C && header.unsafety == Unsafety::Unsafe,
+            // FIXME: Parsing should not depend on ABI or unsafety and
+            // the variadic parameter should always be parsed.
+            allow_c_variadic: is_c_abi && header.unsafety == Unsafety::Unsafe,
             is_name_required: |_| true,
         })?;
         let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
@@ -1905,11 +1912,11 @@ impl<'a> Parser<'a> {
         }
         let asyncness = respan(self.prev_span, asyncness);
         let unsafety = self.parse_unsafety();
-        let (constness, unsafety, abi) = if is_const_fn {
-            (respan(const_span, Constness::Const), unsafety, Abi::default())
+        let (constness, unsafety, ext) = if is_const_fn {
+            (respan(const_span, Constness::Const), unsafety, Extern::None)
         } else {
-            let abi = self.parse_extern_abi()?;
-            (respan(self.prev_span, Constness::NotConst), unsafety, abi)
+            let ext = self.parse_extern()?;
+            (respan(self.prev_span, Constness::NotConst), unsafety, ext)
         };
         if !self.eat_keyword(kw::Fn) {
             // It is possible for `expect_one_of` to recover given the contents of
@@ -1917,7 +1924,7 @@ impl<'a> Parser<'a> {
             // account for this.
             if !self.expect_one_of(&[], &[])? { unreachable!() }
         }
-        Ok(FnHeader { constness, unsafety, asyncness, abi })
+        Ok(FnHeader { constness, unsafety, asyncness, ext })
     }
 
     /// Parse the "signature", including the identifier, parameters, and generics of a function.
diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs
index f62f0c9a268..d5ec4611498 100644
--- a/src/librustc_parse/parser/mod.rs
+++ b/src/librustc_parse/parser/mod.rs
@@ -15,8 +15,8 @@ use crate::{Directory, DirectoryOwnership};
 use crate::lexer::UnmatchedBrace;
 
 use syntax::ast::{
-    self, Abi, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident,
-    IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety,
+    self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, StrLit,
+    IsAsync, MacDelimiter, Mutability, Visibility, VisibilityKind, Unsafety,
 };
 
 use syntax::print::pprust;
@@ -1212,40 +1212,34 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses `extern string_literal?`.
-    /// If `extern` is not found, the Rust ABI is used.
-    /// If `extern` is found and a `string_literal` does not follow, the C ABI is used.
-    fn parse_extern_abi(&mut self) -> PResult<'a, Abi> {
+    fn parse_extern(&mut self) -> PResult<'a, Extern> {
         Ok(if self.eat_keyword(kw::Extern) {
-            self.parse_opt_abi()?
+            Extern::from_abi(self.parse_abi())
         } else {
-            Abi::default()
+            Extern::None
         })
     }
 
     /// Parses a string literal as an ABI spec.
-    /// If one is not found, the "C" ABI is used.
-    fn parse_opt_abi(&mut self) -> PResult<'a, Abi> {
-        let span = if self.token.can_begin_literal_or_bool() {
-            let ast::Lit { span, kind, .. } = self.parse_lit()?;
-            match kind {
-                ast::LitKind::Str(symbol, _) => return Ok(Abi::new(symbol, span)),
-                ast::LitKind::Err(_) => {}
+    fn parse_abi(&mut self) -> Option<StrLit> {
+        match self.parse_str_lit() {
+            Ok(str_lit) => Some(str_lit),
+            Err(Some(lit)) => match lit.kind {
+                ast::LitKind::Err(_) => None,
                 _ => {
-                    self.struct_span_err(span, "non-string ABI literal")
+                    self.struct_span_err(lit.span, "non-string ABI literal")
                         .span_suggestion(
-                            span,
+                            lit.span,
                             "specify the ABI with a string literal",
                             "\"C\"".to_string(),
                             Applicability::MaybeIncorrect,
                         )
                         .emit();
+                    None
                 }
             }
-            span
-        } else {
-            self.prev_span
-        };
-        Ok(Abi::new(sym::C, span))
+            Err(None) => None,
+        }
     }
 
     /// We are parsing `async fn`. If we are on Rust 2015, emit an error.
@@ -1337,34 +1331,6 @@ impl<'a> Parser<'a> {
             self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace) ||
                                    *t == token::BinOp(token::Star))
     }
-
-    fn parse_optional_str(&mut self) -> Option<(Symbol, ast::StrStyle, Option<ast::Name>)> {
-        let ret = match self.token.kind {
-            token::Literal(token::Lit { kind: token::Str, symbol, suffix }) =>
-                (symbol, ast::StrStyle::Cooked, suffix),
-            token::Literal(token::Lit { kind: token::StrRaw(n), symbol, suffix }) =>
-                (symbol, ast::StrStyle::Raw(n), suffix),
-            _ => return None
-        };
-        self.bump();
-        Some(ret)
-    }
-
-    pub fn parse_str(&mut self) -> PResult<'a, (Symbol, StrStyle)> {
-        match self.parse_optional_str() {
-            Some((s, style, suf)) => {
-                let sp = self.prev_span;
-                self.expect_no_suffix(sp, "a string literal", suf);
-                Ok((s, style))
-            }
-            _ => {
-                let msg = "expected string literal";
-                let mut err = self.fatal(msg);
-                err.span_label(self.token.span, msg);
-                Err(err)
-            }
-        }
-    }
 }
 
 crate fn make_unclosed_delims_error(
diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs
index 4c7d1006183..8e6bc29be52 100644
--- a/src/librustc_parse/parser/ty.rs
+++ b/src/librustc_parse/parser/ty.rs
@@ -287,7 +287,7 @@ impl<'a> Parser<'a> {
         */
 
         let unsafety = self.parse_unsafety();
-        let abi = self.parse_extern_abi()?;
+        let ext = self.parse_extern()?;
         self.expect_keyword(kw::Fn)?;
         let cfg = ParamCfg {
             is_self_allowed: false,
@@ -296,7 +296,7 @@ impl<'a> Parser<'a> {
         };
         let decl = self.parse_fn_decl(cfg, false)?;
         Ok(TyKind::BareFn(P(BareFnTy {
-            abi,
+            ext,
             unsafety,
             generic_params,
             decl,
diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs
index 2aeec029cc3..db661e7f4d2 100644
--- a/src/librustc_passes/dead.rs
+++ b/src/librustc_passes/dead.rs
@@ -631,7 +631,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
 
     fn visit_struct_field(&mut self, field: &'tcx hir::StructField) {
         if self.should_warn_about_field(&field) {
-            self.warn_dead_code(field.hir_id, field.span, field.ident.name, "field", "used");
+            self.warn_dead_code(field.hir_id, field.span, field.ident.name, "field", "read");
         }
         intravisit::walk_struct_field(self, field);
     }
diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs
index 3f4b87a97c7..aa5ea80f0b0 100644
--- a/src/librustc_plugin/registry.rs
+++ b/src/librustc_plugin/registry.rs
@@ -7,7 +7,6 @@ use syntax_expand::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExten
 use syntax_expand::base::MacroExpanderFn;
 use syntax::symbol::Symbol;
 use syntax::ast;
-use syntax::feature_gate::AttributeType;
 use syntax_pos::Span;
 
 use std::borrow::ToOwned;
@@ -39,9 +38,6 @@ pub struct Registry<'a> {
 
     #[doc(hidden)]
     pub llvm_passes: Vec<String>,
-
-    #[doc(hidden)]
-    pub attributes: Vec<(Symbol, AttributeType)>,
 }
 
 impl<'a> Registry<'a> {
@@ -54,7 +50,6 @@ impl<'a> Registry<'a> {
             krate_span,
             syntax_exts: vec![],
             llvm_passes: vec![],
-            attributes: vec![],
         }
     }
 
@@ -98,12 +93,4 @@ impl<'a> Registry<'a> {
     pub fn register_llvm_pass(&mut self, name: &str) {
         self.llvm_passes.push(name.to_owned());
     }
-
-    /// Register an attribute with an attribute type.
-    ///
-    /// `Whitelisted` attributes will additionally not trigger the `unused_attribute`
-    /// lint. `CrateLevel` attributes will not be allowed on anything other than a crate.
-    pub fn register_attribute(&mut self, name: Symbol, ty: AttributeType) {
-        self.attributes.push((name, ty));
-    }
 }
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index f2858a62156..e134b8b92ac 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -437,15 +437,6 @@ impl<'a> Resolver<'a> {
                         }));
                     }
                 }
-                Scope::LegacyPluginHelpers => {
-                    let res = Res::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper);
-                    if filter_fn(res) {
-                        let plugin_attributes = this.session.plugin_attributes.borrow();
-                        suggestions.extend(plugin_attributes.iter().map(|(name, _)| {
-                            TypoSuggestion::from_res(*name, res)
-                        }));
-                    }
-                }
                 Scope::ExternPrelude => {
                     suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| {
                         let res = Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX));
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 0f410c623ba..8f6bb91f028 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -105,7 +105,6 @@ enum Scope<'a> {
     RegisteredAttrs,
     MacroUsePrelude,
     BuiltinAttrs,
-    LegacyPluginHelpers,
     ExternPrelude,
     ToolPrelude,
     StdLibPrelude,
@@ -1466,9 +1465,6 @@ impl<'a> Resolver<'a> {
         // 4b. "Standard library prelude" part implemented through `macro-use` (closed, controlled).
         // 4c. Standard library prelude (de-facto closed, controlled).
         // 6. Language prelude: builtin attributes (closed, controlled).
-        // 4-6. Legacy plugin helpers (open, not controlled). Similar to derive helpers,
-        //    but introduced by legacy plugins using `register_attribute`. Priority is somewhere
-        //    in prelude, not sure where exactly (creates ambiguities with any other prelude names).
 
         let rust_2015 = ident.span.rust_2015();
         let (ns, macro_kind, is_absolute_path) = match scope_set {
@@ -1498,7 +1494,6 @@ impl<'a> Resolver<'a> {
                 Scope::RegisteredAttrs => use_prelude,
                 Scope::MacroUsePrelude => use_prelude || rust_2015,
                 Scope::BuiltinAttrs => true,
-                Scope::LegacyPluginHelpers => use_prelude || rust_2015,
                 Scope::ExternPrelude => use_prelude || is_absolute_path,
                 Scope::ToolPrelude => use_prelude,
                 Scope::StdLibPrelude => use_prelude || ns == MacroNS,
@@ -1558,8 +1553,7 @@ impl<'a> Resolver<'a> {
                 }
                 Scope::RegisteredAttrs => Scope::MacroUsePrelude,
                 Scope::MacroUsePrelude => Scope::StdLibPrelude,
-                Scope::BuiltinAttrs => Scope::LegacyPluginHelpers,
-                Scope::LegacyPluginHelpers => break, // nowhere else to search
+                Scope::BuiltinAttrs => break, // nowhere else to search
                 Scope::ExternPrelude if is_absolute_path => break,
                 Scope::ExternPrelude => Scope::ToolPrelude,
                 Scope::ToolPrelude => Scope::StdLibPrelude,
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index cf549d5ba6f..4f687b5ba92 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -613,13 +613,6 @@ impl<'a> Resolver<'a> {
                 } else {
                     Err(Determinacy::Determined)
                 }
-                Scope::LegacyPluginHelpers => if this.session.plugin_attributes.borrow().iter()
-                                                     .any(|(name, _)| ident.name == *name) {
-                    let res = Res::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper);
-                    ok(res, DUMMY_SP, this.arenas)
-                } else {
-                    Err(Determinacy::Determined)
-                }
                 Scope::ExternPrelude => match this.extern_prelude_get(ident, !record_used) {
                     Some(binding) => Ok((binding, Flags::empty())),
                     None => Err(Determinacy::determined(
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 50dfac62024..255938a193c 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -30,9 +30,8 @@ use crate::{id_from_def_id, id_from_node_id, SaveContext};
 use rls_data::{SigElement, Signature};
 
 use rustc::hir::def::{Res, DefKind};
-use syntax::ast::{self, NodeId};
+use syntax::ast::{self, Extern, NodeId};
 use syntax::print::pprust;
-use syntax_pos::sym;
 
 pub fn item_signature(item: &ast::Item, scx: &SaveContext<'_, '_>) -> Option<Signature> {
     if !scx.config.signatures {
@@ -157,9 +156,11 @@ fn text_sig(text: String) -> Signature {
     }
 }
 
-fn push_abi(text: &mut String, abi: ast::Abi) {
-    if abi.symbol != sym::Rust {
-        text.push_str(&format!("extern \"{}\" ", abi.symbol));
+fn push_extern(text: &mut String, ext: Extern) {
+    match ext {
+        Extern::None => {}
+        Extern::Implicit => text.push_str("extern "),
+        Extern::Explicit(abi) => text.push_str(&format!("extern \"{}\" ", abi.symbol)),
     }
 }
 
@@ -237,7 +238,7 @@ impl Sig for ast::Ty {
                 if f.unsafety == ast::Unsafety::Unsafe {
                     text.push_str("unsafe ");
                 }
-                push_abi(&mut text, f.abi);
+                push_extern(&mut text, f.ext);
                 text.push_str("fn(");
 
                 let mut defs = vec![];
@@ -387,7 +388,7 @@ impl Sig for ast::Item {
                 if header.unsafety == ast::Unsafety::Unsafe {
                     text.push_str("unsafe ");
                 }
-                push_abi(&mut text, header.abi);
+                push_extern(&mut text, header.ext);
                 text.push_str("fn ");
 
                 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
@@ -936,7 +937,7 @@ fn make_method_signature(
     if m.header.unsafety == ast::Unsafety::Unsafe {
         text.push_str("unsafe ");
     }
-    push_abi(&mut text, m.header.abi);
+    push_extern(&mut text, m.header.ext);
     text.push_str("fn ");
 
     let mut sig = name_and_generics(text, 0, generics, id, ident, scx)?;
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 507732a9107..2b4ac7676fa 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -21,7 +21,6 @@ use syntax::feature_gate::UnstableFeatures;
 use errors::json::JsonEmitter;
 use syntax::symbol::sym;
 use syntax_pos::DUMMY_SP;
-use errors;
 use errors::emitter::{Emitter, EmitterWriter};
 
 use std::cell::RefCell;
@@ -341,6 +340,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
         lint_caps,
         register_lints: None,
         override_queries: None,
+        registry: rustc_driver::diagnostics_registry(),
     };
 
     interface::run_compiler_in_existing_thread_pool(config, |compiler| {
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 4f102dbf128..8bfaf98f086 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -23,8 +23,9 @@ extern crate getopts;
 extern crate env_logger;
 extern crate rustc;
 extern crate rustc_data_structures;
-extern crate rustc_index;
 extern crate rustc_driver;
+extern crate rustc_error_codes;
+extern crate rustc_index;
 extern crate rustc_resolve;
 extern crate rustc_lint;
 extern crate rustc_interface;
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index c483f6fb477..98e18d666f1 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -80,6 +80,7 @@ pub fn run(options: Options) -> i32 {
         lint_caps: Default::default(),
         register_lints: None,
         override_queries: None,
+        registry: rustc_driver::diagnostics_registry(),
     };
 
     let mut test_args = options.test_args.clone();
diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs
index d025a7d16f2..b0baf36308e 100644
--- a/src/libstd/keyword_docs.rs
+++ b/src/libstd/keyword_docs.rs
@@ -126,7 +126,7 @@ mod break_keyword { }
 /// look like this:
 ///
 /// ```rust
-/// const WORDS: &str = "hello rust!";
+/// const WORDS: &'static str = "hello rust!";
 /// ```
 ///
 /// Thanks to static lifetime elision, you usually don't have to explicitly use 'static:
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index cbeaf20b13a..2df79ee97fb 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -4,53 +4,7 @@
 //! library. Each macro is available for use when linking against the standard
 //! library.
 
-/// Panics the current thread.
-///
-/// This allows a program to terminate immediately and provide feedback
-/// to the caller of the program. `panic!` should be used when a program reaches
-/// an unrecoverable state.
-///
-/// This macro is the perfect way to assert conditions in example code and in
-/// tests. `panic!` is closely tied with the `unwrap` method of both [`Option`]
-/// and [`Result`][runwrap] enums. Both implementations call `panic!` when they are set
-/// to None or Err variants.
-///
-/// This macro is used to inject panic into a Rust thread, causing the thread to
-/// panic entirely. Each thread's panic can be reaped as the `Box<Any>` type,
-/// and the single-argument form of the `panic!` macro will be the value which
-/// is transmitted.
-///
-/// [`Result`] enum is often a better solution for recovering from errors than
-/// using the `panic!` macro. This macro should be used to avoid proceeding using
-/// incorrect values, such as from external sources. Detailed information about
-/// error handling is found in the [book].
-///
-/// The multi-argument form of this macro panics with a string and has the
-/// [`format!`] syntax for building a string.
-///
-/// See also the macro [`compile_error!`], for raising errors during compilation.
-///
-/// [runwrap]: ../std/result/enum.Result.html#method.unwrap
-/// [`Option`]: ../std/option/enum.Option.html#method.unwrap
-/// [`Result`]: ../std/result/enum.Result.html
-/// [`format!`]: ../std/macro.format.html
-/// [`compile_error!`]: ../std/macro.compile_error.html
-/// [book]: ../book/ch09-00-error-handling.html
-///
-/// # Current implementation
-///
-/// If the main thread panics it will terminate all your threads and end your
-/// program with code `101`.
-///
-/// # Examples
-///
-/// ```should_panic
-/// # #![allow(unreachable_code)]
-/// panic!();
-/// panic!("this is a terrible mistake!");
-/// panic!(4); // panic with the value of 4 to be collected elsewhere
-/// panic!("this is a {} {message}", "fancy", message = "message");
-/// ```
+#[doc(include = "../libcore/macros/panic.md")]
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable(libstd_sys_internals)]
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index d358efbe543..bbf00825acb 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1422,6 +1422,33 @@ pub struct Lit {
     pub span: Span,
 }
 
+/// Same as `Lit`, but restricted to string literals.
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
+pub struct StrLit {
+    /// The original literal token as written in source code.
+    pub style: StrStyle,
+    pub symbol: Symbol,
+    pub suffix: Option<Symbol>,
+    pub span: Span,
+    /// The unescaped "semantic" representation of the literal lowered from the original token.
+    /// FIXME: Remove this and only create the semantic representation during lowering to HIR.
+    pub symbol_unescaped: Symbol,
+}
+
+impl StrLit {
+    crate fn as_lit(&self) -> Lit {
+        let token_kind = match self.style {
+            StrStyle::Cooked => token::Str,
+            StrStyle::Raw(n) => token::StrRaw(n),
+        };
+        Lit {
+            token: token::Lit::new(token_kind, self.symbol, self.suffix),
+            span: self.span,
+            kind: LitKind::Str(self.symbol_unescaped, self.style),
+        }
+    }
+}
+
 // Clippy uses Hash and PartialEq
 /// Type of the integer literal based on provided suffix.
 #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)]
@@ -1745,7 +1772,7 @@ pub struct Ty {
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct BareFnTy {
     pub unsafety: Unsafety,
-    pub abi: Abi,
+    pub ext: Extern,
     pub generic_params: Vec<GenericParam>,
     pub decl: P<FnDecl>,
 }
@@ -2128,7 +2155,7 @@ pub struct Mod {
 /// E.g., `extern { .. }` or `extern C { .. }`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct ForeignMod {
-    pub abi: Abi,
+    pub abi: Option<StrLit>,
     pub items: Vec<ForeignItem>,
 }
 
@@ -2411,24 +2438,17 @@ impl Item {
     }
 }
 
-/// A reference to an ABI.
-///
-/// In AST our notion of an ABI is still syntactic unlike in `rustc_target::spec::abi::Abi`.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, PartialEq)]
-pub struct Abi {
-    pub symbol: Symbol,
-    pub span: Span,
-}
-
-impl Abi {
-    pub fn new(symbol: Symbol, span: Span) -> Self {
-        Self { symbol, span }
-    }
+/// `extern` qualifier on a function item or function type.
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
+pub enum Extern {
+    None,
+    Implicit,
+    Explicit(StrLit),
 }
 
-impl Default for Abi {
-    fn default() -> Self {
-        Self::new(sym::Rust, DUMMY_SP)
+impl Extern {
+    pub fn from_abi(abi: Option<StrLit>) -> Extern {
+        abi.map_or(Extern::Implicit, Extern::Explicit)
     }
 }
 
@@ -2441,7 +2461,7 @@ pub struct FnHeader {
     pub unsafety: Unsafety,
     pub asyncness: Spanned<IsAsync>,
     pub constness: Spanned<Constness>,
-    pub abi: Abi,
+    pub ext: Extern,
 }
 
 impl Default for FnHeader {
@@ -2450,7 +2470,7 @@ impl Default for FnHeader {
             unsafety: Unsafety::Normal,
             asyncness: dummy_spanned(IsAsync::NotAsync),
             constness: dummy_spanned(Constness::NotConst),
-            abi: Abi::default(),
+            ext: Extern::None,
         }
     }
 }
diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs
index acf0dd1cabb..767fcabc017 100644
--- a/src/libsyntax/attr/builtin.rs
+++ b/src/libsyntax/attr/builtin.rs
@@ -667,7 +667,10 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess,
             break
         }
 
-        let meta = attr.meta().unwrap();
+        let meta = match attr.meta() {
+            Some(meta) => meta,
+            None => continue,
+        };
         depr = match &meta.kind {
             MetaItemKind::Word => Some(Deprecation { since: None, note: None }),
             MetaItemKind::NameValue(..) => {
diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs
index bd836eee42a..abf9adefd3c 100644
--- a/src/libsyntax/feature_gate/check.rs
+++ b/src/libsyntax/feature_gate/check.rs
@@ -191,10 +191,10 @@ macro_rules! gate_feature_post {
 }
 
 impl<'a> PostExpansionVisitor<'a> {
-    fn check_abi(&self, abi: ast::Abi) {
-        let ast::Abi { symbol, span } = abi;
+    fn check_abi(&self, abi: ast::StrLit) {
+        let ast::StrLit { symbol_unescaped, span, .. } = abi;
 
-        match &*symbol.as_str() {
+        match &*symbol_unescaped.as_str() {
             // Stable
             "Rust" |
             "C" |
@@ -258,6 +258,12 @@ impl<'a> PostExpansionVisitor<'a> {
         }
     }
 
+    fn check_extern(&self, ext: ast::Extern) {
+        if let ast::Extern::Explicit(abi) = ext {
+            self.check_abi(abi);
+        }
+    }
+
     fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) {
         let has_fields = variants.iter().any(|variant| match variant.data {
             VariantData::Tuple(..) | VariantData::Struct(..) => true,
@@ -388,7 +394,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
     fn visit_item(&mut self, i: &'a ast::Item) {
         match i.kind {
             ast::ItemKind::ForeignMod(ref foreign_module) => {
-                self.check_abi(foreign_module.abi);
+                if let Some(abi) = foreign_module.abi {
+                    self.check_abi(abi);
+                }
             }
 
             ast::ItemKind::Fn(..) => {
@@ -511,7 +519,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
     fn visit_ty(&mut self, ty: &'a ast::Ty) {
         match ty.kind {
             ast::TyKind::BareFn(ref bare_fn_ty) => {
-                self.check_abi(bare_fn_ty.abi);
+                self.check_extern(bare_fn_ty.ext);
             }
             ast::TyKind::Never => {
                 gate_feature_post!(&self, never_type, ty.span,
@@ -605,7 +613,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
             // Stability of const fn methods are covered in
             // `visit_trait_item` and `visit_impl_item` below; this is
             // because default methods don't pass through this point.
-            self.check_abi(header.abi);
+            self.check_extern(header.ext);
         }
 
         if fn_decl.c_variadic() {
@@ -639,7 +647,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         match ti.kind {
             ast::TraitItemKind::Method(ref sig, ref block) => {
                 if block.is_none() {
-                    self.check_abi(sig.header.abi);
+                    self.check_extern(sig.header.ext);
                 }
                 if sig.decl.c_variadic() {
                     gate_feature_post!(&self, c_variadic, ti.span,
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index f4ef993edb9..da3c885b860 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -441,7 +441,7 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
             vis.visit_mt(mt);
         }
         TyKind::BareFn(bft) => {
-            let BareFnTy { unsafety: _, abi: _, generic_params, decl } = bft.deref_mut();
+            let BareFnTy { unsafety: _, ext: _, generic_params, decl } = bft.deref_mut();
             generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
             vis.visit_fn_decl(decl);
         }
@@ -974,7 +974,7 @@ pub fn noop_flat_map_impl_item<T: MutVisitor>(mut item: ImplItem, visitor: &mut
 }
 
 pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
-    let FnHeader { unsafety: _, asyncness, constness: _, abi: _ } = header;
+    let FnHeader { unsafety: _, asyncness, constness: _, ext: _ } = header;
     vis.visit_asyncness(&mut asyncness.node);
 }
 
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index ef65a744e83..17a7cbddff9 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1013,7 +1013,7 @@ impl<'a> State<'a> {
                 self.pclose();
             }
             ast::TyKind::BareFn(ref f) => {
-                self.print_ty_fn(f.abi,
+                self.print_ty_fn(f.ext,
                                  f.unsafety,
                                  &f.decl,
                                  None,
@@ -1232,7 +1232,10 @@ impl<'a> State<'a> {
             }
             ast::ItemKind::ForeignMod(ref nmod) => {
                 self.head("extern");
-                self.print_abi(nmod.abi);
+                if let Some(abi) = nmod.abi {
+                    self.print_literal(&abi.as_lit());
+                    self.nbsp();
+                }
                 self.bopen();
                 self.print_foreign_mod(nmod, &item.attrs);
                 self.bclose(item.span);
@@ -2805,7 +2808,7 @@ impl<'a> State<'a> {
     }
 
     crate fn print_ty_fn(&mut self,
-                       abi: ast::Abi,
+                       ext: ast::Extern,
                        unsafety: ast::Unsafety,
                        decl: &ast::FnDecl,
                        name: Option<ast::Ident>,
@@ -2825,7 +2828,7 @@ impl<'a> State<'a> {
             span: syntax_pos::DUMMY_SP,
         };
         self.print_fn(decl,
-                      ast::FnHeader { unsafety, abi, ..ast::FnHeader::default() },
+                      ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() },
                       name,
                       &generics,
                       &source_map::dummy_spanned(ast::VisibilityKind::Inherited));
@@ -2866,18 +2869,21 @@ impl<'a> State<'a> {
         self.print_asyncness(header.asyncness.node);
         self.print_unsafety(header.unsafety);
 
-        if header.abi.symbol != sym::Rust {
-            self.word_nbsp("extern");
-            self.print_abi(header.abi);
+        match header.ext {
+            ast::Extern::None => {}
+            ast::Extern::Implicit => {
+                self.word_nbsp("extern");
+            }
+            ast::Extern::Explicit(abi) => {
+                self.word_nbsp("extern");
+                self.print_literal(&abi.as_lit());
+                self.nbsp();
+            }
         }
 
         self.s.word("fn")
     }
 
-    fn print_abi(&mut self, abi: ast::Abi) {
-        self.word_nbsp(format!("\"{}\"", abi.symbol));
-    }
-
     crate fn print_unsafety(&mut self, s: ast::Unsafety) {
         match s {
             ast::Unsafety::Normal => {},
diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs
index 5fab101957a..bd345a9a7da 100644
--- a/src/libsyntax_ext/asm.rs
+++ b/src/libsyntax_ext/asm.rs
@@ -2,19 +2,17 @@
 //
 use State::*;
 
+use errors::{DiagnosticBuilder, PResult};
 use rustc_data_structures::thin_vec::ThinVec;
-
-use errors::DiagnosticBuilder;
-
-use syntax::ast;
-use syntax_expand::base::{self, *};
-use syntax::token::{self, Token};
+use rustc_parse::parser::Parser;
+use syntax_expand::base::*;
+use syntax_pos::Span;
+use syntax::{span_err, struct_span_err};
+use syntax::ast::{self, AsmDialect};
 use syntax::ptr::P;
 use syntax::symbol::{kw, sym, Symbol};
-use syntax::ast::AsmDialect;
-use syntax_pos::Span;
+use syntax::token::{self, Token};
 use syntax::tokenstream::{self, TokenStream};
-use syntax::{span_err, struct_span_err};
 
 use rustc_error_codes::*;
 
@@ -45,7 +43,7 @@ const OPTIONS: &[Symbol] = &[sym::volatile, sym::alignstack, sym::intel];
 pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>,
                        sp: Span,
                        tts: TokenStream)
-                       -> Box<dyn base::MacResult + 'cx> {
+                       -> Box<dyn MacResult + 'cx> {
     let mut inline_asm = match parse_inline_asm(cx, sp, tts) {
         Ok(Some(inline_asm)) => inline_asm,
         Ok(None) => return DummyResult::any(sp),
@@ -69,6 +67,18 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>,
     }))
 }
 
+fn parse_asm_str<'a>(p: &mut Parser<'a>) -> PResult<'a, Symbol> {
+    match p.parse_str_lit() {
+        Ok(str_lit) => Ok(str_lit.symbol_unescaped),
+        Err(opt_lit) => {
+            let span = opt_lit.map_or(p.token.span, |lit| lit.span);
+            let mut err = p.sess.span_diagnostic.struct_span_err(span, "expected string literal");
+            err.span_label(span, "not a string literal");
+            Err(err)
+        }
+    }
+}
+
 fn parse_inline_asm<'a>(
     cx: &mut ExtCtxt<'a>,
     sp: Span,
@@ -144,7 +154,7 @@ fn parse_inline_asm<'a>(
                         p.eat(&token::Comma);
                     }
 
-                    let (constraint, _) = p.parse_str()?;
+                    let constraint = parse_asm_str(&mut p)?;
 
                     let span = p.prev_span;
 
@@ -189,7 +199,7 @@ fn parse_inline_asm<'a>(
                         p.eat(&token::Comma);
                     }
 
-                    let (constraint, _) = p.parse_str()?;
+                    let constraint = parse_asm_str(&mut p)?;
 
                     if constraint.as_str().starts_with("=") {
                         span_err!(cx, p.prev_span, E0662,
@@ -212,7 +222,7 @@ fn parse_inline_asm<'a>(
                         p.eat(&token::Comma);
                     }
 
-                    let (s, _) = p.parse_str()?;
+                    let s = parse_asm_str(&mut p)?;
 
                     if OPTIONS.iter().any(|&opt| s == opt) {
                         cx.span_warn(p.prev_span, "expected a clobber, found an option");
@@ -225,7 +235,7 @@ fn parse_inline_asm<'a>(
                 }
             }
             Options => {
-                let (option, _) = p.parse_str()?;
+                let option = parse_asm_str(&mut p)?;
 
                 if option == sym::volatile {
                     // Indicates that the inline assembly has side effects
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index b24306def74..b6bf2f88161 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -182,7 +182,7 @@ use std::iter;
 use std::vec;
 
 use rustc_data_structures::thin_vec::ThinVec;
-use syntax::ast::{self, Abi, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind};
+use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind};
 use syntax::ast::{VariantData, GenericParamKind, GenericArg};
 use syntax::attr;
 use syntax::source_map::respan;
@@ -737,7 +737,6 @@ impl<'a> TraitDef<'a> {
                                          self,
                                          type_ident,
                                          generics,
-                                         sym::Rust,
                                          explicit_self,
                                          tys,
                                          body)
@@ -792,7 +791,6 @@ impl<'a> TraitDef<'a> {
                                          self,
                                          type_ident,
                                          generics,
-                                         sym::Rust,
                                          explicit_self,
                                          tys,
                                          body)
@@ -918,7 +916,6 @@ impl<'a> MethodDef<'a> {
                      trait_: &TraitDef<'_>,
                      type_ident: Ident,
                      generics: &Generics,
-                     abi: Symbol,
                      explicit_self: Option<ast::ExplicitSelf>,
                      arg_types: Vec<(Ident, P<ast::Ty>)>,
                      body: P<Expr>)
@@ -953,7 +950,7 @@ impl<'a> MethodDef<'a> {
         let sig = ast::FnSig {
             header: ast::FnHeader {
                 unsafety,
-                abi: Abi::new(abi, trait_lo_sp),
+                ext: ast::Extern::None,
                 ..ast::FnHeader::default()
             },
             decl: fn_decl,
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index b3e9576f43f..86eaeeab5a4 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -570,7 +570,6 @@ symbols! {
         rust_2018_preview,
         rust_begin_unwind,
         rustc,
-        Rust,
         RustcDecodable,
         RustcEncodable,
         rustc_allocator,
diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs
index 9f1850dfb4c..f9ecff2abaa 100644
--- a/src/test/run-make-fulldeps/issue-19371/foo.rs
+++ b/src/test/run-make-fulldeps/issue-19371/foo.rs
@@ -2,7 +2,7 @@
 
 extern crate rustc;
 extern crate rustc_interface;
-extern crate rustc_driver as _;
+extern crate rustc_driver;
 extern crate syntax;
 
 use rustc::session::DiagnosticOutput;
@@ -61,6 +61,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
         lint_caps: Default::default(),
         register_lints: None,
         override_queries: None,
+        registry: rustc_driver::diagnostics_registry(),
     };
 
     interface::run_compiler(config, |compiler| {
diff --git a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs
index 3d08c1c9eee..b17c6a93965 100644
--- a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs
@@ -14,9 +14,6 @@ use syntax::symbol::Symbol;
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_attribute(Symbol::intern("foo"), AttributeType::Normal);
-    reg.register_attribute(Symbol::intern("bar"), AttributeType::CrateLevel);
-    reg.register_attribute(Symbol::intern("baz"), AttributeType::Whitelisted);
     reg.register_syntax_extension(
         Symbol::intern("mac"), SyntaxExtension::dummy_bang(reg.sess.edition())
     );
diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
index 6b914f501ca..68ea10fe735 100644
--- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
+++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
@@ -5,25 +5,17 @@
 extern crate rustc;
 extern crate rustc_driver;
 extern crate syntax;
-extern crate syntax_expand;
 
 use rustc_driver::plugin::Registry;
-use syntax::attr;
-use syntax_expand::base::*;
-use syntax::feature_gate::AttributeType::Whitelisted;
-use syntax::symbol::Symbol;
-
-use rustc::hir;
-use rustc::hir::intravisit;
-use hir::Node;
+use rustc::hir::{self, intravisit, Node};
 use rustc::lint::{LateContext, LintPass, LintArray, LateLintPass, LintContext};
+use syntax::print::pprust;
 use syntax::source_map;
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
     reg.lint_store.register_lints(&[&MISSING_WHITELISTED_ATTR]);
     reg.lint_store.register_late_pass(|| box MissingWhitelistedAttrPass);
-    reg.register_attribute(Symbol::intern("whitelisted_attr"), Whitelisted);
 }
 
 declare_lint! {
@@ -48,7 +40,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingWhitelistedAttrPass {
             _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id)),
         };
 
-        if !attr::contains_name(&item.attrs, Symbol::intern("whitelisted_attr")) {
+        let whitelisted = |attr| pprust::attribute_to_string(attr).contains("whitelisted_attr");
+        if !item.attrs.iter().any(whitelisted) {
             cx.span_lint(MISSING_WHITELISTED_ATTR, span,
                          "Missing 'whitelisted_attr' attribute");
         }
diff --git a/src/test/ui-fulldeps/issue-40001.rs b/src/test/ui-fulldeps/issue-40001.rs
index e0dc3d6a45b..c3f98197250 100644
--- a/src/test/ui-fulldeps/issue-40001.rs
+++ b/src/test/ui-fulldeps/issue-40001.rs
@@ -2,8 +2,9 @@
 // aux-build:issue-40001-plugin.rs
 // ignore-stage1
 
-#![feature(plugin)]
+#![feature(plugin, register_tool)]
 #![plugin(issue_40001_plugin)] //~ WARNING compiler plugins are deprecated
+#![register_tool(plugin)]
 
-#[whitelisted_attr]
+#[plugin::whitelisted_attr]
 fn main() {}
diff --git a/src/test/ui-fulldeps/plugin-attr-register-deny.rs b/src/test/ui-fulldeps/plugin-attr-register-deny.rs
deleted file mode 100644
index dd7c009388e..00000000000
--- a/src/test/ui-fulldeps/plugin-attr-register-deny.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-// aux-build:attr-plugin-test.rs
-// ignore-stage1
-
-#![feature(plugin)]
-#![plugin(attr_plugin_test)]
-//~^ WARN use of deprecated attribute `plugin`
-#![deny(unused_attributes)]
-
-#[baz]
-fn baz() { } // no error
-
-#[foo]
-pub fn main() {
-     //~^^ ERROR unused
-    #[bar]
-    fn inner() {}
-    //~^^ ERROR crate
-    //~^^^ ERROR unused
-    baz();
-    inner();
-}
diff --git a/src/test/ui-fulldeps/plugin-attr-register-deny.stderr b/src/test/ui-fulldeps/plugin-attr-register-deny.stderr
deleted file mode 100644
index 8d95d6ff2d8..00000000000
--- a/src/test/ui-fulldeps/plugin-attr-register-deny.stderr
+++ /dev/null
@@ -1,34 +0,0 @@
-warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
-  --> $DIR/plugin-attr-register-deny.rs:5:1
-   |
-LL | #![plugin(attr_plugin_test)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
-   |
-   = note: `#[warn(deprecated)]` on by default
-
-error: unused attribute
-  --> $DIR/plugin-attr-register-deny.rs:15:5
-   |
-LL |     #[bar]
-   |     ^^^^^^
-   |
-note: lint level defined here
-  --> $DIR/plugin-attr-register-deny.rs:7:9
-   |
-LL | #![deny(unused_attributes)]
-   |         ^^^^^^^^^^^^^^^^^
-
-error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/plugin-attr-register-deny.rs:15:5
-   |
-LL |     #[bar]
-   |     ^^^^^^
-
-error: unused attribute
-  --> $DIR/plugin-attr-register-deny.rs:12:1
-   |
-LL | #[foo]
-   | ^^^^^^
-
-error: aborting due to 3 previous errors
-
diff --git a/src/test/ui/asm/asm-literal-escaping.rs b/src/test/ui/asm/asm-literal-escaping.rs
new file mode 100644
index 00000000000..8d464e752e6
--- /dev/null
+++ b/src/test/ui/asm/asm-literal-escaping.rs
@@ -0,0 +1,12 @@
+// build-pass
+// only-x86_64
+
+#![feature(asm)]
+
+fn main() {
+    unsafe {
+        // "nop" :: "r"(x) : "eax" : "volatile"
+        let x = 10;
+        asm!("\x6Eop" :: "\x72"(x) : "\x65ax" : "\x76olatile");
+    }
+}
diff --git a/src/test/ui/asm/asm-parse-errors.stderr b/src/test/ui/asm/asm-parse-errors.stderr
index 9fe59d12e12..2b29332fef5 100644
--- a/src/test/ui/asm/asm-parse-errors.stderr
+++ b/src/test/ui/asm/asm-parse-errors.stderr
@@ -8,13 +8,13 @@ error: expected string literal
   --> $DIR/asm-parse-errors.rs:5:18
    |
 LL |     asm!("nop" : struct);
-   |                  ^^^^^^ expected string literal
+   |                  ^^^^^^ not a string literal
 
 error: expected string literal
   --> $DIR/asm-parse-errors.rs:6:30
    |
 LL |     asm!("mov %eax, $$0x2" : struct);
-   |                              ^^^^^^ expected string literal
+   |                              ^^^^^^ not a string literal
 
 error: expected `(`, found keyword `struct`
   --> $DIR/asm-parse-errors.rs:7:39
@@ -32,7 +32,7 @@ error: expected string literal
   --> $DIR/asm-parse-errors.rs:9:44
    |
 LL |     asm!("in %dx, %al" : "={al}"(result) : struct);
-   |                                            ^^^^^^ expected string literal
+   |                                            ^^^^^^ not a string literal
 
 error: expected `(`, found keyword `struct`
   --> $DIR/asm-parse-errors.rs:10:51
@@ -50,13 +50,13 @@ error: expected string literal
   --> $DIR/asm-parse-errors.rs:12:36
    |
 LL |     asm!("mov $$0x200, %eax" : : : struct);
-   |                                    ^^^^^^ expected string literal
+   |                                    ^^^^^^ not a string literal
 
 error: expected string literal
   --> $DIR/asm-parse-errors.rs:13:45
    |
 LL |     asm!("mov eax, 2" : "={eax}"(foo) : : : struct);
-   |                                             ^^^^^^ expected string literal
+   |                                             ^^^^^^ not a string literal
 
 error: inline assembly must be a string literal
   --> $DIR/asm-parse-errors.rs:14:10
diff --git a/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs b/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs
new file mode 100644
index 00000000000..c0cde75d4ca
--- /dev/null
+++ b/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs
@@ -0,0 +1,11 @@
+// The original problem in #66340 was that `find_deprecation_generic`
+// called `attr.meta().unwrap()` under the assumption that the attribute
+// was a well-formed `MetaItem`.
+
+fn main() {
+    foo()
+}
+
+#[deprecated(note = test)]
+//~^ ERROR expected unsuffixed literal or identifier, found `test`
+fn foo() {}
diff --git a/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr b/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr
new file mode 100644
index 00000000000..24178faf8de
--- /dev/null
+++ b/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr
@@ -0,0 +1,8 @@
+error: expected unsuffixed literal or identifier, found `test`
+  --> $DIR/issue-66340-deprecated-attr-non-meta-grammar.rs:9:21
+   |
+LL | #[deprecated(note = test)]
+   |                     ^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/dead-code/lint-dead-code-4.rs b/src/test/ui/lint/dead-code/lint-dead-code-4.rs
index 3f4a9e21040..8bcb1e5ba8c 100644
--- a/src/test/ui/lint/dead-code/lint-dead-code-4.rs
+++ b/src/test/ui/lint/dead-code/lint-dead-code-4.rs
@@ -4,7 +4,7 @@
 
 struct Foo {
     x: usize,
-    b: bool, //~ ERROR: field is never used
+    b: bool, //~ ERROR: field is never read
 }
 
 fn field_read(f: Foo) -> usize {
@@ -36,8 +36,8 @@ enum IJK {
     I, //~ ERROR variant is never constructed
     J {
         a: String,
-        b: i32, //~ ERROR field is never used
-        c: i32, //~ ERROR field is never used
+        b: i32, //~ ERROR field is never read
+        c: i32, //~ ERROR field is never read
     },
     K //~ ERROR variant is never constructed
 
@@ -58,9 +58,9 @@ fn field_match_in_patterns(b: XYZ) -> String {
 }
 
 struct Bar {
-    x: usize, //~ ERROR: field is never used
+    x: usize, //~ ERROR: field is never read
     b: bool,
-    c: bool, //~ ERROR: field is never used
+    c: bool, //~ ERROR: field is never read
     _guard: ()
 }
 
diff --git a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr
index 8eaf789f8f7..cc00fa4e42a 100644
--- a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr
+++ b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr
@@ -1,4 +1,4 @@
-error: field is never used: `b`
+error: field is never read: `b`
   --> $DIR/lint-dead-code-4.rs:7:5
    |
 LL |     b: bool,
@@ -38,13 +38,13 @@ error: variant is never constructed: `I`
 LL |     I,
    |     ^
 
-error: field is never used: `b`
+error: field is never read: `b`
   --> $DIR/lint-dead-code-4.rs:39:9
    |
 LL |         b: i32,
    |         ^^^^^^
 
-error: field is never used: `c`
+error: field is never read: `c`
   --> $DIR/lint-dead-code-4.rs:40:9
    |
 LL |         c: i32,
@@ -56,13 +56,13 @@ error: variant is never constructed: `K`
 LL |     K
    |     ^
 
-error: field is never used: `x`
+error: field is never read: `x`
   --> $DIR/lint-dead-code-4.rs:61:5
    |
 LL |     x: usize,
    |     ^^^^^^^^
 
-error: field is never used: `c`
+error: field is never read: `c`
   --> $DIR/lint-dead-code-4.rs:63:5
    |
 LL |     c: bool,
diff --git a/src/test/ui/parser/issue-63116.rs b/src/test/ui/parser/issue-63116.rs
new file mode 100644
index 00000000000..430bc1d716c
--- /dev/null
+++ b/src/test/ui/parser/issue-63116.rs
@@ -0,0 +1,3 @@
+// fixed by #66361
+// error-pattern: aborting due to 3 previous errors
+impl W <s(f;Y(;]
diff --git a/src/test/ui/parser/issue-63116.stderr b/src/test/ui/parser/issue-63116.stderr
new file mode 100644
index 00000000000..0aed0386a90
--- /dev/null
+++ b/src/test/ui/parser/issue-63116.stderr
@@ -0,0 +1,24 @@
+error: this file contains an un-closed delimiter
+  --> $DIR/issue-63116.rs:3:18
+   |
+LL | impl W <s(f;Y(;]
+   |          -       ^
+   |          |
+   |          un-closed delimiter
+
+error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `;`
+  --> $DIR/issue-63116.rs:3:12
+   |
+LL | impl W <s(f;Y(;]
+   |            ^ expected one of 7 possible tokens
+
+error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `->`, `...`, `::`, `<`, `>`, `?`, `[`, `_`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, or lifetime, found `;`
+  --> $DIR/issue-63116.rs:3:15
+   |
+LL | impl W <s(f;Y(;]
+   |              -^ help: `)` may belong here
+   |              |
+   |              unclosed delimiter
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/proc-macro/span-preservation.rs b/src/test/ui/proc-macro/span-preservation.rs
index 55835cb88f4..b22e50c4c17 100644
--- a/src/test/ui/proc-macro/span-preservation.rs
+++ b/src/test/ui/proc-macro/span-preservation.rs
@@ -1,9 +1,8 @@
-//~ ERROR mismatched types
-// aux-build:test-macros.rs
-
 // For each of these, we should get the appropriate type mismatch error message,
 // and the function should be echoed.
 
+// aux-build:test-macros.rs
+
 #[macro_use]
 extern crate test_macros;
 
@@ -35,12 +34,9 @@ fn c() {
     let y = Foo { a: 10, b: 10isize }; //~ ERROR has no field named `b`
 }
 
-// FIXME: This doesn't work at the moment. See the one below. The pretty-printer
-// injects a "C" between `extern` and `fn` which causes a "probably_eq"
-// `TokenStream` mismatch. The lack of `"C"` should be preserved in the AST.
 #[recollect_attr]
 extern fn bar() {
-    0
+    0 //~ ERROR mismatched types
 }
 
 #[recollect_attr]
@@ -48,4 +44,14 @@ extern "C" fn baz() {
     0 //~ ERROR mismatched types
 }
 
+#[recollect_attr]
+extern "Rust" fn rust_abi() {
+    0 //~ ERROR mismatched types
+}
+
+#[recollect_attr]
+extern "\x43" fn c_abi_escaped() {
+    0 //~ ERROR mismatched types
+}
+
 fn main() {}
diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr
index 0290f4b2cc9..545c2fa5f40 100644
--- a/src/test/ui/proc-macro/span-preservation.stderr
+++ b/src/test/ui/proc-macro/span-preservation.stderr
@@ -1,10 +1,5 @@
 error[E0308]: mismatched types
-   |
-   = note: expected type `()`
-              found type `{integer}`
-
-error[E0308]: mismatched types
-  --> $DIR/span-preservation.rs:12:20
+  --> $DIR/span-preservation.rs:11:20
    |
 LL |     let x: usize = "hello";
    |                    ^^^^^^^ expected usize, found reference
@@ -13,7 +8,7 @@ LL |     let x: usize = "hello";
               found type `&'static str`
 
 error[E0308]: mismatched types
-  --> $DIR/span-preservation.rs:18:29
+  --> $DIR/span-preservation.rs:17:29
    |
 LL | fn b(x: Option<isize>) -> usize {
    |                           ----- expected `usize` because of return type
@@ -22,13 +17,13 @@ LL |         Some(x) => { return x },
    |                             ^ expected usize, found isize
 
 error[E0308]: mismatched types
-  --> $DIR/span-preservation.rs:34:22
+  --> $DIR/span-preservation.rs:33:22
    |
 LL |     let x = Foo { a: 10isize };
    |                      ^^^^^^^ expected usize, found isize
 
 error[E0560]: struct `c::Foo` has no field named `b`
-  --> $DIR/span-preservation.rs:35:26
+  --> $DIR/span-preservation.rs:34:26
    |
 LL |     let y = Foo { a: 10, b: 10isize };
    |                          ^ `c::Foo` does not have this field
@@ -36,7 +31,18 @@ LL |     let y = Foo { a: 10, b: 10isize };
    = note: available fields are: `a`
 
 error[E0308]: mismatched types
-  --> $DIR/span-preservation.rs:48:5
+  --> $DIR/span-preservation.rs:39:5
+   |
+LL | extern fn bar() {
+   |                 - possibly return type missing here?
+LL |     0
+   |     ^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/span-preservation.rs:44:5
    |
 LL | extern "C" fn baz() {
    |                     - possibly return type missing here?
@@ -46,7 +52,29 @@ LL |     0
    = note: expected type `()`
               found type `{integer}`
 
-error: aborting due to 6 previous errors
+error[E0308]: mismatched types
+  --> $DIR/span-preservation.rs:49:5
+   |
+LL | extern "Rust" fn rust_abi() {
+   |                             - possibly return type missing here?
+LL |     0
+   |     ^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/span-preservation.rs:54:5
+   |
+LL | extern "\x43" fn c_abi_escaped() {
+   |                                  - possibly return type missing here?
+LL |     0
+   |     ^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0308, E0560.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/union/union-fields-1.rs b/src/test/ui/union/union-fields-1.rs
index 6d76e18cc7e..edef41de159 100644
--- a/src/test/ui/union/union-fields-1.rs
+++ b/src/test/ui/union/union-fields-1.rs
@@ -3,19 +3,19 @@
 union U1 {
     a: u8, // should not be reported
     b: u8, // should not be reported
-    c: u8, //~ ERROR field is never used
+    c: u8, //~ ERROR field is never read
 }
 union U2 {
-    a: u8, //~ ERROR field is never used
+    a: u8, //~ ERROR field is never read
     b: u8, // should not be reported
     c: u8, // should not be reported
 }
-union NoDropLike { a: u8 } //~ ERROR field is never used
+union NoDropLike { a: u8 } //~ ERROR field is never read
 
 union U {
     a: u8, // should not be reported
     b: u8, // should not be reported
-    c: u8, //~ ERROR field is never used
+    c: u8, //~ ERROR field is never read
 }
 type A = U;
 
diff --git a/src/test/ui/union/union-fields-1.stderr b/src/test/ui/union/union-fields-1.stderr
index f848db726f9..be145c9496c 100644
--- a/src/test/ui/union/union-fields-1.stderr
+++ b/src/test/ui/union/union-fields-1.stderr
@@ -1,4 +1,4 @@
-error: field is never used: `c`
+error: field is never read: `c`
   --> $DIR/union-fields-1.rs:6:5
    |
 LL |     c: u8,
@@ -10,19 +10,19 @@ note: lint level defined here
 LL | #![deny(dead_code)]
    |         ^^^^^^^^^
 
-error: field is never used: `a`
+error: field is never read: `a`
   --> $DIR/union-fields-1.rs:9:5
    |
 LL |     a: u8,
    |     ^^^^^
 
-error: field is never used: `a`
+error: field is never read: `a`
   --> $DIR/union-fields-1.rs:13:20
    |
 LL | union NoDropLike { a: u8 }
    |                    ^^^^^
 
-error: field is never used: `c`
+error: field is never read: `c`
   --> $DIR/union-fields-1.rs:18:5
    |
 LL |     c: u8,
diff --git a/src/test/ui/union/union-lint-dead-code.rs b/src/test/ui/union/union-lint-dead-code.rs
index cb6415c18a8..ae5337c618a 100644
--- a/src/test/ui/union/union-lint-dead-code.rs
+++ b/src/test/ui/union/union-lint-dead-code.rs
@@ -2,7 +2,7 @@
 
 union Foo {
     x: usize,
-    b: bool, //~ ERROR: field is never used
+    b: bool, //~ ERROR: field is never read
     _unused: u16,
 }
 
diff --git a/src/test/ui/union/union-lint-dead-code.stderr b/src/test/ui/union/union-lint-dead-code.stderr
index 79c38a46814..5fe26dc2538 100644
--- a/src/test/ui/union/union-lint-dead-code.stderr
+++ b/src/test/ui/union/union-lint-dead-code.stderr
@@ -1,4 +1,4 @@
-error: field is never used: `b`
+error: field is never read: `b`
   --> $DIR/union-lint-dead-code.rs:5:5
    |
 LL |     b: bool,