about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-01-14 23:00:50 +0000
committerbors <bors@rust-lang.org>2019-01-14 23:00:50 +0000
commitaea9f0aa976db2f5de28be3b6b287c6889cd926b (patch)
tree1f45e79c5694619f8b0ea8a4652abce5a2c49a52 /src
parent03acbd71c977cd63ce5f39ba9b6fe9ffd578785a (diff)
parent8a62e393b8fba95e989020f2efbf846ca02113f9 (diff)
downloadrust-aea9f0aa976db2f5de28be3b6b287c6889cd926b.tar.gz
rust-aea9f0aa976db2f5de28be3b6b287c6889cd926b.zip
Auto merge of #57607 - Centril:rollup, r=Centril
Rollup of 8 pull requests

Successful merges:

 - #57043 (Fix poor worst case performance of set intersection)
 - #57480 (Clean up and fix a bug in query plumbing)
 - #57481 (provide suggestion for invalid boolean cast)
 - #57540 (Modify some parser diagnostics to continue evaluating beyond the parser)
 - #57570 (Querify local `plugin_registrar_fn` and `proc_macro_decls_static`)
 - #57572 (Unaccept `extern_in_paths`)
 - #57585 (Recover from item trailing semicolon)
 - #57589 (Add a debug_assert to Vec::set_len)

Failed merges:

r? @ghost
Diffstat (limited to 'src')
-rw-r--r--src/doc/unstable-book/src/language-features/extern-in-paths.md40
-rw-r--r--src/liballoc/vec.rs2
-rw-r--r--src/librustc/middle/cstore.rs2
-rw-r--r--src/librustc/session/mod.rs4
-rw-r--r--src/librustc/ty/query/plumbing.rs41
-rw-r--r--src/librustc_codegen_ssa/back/symbol_export.rs10
-rw-r--r--src/librustc_codegen_utils/symbol_names.rs6
-rw-r--r--src/librustc_driver/driver.rs17
-rw-r--r--src/librustc_driver/proc_macro_decls.rs26
-rw-r--r--src/librustc_lint/builtin.rs4
-rw-r--r--src/librustc_metadata/encoder.rs9
-rw-r--r--src/librustc_plugin/build.rs31
-rw-r--r--src/librustc_resolve/lib.rs9
-rw-r--r--src/librustc_typeck/check/cast.rs26
-rw-r--r--src/libstd/collections/hash/set.rs67
-rw-r--r--src/libsyntax/feature_gate.rs29
-rw-r--r--src/libsyntax/parse/lexer/mod.rs2
-rw-r--r--src/libsyntax/parse/mod.rs8
-rw-r--r--src/libsyntax/parse/parser.rs215
-rw-r--r--src/libsyntax_pos/symbol.rs1
-rw-r--r--src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile5
-rw-r--r--src/test/run-make-fulldeps/save-analysis-rfc2126/extern_in_paths.rs7
-rw-r--r--src/test/run-pass/rfcs/rfc-2126-extern-absolute-paths/extern.rs28
-rw-r--r--src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr2
-rw-r--r--src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr2
-rw-r--r--src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs10
-rw-r--r--src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr6
-rw-r--r--src/test/ui/cast/cast-as-bool.rs9
-rw-r--r--src/test/ui/cast/cast-as-bool.stderr18
-rw-r--r--src/test/ui/cast/cast-rfc0401-2.stderr4
-rw-r--r--src/test/ui/error-codes/E0054.stderr4
-rw-r--r--src/test/ui/error-festival.stderr4
-rw-r--r--src/test/ui/feature-gates/feature-gate-extern_in_paths.rs5
-rw-r--r--src/test/ui/feature-gates/feature-gate-extern_in_paths.stderr11
-rw-r--r--src/test/ui/issues/issue-46186.rs3
-rw-r--r--src/test/ui/issues/issue-46186.stderr4
-rw-r--r--src/test/ui/issues/issue-49040.rs2
-rw-r--r--src/test/ui/issues/issue-49040.stderr9
-rw-r--r--src/test/ui/keyword/extern/keyword-extern-as-identifier-expr.rs3
-rw-r--r--src/test/ui/keyword/extern/keyword-extern-as-identifier-expr.stderr8
-rw-r--r--src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs3
-rw-r--r--src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr8
-rw-r--r--src/test/ui/keyword/extern/keyword-extern-as-identifier-type.rs3
-rw-r--r--src/test/ui/keyword/extern/keyword-extern-as-identifier-type.stderr8
-rw-r--r--src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs3
-rw-r--r--src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr12
-rw-r--r--src/test/ui/keyword/keyword-extern-as-identifier.rs5
-rw-r--r--src/test/ui/keyword/keyword-extern-as-identifier.stderr9
-rw-r--r--src/test/ui/mismatched_types/cast-rfc0401.stderr6
-rw-r--r--src/test/ui/old-suffixes-are-really-forbidden.stderr4
-rw-r--r--src/test/ui/parser/bad-lit-suffixes.stderr24
-rw-r--r--src/test/ui/parser/bad-pointer-type.rs2
-rw-r--r--src/test/ui/parser/bad-pointer-type.stderr6
-rw-r--r--src/test/ui/parser/impl-parsing.stderr4
-rw-r--r--src/test/ui/parser/issue-14303-fncall.rs21
-rw-r--r--src/test/ui/parser/issue-14303-fncall.stderr10
-rw-r--r--src/test/ui/parser/issue-14303-path.rs11
-rw-r--r--src/test/ui/parser/issue-14303-path.stderr12
-rw-r--r--src/test/ui/parser/issue-17383.rs7
-rw-r--r--src/test/ui/parser/issue-17383.stderr6
-rw-r--r--src/test/ui/parser/issue-1802-1.rs5
-rw-r--r--src/test/ui/parser/issue-1802-1.stderr2
-rw-r--r--src/test/ui/parser/issue-1802-2.rs7
-rw-r--r--src/test/ui/parser/issue-1802-2.stderr6
-rw-r--r--src/test/ui/parser/issue-27255.rs9
-rw-r--r--src/test/ui/parser/issue-27255.stderr22
-rw-r--r--src/test/ui/parser/issue-32214.stderr2
-rw-r--r--src/test/ui/parser/lex-bad-numeric-literals.stderr6
-rw-r--r--src/test/ui/parser/no-binary-float-literal.rs5
-rw-r--r--src/test/ui/parser/no-binary-float-literal.stderr18
-rw-r--r--src/test/ui/parser/no-hex-float-literal.rs6
-rw-r--r--src/test/ui/parser/no-hex-float-literal.stderr25
-rw-r--r--src/test/ui/parser/no-unsafe-self.stderr12
-rw-r--r--src/test/ui/parser/pat-tuple-2.rs5
-rw-r--r--src/test/ui/parser/pat-tuple-2.stderr4
-rw-r--r--src/test/ui/parser/pat-tuple-3.rs5
-rw-r--r--src/test/ui/parser/pat-tuple-3.stderr4
-rw-r--r--src/test/ui/parser/tag-variant-disr-non-nullary.rs17
-rw-r--r--src/test/ui/parser/tag-variant-disr-non-nullary.stderr15
-rw-r--r--src/test/ui/parser/where_with_bound.rs1
-rw-r--r--src/test/ui/parser/where_with_bound.stderr11
-rw-r--r--src/test/ui/rfc-2126-extern-in-paths/auxiliary/xcrate.rs5
-rw-r--r--src/test/ui/rfc-2126-extern-in-paths/non-existent-1.rs5
-rw-r--r--src/test/ui/rfc-2126-extern-in-paths/non-existent-1.stderr9
-rw-r--r--src/test/ui/rfc-2126-extern-in-paths/non-existent-2.rs6
-rw-r--r--src/test/ui/rfc-2126-extern-in-paths/non-existent-2.stderr9
-rw-r--r--src/test/ui/rfc-2126-extern-in-paths/non-existent-3.rs5
-rw-r--r--src/test/ui/rfc-2126-extern-in-paths/non-existent-3.stderr9
-rw-r--r--src/test/ui/rfc-2126-extern-in-paths/single-segment.rs13
-rw-r--r--src/test/ui/rfc-2126-extern-in-paths/single-segment.stderr22
-rw-r--r--src/test/ui/suggestions/recover-from-semicolon-trailing-item.rs16
-rw-r--r--src/test/ui/suggestions/recover-from-semicolon-trailing-item.stderr50
-rw-r--r--src/test/ui/traits/trait-object-vs-lifetime.rs2
-rw-r--r--src/test/ui/traits/trait-object-vs-lifetime.stderr16
94 files changed, 715 insertions, 496 deletions
diff --git a/src/doc/unstable-book/src/language-features/extern-in-paths.md b/src/doc/unstable-book/src/language-features/extern-in-paths.md
deleted file mode 100644
index 9979d774229..00000000000
--- a/src/doc/unstable-book/src/language-features/extern-in-paths.md
+++ /dev/null
@@ -1,40 +0,0 @@
-# `extern_in_paths`
-
-The tracking issue for this feature is: [#44660]
-
-[#44660]: https://github.com/rust-lang/rust/issues/44660
-
-------------------------
-
-The `extern_in_paths` feature allows to refer to names from other crates "inline", without
-introducing `extern crate` items, using keyword `extern`.
-
-For example, `extern::my_crat::a::b` will resolve to path `a::b` in crate `my_crate`.
-
-Absolute paths on 2018 edition (e.g. `::my_crate::a::b`) provide the same effect
-and resolve to extern crates (built-in or passed with `--extern`).
-
-```rust,ignore
-#![feature(extern_in_paths)]
-
-// Suppose we have a dependency crate `xcrate` available through `Cargo.toml`, or `--extern`
-// options, or standard Rust distribution, or some other means.
-
-use extern::xcrate::Z;
-
-fn f() {
-    use extern::xcrate;
-    use extern::xcrate as ycrate;
-    let s = xcrate::S;
-    assert_eq!(format!("{:?}", s), "S");
-    let z = ycrate::Z;
-    assert_eq!(format!("{:?}", z), "Z");
-}
-
-fn main() {
-    let s = extern::xcrate::S;
-    assert_eq!(format!("{:?}", s), "S");
-    let z = Z;
-    assert_eq!(format!("{:?}", z), "Z");
-}
-```
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index e1c5ab15bb5..ba3b3dfbfc2 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -819,6 +819,8 @@ impl<T> Vec<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub unsafe fn set_len(&mut self, new_len: usize) {
+        debug_assert!(new_len <= self.capacity());
+
         self.len = new_len;
     }
 
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index c431dc77f78..9168bbf907f 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -140,7 +140,7 @@ pub enum ExternCrateSource {
     ),
     // Crate is loaded by `use`.
     Use,
-    /// Crate is implicitly loaded by an absolute or an `extern::` path.
+    /// Crate is implicitly loaded by an absolute path.
     Path,
 }
 
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index fa0dfc4b38c..7363b8b3a78 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -69,8 +69,6 @@ pub struct Session {
     pub parse_sess: ParseSess,
     /// For a library crate, this is always none
     pub entry_fn: Once<Option<(NodeId, Span, config::EntryFnType)>>,
-    pub plugin_registrar_fn: Once<Option<ast::NodeId>>,
-    pub proc_macro_decls_static: Once<Option<ast::NodeId>>,
     pub sysroot: PathBuf,
     /// The name of the root source file of the crate, in the local file system.
     /// `None` means that there is no source file.
@@ -1177,8 +1175,6 @@ pub fn build_session_(
         parse_sess: p_s,
         // For a library crate, this is always none
         entry_fn: Once::new(),
-        plugin_registrar_fn: Once::new(),
-        proc_macro_decls_static: Once::new(),
         sysroot,
         local_crate_source_file,
         working_dir,
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index 32d4070dfed..562cd75a75f 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -402,7 +402,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         // expensive for some DepKinds.
         if !self.dep_graph.is_fully_enabled() {
             let null_dep_node = DepNode::new_no_params(::dep_graph::DepKind::Null);
-            return self.force_query_with_job::<Q>(key, job, null_dep_node).map(|(v, _)| v);
+            return Ok(self.force_query_with_job::<Q>(key, job, null_dep_node).0);
         }
 
         let dep_node = Q::to_dep_node(self, &key);
@@ -436,20 +436,18 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
         if !dep_node.kind.is_input() {
             if let Some(dep_node_index) = self.try_mark_green_and_read(&dep_node) {
-                return self.load_from_disk_and_cache_in_memory::<Q>(key,
-                                                                    job,
-                                                                    dep_node_index,
-                                                                    &dep_node)
+                return Ok(self.load_from_disk_and_cache_in_memory::<Q>(
+                    key,
+                    job,
+                    dep_node_index,
+                    &dep_node
+                ))
             }
         }
 
-        match self.force_query_with_job::<Q>(key, job, dep_node) {
-            Ok((result, dep_node_index)) => {
-                self.dep_graph.read_index(dep_node_index);
-                Ok(result)
-            }
-            Err(e) => Err(e)
-        }
+        let (result, dep_node_index) = self.force_query_with_job::<Q>(key, job, dep_node);
+        self.dep_graph.read_index(dep_node_index);
+        Ok(result)
     }
 
     fn load_from_disk_and_cache_in_memory<Q: QueryDescription<'gcx>>(
@@ -458,7 +456,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         job: JobOwner<'a, 'gcx, Q>,
         dep_node_index: DepNodeIndex,
         dep_node: &DepNode
-    ) -> Result<Q::Value, Box<CycleError<'gcx>>>
+    ) -> Q::Value
     {
         // Note this function can be called concurrently from the same query
         // We must ensure that this is handled correctly
@@ -523,7 +521,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
         job.complete(&result, dep_node_index);
 
-        Ok(result)
+        result
     }
 
     #[inline(never)]
@@ -563,7 +561,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         key: Q::Key,
         job: JobOwner<'_, 'gcx, Q>,
         dep_node: DepNode)
-    -> Result<(Q::Value, DepNodeIndex), Box<CycleError<'gcx>>> {
+    -> (Q::Value, DepNodeIndex) {
         // If the following assertion triggers, it can have two reasons:
         // 1. Something is wrong with DepNode creation, either here or
         //    in DepGraph::try_mark_green()
@@ -610,7 +608,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
         job.complete(&result, dep_node_index);
 
-        Ok((result, dep_node_index))
+        (result, dep_node_index)
     }
 
     /// Ensure that either this query has all green inputs or been executed.
@@ -657,11 +655,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         // Ensure that only one of them runs the query
         let job = match JobOwner::try_get(self, span, &key) {
             TryGetJob::NotYetStarted(job) => job,
-            TryGetJob::JobCompleted(_) => return,
+            TryGetJob::JobCompleted(result) => {
+                if let Err(e) = result {
+                    self.report_cycle(e).emit();
+                }
+                return
+            }
         };
-        if let Err(e) = self.force_query_with_job::<Q>(key, job, dep_node) {
-            self.report_cycle(e).emit();
-        }
+        self.force_query_with_job::<Q>(key, job, dep_node);
     }
 
     pub(super) fn try_get_query<Q: QueryDescription<'gcx>>(
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index 928e171fe0f..bf69089a254 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -147,14 +147,12 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         })
         .collect();
 
-    if let Some(id) = *tcx.sess.proc_macro_decls_static.get() {
-        let def_id = tcx.hir().local_def_id(id);
-        reachable_non_generics.insert(def_id, SymbolExportLevel::C);
+    if let Some(id) = tcx.proc_macro_decls_static(LOCAL_CRATE) {
+        reachable_non_generics.insert(id, SymbolExportLevel::C);
     }
 
-    if let Some(id) = *tcx.sess.plugin_registrar_fn.get() {
-        let def_id = tcx.hir().local_def_id(id);
-        reachable_non_generics.insert(def_id, SymbolExportLevel::C);
+    if let Some(id) = tcx.plugin_registrar_fn(LOCAL_CRATE) {
+        reachable_non_generics.insert(id, SymbolExportLevel::C);
     }
 
     Lrc::new(reachable_non_generics)
diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs
index 5a5d1b20b21..9267f14f242 100644
--- a/src/librustc_codegen_utils/symbol_names.rs
+++ b/src/librustc_codegen_utils/symbol_names.rs
@@ -242,12 +242,12 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance
 
     let node_id = tcx.hir().as_local_node_id(def_id);
 
-    if let Some(id) = node_id {
-        if *tcx.sess.plugin_registrar_fn.get() == Some(id) {
+    if def_id.is_local() {
+        if tcx.plugin_registrar_fn(LOCAL_CRATE) == Some(def_id) {
             let disambiguator = tcx.sess.local_crate_disambiguator();
             return tcx.sess.generate_plugin_registrar_symbol(disambiguator);
         }
-        if *tcx.sess.proc_macro_decls_static.get() == Some(id) {
+        if tcx.proc_macro_decls_static(LOCAL_CRATE) == Some(def_id) {
             let disambiguator = tcx.sess.local_crate_disambiguator();
             return tcx.sess.generate_proc_macro_decls_symbol(disambiguator);
         }
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 380f9afd68d..3b7de37ae4b 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -1158,6 +1158,8 @@ where
 }
 
 pub fn default_provide(providers: &mut ty::query::Providers) {
+    proc_macro_decls::provide(providers);
+    plugin::build::provide(providers);
     hir::provide(providers);
     borrowck::provide(providers);
     mir::provide(providers);
@@ -1212,13 +1214,6 @@ where
         middle::entry::find_entry_point(sess, &hir_map, name)
     });
 
-    sess.plugin_registrar_fn
-        .set(time(sess, "looking for plugin registrar", || {
-            plugin::build::find_plugin_registrar(sess.diagnostic(), &hir_map)
-        }));
-    sess.proc_macro_decls_static
-        .set(proc_macro_decls::find(&hir_map));
-
     let mut local_providers = ty::query::Providers::default();
     default_provide(&mut local_providers);
     codegen_backend.provide(&mut local_providers);
@@ -1248,6 +1243,14 @@ where
             // tcx available.
             time(sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));
 
+            time(sess, "looking for plugin registrar", || {
+                plugin::build::find_plugin_registrar(tcx)
+            });
+
+            time(sess, "looking for derive registrar", || {
+                proc_macro_decls::find(tcx)
+            });
+
             time(sess, "loop checking", || loops::check_crate(tcx));
 
             time(sess, "attribute checking", || {
diff --git a/src/librustc_driver/proc_macro_decls.rs b/src/librustc_driver/proc_macro_decls.rs
index bb2ea6c2a97..093d15b7e3c 100644
--- a/src/librustc_driver/proc_macro_decls.rs
+++ b/src/librustc_driver/proc_macro_decls.rs
@@ -1,15 +1,25 @@
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::hir::map::Map;
+use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::hir;
+use rustc::ty::TyCtxt;
+use rustc::ty::query::Providers;
 use syntax::ast;
 use syntax::attr;
 
-pub fn find(hir_map: &Map) -> Option<ast::NodeId> {
-    let krate = hir_map.krate();
+pub fn find<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> Option<DefId> {
+    tcx.proc_macro_decls_static(LOCAL_CRATE)
+}
+
+fn proc_macro_decls_static<'tcx>(
+    tcx: TyCtxt<'_, 'tcx, 'tcx>,
+    cnum: CrateNum,
+) -> Option<DefId> {
+    assert_eq!(cnum, LOCAL_CRATE);
 
     let mut finder = Finder { decls: None };
-    krate.visit_all_item_likes(&mut finder);
-    finder.decls
+    tcx.hir().krate().visit_all_item_likes(&mut finder);
+
+    finder.decls.map(|id| tcx.hir().local_def_id(id))
 }
 
 struct Finder {
@@ -30,3 +40,9 @@ impl<'v> ItemLikeVisitor<'v> for Finder {
     }
 }
 
+pub(crate) fn provide(providers: &mut Providers<'_>) {
+    *providers = Providers {
+        proc_macro_decls_static,
+        ..*providers
+    };
+}
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 5678f30dabc..72bcf8edfdd 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -19,7 +19,7 @@
 //! a `pub fn new()`.
 
 use rustc::hir::def::Def;
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::ty::{self, Ty};
 use hir::Node;
 use util::nodemap::NodeSet;
@@ -860,7 +860,7 @@ impl LintPass for PluginAsLibrary {
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PluginAsLibrary {
     fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
-        if cx.sess().plugin_registrar_fn.get().is_some() {
+        if cx.tcx.plugin_registrar_fn(LOCAL_CRATE).is_some() {
             // We're compiling a plugin; it's fine to link other plugins.
             return;
         }
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 032a4656efc..2de1637fb0d 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -482,13 +482,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             has_global_allocator: has_global_allocator,
             has_panic_handler: has_panic_handler,
             has_default_lib_allocator: has_default_lib_allocator,
-            plugin_registrar_fn: tcx.sess
-                .plugin_registrar_fn
-                .get()
-                .map(|id| tcx.hir().local_def_id(id).index),
+            plugin_registrar_fn: tcx.plugin_registrar_fn(LOCAL_CRATE).map(|id| id.index),
             proc_macro_decls_static: if is_proc_macro {
-                let id = tcx.sess.proc_macro_decls_static.get().unwrap();
-                Some(tcx.hir().local_def_id(id).index)
+                let id = tcx.proc_macro_decls_static(LOCAL_CRATE).unwrap();
+                Some(id.index)
             } else {
                 None
             },
diff --git a/src/librustc_plugin/build.rs b/src/librustc_plugin/build.rs
index eca2736ee52..46c452668c3 100644
--- a/src/librustc_plugin/build.rs
+++ b/src/librustc_plugin/build.rs
@@ -2,11 +2,12 @@
 
 use syntax::ast;
 use syntax::attr;
-use errors;
 use syntax_pos::Span;
-use rustc::hir::map::Map;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::hir;
+use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc::ty::TyCtxt;
+use rustc::ty::query::Providers;
 
 struct RegistrarFinder {
     registrars: Vec<(ast::NodeId, Span)> ,
@@ -30,21 +31,27 @@ impl<'v> ItemLikeVisitor<'v> for RegistrarFinder {
 }
 
 /// Find the function marked with `#[plugin_registrar]`, if any.
-pub fn find_plugin_registrar(diagnostic: &errors::Handler,
-                             hir_map: &Map)
-                             -> Option<ast::NodeId> {
-    let krate = hir_map.krate();
+pub fn find_plugin_registrar<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> Option<DefId> {
+    tcx.plugin_registrar_fn(LOCAL_CRATE)
+}
+
+fn plugin_registrar_fn<'tcx>(
+    tcx: TyCtxt<'_, 'tcx, 'tcx>,
+    cnum: CrateNum,
+) -> Option<DefId> {
+    assert_eq!(cnum, LOCAL_CRATE);
 
     let mut finder = RegistrarFinder { registrars: Vec::new() };
-    krate.visit_all_item_likes(&mut finder);
+    tcx.hir().krate().visit_all_item_likes(&mut finder);
 
     match finder.registrars.len() {
         0 => None,
         1 => {
             let (node_id, _) = finder.registrars.pop().unwrap();
-            Some(node_id)
+            Some(tcx.hir().local_def_id(node_id))
         },
         _ => {
+            let diagnostic = tcx.sess.diagnostic();
             let mut e = diagnostic.struct_err("multiple plugin registration functions found");
             for &(_, span) in &finder.registrars {
                 e.span_note(span, "one is here");
@@ -55,3 +62,11 @@ pub fn find_plugin_registrar(diagnostic: &errors::Handler,
         }
     }
 }
+
+
+pub fn provide(providers: &mut Providers<'_>) {
+    *providers = Providers {
+        plugin_registrar_fn,
+        ..*providers
+    };
+}
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index c29b639984d..a25009ccfb4 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1015,7 +1015,7 @@ enum ModuleOrUniformRoot<'a> {
     CrateRootAndExternPrelude,
 
     /// Virtual module that denotes resolution in extern prelude.
-    /// Used for paths starting with `::` on 2018 edition or `extern::`.
+    /// Used for paths starting with `::` on 2018 edition.
     ExternPrelude,
 
     /// Virtual module that denotes resolution in current scope.
@@ -3836,8 +3836,7 @@ impl<'a> Resolver<'a> {
                             self.resolve_self(&mut ctxt, self.current_module)));
                         continue;
                     }
-                    if name == keywords::Extern.name() ||
-                       name == keywords::PathRoot.name() && ident.span.rust_2018() {
+                    if name == keywords::PathRoot.name() && ident.span.rust_2018() {
                         module = Some(ModuleOrUniformRoot::ExternPrelude);
                         continue;
                     }
@@ -4004,8 +4003,8 @@ impl<'a> Resolver<'a> {
         };
 
         // We're only interested in `use` paths which should start with
-        // `{{root}}` or `extern` currently.
-        if first_name != keywords::Extern.name() && first_name != keywords::PathRoot.name() {
+        // `{{root}}` currently.
+        if first_name != keywords::PathRoot.name() {
             return
         }
 
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index fbba89164e6..3f185ba1949 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -257,10 +257,28 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
                     .emit();
             }
             CastError::CastToBool => {
-                struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`")
-                    .span_label(self.span, "unsupported cast")
-                    .help("compare with zero instead")
-                    .emit();
+                let mut err =
+                    struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`");
+
+                if self.expr_ty.is_numeric() {
+                    match fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) {
+                        Ok(snippet) => {
+                            err.span_suggestion_with_applicability(
+                                self.span,
+                                "compare with zero instead",
+                                format!("{} != 0", snippet),
+                                Applicability::MachineApplicable,
+                            );
+                        }
+                        Err(_) => {
+                            err.span_help(self.span, "compare with zero instead");
+                        }
+                    }
+                } else {
+                    err.span_label(self.span, "unsupported cast");
+                }
+
+                err.emit();
             }
             CastError::CastToChar => {
                 type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0604,
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index 92145907b95..c55dd049ec6 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -410,9 +410,16 @@ impl<T, S> HashSet<T, S>
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a, T, S> {
-        Intersection {
-            iter: self.iter(),
-            other,
+        if self.len() <= other.len() {
+            Intersection {
+                iter: self.iter(),
+                other,
+            }
+        } else {
+            Intersection {
+                iter: other.iter(),
+                other: self,
+            }
         }
     }
 
@@ -436,7 +443,15 @@ impl<T, S> HashSet<T, S>
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn union<'a>(&'a self, other: &'a HashSet<T, S>) -> Union<'a, T, S> {
-        Union { iter: self.iter().chain(other.difference(self)) }
+        if self.len() <= other.len() {
+            Union {
+                iter: self.iter().chain(other.difference(self)),
+            }
+        } else {
+            Union {
+                iter: other.iter().chain(self.difference(other)),
+            }
+        }
     }
 
     /// Returns the number of elements in the set.
@@ -584,7 +599,11 @@ impl<T, S> HashSet<T, S>
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_disjoint(&self, other: &HashSet<T, S>) -> bool {
-        self.iter().all(|v| !other.contains(v))
+        if self.len() <= other.len() {
+            self.iter().all(|v| !other.contains(v))
+        } else {
+            other.iter().all(|v| !self.contains(v))
+        }
     }
 
     /// Returns `true` if the set is a subset of another,
@@ -1494,6 +1513,7 @@ mod test_set {
     fn test_intersection() {
         let mut a = HashSet::new();
         let mut b = HashSet::new();
+        assert!(a.intersection(&b).next().is_none());
 
         assert!(a.insert(11));
         assert!(a.insert(1));
@@ -1518,6 +1538,22 @@ mod test_set {
             i += 1
         }
         assert_eq!(i, expected.len());
+
+        assert!(a.insert(9)); // make a bigger than b
+
+        i = 0;
+        for x in a.intersection(&b) {
+            assert!(expected.contains(x));
+            i += 1
+        }
+        assert_eq!(i, expected.len());
+
+        i = 0;
+        for x in b.intersection(&a) {
+            assert!(expected.contains(x));
+            i += 1
+        }
+        assert_eq!(i, expected.len());
     }
 
     #[test]
@@ -1573,11 +1609,11 @@ mod test_set {
     fn test_union() {
         let mut a = HashSet::new();
         let mut b = HashSet::new();
+        assert!(a.union(&b).next().is_none());
+        assert!(b.union(&a).next().is_none());
 
         assert!(a.insert(1));
         assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
         assert!(a.insert(11));
         assert!(a.insert(16));
         assert!(a.insert(19));
@@ -1597,6 +1633,23 @@ mod test_set {
             i += 1
         }
         assert_eq!(i, expected.len());
+
+        assert!(a.insert(9)); // make a bigger than b
+        assert!(a.insert(5));
+
+        i = 0;
+        for x in a.union(&b) {
+            assert!(expected.contains(x));
+            i += 1
+        }
+        assert_eq!(i, expected.len());
+
+        i = 0;
+        for x in b.union(&a) {
+            assert!(expected.contains(x));
+            i += 1
+        }
+        assert_eq!(i, expected.len());
     }
 
     #[test]
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index ac20a62f117..ed278e834cb 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -25,9 +25,9 @@ use syntax_pos::{Span, DUMMY_SP};
 use errors::{DiagnosticBuilder, Handler};
 use visit::{self, FnKind, Visitor};
 use parse::ParseSess;
-use symbol::{keywords, Symbol};
+use symbol::Symbol;
 
-use std::{env};
+use std::env;
 
 macro_rules! set {
     ($field: ident) => {{
@@ -372,9 +372,6 @@ declare_features! (
     // Generic associated types (RFC 1598)
     (active, generic_associated_types, "1.23.0", Some(44265), None),
 
-    // `extern` in paths
-    (active, extern_in_paths, "1.23.0", Some(55600), None),
-
     // Infer static outlives requirements (RFC 2093).
     (active, infer_static_outlives_requirements, "1.26.0", Some(54185), None),
 
@@ -503,6 +500,9 @@ declare_features! (
     // Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`.
     (removed, custom_derive, "1.0.0", Some(29644), None,
      Some("subsumed by `#[proc_macro_derive]`")),
+    // Paths of the form: `extern::foo::bar`
+    (removed, extern_in_paths, "1.33.0", Some(55600), None,
+     Some("subsumed by `::foo::bar` paths")),
 );
 
 declare_features! (
@@ -1827,25 +1827,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         visit::walk_impl_item(self, ii);
     }
 
-    fn visit_path(&mut self, path: &'a ast::Path, _id: NodeId) {
-        for segment in &path.segments {
-            // Identifiers we are going to check could come from a legacy macro (e.g., `#[test]`).
-            // For such macros identifiers must have empty context, because this context is
-            // used during name resolution and produced names must be unhygienic for compatibility.
-            // On the other hand, we need the actual non-empty context for feature gate checking
-            // because it's hygienic even for legacy macros. As previously stated, such context
-            // cannot be kept in identifiers, so it's kept in paths instead and we take it from
-            // there while keeping location info from the ident span.
-            let span = segment.ident.span.with_ctxt(path.span.ctxt());
-            if segment.ident.name == keywords::Extern.name() {
-                gate_feature_post!(&self, extern_in_paths, span,
-                                   "`extern` in paths is experimental");
-            }
-        }
-
-        visit::walk_path(self, path);
-    }
-
     fn visit_vis(&mut self, vis: &'a ast::Visibility) {
         if let ast::VisibilityKind::Crate(ast::CrateSugar::JustCrate) = vis.node {
             gate_feature_post!(&self, crate_visibility_modifier, vis.span,
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index ecb34e43c59..0e1c3b4b61f 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -299,7 +299,7 @@ impl<'a> StringReader<'a> {
 
     /// Report a lexical error with a given span.
     fn err_span(&self, sp: Span, m: &str) {
-        self.sess.span_diagnostic.span_err(sp, m)
+        self.sess.span_diagnostic.struct_span_err(sp, m).emit();
     }
 
 
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index ba5676a65d7..ea205530ca5 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -520,6 +520,7 @@ fn filtered_float_lit(data: Symbol, suffix: Option<Symbol>, diag: Option<(Span,
                 } else {
                     let msg = format!("invalid suffix `{}` for float literal", suf);
                     diag.struct_span_err(span, &msg)
+                        .span_label(span, format!("invalid suffix `{}`", suf))
                         .help("valid suffixes are `f32` and `f64`")
                         .emit();
                 }
@@ -673,7 +674,11 @@ fn integer_lit(s: &str, suffix: Option<Symbol>, diag: Option<(Span, &Handler)>)
                 _ => None,
             };
             if let Some(err) = err {
-                err!(diag, |span, diag| diag.span_err(span, err));
+                err!(diag, |span, diag| {
+                    diag.struct_span_err(span, err)
+                        .span_label(span, "not supported")
+                        .emit();
+                });
             }
             return filtered_float_lit(Symbol::intern(s), Some(suf), diag)
         }
@@ -712,6 +717,7 @@ fn integer_lit(s: &str, suffix: Option<Symbol>, diag: Option<(Span, &Handler)>)
                     } else {
                         let msg = format!("invalid suffix `{}` for numeric literal", suf);
                         diag.struct_span_err(span, &msg)
+                            .span_label(span, format!("invalid suffix `{}`", suf))
                             .help("the suffix must be one of the integral types \
                                    (`u32`, `isize`, etc)")
                             .emit();
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 5c8ed94731a..823c786bded 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1012,7 +1012,10 @@ impl<'a> Parser<'a> {
                 if text.is_empty() {
                     self.span_bug(sp, "found empty literal suffix in Some")
                 }
-                self.span_err(sp, &format!("{} with a suffix is invalid", kind));
+                let msg = format!("{} with a suffix is invalid", kind);
+                self.struct_span_err(sp, &msg)
+                    .span_label(sp, msg)
+                    .emit();
             }
         }
     }
@@ -1299,7 +1302,7 @@ impl<'a> Parser<'a> {
     fn token_is_bare_fn_keyword(&mut self) -> bool {
         self.check_keyword(keywords::Fn) ||
             self.check_keyword(keywords::Unsafe) ||
-            self.check_keyword(keywords::Extern) && self.is_extern_non_path()
+            self.check_keyword(keywords::Extern)
     }
 
     /// parse a `TyKind::BareFn` type:
@@ -1768,9 +1771,11 @@ impl<'a> Parser<'a> {
             Mutability::Immutable
         } else {
             let span = self.prev_span;
-            self.span_err(span,
-                          "expected mut or const in raw pointer type (use \
-                           `*mut T` or `*const T` as appropriate)");
+            let msg = "expected mut or const in raw pointer type";
+            self.struct_span_err(span, msg)
+                .span_label(span, msg)
+                .help("use `*mut T` or `*const T` as appropriate")
+                .emit();
             Mutability::Immutable
         };
         let t = self.parse_ty_no_plus()?;
@@ -3815,8 +3820,12 @@ impl<'a> Parser<'a> {
                     ddpos = Some(fields.len());
                 } else {
                     // Emit a friendly error, ignore `..` and continue parsing
-                    self.span_err(self.prev_span,
-                                  "`..` can only be used once per tuple or tuple struct pattern");
+                    self.struct_span_err(
+                        self.prev_span,
+                        "`..` can only be used once per tuple or tuple struct pattern",
+                    )
+                        .span_label(self.prev_span, "can only be used once per pattern")
+                        .emit();
                 }
             } else if !self.check(&token::CloseDelim(token::Paren)) {
                 fields.push(self.parse_pat(None)?);
@@ -3832,7 +3841,10 @@ impl<'a> Parser<'a> {
 
         if ddpos == Some(fields.len()) && trailing_comma {
             // `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed.
-            self.span_err(self.prev_span, "trailing comma is not permitted after `..`");
+            let msg = "trailing comma is not permitted after `..`";
+            self.struct_span_err(self.prev_span, msg)
+                .span_label(self.prev_span, msg)
+                .emit();
         }
 
         Ok((fields, ddpos, trailing_comma))
@@ -4605,10 +4617,6 @@ impl<'a> Parser<'a> {
         self.token.is_keyword(keywords::Crate) && self.look_ahead(1, |t| t != &token::ModSep)
     }
 
-    fn is_extern_non_path(&self) -> bool {
-        self.token.is_keyword(keywords::Extern) && self.look_ahead(1, |t| t != &token::ModSep)
-    }
-
     fn is_existential_type_decl(&self) -> bool {
         self.token.is_keyword(keywords::Existential) &&
         self.look_ahead(1, |t| t.is_keyword(keywords::Type))
@@ -4712,12 +4720,10 @@ impl<'a> Parser<'a> {
         // like a path (1 token), but it fact not a path.
         // `union::b::c` - path, `union U { ... }` - not a path.
         // `crate::b::c` - path, `crate struct S;` - not a path.
-        // `extern::b::c` - path, `extern crate c;` - not a path.
         } else if self.token.is_path_start() &&
                   !self.token.is_qpath_start() &&
                   !self.is_union_item() &&
                   !self.is_crate_vis() &&
-                  !self.is_extern_non_path() &&
                   !self.is_existential_type_decl() &&
                   !self.is_auto_trait_item() {
             let pth = self.parse_path(PathStyle::Expr)?;
@@ -5256,8 +5262,12 @@ impl<'a> Parser<'a> {
                 // Check for trailing attributes and stop parsing.
                 if !attrs.is_empty() {
                     let param_kind = if seen_ty_param.is_some() { "type" } else { "lifetime" };
-                    self.span_err(attrs[0].span,
-                        &format!("trailing attribute after {} parameters", param_kind));
+                    self.struct_span_err(
+                        attrs[0].span,
+                        &format!("trailing attribute after {} parameters", param_kind),
+                    )
+                    .span_label(attrs[0].span, "attributes must go before parameters")
+                    .emit();
                 }
                 break
             }
@@ -5315,19 +5325,28 @@ impl<'a> Parser<'a> {
 
     /// Parses (possibly empty) list of lifetime and type arguments and associated type bindings,
     /// possibly including trailing comma.
-    fn parse_generic_args(&mut self)
-                          -> PResult<'a, (Vec<GenericArg>, Vec<TypeBinding>)> {
+    fn parse_generic_args(&mut self) -> PResult<'a, (Vec<GenericArg>, Vec<TypeBinding>)> {
         let mut args = Vec::new();
         let mut bindings = Vec::new();
         let mut seen_type = false;
         let mut seen_binding = false;
+        let mut first_type_or_binding_span: Option<Span> = None;
+        let mut bad_lifetime_pos = vec![];
+        let mut last_comma_span = None;
+        let mut suggestions = vec![];
         loop {
             if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
                 // Parse lifetime argument.
                 args.push(GenericArg::Lifetime(self.expect_lifetime()));
                 if seen_type || seen_binding {
-                    self.span_err(self.prev_span,
-                        "lifetime parameters must be declared prior to type parameters");
+                    let remove_sp = last_comma_span.unwrap_or(self.prev_span).to(self.prev_span);
+                    bad_lifetime_pos.push(self.prev_span);
+                    if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.prev_span) {
+                        suggestions.push((remove_sp, String::new()));
+                        suggestions.push((
+                            first_type_or_binding_span.unwrap().shrink_to_lo(),
+                            format!("{}, ", snippet)));
+                    }
                 }
             } else if self.check_ident() && self.look_ahead(1, |t| t == &token::Eq) {
                 // Parse associated type binding.
@@ -5335,19 +5354,33 @@ impl<'a> Parser<'a> {
                 let ident = self.parse_ident()?;
                 self.bump();
                 let ty = self.parse_ty()?;
+                let span = lo.to(self.prev_span);
                 bindings.push(TypeBinding {
                     id: ast::DUMMY_NODE_ID,
                     ident,
                     ty,
-                    span: lo.to(self.prev_span),
+                    span,
                 });
                 seen_binding = true;
+                if first_type_or_binding_span.is_none() {
+                    first_type_or_binding_span = Some(span);
+                }
             } else if self.check_type() {
                 // Parse type argument.
                 let ty_param = self.parse_ty()?;
                 if seen_binding {
-                    self.span_err(ty_param.span,
-                        "type parameters must be declared prior to associated type bindings");
+                    self.struct_span_err(
+                        ty_param.span,
+                        "type parameters must be declared prior to associated type bindings"
+                    )
+                        .span_label(
+                            ty_param.span,
+                            "must be declared prior to associated type bindings",
+                        )
+                        .emit();
+                }
+                if first_type_or_binding_span.is_none() {
+                    first_type_or_binding_span = Some(ty_param.span);
                 }
                 args.push(GenericArg::Type(ty_param));
                 seen_type = true;
@@ -5357,8 +5390,30 @@ impl<'a> Parser<'a> {
 
             if !self.eat(&token::Comma) {
                 break
+            } else {
+                last_comma_span = Some(self.prev_span);
             }
         }
+        if !bad_lifetime_pos.is_empty() {
+            let mut err = self.struct_span_err(
+                bad_lifetime_pos.clone(),
+                "lifetime parameters must be declared prior to type parameters"
+            );
+            for sp in &bad_lifetime_pos {
+                err.span_label(*sp, "must be declared prior to type parameters");
+            }
+            if !suggestions.is_empty() {
+                err.multipart_suggestion_with_applicability(
+                    &format!(
+                        "move the lifetime parameter{} prior to the first type parameter",
+                        if bad_lifetime_pos.len() > 1 { "s" } else { "" },
+                    ),
+                    suggestions,
+                    Applicability::MachineApplicable,
+                );
+            }
+            err.emit();
+        }
         Ok((args, bindings))
     }
 
@@ -5386,8 +5441,12 @@ impl<'a> Parser<'a> {
         // change we parse those generics now, but report an error.
         if self.choose_generics_over_qpath() {
             let generics = self.parse_generics()?;
-            self.span_err(generics.span,
-                          "generic parameters on `where` clauses are reserved for future use");
+            self.struct_span_err(
+                generics.span,
+                "generic parameters on `where` clauses are reserved for future use",
+            )
+                .span_label(generics.span, "currently unsupported")
+                .emit();
         }
 
         loop {
@@ -5587,15 +5646,20 @@ impl<'a> Parser<'a> {
                 // *mut self
                 // *not_self
                 // Emit special error for `self` cases.
+                let msg = "cannot pass `self` by raw pointer";
                 (if isolated_self(self, 1) {
                     self.bump();
-                    self.span_err(self.span, "cannot pass `self` by raw pointer");
+                    self.struct_span_err(self.span, msg)
+                        .span_label(self.span, msg)
+                        .emit();
                     SelfKind::Value(Mutability::Immutable)
                 } else if self.look_ahead(1, |t| t.is_mutability()) &&
                           isolated_self(self, 2) {
                     self.bump();
                     self.bump();
-                    self.span_err(self.span, "cannot pass `self` by raw pointer");
+                    self.struct_span_err(self.span, msg)
+                        .span_label(self.span, msg)
+                        .emit();
                     SelfKind::Value(Mutability::Immutable)
                 } else {
                     return Ok(None);
@@ -5932,7 +5996,10 @@ impl<'a> Parser<'a> {
             tps.where_clause = self.parse_where_clause()?;
             self.expect(&token::Semi)?;
             if unsafety != Unsafety::Normal {
-                self.span_err(self.prev_span, "trait aliases cannot be unsafe");
+                let msg = "trait aliases cannot be unsafe";
+                self.struct_span_err(self.prev_span, msg)
+                    .span_label(self.prev_span, msg)
+                    .emit();
             }
             Ok((ident, ItemKind::TraitAlias(tps, bounds), None))
         } else {
@@ -6048,7 +6115,13 @@ impl<'a> Parser<'a> {
             Some(ty_second) => {
                 // impl Trait for Type
                 if !has_for {
-                    self.span_err(missing_for_span, "missing `for` in a trait impl");
+                    self.struct_span_err(missing_for_span, "missing `for` in a trait impl")
+                        .span_suggestion_short_with_applicability(
+                            missing_for_span,
+                            "add `for` here",
+                            " for ".to_string(),
+                            Applicability::MachineApplicable,
+                        ).emit();
                 }
 
                 let ty_first = ty_first.into_inner();
@@ -6409,41 +6482,52 @@ impl<'a> Parser<'a> {
         }
     }
 
+    fn maybe_consume_incorrect_semicolon(&mut self, items: &[P<Item>]) -> bool {
+        if self.eat(&token::Semi) {
+            let mut err = self.struct_span_err(self.prev_span, "expected item, found `;`");
+            err.span_suggestion_short_with_applicability(
+                self.prev_span,
+                "remove this semicolon",
+                String::new(),
+                Applicability::MachineApplicable,
+            );
+            if !items.is_empty() {
+                let previous_item = &items[items.len()-1];
+                let previous_item_kind_name = match previous_item.node {
+                    // say "braced struct" because tuple-structs and
+                    // braceless-empty-struct declarations do take a semicolon
+                    ItemKind::Struct(..) => Some("braced struct"),
+                    ItemKind::Enum(..) => Some("enum"),
+                    ItemKind::Trait(..) => Some("trait"),
+                    ItemKind::Union(..) => Some("union"),
+                    _ => None,
+                };
+                if let Some(name) = previous_item_kind_name {
+                    err.help(&format!("{} declarations are not followed by a semicolon", name));
+                }
+            }
+            err.emit();
+            true
+        } else {
+            false
+        }
+    }
+
     /// Given a termination token, parse all of the items in a module
     fn parse_mod_items(&mut self, term: &token::Token, inner_lo: Span) -> PResult<'a, Mod> {
         let mut items = vec![];
         while let Some(item) = self.parse_item()? {
             items.push(item);
+            self.maybe_consume_incorrect_semicolon(&items);
         }
 
         if !self.eat(term) {
             let token_str = self.this_token_descr();
-            let mut err = self.fatal(&format!("expected item, found {}", token_str));
-            if self.token == token::Semi {
-                let msg = "consider removing this semicolon";
-                err.span_suggestion_short_with_applicability(
-                    self.span, msg, String::new(), Applicability::MachineApplicable
-                );
-                if !items.is_empty() {  // Issue #51603
-                    let previous_item = &items[items.len()-1];
-                    let previous_item_kind_name = match previous_item.node {
-                        // say "braced struct" because tuple-structs and
-                        // braceless-empty-struct declarations do take a semicolon
-                        ItemKind::Struct(..) => Some("braced struct"),
-                        ItemKind::Enum(..) => Some("enum"),
-                        ItemKind::Trait(..) => Some("trait"),
-                        ItemKind::Union(..) => Some("union"),
-                        _ => None,
-                    };
-                    if let Some(name) = previous_item_kind_name {
-                        err.help(&format!("{} declarations are not followed by a semicolon",
-                                          name));
-                    }
-                }
-            } else {
+            if !self.maybe_consume_incorrect_semicolon(&items) {
+                let mut err = self.fatal(&format!("expected item, found {}", token_str));
                 err.span_label(self.span, "expected item");
+                return Err(err);
             }
-            return Err(err);
         }
 
         let hi = if self.span.is_dummy() {
@@ -6939,7 +7023,7 @@ impl<'a> Parser<'a> {
     fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef> {
         let mut variants = Vec::new();
         let mut all_nullary = true;
-        let mut any_disr = None;
+        let mut any_disr = vec![];
         while self.token != token::CloseDelim(token::Brace) {
             let variant_attrs = self.parse_outer_attributes()?;
             let vlo = self.span;
@@ -6961,7 +7045,9 @@ impl<'a> Parser<'a> {
                     id: ast::DUMMY_NODE_ID,
                     value: self.parse_expr()?,
                 });
-                any_disr = disr_expr.as_ref().map(|c| c.value.span);
+                if let Some(sp) = disr_expr.as_ref().map(|c| c.value.span) {
+                    any_disr.push(sp);
+                }
                 struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
             } else {
                 struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
@@ -6978,11 +7064,15 @@ impl<'a> Parser<'a> {
             if !self.eat(&token::Comma) { break; }
         }
         self.expect(&token::CloseDelim(token::Brace))?;
-        match any_disr {
-            Some(disr_span) if !all_nullary =>
-                self.span_err(disr_span,
-                    "discriminator values can only be used with a field-less enum"),
-            _ => ()
+        if !any_disr.is_empty() && !all_nullary {
+            let mut err =self.struct_span_err(
+                any_disr.clone(),
+                "discriminator values can only be used with a field-less enum",
+            );
+            for sp in any_disr {
+                err.span_label(sp, "only valid in field-less enums");
+            }
+            err.emit();
         }
 
         Ok(ast::EnumDef { variants })
@@ -7113,8 +7203,7 @@ impl<'a> Parser<'a> {
             return Ok(Some(item));
         }
 
-        if self.check_keyword(keywords::Extern) && self.is_extern_non_path() {
-            self.bump(); // `extern`
+        if self.eat_keyword(keywords::Extern) {
             if self.eat_keyword(keywords::Crate) {
                 return Ok(Some(self.parse_item_extern_crate(lo, visibility, attrs)?));
             }
@@ -7623,7 +7712,7 @@ impl<'a> Parser<'a> {
     fn parse_assoc_macro_invoc(&mut self, item_kind: &str, vis: Option<&Visibility>,
                                at_end: &mut bool) -> PResult<'a, Option<Mac>>
     {
-        if self.token.is_path_start() && !self.is_extern_non_path() {
+        if self.token.is_path_start() {
             let prev_span = self.prev_span;
             let lo = self.span;
             let pth = self.parse_path(PathStyle::Mod)?;
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 76d47f421b3..e741b79bd4c 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -478,7 +478,6 @@ impl Ident {
         self.name == keywords::Super.name() ||
         self.name == keywords::SelfLower.name() ||
         self.name == keywords::SelfUpper.name() ||
-        self.name == keywords::Extern.name() ||
         self.name == keywords::Crate.name() ||
         self.name == keywords::PathRoot.name() ||
         self.name == keywords::DollarCrate.name()
diff --git a/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile b/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile
index 2b931d89f1f..bf98fcd10cf 100644
--- a/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile
+++ b/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile
@@ -1,12 +1,9 @@
 -include ../tools.mk
 
-all: extern_absolute_paths.rs extern_in_paths.rs krate2
+all: extern_absolute_paths.rs krate2
 	$(RUSTC) extern_absolute_paths.rs -Zsave-analysis --edition=2018 \
 		-Z unstable-options --extern krate2
 	cat $(TMPDIR)/save-analysis/extern_absolute_paths.json | "$(PYTHON)" validate_json.py
-	$(RUSTC) extern_in_paths.rs -Zsave-analysis --edition=2018 \
-		-Z unstable-options --extern krate2
-	cat $(TMPDIR)/save-analysis/extern_in_paths.json | "$(PYTHON)" validate_json.py
 
 krate2: krate2.rs
 	$(RUSTC) $<
diff --git a/src/test/run-make-fulldeps/save-analysis-rfc2126/extern_in_paths.rs b/src/test/run-make-fulldeps/save-analysis-rfc2126/extern_in_paths.rs
deleted file mode 100644
index 299b96621ac..00000000000
--- a/src/test/run-make-fulldeps/save-analysis-rfc2126/extern_in_paths.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-#![feature(extern_in_paths)]
-
-use extern::krate2;
-
-fn main() {
-    extern::krate2::hello();
-}
diff --git a/src/test/run-pass/rfcs/rfc-2126-extern-absolute-paths/extern.rs b/src/test/run-pass/rfcs/rfc-2126-extern-absolute-paths/extern.rs
deleted file mode 100644
index 165a753c8a4..00000000000
--- a/src/test/run-pass/rfcs/rfc-2126-extern-absolute-paths/extern.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-// aux-build:xcrate.rs
-// compile-flags:--extern xcrate
-
-#![feature(extern_in_paths)]
-
-use extern::xcrate::Z;
-
-type A = extern::xcrate::S;
-type B = for<'a> extern::xcrate::Tr<'a>;
-
-fn f() {
-    use extern::xcrate;
-    use extern::xcrate as ycrate;
-    let s = xcrate::S;
-    assert_eq!(format!("{:?}", s), "S");
-    let z = ycrate::Z;
-    assert_eq!(format!("{:?}", z), "Z");
-}
-
-fn main() {
-    let s = extern::xcrate::S;
-    assert_eq!(format!("{:?}", s), "S");
-    let z = Z;
-    assert_eq!(format!("{:?}", z), "Z");
-    assert_eq!(A {}, extern::xcrate::S {});
-}
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr
index 75c0d91ee17..c4c0cee5ccc 100644
--- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-1.stderr
@@ -2,7 +2,7 @@ error: trailing attribute after lifetime parameters
   --> $DIR/attrs-with-no-formal-in-generics-1.rs:9:25
    |
 LL | impl<#[rustc_1] 'a, 'b, #[oops]> RefIntPair<'a, 'b> {
-   |                         ^^^^^^^
+   |                         ^^^^^^^ attributes must go before parameters
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr
index 7585c6dd738..9099d74ce1b 100644
--- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-2.stderr
@@ -2,7 +2,7 @@ error: trailing attribute after type parameters
   --> $DIR/attrs-with-no-formal-in-generics-2.rs:9:35
    |
 LL | impl<#[rustc_1] 'a, #[rustc_2] T, #[oops]> RefAny<'a, T> {}
-   |                                   ^^^^^^^
+   |                                   ^^^^^^^ attributes must go before parameters
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs
index 343a2d7a563..e9f908d479f 100644
--- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.rs
@@ -5,12 +5,8 @@
 struct RefIntPair<'a, 'b>(&'a u32, &'b u32);
 
 fn hof_lt<Q>(_: Q)
-    where Q: for <#[rustc_1] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
+    where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
     //~^ ERROR trailing attribute after lifetime parameters
-{
+{}
 
-}
-
-fn main() {
-
-}
+fn main() {}
diff --git a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr
index 91960510de4..452f0ea5e17 100644
--- a/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr
+++ b/src/test/ui/attrs-with-no-formal-in-generics/attrs-with-no-formal-in-generics-3.stderr
@@ -1,8 +1,8 @@
 error: trailing attribute after lifetime parameters
-  --> $DIR/attrs-with-no-formal-in-generics-3.rs:8:38
+  --> $DIR/attrs-with-no-formal-in-generics-3.rs:8:44
    |
-LL |     where Q: for <#[rustc_1] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
-   |                                      ^^^^^^^
+LL |     where Q: for <#[allow(unused)] 'a, 'b, #[oops]> Fn(RefIntPair<'a,'b>) -> &'b u32
+   |                                            ^^^^^^^ attributes must go before parameters
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/cast/cast-as-bool.rs b/src/test/ui/cast/cast-as-bool.rs
index 7a0bd0ec098..8130f4dedc9 100644
--- a/src/test/ui/cast/cast-as-bool.rs
+++ b/src/test/ui/cast/cast-as-bool.rs
@@ -1,4 +1,9 @@
 fn main() {
-    let u = 5 as bool;
-    //~^ ERROR cannot cast as `bool`
+    let u = 5 as bool; //~ ERROR cannot cast as `bool`
+                       //~| HELP compare with zero instead
+                       //~| SUGGESTION 5 != 0
+    let t = (1 + 2) as bool; //~ ERROR cannot cast as `bool`
+                             //~| HELP compare with zero instead
+                             //~| SUGGESTION (1 + 2) != 0
+    let v = "hello" as bool; //~ ERROR cannot cast as `bool`
 }
diff --git a/src/test/ui/cast/cast-as-bool.stderr b/src/test/ui/cast/cast-as-bool.stderr
index 086d08a569a..6099a4195b3 100644
--- a/src/test/ui/cast/cast-as-bool.stderr
+++ b/src/test/ui/cast/cast-as-bool.stderr
@@ -1,11 +1,21 @@
 error[E0054]: cannot cast as `bool`
   --> $DIR/cast-as-bool.rs:2:13
    |
-LL |     let u = 5 as bool;
-   |             ^^^^^^^^^ unsupported cast
+LL |     let u = 5 as bool; //~ ERROR cannot cast as `bool`
+   |             ^^^^^^^^^ help: compare with zero instead: `5 != 0`
+
+error[E0054]: cannot cast as `bool`
+  --> $DIR/cast-as-bool.rs:5:13
+   |
+LL |     let t = (1 + 2) as bool; //~ ERROR cannot cast as `bool`
+   |             ^^^^^^^^^^^^^^^ help: compare with zero instead: `(1 + 2) != 0`
+
+error[E0054]: cannot cast as `bool`
+  --> $DIR/cast-as-bool.rs:8:13
    |
-   = help: compare with zero instead
+LL |     let v = "hello" as bool; //~ ERROR cannot cast as `bool`
+   |             ^^^^^^^^^^^^^^^ unsupported cast
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0054`.
diff --git a/src/test/ui/cast/cast-rfc0401-2.stderr b/src/test/ui/cast/cast-rfc0401-2.stderr
index 3bf6e5367f0..52f6af78a9b 100644
--- a/src/test/ui/cast/cast-rfc0401-2.stderr
+++ b/src/test/ui/cast/cast-rfc0401-2.stderr
@@ -2,9 +2,7 @@ error[E0054]: cannot cast as `bool`
   --> $DIR/cast-rfc0401-2.rs:6:13
    |
 LL |     let _ = 3 as bool;
-   |             ^^^^^^^^^ unsupported cast
-   |
-   = help: compare with zero instead
+   |             ^^^^^^^^^ help: compare with zero instead: `3 != 0`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0054.stderr b/src/test/ui/error-codes/E0054.stderr
index 416029c5f86..cce32fa2944 100644
--- a/src/test/ui/error-codes/E0054.stderr
+++ b/src/test/ui/error-codes/E0054.stderr
@@ -2,9 +2,7 @@ error[E0054]: cannot cast as `bool`
   --> $DIR/E0054.rs:3:24
    |
 LL |     let x_is_nonzero = x as bool; //~ ERROR E0054
-   |                        ^^^^^^^^^ unsupported cast
-   |
-   = help: compare with zero instead
+   |                        ^^^^^^^^^ help: compare with zero instead: `x != 0`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-festival.stderr b/src/test/ui/error-festival.stderr
index a600ff14d3b..ff6504e9688 100644
--- a/src/test/ui/error-festival.stderr
+++ b/src/test/ui/error-festival.stderr
@@ -52,9 +52,7 @@ error[E0054]: cannot cast as `bool`
   --> $DIR/error-festival.rs:33:24
    |
 LL |     let x_is_nonzero = x as bool;
-   |                        ^^^^^^^^^ unsupported cast
-   |
-   = help: compare with zero instead
+   |                        ^^^^^^^^^ help: compare with zero instead: `x != 0`
 
 error[E0606]: casting `&u8` as `u32` is invalid
   --> $DIR/error-festival.rs:37:18
diff --git a/src/test/ui/feature-gates/feature-gate-extern_in_paths.rs b/src/test/ui/feature-gates/feature-gate-extern_in_paths.rs
deleted file mode 100644
index 2d23d13d247..00000000000
--- a/src/test/ui/feature-gates/feature-gate-extern_in_paths.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-struct S;
-
-fn main() {
-    let _ = extern::std::vec::Vec::new(); //~ ERROR `extern` in paths is experimental
-}
diff --git a/src/test/ui/feature-gates/feature-gate-extern_in_paths.stderr b/src/test/ui/feature-gates/feature-gate-extern_in_paths.stderr
deleted file mode 100644
index 6b5963b8559..00000000000
--- a/src/test/ui/feature-gates/feature-gate-extern_in_paths.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: `extern` in paths is experimental (see issue #55600)
-  --> $DIR/feature-gate-extern_in_paths.rs:4:13
-   |
-LL |     let _ = extern::std::vec::Vec::new(); //~ ERROR `extern` in paths is experimental
-   |             ^^^^^^
-   |
-   = help: add #![feature(extern_in_paths)] to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-46186.rs b/src/test/ui/issues/issue-46186.rs
index de7d13a2280..9dfd61fdf3f 100644
--- a/src/test/ui/issues/issue-46186.rs
+++ b/src/test/ui/issues/issue-46186.rs
@@ -1,5 +1,6 @@
 struct Struct {
     a: usize,
-}; //~ ERROR expected item, found `;`
+};
+//~^ ERROR expected item, found `;`
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-46186.stderr b/src/test/ui/issues/issue-46186.stderr
index 11a1fc072c9..eb0dbb8aa41 100644
--- a/src/test/ui/issues/issue-46186.stderr
+++ b/src/test/ui/issues/issue-46186.stderr
@@ -1,8 +1,8 @@
 error: expected item, found `;`
   --> $DIR/issue-46186.rs:3:2
    |
-LL | }; //~ ERROR expected item, found `;`
-   |  ^ help: consider removing this semicolon
+LL | };
+   |  ^ help: remove this semicolon
    |
    = help: braced struct declarations are not followed by a semicolon
 
diff --git a/src/test/ui/issues/issue-49040.rs b/src/test/ui/issues/issue-49040.rs
index 7c8d3d0ee69..a5f05d2824e 100644
--- a/src/test/ui/issues/issue-49040.rs
+++ b/src/test/ui/issues/issue-49040.rs
@@ -1,2 +1,2 @@
 #![allow(unused_variables)]; //~ ERROR expected item, found `;`
-fn main() {}
+fn foo() {}
diff --git a/src/test/ui/issues/issue-49040.stderr b/src/test/ui/issues/issue-49040.stderr
index eec88f0c3f3..12e78e2f3bc 100644
--- a/src/test/ui/issues/issue-49040.stderr
+++ b/src/test/ui/issues/issue-49040.stderr
@@ -2,7 +2,12 @@ error: expected item, found `;`
   --> $DIR/issue-49040.rs:1:28
    |
 LL | #![allow(unused_variables)]; //~ ERROR expected item, found `;`
-   |                            ^ help: consider removing this semicolon
+   |                            ^ help: remove this semicolon
 
-error: aborting due to previous error
+error[E0601]: `main` function not found in crate `issue_49040`
+   |
+   = note: consider adding a `main` function to `$DIR/issue-49040.rs`
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-expr.rs b/src/test/ui/keyword/extern/keyword-extern-as-identifier-expr.rs
new file mode 100644
index 00000000000..b738eb4c703
--- /dev/null
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-expr.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let s = extern::foo::Bar; //~ ERROR expected expression, found keyword `extern`
+}
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-expr.stderr b/src/test/ui/keyword/extern/keyword-extern-as-identifier-expr.stderr
new file mode 100644
index 00000000000..150fc88e7ef
--- /dev/null
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-expr.stderr
@@ -0,0 +1,8 @@
+error: expected expression, found keyword `extern`
+  --> $DIR/keyword-extern-as-identifier-expr.rs:2:13
+   |
+LL |     let s = extern::foo::Bar; //~ ERROR expected expression, found keyword `extern`
+   |             ^^^^^^ expected expression
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs
new file mode 100644
index 00000000000..f9b6bad7c25
--- /dev/null
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.rs
@@ -0,0 +1,3 @@
+fn main() {
+    let extern = 0; //~ ERROR expected pattern, found keyword `extern`
+}
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr
new file mode 100644
index 00000000000..426b4eef056
--- /dev/null
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-pat.stderr
@@ -0,0 +1,8 @@
+error: expected pattern, found keyword `extern`
+  --> $DIR/keyword-extern-as-identifier-pat.rs:2:9
+   |
+LL |     let extern = 0; //~ ERROR expected pattern, found keyword `extern`
+   |         ^^^^^^ expected pattern
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-type.rs b/src/test/ui/keyword/extern/keyword-extern-as-identifier-type.rs
new file mode 100644
index 00000000000..3845a9aa017
--- /dev/null
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-type.rs
@@ -0,0 +1,3 @@
+type A = extern::foo::bar; //~ ERROR expected `fn`, found `::`
+
+fn main() {}
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-type.stderr b/src/test/ui/keyword/extern/keyword-extern-as-identifier-type.stderr
new file mode 100644
index 00000000000..97b641fbea5
--- /dev/null
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-type.stderr
@@ -0,0 +1,8 @@
+error: expected `fn`, found `::`
+  --> $DIR/keyword-extern-as-identifier-type.rs:1:16
+   |
+LL | type A = extern::foo::bar; //~ ERROR expected `fn`, found `::`
+   |                ^^ expected `fn` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs
new file mode 100644
index 00000000000..b07de3e341c
--- /dev/null
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs
@@ -0,0 +1,3 @@
+use extern::foo; //~ ERROR expected identifier, found keyword `extern`
+
+fn main() {}
diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr
new file mode 100644
index 00000000000..31b575a92e0
--- /dev/null
+++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr
@@ -0,0 +1,12 @@
+error: expected identifier, found keyword `extern`
+  --> $DIR/keyword-extern-as-identifier-use.rs:1:5
+   |
+LL | use extern::foo; //~ ERROR expected identifier, found keyword `extern`
+   |     ^^^^^^ expected identifier, found keyword
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL | use r#extern::foo; //~ ERROR expected identifier, found keyword `extern`
+   |     ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/keyword/keyword-extern-as-identifier.rs b/src/test/ui/keyword/keyword-extern-as-identifier.rs
deleted file mode 100644
index 6775290a26b..00000000000
--- a/src/test/ui/keyword/keyword-extern-as-identifier.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-#![feature(extern_in_paths)]
-
-fn main() {
-    let extern = 0; //~ ERROR cannot find unit struct/variant or constant `extern` in this scope
-}
diff --git a/src/test/ui/keyword/keyword-extern-as-identifier.stderr b/src/test/ui/keyword/keyword-extern-as-identifier.stderr
deleted file mode 100644
index ef2a4b3ff3c..00000000000
--- a/src/test/ui/keyword/keyword-extern-as-identifier.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0531]: cannot find unit struct/variant or constant `extern` in this scope
-  --> $DIR/keyword-extern-as-identifier.rs:4:9
-   |
-LL |     let extern = 0; //~ ERROR cannot find unit struct/variant or constant `extern` in this scope
-   |         ^^^^^^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0531`.
diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr
index fbe5e6d4099..76091f2d09e 100644
--- a/src/test/ui/mismatched_types/cast-rfc0401.stderr
+++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr
@@ -90,17 +90,13 @@ error[E0054]: cannot cast as `bool`
   --> $DIR/cast-rfc0401.rs:39:13
    |
 LL |     let _ = 3_i32 as bool; //~ ERROR cannot cast
-   |             ^^^^^^^^^^^^^ unsupported cast
-   |
-   = help: compare with zero instead
+   |             ^^^^^^^^^^^^^ help: compare with zero instead: `3_i32 != 0`
 
 error[E0054]: cannot cast as `bool`
   --> $DIR/cast-rfc0401.rs:40:13
    |
 LL |     let _ = E::A as bool; //~ ERROR cannot cast
    |             ^^^^^^^^^^^^ unsupported cast
-   |
-   = help: compare with zero instead
 
 error[E0604]: only `u8` can be cast as `char`, not `u32`
   --> $DIR/cast-rfc0401.rs:41:13
diff --git a/src/test/ui/old-suffixes-are-really-forbidden.stderr b/src/test/ui/old-suffixes-are-really-forbidden.stderr
index 557e7ef6794..c54b72a3585 100644
--- a/src/test/ui/old-suffixes-are-really-forbidden.stderr
+++ b/src/test/ui/old-suffixes-are-really-forbidden.stderr
@@ -2,7 +2,7 @@ error: invalid suffix `is` for numeric literal
   --> $DIR/old-suffixes-are-really-forbidden.rs:2:13
    |
 LL |     let a = 1_is; //~ ERROR invalid suffix
-   |             ^^^^
+   |             ^^^^ invalid suffix `is`
    |
    = help: the suffix must be one of the integral types (`u32`, `isize`, etc)
 
@@ -10,7 +10,7 @@ error: invalid suffix `us` for numeric literal
   --> $DIR/old-suffixes-are-really-forbidden.rs:3:13
    |
 LL |     let b = 2_us; //~ ERROR invalid suffix
-   |             ^^^^
+   |             ^^^^ invalid suffix `us`
    |
    = help: the suffix must be one of the integral types (`u32`, `isize`, etc)
 
diff --git a/src/test/ui/parser/bad-lit-suffixes.stderr b/src/test/ui/parser/bad-lit-suffixes.stderr
index 4fd2ab8177b..608c5fda248 100644
--- a/src/test/ui/parser/bad-lit-suffixes.stderr
+++ b/src/test/ui/parser/bad-lit-suffixes.stderr
@@ -2,49 +2,49 @@ error: ABI spec with a suffix is invalid
   --> $DIR/bad-lit-suffixes.rs:5:5
    |
 LL |     "C"suffix //~ ERROR ABI spec with a suffix is invalid
-   |     ^^^^^^^^^
+   |     ^^^^^^^^^ ABI spec with a suffix is invalid
 
 error: ABI spec with a suffix is invalid
   --> $DIR/bad-lit-suffixes.rs:9:5
    |
 LL |     "C"suffix //~ ERROR ABI spec with a suffix is invalid
-   |     ^^^^^^^^^
+   |     ^^^^^^^^^ ABI spec with a suffix is invalid
 
 error: string literal with a suffix is invalid
   --> $DIR/bad-lit-suffixes.rs:13:5
    |
 LL |     ""suffix; //~ ERROR string literal with a suffix is invalid
-   |     ^^^^^^^^
+   |     ^^^^^^^^ string literal with a suffix is invalid
 
 error: byte string literal with a suffix is invalid
   --> $DIR/bad-lit-suffixes.rs:14:5
    |
 LL |     b""suffix; //~ ERROR byte string literal with a suffix is invalid
-   |     ^^^^^^^^^
+   |     ^^^^^^^^^ byte string literal with a suffix is invalid
 
 error: string literal with a suffix is invalid
   --> $DIR/bad-lit-suffixes.rs:15:5
    |
 LL |     r#""#suffix; //~ ERROR string literal with a suffix is invalid
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^ string literal with a suffix is invalid
 
 error: byte string literal with a suffix is invalid
   --> $DIR/bad-lit-suffixes.rs:16:5
    |
 LL |     br#""#suffix; //~ ERROR byte string literal with a suffix is invalid
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^ byte string literal with a suffix is invalid
 
 error: char literal with a suffix is invalid
   --> $DIR/bad-lit-suffixes.rs:17:5
    |
 LL |     'a'suffix; //~ ERROR char literal with a suffix is invalid
-   |     ^^^^^^^^^
+   |     ^^^^^^^^^ char literal with a suffix is invalid
 
 error: byte literal with a suffix is invalid
   --> $DIR/bad-lit-suffixes.rs:18:5
    |
 LL |     b'a'suffix; //~ ERROR byte literal with a suffix is invalid
-   |     ^^^^^^^^^^
+   |     ^^^^^^^^^^ byte literal with a suffix is invalid
 
 error: invalid width `1024` for integer literal
   --> $DIR/bad-lit-suffixes.rs:20:5
@@ -82,7 +82,7 @@ error: invalid suffix `suffix` for numeric literal
   --> $DIR/bad-lit-suffixes.rs:25:5
    |
 LL |     1234suffix; //~ ERROR invalid suffix `suffix` for numeric literal
-   |     ^^^^^^^^^^
+   |     ^^^^^^^^^^ invalid suffix `suffix`
    |
    = help: the suffix must be one of the integral types (`u32`, `isize`, etc)
 
@@ -90,7 +90,7 @@ error: invalid suffix `suffix` for numeric literal
   --> $DIR/bad-lit-suffixes.rs:26:5
    |
 LL |     0b101suffix; //~ ERROR invalid suffix `suffix` for numeric literal
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^ invalid suffix `suffix`
    |
    = help: the suffix must be one of the integral types (`u32`, `isize`, etc)
 
@@ -98,7 +98,7 @@ error: invalid suffix `suffix` for float literal
   --> $DIR/bad-lit-suffixes.rs:27:5
    |
 LL |     1.0suffix; //~ ERROR invalid suffix `suffix` for float literal
-   |     ^^^^^^^^^
+   |     ^^^^^^^^^ invalid suffix `suffix`
    |
    = help: valid suffixes are `f32` and `f64`
 
@@ -106,7 +106,7 @@ error: invalid suffix `suffix` for float literal
   --> $DIR/bad-lit-suffixes.rs:28:5
    |
 LL |     1.0e10suffix; //~ ERROR invalid suffix `suffix` for float literal
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^ invalid suffix `suffix`
    |
    = help: valid suffixes are `f32` and `f64`
 
diff --git a/src/test/ui/parser/bad-pointer-type.rs b/src/test/ui/parser/bad-pointer-type.rs
index 0e5a01103dc..59e5e0c5d31 100644
--- a/src/test/ui/parser/bad-pointer-type.rs
+++ b/src/test/ui/parser/bad-pointer-type.rs
@@ -1,5 +1,5 @@
 fn foo(_: *()) {
-    //~^ expected mut or const in raw pointer type (use `*mut T` or `*const T` as appropriate)
+    //~^ ERROR expected mut or const in raw pointer type
 }
 
 fn main() {}
diff --git a/src/test/ui/parser/bad-pointer-type.stderr b/src/test/ui/parser/bad-pointer-type.stderr
index 860f9f96bb8..e18c220affe 100644
--- a/src/test/ui/parser/bad-pointer-type.stderr
+++ b/src/test/ui/parser/bad-pointer-type.stderr
@@ -1,8 +1,10 @@
-error: expected mut or const in raw pointer type (use `*mut T` or `*const T` as appropriate)
+error: expected mut or const in raw pointer type
   --> $DIR/bad-pointer-type.rs:1:11
    |
 LL | fn foo(_: *()) {
-   |           ^
+   |           ^ expected mut or const in raw pointer type
+   |
+   = help: use `*mut T` or `*const T` as appropriate
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/impl-parsing.stderr b/src/test/ui/parser/impl-parsing.stderr
index 308f14c60c7..353f5e21ee6 100644
--- a/src/test/ui/parser/impl-parsing.stderr
+++ b/src/test/ui/parser/impl-parsing.stderr
@@ -2,13 +2,13 @@ error: missing `for` in a trait impl
   --> $DIR/impl-parsing.rs:6:11
    |
 LL | impl Trait Type {} //~ ERROR missing `for` in a trait impl
-   |           ^
+   |           ^ help: add `for` here
 
 error: missing `for` in a trait impl
   --> $DIR/impl-parsing.rs:7:11
    |
 LL | impl Trait .. {} //~ ERROR missing `for` in a trait impl
-   |           ^
+   |           ^ help: add `for` here
 
 error: expected a trait, found type
   --> $DIR/impl-parsing.rs:8:6
diff --git a/src/test/ui/parser/issue-14303-fncall.rs b/src/test/ui/parser/issue-14303-fncall.rs
index f5894349e15..17b9b766b21 100644
--- a/src/test/ui/parser/issue-14303-fncall.rs
+++ b/src/test/ui/parser/issue-14303-fncall.rs
@@ -1,6 +1,17 @@
-fn main() {
-    (0..4)
-    .map(|x| x * 2)
-    .collect::<Vec<'a, usize, 'b>>()
-    //~^ ERROR lifetime parameters must be declared prior to type parameters
+// can't run rustfix because it doesn't handle multipart suggestions correctly
+// compile-flags: -Zborrowck=mir
+// we need the above to avoid ast borrowck failure in recovered code
+
+struct S<'a, T> {
+    a: &'a T,
+    b: &'a T,
 }
+
+fn foo<'a, 'b>(start: &'a usize, end: &'a usize) {
+    let _x = (*start..*end)
+        .map(|x| S { a: start, b: end })
+        .collect::<Vec<S<_, 'a>>>();
+        //~^ ERROR lifetime parameters must be declared prior to type parameters
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-14303-fncall.stderr b/src/test/ui/parser/issue-14303-fncall.stderr
index 1cc82f523c4..2a736491594 100644
--- a/src/test/ui/parser/issue-14303-fncall.stderr
+++ b/src/test/ui/parser/issue-14303-fncall.stderr
@@ -1,8 +1,12 @@
 error: lifetime parameters must be declared prior to type parameters
-  --> $DIR/issue-14303-fncall.rs:4:31
+  --> $DIR/issue-14303-fncall.rs:13:29
    |
-LL |     .collect::<Vec<'a, usize, 'b>>()
-   |                               ^^
+LL |         .collect::<Vec<S<_, 'a>>>();
+   |                             ^^ must be declared prior to type parameters
+help: move the lifetime parameter prior to the first type parameter
+   |
+LL |         .collect::<Vec<S<'a, _>>>();
+   |                          ^^^ --
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-14303-path.rs b/src/test/ui/parser/issue-14303-path.rs
index f61cb6b8dd6..a08c89f3437 100644
--- a/src/test/ui/parser/issue-14303-path.rs
+++ b/src/test/ui/parser/issue-14303-path.rs
@@ -1,4 +1,13 @@
-fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {}
+mod foo {
+    pub struct X<'a, 'b, 'c, T> {
+        a: &'a str,
+        b: &'b str,
+        c: &'c str,
+        t: T,
+    }
+}
+
+fn bar<'a, 'b, 'c, T>(x: foo::X<'a, T, 'b, 'c>) {}
 //~^ ERROR lifetime parameters must be declared prior to type parameters
 
 fn main() {}
diff --git a/src/test/ui/parser/issue-14303-path.stderr b/src/test/ui/parser/issue-14303-path.stderr
index 3de8a169c69..fb4fb32e11e 100644
--- a/src/test/ui/parser/issue-14303-path.stderr
+++ b/src/test/ui/parser/issue-14303-path.stderr
@@ -1,8 +1,14 @@
 error: lifetime parameters must be declared prior to type parameters
-  --> $DIR/issue-14303-path.rs:1:37
+  --> $DIR/issue-14303-path.rs:10:40
    |
-LL | fn bar<'a, T>(x: mymodule::X<'a, T, 'b, 'c>) {}
-   |                                     ^^
+LL | fn bar<'a, 'b, 'c, T>(x: foo::X<'a, T, 'b, 'c>) {}
+   |                                        ^^  ^^ must be declared prior to type parameters
+   |                                        |
+   |                                        must be declared prior to type parameters
+help: move the lifetime parameters prior to the first type parameter
+   |
+LL | fn bar<'a, 'b, 'c, T>(x: foo::X<'a, 'b, 'c, T>) {}
+   |                                     ^^^ ^^^ --
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-17383.rs b/src/test/ui/parser/issue-17383.rs
index 9c00289287c..04cd43d0b10 100644
--- a/src/test/ui/parser/issue-17383.rs
+++ b/src/test/ui/parser/issue-17383.rs
@@ -1,8 +1,7 @@
 enum X {
-    A =
-        b'a' //~ ERROR discriminator values can only be used with a field-less enum
-    ,
-    B(isize)
+    A = 3,
+    //~^ ERROR discriminator values can only be used with a field-less enum
+    B(usize)
 }
 
 fn main() {}
diff --git a/src/test/ui/parser/issue-17383.stderr b/src/test/ui/parser/issue-17383.stderr
index b225e11066d..57caa3372a6 100644
--- a/src/test/ui/parser/issue-17383.stderr
+++ b/src/test/ui/parser/issue-17383.stderr
@@ -1,8 +1,8 @@
 error: discriminator values can only be used with a field-less enum
-  --> $DIR/issue-17383.rs:3:9
+  --> $DIR/issue-17383.rs:2:9
    |
-LL |         b'a' //~ ERROR discriminator values can only be used with a field-less enum
-   |         ^^^^
+LL |     A = 3,
+   |         ^ only valid in field-less enums
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-1802-1.rs b/src/test/ui/parser/issue-1802-1.rs
index 050e9a258d1..3c34b0d8feb 100644
--- a/src/test/ui/parser/issue-1802-1.rs
+++ b/src/test/ui/parser/issue-1802-1.rs
@@ -1,4 +1,7 @@
-// error-pattern:no valid digits found for number
+fn log(a: i32, b: i32) {}
+
 fn main() {
+    let error = 42;
     log(error, 0b);
+    //~^ ERROR no valid digits found for number
 }
diff --git a/src/test/ui/parser/issue-1802-1.stderr b/src/test/ui/parser/issue-1802-1.stderr
index 5cd6a4f7c68..b7d003df56b 100644
--- a/src/test/ui/parser/issue-1802-1.stderr
+++ b/src/test/ui/parser/issue-1802-1.stderr
@@ -1,5 +1,5 @@
 error: no valid digits found for number
-  --> $DIR/issue-1802-1.rs:3:16
+  --> $DIR/issue-1802-1.rs:5:16
    |
 LL |     log(error, 0b);
    |                ^^
diff --git a/src/test/ui/parser/issue-1802-2.rs b/src/test/ui/parser/issue-1802-2.rs
index 796db66d22e..3c34b0d8feb 100644
--- a/src/test/ui/parser/issue-1802-2.rs
+++ b/src/test/ui/parser/issue-1802-2.rs
@@ -1,4 +1,7 @@
-// error-pattern:no valid digits found for number
+fn log(a: i32, b: i32) {}
+
 fn main() {
-    log(error, 0b_usize);
+    let error = 42;
+    log(error, 0b);
+    //~^ ERROR no valid digits found for number
 }
diff --git a/src/test/ui/parser/issue-1802-2.stderr b/src/test/ui/parser/issue-1802-2.stderr
index c6c04279666..8491dd07cb7 100644
--- a/src/test/ui/parser/issue-1802-2.stderr
+++ b/src/test/ui/parser/issue-1802-2.stderr
@@ -1,8 +1,8 @@
 error: no valid digits found for number
-  --> $DIR/issue-1802-2.rs:3:16
+  --> $DIR/issue-1802-2.rs:5:16
    |
-LL |     log(error, 0b_usize);
-   |                ^^^
+LL |     log(error, 0b);
+   |                ^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-27255.rs b/src/test/ui/parser/issue-27255.rs
index c0ff331b8ba..d619688e101 100644
--- a/src/test/ui/parser/issue-27255.rs
+++ b/src/test/ui/parser/issue-27255.rs
@@ -1,3 +1,10 @@
-impl A .. {} //~ ERROR
+trait A {}
+
+impl A .. {}
+//~^ ERROR missing `for` in a trait impl
+//~| ERROR `impl Trait for .. {}` is an obsolete syntax
+
+impl A      usize {}
+//~^ ERROR missing `for` in a trait impl
 
 fn main() {}
diff --git a/src/test/ui/parser/issue-27255.stderr b/src/test/ui/parser/issue-27255.stderr
index 6d09d82e34f..391a23556c4 100644
--- a/src/test/ui/parser/issue-27255.stderr
+++ b/src/test/ui/parser/issue-27255.stderr
@@ -1,8 +1,22 @@
 error: missing `for` in a trait impl
-  --> $DIR/issue-27255.rs:1:7
+  --> $DIR/issue-27255.rs:3:7
    |
-LL | impl A .. {} //~ ERROR
-   |       ^
+LL | impl A .. {}
+   |       ^ help: add `for` here
 
-error: aborting due to previous error
+error: missing `for` in a trait impl
+  --> $DIR/issue-27255.rs:7:7
+   |
+LL | impl A      usize {}
+   |       ^^^^^^ help: add `for` here
+
+error: `impl Trait for .. {}` is an obsolete syntax
+  --> $DIR/issue-27255.rs:3:1
+   |
+LL | impl A .. {}
+   | ^^^^^^^^^^^^
+   |
+   = help: use `auto trait Trait {}` instead
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/parser/issue-32214.stderr b/src/test/ui/parser/issue-32214.stderr
index a01517d016d..a889513eaee 100644
--- a/src/test/ui/parser/issue-32214.stderr
+++ b/src/test/ui/parser/issue-32214.stderr
@@ -2,7 +2,7 @@ error: type parameters must be declared prior to associated type bindings
   --> $DIR/issue-32214.rs:5:34
    |
 LL | pub fn test<W, I: Trait<Item=(), W> >() {}
-   |                                  ^
+   |                                  ^ must be declared prior to associated type bindings
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/lex-bad-numeric-literals.stderr b/src/test/ui/parser/lex-bad-numeric-literals.stderr
index b1a91705533..1fa23b8b73c 100644
--- a/src/test/ui/parser/lex-bad-numeric-literals.stderr
+++ b/src/test/ui/parser/lex-bad-numeric-literals.stderr
@@ -110,7 +110,7 @@ error: octal float literal is not supported
   --> $DIR/lex-bad-numeric-literals.rs:5:5
    |
 LL |     0o2f32; //~ ERROR: octal float literal is not supported
-   |     ^^^^^^
+   |     ^^^^^^ not supported
 
 error: int literal is too large
   --> $DIR/lex-bad-numeric-literals.rs:16:5
@@ -128,13 +128,13 @@ error: octal float literal is not supported
   --> $DIR/lex-bad-numeric-literals.rs:23:5
    |
 LL |     0o123f64; //~ ERROR: octal float literal is not supported
-   |     ^^^^^^^^
+   |     ^^^^^^^^ not supported
 
 error: binary float literal is not supported
   --> $DIR/lex-bad-numeric-literals.rs:25:5
    |
 LL |     0b101f64; //~ ERROR: binary float literal is not supported
-   |     ^^^^^^^^
+   |     ^^^^^^^^ not supported
 
 error: aborting due to 23 previous errors
 
diff --git a/src/test/ui/parser/no-binary-float-literal.rs b/src/test/ui/parser/no-binary-float-literal.rs
index c078bf5f63e..a42d2cbc442 100644
--- a/src/test/ui/parser/no-binary-float-literal.rs
+++ b/src/test/ui/parser/no-binary-float-literal.rs
@@ -1,7 +1,8 @@
-// error-pattern:binary float literal is not supported
-
 fn main() {
     0b101010f64;
+    //~^ ERROR binary float literal is not supported
     0b101.010;
+    //~^ ERROR binary float literal is not supported
     0b101p4f64;
+    //~^ ERROR invalid suffix `p4f64` for numeric literal
 }
diff --git a/src/test/ui/parser/no-binary-float-literal.stderr b/src/test/ui/parser/no-binary-float-literal.stderr
index 7ff3e28ccb6..21f415bcfb0 100644
--- a/src/test/ui/parser/no-binary-float-literal.stderr
+++ b/src/test/ui/parser/no-binary-float-literal.stderr
@@ -1,8 +1,22 @@
 error: binary float literal is not supported
-  --> $DIR/no-binary-float-literal.rs:5:5
+  --> $DIR/no-binary-float-literal.rs:4:5
    |
 LL |     0b101.010;
    |     ^^^^^^^^^
 
-error: aborting due to previous error
+error: binary float literal is not supported
+  --> $DIR/no-binary-float-literal.rs:2:5
+   |
+LL |     0b101010f64;
+   |     ^^^^^^^^^^^ not supported
+
+error: invalid suffix `p4f64` for numeric literal
+  --> $DIR/no-binary-float-literal.rs:6:5
+   |
+LL |     0b101p4f64;
+   |     ^^^^^^^^^^ invalid suffix `p4f64`
+   |
+   = help: the suffix must be one of the integral types (`u32`, `isize`, etc)
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/parser/no-hex-float-literal.rs b/src/test/ui/parser/no-hex-float-literal.rs
index d830c96fc2f..bf11dee0833 100644
--- a/src/test/ui/parser/no-hex-float-literal.rs
+++ b/src/test/ui/parser/no-hex-float-literal.rs
@@ -1,7 +1,9 @@
-// error-pattern:hexadecimal float literal is not supported
-
 fn main() {
     0xABC.Df;
+    //~^ ERROR `{integer}` is a primitive type and therefore doesn't have fields
     0x567.89;
+    //~^ ERROR hexadecimal float literal is not supported
     0xDEAD.BEEFp-2f;
+    //~^ ERROR invalid suffix `f` for float literal
+    //~| ERROR `{integer}` is a primitive type and therefore doesn't have fields
 }
diff --git a/src/test/ui/parser/no-hex-float-literal.stderr b/src/test/ui/parser/no-hex-float-literal.stderr
index 1668cfe5a33..258ab06d5ee 100644
--- a/src/test/ui/parser/no-hex-float-literal.stderr
+++ b/src/test/ui/parser/no-hex-float-literal.stderr
@@ -1,8 +1,29 @@
 error: hexadecimal float literal is not supported
-  --> $DIR/no-hex-float-literal.rs:5:5
+  --> $DIR/no-hex-float-literal.rs:4:5
    |
 LL |     0x567.89;
    |     ^^^^^^^^
 
-error: aborting due to previous error
+error: invalid suffix `f` for float literal
+  --> $DIR/no-hex-float-literal.rs:6:18
+   |
+LL |     0xDEAD.BEEFp-2f;
+   |                  ^^ invalid suffix `f`
+   |
+   = help: valid suffixes are `f32` and `f64`
+
+error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
+  --> $DIR/no-hex-float-literal.rs:2:11
+   |
+LL |     0xABC.Df;
+   |           ^^
+
+error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
+  --> $DIR/no-hex-float-literal.rs:6:12
+   |
+LL |     0xDEAD.BEEFp-2f;
+   |            ^^^^^
+
+error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0610`.
diff --git a/src/test/ui/parser/no-unsafe-self.stderr b/src/test/ui/parser/no-unsafe-self.stderr
index 364c22a9622..84779b09dc7 100644
--- a/src/test/ui/parser/no-unsafe-self.stderr
+++ b/src/test/ui/parser/no-unsafe-self.stderr
@@ -2,37 +2,37 @@ error: cannot pass `self` by raw pointer
   --> $DIR/no-unsafe-self.rs:4:17
    |
 LL |     fn foo(*mut self); //~ ERROR cannot pass `self` by raw pointer
-   |                 ^^^^
+   |                 ^^^^ cannot pass `self` by raw pointer
 
 error: cannot pass `self` by raw pointer
   --> $DIR/no-unsafe-self.rs:5:19
    |
 LL |     fn baz(*const self); //~ ERROR cannot pass `self` by raw pointer
-   |                   ^^^^
+   |                   ^^^^ cannot pass `self` by raw pointer
 
 error: cannot pass `self` by raw pointer
   --> $DIR/no-unsafe-self.rs:6:13
    |
 LL |     fn bar(*self); //~ ERROR cannot pass `self` by raw pointer
-   |             ^^^^
+   |             ^^^^ cannot pass `self` by raw pointer
 
 error: cannot pass `self` by raw pointer
   --> $DIR/no-unsafe-self.rs:11:17
    |
 LL |     fn foo(*mut self) { } //~ ERROR cannot pass `self` by raw pointer
-   |                 ^^^^
+   |                 ^^^^ cannot pass `self` by raw pointer
 
 error: cannot pass `self` by raw pointer
   --> $DIR/no-unsafe-self.rs:12:19
    |
 LL |     fn baz(*const self) { } //~ ERROR cannot pass `self` by raw pointer
-   |                   ^^^^
+   |                   ^^^^ cannot pass `self` by raw pointer
 
 error: cannot pass `self` by raw pointer
   --> $DIR/no-unsafe-self.rs:13:13
    |
 LL |     fn bar(*self) { } //~ ERROR cannot pass `self` by raw pointer
-   |             ^^^^
+   |             ^^^^ cannot pass `self` by raw pointer
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/parser/pat-tuple-2.rs b/src/test/ui/parser/pat-tuple-2.rs
index 108278fa58e..fd25499381a 100644
--- a/src/test/ui/parser/pat-tuple-2.rs
+++ b/src/test/ui/parser/pat-tuple-2.rs
@@ -1,5 +1,6 @@
 fn main() {
-    match 0 {
-        (pat, ..,) => {} //~ ERROR trailing comma is not permitted after `..`
+    match (0, 1, 2) {
+        (pat, ..,) => {}
+        //~^ ERROR trailing comma is not permitted after `..`
     }
 }
diff --git a/src/test/ui/parser/pat-tuple-2.stderr b/src/test/ui/parser/pat-tuple-2.stderr
index ec123363566..c3a5c39a8e3 100644
--- a/src/test/ui/parser/pat-tuple-2.stderr
+++ b/src/test/ui/parser/pat-tuple-2.stderr
@@ -1,8 +1,8 @@
 error: trailing comma is not permitted after `..`
   --> $DIR/pat-tuple-2.rs:3:17
    |
-LL |         (pat, ..,) => {} //~ ERROR trailing comma is not permitted after `..`
-   |                 ^
+LL |         (pat, ..,) => {}
+   |                 ^ trailing comma is not permitted after `..`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/pat-tuple-3.rs b/src/test/ui/parser/pat-tuple-3.rs
index 63dcde45bfb..e1e975d3c3e 100644
--- a/src/test/ui/parser/pat-tuple-3.rs
+++ b/src/test/ui/parser/pat-tuple-3.rs
@@ -1,5 +1,6 @@
 fn main() {
-    match 0 {
-        (.., pat, ..) => {} //~ ERROR `..` can only be used once per tuple or tuple struct pattern
+    match (0, 1, 2) {
+        (.., pat, ..) => {}
+        //~^ ERROR `..` can only be used once per tuple or tuple struct pattern
     }
 }
diff --git a/src/test/ui/parser/pat-tuple-3.stderr b/src/test/ui/parser/pat-tuple-3.stderr
index 90940eb1723..0ad7d27b94e 100644
--- a/src/test/ui/parser/pat-tuple-3.stderr
+++ b/src/test/ui/parser/pat-tuple-3.stderr
@@ -1,8 +1,8 @@
 error: `..` can only be used once per tuple or tuple struct pattern
   --> $DIR/pat-tuple-3.rs:3:19
    |
-LL |         (.., pat, ..) => {} //~ ERROR `..` can only be used once per tuple or tuple struct pattern
-   |                   ^^
+LL |         (.., pat, ..) => {}
+   |                   ^^ can only be used once per pattern
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.rs b/src/test/ui/parser/tag-variant-disr-non-nullary.rs
index 35a36cbbf91..83a3b727982 100644
--- a/src/test/ui/parser/tag-variant-disr-non-nullary.rs
+++ b/src/test/ui/parser/tag-variant-disr-non-nullary.rs
@@ -1,12 +1,11 @@
-//error-pattern: discriminator values can only be used with a field-less enum
-
-enum color {
-    red = 0xff0000,
-    green = 0x00ff00,
-    blue = 0x0000ff,
-    black = 0x000000,
-    white = 0xffffff,
-    other (str),
+enum Color {
+    Red = 0xff0000,
+    //~^ ERROR discriminator values can only be used with a field-less enum
+    Green = 0x00ff00,
+    Blue = 0x0000ff,
+    Black = 0x000000,
+    White = 0xffffff,
+    Other(usize),
 }
 
 fn main() {}
diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.stderr b/src/test/ui/parser/tag-variant-disr-non-nullary.stderr
index aa45ea4ac26..cc6312b4545 100644
--- a/src/test/ui/parser/tag-variant-disr-non-nullary.stderr
+++ b/src/test/ui/parser/tag-variant-disr-non-nullary.stderr
@@ -1,8 +1,17 @@
 error: discriminator values can only be used with a field-less enum
-  --> $DIR/tag-variant-disr-non-nullary.rs:8:13
+  --> $DIR/tag-variant-disr-non-nullary.rs:2:11
    |
-LL |     white = 0xffffff,
-   |             ^^^^^^^^
+LL |     Red = 0xff0000,
+   |           ^^^^^^^^ only valid in field-less enums
+LL |     //~^ ERROR discriminator values can only be used with a field-less enum
+LL |     Green = 0x00ff00,
+   |             ^^^^^^^^ only valid in field-less enums
+LL |     Blue = 0x0000ff,
+   |            ^^^^^^^^ only valid in field-less enums
+LL |     Black = 0x000000,
+   |             ^^^^^^^^ only valid in field-less enums
+LL |     White = 0xffffff,
+   |             ^^^^^^^^ only valid in field-less enums
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/where_with_bound.rs b/src/test/ui/parser/where_with_bound.rs
index 3a1edb9ffc9..3ca45f1889c 100644
--- a/src/test/ui/parser/where_with_bound.rs
+++ b/src/test/ui/parser/where_with_bound.rs
@@ -1,4 +1,5 @@
 fn foo<T>() where <T>::Item: ToString, T: Iterator { }
 //~^ ERROR generic parameters on `where` clauses are reserved for future use
+//~| ERROR cannot find type `Item` in the crate root
 
 fn main() {}
diff --git a/src/test/ui/parser/where_with_bound.stderr b/src/test/ui/parser/where_with_bound.stderr
index e68f7445558..ff98b3f5fed 100644
--- a/src/test/ui/parser/where_with_bound.stderr
+++ b/src/test/ui/parser/where_with_bound.stderr
@@ -2,7 +2,14 @@ error: generic parameters on `where` clauses are reserved for future use
   --> $DIR/where_with_bound.rs:1:19
    |
 LL | fn foo<T>() where <T>::Item: ToString, T: Iterator { }
-   |                   ^^^
+   |                   ^^^ currently unsupported
 
-error: aborting due to previous error
+error[E0412]: cannot find type `Item` in the crate root
+  --> $DIR/where_with_bound.rs:1:24
+   |
+LL | fn foo<T>() where <T>::Item: ToString, T: Iterator { }
+   |                        ^^^^ not found in the crate root
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/rfc-2126-extern-in-paths/auxiliary/xcrate.rs b/src/test/ui/rfc-2126-extern-in-paths/auxiliary/xcrate.rs
deleted file mode 100644
index c4d44476445..00000000000
--- a/src/test/ui/rfc-2126-extern-in-paths/auxiliary/xcrate.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-#[derive(Debug)]
-pub struct S;
-
-#[derive(Debug)]
-pub struct Z;
diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.rs b/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.rs
deleted file mode 100644
index 5e5e6c6eebf..00000000000
--- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-#![feature(extern_in_paths)]
-
-use extern::xcrate::S; //~ ERROR unresolved import `extern::xcrate`
-
-fn main() {}
diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.stderr b/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.stderr
deleted file mode 100644
index 5b7528c2ed9..00000000000
--- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-1.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0432]: unresolved import `extern::xcrate`
-  --> $DIR/non-existent-1.rs:3:13
-   |
-LL | use extern::xcrate::S; //~ ERROR unresolved import `extern::xcrate`
-   |             ^^^^^^ could not find `xcrate` in `extern`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.rs b/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.rs
deleted file mode 100644
index 0f26eef5d7e..00000000000
--- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#![feature(extern_in_paths)]
-
-fn main() {
-    let s = extern::xcrate::S;
-    //~^ ERROR failed to resolve: could not find `xcrate` in `extern`
-}
diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.stderr b/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.stderr
deleted file mode 100644
index 21c2a0c14d6..00000000000
--- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-2.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0433]: failed to resolve: could not find `xcrate` in `extern`
-  --> $DIR/non-existent-2.rs:4:21
-   |
-LL |     let s = extern::xcrate::S;
-   |                     ^^^^^^ could not find `xcrate` in `extern`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.rs b/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.rs
deleted file mode 100644
index 1875fb99fe8..00000000000
--- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-#![feature(extern_in_paths)]
-
-use extern::ycrate; //~ ERROR unresolved import `extern::ycrate`
-
-fn main() {}
diff --git a/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.stderr b/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.stderr
deleted file mode 100644
index e2e7df648c6..00000000000
--- a/src/test/ui/rfc-2126-extern-in-paths/non-existent-3.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0432]: unresolved import `extern::ycrate`
-  --> $DIR/non-existent-3.rs:3:5
-   |
-LL | use extern::ycrate; //~ ERROR unresolved import `extern::ycrate`
-   |     ^^^^^^^^^^^^^^ no `ycrate` external crate
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/rfc-2126-extern-in-paths/single-segment.rs b/src/test/ui/rfc-2126-extern-in-paths/single-segment.rs
deleted file mode 100644
index 1d5af1e9d86..00000000000
--- a/src/test/ui/rfc-2126-extern-in-paths/single-segment.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// aux-build:xcrate.rs
-// compile-flags:--extern xcrate
-
-#![feature(extern_in_paths)]
-
-use extern; //~ ERROR unresolved import `extern`
-            //~^ NOTE no `extern` in the root
-use extern::*; //~ ERROR cannot glob-import all possible crates
-
-fn main() {
-    let s = extern::xcrate; //~ ERROR expected value, found module `extern::xcrate`
-                            //~^ NOTE not a value
-}
diff --git a/src/test/ui/rfc-2126-extern-in-paths/single-segment.stderr b/src/test/ui/rfc-2126-extern-in-paths/single-segment.stderr
deleted file mode 100644
index 2d8ecd48d48..00000000000
--- a/src/test/ui/rfc-2126-extern-in-paths/single-segment.stderr
+++ /dev/null
@@ -1,22 +0,0 @@
-error: cannot glob-import all possible crates
-  --> $DIR/single-segment.rs:8:5
-   |
-LL | use extern::*; //~ ERROR cannot glob-import all possible crates
-   |     ^^^^^^^^^
-
-error[E0432]: unresolved import `extern`
-  --> $DIR/single-segment.rs:6:5
-   |
-LL | use extern; //~ ERROR unresolved import `extern`
-   |     ^^^^^^ no `extern` in the root
-
-error[E0423]: expected value, found module `extern::xcrate`
-  --> $DIR/single-segment.rs:11:13
-   |
-LL |     let s = extern::xcrate; //~ ERROR expected value, found module `extern::xcrate`
-   |             ^^^^^^^^^^^^^^ not a value
-
-error: aborting due to 3 previous errors
-
-Some errors occurred: E0423, E0432.
-For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/suggestions/recover-from-semicolon-trailing-item.rs b/src/test/ui/suggestions/recover-from-semicolon-trailing-item.rs
new file mode 100644
index 00000000000..82935af0a81
--- /dev/null
+++ b/src/test/ui/suggestions/recover-from-semicolon-trailing-item.rs
@@ -0,0 +1,16 @@
+// verify that after encountering a semicolon after an item the parser recovers
+mod M {};
+//~^ ERROR expected item, found `;`
+struct S {};
+//~^ ERROR expected item, found `;`
+fn foo(a: usize) {};
+//~^ ERROR expected item, found `;`
+fn main() {
+    struct X {};  // ok
+    let _: usize = S {};
+    //~^ ERROR mismatched types
+    let _: usize = X {};
+    //~^ ERROR mismatched types
+    foo("");
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/suggestions/recover-from-semicolon-trailing-item.stderr b/src/test/ui/suggestions/recover-from-semicolon-trailing-item.stderr
new file mode 100644
index 00000000000..9a47a1efb75
--- /dev/null
+++ b/src/test/ui/suggestions/recover-from-semicolon-trailing-item.stderr
@@ -0,0 +1,50 @@
+error: expected item, found `;`
+  --> $DIR/recover-from-semicolon-trailing-item.rs:2:9
+   |
+LL | mod M {};
+   |         ^ help: remove this semicolon
+
+error: expected item, found `;`
+  --> $DIR/recover-from-semicolon-trailing-item.rs:4:12
+   |
+LL | struct S {};
+   |            ^ help: remove this semicolon
+   |
+   = help: braced struct declarations are not followed by a semicolon
+
+error: expected item, found `;`
+  --> $DIR/recover-from-semicolon-trailing-item.rs:6:20
+   |
+LL | fn foo(a: usize) {};
+   |                    ^ help: remove this semicolon
+
+error[E0308]: mismatched types
+  --> $DIR/recover-from-semicolon-trailing-item.rs:10:20
+   |
+LL |     let _: usize = S {};
+   |                    ^^^^ expected usize, found struct `S`
+   |
+   = note: expected type `usize`
+              found type `S`
+
+error[E0308]: mismatched types
+  --> $DIR/recover-from-semicolon-trailing-item.rs:12:20
+   |
+LL |     let _: usize = X {};
+   |                    ^^^^ expected usize, found struct `main::X`
+   |
+   = note: expected type `usize`
+              found type `main::X`
+
+error[E0308]: mismatched types
+  --> $DIR/recover-from-semicolon-trailing-item.rs:14:9
+   |
+LL |     foo("");
+   |         ^^ expected usize, found reference
+   |
+   = note: expected type `usize`
+              found type `&'static str`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/traits/trait-object-vs-lifetime.rs b/src/test/ui/traits/trait-object-vs-lifetime.rs
index 57d9b2df9f5..a12429c868e 100644
--- a/src/test/ui/traits/trait-object-vs-lifetime.rs
+++ b/src/test/ui/traits/trait-object-vs-lifetime.rs
@@ -1,8 +1,6 @@
 // A few contrived examples where lifetime should (or should not) be parsed as an object type.
 // Lifetimes parsed as types are still rejected later by semantic checks.
 
-// compile-flags: -Z continue-parse-after-error
-
 struct S<'a, T>(&'a u8, T);
 
 fn main() {
diff --git a/src/test/ui/traits/trait-object-vs-lifetime.stderr b/src/test/ui/traits/trait-object-vs-lifetime.stderr
index 20218c19e45..4cc96bae5cd 100644
--- a/src/test/ui/traits/trait-object-vs-lifetime.stderr
+++ b/src/test/ui/traits/trait-object-vs-lifetime.stderr
@@ -1,29 +1,33 @@
 error: lifetime parameters must be declared prior to type parameters
-  --> $DIR/trait-object-vs-lifetime.rs:16:25
+  --> $DIR/trait-object-vs-lifetime.rs:14:25
    |
 LL |     let _: S<'static +, 'static>;
-   |                         ^^^^^^^
+   |                         ^^^^^^^ must be declared prior to type parameters
+help: move the lifetime parameter prior to the first type parameter
+   |
+LL |     let _: S<'static, 'static +>;
+   |              ^^^^^^^^         --
 
 error[E0224]: at least one non-builtin trait is required for an object type
-  --> $DIR/trait-object-vs-lifetime.rs:11:23
+  --> $DIR/trait-object-vs-lifetime.rs:9:23
    |
 LL |     let _: S<'static, 'static +>;
    |                       ^^^^^^^^^
 
 error[E0107]: wrong number of lifetime arguments: expected 1, found 2
-  --> $DIR/trait-object-vs-lifetime.rs:13:23
+  --> $DIR/trait-object-vs-lifetime.rs:11:23
    |
 LL |     let _: S<'static, 'static>;
    |                       ^^^^^^^ unexpected lifetime argument
 
 error[E0107]: wrong number of type arguments: expected 1, found 0
-  --> $DIR/trait-object-vs-lifetime.rs:13:12
+  --> $DIR/trait-object-vs-lifetime.rs:11:12
    |
 LL |     let _: S<'static, 'static>;
    |            ^^^^^^^^^^^^^^^^^^^ expected 1 type argument
 
 error[E0224]: at least one non-builtin trait is required for an object type
-  --> $DIR/trait-object-vs-lifetime.rs:16:14
+  --> $DIR/trait-object-vs-lifetime.rs:14:14
    |
 LL |     let _: S<'static +, 'static>;
    |              ^^^^^^^^^