From fa2a792491ed28530146ee55a46128c05a8026ad Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sat, 22 Feb 2020 02:01:53 +0100
Subject: [PATCH 01/17] add `Span` to `ast::Defaultness::Default`.

---
 src/librustc_ast_lowering/item.rs             | 12 ++++------
 src/librustc_ast_passes/ast_validation.rs     | 12 ++++++----
 src/librustc_ast_passes/feature_gate.rs       |  4 ++--
 src/librustc_ast_pretty/pprust.rs             |  2 +-
 src/librustc_parse/parser/item.rs             |  2 +-
 src/librustc_save_analysis/sig.rs             |  2 +-
 src/libsyntax/ast.rs                          |  2 +-
 .../parser/assoc-static-semantic-fail.stderr  |  8 +++++--
 ...item-with-defaultness-fail-semantic.stderr | 24 ++++++++++++++-----
 .../specialization/defaultimpl/validation.rs  |  2 +-
 .../defaultimpl/validation.stderr             |  8 ++++---
 11 files changed, 48 insertions(+), 30 deletions(-)

diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index 1a19fab0265e6..3d6926df58d52 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -810,13 +810,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
             AssocItemKind::Macro(..) => unimplemented!(),
         };
-        hir::TraitItemRef {
-            id: hir::TraitItemId { hir_id: self.lower_node_id(i.id) },
-            ident: i.ident,
-            span: i.span,
-            defaultness: self.lower_defaultness(Defaultness::Default, has_default),
-            kind,
-        }
+        let id = hir::TraitItemId { hir_id: self.lower_node_id(i.id) };
+        let defaultness = hir::Defaultness::Default { has_value: has_default };
+        hir::TraitItemRef { id, ident: i.ident, span: i.span, defaultness, kind }
     }
 
     /// Construct `ExprKind::Err` for the given `span`.
@@ -948,7 +944,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
     fn lower_defaultness(&self, d: Defaultness, has_value: bool) -> hir::Defaultness {
         match d {
-            Defaultness::Default => hir::Defaultness::Default { has_value: has_value },
+            Defaultness::Default(_) => hir::Defaultness::Default { has_value },
             Defaultness::Final => {
                 assert!(has_value);
                 hir::Defaultness::Final
diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs
index a9844a7059e55..d385ea1a4a6d7 100644
--- a/src/librustc_ast_passes/ast_validation.rs
+++ b/src/librustc_ast_passes/ast_validation.rs
@@ -400,9 +400,11 @@ impl<'a> AstValidator<'a> {
     }
 
     fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
-        if let Defaultness::Default = defaultness {
+        if let Defaultness::Default(def_span) = defaultness {
+            let span = self.session.source_map().def_span(span);
             self.err_handler()
                 .struct_span_err(span, "`default` is only allowed on items in `impl` definitions")
+                .span_label(def_span, "`default` because of this")
                 .emit();
         }
     }
@@ -863,10 +865,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 if polarity == ImplPolarity::Negative {
                     self.err_handler().span_err(item.span, "inherent impls cannot be negative");
                 }
-                if defaultness == Defaultness::Default {
+                if let Defaultness::Default(def_span) = defaultness {
+                    let span = self.session.source_map().def_span(item.span);
                     self.err_handler()
-                        .struct_span_err(item.span, "inherent impls cannot be default")
-                        .note("only trait implementations may be annotated with default")
+                        .struct_span_err(span, "inherent impls cannot be `default`")
+                        .span_label(def_span, "`default` because of this")
+                        .note("only trait implementations may be annotated with `default`")
                         .emit();
                 }
                 if let Const::Yes(span) = constness {
diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs
index 5bddae0d49e7d..586539d9b5ee2 100644
--- a/src/librustc_ast_passes/feature_gate.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -349,7 +349,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                     );
                 }
 
-                if let ast::Defaultness::Default = defaultness {
+                if let ast::Defaultness::Default(_) = defaultness {
                     gate_feature_post!(&self, specialization, i.span, "specialization is unstable");
                 }
             }
@@ -543,7 +543,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
     }
 
     fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
-        if i.defaultness == ast::Defaultness::Default {
+        if let ast::Defaultness::Default(_) = i.defaultness {
             gate_feature_post!(&self, specialization, i.span, "specialization is unstable");
         }
 
diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs
index 548ae6e7e63c4..abe3165df4b9a 100644
--- a/src/librustc_ast_pretty/pprust.rs
+++ b/src/librustc_ast_pretty/pprust.rs
@@ -1389,7 +1389,7 @@ impl<'a> State<'a> {
     }
 
     crate fn print_defaultness(&mut self, defaultness: ast::Defaultness) {
-        if let ast::Defaultness::Default = defaultness {
+        if let ast::Defaultness::Default(_) = defaultness {
             self.word_nbsp("default");
         }
     }
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 328cf11c53247..a6e4900bc626d 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -547,7 +547,7 @@ impl<'a> Parser<'a> {
             )
         {
             self.bump(); // `default`
-            Defaultness::Default
+            Defaultness::Default(self.prev_span)
         } else {
             Defaultness::Final
         }
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 2c07ed0571bde..a7a10c0be0d62 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -502,7 +502,7 @@ impl Sig for ast::Item {
                 items: _,
             } => {
                 let mut text = String::new();
-                if let ast::Defaultness::Default = defaultness {
+                if let ast::Defaultness::Default(_) = defaultness {
                     text.push_str("default ");
                 }
                 if let ast::Unsafe::Yes(_) = unsafety {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 849950e939a02..bcf94d196132f 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -2106,7 +2106,7 @@ pub enum Const {
 /// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532).
 #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub enum Defaultness {
-    Default,
+    Default(Span),
     Final,
 }
 
diff --git a/src/test/ui/parser/assoc-static-semantic-fail.stderr b/src/test/ui/parser/assoc-static-semantic-fail.stderr
index d02e2855c7e62..dfd0053fda2f3 100644
--- a/src/test/ui/parser/assoc-static-semantic-fail.stderr
+++ b/src/test/ui/parser/assoc-static-semantic-fail.stderr
@@ -74,13 +74,17 @@ error: `default` is only allowed on items in `impl` definitions
   --> $DIR/assoc-static-semantic-fail.rs:24:5
    |
 LL |     default static TC: u8 = 0;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     -------^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     `default` because of this
 
 error: `default` is only allowed on items in `impl` definitions
   --> $DIR/assoc-static-semantic-fail.rs:27:5
    |
 LL |     pub(crate) default static TD: u8;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^-------^^^^^^^^^^^^^^^
+   |                |
+   |                `default` because of this
 
 error[E0449]: unnecessary visibility qualifier
   --> $DIR/assoc-static-semantic-fail.rs:27:5
diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr
index 54111df342343..6bb946d5b6470 100644
--- a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr
+++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr
@@ -2,37 +2,49 @@ error: `default` is only allowed on items in `impl` definitions
   --> $DIR/trait-item-with-defaultness-fail-semantic.rs:6:5
    |
 LL |     default const A: u8;
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |     -------^^^^^^^^^^^^^
+   |     |
+   |     `default` because of this
 
 error: `default` is only allowed on items in `impl` definitions
   --> $DIR/trait-item-with-defaultness-fail-semantic.rs:7:5
    |
 LL |     default const B: u8 = 0;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |     -------^^^^^^^^^^^^^^^^^
+   |     |
+   |     `default` because of this
 
 error: `default` is only allowed on items in `impl` definitions
   --> $DIR/trait-item-with-defaultness-fail-semantic.rs:8:5
    |
 LL |     default type D;
-   |     ^^^^^^^^^^^^^^^
+   |     -------^^^^^^^^
+   |     |
+   |     `default` because of this
 
 error: `default` is only allowed on items in `impl` definitions
   --> $DIR/trait-item-with-defaultness-fail-semantic.rs:9:5
    |
 LL |     default type C: Ord;
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |     -------^^^^^^^^^^^^^
+   |     |
+   |     `default` because of this
 
 error: `default` is only allowed on items in `impl` definitions
   --> $DIR/trait-item-with-defaultness-fail-semantic.rs:10:5
    |
 LL |     default fn f1();
-   |     ^^^^^^^^^^^^^^^^
+   |     -------^^^^^^^^^
+   |     |
+   |     `default` because of this
 
 error: `default` is only allowed on items in `impl` definitions
   --> $DIR/trait-item-with-defaultness-fail-semantic.rs:11:5
    |
 LL |     default fn f2() {}
-   |     ^^^^^^^^^^^^^^^^^^
+   |     -------^^^^^^^^
+   |     |
+   |     `default` because of this
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/specialization/defaultimpl/validation.rs b/src/test/ui/specialization/defaultimpl/validation.rs
index cf5d6628054ab..26b3f1ec41491 100644
--- a/src/test/ui/specialization/defaultimpl/validation.rs
+++ b/src/test/ui/specialization/defaultimpl/validation.rs
@@ -4,7 +4,7 @@
 struct S;
 struct Z;
 
-default impl S {} //~ ERROR inherent impls cannot be default
+default impl S {} //~ ERROR inherent impls cannot be `default`
 
 default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default
 default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default
diff --git a/src/test/ui/specialization/defaultimpl/validation.stderr b/src/test/ui/specialization/defaultimpl/validation.stderr
index 14a06c39088d4..03b1ef69ca072 100644
--- a/src/test/ui/specialization/defaultimpl/validation.stderr
+++ b/src/test/ui/specialization/defaultimpl/validation.stderr
@@ -1,10 +1,12 @@
-error: inherent impls cannot be default
+error: inherent impls cannot be `default`
   --> $DIR/validation.rs:7:1
    |
 LL | default impl S {}
-   | ^^^^^^^^^^^^^^^^^
+   | -------^^^^^^^
+   | |
+   | `default` because of this
    |
-   = note: only trait implementations may be annotated with default
+   = note: only trait implementations may be annotated with `default`
 
 error: impls of auto traits cannot be default
   --> $DIR/validation.rs:9:1

From d41fc138bf57db0d5491d0886a676c3ade4b746f Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sat, 22 Feb 2020 02:32:02 +0100
Subject: [PATCH 02/17] `parse_defaultness`: avoid hardcoded list of keywords.

---
 src/librustc_parse/parser/item.rs | 39 +++++++++++--------------------
 1 file changed, 13 insertions(+), 26 deletions(-)

diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index a6e4900bc626d..e770b4212e5ec 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -147,10 +147,7 @@ impl<'a> Parser<'a> {
             || self.check_keyword(kw::Default) && self.is_keyword_ahead(1, &[kw::Impl, kw::Unsafe])
         {
             // IMPL ITEM
-            let defaultness = self.parse_defaultness();
-            let unsafety = self.parse_unsafety();
-            self.expect_keyword(kw::Impl)?;
-            self.parse_item_impl(attrs, unsafety, defaultness)?
+            self.parse_item_impl(attrs)?
         } else if self.eat_keyword(kw::Mod) {
             // MODULE ITEM
             self.parse_item_mod(attrs)?
@@ -349,7 +346,7 @@ impl<'a> Parser<'a> {
         err
     }
 
-    /// Parses an implementation item, `impl` keyword is already parsed.
+    /// Parses an implementation item.
     ///
     /// ```
     /// impl<'a, T> TYPE { /* impl items */ }
@@ -363,12 +360,11 @@ impl<'a> Parser<'a> {
     /// "impl" GENERICS "const"? "!"? TYPE "for"? (TYPE | "..") ("where" PREDICATES)? "{" BODY "}"
     /// "impl" GENERICS "const"? "!"? TYPE ("where" PREDICATES)? "{" BODY "}"
     /// ```
-    fn parse_item_impl(
-        &mut self,
-        attrs: &mut Vec<Attribute>,
-        unsafety: Unsafe,
-        defaultness: Defaultness,
-    ) -> PResult<'a, ItemInfo> {
+    fn parse_item_impl(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, ItemInfo> {
+        let defaultness = self.parse_defaultness();
+        let unsafety = self.parse_unsafety();
+        self.expect_keyword(kw::Impl)?;
+
         // First, parse generic parameters if necessary.
         let mut generics = if self.choose_generics_over_qpath() {
             self.parse_generics()?
@@ -529,22 +525,13 @@ impl<'a> Parser<'a> {
 
     /// Parses defaultness (i.e., `default` or nothing).
     fn parse_defaultness(&mut self) -> Defaultness {
-        // `pub` is included for better error messages
+        // We are interested in `default` followed by another keyword.
+        // However, we must avoid keywords that occur as binary operators.
+        // Currently, the only applicable keyword is `as` (`default as Ty`).
         if self.check_keyword(kw::Default)
-            && self.is_keyword_ahead(
-                1,
-                &[
-                    kw::Impl,
-                    kw::Static,
-                    kw::Const,
-                    kw::Async,
-                    kw::Fn,
-                    kw::Unsafe,
-                    kw::Extern,
-                    kw::Type,
-                    kw::Pub,
-                ],
-            )
+            && self.look_ahead(1, |t| {
+                t.is_non_raw_ident_where(|i| i.is_reserved() && i.name != kw::As)
+            })
         {
             self.bump(); // `default`
             Defaultness::Default(self.prev_span)

From 7017058e6b289ea6253e62b9ffdae5dea036855f Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sat, 22 Feb 2020 03:29:17 +0100
Subject: [PATCH 03/17] ast: add `Defaultness` to `Item`, making `AssocItem` an
 alias.

---
 src/librustc_ast_pretty/pprust.rs             |  4 ++--
 src/librustc_builtin_macros/global_asm.rs     |  1 +
 src/librustc_builtin_macros/test_harness.rs   | 24 +++++++------------
 src/librustc_expand/build.rs                  |  1 +
 src/librustc_expand/expand.rs                 |  1 +
 src/librustc_expand/placeholders.rs           |  3 +++
 .../rmeta/decoder/cstore_impl.rs              |  1 +
 src/librustc_parse/parser/item.rs             |  7 +++---
 src/libsyntax/ast.rs                          | 23 ++++++------------
 src/libsyntax/attr/mod.rs                     |  2 +-
 src/libsyntax/mut_visit.rs                    |  8 +++----
 src/libsyntax/visit.rs                        |  2 +-
 src/test/ui/ast-json/ast-json-output.stdout   |  2 +-
 13 files changed, 35 insertions(+), 44 deletions(-)

diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs
index abe3165df4b9a..503310c6db539 100644
--- a/src/librustc_ast_pretty/pprust.rs
+++ b/src/librustc_ast_pretty/pprust.rs
@@ -1016,8 +1016,8 @@ impl<'a> State<'a> {
     }
 
     crate fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
-        let ast::ForeignItem { id, span, ident, attrs, kind, vis, tokens: _ } = item;
-        self.print_nested_item_kind(*id, *span, *ident, attrs, ast::Defaultness::Final, kind, vis);
+        let ast::Item { id, span, ident, attrs, kind, vis, defaultness, tokens: _ } = item;
+        self.print_nested_item_kind(*id, *span, *ident, attrs, *defaultness, kind, vis);
     }
 
     fn print_nested_item_kind(
diff --git a/src/librustc_builtin_macros/global_asm.rs b/src/librustc_builtin_macros/global_asm.rs
index 052e62ee9ffd3..70b9fccbafc15 100644
--- a/src/librustc_builtin_macros/global_asm.rs
+++ b/src/librustc_builtin_macros/global_asm.rs
@@ -30,6 +30,7 @@ pub fn expand_global_asm<'cx>(
             id: ast::DUMMY_NODE_ID,
             kind: ast::ItemKind::GlobalAsm(P(global_asm)),
             vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
+            defaultness: ast::Defaultness::Final,
             span: cx.with_def_site_ctxt(sp),
             tokens: None,
         })]),
diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs
index f0ea256cf2bf3..1d8ade1b2ba78 100644
--- a/src/librustc_builtin_macros/test_harness.rs
+++ b/src/librustc_builtin_macros/test_harness.rs
@@ -162,7 +162,7 @@ impl MutVisitor for EntryPointCleaner {
         // #[allow(dead_code)] to avoid printing warnings.
         let item = match entry::entry_point_type(&item, self.depth) {
             EntryPointType::MainNamed | EntryPointType::MainAttr | EntryPointType::Start => item
-                .map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| {
+                .map(|ast::Item { id, ident, attrs, kind, vis, defaultness, span, tokens }| {
                     let allow_ident = Ident::new(sym::allow, self.def_site);
                     let dc_nested = attr::mk_nested_word_item(Ident::from_str_and_span(
                         "dead_code",
@@ -170,22 +170,13 @@ impl MutVisitor for EntryPointCleaner {
                     ));
                     let allow_dead_code_item = attr::mk_list_item(allow_ident, vec![dc_nested]);
                     let allow_dead_code = attr::mk_attr_outer(allow_dead_code_item);
+                    let attrs = attrs
+                        .into_iter()
+                        .filter(|attr| !attr.check_name(sym::main) && !attr.check_name(sym::start))
+                        .chain(iter::once(allow_dead_code))
+                        .collect();
 
-                    ast::Item {
-                        id,
-                        ident,
-                        attrs: attrs
-                            .into_iter()
-                            .filter(|attr| {
-                                !attr.check_name(sym::main) && !attr.check_name(sym::start)
-                            })
-                            .chain(iter::once(allow_dead_code))
-                            .collect(),
-                        kind,
-                        vis,
-                        span,
-                        tokens,
-                    }
+                    ast::Item { id, ident, attrs, kind, vis, defaultness, span, tokens }
                 }),
             EntryPointType::None | EntryPointType::OtherMain => item,
         };
@@ -321,6 +312,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
         id: ast::DUMMY_NODE_ID,
         kind: main,
         vis: respan(sp, ast::VisibilityKind::Public),
+        defaultness: ast::Defaultness::Final,
         span: sp,
         tokens: None,
     });
diff --git a/src/librustc_expand/build.rs b/src/librustc_expand/build.rs
index 8a53e1d1861aa..246b3bff71d4e 100644
--- a/src/librustc_expand/build.rs
+++ b/src/librustc_expand/build.rs
@@ -588,6 +588,7 @@ impl<'a> ExtCtxt<'a> {
             id: ast::DUMMY_NODE_ID,
             kind,
             vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
+            defaultness: ast::Defaultness::Final,
             span,
             tokens: None,
         })
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index 5d0c474140f16..ba26780dea204 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -358,6 +358,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             ident: Ident::invalid(),
             id: ast::DUMMY_NODE_ID,
             vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public),
+            defaultness: ast::Defaultness::Final,
             tokens: None,
         })]);
 
diff --git a/src/librustc_expand/placeholders.rs b/src/librustc_expand/placeholders.rs
index c96b394c7b5e2..e7e4f482a5e31 100644
--- a/src/librustc_expand/placeholders.rs
+++ b/src/librustc_expand/placeholders.rs
@@ -26,6 +26,7 @@ pub fn placeholder(
     let ident = ast::Ident::invalid();
     let attrs = Vec::new();
     let vis = vis.unwrap_or_else(|| dummy_spanned(ast::VisibilityKind::Inherited));
+    let defaultness = ast::Defaultness::Final;
     let span = DUMMY_SP;
     let expr_placeholder = || {
         P(ast::Expr {
@@ -46,6 +47,7 @@ pub fn placeholder(
             span,
             ident,
             vis,
+            defaultness,
             attrs,
             kind: ast::ItemKind::Mac(mac_placeholder()),
             tokens: None,
@@ -76,6 +78,7 @@ pub fn placeholder(
                 span,
                 ident,
                 vis,
+                defaultness,
                 attrs,
                 kind: ast::ForeignItemKind::Macro(mac_placeholder()),
                 tokens: None,
diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
index fb7e5541e266e..602be37257361 100644
--- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
+++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
@@ -464,6 +464,7 @@ impl CStore {
                     legacy: def.legacy,
                 }),
                 vis: source_map::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited),
+                defaultness: ast::Defaultness::Final,
                 tokens: None,
             },
             data.root.edition,
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index e770b4212e5ec..190baa9b2d90e 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -85,7 +85,7 @@ impl<'a> Parser<'a> {
         let vis = self.parse_visibility(FollowedByType::No)?;
 
         if let Some((ident, kind)) = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis)? {
-            return Ok(Some(P(self.mk_item(lo, ident, kind, vis, attrs))));
+            return Ok(Some(P(self.mk_item(lo, ident, kind, vis, Defaultness::Final, attrs))));
         }
 
         // FAILURE TO PARSE ITEM
@@ -866,7 +866,7 @@ impl<'a> Parser<'a> {
         let lo = self.token.span;
         let vis = self.parse_visibility(FollowedByType::No)?;
         let (ident, kind) = self.parse_assoc_item_kind(at_end, &mut attrs, |_| true, &vis)?;
-        let item = self.mk_item(lo, ident, kind, vis, attrs);
+        let item = self.mk_item(lo, ident, kind, vis, Defaultness::Final, attrs);
         self.error_on_foreign_const(&item);
         Ok(P(item))
     }
@@ -1420,10 +1420,11 @@ impl<'a> Parser<'a> {
         ident: Ident,
         kind: K,
         vis: Visibility,
+        defaultness: Defaultness,
         attrs: Vec<Attribute>,
     ) -> Item<K> {
         let span = lo.to(self.prev_span);
-        Item { ident, attrs, id: DUMMY_NODE_ID, kind, vis, span, tokens: None }
+        Item { ident, attrs, id: DUMMY_NODE_ID, kind, vis, defaultness, span, tokens: None }
     }
 }
 
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index bcf94d196132f..dd3319fcba155 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -2411,16 +2411,19 @@ impl VariantData {
     }
 }
 
-/// An item.
-///
-/// The name might be a dummy name in case of anonymous items.
+/// An item definition.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Item<K = ItemKind> {
     pub attrs: Vec<Attribute>,
     pub id: NodeId,
     pub span: Span,
     pub vis: Visibility,
+    /// The name of the item.
+    /// It might be a dummy name in case of anonymous items.
     pub ident: Ident,
+    /// The `default`ness of this item.
+    /// This should only occur in syntactically well-formed code in associated contexts.
+    pub defaultness: Defaultness,
 
     pub kind: K,
 
@@ -2613,19 +2616,7 @@ pub type ForeignItemKind = AssocItemKind;
 
 /// Represents associated items.
 /// These include items in `impl` and `trait` definitions.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct AssocItem {
-    pub attrs: Vec<Attribute>,
-    pub id: NodeId,
-    pub span: Span,
-    pub vis: Visibility,
-    pub ident: Ident,
-
-    pub defaultness: Defaultness,
-    pub kind: AssocItemKind,
-    /// See `Item::tokens` for what this is.
-    pub tokens: Option<TokenStream>,
-}
+pub type AssocItem = Item<AssocItemKind>;
 
 /// Represents non-free item kinds.
 ///
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index 313f526923564..cd485e7137808 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -722,6 +722,6 @@ macro_rules! derive_has_attrs {
 }
 
 derive_has_attrs! {
-    Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::AssocItem, ast::Arm,
+    Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::Arm,
     ast::Field, ast::FieldPat, ast::Variant, ast::Param, GenericParam
 }
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 02f790dfbb4e9..048026cbb248e 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -948,8 +948,7 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
     mut item: P<AssocItem>,
     visitor: &mut T,
 ) -> SmallVec<[P<AssocItem>; 1]> {
-    let AssocItem { id, ident, vis, defaultness: _, attrs, kind, span, tokens: _ } =
-        item.deref_mut();
+    let Item { id, ident, vis, defaultness: _, attrs, kind, span, tokens: _ } = item.deref_mut();
     walk_nested_item(visitor, id, span, ident, vis, attrs, kind);
     smallvec![item]
 }
@@ -1004,6 +1003,7 @@ pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
             attrs,
             id: DUMMY_NODE_ID,
             vis: respan(span.shrink_to_lo(), VisibilityKind::Public),
+            defaultness: Defaultness::Final,
             span,
             kind: ItemKind::Mod(module),
             tokens: None,
@@ -1031,7 +1031,7 @@ pub fn noop_flat_map_item<T: MutVisitor>(
     mut item: P<Item>,
     visitor: &mut T,
 ) -> SmallVec<[P<Item>; 1]> {
-    let Item { ident, attrs, id, kind, vis, span, tokens: _ } = item.deref_mut();
+    let Item { ident, attrs, id, kind, vis, defaultness: _, span, tokens: _ } = item.deref_mut();
     visitor.visit_ident(ident);
     visit_attrs(attrs, visitor);
     visitor.visit_id(id);
@@ -1049,7 +1049,7 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
     mut item: P<ForeignItem>,
     visitor: &mut T,
 ) -> SmallVec<[P<ForeignItem>; 1]> {
-    let ForeignItem { ident, attrs, id, kind, vis, span, tokens: _ } = item.deref_mut();
+    let Item { ident, attrs, id, kind, vis, defaultness: _, span, tokens: _ } = item.deref_mut();
     walk_nested_item(visitor, id, span, ident, vis, attrs, kind);
     smallvec![item]
 }
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index bd35918dba728..244cb80064ebc 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -526,7 +526,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
 }
 
 pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) {
-    let ForeignItem { id, span, ident, vis, attrs, kind, tokens: _ } = item;
+    let ForeignItem { id, span, ident, vis, defaultness: _, attrs, kind, tokens: _ } = item;
     walk_nested_item(visitor, *id, *span, *ident, vis, attrs, kind, FnCtxt::Foreign);
 }
 
diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout
index 35e418696f17c..bbda63955e0b7 100644
--- a/src/test/ui/ast-json/ast-json-output.stdout
+++ b/src/test/ui/ast-json/ast-json-output.stdout
@@ -1 +1 @@
-{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0},"proc_macros":[]}
+{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"defaultness":"Final","kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0},"proc_macros":[]}

From 9ed4c0998381901ac68c19c30c375f5760016759 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sat, 22 Feb 2020 03:44:24 +0100
Subject: [PATCH 04/17] parse: extract `error_on_unmatched_vis`.

---
 src/librustc_parse/parser/item.rs | 26 ++++++++++++++++----------
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 190baa9b2d90e..732bbdf1c5477 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -88,16 +88,9 @@ impl<'a> Parser<'a> {
             return Ok(Some(P(self.mk_item(lo, ident, kind, vis, Defaultness::Final, attrs))));
         }
 
-        // FAILURE TO PARSE ITEM
-        if let VisibilityKind::Inherited = vis.node {
-        } else {
-            let vs = pprust::vis_to_string(&vis);
-            let vs = vs.trim_end();
-            self.struct_span_err(vis.span, &format!("unmatched visibility `{}`", vs))
-                .span_label(vis.span, "the unmatched visibility")
-                .help(&format!("you likely meant to define an item, e.g., `{} fn foo() {{}}`", vs))
-                .emit();
-        }
+        // At this point, we have failed to parse an item.
+
+        self.error_on_unmatched_vis(&vis);
 
         if !attributes_allowed {
             self.recover_attrs_no_item(&attrs)?;
@@ -105,6 +98,19 @@ impl<'a> Parser<'a> {
         Ok(None)
     }
 
+    /// Error in-case a non-inherited visibility was parsed but no item followed.
+    fn error_on_unmatched_vis(&self, vis: &Visibility) {
+        if let VisibilityKind::Inherited = vis.node {
+            return;
+        }
+        let vs = pprust::vis_to_string(&vis);
+        let vs = vs.trim_end();
+        self.struct_span_err(vis.span, &format!("unmatched visibility `{}`", vs))
+            .span_label(vis.span, "the unmatched visibility")
+            .help(&format!("you likely meant to define an item, e.g., `{} fn foo() {{}}`", vs))
+            .emit();
+    }
+
     /// Parses one of the items allowed by the flags.
     fn parse_item_kind(
         &mut self,

From a920a056035d3aa8f5e90ff174764a886366d379 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sat, 22 Feb 2020 04:53:02 +0100
Subject: [PATCH 05/17] parse: recover `default` on free items.

---
 src/librustc_parse/parser/item.rs             |  59 +++++++--
 .../ui/parser/default-on-wrong-item-kind.rs   |  26 ++++
 .../parser/default-on-wrong-item-kind.stderr  | 122 ++++++++++++++++++
 src/test/ui/parser/default-unmatched.rs       |   6 +
 src/test/ui/parser/default-unmatched.stderr   |  14 ++
 src/test/ui/parser/impl-parsing.rs            |   3 +-
 src/test/ui/parser/impl-parsing.stderr        |  14 +-
 7 files changed, 226 insertions(+), 18 deletions(-)
 create mode 100644 src/test/ui/parser/default-on-wrong-item-kind.rs
 create mode 100644 src/test/ui/parser/default-on-wrong-item-kind.stderr
 create mode 100644 src/test/ui/parser/default-unmatched.rs
 create mode 100644 src/test/ui/parser/default-unmatched.stderr

diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 732bbdf1c5477..184956e1065fa 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -81,17 +81,30 @@ impl<'a> Parser<'a> {
             Some(item)
         });
 
+        let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed)?;
+        if let Some(ref item) = item {
+            self.error_on_illegal_default(item.defaultness);
+        }
+        Ok(item.map(P))
+    }
+
+    fn parse_item_common(
+        &mut self,
+        mut attrs: Vec<Attribute>,
+        macros_allowed: bool,
+        attributes_allowed: bool,
+    ) -> PResult<'a, Option<Item>> {
         let lo = self.token.span;
         let vis = self.parse_visibility(FollowedByType::No)?;
-
-        if let Some((ident, kind)) = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis)? {
-            return Ok(Some(P(self.mk_item(lo, ident, kind, vis, Defaultness::Final, attrs))));
+        let mut def = self.parse_defaultness();
+        let kind = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis, &mut def)?;
+        if let Some((ident, kind)) = kind {
+            return Ok(Some(self.mk_item(lo, ident, kind, vis, def, attrs)));
         }
 
         // At this point, we have failed to parse an item.
-
         self.error_on_unmatched_vis(&vis);
-
+        self.error_on_unmatched_defaultness(def);
         if !attributes_allowed {
             self.recover_attrs_no_item(&attrs)?;
         }
@@ -111,6 +124,25 @@ impl<'a> Parser<'a> {
             .emit();
     }
 
+    /// Error in-case a `default` was parsed but no item followed.
+    fn error_on_unmatched_defaultness(&self, def: Defaultness) {
+        if let Defaultness::Default(span) = def {
+            self.struct_span_err(span, "unmatched `default`")
+                .span_label(span, "the unmatched `default`")
+                .emit();
+        }
+    }
+
+    /// Error in-case `default` was parsed in an in-appropriate context.
+    fn error_on_illegal_default(&self, def: Defaultness) {
+        if let Defaultness::Default(span) = def {
+            self.struct_span_err(span, "item cannot be `default`")
+                .span_label(span, "`default` because of this")
+                .note("only associated `fn`, `const`, and `type` items can be `default`")
+                .emit();
+        }
+    }
+
     /// Parses one of the items allowed by the flags.
     fn parse_item_kind(
         &mut self,
@@ -118,6 +150,7 @@ impl<'a> Parser<'a> {
         macros_allowed: bool,
         lo: Span,
         vis: &Visibility,
+        def: &mut Defaultness,
     ) -> PResult<'a, Option<ItemInfo>> {
         let info = if self.eat_keyword(kw::Use) {
             // USE ITEM
@@ -150,10 +183,9 @@ impl<'a> Parser<'a> {
             self.parse_item_trait(attrs, lo)?
         } else if self.check_keyword(kw::Impl)
             || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Impl])
-            || self.check_keyword(kw::Default) && self.is_keyword_ahead(1, &[kw::Impl, kw::Unsafe])
         {
             // IMPL ITEM
-            self.parse_item_impl(attrs)?
+            self.parse_item_impl(attrs, mem::replace(def, Defaultness::Final))?
         } else if self.eat_keyword(kw::Mod) {
             // MODULE ITEM
             self.parse_item_mod(attrs)?
@@ -366,8 +398,11 @@ impl<'a> Parser<'a> {
     /// "impl" GENERICS "const"? "!"? TYPE "for"? (TYPE | "..") ("where" PREDICATES)? "{" BODY "}"
     /// "impl" GENERICS "const"? "!"? TYPE ("where" PREDICATES)? "{" BODY "}"
     /// ```
-    fn parse_item_impl(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, ItemInfo> {
-        let defaultness = self.parse_defaultness();
+    fn parse_item_impl(
+        &mut self,
+        attrs: &mut Vec<Attribute>,
+        defaultness: Defaultness,
+    ) -> PResult<'a, ItemInfo> {
         let unsafety = self.parse_unsafety();
         self.expect_keyword(kw::Impl)?;
 
@@ -531,13 +566,11 @@ impl<'a> Parser<'a> {
 
     /// Parses defaultness (i.e., `default` or nothing).
     fn parse_defaultness(&mut self) -> Defaultness {
-        // We are interested in `default` followed by another keyword.
+        // We are interested in `default` followed by another identifier.
         // However, we must avoid keywords that occur as binary operators.
         // Currently, the only applicable keyword is `as` (`default as Ty`).
         if self.check_keyword(kw::Default)
-            && self.look_ahead(1, |t| {
-                t.is_non_raw_ident_where(|i| i.is_reserved() && i.name != kw::As)
-            })
+            && self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As))
         {
             self.bump(); // `default`
             Defaultness::Default(self.prev_span)
diff --git a/src/test/ui/parser/default-on-wrong-item-kind.rs b/src/test/ui/parser/default-on-wrong-item-kind.rs
new file mode 100644
index 0000000000000..f7d390eb8a25a
--- /dev/null
+++ b/src/test/ui/parser/default-on-wrong-item-kind.rs
@@ -0,0 +1,26 @@
+// Test parsing for `default` where it doesn't belong.
+// Specifically, we are interested in kinds of items or items in certain contexts.
+
+fn main() {}
+
+#[cfg(FALSE)]
+mod free_items {
+    default extern crate foo; //~ ERROR item cannot be `default`
+    default use foo; //~ ERROR item cannot be `default`
+    default static foo: u8; //~ ERROR item cannot be `default`
+    default const foo: u8; //~ ERROR item cannot be `default`
+    default fn foo(); //~ ERROR item cannot be `default`
+    default mod foo {} //~ ERROR item cannot be `default`
+    default extern "C" {} //~ ERROR item cannot be `default`
+    default type foo = u8; //~ ERROR item cannot be `default`
+    default enum foo {} //~ ERROR item cannot be `default`
+    default struct foo {} //~ ERROR item cannot be `default`
+    default union foo {} //~ ERROR item cannot be `default`
+    default trait foo {} //~ ERROR item cannot be `default`
+    default trait foo = Ord; //~ ERROR item cannot be `default`
+    default impl foo {}
+    default!();
+    default::foo::bar!();
+    default macro foo {} //~ ERROR item cannot be `default`
+    default macro_rules! foo {} //~ ERROR item cannot be `default`
+}
diff --git a/src/test/ui/parser/default-on-wrong-item-kind.stderr b/src/test/ui/parser/default-on-wrong-item-kind.stderr
new file mode 100644
index 0000000000000..d279fd962bbba
--- /dev/null
+++ b/src/test/ui/parser/default-on-wrong-item-kind.stderr
@@ -0,0 +1,122 @@
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:8:5
+   |
+LL |     default extern crate foo;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:9:5
+   |
+LL |     default use foo;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:10:5
+   |
+LL |     default static foo: u8;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:11:5
+   |
+LL |     default const foo: u8;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:12:5
+   |
+LL |     default fn foo();
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:13:5
+   |
+LL |     default mod foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:14:5
+   |
+LL |     default extern "C" {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:15:5
+   |
+LL |     default type foo = u8;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:16:5
+   |
+LL |     default enum foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:17:5
+   |
+LL |     default struct foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:18:5
+   |
+LL |     default union foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:19:5
+   |
+LL |     default trait foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:20:5
+   |
+LL |     default trait foo = Ord;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:24:5
+   |
+LL |     default macro foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:25:5
+   |
+LL |     default macro_rules! foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: aborting due to 15 previous errors
+
diff --git a/src/test/ui/parser/default-unmatched.rs b/src/test/ui/parser/default-unmatched.rs
new file mode 100644
index 0000000000000..31696de0a5caa
--- /dev/null
+++ b/src/test/ui/parser/default-unmatched.rs
@@ -0,0 +1,6 @@
+mod foo {
+    default!(); // OK.
+    default do
+    //~^ ERROR unmatched `default`
+    //~| ERROR expected item, found reserved keyword `do`
+}
diff --git a/src/test/ui/parser/default-unmatched.stderr b/src/test/ui/parser/default-unmatched.stderr
new file mode 100644
index 0000000000000..6e4ef7b79fcc3
--- /dev/null
+++ b/src/test/ui/parser/default-unmatched.stderr
@@ -0,0 +1,14 @@
+error: unmatched `default`
+  --> $DIR/default-unmatched.rs:3:5
+   |
+LL |     default do
+   |     ^^^^^^^ the unmatched `default`
+
+error: expected item, found reserved keyword `do`
+  --> $DIR/default-unmatched.rs:3:13
+   |
+LL |     default do
+   |             ^^ expected item
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/impl-parsing.rs b/src/test/ui/parser/impl-parsing.rs
index 270c8b43dfd5e..662ed28f2f742 100644
--- a/src/test/ui/parser/impl-parsing.rs
+++ b/src/test/ui/parser/impl-parsing.rs
@@ -6,4 +6,5 @@ impl Trait .. {} //~ ERROR missing `for` in a trait impl
 impl ?Sized for Type {} //~ ERROR expected a trait, found type
 impl ?Sized for .. {} //~ ERROR expected a trait, found type
 
-default unsafe FAIL //~ ERROR expected `impl`, found `FAIL`
+default unsafe FAIL //~ ERROR expected item, found keyword `unsafe`
+//~^ ERROR unmatched `default`
diff --git a/src/test/ui/parser/impl-parsing.stderr b/src/test/ui/parser/impl-parsing.stderr
index 7c2a7937c5da7..a5fc3e46896eb 100644
--- a/src/test/ui/parser/impl-parsing.stderr
+++ b/src/test/ui/parser/impl-parsing.stderr
@@ -22,11 +22,17 @@ error: expected a trait, found type
 LL | impl ?Sized for .. {}
    |      ^^^^^^
 
-error: expected `impl`, found `FAIL`
-  --> $DIR/impl-parsing.rs:9:16
+error: unmatched `default`
+  --> $DIR/impl-parsing.rs:9:1
    |
 LL | default unsafe FAIL
-   |                ^^^^ expected `impl`
+   | ^^^^^^^ the unmatched `default`
 
-error: aborting due to 5 previous errors
+error: expected item, found keyword `unsafe`
+  --> $DIR/impl-parsing.rs:9:9
+   |
+LL | default unsafe FAIL
+   |         ^^^^^^ expected item
+
+error: aborting due to 6 previous errors
 

From a63f35daeefc4ae89ba5b6bd0323d97bb0d050e6 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sat, 22 Feb 2020 06:57:31 +0100
Subject: [PATCH 06/17] parse: use `parse_item_common` in `parse_foreign_item`.

---
 src/librustc_expand/expand.rs                 |   4 +-
 src/librustc_parse/parser/item.rs             |  81 +++---
 src/test/ui/macros/issue-54441.rs             |   3 +-
 src/test/ui/macros/issue-54441.stderr         |  16 +-
 .../ui/parser/default-on-wrong-item-kind.rs   |  36 +++
 .../parser/default-on-wrong-item-kind.stderr  | 234 ++++++++++++++++--
 .../ui/parser/default-unmatched-extern.rs     |   8 +
 .../ui/parser/default-unmatched-extern.stderr |  26 ++
 src/test/ui/parser/duplicate-visibility.rs    |   3 +-
 .../ui/parser/duplicate-visibility.stderr     |  21 +-
 src/test/ui/parser/extern-no-fn.rs            |   3 +-
 src/test/ui/parser/extern-no-fn.stderr        |  11 +-
 .../ui/parser/foreign-const-semantic-fail.rs  |   1 +
 .../parser/foreign-const-semantic-fail.stderr |  15 +-
 14 files changed, 392 insertions(+), 70 deletions(-)
 create mode 100644 src/test/ui/parser/default-unmatched-extern.rs
 create mode 100644 src/test/ui/parser/default-unmatched-extern.stderr

diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index ba26780dea204..df2753813f9f3 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -879,8 +879,8 @@ pub fn parse_ast_fragment<'a>(
         }
         AstFragmentKind::ForeignItems => {
             let mut items = SmallVec::new();
-            while this.token != token::Eof {
-                items.push(this.parse_foreign_item(&mut false)?);
+            while let Some(item) = this.parse_foreign_item()? {
+                items.extend(item);
             }
             AstFragment::ForeignItems(items)
         }
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 184956e1065fa..ecd2049963b3f 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -457,7 +457,8 @@ impl<'a> Parser<'a> {
 
         generics.where_clause = self.parse_where_clause()?;
 
-        let impl_items = self.parse_item_list(attrs, |p, at_end| p.parse_impl_item(at_end))?;
+        let impl_items =
+            self.parse_item_list(attrs, |p, at_end| p.parse_impl_item(at_end).map(Some).map(Some))?;
 
         let item_kind = match ty_second {
             Some(ty_second) => {
@@ -516,8 +517,9 @@ impl<'a> Parser<'a> {
     fn parse_item_list<T>(
         &mut self,
         attrs: &mut Vec<Attribute>,
-        mut parse_item: impl FnMut(&mut Parser<'a>, &mut bool) -> PResult<'a, T>,
+        mut parse_item: impl FnMut(&mut Parser<'a>, &mut bool) -> PResult<'a, Option<Option<T>>>,
     ) -> PResult<'a, Vec<T>> {
+        let open_brace_span = self.token.span;
         self.expect(&token::OpenDelim(token::Brace))?;
         attrs.append(&mut self.parse_inner_attributes()?);
 
@@ -528,7 +530,18 @@ impl<'a> Parser<'a> {
             }
             let mut at_end = false;
             match parse_item(self, &mut at_end) {
-                Ok(item) => items.push(item),
+                Ok(None) => {
+                    // We have to bail or we'll potentially never make progress.
+                    let non_item_span = self.token.span;
+                    self.consume_block(token::Brace, ConsumeClosingDelim::Yes);
+                    self.struct_span_err(non_item_span, "non-item in item list")
+                        .span_label(open_brace_span, "item list starts here")
+                        .span_label(non_item_span, "non-item starts here")
+                        .span_label(self.prev_span, "item list ends here")
+                        .emit();
+                    break;
+                }
+                Ok(Some(item)) => items.extend(item),
                 Err(mut err) => {
                     err.emit();
                     if !at_end {
@@ -631,7 +644,9 @@ impl<'a> Parser<'a> {
         } else {
             // It's a normal trait.
             tps.where_clause = self.parse_where_clause()?;
-            let items = self.parse_item_list(attrs, |p, at_end| p.parse_trait_item(at_end))?;
+            let items = self.parse_item_list(attrs, |p, at_end| {
+                p.parse_trait_item(at_end).map(Some).map(Some)
+            })?;
             Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, items)))
         }
     }
@@ -892,38 +907,48 @@ impl<'a> Parser<'a> {
     /// ```
     fn parse_item_foreign_mod(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, ItemInfo> {
         let abi = self.parse_abi(); // ABI?
-        let items = self.parse_item_list(attrs, |p, at_end| p.parse_foreign_item(at_end))?;
+        let items = self.parse_item_list(attrs, |p, _| p.parse_foreign_item())?;
         let module = ast::ForeignMod { abi, items };
         Ok((Ident::invalid(), ItemKind::ForeignMod(module)))
     }
 
     /// Parses a foreign item (one in an `extern { ... }` block).
-    pub fn parse_foreign_item(&mut self, at_end: &mut bool) -> PResult<'a, P<ForeignItem>> {
-        maybe_whole!(self, NtForeignItem, |ni| ni);
+    pub fn parse_foreign_item(&mut self) -> PResult<'a, Option<Option<P<ForeignItem>>>> {
+        maybe_whole!(self, NtForeignItem, |item| Some(Some(item)));
 
-        let mut attrs = self.parse_outer_attributes()?;
-        let lo = self.token.span;
-        let vis = self.parse_visibility(FollowedByType::No)?;
-        let (ident, kind) = self.parse_assoc_item_kind(at_end, &mut attrs, |_| true, &vis)?;
-        let item = self.mk_item(lo, ident, kind, vis, Defaultness::Final, attrs);
-        self.error_on_foreign_const(&item);
-        Ok(P(item))
+        let attrs = self.parse_outer_attributes()?;
+        let it = self.parse_item_common(attrs, true, false)?;
+        Ok(it.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| {
+            self.error_on_illegal_default(defaultness);
+            let kind = match kind {
+                ItemKind::Mac(a) => AssocItemKind::Macro(a),
+                ItemKind::Fn(a, b, c) => AssocItemKind::Fn(a, b, c),
+                ItemKind::TyAlias(a, b, c) => AssocItemKind::TyAlias(a, b, c),
+                ItemKind::Static(a, b, c) => AssocItemKind::Static(a, b, c),
+                ItemKind::Const(a, b) => {
+                    self.error_on_foreign_const(span, ident);
+                    AssocItemKind::Static(a, Mutability::Not, b)
+                }
+                _ => {
+                    let span = self.sess.source_map().def_span(span);
+                    self.struct_span_err(span, "item kind not supported in `extern` block").emit();
+                    return None;
+                }
+            };
+            Some(P(Item { attrs, id, span, vis, ident, defaultness, kind, tokens }))
+        }))
     }
 
-    fn error_on_foreign_const(&self, item: &ForeignItem) {
-        if let AssocItemKind::Const(..) = item.kind {
-            self.struct_span_err(item.ident.span, "extern items cannot be `const`")
-                .span_suggestion(
-                    item.span.with_hi(item.ident.span.lo()),
-                    "try using a static value",
-                    "static ".to_string(),
-                    Applicability::MachineApplicable,
-                )
-                .note(
-                    "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html",
-                )
-                .emit();
-        }
+    fn error_on_foreign_const(&self, span: Span, ident: Ident) {
+        self.struct_span_err(ident.span, "extern items cannot be `const`")
+            .span_suggestion(
+                span.with_hi(ident.span.lo()),
+                "try using a static value",
+                "static ".to_string(),
+                Applicability::MachineApplicable,
+            )
+            .note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html")
+            .emit();
     }
 
     fn is_static_global(&mut self) -> bool {
diff --git a/src/test/ui/macros/issue-54441.rs b/src/test/ui/macros/issue-54441.rs
index 5570f081b157d..b24d7e1f6bee5 100644
--- a/src/test/ui/macros/issue-54441.rs
+++ b/src/test/ui/macros/issue-54441.rs
@@ -1,7 +1,6 @@
 macro_rules! m {
-    //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration
     () => {
-        let
+        let //~ ERROR macro expansion ignores token `let` and any following
     };
 }
 
diff --git a/src/test/ui/macros/issue-54441.stderr b/src/test/ui/macros/issue-54441.stderr
index 5857aacb43176..752916e665560 100644
--- a/src/test/ui/macros/issue-54441.stderr
+++ b/src/test/ui/macros/issue-54441.stderr
@@ -1,11 +1,13 @@
-error: missing `fn`, `type`, `const`, or `static` for item declaration
-  --> $DIR/issue-54441.rs:1:1
+error: macro expansion ignores token `let` and any following
+  --> $DIR/issue-54441.rs:3:9
    |
-LL | / macro_rules! m {
-LL | |
-LL | |     () => {
-LL | |         let
-   | |________^ missing `fn`, `type`, `const`, or `static`
+LL |         let
+   |         ^^^
+...
+LL |     m!();
+   |     ----- caused by the macro expansion here
+   |
+   = note: the usage of `m!` is likely invalid in foreign item context
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/default-on-wrong-item-kind.rs b/src/test/ui/parser/default-on-wrong-item-kind.rs
index f7d390eb8a25a..0fe20473587ca 100644
--- a/src/test/ui/parser/default-on-wrong-item-kind.rs
+++ b/src/test/ui/parser/default-on-wrong-item-kind.rs
@@ -1,5 +1,6 @@
 // Test parsing for `default` where it doesn't belong.
 // Specifically, we are interested in kinds of items or items in certain contexts.
+// Also test item kinds in `extern` blocks and associated contexts which are not allowed there.
 
 fn main() {}
 
@@ -24,3 +25,38 @@ mod free_items {
     default macro foo {} //~ ERROR item cannot be `default`
     default macro_rules! foo {} //~ ERROR item cannot be `default`
 }
+
+#[cfg(FALSE)]
+extern "C" {
+    default extern crate foo; //~ ERROR item cannot be `default`
+    //~^ ERROR item kind not supported in `extern` block
+    default use foo; //~ ERROR item cannot be `default`
+    //~^ ERROR item kind not supported in `extern` block
+    default static foo: u8; //~ ERROR item cannot be `default`
+    default const foo: u8; //~ ERROR item cannot be `default`
+    //~^ ERROR extern items cannot be `const`
+    default fn foo(); //~ ERROR item cannot be `default`
+    default mod foo {} //~ ERROR item cannot be `default`
+    //~^ ERROR item kind not supported in `extern` block
+    default extern "C" {} //~ ERROR item cannot be `default`
+    //~^ ERROR item kind not supported in `extern` block
+    default type foo = u8; //~ ERROR item cannot be `default`
+    default enum foo {} //~ ERROR item cannot be `default`
+    //~^ ERROR item kind not supported in `extern` block
+    default struct foo {} //~ ERROR item cannot be `default`
+    //~^ ERROR item kind not supported in `extern` block
+    default union foo {} //~ ERROR item cannot be `default`
+    //~^ ERROR item kind not supported in `extern` block
+    default trait foo {} //~ ERROR item cannot be `default`
+    //~^ ERROR item kind not supported in `extern` block
+    default trait foo = Ord; //~ ERROR item cannot be `default`
+    //~^ ERROR item kind not supported in `extern` block
+    default impl foo {}
+    //~^ ERROR item kind not supported in `extern` block
+    default!();
+    default::foo::bar!();
+    default macro foo {} //~ ERROR item cannot be `default`
+    //~^ ERROR item kind not supported in `extern` block
+    default macro_rules! foo {} //~ ERROR item cannot be `default`
+    //~^ ERROR item kind not supported in `extern` block
+}
diff --git a/src/test/ui/parser/default-on-wrong-item-kind.stderr b/src/test/ui/parser/default-on-wrong-item-kind.stderr
index d279fd962bbba..e089bbbddde91 100644
--- a/src/test/ui/parser/default-on-wrong-item-kind.stderr
+++ b/src/test/ui/parser/default-on-wrong-item-kind.stderr
@@ -1,5 +1,5 @@
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:8:5
+  --> $DIR/default-on-wrong-item-kind.rs:9:5
    |
 LL |     default extern crate foo;
    |     ^^^^^^^ `default` because of this
@@ -7,7 +7,7 @@ LL |     default extern crate foo;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:9:5
+  --> $DIR/default-on-wrong-item-kind.rs:10:5
    |
 LL |     default use foo;
    |     ^^^^^^^ `default` because of this
@@ -15,7 +15,7 @@ LL |     default use foo;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:10:5
+  --> $DIR/default-on-wrong-item-kind.rs:11:5
    |
 LL |     default static foo: u8;
    |     ^^^^^^^ `default` because of this
@@ -23,7 +23,7 @@ LL |     default static foo: u8;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:11:5
+  --> $DIR/default-on-wrong-item-kind.rs:12:5
    |
 LL |     default const foo: u8;
    |     ^^^^^^^ `default` because of this
@@ -31,7 +31,7 @@ LL |     default const foo: u8;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:12:5
+  --> $DIR/default-on-wrong-item-kind.rs:13:5
    |
 LL |     default fn foo();
    |     ^^^^^^^ `default` because of this
@@ -39,7 +39,7 @@ LL |     default fn foo();
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:13:5
+  --> $DIR/default-on-wrong-item-kind.rs:14:5
    |
 LL |     default mod foo {}
    |     ^^^^^^^ `default` because of this
@@ -47,7 +47,7 @@ LL |     default mod foo {}
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:14:5
+  --> $DIR/default-on-wrong-item-kind.rs:15:5
    |
 LL |     default extern "C" {}
    |     ^^^^^^^ `default` because of this
@@ -55,7 +55,7 @@ LL |     default extern "C" {}
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:15:5
+  --> $DIR/default-on-wrong-item-kind.rs:16:5
    |
 LL |     default type foo = u8;
    |     ^^^^^^^ `default` because of this
@@ -63,7 +63,7 @@ LL |     default type foo = u8;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:16:5
+  --> $DIR/default-on-wrong-item-kind.rs:17:5
    |
 LL |     default enum foo {}
    |     ^^^^^^^ `default` because of this
@@ -71,7 +71,7 @@ LL |     default enum foo {}
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:17:5
+  --> $DIR/default-on-wrong-item-kind.rs:18:5
    |
 LL |     default struct foo {}
    |     ^^^^^^^ `default` because of this
@@ -79,7 +79,7 @@ LL |     default struct foo {}
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:18:5
+  --> $DIR/default-on-wrong-item-kind.rs:19:5
    |
 LL |     default union foo {}
    |     ^^^^^^^ `default` because of this
@@ -87,7 +87,7 @@ LL |     default union foo {}
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:19:5
+  --> $DIR/default-on-wrong-item-kind.rs:20:5
    |
 LL |     default trait foo {}
    |     ^^^^^^^ `default` because of this
@@ -95,7 +95,7 @@ LL |     default trait foo {}
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:20:5
+  --> $DIR/default-on-wrong-item-kind.rs:21:5
    |
 LL |     default trait foo = Ord;
    |     ^^^^^^^ `default` because of this
@@ -103,7 +103,7 @@ LL |     default trait foo = Ord;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:24:5
+  --> $DIR/default-on-wrong-item-kind.rs:25:5
    |
 LL |     default macro foo {}
    |     ^^^^^^^ `default` because of this
@@ -111,12 +111,214 @@ LL |     default macro foo {}
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:25:5
+  --> $DIR/default-on-wrong-item-kind.rs:26:5
+   |
+LL |     default macro_rules! foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:31:5
+   |
+LL |     default extern crate foo;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item kind not supported in `extern` block
+  --> $DIR/default-on-wrong-item-kind.rs:31:5
+   |
+LL |     default extern crate foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:33:5
+   |
+LL |     default use foo;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item kind not supported in `extern` block
+  --> $DIR/default-on-wrong-item-kind.rs:33:5
+   |
+LL |     default use foo;
+   |     ^^^^^^^^^^^^^^^^
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:35:5
+   |
+LL |     default static foo: u8;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:36:5
+   |
+LL |     default const foo: u8;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: extern items cannot be `const`
+  --> $DIR/default-on-wrong-item-kind.rs:36:19
+   |
+LL |     default const foo: u8;
+   |     --------------^^^
+   |     |
+   |     help: try using a static value: `static`
+   |
+   = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:38:5
+   |
+LL |     default fn foo();
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:39:5
+   |
+LL |     default mod foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item kind not supported in `extern` block
+  --> $DIR/default-on-wrong-item-kind.rs:39:5
+   |
+LL |     default mod foo {}
+   |     ^^^^^^^^^^^^^^^
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:41:5
+   |
+LL |     default extern "C" {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item kind not supported in `extern` block
+  --> $DIR/default-on-wrong-item-kind.rs:41:5
+   |
+LL |     default extern "C" {}
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:43:5
+   |
+LL |     default type foo = u8;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:44:5
+   |
+LL |     default enum foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item kind not supported in `extern` block
+  --> $DIR/default-on-wrong-item-kind.rs:44:5
+   |
+LL |     default enum foo {}
+   |     ^^^^^^^^^^^^^^^^
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:46:5
+   |
+LL |     default struct foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item kind not supported in `extern` block
+  --> $DIR/default-on-wrong-item-kind.rs:46:5
+   |
+LL |     default struct foo {}
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:48:5
+   |
+LL |     default union foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item kind not supported in `extern` block
+  --> $DIR/default-on-wrong-item-kind.rs:48:5
+   |
+LL |     default union foo {}
+   |     ^^^^^^^^^^^^^^^^^
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:50:5
+   |
+LL |     default trait foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item kind not supported in `extern` block
+  --> $DIR/default-on-wrong-item-kind.rs:50:5
+   |
+LL |     default trait foo {}
+   |     ^^^^^^^^^^^^^^^^^
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:52:5
+   |
+LL |     default trait foo = Ord;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item kind not supported in `extern` block
+  --> $DIR/default-on-wrong-item-kind.rs:52:5
+   |
+LL |     default trait foo = Ord;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `extern` block
+  --> $DIR/default-on-wrong-item-kind.rs:54:5
+   |
+LL |     default impl foo {}
+   |     ^^^^^^^^^^^^^^^^
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:58:5
+   |
+LL |     default macro foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item kind not supported in `extern` block
+  --> $DIR/default-on-wrong-item-kind.rs:58:5
+   |
+LL |     default macro foo {}
+   |     ^^^^^^^^^^^^^^^^^
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:60:5
    |
 LL |     default macro_rules! foo {}
    |     ^^^^^^^ `default` because of this
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: aborting due to 15 previous errors
+error: item kind not supported in `extern` block
+  --> $DIR/default-on-wrong-item-kind.rs:60:5
+   |
+LL |     default macro_rules! foo {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 43 previous errors
 
diff --git a/src/test/ui/parser/default-unmatched-extern.rs b/src/test/ui/parser/default-unmatched-extern.rs
new file mode 100644
index 0000000000000..fbf87a892f0da
--- /dev/null
+++ b/src/test/ui/parser/default-unmatched-extern.rs
@@ -0,0 +1,8 @@
+fn main() {}
+
+extern "C" {
+    default!(); //~ ERROR cannot find macro `default` in this scope
+    default do
+    //~^ ERROR unmatched `default`
+    //~| ERROR non-item in item list
+}
diff --git a/src/test/ui/parser/default-unmatched-extern.stderr b/src/test/ui/parser/default-unmatched-extern.stderr
new file mode 100644
index 0000000000000..00c8898e2ce82
--- /dev/null
+++ b/src/test/ui/parser/default-unmatched-extern.stderr
@@ -0,0 +1,26 @@
+error: unmatched `default`
+  --> $DIR/default-unmatched-extern.rs:5:5
+   |
+LL |     default do
+   |     ^^^^^^^ the unmatched `default`
+
+error: non-item in item list
+  --> $DIR/default-unmatched-extern.rs:5:13
+   |
+LL | extern "C" {
+   |            - item list starts here
+LL |     default!();
+LL |     default do
+   |             ^^ non-item starts here
+...
+LL | }
+   | - item list ends here
+
+error: cannot find macro `default` in this scope
+  --> $DIR/default-unmatched-extern.rs:4:5
+   |
+LL |     default!();
+   |     ^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs
index f6e7f7e6abe8f..949b6e1dc24f4 100644
--- a/src/test/ui/parser/duplicate-visibility.rs
+++ b/src/test/ui/parser/duplicate-visibility.rs
@@ -2,5 +2,6 @@ fn main() {}
 
 extern {
     pub pub fn foo();
-    //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration
+    //~^ ERROR unmatched visibility `pub`
+    //~| ERROR non-item in item list
 }
diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr
index 398ba65c9e1d8..2c79a343d0578 100644
--- a/src/test/ui/parser/duplicate-visibility.stderr
+++ b/src/test/ui/parser/duplicate-visibility.stderr
@@ -1,8 +1,21 @@
-error: missing `fn`, `type`, `const`, or `static` for item declaration
-  --> $DIR/duplicate-visibility.rs:4:8
+error: unmatched visibility `pub`
+  --> $DIR/duplicate-visibility.rs:4:5
    |
 LL |     pub pub fn foo();
-   |        ^ missing `fn`, `type`, `const`, or `static`
+   |     ^^^ the unmatched visibility
+   |
+   = help: you likely meant to define an item, e.g., `pub fn foo() {}`
+
+error: non-item in item list
+  --> $DIR/duplicate-visibility.rs:4:9
+   |
+LL | extern {
+   |        - item list starts here
+LL |     pub pub fn foo();
+   |         ^^^ non-item starts here
+...
+LL | }
+   | - item list ends here
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/extern-no-fn.rs b/src/test/ui/parser/extern-no-fn.rs
index dc47f7410730c..d9f35e0eb5cfc 100644
--- a/src/test/ui/parser/extern-no-fn.rs
+++ b/src/test/ui/parser/extern-no-fn.rs
@@ -1,6 +1,5 @@
 extern {
-//~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration
-    f();
+    f(); //~ ERROR expected one of `!` or `::`, found `(`
 }
 
 fn main() {
diff --git a/src/test/ui/parser/extern-no-fn.stderr b/src/test/ui/parser/extern-no-fn.stderr
index 8d55eefc8d0ec..023201250148e 100644
--- a/src/test/ui/parser/extern-no-fn.stderr
+++ b/src/test/ui/parser/extern-no-fn.stderr
@@ -1,11 +1,8 @@
-error: missing `fn`, `type`, `const`, or `static` for item declaration
-  --> $DIR/extern-no-fn.rs:1:9
+error: expected one of `!` or `::`, found `(`
+  --> $DIR/extern-no-fn.rs:2:6
    |
-LL |   extern {
-   |  _________^
-LL | |
-LL | |     f();
-   | |____^ missing `fn`, `type`, `const`, or `static`
+LL |     f();
+   |      ^ expected one of `!` or `::`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/foreign-const-semantic-fail.rs b/src/test/ui/parser/foreign-const-semantic-fail.rs
index d28b64142826c..82978e655ba38 100644
--- a/src/test/ui/parser/foreign-const-semantic-fail.rs
+++ b/src/test/ui/parser/foreign-const-semantic-fail.rs
@@ -5,4 +5,5 @@ extern {
     //~^ ERROR extern items cannot be `const`
     const B: isize = 42;
     //~^ ERROR extern items cannot be `const`
+    //~| ERROR incorrect `static` inside `extern` block
 }
diff --git a/src/test/ui/parser/foreign-const-semantic-fail.stderr b/src/test/ui/parser/foreign-const-semantic-fail.stderr
index f364f11bb038d..f529b3ad87b2f 100644
--- a/src/test/ui/parser/foreign-const-semantic-fail.stderr
+++ b/src/test/ui/parser/foreign-const-semantic-fail.stderr
@@ -18,5 +18,18 @@ LL |     const B: isize = 42;
    |
    = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
 
-error: aborting due to 2 previous errors
+error: incorrect `static` inside `extern` block
+  --> $DIR/foreign-const-semantic-fail.rs:6:11
+   |
+LL | extern {
+   | ------ `extern` blocks define existing foreign statics and statics inside of them cannot have a body
+...
+LL |     const B: isize = 42;
+   |           ^          -- the invalid body
+   |           |
+   |           cannot have a body
+   |
+   = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+error: aborting due to 3 previous errors
 

From a05c83b2ebc4e85e32f723e708a40dbd3f165cd0 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sat, 22 Feb 2020 08:16:39 +0100
Subject: [PATCH 07/17] parse: use `parse_item_common` in `parse_assoc_item_`.

---
 src/librustc_expand/expand.rs                 |   8 +-
 src/librustc_parse/parser/item.rs             | 216 ++++++------------
 .../ui/async-await/no-unsafe-async.stderr     |   5 +
 src/test/ui/did_you_mean/issue-40006.rs       |  20 +-
 src/test/ui/did_you_mean/issue-40006.stderr   |  92 +++++---
 .../empty_generics.stderr                     |   5 +
 src/test/ui/issues/issue-58856-1.stderr       |   6 +
 src/test/ui/issues/issue-58856-2.rs           |   2 +-
 src/test/ui/issues/issue-58856-2.stderr       |  12 +-
 src/test/ui/issues/issue-60075.rs             |   5 +-
 src/test/ui/issues/issue-60075.stderr         |  18 +-
 .../ui/parser/assoc-static-semantic-fail.rs   |   4 +
 .../parser/assoc-static-semantic-fail.stderr  |  62 +++--
 .../ui/parser/attrs-after-extern-mod.stderr   |   4 +
 .../ui/parser/default-on-wrong-item-kind.rs   |  70 ++++++
 .../parser/default-on-wrong-item-kind.stderr  | 158 ++++++++++++-
 src/test/ui/parser/default-unmatched-assoc.rs |  16 ++
 .../ui/parser/default-unmatched-assoc.stderr  |  50 ++++
 src/test/ui/parser/default.rs                 |   3 +-
 src/test/ui/parser/default.stderr             |  19 +-
 src/test/ui/parser/extern-no-fn.stderr        |   4 +
 src/test/ui/parser/issue-19398.rs             |   2 +-
 src/test/ui/parser/issue-19398.stderr         |  16 +-
 src/test/ui/parser/issue-20711-2.stderr       |   6 +
 src/test/ui/parser/issue-20711.stderr         |   5 +
 src/test/ui/parser/issue-21153.rs             |   2 +-
 src/test/ui/parser/issue-21153.stderr         |  16 +-
 src/test/ui/parser/issue-32446.stderr         |   7 +-
 src/test/ui/parser/issue-41155.rs             |   4 +-
 src/test/ui/parser/issue-41155.stderr         |  20 +-
 src/test/ui/parser/issue-6610.stderr          |   6 +-
 .../ui/parser/macro/trait-non-item-macros.rs  |  11 +-
 .../parser/macro/trait-non-item-macros.stderr |  23 +-
 .../missing-close-brace-in-impl-trait.rs      |   5 +-
 .../missing-close-brace-in-impl-trait.stderr  |  22 +-
 .../missing-close-brace-in-trait.rs           |   4 +-
 .../missing-close-brace-in-trait.stderr       |  21 +-
 .../ui/parser/removed-syntax-static-fn.stderr |   5 +
 38 files changed, 668 insertions(+), 286 deletions(-)
 create mode 100644 src/test/ui/parser/default-unmatched-assoc.rs
 create mode 100644 src/test/ui/parser/default-unmatched-assoc.stderr

diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index df2753813f9f3..e5f957a63de55 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -865,15 +865,15 @@ pub fn parse_ast_fragment<'a>(
         }
         AstFragmentKind::TraitItems => {
             let mut items = SmallVec::new();
-            while this.token != token::Eof {
-                items.push(this.parse_trait_item(&mut false)?);
+            while let Some(item) = this.parse_trait_item()? {
+                items.extend(item);
             }
             AstFragment::TraitItems(items)
         }
         AstFragmentKind::ImplItems => {
             let mut items = SmallVec::new();
-            while this.token != token::Eof {
-                items.push(this.parse_impl_item(&mut false)?);
+            while let Some(item) = this.parse_impl_item()? {
+                items.extend(item);
             }
             AstFragment::ImplItems(items)
         }
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index ecd2049963b3f..8c5add46bfcae 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -5,12 +5,12 @@ use super::{FollowedByType, Parser, PathStyle};
 use crate::maybe_whole;
 
 use rustc_ast_pretty::pprust;
-use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult, StashKey};
+use rustc_errors::{struct_span_err, Applicability, PResult, StashKey};
 use rustc_span::source_map::{self, Span};
 use rustc_span::symbol::{kw, sym, Symbol};
 use syntax::ast::{self, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID};
-use syntax::ast::{AssocItem, AssocItemKind, Item, ItemKind, UseTree, UseTreeKind};
-use syntax::ast::{Async, Const, Defaultness, IsAuto, PathSegment, Unsafe};
+use syntax::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind};
+use syntax::ast::{Async, Const, Defaultness, IsAuto, PathSegment, Unsafe, UseTree, UseTreeKind};
 use syntax::ast::{BindingMode, Block, FnDecl, FnSig, Mac, MacArgs, MacDelimiter, Param, SelfKind};
 use syntax::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData};
 use syntax::ast::{FnHeader, ForeignItem, Mutability, Visibility, VisibilityKind};
@@ -81,7 +81,7 @@ impl<'a> Parser<'a> {
             Some(item)
         });
 
-        let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed)?;
+        let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed, |_| true)?;
         if let Some(ref item) = item {
             self.error_on_illegal_default(item.defaultness);
         }
@@ -91,21 +91,25 @@ impl<'a> Parser<'a> {
     fn parse_item_common(
         &mut self,
         mut attrs: Vec<Attribute>,
-        macros_allowed: bool,
-        attributes_allowed: bool,
+        mac_allowed: bool,
+        attrs_allowed: bool,
+        req_name: ReqName,
     ) -> PResult<'a, Option<Item>> {
         let lo = self.token.span;
         let vis = self.parse_visibility(FollowedByType::No)?;
         let mut def = self.parse_defaultness();
-        let kind = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis, &mut def)?;
+        let kind = self.parse_item_kind(&mut attrs, mac_allowed, lo, &vis, &mut def, req_name)?;
         if let Some((ident, kind)) = kind {
-            return Ok(Some(self.mk_item(lo, ident, kind, vis, def, attrs)));
+            let span = lo.to(self.prev_span);
+            let id = DUMMY_NODE_ID;
+            let item = Item { ident, attrs, id, kind, vis, defaultness: def, span, tokens: None };
+            return Ok(Some(item));
         }
 
         // At this point, we have failed to parse an item.
         self.error_on_unmatched_vis(&vis);
         self.error_on_unmatched_defaultness(def);
-        if !attributes_allowed {
+        if !attrs_allowed {
             self.recover_attrs_no_item(&attrs)?;
         }
         Ok(None)
@@ -151,6 +155,7 @@ impl<'a> Parser<'a> {
         lo: Span,
         vis: &Visibility,
         def: &mut Defaultness,
+        req_name: ReqName,
     ) -> PResult<'a, Option<ItemInfo>> {
         let info = if self.eat_keyword(kw::Use) {
             // USE ITEM
@@ -159,7 +164,7 @@ impl<'a> Parser<'a> {
             (Ident::invalid(), ItemKind::Use(P(tree)))
         } else if self.check_fn_front_matter() {
             // FUNCTION ITEM
-            let (ident, sig, generics, body) = self.parse_fn(&mut false, attrs, |_| true)?;
+            let (ident, sig, generics, body) = self.parse_fn(&mut false, attrs, req_name)?;
             (ident, ItemKind::Fn(sig, generics, body))
         } else if self.eat_keyword(kw::Extern) {
             if self.eat_keyword(kw::Crate) {
@@ -367,23 +372,6 @@ impl<'a> Parser<'a> {
         self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn])
     }
 
-    /// Given this code `path(`, it seems like this is not
-    /// setting the visibility of a macro invocation,
-    /// but rather a mistyped method declaration.
-    /// Create a diagnostic pointing out that `fn` is missing.
-    ///
-    /// ```
-    /// x |     pub   path(&self) {
-    ///   |         ^ missing `fn`, `type`, `const`, or `static`
-    /// ```
-    fn missing_nested_item_kind_err(&self, prev_span: Span) -> DiagnosticBuilder<'a> {
-        let sp = prev_span.between(self.token.span);
-        let expected_kinds = "missing `fn`, `type`, `const`, or `static`";
-        let mut err = self.struct_span_err(sp, &format!("{} for item declaration", expected_kinds));
-        err.span_label(sp, expected_kinds);
-        err
-    }
-
     /// Parses an implementation item.
     ///
     /// ```
@@ -457,8 +445,7 @@ impl<'a> Parser<'a> {
 
         generics.where_clause = self.parse_where_clause()?;
 
-        let impl_items =
-            self.parse_item_list(attrs, |p, at_end| p.parse_impl_item(at_end).map(Some).map(Some))?;
+        let impl_items = self.parse_item_list(attrs, |p| p.parse_impl_item())?;
 
         let item_kind = match ty_second {
             Some(ty_second) => {
@@ -517,7 +504,7 @@ impl<'a> Parser<'a> {
     fn parse_item_list<T>(
         &mut self,
         attrs: &mut Vec<Attribute>,
-        mut parse_item: impl FnMut(&mut Parser<'a>, &mut bool) -> PResult<'a, Option<Option<T>>>,
+        mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
     ) -> PResult<'a, Vec<T>> {
         let open_brace_span = self.token.span;
         self.expect(&token::OpenDelim(token::Brace))?;
@@ -528,8 +515,7 @@ impl<'a> Parser<'a> {
             if self.recover_doc_comment_before_brace() {
                 continue;
             }
-            let mut at_end = false;
-            match parse_item(self, &mut at_end) {
+            match parse_item(self) {
                 Ok(None) => {
                     // We have to bail or we'll potentially never make progress.
                     let non_item_span = self.token.span;
@@ -543,11 +529,11 @@ impl<'a> Parser<'a> {
                 }
                 Ok(Some(item)) => items.extend(item),
                 Err(mut err) => {
-                    err.emit();
-                    if !at_end {
-                        self.consume_block(token::Brace, ConsumeClosingDelim::Yes);
-                        break;
-                    }
+                    self.consume_block(token::Brace, ConsumeClosingDelim::Yes);
+                    err.span_label(open_brace_span, "while parsing this item list starting here")
+                        .span_label(self.prev_span, "the item list ends here")
+                        .emit();
+                    break;
                 }
             }
         }
@@ -644,103 +630,69 @@ impl<'a> Parser<'a> {
         } else {
             // It's a normal trait.
             tps.where_clause = self.parse_where_clause()?;
-            let items = self.parse_item_list(attrs, |p, at_end| {
-                p.parse_trait_item(at_end).map(Some).map(Some)
-            })?;
+            let items = self.parse_item_list(attrs, |p| p.parse_trait_item())?;
             Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, items)))
         }
     }
 
-    pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, P<AssocItem>> {
-        maybe_whole!(self, NtImplItem, |x| x);
-        self.parse_assoc_item(at_end, |_| true)
+    pub fn parse_impl_item(&mut self) -> PResult<'a, Option<Option<P<AssocItem>>>> {
+        maybe_whole!(self, NtImplItem, |x| Some(Some(x)));
+        self.parse_assoc_item(|_| true)
     }
 
-    pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, P<AssocItem>> {
-        maybe_whole!(self, NtTraitItem, |x| x);
+    pub fn parse_trait_item(&mut self) -> PResult<'a, Option<Option<P<AssocItem>>>> {
+        maybe_whole!(self, NtTraitItem, |x| Some(Some(x)));
         // This is somewhat dubious; We don't want to allow
         // param names to be left off if there is a definition...
         //
         // We don't allow param names to be left off in edition 2018.
-        self.parse_assoc_item(at_end, |t| t.span.rust_2018())
+        self.parse_assoc_item(|t| t.span.rust_2018())
     }
 
     /// Parses associated items.
-    fn parse_assoc_item(
-        &mut self,
-        at_end: &mut bool,
-        req_name: ReqName,
-    ) -> PResult<'a, P<AssocItem>> {
+    fn parse_assoc_item(&mut self, req_name: ReqName) -> PResult<'a, Option<Option<P<AssocItem>>>> {
         let attrs = self.parse_outer_attributes()?;
         let mut unclosed_delims = vec![];
         let (mut item, tokens) = self.collect_tokens(|this| {
-            let item = this.parse_assoc_item_(at_end, attrs, req_name);
+            let item = this.parse_assoc_item_(attrs, req_name);
             unclosed_delims.append(&mut this.unclosed_delims);
             item
         })?;
         self.unclosed_delims.append(&mut unclosed_delims);
         // See `parse_item` for why this clause is here.
-        if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) {
-            item.tokens = Some(tokens);
-        }
-        self.error_on_assoc_static(&item);
-        Ok(P(item))
-    }
-
-    fn error_on_assoc_static(&self, item: &AssocItem) {
-        if let AssocItemKind::Static(..) = item.kind {
-            self.struct_span_err(item.span, "associated `static` items are not allowed").emit();
+        if let Some(Some(item)) = &mut item {
+            if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) {
+                item.tokens = Some(tokens);
+            }
         }
+        Ok(item)
     }
 
     fn parse_assoc_item_(
         &mut self,
-        at_end: &mut bool,
-        mut attrs: Vec<Attribute>,
-        req_name: ReqName,
-    ) -> PResult<'a, AssocItem> {
-        let lo = self.token.span;
-        let vis = self.parse_visibility(FollowedByType::No)?;
-        let defaultness = self.parse_defaultness();
-        let (ident, kind) = self.parse_assoc_item_kind(at_end, &mut attrs, req_name, &vis)?;
-        let span = lo.to(self.prev_span);
-        let id = DUMMY_NODE_ID;
-        Ok(AssocItem { id, span, ident, attrs, vis, defaultness, kind, tokens: None })
-    }
-
-    fn parse_assoc_item_kind(
-        &mut self,
-        at_end: &mut bool,
-        attrs: &mut Vec<Attribute>,
+        attrs: Vec<Attribute>,
         req_name: ReqName,
-        vis: &Visibility,
-    ) -> PResult<'a, (Ident, AssocItemKind)> {
-        if self.eat_keyword(kw::Type) {
-            match self.parse_type_alias()? {
-                (ident, ItemKind::TyAlias(a, b, c)) => Ok((ident, AssocItemKind::TyAlias(a, b, c))),
-                _ => unreachable!(),
-            }
-        } else if self.check_fn_front_matter() {
-            let (ident, sig, generics, body) = self.parse_fn(at_end, attrs, req_name)?;
-            Ok((ident, AssocItemKind::Fn(sig, generics, body)))
-        } else if self.is_static_global() {
-            self.bump(); // `static`
-            let mutbl = self.parse_mutability();
-            let (ident, ty, expr) = self.parse_item_const_common(Some(mutbl))?;
-            Ok((ident, AssocItemKind::Static(ty, mutbl, expr)))
-        } else if self.eat_keyword(kw::Const) {
-            let (ident, ty, expr) = self.parse_item_const_common(None)?;
-            Ok((ident, AssocItemKind::Const(ty, expr)))
-        } else if self.isnt_macro_invocation() {
-            Err(self.missing_nested_item_kind_err(self.prev_span))
-        } else if self.token.is_path_start() {
-            let mac = self.parse_item_macro(&vis)?;
-            *at_end = true;
-            Ok((Ident::invalid(), AssocItemKind::Macro(mac)))
-        } else {
-            self.recover_attrs_no_item(attrs)?;
-            self.unexpected()
-        }
+    ) -> PResult<'a, Option<Option<P<AssocItem>>>> {
+        let it = self.parse_item_common(attrs, true, false, req_name)?;
+        Ok(it.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| {
+            let kind = match kind {
+                ItemKind::Mac(a) => AssocItemKind::Macro(a),
+                ItemKind::Fn(a, b, c) => AssocItemKind::Fn(a, b, c),
+                ItemKind::TyAlias(a, b, c) => AssocItemKind::TyAlias(a, b, c),
+                ItemKind::Const(a, c) => AssocItemKind::Const(a, c),
+                ItemKind::Static(a, _, b) => {
+                    self.struct_span_err(span, "associated `static` items are not allowed").emit();
+                    AssocItemKind::Const(a, b)
+                }
+                _ => {
+                    let span = self.sess.source_map().def_span(span);
+                    self.struct_span_err(span, "item kind not supported in `trait` or `impl`")
+                        .emit();
+                    return None;
+                }
+            };
+            Some(P(Item { attrs, id, span, vis, ident, defaultness, kind, tokens }))
+        }))
     }
 
     /// Parses a `type` alias with the following grammar:
@@ -907,7 +859,7 @@ impl<'a> Parser<'a> {
     /// ```
     fn parse_item_foreign_mod(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, ItemInfo> {
         let abi = self.parse_abi(); // ABI?
-        let items = self.parse_item_list(attrs, |p, _| p.parse_foreign_item())?;
+        let items = self.parse_item_list(attrs, |p| p.parse_foreign_item())?;
         let module = ast::ForeignMod { abi, items };
         Ok((Ident::invalid(), ItemKind::ForeignMod(module)))
     }
@@ -917,17 +869,17 @@ impl<'a> Parser<'a> {
         maybe_whole!(self, NtForeignItem, |item| Some(Some(item)));
 
         let attrs = self.parse_outer_attributes()?;
-        let it = self.parse_item_common(attrs, true, false)?;
+        let it = self.parse_item_common(attrs, true, false, |_| true)?;
         Ok(it.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| {
             self.error_on_illegal_default(defaultness);
             let kind = match kind {
-                ItemKind::Mac(a) => AssocItemKind::Macro(a),
-                ItemKind::Fn(a, b, c) => AssocItemKind::Fn(a, b, c),
-                ItemKind::TyAlias(a, b, c) => AssocItemKind::TyAlias(a, b, c),
-                ItemKind::Static(a, b, c) => AssocItemKind::Static(a, b, c),
+                ItemKind::Mac(a) => ForeignItemKind::Macro(a),
+                ItemKind::Fn(a, b, c) => ForeignItemKind::Fn(a, b, c),
+                ItemKind::TyAlias(a, b, c) => ForeignItemKind::TyAlias(a, b, c),
+                ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c),
                 ItemKind::Const(a, b) => {
                     self.error_on_foreign_const(span, ident);
-                    AssocItemKind::Static(a, Mutability::Not, b)
+                    ForeignItemKind::Static(a, Mutability::Not, b)
                 }
                 _ => {
                     let span = self.sess.source_map().def_span(span);
@@ -989,22 +941,6 @@ impl<'a> Parser<'a> {
     ///
     /// When `m` is `"const"`, `$ident` may also be `"_"`.
     fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<'a, ItemInfo> {
-        let (id, ty, expr) = self.parse_item_const_common(m)?;
-        let item = match m {
-            Some(m) => ItemKind::Static(ty, m, expr),
-            None => ItemKind::Const(ty, expr),
-        };
-        Ok((id, item))
-    }
-
-    /// Parse `["const" | ("static" "mut"?)] $ident ":" $ty (= $expr)?` with
-    /// `["const" | ("static" "mut"?)]` already parsed and stored in `m`.
-    ///
-    /// When `m` is `"const"`, `$ident` may also be `"_"`.
-    fn parse_item_const_common(
-        &mut self,
-        m: Option<Mutability>,
-    ) -> PResult<'a, (Ident, P<Ty>, Option<P<ast::Expr>>)> {
         let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?;
 
         // Parse the type of a `const` or `static mut?` item.
@@ -1017,7 +953,12 @@ impl<'a> Parser<'a> {
 
         let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None };
         self.expect_semi()?;
-        Ok((id, ty, expr))
+
+        let item = match m {
+            Some(m) => ItemKind::Static(ty, m, expr),
+            None => ItemKind::Const(ty, expr),
+        };
+        Ok((id, item))
     }
 
     /// We were supposed to parse `:` but the `:` was missing.
@@ -1477,19 +1418,6 @@ impl<'a> Parser<'a> {
         }
         Ok(true)
     }
-
-    fn mk_item<K>(
-        &self,
-        lo: Span,
-        ident: Ident,
-        kind: K,
-        vis: Visibility,
-        defaultness: Defaultness,
-        attrs: Vec<Attribute>,
-    ) -> Item<K> {
-        let span = lo.to(self.prev_span);
-        Item { ident, attrs, id: DUMMY_NODE_ID, kind, vis, defaultness, span, tokens: None }
-    }
 }
 
 /// The parsing configuration used to parse a parameter list (see `parse_fn_params`).
diff --git a/src/test/ui/async-await/no-unsafe-async.stderr b/src/test/ui/async-await/no-unsafe-async.stderr
index 2651588d59710..c97b4ff0f497e 100644
--- a/src/test/ui/async-await/no-unsafe-async.stderr
+++ b/src/test/ui/async-await/no-unsafe-async.stderr
@@ -1,8 +1,13 @@
 error: expected one of `extern` or `fn`, found keyword `async`
   --> $DIR/no-unsafe-async.rs:7:12
    |
+LL | impl S {
+   |        - while parsing this item list starting here
+LL |     #[cfg(FALSE)]
 LL |     unsafe async fn g() {}
    |            ^^^^^ expected one of `extern` or `fn`
+LL | }
+   | - the item list ends here
 
 error: expected one of `extern` or `fn`, found keyword `async`
   --> $DIR/no-unsafe-async.rs:11:8
diff --git a/src/test/ui/did_you_mean/issue-40006.rs b/src/test/ui/did_you_mean/issue-40006.rs
index 2ed682cea9503..74f304d81a0f1 100644
--- a/src/test/ui/did_you_mean/issue-40006.rs
+++ b/src/test/ui/did_you_mean/issue-40006.rs
@@ -1,28 +1,28 @@
-impl dyn A { //~ ERROR missing
+impl dyn A {
     Y
-}
+} //~ ERROR expected one of `!` or `::`, found `}`
 
 struct S;
 
-trait X { //~ ERROR missing
-    X() {}
+trait X {
+    X() {} //~ ERROR expected one of `!` or `::`, found `(`
     fn xxx() { ### }
     L = M;
     Z = { 2 + 3 };
     ::Y ();
 }
 
-trait A { //~ ERROR missing
-    X() {}
+trait A {
+    X() {} //~ ERROR expected one of `!` or `::`, found `(`
 }
 trait B {
     fn xxx() { ### } //~ ERROR expected
 }
-trait C { //~ ERROR missing `fn`, `type`, `const`, or `static` for item declaration
-    L = M;
+trait C {
+    L = M; //~ ERROR expected one of `!` or `::`, found `=`
 }
-trait D { //~ ERROR missing `fn`, `type`, `const`, or `static` for item declaration
-    Z = { 2 + 3 };
+trait D {
+    Z = { 2 + 3 }; //~ ERROR expected one of `!` or `::`, found `=`
 }
 trait E {
     ::Y (); //~ ERROR expected one of
diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr
index 119e30a3e0f57..613d7eee59480 100644
--- a/src/test/ui/did_you_mean/issue-40006.stderr
+++ b/src/test/ui/did_you_mean/issue-40006.stderr
@@ -1,26 +1,36 @@
-error: missing `fn`, `type`, `const`, or `static` for item declaration
-  --> $DIR/issue-40006.rs:1:13
+error: expected one of `!` or `::`, found `}`
+  --> $DIR/issue-40006.rs:3:1
    |
-LL |   impl dyn A {
-   |  _____________^
-LL | |     Y
-   | |____^ missing `fn`, `type`, `const`, or `static`
+LL | impl dyn A {
+   |            - while parsing this item list starting here
+LL |     Y
+   |      - expected one of `!` or `::`
+LL | }
+   | ^
+   | |
+   | unexpected token
+   | the item list ends here
 
-error: missing `fn`, `type`, `const`, or `static` for item declaration
-  --> $DIR/issue-40006.rs:7:10
+error: expected one of `!` or `::`, found `(`
+  --> $DIR/issue-40006.rs:8:6
    |
-LL |   trait X {
-   |  __________^
-LL | |     X() {}
-   | |____^ missing `fn`, `type`, `const`, or `static`
+LL | trait X {
+   |         - while parsing this item list starting here
+LL |     X() {}
+   |      ^ expected one of `!` or `::`
+...
+LL | }
+   | - the item list ends here
 
-error: missing `fn`, `type`, `const`, or `static` for item declaration
-  --> $DIR/issue-40006.rs:15:10
+error: expected one of `!` or `::`, found `(`
+  --> $DIR/issue-40006.rs:16:6
    |
-LL |   trait A {
-   |  __________^
-LL | |     X() {}
-   | |____^ missing `fn`, `type`, `const`, or `static`
+LL | trait A {
+   |         - while parsing this item list starting here
+LL |     X() {}
+   |      ^ expected one of `!` or `::`
+LL | }
+   | - the item list ends here
 
 error: expected `[`, found `#`
   --> $DIR/issue-40006.rs:19:17
@@ -28,33 +38,51 @@ error: expected `[`, found `#`
 LL |     fn xxx() { ### }
    |                 ^ expected `[`
 
-error: missing `fn`, `type`, `const`, or `static` for item declaration
-  --> $DIR/issue-40006.rs:21:10
+error: expected one of `!` or `::`, found `=`
+  --> $DIR/issue-40006.rs:22:7
    |
-LL |   trait C {
-   |  __________^
-LL | |     L = M;
-   | |____^ missing `fn`, `type`, `const`, or `static`
+LL | trait C {
+   |         - while parsing this item list starting here
+LL |     L = M;
+   |       ^ expected one of `!` or `::`
+LL | }
+   | - the item list ends here
 
-error: missing `fn`, `type`, `const`, or `static` for item declaration
-  --> $DIR/issue-40006.rs:24:10
+error: expected one of `!` or `::`, found `=`
+  --> $DIR/issue-40006.rs:25:7
    |
-LL |   trait D {
-   |  __________^
-LL | |     Z = { 2 + 3 };
-   | |____^ missing `fn`, `type`, `const`, or `static`
+LL | trait D {
+   |         - while parsing this item list starting here
+LL |     Z = { 2 + 3 };
+   |       ^ expected one of `!` or `::`
+LL | }
+   | - the item list ends here
 
 error: expected one of `!` or `::`, found `(`
   --> $DIR/issue-40006.rs:28:9
    |
+LL | trait E {
+   |         - while parsing this item list starting here
 LL |     ::Y ();
    |         ^ expected one of `!` or `::`
+LL | }
+   | - the item list ends here
 
-error: missing `fn`, `type`, `const`, or `static` for item declaration
+error: missing `fn` for method definition
   --> $DIR/issue-40006.rs:32:8
    |
+LL | impl S {
+   |        - while parsing this item list starting here
 LL |     pub hello_method(&self) {
-   |        ^ missing `fn`, `type`, `const`, or `static`
+   |        ^
+...
+LL | }
+   | - the item list ends here
+   |
+help: add `fn` here to parse `hello_method` as a public method
+   |
+LL |     pub fn hello_method(&self) {
+   |         ^^
 
 error[E0599]: no method named `hello_method` found for struct `S` in the current scope
   --> $DIR/issue-40006.rs:38:7
diff --git a/src/test/ui/generic-associated-types/empty_generics.stderr b/src/test/ui/generic-associated-types/empty_generics.stderr
index d3acad47831be..bd5708d814037 100644
--- a/src/test/ui/generic-associated-types/empty_generics.stderr
+++ b/src/test/ui/generic-associated-types/empty_generics.stderr
@@ -1,8 +1,13 @@
 error: expected one of `>`, `const`, identifier, or lifetime, found `,`
   --> $DIR/empty_generics.rs:5:14
    |
+LL | trait Foo {
+   |           - while parsing this item list starting here
 LL |     type Bar<,>;
    |              ^ expected one of `>`, `const`, identifier, or lifetime
+LL |
+LL | }
+   | - the item list ends here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-58856-1.stderr b/src/test/ui/issues/issue-58856-1.stderr
index 0ea6b01754890..a8db8e8b41ad2 100644
--- a/src/test/ui/issues/issue-58856-1.stderr
+++ b/src/test/ui/issues/issue-58856-1.stderr
@@ -9,8 +9,14 @@ LL |     fn b(self>
 error: expected `;` or `{`, found `>`
   --> $DIR/issue-58856-1.rs:3:14
    |
+LL | impl A {
+   |        - while parsing this item list starting here
+LL |
 LL |     fn b(self>
    |              ^ expected `;` or `{`
+...
+LL | }
+   | - the item list ends here
 
 error[E0412]: cannot find type `A` in this scope
   --> $DIR/issue-58856-1.rs:1:6
diff --git a/src/test/ui/issues/issue-58856-2.rs b/src/test/ui/issues/issue-58856-2.rs
index 745f0300bd5ad..9356d57b0e5f4 100644
--- a/src/test/ui/issues/issue-58856-2.rs
+++ b/src/test/ui/issues/issue-58856-2.rs
@@ -9,6 +9,6 @@ impl Howness for () {
         Empty
     }
 }
-//~^ ERROR expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`,
+//~^ ERROR non-item in item list
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-58856-2.stderr b/src/test/ui/issues/issue-58856-2.stderr
index f4ca3c46ea28a..303b5eacc3296 100644
--- a/src/test/ui/issues/issue-58856-2.stderr
+++ b/src/test/ui/issues/issue-58856-2.stderr
@@ -7,13 +7,17 @@ LL |     fn how_are_you(&self -> Empty {
    |                   |     help: `)` may belong here
    |                   unclosed delimiter
 
-error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `static`, `type`, `unsafe`, `}`, or identifier, found `)`
+error: non-item in item list
   --> $DIR/issue-58856-2.rs:11:1
    |
-LL |     }
-   |      - expected one of 12 possible tokens
+LL | impl Howness for () {
+   |                     - item list starts here
+...
 LL | }
-   | ^ unexpected token
+   | ^
+   | |
+   | non-item starts here
+   | item list ends here
 
 error[E0407]: method `how_are_you` is not a member of trait `Howness`
   --> $DIR/issue-58856-2.rs:6:5
diff --git a/src/test/ui/issues/issue-60075.rs b/src/test/ui/issues/issue-60075.rs
index 1323f646be893..e89d78ee8a6a2 100644
--- a/src/test/ui/issues/issue-60075.rs
+++ b/src/test/ui/issues/issue-60075.rs
@@ -4,7 +4,8 @@ trait T {
     fn qux() -> Option<usize> {
         let _ = if true {
         });
-//~^ ERROR expected one of `async`
-//~| ERROR expected one of `.`, `;`, `?`, `else`, or an operator, found `}`
+//~^ ERROR non-item in item list
+//~| ERROR mismatched closing delimiter: `)`
+//~| ERROR expected one of `.`, `;`
         Some(4)
     }
diff --git a/src/test/ui/issues/issue-60075.stderr b/src/test/ui/issues/issue-60075.stderr
index bab50a53b1ae4..e3b7f4ad420e8 100644
--- a/src/test/ui/issues/issue-60075.stderr
+++ b/src/test/ui/issues/issue-60075.stderr
@@ -4,14 +4,26 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `}`
 LL |         });
    |          ^ expected one of `.`, `;`, `?`, `else`, or an operator
 
-error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `static`, `type`, `unsafe`, `}`, or identifier, found `;`
+error: non-item in item list
   --> $DIR/issue-60075.rs:6:11
    |
+LL | trait T {
+   |         - item list starts here
+...
+LL |         });
+   |           ^ non-item starts here
+...
+LL |     }
+   |     - item list ends here
+
+error: mismatched closing delimiter: `)`
+  --> $DIR/issue-60075.rs:6:10
+   |
 LL |     fn qux() -> Option<usize> {
    |                               - unclosed delimiter
 LL |         let _ = if true {
 LL |         });
-   |           ^ help: `}` may belong here
+   |          ^ mismatched closing delimiter
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/parser/assoc-static-semantic-fail.rs b/src/test/ui/parser/assoc-static-semantic-fail.rs
index cf3debd77cbfd..da4015a4620ff 100644
--- a/src/test/ui/parser/assoc-static-semantic-fail.rs
+++ b/src/test/ui/parser/assoc-static-semantic-fail.rs
@@ -10,10 +10,12 @@ impl S {
     //~^ ERROR associated `static` items are not allowed
     static IB: u8;
     //~^ ERROR associated `static` items are not allowed
+    //~| ERROR associated constant in `impl` without body
     default static IC: u8 = 0;
     //~^ ERROR associated `static` items are not allowed
     pub(crate) default static ID: u8;
     //~^ ERROR associated `static` items are not allowed
+    //~| ERROR associated constant in `impl` without body
 }
 
 trait T {
@@ -35,9 +37,11 @@ impl T for S {
     //~^ ERROR associated `static` items are not allowed
     static TB: u8;
     //~^ ERROR associated `static` items are not allowed
+    //~| ERROR associated constant in `impl` without body
     default static TC: u8 = 0;
     //~^ ERROR associated `static` items are not allowed
     pub default static TD: u8;
     //~^ ERROR associated `static` items are not allowed
+    //~| ERROR associated constant in `impl` without body
     //~| ERROR unnecessary visibility qualifier
 }
diff --git a/src/test/ui/parser/assoc-static-semantic-fail.stderr b/src/test/ui/parser/assoc-static-semantic-fail.stderr
index dfd0053fda2f3..ca05b05e9b110 100644
--- a/src/test/ui/parser/assoc-static-semantic-fail.stderr
+++ b/src/test/ui/parser/assoc-static-semantic-fail.stderr
@@ -11,67 +11,83 @@ LL |     static IB: u8;
    |     ^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:13:5
+  --> $DIR/assoc-static-semantic-fail.rs:14:5
    |
 LL |     default static IC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:15:5
+  --> $DIR/assoc-static-semantic-fail.rs:16:5
    |
 LL |     pub(crate) default static ID: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:20:5
+  --> $DIR/assoc-static-semantic-fail.rs:22:5
    |
 LL |     static TA: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:22:5
+  --> $DIR/assoc-static-semantic-fail.rs:24:5
    |
 LL |     static TB: u8;
    |     ^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:24:5
+  --> $DIR/assoc-static-semantic-fail.rs:26:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:27:5
+  --> $DIR/assoc-static-semantic-fail.rs:29:5
    |
 LL |     pub(crate) default static TD: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:34:5
+  --> $DIR/assoc-static-semantic-fail.rs:36:5
    |
 LL |     static TA: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:36:5
+  --> $DIR/assoc-static-semantic-fail.rs:38:5
    |
 LL |     static TB: u8;
    |     ^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:38:5
+  --> $DIR/assoc-static-semantic-fail.rs:41:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:40:5
+  --> $DIR/assoc-static-semantic-fail.rs:43:5
    |
 LL |     pub default static TD: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: associated constant in `impl` without body
+  --> $DIR/assoc-static-semantic-fail.rs:11:5
+   |
+LL |     static IB: u8;
+   |     ^^^^^^^^^^^^^-
+   |                  |
+   |                  help: provide a definition for the constant: `= <expr>;`
+
+error: associated constant in `impl` without body
+  --> $DIR/assoc-static-semantic-fail.rs:16:5
+   |
+LL |     pub(crate) default static ID: u8;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                                     |
+   |                                     help: provide a definition for the constant: `= <expr>;`
+
 error: `default` is only allowed on items in `impl` definitions
-  --> $DIR/assoc-static-semantic-fail.rs:24:5
+  --> $DIR/assoc-static-semantic-fail.rs:26:5
    |
 LL |     default static TC: u8 = 0;
    |     -------^^^^^^^^^^^^^^^^^^^
@@ -79,7 +95,7 @@ LL |     default static TC: u8 = 0;
    |     `default` because of this
 
 error: `default` is only allowed on items in `impl` definitions
-  --> $DIR/assoc-static-semantic-fail.rs:27:5
+  --> $DIR/assoc-static-semantic-fail.rs:29:5
    |
 LL |     pub(crate) default static TD: u8;
    |     ^^^^^^^^^^^-------^^^^^^^^^^^^^^^
@@ -87,17 +103,33 @@ LL |     pub(crate) default static TD: u8;
    |                `default` because of this
 
 error[E0449]: unnecessary visibility qualifier
-  --> $DIR/assoc-static-semantic-fail.rs:27:5
+  --> $DIR/assoc-static-semantic-fail.rs:29:5
    |
 LL |     pub(crate) default static TD: u8;
    |     ^^^^^^^^^^
 
+error: associated constant in `impl` without body
+  --> $DIR/assoc-static-semantic-fail.rs:38:5
+   |
+LL |     static TB: u8;
+   |     ^^^^^^^^^^^^^-
+   |                  |
+   |                  help: provide a definition for the constant: `= <expr>;`
+
+error: associated constant in `impl` without body
+  --> $DIR/assoc-static-semantic-fail.rs:43:5
+   |
+LL |     pub default static TD: u8;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |                              |
+   |                              help: provide a definition for the constant: `= <expr>;`
+
 error[E0449]: unnecessary visibility qualifier
-  --> $DIR/assoc-static-semantic-fail.rs:40:5
+  --> $DIR/assoc-static-semantic-fail.rs:43:5
    |
 LL |     pub default static TD: u8;
    |     ^^^ `pub` not permitted here because it's implied
 
-error: aborting due to 16 previous errors
+error: aborting due to 20 previous errors
 
 For more information about this error, try `rustc --explain E0449`.
diff --git a/src/test/ui/parser/attrs-after-extern-mod.stderr b/src/test/ui/parser/attrs-after-extern-mod.stderr
index 6060f3afe1e95..3862f5c379fc3 100644
--- a/src/test/ui/parser/attrs-after-extern-mod.stderr
+++ b/src/test/ui/parser/attrs-after-extern-mod.stderr
@@ -1,8 +1,12 @@
 error: expected item after attributes
   --> $DIR/attrs-after-extern-mod.rs:6:5
    |
+LL | extern {
+   |        - while parsing this item list starting here
 LL |     #[cfg(stage37)]
    |     ^^^^^^^^^^^^^^^
+LL | }
+   | - the item list ends here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/default-on-wrong-item-kind.rs b/src/test/ui/parser/default-on-wrong-item-kind.rs
index 0fe20473587ca..16bb7735c90c6 100644
--- a/src/test/ui/parser/default-on-wrong-item-kind.rs
+++ b/src/test/ui/parser/default-on-wrong-item-kind.rs
@@ -60,3 +60,73 @@ extern "C" {
     default macro_rules! foo {} //~ ERROR item cannot be `default`
     //~^ ERROR item kind not supported in `extern` block
 }
+
+#[cfg(FALSE)]
+impl S {
+    default extern crate foo;
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default use foo;
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default static foo: u8;
+    //~^ ERROR associated `static` items are not allowed
+    default const foo: u8;
+    default fn foo();
+    default mod foo {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default extern "C" {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default type foo = u8;
+    default enum foo {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default struct foo {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default union foo {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default trait foo {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default trait foo = Ord;
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default impl foo {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default!();
+    default::foo::bar!();
+    default macro foo {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default macro_rules! foo {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+}
+
+#[cfg(FALSE)]
+trait T {
+    default extern crate foo;
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default use foo;
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default static foo: u8;
+    //~^ ERROR associated `static` items are not allowed
+    default const foo: u8;
+    default fn foo();
+    default mod foo {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default extern "C" {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default type foo = u8;
+    default enum foo {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default struct foo {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default union foo {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default trait foo {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default trait foo = Ord;
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default impl foo {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default!();
+    default::foo::bar!();
+    default macro foo {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+    default macro_rules! foo {}
+    //~^ ERROR item kind not supported in `trait` or `impl`
+}
diff --git a/src/test/ui/parser/default-on-wrong-item-kind.stderr b/src/test/ui/parser/default-on-wrong-item-kind.stderr
index e089bbbddde91..1812c45eba6a9 100644
--- a/src/test/ui/parser/default-on-wrong-item-kind.stderr
+++ b/src/test/ui/parser/default-on-wrong-item-kind.stderr
@@ -320,5 +320,161 @@ error: item kind not supported in `extern` block
 LL |     default macro_rules! foo {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 43 previous errors
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:66:5
+   |
+LL |     default extern crate foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:68:5
+   |
+LL |     default use foo;
+   |     ^^^^^^^^^^^^^^^^
+
+error: associated `static` items are not allowed
+  --> $DIR/default-on-wrong-item-kind.rs:70:5
+   |
+LL |     default static foo: u8;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:74:5
+   |
+LL |     default mod foo {}
+   |     ^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:76:5
+   |
+LL |     default extern "C" {}
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:79:5
+   |
+LL |     default enum foo {}
+   |     ^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:81:5
+   |
+LL |     default struct foo {}
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:83:5
+   |
+LL |     default union foo {}
+   |     ^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:85:5
+   |
+LL |     default trait foo {}
+   |     ^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:87:5
+   |
+LL |     default trait foo = Ord;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:89:5
+   |
+LL |     default impl foo {}
+   |     ^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:93:5
+   |
+LL |     default macro foo {}
+   |     ^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:95:5
+   |
+LL |     default macro_rules! foo {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:101:5
+   |
+LL |     default extern crate foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:103:5
+   |
+LL |     default use foo;
+   |     ^^^^^^^^^^^^^^^^
+
+error: associated `static` items are not allowed
+  --> $DIR/default-on-wrong-item-kind.rs:105:5
+   |
+LL |     default static foo: u8;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:109:5
+   |
+LL |     default mod foo {}
+   |     ^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:111:5
+   |
+LL |     default extern "C" {}
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:114:5
+   |
+LL |     default enum foo {}
+   |     ^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:116:5
+   |
+LL |     default struct foo {}
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:118:5
+   |
+LL |     default union foo {}
+   |     ^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:120:5
+   |
+LL |     default trait foo {}
+   |     ^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:122:5
+   |
+LL |     default trait foo = Ord;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:124:5
+   |
+LL |     default impl foo {}
+   |     ^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:128:5
+   |
+LL |     default macro foo {}
+   |     ^^^^^^^^^^^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/default-on-wrong-item-kind.rs:130:5
+   |
+LL |     default macro_rules! foo {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 69 previous errors
 
diff --git a/src/test/ui/parser/default-unmatched-assoc.rs b/src/test/ui/parser/default-unmatched-assoc.rs
new file mode 100644
index 0000000000000..bca6f5654dbfb
--- /dev/null
+++ b/src/test/ui/parser/default-unmatched-assoc.rs
@@ -0,0 +1,16 @@
+fn main() {}
+
+trait Foo {
+    default!(); //~ ERROR cannot find macro `default` in this scope
+    default do
+    //~^ ERROR unmatched `default`
+    //~| ERROR non-item in item list
+}
+
+struct S;
+impl S {
+    default!(); //~ ERROR cannot find macro `default` in this scope
+    default do
+    //~^ ERROR unmatched `default`
+    //~| ERROR non-item in item list
+}
diff --git a/src/test/ui/parser/default-unmatched-assoc.stderr b/src/test/ui/parser/default-unmatched-assoc.stderr
new file mode 100644
index 0000000000000..f3877f2ca6d51
--- /dev/null
+++ b/src/test/ui/parser/default-unmatched-assoc.stderr
@@ -0,0 +1,50 @@
+error: unmatched `default`
+  --> $DIR/default-unmatched-assoc.rs:5:5
+   |
+LL |     default do
+   |     ^^^^^^^ the unmatched `default`
+
+error: non-item in item list
+  --> $DIR/default-unmatched-assoc.rs:5:13
+   |
+LL | trait Foo {
+   |           - item list starts here
+LL |     default!();
+LL |     default do
+   |             ^^ non-item starts here
+...
+LL | }
+   | - item list ends here
+
+error: unmatched `default`
+  --> $DIR/default-unmatched-assoc.rs:13:5
+   |
+LL |     default do
+   |     ^^^^^^^ the unmatched `default`
+
+error: non-item in item list
+  --> $DIR/default-unmatched-assoc.rs:13:13
+   |
+LL | impl S {
+   |        - item list starts here
+LL |     default!();
+LL |     default do
+   |             ^^ non-item starts here
+...
+LL | }
+   | - item list ends here
+
+error: cannot find macro `default` in this scope
+  --> $DIR/default-unmatched-assoc.rs:12:5
+   |
+LL |     default!();
+   |     ^^^^^^^
+
+error: cannot find macro `default` in this scope
+  --> $DIR/default-unmatched-assoc.rs:4:5
+   |
+LL |     default!();
+   |     ^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/parser/default.rs b/src/test/ui/parser/default.rs
index 50952eef22f5c..bd9ed0f452470 100644
--- a/src/test/ui/parser/default.rs
+++ b/src/test/ui/parser/default.rs
@@ -20,7 +20,8 @@ impl Foo for u16 {
 
 impl Foo for u32 { //~ ERROR not all trait items implemented, missing: `foo`
     default pub fn foo<T: Default>() -> T { T::default() }
-    //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration
+    //~^ ERROR unmatched `default`
+    //~| ERROR non-item in item list
 }
 
 fn main() {}
diff --git a/src/test/ui/parser/default.stderr b/src/test/ui/parser/default.stderr
index 07b051ece2b5d..fbf8101c36a73 100644
--- a/src/test/ui/parser/default.stderr
+++ b/src/test/ui/parser/default.stderr
@@ -1,8 +1,19 @@
-error: missing `fn`, `type`, `const`, or `static` for item declaration
-  --> $DIR/default.rs:22:12
+error: unmatched `default`
+  --> $DIR/default.rs:22:5
    |
 LL |     default pub fn foo<T: Default>() -> T { T::default() }
-   |            ^ missing `fn`, `type`, `const`, or `static`
+   |     ^^^^^^^ the unmatched `default`
+
+error: non-item in item list
+  --> $DIR/default.rs:22:13
+   |
+LL | impl Foo for u32 {
+   |                  - item list starts here
+LL |     default pub fn foo<T: Default>() -> T { T::default() }
+   |             ^^^ non-item starts here
+...
+LL | }
+   | - item list ends here
 
 error[E0449]: unnecessary visibility qualifier
   --> $DIR/default.rs:16:5
@@ -19,7 +30,7 @@ LL |     fn foo<T: Default>() -> T;
 LL | impl Foo for u32 {
    | ^^^^^^^^^^^^^^^^ missing `foo` in implementation
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0046, E0449.
 For more information about an error, try `rustc --explain E0046`.
diff --git a/src/test/ui/parser/extern-no-fn.stderr b/src/test/ui/parser/extern-no-fn.stderr
index 023201250148e..0151cb4235b0d 100644
--- a/src/test/ui/parser/extern-no-fn.stderr
+++ b/src/test/ui/parser/extern-no-fn.stderr
@@ -1,8 +1,12 @@
 error: expected one of `!` or `::`, found `(`
   --> $DIR/extern-no-fn.rs:2:6
    |
+LL | extern {
+   |        - while parsing this item list starting here
 LL |     f();
    |      ^ expected one of `!` or `::`
+LL | }
+   | - the item list ends here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-19398.rs b/src/test/ui/parser/issue-19398.rs
index 014c930ef8205..46eb320a172f2 100644
--- a/src/test/ui/parser/issue-19398.rs
+++ b/src/test/ui/parser/issue-19398.rs
@@ -1,6 +1,6 @@
 trait T {
-    //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration
     extern "Rust" unsafe fn foo();
+    //~^ ERROR expected `{`, found keyword `unsafe`
 }
 
 fn main() {}
diff --git a/src/test/ui/parser/issue-19398.stderr b/src/test/ui/parser/issue-19398.stderr
index b38b39f9bd99f..1da00960adfe4 100644
--- a/src/test/ui/parser/issue-19398.stderr
+++ b/src/test/ui/parser/issue-19398.stderr
@@ -1,11 +1,13 @@
-error: missing `fn`, `type`, `const`, or `static` for item declaration
-  --> $DIR/issue-19398.rs:1:10
+error: expected `{`, found keyword `unsafe`
+  --> $DIR/issue-19398.rs:2:19
    |
-LL |   trait T {
-   |  __________^
-LL | |
-LL | |     extern "Rust" unsafe fn foo();
-   | |____^ missing `fn`, `type`, `const`, or `static`
+LL | trait T {
+   |         - while parsing this item list starting here
+LL |     extern "Rust" unsafe fn foo();
+   |                   ^^^^^^ expected `{`
+LL |
+LL | }
+   | - the item list ends here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-20711-2.stderr b/src/test/ui/parser/issue-20711-2.stderr
index 10ef31584dec1..12b18bbc59416 100644
--- a/src/test/ui/parser/issue-20711-2.stderr
+++ b/src/test/ui/parser/issue-20711-2.stderr
@@ -1,8 +1,14 @@
 error: expected item after attributes
   --> $DIR/issue-20711-2.rs:6:5
    |
+LL | impl Foo {
+   |          - while parsing this item list starting here
+...
 LL |     #[stable(feature = "rust1", since = "1.0.0")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | }
+   | - the item list ends here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-20711.stderr b/src/test/ui/parser/issue-20711.stderr
index 66768de569418..4af4b22bee292 100644
--- a/src/test/ui/parser/issue-20711.stderr
+++ b/src/test/ui/parser/issue-20711.stderr
@@ -1,8 +1,13 @@
 error: expected item after attributes
   --> $DIR/issue-20711.rs:4:5
    |
+LL | impl Foo {
+   |          - while parsing this item list starting here
 LL |     #[stable(feature = "rust1", since = "1.0.0")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | }
+   | - the item list ends here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-21153.rs b/src/test/ui/parser/issue-21153.rs
index 4fe05e6f04155..bf5fdb1f3c6b0 100644
--- a/src/test/ui/parser/issue-21153.rs
+++ b/src/test/ui/parser/issue-21153.rs
@@ -1,6 +1,6 @@
 trait MyTrait<T>: Iterator {
-    //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration
     Item = T;
+    //~^ ERROR expected one of `!` or `::`, found `=`
 }
 
 fn main() {}
diff --git a/src/test/ui/parser/issue-21153.stderr b/src/test/ui/parser/issue-21153.stderr
index e9824bd729081..cbfa9ded3c393 100644
--- a/src/test/ui/parser/issue-21153.stderr
+++ b/src/test/ui/parser/issue-21153.stderr
@@ -1,11 +1,13 @@
-error: missing `fn`, `type`, `const`, or `static` for item declaration
-  --> $DIR/issue-21153.rs:1:29
+error: expected one of `!` or `::`, found `=`
+  --> $DIR/issue-21153.rs:2:10
    |
-LL |   trait MyTrait<T>: Iterator {
-   |  _____________________________^
-LL | |
-LL | |     Item = T;
-   | |____^ missing `fn`, `type`, `const`, or `static`
+LL | trait MyTrait<T>: Iterator {
+   |                            - while parsing this item list starting here
+LL |     Item = T;
+   |          ^ expected one of `!` or `::`
+LL |
+LL | }
+   | - the item list ends here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-32446.stderr b/src/test/ui/parser/issue-32446.stderr
index d25828da0b979..7515369aaa0b9 100644
--- a/src/test/ui/parser/issue-32446.stderr
+++ b/src/test/ui/parser/issue-32446.stderr
@@ -1,8 +1,11 @@
-error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `static`, `type`, `unsafe`, `}`, or identifier, found `...`
+error: non-item in item list
   --> $DIR/issue-32446.rs:4:11
    |
 LL | trait T { ... }
-   |           ^^^ expected one of 12 possible tokens
+   |         - ^^^ - item list ends here
+   |         | |
+   |         | non-item starts here
+   |         item list starts here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-41155.rs b/src/test/ui/parser/issue-41155.rs
index 3c24d2b447de4..bed4805e7cea9 100644
--- a/src/test/ui/parser/issue-41155.rs
+++ b/src/test/ui/parser/issue-41155.rs
@@ -1,7 +1,7 @@
 struct S;
 
 impl S {
-    pub
-} //~ ERROR expected one of
+    pub //~ ERROR unmatched visibility `pub`
+} //~ ERROR non-item in item list
 
 fn main() {}
diff --git a/src/test/ui/parser/issue-41155.stderr b/src/test/ui/parser/issue-41155.stderr
index a91ef6c67e89e..a9c1035f4d85d 100644
--- a/src/test/ui/parser/issue-41155.stderr
+++ b/src/test/ui/parser/issue-41155.stderr
@@ -1,10 +1,22 @@
-error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `static`, `type`, `unsafe`, or identifier, found `}`
+error: unmatched visibility `pub`
+  --> $DIR/issue-41155.rs:4:5
+   |
+LL |     pub
+   |     ^^^ the unmatched visibility
+   |
+   = help: you likely meant to define an item, e.g., `pub fn foo() {}`
+
+error: non-item in item list
   --> $DIR/issue-41155.rs:5:1
    |
+LL | impl S {
+   |        - item list starts here
 LL |     pub
-   |        - expected one of 10 possible tokens
 LL | }
-   | ^ unexpected token
+   | ^
+   | |
+   | non-item starts here
+   | item list ends here
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/issue-6610.stderr b/src/test/ui/parser/issue-6610.stderr
index 22d93bffeaded..a980420894664 100644
--- a/src/test/ui/parser/issue-6610.stderr
+++ b/src/test/ui/parser/issue-6610.stderr
@@ -2,7 +2,11 @@ error: expected `;` or `{`, found `}`
   --> $DIR/issue-6610.rs:1:20
    |
 LL | trait Foo { fn a() }
-   |                    ^ expected `;` or `{`
+   |           -        ^
+   |           |        |
+   |           |        expected `;` or `{`
+   |           |        the item list ends here
+   |           while parsing this item list starting here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/macro/trait-non-item-macros.rs b/src/test/ui/parser/macro/trait-non-item-macros.rs
index 5021886bf9881..97fb564bf6479 100644
--- a/src/test/ui/parser/macro/trait-non-item-macros.rs
+++ b/src/test/ui/parser/macro/trait-non-item-macros.rs
@@ -1,10 +1,13 @@
 macro_rules! bah {
-    ($a:expr) => ($a)
-    //~^ ERROR expected one of `async`
+    ($a:expr) => {
+        $a
+    }; //~^ ERROR macro expansion ignores token `2` and any following
 }
 
-trait bar {
+trait Bar {
     bah!(2);
 }
 
-fn main() {}
+fn main() {
+    let _recovery_witness: () = 0; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/parser/macro/trait-non-item-macros.stderr b/src/test/ui/parser/macro/trait-non-item-macros.stderr
index c76b096a1ebf4..35e5bfe62f5b4 100644
--- a/src/test/ui/parser/macro/trait-non-item-macros.stderr
+++ b/src/test/ui/parser/macro/trait-non-item-macros.stderr
@@ -1,13 +1,22 @@
-error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `static`, `type`, `unsafe`, or identifier, found `2`
-  --> $DIR/trait-non-item-macros.rs:2:19
+error: macro expansion ignores token `2` and any following
+  --> $DIR/trait-non-item-macros.rs:3:9
    |
-LL |     ($a:expr) => ($a)
-   |                   ^^ expected one of 11 possible tokens
+LL |         $a
+   |         ^^
 ...
 LL |     bah!(2);
-   |     -------- in this macro invocation
+   |     -------- caused by the macro expansion here
    |
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: the usage of `bah!` is likely invalid in trait item context
 
-error: aborting due to previous error
+error[E0308]: mismatched types
+  --> $DIR/trait-non-item-macros.rs:12:33
+   |
+LL |     let _recovery_witness: () = 0;
+   |                            --   ^ expected `()`, found integer
+   |                            |
+   |                            expected due to this
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs
index 748db8983b595..d85255328f7f4 100644
--- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs
+++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs
@@ -3,12 +3,11 @@ fn main() {}
 impl T for () { //~ ERROR cannot find trait `T` in this scope
 
 fn foo(&self) {}
-//~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration
 
-trait T {
+trait T { //~ ERROR item kind not supported in `trait` or `impl`
     fn foo(&self);
 }
 
-pub(crate) struct Bar<T>();
+pub(crate) struct Bar<T>(); //~ ERROR item kind not supported in `trait` or `impl`
 
 //~ ERROR this file contains an unclosed delimiter
diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
index 240be39eacef4..2b72c06c9c7d3 100644
--- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
+++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/missing-close-brace-in-impl-trait.rs:14:52
+  --> $DIR/missing-close-brace-in-impl-trait.rs:13:52
    |
 LL | impl T for () {
    |               - unclosed delimiter
@@ -7,15 +7,17 @@ LL | impl T for () {
 LL |
    |                                                    ^
 
-error: missing `fn`, `type`, `const`, or `static` for item declaration
-  --> $DIR/missing-close-brace-in-impl-trait.rs:5:17
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/missing-close-brace-in-impl-trait.rs:7:1
    |
-LL |   fn foo(&self) {}
-   |  _________________^
-LL | |
-LL | |
-LL | | trait T {
-   | |_ missing `fn`, `type`, `const`, or `static`
+LL | trait T {
+   | ^^^^^^^
+
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/missing-close-brace-in-impl-trait.rs:11:1
+   |
+LL | pub(crate) struct Bar<T>();
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0405]: cannot find trait `T` in this scope
   --> $DIR/missing-close-brace-in-impl-trait.rs:3:6
@@ -23,6 +25,6 @@ error[E0405]: cannot find trait `T` in this scope
 LL | impl T for () {
    |      ^ not found in this scope
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0405`.
diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs
index 4e8cc6489bc64..b2515b17ff338 100644
--- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs
+++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs
@@ -1,11 +1,11 @@
 trait T {
-//~^ ERROR `main` function not found in crate `missing_close_brace_in_trait`
     fn foo(&self);
 
 pub(crate) struct Bar<T>();
-//~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration
+//~^ ERROR item kind not supported in `trait` or `impl`
 
 impl T for Bar<usize> {
+//~^ ERROR item kind not supported in `trait` or `impl`
 fn foo(&self) {}
 }
 
diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
index 54afad5755b15..89bf29165109f 100644
--- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
+++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
@@ -7,24 +7,17 @@ LL | trait T {
 LL | fn main() {}
    |                                                                 ^
 
-error: missing `fn`, `type`, `const`, or `static` for item declaration
-  --> $DIR/missing-close-brace-in-trait.rs:5:11
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/missing-close-brace-in-trait.rs:4:1
    |
 LL | pub(crate) struct Bar<T>();
-   |           ^ missing `fn`, `type`, `const`, or `static`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0601]: `main` function not found in crate `missing_close_brace_in_trait`
-  --> $DIR/missing-close-brace-in-trait.rs:1:1
+error: item kind not supported in `trait` or `impl`
+  --> $DIR/missing-close-brace-in-trait.rs:7:1
    |
-LL | / trait T {
-LL | |
-LL | |     fn foo(&self);
-LL | |
-...  |
-LL | |
-LL | | fn main() {}
-   | |________________________________________________________________^ consider adding a `main` function to `$DIR/missing-close-brace-in-trait.rs`
+LL | impl T for Bar<usize> {
+   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/parser/removed-syntax-static-fn.stderr b/src/test/ui/parser/removed-syntax-static-fn.stderr
index dc5625bdadea3..04e34dc16a842 100644
--- a/src/test/ui/parser/removed-syntax-static-fn.stderr
+++ b/src/test/ui/parser/removed-syntax-static-fn.stderr
@@ -7,8 +7,13 @@ LL |     static fn f() {}
 error: expected one of `:`, `;`, or `=`, found `f`
   --> $DIR/removed-syntax-static-fn.rs:4:15
    |
+LL | impl S {
+   |        - while parsing this item list starting here
 LL |     static fn f() {}
    |               ^ expected one of `:`, `;`, or `=`
+...
+LL | }
+   | - the item list ends here
 
 error: missing type for `static` item
   --> $DIR/removed-syntax-static-fn.rs:4:12

From a3b08294141bb209f9cd6a0d0b9bf56890edc742 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sat, 22 Feb 2020 08:34:24 +0100
Subject: [PATCH 08/17] parse: move token hack into `parse_item_common`.

---
 src/librustc_parse/parser/item.rs | 86 +++++++++++--------------------
 1 file changed, 31 insertions(+), 55 deletions(-)

diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 8c5add46bfcae..4bb376799ec16 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -31,13 +31,33 @@ impl<'a> Parser<'a> {
 
     pub(super) fn parse_item_(
         &mut self,
-        attrs: Vec<Attribute>,
+        mut attrs: Vec<Attribute>,
         macros_allowed: bool,
         attributes_allowed: bool,
     ) -> PResult<'a, Option<P<Item>>> {
+        maybe_whole!(self, NtItem, |item| {
+            let mut item = item;
+            mem::swap(&mut item.attrs, &mut attrs);
+            item.attrs.extend(attrs);
+            Some(item)
+        });
+        let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed, |_| true)?;
+        if let Some(ref item) = item {
+            self.error_on_illegal_default(item.defaultness);
+        }
+        Ok(item.map(P))
+    }
+
+    fn parse_item_common(
+        &mut self,
+        attrs: Vec<Attribute>,
+        mac_allowed: bool,
+        attrs_allowed: bool,
+        req_name: ReqName,
+    ) -> PResult<'a, Option<Item>> {
         let mut unclosed_delims = vec![];
-        let (ret, tokens) = self.collect_tokens(|this| {
-            let item = this.parse_item_implementation(attrs, macros_allowed, attributes_allowed);
+        let (mut item, tokens) = self.collect_tokens(|this| {
+            let item = this.parse_item_common_(attrs, mac_allowed, attrs_allowed, req_name);
             unclosed_delims.append(&mut this.unclosed_delims);
             item
         })?;
@@ -57,38 +77,15 @@ impl<'a> Parser<'a> {
         // it (bad!). To work around this case for now we just avoid recording
         // `tokens` if we detect any inner attributes. This should help keep
         // expansion correct, but we should fix this bug one day!
-        Ok(ret.map(|item| {
-            item.map(|mut i| {
-                if !i.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) {
-                    i.tokens = Some(tokens);
-                }
-                i
-            })
-        }))
-    }
-
-    /// Parses one of the items allowed by the flags.
-    fn parse_item_implementation(
-        &mut self,
-        mut attrs: Vec<Attribute>,
-        macros_allowed: bool,
-        attributes_allowed: bool,
-    ) -> PResult<'a, Option<P<Item>>> {
-        maybe_whole!(self, NtItem, |item| {
-            let mut item = item;
-            mem::swap(&mut item.attrs, &mut attrs);
-            item.attrs.extend(attrs);
-            Some(item)
-        });
-
-        let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed, |_| true)?;
-        if let Some(ref item) = item {
-            self.error_on_illegal_default(item.defaultness);
+        if let Some(item) = &mut item {
+            if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) {
+                item.tokens = Some(tokens);
+            }
         }
-        Ok(item.map(P))
+        Ok(item)
     }
 
-    fn parse_item_common(
+    fn parse_item_common_(
         &mut self,
         mut attrs: Vec<Attribute>,
         mac_allowed: bool,
@@ -652,27 +649,6 @@ impl<'a> Parser<'a> {
     /// Parses associated items.
     fn parse_assoc_item(&mut self, req_name: ReqName) -> PResult<'a, Option<Option<P<AssocItem>>>> {
         let attrs = self.parse_outer_attributes()?;
-        let mut unclosed_delims = vec![];
-        let (mut item, tokens) = self.collect_tokens(|this| {
-            let item = this.parse_assoc_item_(attrs, req_name);
-            unclosed_delims.append(&mut this.unclosed_delims);
-            item
-        })?;
-        self.unclosed_delims.append(&mut unclosed_delims);
-        // See `parse_item` for why this clause is here.
-        if let Some(Some(item)) = &mut item {
-            if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) {
-                item.tokens = Some(tokens);
-            }
-        }
-        Ok(item)
-    }
-
-    fn parse_assoc_item_(
-        &mut self,
-        attrs: Vec<Attribute>,
-        req_name: ReqName,
-    ) -> PResult<'a, Option<Option<P<AssocItem>>>> {
         let it = self.parse_item_common(attrs, true, false, req_name)?;
         Ok(it.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| {
             let kind = match kind {
@@ -869,8 +845,8 @@ impl<'a> Parser<'a> {
         maybe_whole!(self, NtForeignItem, |item| Some(Some(item)));
 
         let attrs = self.parse_outer_attributes()?;
-        let it = self.parse_item_common(attrs, true, false, |_| true)?;
-        Ok(it.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| {
+        let item = self.parse_item_common(attrs, true, false, |_| true)?;
+        Ok(item.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| {
             self.error_on_illegal_default(defaultness);
             let kind = match kind {
                 ItemKind::Mac(a) => ForeignItemKind::Macro(a),

From abc46a579b336f7ac686b8f24c0ff31be8726038 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sat, 22 Feb 2020 08:55:01 +0100
Subject: [PATCH 09/17] parse: harden `default` test.

---
 .../ui/parser/default-on-wrong-item-kind.rs   |   8 +
 .../parser/default-on-wrong-item-kind.stderr  | 144 +++++++++++-------
 2 files changed, 96 insertions(+), 56 deletions(-)

diff --git a/src/test/ui/parser/default-on-wrong-item-kind.rs b/src/test/ui/parser/default-on-wrong-item-kind.rs
index 16bb7735c90c6..0951af1579bbc 100644
--- a/src/test/ui/parser/default-on-wrong-item-kind.rs
+++ b/src/test/ui/parser/default-on-wrong-item-kind.rs
@@ -22,6 +22,8 @@ mod free_items {
     default impl foo {}
     default!();
     default::foo::bar!();
+    default default!(); //~ ERROR item cannot be `default`
+    default default::foo::bar!(); //~ ERROR item cannot be `default`
     default macro foo {} //~ ERROR item cannot be `default`
     default macro_rules! foo {} //~ ERROR item cannot be `default`
 }
@@ -55,6 +57,8 @@ extern "C" {
     //~^ ERROR item kind not supported in `extern` block
     default!();
     default::foo::bar!();
+    default default!(); //~ ERROR item cannot be `default`
+    default default::foo::bar!(); //~ ERROR item cannot be `default`
     default macro foo {} //~ ERROR item cannot be `default`
     //~^ ERROR item kind not supported in `extern` block
     default macro_rules! foo {} //~ ERROR item cannot be `default`
@@ -90,6 +94,8 @@ impl S {
     //~^ ERROR item kind not supported in `trait` or `impl`
     default!();
     default::foo::bar!();
+    default default!();
+    default default::foo::bar!();
     default macro foo {}
     //~^ ERROR item kind not supported in `trait` or `impl`
     default macro_rules! foo {}
@@ -125,6 +131,8 @@ trait T {
     //~^ ERROR item kind not supported in `trait` or `impl`
     default!();
     default::foo::bar!();
+    default default!();
+    default default::foo::bar!();
     default macro foo {}
     //~^ ERROR item kind not supported in `trait` or `impl`
     default macro_rules! foo {}
diff --git a/src/test/ui/parser/default-on-wrong-item-kind.stderr b/src/test/ui/parser/default-on-wrong-item-kind.stderr
index 1812c45eba6a9..6c4c108a28f7c 100644
--- a/src/test/ui/parser/default-on-wrong-item-kind.stderr
+++ b/src/test/ui/parser/default-on-wrong-item-kind.stderr
@@ -105,7 +105,7 @@ LL |     default trait foo = Ord;
 error: item cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:25:5
    |
-LL |     default macro foo {}
+LL |     default default!();
    |     ^^^^^^^ `default` because of this
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
@@ -113,13 +113,29 @@ LL |     default macro foo {}
 error: item cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:26:5
    |
+LL |     default default::foo::bar!();
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:27:5
+   |
+LL |     default macro foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:28:5
+   |
 LL |     default macro_rules! foo {}
    |     ^^^^^^^ `default` because of this
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:31:5
+  --> $DIR/default-on-wrong-item-kind.rs:33:5
    |
 LL |     default extern crate foo;
    |     ^^^^^^^ `default` because of this
@@ -127,13 +143,13 @@ LL |     default extern crate foo;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item kind not supported in `extern` block
-  --> $DIR/default-on-wrong-item-kind.rs:31:5
+  --> $DIR/default-on-wrong-item-kind.rs:33:5
    |
 LL |     default extern crate foo;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:33:5
+  --> $DIR/default-on-wrong-item-kind.rs:35:5
    |
 LL |     default use foo;
    |     ^^^^^^^ `default` because of this
@@ -141,13 +157,13 @@ LL |     default use foo;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item kind not supported in `extern` block
-  --> $DIR/default-on-wrong-item-kind.rs:33:5
+  --> $DIR/default-on-wrong-item-kind.rs:35:5
    |
 LL |     default use foo;
    |     ^^^^^^^^^^^^^^^^
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:35:5
+  --> $DIR/default-on-wrong-item-kind.rs:37:5
    |
 LL |     default static foo: u8;
    |     ^^^^^^^ `default` because of this
@@ -155,7 +171,7 @@ LL |     default static foo: u8;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:36:5
+  --> $DIR/default-on-wrong-item-kind.rs:38:5
    |
 LL |     default const foo: u8;
    |     ^^^^^^^ `default` because of this
@@ -163,7 +179,7 @@ LL |     default const foo: u8;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: extern items cannot be `const`
-  --> $DIR/default-on-wrong-item-kind.rs:36:19
+  --> $DIR/default-on-wrong-item-kind.rs:38:19
    |
 LL |     default const foo: u8;
    |     --------------^^^
@@ -173,7 +189,7 @@ LL |     default const foo: u8;
    = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:38:5
+  --> $DIR/default-on-wrong-item-kind.rs:40:5
    |
 LL |     default fn foo();
    |     ^^^^^^^ `default` because of this
@@ -181,7 +197,7 @@ LL |     default fn foo();
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:39:5
+  --> $DIR/default-on-wrong-item-kind.rs:41:5
    |
 LL |     default mod foo {}
    |     ^^^^^^^ `default` because of this
@@ -189,13 +205,13 @@ LL |     default mod foo {}
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item kind not supported in `extern` block
-  --> $DIR/default-on-wrong-item-kind.rs:39:5
+  --> $DIR/default-on-wrong-item-kind.rs:41:5
    |
 LL |     default mod foo {}
    |     ^^^^^^^^^^^^^^^
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:41:5
+  --> $DIR/default-on-wrong-item-kind.rs:43:5
    |
 LL |     default extern "C" {}
    |     ^^^^^^^ `default` because of this
@@ -203,13 +219,13 @@ LL |     default extern "C" {}
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item kind not supported in `extern` block
-  --> $DIR/default-on-wrong-item-kind.rs:41:5
+  --> $DIR/default-on-wrong-item-kind.rs:43:5
    |
 LL |     default extern "C" {}
    |     ^^^^^^^^^^^^^^^^^^
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:43:5
+  --> $DIR/default-on-wrong-item-kind.rs:45:5
    |
 LL |     default type foo = u8;
    |     ^^^^^^^ `default` because of this
@@ -217,7 +233,7 @@ LL |     default type foo = u8;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:44:5
+  --> $DIR/default-on-wrong-item-kind.rs:46:5
    |
 LL |     default enum foo {}
    |     ^^^^^^^ `default` because of this
@@ -225,13 +241,13 @@ LL |     default enum foo {}
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item kind not supported in `extern` block
-  --> $DIR/default-on-wrong-item-kind.rs:44:5
+  --> $DIR/default-on-wrong-item-kind.rs:46:5
    |
 LL |     default enum foo {}
    |     ^^^^^^^^^^^^^^^^
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:46:5
+  --> $DIR/default-on-wrong-item-kind.rs:48:5
    |
 LL |     default struct foo {}
    |     ^^^^^^^ `default` because of this
@@ -239,13 +255,13 @@ LL |     default struct foo {}
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item kind not supported in `extern` block
-  --> $DIR/default-on-wrong-item-kind.rs:46:5
+  --> $DIR/default-on-wrong-item-kind.rs:48:5
    |
 LL |     default struct foo {}
    |     ^^^^^^^^^^^^^^^^^^
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:48:5
+  --> $DIR/default-on-wrong-item-kind.rs:50:5
    |
 LL |     default union foo {}
    |     ^^^^^^^ `default` because of this
@@ -253,13 +269,13 @@ LL |     default union foo {}
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item kind not supported in `extern` block
-  --> $DIR/default-on-wrong-item-kind.rs:48:5
+  --> $DIR/default-on-wrong-item-kind.rs:50:5
    |
 LL |     default union foo {}
    |     ^^^^^^^^^^^^^^^^^
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:50:5
+  --> $DIR/default-on-wrong-item-kind.rs:52:5
    |
 LL |     default trait foo {}
    |     ^^^^^^^ `default` because of this
@@ -267,13 +283,13 @@ LL |     default trait foo {}
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item kind not supported in `extern` block
-  --> $DIR/default-on-wrong-item-kind.rs:50:5
+  --> $DIR/default-on-wrong-item-kind.rs:52:5
    |
 LL |     default trait foo {}
    |     ^^^^^^^^^^^^^^^^^
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:52:5
+  --> $DIR/default-on-wrong-item-kind.rs:54:5
    |
 LL |     default trait foo = Ord;
    |     ^^^^^^^ `default` because of this
@@ -281,19 +297,35 @@ LL |     default trait foo = Ord;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item kind not supported in `extern` block
-  --> $DIR/default-on-wrong-item-kind.rs:52:5
+  --> $DIR/default-on-wrong-item-kind.rs:54:5
    |
 LL |     default trait foo = Ord;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `extern` block
-  --> $DIR/default-on-wrong-item-kind.rs:54:5
+  --> $DIR/default-on-wrong-item-kind.rs:56:5
    |
 LL |     default impl foo {}
    |     ^^^^^^^^^^^^^^^^
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:58:5
+  --> $DIR/default-on-wrong-item-kind.rs:60:5
+   |
+LL |     default default!();
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:61:5
+   |
+LL |     default default::foo::bar!();
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:62:5
    |
 LL |     default macro foo {}
    |     ^^^^^^^ `default` because of this
@@ -301,13 +333,13 @@ LL |     default macro foo {}
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item kind not supported in `extern` block
-  --> $DIR/default-on-wrong-item-kind.rs:58:5
+  --> $DIR/default-on-wrong-item-kind.rs:62:5
    |
 LL |     default macro foo {}
    |     ^^^^^^^^^^^^^^^^^
 
 error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:60:5
+  --> $DIR/default-on-wrong-item-kind.rs:64:5
    |
 LL |     default macro_rules! foo {}
    |     ^^^^^^^ `default` because of this
@@ -315,166 +347,166 @@ LL |     default macro_rules! foo {}
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: item kind not supported in `extern` block
-  --> $DIR/default-on-wrong-item-kind.rs:60:5
+  --> $DIR/default-on-wrong-item-kind.rs:64:5
    |
 LL |     default macro_rules! foo {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:66:5
+  --> $DIR/default-on-wrong-item-kind.rs:70:5
    |
 LL |     default extern crate foo;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:68:5
+  --> $DIR/default-on-wrong-item-kind.rs:72:5
    |
 LL |     default use foo;
    |     ^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/default-on-wrong-item-kind.rs:70:5
+  --> $DIR/default-on-wrong-item-kind.rs:74:5
    |
 LL |     default static foo: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:74:5
+  --> $DIR/default-on-wrong-item-kind.rs:78:5
    |
 LL |     default mod foo {}
    |     ^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:76:5
+  --> $DIR/default-on-wrong-item-kind.rs:80:5
    |
 LL |     default extern "C" {}
    |     ^^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:79:5
+  --> $DIR/default-on-wrong-item-kind.rs:83:5
    |
 LL |     default enum foo {}
    |     ^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:81:5
+  --> $DIR/default-on-wrong-item-kind.rs:85:5
    |
 LL |     default struct foo {}
    |     ^^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:83:5
+  --> $DIR/default-on-wrong-item-kind.rs:87:5
    |
 LL |     default union foo {}
    |     ^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:85:5
+  --> $DIR/default-on-wrong-item-kind.rs:89:5
    |
 LL |     default trait foo {}
    |     ^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:87:5
+  --> $DIR/default-on-wrong-item-kind.rs:91:5
    |
 LL |     default trait foo = Ord;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:89:5
+  --> $DIR/default-on-wrong-item-kind.rs:93:5
    |
 LL |     default impl foo {}
    |     ^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:93:5
+  --> $DIR/default-on-wrong-item-kind.rs:99:5
    |
 LL |     default macro foo {}
    |     ^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:95:5
+  --> $DIR/default-on-wrong-item-kind.rs:101:5
    |
 LL |     default macro_rules! foo {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:101:5
+  --> $DIR/default-on-wrong-item-kind.rs:107:5
    |
 LL |     default extern crate foo;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:103:5
+  --> $DIR/default-on-wrong-item-kind.rs:109:5
    |
 LL |     default use foo;
    |     ^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/default-on-wrong-item-kind.rs:105:5
+  --> $DIR/default-on-wrong-item-kind.rs:111:5
    |
 LL |     default static foo: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:109:5
+  --> $DIR/default-on-wrong-item-kind.rs:115:5
    |
 LL |     default mod foo {}
    |     ^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:111:5
+  --> $DIR/default-on-wrong-item-kind.rs:117:5
    |
 LL |     default extern "C" {}
    |     ^^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:114:5
+  --> $DIR/default-on-wrong-item-kind.rs:120:5
    |
 LL |     default enum foo {}
    |     ^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:116:5
+  --> $DIR/default-on-wrong-item-kind.rs:122:5
    |
 LL |     default struct foo {}
    |     ^^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:118:5
+  --> $DIR/default-on-wrong-item-kind.rs:124:5
    |
 LL |     default union foo {}
    |     ^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:120:5
+  --> $DIR/default-on-wrong-item-kind.rs:126:5
    |
 LL |     default trait foo {}
    |     ^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:122:5
+  --> $DIR/default-on-wrong-item-kind.rs:128:5
    |
 LL |     default trait foo = Ord;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:124:5
+  --> $DIR/default-on-wrong-item-kind.rs:130:5
    |
 LL |     default impl foo {}
    |     ^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:128:5
+  --> $DIR/default-on-wrong-item-kind.rs:136:5
    |
 LL |     default macro foo {}
    |     ^^^^^^^^^^^^^^^^^
 
 error: item kind not supported in `trait` or `impl`
-  --> $DIR/default-on-wrong-item-kind.rs:130:5
+  --> $DIR/default-on-wrong-item-kind.rs:138:5
    |
 LL |     default macro_rules! foo {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 69 previous errors
+error: aborting due to 73 previous errors
 

From d446c73e6ab94fe37f7d7b8f2abf633ed6344c8a Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sat, 22 Feb 2020 10:03:10 +0100
Subject: [PATCH 10/17] parser: refactor away at_end

---
 src/librustc_parse/parser/item.rs | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 4bb376799ec16..52619866c4ef6 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -161,7 +161,7 @@ impl<'a> Parser<'a> {
             (Ident::invalid(), ItemKind::Use(P(tree)))
         } else if self.check_fn_front_matter() {
             // FUNCTION ITEM
-            let (ident, sig, generics, body) = self.parse_fn(&mut false, attrs, req_name)?;
+            let (ident, sig, generics, body) = self.parse_fn(attrs, req_name)?;
             (ident, ItemKind::Fn(sig, generics, body))
         } else if self.eat_keyword(kw::Extern) {
             if self.eat_keyword(kw::Crate) {
@@ -1406,7 +1406,6 @@ impl<'a> Parser<'a> {
     /// Parse a function starting from the front matter (`const ...`) to the body `{ ... }` or `;`.
     fn parse_fn(
         &mut self,
-        at_end: &mut bool,
         attrs: &mut Vec<Attribute>,
         req_name: ReqName,
     ) -> PResult<'a, (Ident, FnSig, Generics, Option<P<Block>>)> {
@@ -1415,18 +1414,14 @@ impl<'a> Parser<'a> {
         let mut generics = self.parse_generics()?; // `<'a, T, ...>`
         let decl = self.parse_fn_decl(req_name, AllowPlus::Yes)?; // `(p: u8, ...)`
         generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
-        let body = self.parse_fn_body(at_end, attrs)?; // `;` or `{ ... }`.
+        let body = self.parse_fn_body(attrs)?; // `;` or `{ ... }`.
         Ok((ident, FnSig { header, decl }, generics, body))
     }
 
     /// Parse the "body" of a function.
     /// This can either be `;` when there's no body,
     /// or e.g. a block when the function is a provided one.
-    fn parse_fn_body(
-        &mut self,
-        at_end: &mut bool,
-        attrs: &mut Vec<Attribute>,
-    ) -> PResult<'a, Option<P<Block>>> {
+    fn parse_fn_body(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, Option<P<Block>>> {
         let (inner_attrs, body) = match self.token.kind {
             token::Semi => {
                 self.bump();
@@ -1446,7 +1441,6 @@ impl<'a> Parser<'a> {
             _ => return self.expected_semi_or_open_brace(),
         };
         attrs.extend(inner_attrs);
-        *at_end = true;
         Ok(body)
     }
 

From ab84914fe47aa2da615c9e759e686d1a45f8aae3 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sun, 23 Feb 2020 04:49:26 +0100
Subject: [PATCH 11/17] parser: tweak unmatched wording

---
 src/librustc_parse/parser/item.rs                  | 11 ++++++-----
 src/test/ui/parser/default-unmatched-assoc.rs      |  4 ++--
 src/test/ui/parser/default-unmatched-assoc.stderr  | 12 ++++++++----
 src/test/ui/parser/default-unmatched-extern.rs     |  2 +-
 src/test/ui/parser/default-unmatched-extern.stderr |  6 ++++--
 src/test/ui/parser/default-unmatched.rs            |  2 +-
 src/test/ui/parser/default-unmatched.stderr        |  6 ++++--
 src/test/ui/parser/default.rs                      |  2 +-
 src/test/ui/parser/default.stderr                  |  6 ++++--
 src/test/ui/parser/duplicate-visibility.rs         |  2 +-
 src/test/ui/parser/duplicate-visibility.stderr     |  4 ++--
 src/test/ui/parser/impl-parsing.rs                 |  2 +-
 src/test/ui/parser/impl-parsing.stderr             |  6 ++++--
 src/test/ui/parser/issue-41155.rs                  |  2 +-
 src/test/ui/parser/issue-41155.stderr              |  4 ++--
 src/test/ui/pub/pub-restricted-error-fn.rs         |  2 +-
 src/test/ui/pub/pub-restricted-error-fn.stderr     |  4 ++--
 17 files changed, 45 insertions(+), 32 deletions(-)

diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 52619866c4ef6..d2073a5473ae1 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -119,17 +119,18 @@ impl<'a> Parser<'a> {
         }
         let vs = pprust::vis_to_string(&vis);
         let vs = vs.trim_end();
-        self.struct_span_err(vis.span, &format!("unmatched visibility `{}`", vs))
-            .span_label(vis.span, "the unmatched visibility")
+        self.struct_span_err(vis.span, &format!("visibility `{}` not followed by an item", vs))
+            .span_label(vis.span, "the visibility")
             .help(&format!("you likely meant to define an item, e.g., `{} fn foo() {{}}`", vs))
             .emit();
     }
 
     /// Error in-case a `default` was parsed but no item followed.
     fn error_on_unmatched_defaultness(&self, def: Defaultness) {
-        if let Defaultness::Default(span) = def {
-            self.struct_span_err(span, "unmatched `default`")
-                .span_label(span, "the unmatched `default`")
+        if let Defaultness::Default(sp) = def {
+            self.struct_span_err(sp, "`default` not followed by an item")
+                .span_label(sp, "the `default` qualifier")
+                .note("only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`")
                 .emit();
         }
     }
diff --git a/src/test/ui/parser/default-unmatched-assoc.rs b/src/test/ui/parser/default-unmatched-assoc.rs
index bca6f5654dbfb..0c8ee0f7800d8 100644
--- a/src/test/ui/parser/default-unmatched-assoc.rs
+++ b/src/test/ui/parser/default-unmatched-assoc.rs
@@ -3,7 +3,7 @@ fn main() {}
 trait Foo {
     default!(); //~ ERROR cannot find macro `default` in this scope
     default do
-    //~^ ERROR unmatched `default`
+    //~^ ERROR `default` not followed by an item
     //~| ERROR non-item in item list
 }
 
@@ -11,6 +11,6 @@ struct S;
 impl S {
     default!(); //~ ERROR cannot find macro `default` in this scope
     default do
-    //~^ ERROR unmatched `default`
+    //~^ ERROR `default` not followed by an item
     //~| ERROR non-item in item list
 }
diff --git a/src/test/ui/parser/default-unmatched-assoc.stderr b/src/test/ui/parser/default-unmatched-assoc.stderr
index f3877f2ca6d51..22db46d63dffb 100644
--- a/src/test/ui/parser/default-unmatched-assoc.stderr
+++ b/src/test/ui/parser/default-unmatched-assoc.stderr
@@ -1,8 +1,10 @@
-error: unmatched `default`
+error: `default` not followed by an item
   --> $DIR/default-unmatched-assoc.rs:5:5
    |
 LL |     default do
-   |     ^^^^^^^ the unmatched `default`
+   |     ^^^^^^^ the `default` qualifier
+   |
+   = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
 
 error: non-item in item list
   --> $DIR/default-unmatched-assoc.rs:5:13
@@ -16,11 +18,13 @@ LL |     default do
 LL | }
    | - item list ends here
 
-error: unmatched `default`
+error: `default` not followed by an item
   --> $DIR/default-unmatched-assoc.rs:13:5
    |
 LL |     default do
-   |     ^^^^^^^ the unmatched `default`
+   |     ^^^^^^^ the `default` qualifier
+   |
+   = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
 
 error: non-item in item list
   --> $DIR/default-unmatched-assoc.rs:13:13
diff --git a/src/test/ui/parser/default-unmatched-extern.rs b/src/test/ui/parser/default-unmatched-extern.rs
index fbf87a892f0da..784df9bc77e57 100644
--- a/src/test/ui/parser/default-unmatched-extern.rs
+++ b/src/test/ui/parser/default-unmatched-extern.rs
@@ -3,6 +3,6 @@ fn main() {}
 extern "C" {
     default!(); //~ ERROR cannot find macro `default` in this scope
     default do
-    //~^ ERROR unmatched `default`
+    //~^ ERROR `default` not followed by an item
     //~| ERROR non-item in item list
 }
diff --git a/src/test/ui/parser/default-unmatched-extern.stderr b/src/test/ui/parser/default-unmatched-extern.stderr
index 00c8898e2ce82..ffbfbc73c18d4 100644
--- a/src/test/ui/parser/default-unmatched-extern.stderr
+++ b/src/test/ui/parser/default-unmatched-extern.stderr
@@ -1,8 +1,10 @@
-error: unmatched `default`
+error: `default` not followed by an item
   --> $DIR/default-unmatched-extern.rs:5:5
    |
 LL |     default do
-   |     ^^^^^^^ the unmatched `default`
+   |     ^^^^^^^ the `default` qualifier
+   |
+   = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
 
 error: non-item in item list
   --> $DIR/default-unmatched-extern.rs:5:13
diff --git a/src/test/ui/parser/default-unmatched.rs b/src/test/ui/parser/default-unmatched.rs
index 31696de0a5caa..796e184a0d815 100644
--- a/src/test/ui/parser/default-unmatched.rs
+++ b/src/test/ui/parser/default-unmatched.rs
@@ -1,6 +1,6 @@
 mod foo {
     default!(); // OK.
     default do
-    //~^ ERROR unmatched `default`
+    //~^ ERROR `default` not followed by an item
     //~| ERROR expected item, found reserved keyword `do`
 }
diff --git a/src/test/ui/parser/default-unmatched.stderr b/src/test/ui/parser/default-unmatched.stderr
index 6e4ef7b79fcc3..2601255776108 100644
--- a/src/test/ui/parser/default-unmatched.stderr
+++ b/src/test/ui/parser/default-unmatched.stderr
@@ -1,8 +1,10 @@
-error: unmatched `default`
+error: `default` not followed by an item
   --> $DIR/default-unmatched.rs:3:5
    |
 LL |     default do
-   |     ^^^^^^^ the unmatched `default`
+   |     ^^^^^^^ the `default` qualifier
+   |
+   = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
 
 error: expected item, found reserved keyword `do`
   --> $DIR/default-unmatched.rs:3:13
diff --git a/src/test/ui/parser/default.rs b/src/test/ui/parser/default.rs
index bd9ed0f452470..6cfa141478e4a 100644
--- a/src/test/ui/parser/default.rs
+++ b/src/test/ui/parser/default.rs
@@ -20,7 +20,7 @@ impl Foo for u16 {
 
 impl Foo for u32 { //~ ERROR not all trait items implemented, missing: `foo`
     default pub fn foo<T: Default>() -> T { T::default() }
-    //~^ ERROR unmatched `default`
+    //~^ ERROR `default` not followed by an item
     //~| ERROR non-item in item list
 }
 
diff --git a/src/test/ui/parser/default.stderr b/src/test/ui/parser/default.stderr
index fbf8101c36a73..96b14b42767a3 100644
--- a/src/test/ui/parser/default.stderr
+++ b/src/test/ui/parser/default.stderr
@@ -1,8 +1,10 @@
-error: unmatched `default`
+error: `default` not followed by an item
   --> $DIR/default.rs:22:5
    |
 LL |     default pub fn foo<T: Default>() -> T { T::default() }
-   |     ^^^^^^^ the unmatched `default`
+   |     ^^^^^^^ the `default` qualifier
+   |
+   = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
 
 error: non-item in item list
   --> $DIR/default.rs:22:13
diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs
index 949b6e1dc24f4..edea2d1e5e2f3 100644
--- a/src/test/ui/parser/duplicate-visibility.rs
+++ b/src/test/ui/parser/duplicate-visibility.rs
@@ -2,6 +2,6 @@ fn main() {}
 
 extern {
     pub pub fn foo();
-    //~^ ERROR unmatched visibility `pub`
+    //~^ ERROR visibility `pub` not followed by an item
     //~| ERROR non-item in item list
 }
diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr
index 2c79a343d0578..d8e38046a6c15 100644
--- a/src/test/ui/parser/duplicate-visibility.stderr
+++ b/src/test/ui/parser/duplicate-visibility.stderr
@@ -1,8 +1,8 @@
-error: unmatched visibility `pub`
+error: visibility `pub` not followed by an item
   --> $DIR/duplicate-visibility.rs:4:5
    |
 LL |     pub pub fn foo();
-   |     ^^^ the unmatched visibility
+   |     ^^^ the visibility
    |
    = help: you likely meant to define an item, e.g., `pub fn foo() {}`
 
diff --git a/src/test/ui/parser/impl-parsing.rs b/src/test/ui/parser/impl-parsing.rs
index 662ed28f2f742..c2ed7531a9432 100644
--- a/src/test/ui/parser/impl-parsing.rs
+++ b/src/test/ui/parser/impl-parsing.rs
@@ -7,4 +7,4 @@ impl ?Sized for Type {} //~ ERROR expected a trait, found type
 impl ?Sized for .. {} //~ ERROR expected a trait, found type
 
 default unsafe FAIL //~ ERROR expected item, found keyword `unsafe`
-//~^ ERROR unmatched `default`
+//~^ ERROR `default` not followed by an item
diff --git a/src/test/ui/parser/impl-parsing.stderr b/src/test/ui/parser/impl-parsing.stderr
index a5fc3e46896eb..ce673765aba1d 100644
--- a/src/test/ui/parser/impl-parsing.stderr
+++ b/src/test/ui/parser/impl-parsing.stderr
@@ -22,11 +22,13 @@ error: expected a trait, found type
 LL | impl ?Sized for .. {}
    |      ^^^^^^
 
-error: unmatched `default`
+error: `default` not followed by an item
   --> $DIR/impl-parsing.rs:9:1
    |
 LL | default unsafe FAIL
-   | ^^^^^^^ the unmatched `default`
+   | ^^^^^^^ the `default` qualifier
+   |
+   = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
 
 error: expected item, found keyword `unsafe`
   --> $DIR/impl-parsing.rs:9:9
diff --git a/src/test/ui/parser/issue-41155.rs b/src/test/ui/parser/issue-41155.rs
index bed4805e7cea9..5bfbe0c5e6890 100644
--- a/src/test/ui/parser/issue-41155.rs
+++ b/src/test/ui/parser/issue-41155.rs
@@ -1,7 +1,7 @@
 struct S;
 
 impl S {
-    pub //~ ERROR unmatched visibility `pub`
+    pub //~ ERROR visibility `pub` not followed by an item
 } //~ ERROR non-item in item list
 
 fn main() {}
diff --git a/src/test/ui/parser/issue-41155.stderr b/src/test/ui/parser/issue-41155.stderr
index a9c1035f4d85d..09bbee51800d9 100644
--- a/src/test/ui/parser/issue-41155.stderr
+++ b/src/test/ui/parser/issue-41155.stderr
@@ -1,8 +1,8 @@
-error: unmatched visibility `pub`
+error: visibility `pub` not followed by an item
   --> $DIR/issue-41155.rs:4:5
    |
 LL |     pub
-   |     ^^^ the unmatched visibility
+   |     ^^^ the visibility
    |
    = help: you likely meant to define an item, e.g., `pub fn foo() {}`
 
diff --git a/src/test/ui/pub/pub-restricted-error-fn.rs b/src/test/ui/pub/pub-restricted-error-fn.rs
index 3f8904fbe79d8..73806fdfe72b9 100644
--- a/src/test/ui/pub/pub-restricted-error-fn.rs
+++ b/src/test/ui/pub/pub-restricted-error-fn.rs
@@ -1,2 +1,2 @@
-pub(crate) () fn foo() {} //~ unmatched visibility
+pub(crate) () fn foo() {} //~ ERROR visibility `pub(crate)` not followed by an item
 //~^ ERROR expected item, found `(`
diff --git a/src/test/ui/pub/pub-restricted-error-fn.stderr b/src/test/ui/pub/pub-restricted-error-fn.stderr
index c0168b02da607..42d03941e411f 100644
--- a/src/test/ui/pub/pub-restricted-error-fn.stderr
+++ b/src/test/ui/pub/pub-restricted-error-fn.stderr
@@ -1,8 +1,8 @@
-error: unmatched visibility `pub(crate)`
+error: visibility `pub(crate)` not followed by an item
   --> $DIR/pub-restricted-error-fn.rs:1:1
    |
 LL | pub(crate) () fn foo() {}
-   | ^^^^^^^^^^ the unmatched visibility
+   | ^^^^^^^^^^ the visibility
    |
    = help: you likely meant to define an item, e.g., `pub(crate) fn foo() {}`
 

From b01c1e2092b0d3c4e86aedf1e0875898fbde21e3 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sun, 23 Feb 2020 06:04:37 +0100
Subject: [PATCH 12/17] parser: tweak item kind wording

---
 src/librustc_expand/expand.rs                 |  4 +-
 src/librustc_hir/hir.rs                       | 10 +--
 src/librustc_parse/parser/item.rs             | 20 +++---
 src/librustc_passes/dead.rs                   |  8 +--
 src/librustc_passes/stability.rs              |  2 +-
 src/libsyntax/ast.rs                          | 23 ++++--
 .../ui/parser/default-on-wrong-item-kind.rs   | 72 +++++++++----------
 .../parser/default-on-wrong-item-kind.stderr  | 72 +++++++++----------
 .../missing-close-brace-in-impl-trait.rs      |  4 +-
 .../missing-close-brace-in-impl-trait.stderr  |  4 +-
 .../missing-close-brace-in-trait.rs           |  4 +-
 .../missing-close-brace-in-trait.stderr       |  4 +-
 12 files changed, 115 insertions(+), 112 deletions(-)

diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index e5f957a63de55..fce2a1d7a7ee2 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -378,8 +378,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 self.cx.span_err(
                     span,
                     &format!(
-                        "expected crate top-level item to be a module after macro expansion, found a {}",
-                        kind.descriptive_variant()
+                        "expected crate top-level item to be a module after macro expansion, found {} {}",
+                        kind.article(), kind.descr()
                     ),
                 );
             }
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index 8496a6ed23b8c..6d2f5ba6baf14 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -2500,16 +2500,16 @@ pub enum ItemKind<'hir> {
 }
 
 impl ItemKind<'_> {
-    pub fn descriptive_variant(&self) -> &str {
+    pub fn descr(&self) -> &str {
         match *self {
             ItemKind::ExternCrate(..) => "extern crate",
-            ItemKind::Use(..) => "use",
+            ItemKind::Use(..) => "`use` import",
             ItemKind::Static(..) => "static item",
             ItemKind::Const(..) => "constant item",
             ItemKind::Fn(..) => "function",
             ItemKind::Mod(..) => "module",
-            ItemKind::ForeignMod(..) => "foreign module",
-            ItemKind::GlobalAsm(..) => "global asm",
+            ItemKind::ForeignMod(..) => "extern block",
+            ItemKind::GlobalAsm(..) => "global asm item",
             ItemKind::TyAlias(..) => "type alias",
             ItemKind::OpaqueTy(..) => "opaque type",
             ItemKind::Enum(..) => "enum",
@@ -2517,7 +2517,7 @@ impl ItemKind<'_> {
             ItemKind::Union(..) => "union",
             ItemKind::Trait(..) => "trait",
             ItemKind::TraitAlias(..) => "trait alias",
-            ItemKind::Impl { .. } => "impl",
+            ItemKind::Impl { .. } => "implementation",
         }
     }
 
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index d2073a5473ae1..0e0017d4ee566 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -661,12 +661,7 @@ impl<'a> Parser<'a> {
                     self.struct_span_err(span, "associated `static` items are not allowed").emit();
                     AssocItemKind::Const(a, b)
                 }
-                _ => {
-                    let span = self.sess.source_map().def_span(span);
-                    self.struct_span_err(span, "item kind not supported in `trait` or `impl`")
-                        .emit();
-                    return None;
-                }
+                _ => return self.error_bad_item_kind(span, &kind, "`trait` or `impl`"),
             };
             Some(P(Item { attrs, id, span, vis, ident, defaultness, kind, tokens }))
         }))
@@ -858,16 +853,19 @@ impl<'a> Parser<'a> {
                     self.error_on_foreign_const(span, ident);
                     ForeignItemKind::Static(a, Mutability::Not, b)
                 }
-                _ => {
-                    let span = self.sess.source_map().def_span(span);
-                    self.struct_span_err(span, "item kind not supported in `extern` block").emit();
-                    return None;
-                }
+                _ => return self.error_bad_item_kind(span, &kind, "`extern` block"),
             };
             Some(P(Item { attrs, id, span, vis, ident, defaultness, kind, tokens }))
         }))
     }
 
+    fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &str) -> Option<T> {
+        let span = self.sess.source_map().def_span(span);
+        let msg = format!("{} not supported in {}", kind.descr(), ctx);
+        self.struct_span_err(span, &msg).emit();
+        return None;
+    }
+
     fn error_on_foreign_const(&self, span: Span, ident: Ident) {
         self.struct_span_err(ident.span, "extern items cannot be `const`")
             .span_suggestion(
diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs
index 25b8b8fcd444b..e0eef1db0f089 100644
--- a/src/librustc_passes/dead.rs
+++ b/src/librustc_passes/dead.rs
@@ -601,13 +601,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
                 hir::ItemKind::Struct(..) => "constructed", // Issue #52325
                 _ => "used",
             };
-            self.warn_dead_code(
-                item.hir_id,
-                span,
-                item.ident.name,
-                item.kind.descriptive_variant(),
-                participle,
-            );
+            self.warn_dead_code(item.hir_id, span, item.ident.name, item.kind.descr(), participle);
         } else {
             // Only continue if we didn't warn
             intravisit::walk_item(self, item);
diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs
index 0c7f64fefd0d2..99fbac4568e4f 100644
--- a/src/librustc_passes/stability.rs
+++ b/src/librustc_passes/stability.rs
@@ -362,7 +362,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> {
             // optional. They inherit stability from their parents when unannotated.
             hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..) => {}
 
-            _ => self.check_missing_stability(i.hir_id, i.span, i.kind.descriptive_variant()),
+            _ => self.check_missing_stability(i.hir_id, i.span, i.kind.descr()),
         }
 
         intravisit::walk_item(self, i)
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index dd3319fcba155..f8a27cf714246 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -2574,23 +2574,34 @@ pub enum ItemKind {
 }
 
 impl ItemKind {
-    pub fn descriptive_variant(&self) -> &str {
-        match *self {
+    pub fn article(&self) -> &str {
+        use ItemKind::*;
+        match self {
+            Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
+            | Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..) => "a",
+            ExternCrate(..) | ForeignMod(..) | Mac(..) | Enum(..) | Impl { .. } => "an",
+        }
+    }
+
+    pub fn descr(&self) -> &str {
+        match self {
             ItemKind::ExternCrate(..) => "extern crate",
-            ItemKind::Use(..) => "use",
+            ItemKind::Use(..) => "`use` import",
             ItemKind::Static(..) => "static item",
             ItemKind::Const(..) => "constant item",
             ItemKind::Fn(..) => "function",
             ItemKind::Mod(..) => "module",
-            ItemKind::ForeignMod(..) => "foreign module",
-            ItemKind::GlobalAsm(..) => "global asm",
+            ItemKind::ForeignMod(..) => "extern block",
+            ItemKind::GlobalAsm(..) => "global asm item",
             ItemKind::TyAlias(..) => "type alias",
             ItemKind::Enum(..) => "enum",
             ItemKind::Struct(..) => "struct",
             ItemKind::Union(..) => "union",
             ItemKind::Trait(..) => "trait",
             ItemKind::TraitAlias(..) => "trait alias",
-            ItemKind::Mac(..) | ItemKind::MacroDef(..) | ItemKind::Impl { .. } => "item",
+            ItemKind::Mac(..) => "item macro invocation",
+            ItemKind::MacroDef(..) => "macro definition",
+            ItemKind::Impl { .. } => "implementation",
         }
     }
 
diff --git a/src/test/ui/parser/default-on-wrong-item-kind.rs b/src/test/ui/parser/default-on-wrong-item-kind.rs
index 0951af1579bbc..47b9e34305f21 100644
--- a/src/test/ui/parser/default-on-wrong-item-kind.rs
+++ b/src/test/ui/parser/default-on-wrong-item-kind.rs
@@ -31,110 +31,110 @@ mod free_items {
 #[cfg(FALSE)]
 extern "C" {
     default extern crate foo; //~ ERROR item cannot be `default`
-    //~^ ERROR item kind not supported in `extern` block
+    //~^ ERROR extern crate not supported in `extern` block
     default use foo; //~ ERROR item cannot be `default`
-    //~^ ERROR item kind not supported in `extern` block
+    //~^ ERROR `use` import not supported in `extern` block
     default static foo: u8; //~ ERROR item cannot be `default`
     default const foo: u8; //~ ERROR item cannot be `default`
     //~^ ERROR extern items cannot be `const`
     default fn foo(); //~ ERROR item cannot be `default`
     default mod foo {} //~ ERROR item cannot be `default`
-    //~^ ERROR item kind not supported in `extern` block
+    //~^ ERROR module not supported in `extern` block
     default extern "C" {} //~ ERROR item cannot be `default`
-    //~^ ERROR item kind not supported in `extern` block
+    //~^ ERROR extern block not supported in `extern` block
     default type foo = u8; //~ ERROR item cannot be `default`
     default enum foo {} //~ ERROR item cannot be `default`
-    //~^ ERROR item kind not supported in `extern` block
+    //~^ ERROR enum not supported in `extern` block
     default struct foo {} //~ ERROR item cannot be `default`
-    //~^ ERROR item kind not supported in `extern` block
+    //~^ ERROR struct not supported in `extern` block
     default union foo {} //~ ERROR item cannot be `default`
-    //~^ ERROR item kind not supported in `extern` block
+    //~^ ERROR union not supported in `extern` block
     default trait foo {} //~ ERROR item cannot be `default`
-    //~^ ERROR item kind not supported in `extern` block
+    //~^ ERROR trait not supported in `extern` block
     default trait foo = Ord; //~ ERROR item cannot be `default`
-    //~^ ERROR item kind not supported in `extern` block
+    //~^ ERROR trait alias not supported in `extern` block
     default impl foo {}
-    //~^ ERROR item kind not supported in `extern` block
+    //~^ ERROR implementation not supported in `extern` block
     default!();
     default::foo::bar!();
     default default!(); //~ ERROR item cannot be `default`
     default default::foo::bar!(); //~ ERROR item cannot be `default`
     default macro foo {} //~ ERROR item cannot be `default`
-    //~^ ERROR item kind not supported in `extern` block
+    //~^ ERROR macro definition not supported in `extern` block
     default macro_rules! foo {} //~ ERROR item cannot be `default`
-    //~^ ERROR item kind not supported in `extern` block
+    //~^ ERROR macro definition not supported in `extern` block
 }
 
 #[cfg(FALSE)]
 impl S {
     default extern crate foo;
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR extern crate not supported in `trait` or `impl`
     default use foo;
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR `use` import not supported in `trait` or `impl`
     default static foo: u8;
     //~^ ERROR associated `static` items are not allowed
     default const foo: u8;
     default fn foo();
     default mod foo {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR module not supported in `trait` or `impl`
     default extern "C" {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR extern block not supported in `trait` or `impl`
     default type foo = u8;
     default enum foo {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR enum not supported in `trait` or `impl`
     default struct foo {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR struct not supported in `trait` or `impl`
     default union foo {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR union not supported in `trait` or `impl`
     default trait foo {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR trait not supported in `trait` or `impl`
     default trait foo = Ord;
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR trait alias not supported in `trait` or `impl`
     default impl foo {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR implementation not supported in `trait` or `impl`
     default!();
     default::foo::bar!();
     default default!();
     default default::foo::bar!();
     default macro foo {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR macro definition not supported in `trait` or `impl`
     default macro_rules! foo {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR macro definition not supported in `trait` or `impl`
 }
 
 #[cfg(FALSE)]
 trait T {
     default extern crate foo;
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR extern crate not supported in `trait` or `impl`
     default use foo;
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR `use` import not supported in `trait` or `impl`
     default static foo: u8;
     //~^ ERROR associated `static` items are not allowed
     default const foo: u8;
     default fn foo();
     default mod foo {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR module not supported in `trait` or `impl`
     default extern "C" {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR extern block not supported in `trait` or `impl`
     default type foo = u8;
     default enum foo {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR enum not supported in `trait` or `impl`
     default struct foo {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR struct not supported in `trait` or `impl`
     default union foo {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR union not supported in `trait` or `impl`
     default trait foo {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR trait not supported in `trait` or `impl`
     default trait foo = Ord;
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR trait alias not supported in `trait` or `impl`
     default impl foo {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR implementation not supported in `trait` or `impl`
     default!();
     default::foo::bar!();
     default default!();
     default default::foo::bar!();
     default macro foo {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR macro definition not supported in `trait` or `impl`
     default macro_rules! foo {}
-    //~^ ERROR item kind not supported in `trait` or `impl`
+    //~^ ERROR macro definition not supported in `trait` or `impl`
 }
diff --git a/src/test/ui/parser/default-on-wrong-item-kind.stderr b/src/test/ui/parser/default-on-wrong-item-kind.stderr
index 6c4c108a28f7c..ec569b43d700d 100644
--- a/src/test/ui/parser/default-on-wrong-item-kind.stderr
+++ b/src/test/ui/parser/default-on-wrong-item-kind.stderr
@@ -142,7 +142,7 @@ LL |     default extern crate foo;
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item kind not supported in `extern` block
+error: extern crate not supported in `extern` block
   --> $DIR/default-on-wrong-item-kind.rs:33:5
    |
 LL |     default extern crate foo;
@@ -156,7 +156,7 @@ LL |     default use foo;
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item kind not supported in `extern` block
+error: `use` import not supported in `extern` block
   --> $DIR/default-on-wrong-item-kind.rs:35:5
    |
 LL |     default use foo;
@@ -204,7 +204,7 @@ LL |     default mod foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item kind not supported in `extern` block
+error: module not supported in `extern` block
   --> $DIR/default-on-wrong-item-kind.rs:41:5
    |
 LL |     default mod foo {}
@@ -218,7 +218,7 @@ LL |     default extern "C" {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item kind not supported in `extern` block
+error: extern block not supported in `extern` block
   --> $DIR/default-on-wrong-item-kind.rs:43:5
    |
 LL |     default extern "C" {}
@@ -240,7 +240,7 @@ LL |     default enum foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item kind not supported in `extern` block
+error: enum not supported in `extern` block
   --> $DIR/default-on-wrong-item-kind.rs:46:5
    |
 LL |     default enum foo {}
@@ -254,7 +254,7 @@ LL |     default struct foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item kind not supported in `extern` block
+error: struct not supported in `extern` block
   --> $DIR/default-on-wrong-item-kind.rs:48:5
    |
 LL |     default struct foo {}
@@ -268,7 +268,7 @@ LL |     default union foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item kind not supported in `extern` block
+error: union not supported in `extern` block
   --> $DIR/default-on-wrong-item-kind.rs:50:5
    |
 LL |     default union foo {}
@@ -282,7 +282,7 @@ LL |     default trait foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item kind not supported in `extern` block
+error: trait not supported in `extern` block
   --> $DIR/default-on-wrong-item-kind.rs:52:5
    |
 LL |     default trait foo {}
@@ -296,13 +296,13 @@ LL |     default trait foo = Ord;
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item kind not supported in `extern` block
+error: trait alias not supported in `extern` block
   --> $DIR/default-on-wrong-item-kind.rs:54:5
    |
 LL |     default trait foo = Ord;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `extern` block
+error: implementation not supported in `extern` block
   --> $DIR/default-on-wrong-item-kind.rs:56:5
    |
 LL |     default impl foo {}
@@ -332,7 +332,7 @@ LL |     default macro foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item kind not supported in `extern` block
+error: macro definition not supported in `extern` block
   --> $DIR/default-on-wrong-item-kind.rs:62:5
    |
 LL |     default macro foo {}
@@ -346,19 +346,19 @@ LL |     default macro_rules! foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item kind not supported in `extern` block
+error: macro definition not supported in `extern` block
   --> $DIR/default-on-wrong-item-kind.rs:64:5
    |
 LL |     default macro_rules! foo {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: extern crate not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:70:5
    |
 LL |     default extern crate foo;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: `use` import not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:72:5
    |
 LL |     default use foo;
@@ -370,73 +370,73 @@ error: associated `static` items are not allowed
 LL |     default static foo: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: module not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:78:5
    |
 LL |     default mod foo {}
    |     ^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: extern block not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:80:5
    |
 LL |     default extern "C" {}
    |     ^^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: enum not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:83:5
    |
 LL |     default enum foo {}
    |     ^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: struct not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:85:5
    |
 LL |     default struct foo {}
    |     ^^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: union not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:87:5
    |
 LL |     default union foo {}
    |     ^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: trait not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:89:5
    |
 LL |     default trait foo {}
    |     ^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: trait alias not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:91:5
    |
 LL |     default trait foo = Ord;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: implementation not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:93:5
    |
 LL |     default impl foo {}
    |     ^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: macro definition not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:99:5
    |
 LL |     default macro foo {}
    |     ^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: macro definition not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:101:5
    |
 LL |     default macro_rules! foo {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: extern crate not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:107:5
    |
 LL |     default extern crate foo;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: `use` import not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:109:5
    |
 LL |     default use foo;
@@ -448,61 +448,61 @@ error: associated `static` items are not allowed
 LL |     default static foo: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: module not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:115:5
    |
 LL |     default mod foo {}
    |     ^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: extern block not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:117:5
    |
 LL |     default extern "C" {}
    |     ^^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: enum not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:120:5
    |
 LL |     default enum foo {}
    |     ^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: struct not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:122:5
    |
 LL |     default struct foo {}
    |     ^^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: union not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:124:5
    |
 LL |     default union foo {}
    |     ^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: trait not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:126:5
    |
 LL |     default trait foo {}
    |     ^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: trait alias not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:128:5
    |
 LL |     default trait foo = Ord;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: implementation not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:130:5
    |
 LL |     default impl foo {}
    |     ^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: macro definition not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:136:5
    |
 LL |     default macro foo {}
    |     ^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: macro definition not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:138:5
    |
 LL |     default macro_rules! foo {}
diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs
index d85255328f7f4..b26e5134db6cc 100644
--- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs
+++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs
@@ -4,10 +4,10 @@ impl T for () { //~ ERROR cannot find trait `T` in this scope
 
 fn foo(&self) {}
 
-trait T { //~ ERROR item kind not supported in `trait` or `impl`
+trait T { //~ ERROR trait not supported in `trait` or `impl`
     fn foo(&self);
 }
 
-pub(crate) struct Bar<T>(); //~ ERROR item kind not supported in `trait` or `impl`
+pub(crate) struct Bar<T>(); //~ ERROR struct not supported in `trait` or `impl`
 
 //~ ERROR this file contains an unclosed delimiter
diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
index 2b72c06c9c7d3..b1bd1a784be34 100644
--- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
+++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
@@ -7,13 +7,13 @@ LL | impl T for () {
 LL |
    |                                                    ^
 
-error: item kind not supported in `trait` or `impl`
+error: trait not supported in `trait` or `impl`
   --> $DIR/missing-close-brace-in-impl-trait.rs:7:1
    |
 LL | trait T {
    | ^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: struct not supported in `trait` or `impl`
   --> $DIR/missing-close-brace-in-impl-trait.rs:11:1
    |
 LL | pub(crate) struct Bar<T>();
diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs
index b2515b17ff338..d52add273981d 100644
--- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs
+++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs
@@ -2,10 +2,10 @@ trait T {
     fn foo(&self);
 
 pub(crate) struct Bar<T>();
-//~^ ERROR item kind not supported in `trait` or `impl`
+//~^ ERROR struct not supported in `trait` or `impl`
 
 impl T for Bar<usize> {
-//~^ ERROR item kind not supported in `trait` or `impl`
+//~^ ERROR implementation not supported in `trait` or `impl`
 fn foo(&self) {}
 }
 
diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
index 89bf29165109f..49c685f254956 100644
--- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
+++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
@@ -7,13 +7,13 @@ LL | trait T {
 LL | fn main() {}
    |                                                                 ^
 
-error: item kind not supported in `trait` or `impl`
+error: struct not supported in `trait` or `impl`
   --> $DIR/missing-close-brace-in-trait.rs:4:1
    |
 LL | pub(crate) struct Bar<T>();
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: item kind not supported in `trait` or `impl`
+error: implementation not supported in `trait` or `impl`
   --> $DIR/missing-close-brace-in-trait.rs:7:1
    |
 LL | impl T for Bar<usize> {

From 842027f35bd0c957fff862ef864f4fc57988ed7e Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sun, 23 Feb 2020 06:53:59 +0100
Subject: [PATCH 13/17] parse: `NtItem` -> `parse_item_common`.

---
 src/librustc_parse/parser/item.rs             | 17 +++++-----
 ...37-macros-cannot-interpolate-impl-items.rs | 34 +++++++++++++++++++
 2 files changed, 43 insertions(+), 8 deletions(-)
 create mode 100644 src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items.rs

diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 0e0017d4ee566..6fa9e615b459f 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -31,16 +31,10 @@ impl<'a> Parser<'a> {
 
     pub(super) fn parse_item_(
         &mut self,
-        mut attrs: Vec<Attribute>,
+        attrs: Vec<Attribute>,
         macros_allowed: bool,
         attributes_allowed: bool,
     ) -> PResult<'a, Option<P<Item>>> {
-        maybe_whole!(self, NtItem, |item| {
-            let mut item = item;
-            mem::swap(&mut item.attrs, &mut attrs);
-            item.attrs.extend(attrs);
-            Some(item)
-        });
         let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed, |_| true)?;
         if let Some(ref item) = item {
             self.error_on_illegal_default(item.defaultness);
@@ -50,11 +44,18 @@ impl<'a> Parser<'a> {
 
     fn parse_item_common(
         &mut self,
-        attrs: Vec<Attribute>,
+        mut attrs: Vec<Attribute>,
         mac_allowed: bool,
         attrs_allowed: bool,
         req_name: ReqName,
     ) -> PResult<'a, Option<Item>> {
+        maybe_whole!(self, NtItem, |item| {
+            let mut item = item;
+            mem::swap(&mut item.attrs, &mut attrs);
+            item.attrs.extend(attrs);
+            Some(item.into_inner())
+        });
+
         let mut unclosed_delims = vec![];
         let (mut item, tokens) = self.collect_tokens(|this| {
             let item = this.parse_item_common_(attrs, mac_allowed, attrs_allowed, req_name);
diff --git a/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items.rs b/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items.rs
new file mode 100644
index 0000000000000..8592f8a728715
--- /dev/null
+++ b/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items.rs
@@ -0,0 +1,34 @@
+// check-pass
+
+fn main() {}
+
+macro_rules! mac_impl {
+    ($i:item) => {
+        struct S;
+        impl S { $i }
+    }
+}
+
+mac_impl! {
+    fn foo() {}
+}
+
+macro_rules! mac_trait {
+    ($i:item) => {
+        trait T { $i }
+    }
+}
+
+mac_trait! {
+    fn foo() {}
+}
+
+macro_rules! mac_extern {
+    ($i:item) => {
+        extern "C" { $i }
+    }
+}
+
+mac_extern! {
+    fn foo();
+}

From 62930d31514d6d9b4b0df3755d643f06f0d4212a Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sun, 23 Feb 2020 10:24:30 +0100
Subject: [PATCH 14/17] parse/ast: move `Defaultness` into variants.

---
 src/librustc_ast_lowering/item.rs             |  48 +--
 src/librustc_ast_lowering/lib.rs              |   4 +-
 src/librustc_ast_passes/ast_validation.rs     |  27 +-
 src/librustc_ast_passes/feature_gate.rs       |   8 +-
 src/librustc_ast_pretty/pprust.rs             |  31 +-
 .../deriving/generic/mod.rs                   |   6 +-
 .../global_allocator.rs                       |   3 +-
 src/librustc_builtin_macros/global_asm.rs     |   1 -
 src/librustc_builtin_macros/test.rs           |   5 +-
 src/librustc_builtin_macros/test_harness.rs   |   8 +-
 src/librustc_expand/build.rs                  |   4 +-
 src/librustc_expand/expand.rs                 |   1 -
 src/librustc_expand/placeholders.rs           |   5 -
 src/librustc_interface/util.rs                |   4 +-
 src/librustc_lint/builtin.rs                  |   2 +-
 .../rmeta/decoder/cstore_impl.rs              |   1 -
 src/librustc_parse/parser/item.rs             |  64 ++--
 src/librustc_resolve/build_reduced_graph.rs   |   4 +-
 src/librustc_resolve/def_collector.rs         |   4 +-
 src/librustc_resolve/late.rs                  |  22 +-
 src/librustc_save_analysis/dump_visitor.rs    |  25 +-
 src/librustc_save_analysis/lib.rs             |   9 +-
 src/librustc_save_analysis/sig.rs             |   8 +-
 src/libsyntax/ast.rs                          |  28 +-
 src/libsyntax/mut_visit.rs                    |  19 +-
 src/libsyntax/visit.rs                        |  16 +-
 src/test/ui/ast-json/ast-json-output.stdout   |   2 +-
 .../ui/parser/assoc-static-semantic-fail.rs   |   8 +-
 .../parser/assoc-static-semantic-fail.stderr  |  94 +++--
 .../ui/parser/assoc-static-syntactic-fail.rs  |   6 +
 .../parser/assoc-static-syntactic-fail.stderr |  68 +++-
 .../ui/parser/default-on-wrong-item-kind.rs   | 124 +++----
 .../parser/default-on-wrong-item-kind.stderr  | 330 ++++++++++++++----
 33 files changed, 630 insertions(+), 359 deletions(-)

diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index 3d6926df58d52..b5e4fe90d0dce 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -173,7 +173,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 }
                 ids
             }
-            ItemKind::Const(ref ty, ..) => {
+            ItemKind::Const(_, ref ty, ..) => {
                 let mut ids = smallvec![i.id];
                 if self.sess.features_untracked().impl_trait_in_bindings {
                     let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids };
@@ -264,11 +264,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
                 hir::ItemKind::Static(ty, m, body_id)
             }
-            ItemKind::Const(ref t, ref e) => {
+            ItemKind::Const(_, ref t, ref e) => {
                 let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
                 hir::ItemKind::Const(ty, body_id)
             }
-            ItemKind::Fn(FnSig { ref decl, header }, ref generics, ref body) => {
+            ItemKind::Fn(_, FnSig { ref decl, header }, ref generics, ref body) => {
                 let fn_def_id = self.resolver.definitions().local_def_id(id);
                 self.with_new_scopes(|this| {
                     this.current_item = Some(ident.span);
@@ -297,16 +297,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
             ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)),
             ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
-            ItemKind::TyAlias(ref generics, _, Some(ref ty)) => match ty.kind.opaque_top_hack() {
+            ItemKind::TyAlias(_, ref gen, _, Some(ref ty)) => match ty.kind.opaque_top_hack() {
                 None => {
                     let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
-                    let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
+                    let generics = self.lower_generics(gen, ImplTraitContext::disallowed());
                     hir::ItemKind::TyAlias(ty, generics)
                 }
                 Some(bounds) => {
                     let ctx = || ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc);
                     let ty = hir::OpaqueTy {
-                        generics: self.lower_generics(generics, ctx()),
+                        generics: self.lower_generics(gen, ctx()),
                         bounds: self.lower_param_bounds(bounds, ctx()),
                         impl_trait_fn: None,
                         origin: hir::OpaqueTyOrigin::TypeAlias,
@@ -314,7 +314,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     hir::ItemKind::OpaqueTy(ty)
                 }
             },
-            ItemKind::TyAlias(ref generics, _, None) => {
+            ItemKind::TyAlias(_, ref generics, _, None) => {
                 let ty = self.arena.alloc(self.ty(span, hir::TyKind::Err));
                 let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
                 hir::ItemKind::TyAlias(ty, generics)
@@ -654,7 +654,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ident: i.ident,
             attrs: self.lower_attrs(&i.attrs),
             kind: match i.kind {
-                ForeignItemKind::Fn(ref sig, ref generics, _) => {
+                ForeignItemKind::Fn(_, ref sig, ref generics, _) => {
                     let fdec = &sig.decl;
                     let (generics, (fn_dec, fn_args)) = self.add_in_band_defs(
                         generics,
@@ -675,7 +675,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     let ty = self.lower_ty(t, ImplTraitContext::disallowed());
                     hir::ForeignItemKind::Static(ty, m)
                 }
-                ForeignItemKind::Const(ref t, _) => {
+                ForeignItemKind::Const(_, ref t, _) => {
                     // For recovery purposes.
                     let ty = self.lower_ty(t, ImplTraitContext::disallowed());
                     hir::ForeignItemKind::Static(ty, Mutability::Not)
@@ -758,24 +758,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         let (generics, kind) = match i.kind {
             AssocItemKind::Static(ref ty, _, ref default) // Let's pretend this is a `const`.
-            | AssocItemKind::Const(ref ty, ref default) => {
+            | AssocItemKind::Const(_, ref ty, ref default) => {
                 let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
                 let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x)));
                 (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body))
             }
-            AssocItemKind::Fn(ref sig, ref generics, None) => {
+            AssocItemKind::Fn(_, ref sig, ref generics, None) => {
                 let names = self.lower_fn_params_to_names(&sig.decl);
                 let (generics, sig) =
                     self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
                 (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names)))
             }
-            AssocItemKind::Fn(ref sig, ref generics, Some(ref body)) => {
+            AssocItemKind::Fn(_, ref sig, ref generics, Some(ref body)) => {
                 let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body));
                 let (generics, sig) =
                     self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
                 (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id)))
             }
-            AssocItemKind::TyAlias(ref generics, ref bounds, ref default) => {
+            AssocItemKind::TyAlias(_, ref generics, ref bounds, ref default) => {
                 let ty = default.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::disallowed()));
                 let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
                 let kind = hir::TraitItemKind::Type(
@@ -801,11 +801,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
         let (kind, has_default) = match &i.kind {
             AssocItemKind::Static(_, _, default) // Let's pretend this is a `const` for recovery.
-            | AssocItemKind::Const(_, default) => {
+            | AssocItemKind::Const(_, _, default) => {
                 (hir::AssocItemKind::Const, default.is_some())
             }
-            AssocItemKind::TyAlias(_, _, default) => (hir::AssocItemKind::Type, default.is_some()),
-            AssocItemKind::Fn(sig, _, default) => {
+            AssocItemKind::TyAlias(_, _, _, default) => (hir::AssocItemKind::Type, default.is_some()),
+            AssocItemKind::Fn(_, sig, _, default) => {
                 (hir::AssocItemKind::Method { has_self: sig.decl.has_self() }, default.is_some())
             }
             AssocItemKind::Macro(..) => unimplemented!(),
@@ -823,15 +823,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> {
         let impl_item_def_id = self.resolver.definitions().local_def_id(i.id);
 
-        let (generics, kind) = match i.kind {
-            AssocItemKind::Static(ref ty, _, ref expr) | AssocItemKind::Const(ref ty, ref expr) => {
+        let (generics, kind) = match &i.kind {
+            AssocItemKind::Static(ty, _, expr) | AssocItemKind::Const(_, ty, expr) => {
                 let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
                 (
                     hir::Generics::empty(),
                     hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())),
                 )
             }
-            AssocItemKind::Fn(ref sig, ref generics, ref body) => {
+            AssocItemKind::Fn(_, sig, generics, body) => {
                 self.current_item = Some(i.span);
                 let asyncness = sig.header.asyncness;
                 let body_id =
@@ -847,7 +847,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
                 (generics, hir::ImplItemKind::Method(sig, body_id))
             }
-            AssocItemKind::TyAlias(ref generics, _, ref ty) => {
+            AssocItemKind::TyAlias(_, generics, _, ty) => {
                 let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
                 let kind = match ty {
                     None => {
@@ -876,7 +876,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             attrs: self.lower_attrs(&i.attrs),
             generics,
             vis: self.lower_visibility(&i.vis, None),
-            defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
+            defaultness: self.lower_defaultness(i.kind.defaultness(), true /* [1] */),
             kind,
             span: i.span,
         }
@@ -890,17 +890,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ident: i.ident,
             span: i.span,
             vis: self.lower_visibility(&i.vis, Some(i.id)),
-            defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
+            defaultness: self.lower_defaultness(i.kind.defaultness(), true /* [1] */),
             kind: match &i.kind {
                 AssocItemKind::Static(..) // Let's pretend this is a `const` for recovery.
                 | AssocItemKind::Const(..) => hir::AssocItemKind::Const,
-                AssocItemKind::TyAlias(_, _, ty) => {
+                AssocItemKind::TyAlias(.., ty) => {
                     match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) {
                         None => hir::AssocItemKind::Type,
                         Some(_) => hir::AssocItemKind::OpaqueTy,
                     }
                 }
-                AssocItemKind::Fn(sig, _, _) => {
+                AssocItemKind::Fn(_, sig, ..) => {
                     hir::AssocItemKind::Method { has_self: sig.decl.has_self() }
                 }
                 AssocItemKind::Macro(..) => unimplemented!(),
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index 9bb46009fe64b..8bf9311bfc798 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -462,7 +462,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     ItemKind::Struct(_, ref generics)
                     | ItemKind::Union(_, ref generics)
                     | ItemKind::Enum(_, ref generics)
-                    | ItemKind::TyAlias(ref generics, ..)
+                    | ItemKind::TyAlias(_, ref generics, ..)
                     | ItemKind::Trait(_, _, ref generics, ..) => {
                         let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
                         let count = generics
@@ -490,7 +490,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 self.lctx.allocate_hir_id_counter(item.id);
                 let owner = match (&item.kind, ctxt) {
                     // Ignore patterns in trait methods without bodies.
-                    (AssocItemKind::Fn(_, _, None), AssocCtxt::Trait) => None,
+                    (AssocItemKind::Fn(_, _, _, None), AssocCtxt::Trait) => None,
                     _ => Some(item.id),
                 };
                 self.with_hir_id_owner(owner, |this| visit::walk_assoc_item(this, item, ctxt));
diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs
index d385ea1a4a6d7..44fed6dee6628 100644
--- a/src/librustc_ast_passes/ast_validation.rs
+++ b/src/librustc_ast_passes/ast_validation.rs
@@ -881,7 +881,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         .emit();
                 }
             }
-            ItemKind::Fn(ref sig, ref generics, ref body) => {
+            ItemKind::Fn(def, ref sig, ref generics, ref body) => {
+                self.check_defaultness(item.span, def);
                 self.check_const_fn_const_generic(item.span, sig, generics);
 
                 if body.is_none() {
@@ -965,7 +966,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     self.err_handler().span_err(item.span, "unions cannot have zero fields");
                 }
             }
-            ItemKind::Const(.., None) => {
+            ItemKind::Const(def, .., None) => {
+                self.check_defaultness(item.span, def);
                 let msg = "free constant item without body";
                 self.error_item_without_body(item.span, "constant", msg, " = <expr>;");
             }
@@ -973,7 +975,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 let msg = "free static item without body";
                 self.error_item_without_body(item.span, "static", msg, " = <expr>;");
             }
-            ItemKind::TyAlias(_, ref bounds, ref body) => {
+            ItemKind::TyAlias(def, _, ref bounds, ref body) => {
+                self.check_defaultness(item.span, def);
                 if body.is_none() {
                     let msg = "free type alias without body";
                     self.error_item_without_body(item.span, "type", msg, " = <type>;");
@@ -988,11 +991,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
 
     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
         match &fi.kind {
-            ForeignItemKind::Fn(sig, _, body) => {
+            ForeignItemKind::Fn(def, sig, _, body) => {
+                self.check_defaultness(fi.span, *def);
                 self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
                 self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
             }
-            ForeignItemKind::TyAlias(generics, bounds, body) => {
+            ForeignItemKind::TyAlias(def, generics, bounds, body) => {
+                self.check_defaultness(fi.span, *def);
                 self.check_foreign_kind_bodyless(fi.ident, "type", body.as_ref().map(|b| b.span));
                 self.check_type_no_bounds(bounds, "`extern` blocks");
                 self.check_foreign_ty_genericless(generics);
@@ -1233,19 +1238,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
     }
 
     fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
-        if ctxt == AssocCtxt::Trait {
-            self.check_defaultness(item.span, item.defaultness);
+        if ctxt == AssocCtxt::Trait || !self.in_trait_impl {
+            self.check_defaultness(item.span, item.kind.defaultness());
         }
 
         if ctxt == AssocCtxt::Impl {
             match &item.kind {
-                AssocItemKind::Const(_, body) => {
+                AssocItemKind::Const(_, _, body) => {
                     self.check_impl_item_provided(item.span, body, "constant", " = <expr>;");
                 }
-                AssocItemKind::Fn(_, _, body) => {
+                AssocItemKind::Fn(_, _, _, body) => {
                     self.check_impl_item_provided(item.span, body, "function", " { <body> }");
                 }
-                AssocItemKind::TyAlias(_, bounds, body) => {
+                AssocItemKind::TyAlias(_, _, bounds, body) => {
                     self.check_impl_item_provided(item.span, body, "type", " = <type>;");
                     self.check_type_no_bounds(bounds, "`impl`s");
                 }
@@ -1255,7 +1260,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
 
         if ctxt == AssocCtxt::Trait || self.in_trait_impl {
             self.invalid_visibility(&item.vis, None);
-            if let AssocItemKind::Fn(sig, _, _) = &item.kind {
+            if let AssocItemKind::Fn(_, sig, _, _) = &item.kind {
                 self.check_trait_fn_not_const(sig.header.constness);
                 self.check_trait_fn_not_async(item.span, sig.header.asyncness);
             }
diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs
index 586539d9b5ee2..33ff0bc451b32 100644
--- a/src/librustc_ast_passes/feature_gate.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -372,7 +372,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 gate_feature_post!(&self, decl_macro, i.span, msg);
             }
 
-            ast::ItemKind::TyAlias(_, _, Some(ref ty)) => self.check_impl_trait(&ty),
+            ast::ItemKind::TyAlias(_, _, _, Some(ref ty)) => self.check_impl_trait(&ty),
 
             _ => {}
         }
@@ -543,17 +543,17 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
     }
 
     fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
-        if let ast::Defaultness::Default(_) = i.defaultness {
+        if let ast::Defaultness::Default(_) = i.kind.defaultness() {
             gate_feature_post!(&self, specialization, i.span, "specialization is unstable");
         }
 
         match i.kind {
-            ast::AssocItemKind::Fn(ref sig, _, _) => {
+            ast::AssocItemKind::Fn(_, ref sig, _, _) => {
                 if let (ast::Const::Yes(_), AssocCtxt::Trait) = (sig.header.constness, ctxt) {
                     gate_feature_post!(&self, const_fn, i.span, "const fn is unstable");
                 }
             }
-            ast::AssocItemKind::TyAlias(ref generics, _, ref ty) => {
+            ast::AssocItemKind::TyAlias(_, ref generics, _, ref ty) => {
                 if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
                     gate_feature_post!(
                         &self,
diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs
index 503310c6db539..2b223d92ff198 100644
--- a/src/librustc_ast_pretty/pprust.rs
+++ b/src/librustc_ast_pretty/pprust.rs
@@ -1016,8 +1016,8 @@ impl<'a> State<'a> {
     }
 
     crate fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
-        let ast::Item { id, span, ident, attrs, kind, vis, defaultness, tokens: _ } = item;
-        self.print_nested_item_kind(*id, *span, *ident, attrs, *defaultness, kind, vis);
+        let ast::Item { id, span, ident, attrs, kind, vis, tokens: _ } = item;
+        self.print_nested_item_kind(*id, *span, *ident, attrs, kind, vis);
     }
 
     fn print_nested_item_kind(
@@ -1026,7 +1026,6 @@ impl<'a> State<'a> {
         span: Span,
         ident: ast::Ident,
         attrs: &[Attribute],
-        def: ast::Defaultness,
         kind: &ast::AssocItemKind,
         vis: &ast::Visibility,
     ) {
@@ -1035,17 +1034,18 @@ impl<'a> State<'a> {
         self.maybe_print_comment(span.lo());
         self.print_outer_attributes(attrs);
         match kind {
-            ast::ForeignItemKind::Fn(sig, gen, body) => {
-                self.print_fn_full(sig, ident, gen, vis, def, body.as_deref(), attrs);
+            ast::ForeignItemKind::Fn(def, sig, gen, body) => {
+                self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs);
             }
-            ast::ForeignItemKind::Const(ty, body) => {
-                self.print_item_const(ident, None, ty, body.as_deref(), vis, def);
+            ast::ForeignItemKind::Const(def, ty, body) => {
+                self.print_item_const(ident, None, ty, body.as_deref(), vis, *def);
             }
             ast::ForeignItemKind::Static(ty, mutbl, body) => {
+                let def = ast::Defaultness::Final;
                 self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis, def);
             }
-            ast::ForeignItemKind::TyAlias(generics, bounds, ty) => {
-                self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, def);
+            ast::ForeignItemKind::TyAlias(def, generics, bounds, ty) => {
+                self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def);
             }
             ast::ForeignItemKind::Macro(m) => {
                 self.print_mac(m);
@@ -1146,12 +1146,10 @@ impl<'a> State<'a> {
                 let def = ast::Defaultness::Final;
                 self.print_item_const(item.ident, Some(mutbl), ty, body.as_deref(), &item.vis, def);
             }
-            ast::ItemKind::Const(ref ty, ref body) => {
-                let def = ast::Defaultness::Final;
+            ast::ItemKind::Const(def, ref ty, ref body) => {
                 self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis, def);
             }
-            ast::ItemKind::Fn(ref sig, ref gen, ref body) => {
-                let def = ast::Defaultness::Final;
+            ast::ItemKind::Fn(def, ref sig, ref gen, ref body) => {
                 let body = body.as_deref();
                 self.print_fn_full(sig, item.ident, gen, &item.vis, def, body, &item.attrs);
             }
@@ -1185,8 +1183,7 @@ impl<'a> State<'a> {
                 self.s.word(ga.asm.to_string());
                 self.end();
             }
-            ast::ItemKind::TyAlias(ref generics, ref bounds, ref ty) => {
-                let def = ast::Defaultness::Final;
+            ast::ItemKind::TyAlias(def, ref generics, ref bounds, ref ty) => {
                 let ty = ty.as_deref();
                 self.print_associated_type(item.ident, generics, bounds, ty, &item.vis, def);
             }
@@ -1461,8 +1458,8 @@ impl<'a> State<'a> {
     }
 
     crate fn print_assoc_item(&mut self, item: &ast::AssocItem) {
-        let ast::AssocItem { id, span, ident, attrs, defaultness, kind, vis, tokens: _ } = item;
-        self.print_nested_item_kind(*id, *span, *ident, attrs, *defaultness, kind, vis);
+        let ast::Item { id, span, ident, attrs, kind, vis, tokens: _ } = item;
+        self.print_nested_item_kind(*id, *span, *ident, attrs, kind, vis);
     }
 
     crate fn print_stmt(&mut self, st: &ast::Stmt) {
diff --git a/src/librustc_builtin_macros/deriving/generic/mod.rs b/src/librustc_builtin_macros/deriving/generic/mod.rs
index 294b7463916b8..00ed05608b50b 100644
--- a/src/librustc_builtin_macros/deriving/generic/mod.rs
+++ b/src/librustc_builtin_macros/deriving/generic/mod.rs
@@ -542,9 +542,9 @@ impl<'a> TraitDef<'a> {
                 span: self.span,
                 ident,
                 vis: respan(self.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
-                defaultness: ast::Defaultness::Final,
                 attrs: Vec::new(),
                 kind: ast::AssocItemKind::TyAlias(
+                    ast::Defaultness::Final,
                     Generics::default(),
                     Vec::new(),
                     Some(type_def.to_ty(cx, self.span, type_ident, generics)),
@@ -968,6 +968,7 @@ impl<'a> MethodDef<'a> {
             header: ast::FnHeader { unsafety, ext: ast::Extern::None, ..ast::FnHeader::default() },
             decl: fn_decl,
         };
+        let def = ast::Defaultness::Final;
 
         // Create the method.
         P(ast::AssocItem {
@@ -975,9 +976,8 @@ impl<'a> MethodDef<'a> {
             attrs: self.attributes.clone(),
             span: trait_.span,
             vis: respan(trait_lo_sp, ast::VisibilityKind::Inherited),
-            defaultness: ast::Defaultness::Final,
             ident: method_ident,
-            kind: ast::AssocItemKind::Fn(sig, fn_generics, Some(body_block)),
+            kind: ast::AssocItemKind::Fn(def, sig, fn_generics, Some(body_block)),
             tokens: None,
         })
     }
diff --git a/src/librustc_builtin_macros/global_allocator.rs b/src/librustc_builtin_macros/global_allocator.rs
index 3ffb1d2206a5e..5a0b1a6b88542 100644
--- a/src/librustc_builtin_macros/global_allocator.rs
+++ b/src/librustc_builtin_macros/global_allocator.rs
@@ -66,7 +66,8 @@ impl AllocFnFactory<'_, '_> {
         let decl = self.cx.fn_decl(abi_args, ast::FnRetTy::Ty(output_ty));
         let header = FnHeader { unsafety: Unsafe::Yes(self.span), ..FnHeader::default() };
         let sig = FnSig { decl, header };
-        let kind = ItemKind::Fn(sig, Generics::default(), Some(self.cx.block_expr(output_expr)));
+        let block = Some(self.cx.block_expr(output_expr));
+        let kind = ItemKind::Fn(ast::Defaultness::Final, sig, Generics::default(), block);
         let item = self.cx.item(
             self.span,
             self.cx.ident_of(&self.kind.fn_name(method.name), self.span),
diff --git a/src/librustc_builtin_macros/global_asm.rs b/src/librustc_builtin_macros/global_asm.rs
index 70b9fccbafc15..052e62ee9ffd3 100644
--- a/src/librustc_builtin_macros/global_asm.rs
+++ b/src/librustc_builtin_macros/global_asm.rs
@@ -30,7 +30,6 @@ pub fn expand_global_asm<'cx>(
             id: ast::DUMMY_NODE_ID,
             kind: ast::ItemKind::GlobalAsm(P(global_asm)),
             vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
-            defaultness: ast::Defaultness::Final,
             span: cx.with_def_site_ctxt(sp),
             tokens: None,
         })]),
diff --git a/src/librustc_builtin_macros/test.rs b/src/librustc_builtin_macros/test.rs
index e15405e1f0dfc..8407352f57714 100644
--- a/src/librustc_builtin_macros/test.rs
+++ b/src/librustc_builtin_macros/test.rs
@@ -184,6 +184,7 @@ pub fn expand_test_or_bench(
         ],
         // const $ident: test::TestDescAndFn =
         ast::ItemKind::Const(
+            ast::Defaultness::Final,
             cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
             // test::TestDescAndFn {
             Some(
@@ -378,7 +379,7 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType {
 fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
     let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic);
     let ref sd = cx.parse_sess.span_diagnostic;
-    if let ast::ItemKind::Fn(ref sig, ref generics, _) = i.kind {
+    if let ast::ItemKind::Fn(_, ref sig, ref generics, _) = i.kind {
         if let ast::Unsafe::Yes(span) = sig.header.unsafety {
             sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
                 .span_label(span, "`unsafe` because of this")
@@ -427,7 +428,7 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
 }
 
 fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
-    let has_sig = if let ast::ItemKind::Fn(ref sig, _, _) = i.kind {
+    let has_sig = if let ast::ItemKind::Fn(_, ref sig, _, _) = i.kind {
         // N.B., inadequate check, but we're running
         // well before resolve, can't get too deep.
         sig.decl.inputs.len() == 1
diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs
index 1d8ade1b2ba78..4bbab0d257489 100644
--- a/src/librustc_builtin_macros/test_harness.rs
+++ b/src/librustc_builtin_macros/test_harness.rs
@@ -162,7 +162,7 @@ impl MutVisitor for EntryPointCleaner {
         // #[allow(dead_code)] to avoid printing warnings.
         let item = match entry::entry_point_type(&item, self.depth) {
             EntryPointType::MainNamed | EntryPointType::MainAttr | EntryPointType::Start => item
-                .map(|ast::Item { id, ident, attrs, kind, vis, defaultness, span, tokens }| {
+                .map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| {
                     let allow_ident = Ident::new(sym::allow, self.def_site);
                     let dc_nested = attr::mk_nested_word_item(Ident::from_str_and_span(
                         "dead_code",
@@ -176,7 +176,7 @@ impl MutVisitor for EntryPointCleaner {
                         .chain(iter::once(allow_dead_code))
                         .collect();
 
-                    ast::Item { id, ident, attrs, kind, vis, defaultness, span, tokens }
+                    ast::Item { id, ident, attrs, kind, vis, span, tokens }
                 }),
             EntryPointType::None | EntryPointType::OtherMain => item,
         };
@@ -298,7 +298,8 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
 
     let decl = ecx.fn_decl(vec![], ast::FnRetTy::Ty(main_ret_ty));
     let sig = ast::FnSig { decl, header: ast::FnHeader::default() };
-    let main = ast::ItemKind::Fn(sig, ast::Generics::default(), Some(main_body));
+    let def = ast::Defaultness::Final;
+    let main = ast::ItemKind::Fn(def, sig, ast::Generics::default(), Some(main_body));
 
     // Honor the reexport_test_harness_main attribute
     let main_id = match cx.reexport_test_harness_main {
@@ -312,7 +313,6 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
         id: ast::DUMMY_NODE_ID,
         kind: main,
         vis: respan(sp, ast::VisibilityKind::Public),
-        defaultness: ast::Defaultness::Final,
         span: sp,
         tokens: None,
     });
diff --git a/src/librustc_expand/build.rs b/src/librustc_expand/build.rs
index 246b3bff71d4e..bd6823cd4e275 100644
--- a/src/librustc_expand/build.rs
+++ b/src/librustc_expand/build.rs
@@ -588,7 +588,6 @@ impl<'a> ExtCtxt<'a> {
             id: ast::DUMMY_NODE_ID,
             kind,
             vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
-            defaultness: ast::Defaultness::Final,
             span,
             tokens: None,
         })
@@ -645,7 +644,8 @@ impl<'a> ExtCtxt<'a> {
         ty: P<ast::Ty>,
         expr: P<ast::Expr>,
     ) -> P<ast::Item> {
-        self.item(span, name, Vec::new(), ast::ItemKind::Const(ty, Some(expr)))
+        let def = ast::Defaultness::Final;
+        self.item(span, name, Vec::new(), ast::ItemKind::Const(def, ty, Some(expr)))
     }
 
     pub fn attribute(&self, mi: ast::MetaItem) -> ast::Attribute {
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index fce2a1d7a7ee2..bbea066b048d2 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -358,7 +358,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             ident: Ident::invalid(),
             id: ast::DUMMY_NODE_ID,
             vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public),
-            defaultness: ast::Defaultness::Final,
             tokens: None,
         })]);
 
diff --git a/src/librustc_expand/placeholders.rs b/src/librustc_expand/placeholders.rs
index e7e4f482a5e31..c323af4336a4c 100644
--- a/src/librustc_expand/placeholders.rs
+++ b/src/librustc_expand/placeholders.rs
@@ -26,7 +26,6 @@ pub fn placeholder(
     let ident = ast::Ident::invalid();
     let attrs = Vec::new();
     let vis = vis.unwrap_or_else(|| dummy_spanned(ast::VisibilityKind::Inherited));
-    let defaultness = ast::Defaultness::Final;
     let span = DUMMY_SP;
     let expr_placeholder = || {
         P(ast::Expr {
@@ -47,7 +46,6 @@ pub fn placeholder(
             span,
             ident,
             vis,
-            defaultness,
             attrs,
             kind: ast::ItemKind::Mac(mac_placeholder()),
             tokens: None,
@@ -59,7 +57,6 @@ pub fn placeholder(
             vis,
             attrs,
             kind: ast::AssocItemKind::Macro(mac_placeholder()),
-            defaultness: ast::Defaultness::Final,
             tokens: None,
         })]),
         AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem {
@@ -69,7 +66,6 @@ pub fn placeholder(
             vis,
             attrs,
             kind: ast::AssocItemKind::Macro(mac_placeholder()),
-            defaultness: ast::Defaultness::Final,
             tokens: None,
         })]),
         AstFragmentKind::ForeignItems => {
@@ -78,7 +74,6 @@ pub fn placeholder(
                 span,
                 ident,
                 vis,
-                defaultness,
                 attrs,
                 kind: ast::ForeignItemKind::Macro(mac_placeholder()),
                 tokens: None,
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index 99e9878bfd8bb..c73f7aafb4860 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -677,7 +677,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
     fn visit_item_kind(&mut self, i: &mut ast::ItemKind) {
         let is_const = match i {
             ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true,
-            ast::ItemKind::Fn(ref sig, _, _) => Self::is_sig_const(sig),
+            ast::ItemKind::Fn(_, ref sig, _, _) => Self::is_sig_const(sig),
             _ => false,
         };
         self.run(is_const, |s| noop_visit_item_kind(i, s))
@@ -686,7 +686,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
     fn flat_map_trait_item(&mut self, i: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
         let is_const = match i.kind {
             ast::AssocItemKind::Const(..) => true,
-            ast::AssocItemKind::Fn(ref sig, _, _) => Self::is_sig_const(sig),
+            ast::AssocItemKind::Fn(_, ref sig, _, _) => Self::is_sig_const(sig),
             _ => false,
         };
         self.run(is_const, |s| noop_flat_map_assoc_item(i, s))
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 5c601803a77a2..ca3727d175563 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -640,7 +640,7 @@ declare_lint_pass!(
 impl EarlyLintPass for AnonymousParameters {
     fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
         match it.kind {
-            ast::AssocItemKind::Fn(ref sig, _, _) => {
+            ast::AssocItemKind::Fn(_, ref sig, _, _) => {
                 for arg in sig.decl.inputs.iter() {
                     match arg.pat.kind {
                         ast::PatKind::Ident(_, ident, None) => {
diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
index 602be37257361..fb7e5541e266e 100644
--- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
+++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs
@@ -464,7 +464,6 @@ impl CStore {
                     legacy: def.legacy,
                 }),
                 vis: source_map::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited),
-                defaultness: ast::Defaultness::Final,
                 tokens: None,
             },
             data.root.edition,
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 6fa9e615b459f..451f1fdf14a07 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -36,9 +36,6 @@ impl<'a> Parser<'a> {
         attributes_allowed: bool,
     ) -> PResult<'a, Option<P<Item>>> {
         let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed, |_| true)?;
-        if let Some(ref item) = item {
-            self.error_on_illegal_default(item.defaultness);
-        }
         Ok(item.map(P))
     }
 
@@ -98,9 +95,10 @@ impl<'a> Parser<'a> {
         let mut def = self.parse_defaultness();
         let kind = self.parse_item_kind(&mut attrs, mac_allowed, lo, &vis, &mut def, req_name)?;
         if let Some((ident, kind)) = kind {
+            self.error_on_unconsumed_default(def, &kind);
             let span = lo.to(self.prev_span);
             let id = DUMMY_NODE_ID;
-            let item = Item { ident, attrs, id, kind, vis, defaultness: def, span, tokens: None };
+            let item = Item { ident, attrs, id, kind, vis, span, tokens: None };
             return Ok(Some(item));
         }
 
@@ -137,9 +135,10 @@ impl<'a> Parser<'a> {
     }
 
     /// Error in-case `default` was parsed in an in-appropriate context.
-    fn error_on_illegal_default(&self, def: Defaultness) {
+    fn error_on_unconsumed_default(&self, def: Defaultness, kind: &ItemKind) {
         if let Defaultness::Default(span) = def {
-            self.struct_span_err(span, "item cannot be `default`")
+            let msg = format!("{} {} cannot be `default`", kind.article(), kind.descr());
+            self.struct_span_err(span, &msg)
                 .span_label(span, "`default` because of this")
                 .note("only associated `fn`, `const`, and `type` items can be `default`")
                 .emit();
@@ -156,6 +155,8 @@ impl<'a> Parser<'a> {
         def: &mut Defaultness,
         req_name: ReqName,
     ) -> PResult<'a, Option<ItemInfo>> {
+        let mut def = || mem::replace(def, Defaultness::Final);
+
         let info = if self.eat_keyword(kw::Use) {
             // USE ITEM
             let tree = self.parse_use_tree()?;
@@ -164,7 +165,7 @@ impl<'a> Parser<'a> {
         } else if self.check_fn_front_matter() {
             // FUNCTION ITEM
             let (ident, sig, generics, body) = self.parse_fn(attrs, req_name)?;
-            (ident, ItemKind::Fn(sig, generics, body))
+            (ident, ItemKind::Fn(def(), sig, generics, body))
         } else if self.eat_keyword(kw::Extern) {
             if self.eat_keyword(kw::Crate) {
                 // EXTERN CRATE
@@ -177,11 +178,13 @@ impl<'a> Parser<'a> {
             // STATIC ITEM
             self.bump(); // `static`
             let m = self.parse_mutability();
-            self.parse_item_const(Some(m))?
+            let (ident, ty, expr) = self.parse_item_global(Some(m))?;
+            (ident, ItemKind::Static(ty, m, expr))
         } else if let Const::Yes(const_span) = self.parse_constness() {
             // CONST ITEM
             self.recover_const_mut(const_span);
-            self.parse_item_const(None)?
+            let (ident, ty, expr) = self.parse_item_global(None)?;
+            (ident, ItemKind::Const(def(), ty, expr))
         } else if self.check_keyword(kw::Trait) || self.check_auto_or_unsafe_trait_item() {
             // TRAIT ITEM
             self.parse_item_trait(attrs, lo)?
@@ -189,13 +192,13 @@ impl<'a> Parser<'a> {
             || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Impl])
         {
             // IMPL ITEM
-            self.parse_item_impl(attrs, mem::replace(def, Defaultness::Final))?
+            self.parse_item_impl(attrs, def())?
         } else if self.eat_keyword(kw::Mod) {
             // MODULE ITEM
             self.parse_item_mod(attrs)?
         } else if self.eat_keyword(kw::Type) {
             // TYPE ITEM
-            self.parse_type_alias()?
+            self.parse_type_alias(def())?
         } else if self.eat_keyword(kw::Enum) {
             // ENUM ITEM
             self.parse_item_enum()?
@@ -652,19 +655,19 @@ impl<'a> Parser<'a> {
     fn parse_assoc_item(&mut self, req_name: ReqName) -> PResult<'a, Option<Option<P<AssocItem>>>> {
         let attrs = self.parse_outer_attributes()?;
         let it = self.parse_item_common(attrs, true, false, req_name)?;
-        Ok(it.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| {
+        Ok(it.map(|Item { attrs, id, span, vis, ident, kind, tokens }| {
             let kind = match kind {
                 ItemKind::Mac(a) => AssocItemKind::Macro(a),
-                ItemKind::Fn(a, b, c) => AssocItemKind::Fn(a, b, c),
-                ItemKind::TyAlias(a, b, c) => AssocItemKind::TyAlias(a, b, c),
-                ItemKind::Const(a, c) => AssocItemKind::Const(a, c),
+                ItemKind::Fn(a, b, c, d) => AssocItemKind::Fn(a, b, c, d),
+                ItemKind::TyAlias(a, b, c, d) => AssocItemKind::TyAlias(a, b, c, d),
+                ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c),
                 ItemKind::Static(a, _, b) => {
                     self.struct_span_err(span, "associated `static` items are not allowed").emit();
-                    AssocItemKind::Const(a, b)
+                    AssocItemKind::Const(Defaultness::Final, a, b)
                 }
                 _ => return self.error_bad_item_kind(span, &kind, "`trait` or `impl`"),
             };
-            Some(P(Item { attrs, id, span, vis, ident, defaultness, kind, tokens }))
+            Some(P(Item { attrs, id, span, vis, ident, kind, tokens }))
         }))
     }
 
@@ -673,7 +676,7 @@ impl<'a> Parser<'a> {
     /// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ;
     /// ```
     /// The `"type"` has already been eaten.
-    fn parse_type_alias(&mut self) -> PResult<'a, (Ident, ItemKind)> {
+    fn parse_type_alias(&mut self, def: Defaultness) -> PResult<'a, ItemInfo> {
         let ident = self.parse_ident()?;
         let mut generics = self.parse_generics()?;
 
@@ -685,7 +688,7 @@ impl<'a> Parser<'a> {
         let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
         self.expect_semi()?;
 
-        Ok((ident, ItemKind::TyAlias(generics, bounds, default)))
+        Ok((ident, ItemKind::TyAlias(def, generics, bounds, default)))
     }
 
     /// Parses a `UseTree`.
@@ -843,20 +846,19 @@ impl<'a> Parser<'a> {
 
         let attrs = self.parse_outer_attributes()?;
         let item = self.parse_item_common(attrs, true, false, |_| true)?;
-        Ok(item.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| {
-            self.error_on_illegal_default(defaultness);
+        Ok(item.map(|Item { attrs, id, span, vis, ident, kind, tokens }| {
             let kind = match kind {
                 ItemKind::Mac(a) => ForeignItemKind::Macro(a),
-                ItemKind::Fn(a, b, c) => ForeignItemKind::Fn(a, b, c),
-                ItemKind::TyAlias(a, b, c) => ForeignItemKind::TyAlias(a, b, c),
+                ItemKind::Fn(a, b, c, d) => ForeignItemKind::Fn(a, b, c, d),
+                ItemKind::TyAlias(a, b, c, d) => ForeignItemKind::TyAlias(a, b, c, d),
                 ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c),
-                ItemKind::Const(a, b) => {
+                ItemKind::Const(_, a, b) => {
                     self.error_on_foreign_const(span, ident);
                     ForeignItemKind::Static(a, Mutability::Not, b)
                 }
                 _ => return self.error_bad_item_kind(span, &kind, "`extern` block"),
             };
-            Some(P(Item { attrs, id, span, vis, ident, defaultness, kind, tokens }))
+            Some(P(Item { attrs, id, span, vis, ident, kind, tokens }))
         }))
     }
 
@@ -916,7 +918,10 @@ impl<'a> Parser<'a> {
     /// `["const" | ("static" "mut"?)]` already parsed and stored in `m`.
     ///
     /// When `m` is `"const"`, `$ident` may also be `"_"`.
-    fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<'a, ItemInfo> {
+    fn parse_item_global(
+        &mut self,
+        m: Option<Mutability>,
+    ) -> PResult<'a, (Ident, P<Ty>, Option<P<ast::Expr>>)> {
         let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?;
 
         // Parse the type of a `const` or `static mut?` item.
@@ -929,12 +934,7 @@ impl<'a> Parser<'a> {
 
         let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None };
         self.expect_semi()?;
-
-        let item = match m {
-            Some(m) => ItemKind::Static(ty, m, expr),
-            None => ItemKind::Const(ty, expr),
-        };
-        Ok((id, item))
+        Ok((id, ty, expr))
     }
 
     /// We were supposed to parse `:` but the `:` was missing.
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 383bfe18fd00b..a81caea4e412a 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -718,7 +718,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             }
 
             // These items live in the type namespace.
-            ItemKind::TyAlias(_, _, ref ty) => {
+            ItemKind::TyAlias(_, _, _, ref ty) => {
                 let def_kind = match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) {
                     None => DefKind::TyAlias,
                     Some(_) => DefKind::OpaqueTy,
@@ -1253,7 +1253,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
         let (res, ns) = match item.kind {
             AssocItemKind::Static(..) // Let's pretend it's a `const` for recovery.
             | AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS),
-            AssocItemKind::Fn(ref sig, _, _) => {
+            AssocItemKind::Fn(_, ref sig, _, _) => {
                 if sig.decl.has_self() {
                     self.r.has_self.insert(item_def_id);
                 }
diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs
index 60cba55512193..30089633689c4 100644
--- a/src/librustc_resolve/def_collector.rs
+++ b/src/librustc_resolve/def_collector.rs
@@ -117,7 +117,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             | ItemKind::ExternCrate(..)
             | ItemKind::ForeignMod(..)
             | ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name),
-            ItemKind::Fn(sig, generics, body) if sig.header.asyncness.is_async() => {
+            ItemKind::Fn(_, sig, generics, body) if sig.header.asyncness.is_async() => {
                 return self.visit_async_fn(
                     i.id,
                     i.ident.name,
@@ -215,7 +215,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
 
     fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
         let def_data = match &i.kind {
-            AssocItemKind::Fn(FnSig { header, decl }, generics, body)
+            AssocItemKind::Fn(_, FnSig { header, decl }, generics, body)
                 if header.asyncness.is_async() =>
             {
                 return self.visit_async_fn(
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 74628e6e5a03e..5b5180a7e1a44 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -437,8 +437,8 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
     }
     fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
         match foreign_item.kind {
-            ForeignItemKind::Fn(_, ref generics, _)
-            | ForeignItemKind::TyAlias(ref generics, ..) => {
+            ForeignItemKind::Fn(_, _, ref generics, _)
+            | ForeignItemKind::TyAlias(_, ref generics, ..) => {
                 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
                     visit::walk_foreign_item(this, foreign_item);
                 });
@@ -797,7 +797,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         debug!("(resolving item) resolving {} ({:?})", name, item.kind);
 
         match item.kind {
-            ItemKind::TyAlias(ref generics, _, _) | ItemKind::Fn(_, ref generics, _) => {
+            ItemKind::TyAlias(_, ref generics, _, _) | ItemKind::Fn(_, _, ref generics, _) => {
                 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
                     visit::walk_item(this, item)
                 });
@@ -837,7 +837,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                             this.with_trait_items(trait_items, |this| {
                                 match &item.kind {
                                     AssocItemKind::Static(ty, _, default)
-                                    | AssocItemKind::Const(ty, default) => {
+                                    | AssocItemKind::Const(_, ty, default) => {
                                         this.visit_ty(ty);
                                         // Only impose the restrictions of `ConstRibKind` for an
                                         // actual constant expression in a provided default.
@@ -845,10 +845,10 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                             this.with_constant_rib(|this| this.visit_expr(expr));
                                         }
                                     }
-                                    AssocItemKind::Fn(_, generics, _) => {
+                                    AssocItemKind::Fn(_, _, generics, _) => {
                                         walk_assoc_item(this, generics, item);
                                     }
-                                    AssocItemKind::TyAlias(generics, _, _) => {
+                                    AssocItemKind::TyAlias(_, generics, _, _) => {
                                         walk_assoc_item(this, generics, item);
                                     }
                                     AssocItemKind::Macro(_) => {
@@ -878,7 +878,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 });
             }
 
-            ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(ref ty, ref expr) => {
+            ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(_, ref ty, ref expr) => {
                 debug!("resolve_item ItemKind::Const");
                 self.with_item_rib(HasGenericParams::No, |this| {
                     this.visit_ty(ty);
@@ -1015,7 +1015,9 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             trait_items
                 .iter()
                 .filter_map(|item| match &item.kind {
-                    AssocItemKind::TyAlias(_, bounds, _) if bounds.len() == 0 => Some(item.ident),
+                    AssocItemKind::TyAlias(_, _, bounds, _) if bounds.len() == 0 => {
+                        Some(item.ident)
+                    }
                     _ => None,
                 })
                 .collect(),
@@ -1125,7 +1127,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                                 visit::walk_assoc_item(this, item, AssocCtxt::Impl)
                                             });
                                         }
-                                        AssocItemKind::Fn(_, generics, _) => {
+                                        AssocItemKind::Fn(_, _, generics, _) => {
                                             // We also need a new scope for the impl item type parameters.
                                             this.with_generic_param_rib(
                                                 generics,
@@ -1148,7 +1150,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                                 },
                                             );
                                         }
-                                        AssocItemKind::TyAlias(generics, _, _) => {
+                                        AssocItemKind::TyAlias(_, generics, _, _) => {
                                             // We also need a new scope for the impl item type parameters.
                                             this.with_generic_param_rib(
                                                 generics,
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 442f3b695a26f..b3a8657d80bed 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -1005,7 +1005,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         let vis_span = trait_item.span.shrink_to_lo();
         match trait_item.kind {
             ast::AssocItemKind::Static(ref ty, _, ref expr)
-            | ast::AssocItemKind::Const(ref ty, ref expr) => {
+            | ast::AssocItemKind::Const(_, ref ty, ref expr) => {
                 self.process_assoc_const(
                     trait_item.id,
                     trait_item.ident,
@@ -1016,7 +1016,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     &trait_item.attrs,
                 );
             }
-            ast::AssocItemKind::Fn(ref sig, ref generics, ref body) => {
+            ast::AssocItemKind::Fn(_, ref sig, ref generics, ref body) => {
                 self.process_method(
                     sig,
                     body.as_ref().map(|x| &**x),
@@ -1027,7 +1027,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     trait_item.span,
                 );
             }
-            ast::AssocItemKind::TyAlias(_, ref bounds, ref default_ty) => {
+            ast::AssocItemKind::TyAlias(_, _, ref bounds, ref default_ty) => {
                 // FIXME do something with _bounds (for type refs)
                 let name = trait_item.ident.name.to_string();
                 let qualname = format!(
@@ -1076,7 +1076,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         self.process_macro_use(impl_item.span);
         match impl_item.kind {
             ast::AssocItemKind::Static(ref ty, _, ref expr)
-            | ast::AssocItemKind::Const(ref ty, ref expr) => {
+            | ast::AssocItemKind::Const(_, ref ty, ref expr) => {
                 self.process_assoc_const(
                     impl_item.id,
                     impl_item.ident,
@@ -1087,7 +1087,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     &impl_item.attrs,
                 );
             }
-            ast::AssocItemKind::Fn(ref sig, ref generics, ref body) => {
+            ast::AssocItemKind::Fn(_, ref sig, ref generics, ref body) => {
                 self.process_method(
                     sig,
                     body.as_deref(),
@@ -1098,8 +1098,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     impl_item.span,
                 );
             }
-            ast::AssocItemKind::TyAlias(_, _, None) => {}
-            ast::AssocItemKind::TyAlias(_, _, Some(ref ty)) => {
+            ast::AssocItemKind::TyAlias(_, _, _, None) => {}
+            ast::AssocItemKind::TyAlias(_, _, _, Some(ref ty)) => {
                 // FIXME: uses of the assoc type should ideally point to this
                 // 'def' and the name here should be a ref to the def in the
                 // trait.
@@ -1292,11 +1292,11 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
                     );
                 }
             }
-            Fn(ref sig, ref ty_params, ref body) => {
+            Fn(_, ref sig, ref ty_params, ref body) => {
                 self.process_fn(item, &sig.decl, &sig.header, ty_params, body.as_deref())
             }
             Static(ref typ, _, ref e) => self.process_static_or_const_item(item, typ, e.as_deref()),
-            Const(ref typ, ref e) => self.process_static_or_const_item(item, typ, e.as_deref()),
+            Const(_, ref typ, ref e) => self.process_static_or_const_item(item, typ, e.as_deref()),
             Struct(ref def, ref ty_params) | Union(ref def, ref ty_params) => {
                 self.process_struct(item, def, ty_params)
             }
@@ -1311,7 +1311,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
                 self.process_mod(item);
                 visit::walk_mod(self, m);
             }
-            TyAlias(ref ty_params, _, ref ty) => {
+            TyAlias(_, ref ty_params, _, ref ty) => {
                 let qualname = format!(
                     "::{}",
                     self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id))
@@ -1520,7 +1520,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
         let access = access_from!(self.save_ctxt, item, hir_id);
 
         match item.kind {
-            ast::ForeignItemKind::Fn(ref sig, ref generics, _) => {
+            ast::ForeignItemKind::Fn(_, ref sig, ref generics, _) => {
                 let decl = &sig.decl;
                 if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) {
                     down_cast_data!(fn_data, DefData, item.span);
@@ -1537,7 +1537,8 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> {
                     self.visit_ty(&ret_ty);
                 }
             }
-            ast::ForeignItemKind::Const(ref ty, _) | ast::ForeignItemKind::Static(ref ty, _, _) => {
+            ast::ForeignItemKind::Const(_, ref ty, _)
+            | ast::ForeignItemKind::Static(ref ty, _, _) => {
                 if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
                     down_cast_data!(var_data, DefData, item.span);
                     self.dumper.dump_def(&access, var_data);
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 43a0cfecd3ed0..b253559dd5cd5 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -133,7 +133,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
             self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id))
         );
         match item.kind {
-            ast::ForeignItemKind::Fn(ref sig, ref generics, _) => {
+            ast::ForeignItemKind::Fn(_, ref sig, ref generics, _) => {
                 filter!(self.span_utils, item.ident.span);
 
                 Some(Data::DefData(Def {
@@ -151,7 +151,8 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                     attributes: lower_attributes(item.attrs.clone(), self),
                 }))
             }
-            ast::ForeignItemKind::Const(ref ty, _) | ast::ForeignItemKind::Static(ref ty, _, _) => {
+            ast::ForeignItemKind::Const(_, ref ty, _)
+            | ast::ForeignItemKind::Static(ref ty, _, _) => {
                 filter!(self.span_utils, item.ident.span);
 
                 let id = id_from_node_id(item.id, self);
@@ -180,7 +181,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
 
     pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
         match item.kind {
-            ast::ItemKind::Fn(ref sig, .., ref generics, _) => {
+            ast::ItemKind::Fn(_, ref sig, .., ref generics, _) => {
                 let qualname = format!(
                     "::{}",
                     self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id))
@@ -227,7 +228,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                     attributes: lower_attributes(item.attrs.clone(), self),
                 }))
             }
-            ast::ItemKind::Const(ref typ, _) => {
+            ast::ItemKind::Const(_, ref typ, _) => {
                 let qualname = format!(
                     "::{}",
                     self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id))
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index a7a10c0be0d62..9670fb1e2c465 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -345,7 +345,7 @@ impl Sig for ast::Item {
 
                 Ok(extend_sig(ty, text, defs, vec![]))
             }
-            ast::ItemKind::Const(ref ty, ref expr) => {
+            ast::ItemKind::Const(_, ref ty, ref expr) => {
                 let mut text = "const ".to_owned();
                 let name = self.ident.to_string();
                 let defs = vec![SigElement {
@@ -369,7 +369,7 @@ impl Sig for ast::Item {
 
                 Ok(extend_sig(ty, text, defs, vec![]))
             }
-            ast::ItemKind::Fn(ast::FnSig { ref decl, header }, ref generics, _) => {
+            ast::ItemKind::Fn(_, ast::FnSig { ref decl, header }, ref generics, _) => {
                 let mut text = String::new();
                 if let ast::Const::Yes(_) = header.constness {
                     text.push_str("const ");
@@ -423,7 +423,7 @@ impl Sig for ast::Item {
 
                 Ok(Signature { text, defs, refs: vec![] })
             }
-            ast::ItemKind::TyAlias(ref generics, _, ref ty) => {
+            ast::ItemKind::TyAlias(_, ref generics, _, ref ty) => {
                 let text = "type ".to_owned();
                 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
 
@@ -732,7 +732,7 @@ impl Sig for ast::ForeignItem {
     fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
         let id = Some(self.id);
         match self.kind {
-            ast::ForeignItemKind::Fn(ref sig, ref generics, _) => {
+            ast::ForeignItemKind::Fn(_, ref sig, ref generics, _) => {
                 let decl = &sig.decl;
                 let mut text = String::new();
                 text.push_str("fn ");
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index f8a27cf714246..19c705fa99753 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -2421,9 +2421,6 @@ pub struct Item<K = ItemKind> {
     /// The name of the item.
     /// It might be a dummy name in case of anonymous items.
     pub ident: Ident,
-    /// The `default`ness of this item.
-    /// This should only occur in syntactically well-formed code in associated contexts.
-    pub defaultness: Defaultness,
 
     pub kind: K,
 
@@ -2509,11 +2506,11 @@ pub enum ItemKind {
     /// A constant item (`const`).
     ///
     /// E.g., `const FOO: i32 = 42;`.
-    Const(P<Ty>, Option<P<Expr>>),
+    Const(Defaultness, P<Ty>, Option<P<Expr>>),
     /// A function declaration (`fn`).
     ///
     /// E.g., `fn foo(bar: usize) -> usize { .. }`.
-    Fn(FnSig, Generics, Option<P<Block>>),
+    Fn(Defaultness, FnSig, Generics, Option<P<Block>>),
     /// A module declaration (`mod`).
     ///
     /// E.g., `mod foo;` or `mod foo { .. }`.
@@ -2527,7 +2524,7 @@ pub enum ItemKind {
     /// A type alias (`type`).
     ///
     /// E.g., `type Foo = Bar<u8>;`.
-    TyAlias(Generics, GenericBounds, Option<P<Ty>>),
+    TyAlias(Defaultness, Generics, GenericBounds, Option<P<Ty>>),
     /// An enum definition (`enum`).
     ///
     /// E.g., `enum Foo<A, B> { C<A>, D<B> }`.
@@ -2607,8 +2604,8 @@ impl ItemKind {
 
     pub fn generics(&self) -> Option<&Generics> {
         match self {
-            Self::Fn(_, generics, _)
-            | Self::TyAlias(generics, ..)
+            Self::Fn(_, _, generics, _)
+            | Self::TyAlias(_, generics, ..)
             | Self::Enum(_, generics)
             | Self::Struct(_, generics)
             | Self::Union(_, generics)
@@ -2640,13 +2637,22 @@ pub type AssocItem = Item<AssocItemKind>;
 pub enum AssocItemKind {
     /// A constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`.
     /// If `def` is parsed, then the constant is provided, and otherwise required.
-    Const(P<Ty>, Option<P<Expr>>),
+    Const(Defaultness, P<Ty>, Option<P<Expr>>),
     /// A static item (`static FOO: u8`).
     Static(P<Ty>, Mutability, Option<P<Expr>>),
     /// A function.
-    Fn(FnSig, Generics, Option<P<Block>>),
+    Fn(Defaultness, FnSig, Generics, Option<P<Block>>),
     /// A type.
-    TyAlias(Generics, GenericBounds, Option<P<Ty>>),
+    TyAlias(Defaultness, Generics, GenericBounds, Option<P<Ty>>),
     /// A macro expanding to items.
     Macro(Mac),
 }
+
+impl AssocItemKind {
+    pub fn defaultness(&self) -> Defaultness {
+        match *self {
+            Self::Const(def, ..) | Self::Fn(def, ..) | Self::TyAlias(def, ..) => def,
+            Self::Macro(..) | Self::Static(..) => Defaultness::Final,
+        }
+    }
+}
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 048026cbb248e..05bb07cd4b90a 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -890,11 +890,11 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
     match kind {
         ItemKind::ExternCrate(_orig_name) => {}
         ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
-        ItemKind::Static(ty, _, expr) | ItemKind::Const(ty, expr) => {
+        ItemKind::Static(ty, _, expr) | ItemKind::Const(_, ty, expr) => {
             vis.visit_ty(ty);
             visit_opt(expr, |expr| vis.visit_expr(expr));
         }
-        ItemKind::Fn(sig, generics, body) => {
+        ItemKind::Fn(_, sig, generics, body) => {
             visit_fn_sig(sig, vis);
             vis.visit_generics(generics);
             visit_opt(body, |body| vis.visit_block(body));
@@ -902,7 +902,7 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
         ItemKind::Mod(m) => vis.visit_mod(m),
         ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
         ItemKind::GlobalAsm(_ga) => {}
-        ItemKind::TyAlias(generics, bounds, ty) => {
+        ItemKind::TyAlias(_, generics, bounds, ty) => {
             vis.visit_generics(generics);
             visit_bounds(bounds, vis);
             visit_opt(ty, |ty| vis.visit_ty(ty));
@@ -948,7 +948,7 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
     mut item: P<AssocItem>,
     visitor: &mut T,
 ) -> SmallVec<[P<AssocItem>; 1]> {
-    let Item { id, ident, vis, defaultness: _, attrs, kind, span, tokens: _ } = item.deref_mut();
+    let Item { id, ident, vis, attrs, kind, span, tokens: _ } = item.deref_mut();
     walk_nested_item(visitor, id, span, ident, vis, attrs, kind);
     smallvec![item]
 }
@@ -967,16 +967,16 @@ pub fn walk_nested_item(
     visitor.visit_vis(vis);
     visit_attrs(attrs, visitor);
     match kind {
-        AssocItemKind::Const(ty, expr) | AssocItemKind::Static(ty, _, expr) => {
+        AssocItemKind::Const(_, ty, expr) | AssocItemKind::Static(ty, _, expr) => {
             visitor.visit_ty(ty);
             visit_opt(expr, |expr| visitor.visit_expr(expr));
         }
-        AssocItemKind::Fn(sig, generics, body) => {
+        AssocItemKind::Fn(_, sig, generics, body) => {
             visitor.visit_generics(generics);
             visit_fn_sig(sig, visitor);
             visit_opt(body, |body| visitor.visit_block(body));
         }
-        AssocItemKind::TyAlias(generics, bounds, ty) => {
+        AssocItemKind::TyAlias(_, generics, bounds, ty) => {
             visitor.visit_generics(generics);
             visit_bounds(bounds, visitor);
             visit_opt(ty, |ty| visitor.visit_ty(ty));
@@ -1003,7 +1003,6 @@ pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
             attrs,
             id: DUMMY_NODE_ID,
             vis: respan(span.shrink_to_lo(), VisibilityKind::Public),
-            defaultness: Defaultness::Final,
             span,
             kind: ItemKind::Mod(module),
             tokens: None,
@@ -1031,7 +1030,7 @@ pub fn noop_flat_map_item<T: MutVisitor>(
     mut item: P<Item>,
     visitor: &mut T,
 ) -> SmallVec<[P<Item>; 1]> {
-    let Item { ident, attrs, id, kind, vis, defaultness: _, span, tokens: _ } = item.deref_mut();
+    let Item { ident, attrs, id, kind, vis, span, tokens: _ } = item.deref_mut();
     visitor.visit_ident(ident);
     visit_attrs(attrs, visitor);
     visitor.visit_id(id);
@@ -1049,7 +1048,7 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
     mut item: P<ForeignItem>,
     visitor: &mut T,
 ) -> SmallVec<[P<ForeignItem>; 1]> {
-    let Item { ident, attrs, id, kind, vis, defaultness: _, span, tokens: _ } = item.deref_mut();
+    let Item { ident, attrs, id, kind, vis, span, tokens: _ } = item.deref_mut();
     walk_nested_item(visitor, id, span, ident, vis, attrs, kind);
     smallvec![item]
 }
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 244cb80064ebc..96149ad7947ce 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -298,11 +298,11 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             }
         }
         ItemKind::Use(ref use_tree) => visitor.visit_use_tree(use_tree, item.id, false),
-        ItemKind::Static(ref typ, _, ref expr) | ItemKind::Const(ref typ, ref expr) => {
+        ItemKind::Static(ref typ, _, ref expr) | ItemKind::Const(_, ref typ, ref expr) => {
             visitor.visit_ty(typ);
             walk_list!(visitor, visit_expr, expr);
         }
-        ItemKind::Fn(ref sig, ref generics, ref body) => {
+        ItemKind::Fn(_, ref sig, ref generics, ref body) => {
             visitor.visit_generics(generics);
             let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
             visitor.visit_fn(kind, item.span, item.id)
@@ -312,7 +312,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             walk_list!(visitor, visit_foreign_item, &foreign_module.items);
         }
         ItemKind::GlobalAsm(ref ga) => visitor.visit_global_asm(ga),
-        ItemKind::TyAlias(ref generics, ref bounds, ref ty) => {
+        ItemKind::TyAlias(_, ref generics, ref bounds, ref ty) => {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_ty, ty);
@@ -526,7 +526,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
 }
 
 pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) {
-    let ForeignItem { id, span, ident, vis, defaultness: _, attrs, kind, tokens: _ } = item;
+    let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item;
     walk_nested_item(visitor, *id, *span, *ident, vis, attrs, kind, FnCtxt::Foreign);
 }
 
@@ -610,7 +610,7 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Spa
 }
 
 pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, ctxt: AssocCtxt) {
-    let AssocItem { id, span, ident, vis, attrs, kind, tokens: _, defaultness: _ } = item;
+    let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item;
     walk_nested_item(visitor, *id, *span, *ident, vis, attrs, kind, FnCtxt::Assoc(ctxt));
 }
 
@@ -628,16 +628,16 @@ fn walk_nested_item<'a, V: Visitor<'a>>(
     visitor.visit_ident(ident);
     walk_list!(visitor, visit_attribute, attrs);
     match kind {
-        AssocItemKind::Const(ty, expr) | AssocItemKind::Static(ty, _, expr) => {
+        AssocItemKind::Const(_, ty, expr) | AssocItemKind::Static(ty, _, expr) => {
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_expr, expr);
         }
-        AssocItemKind::Fn(sig, generics, body) => {
+        AssocItemKind::Fn(_, sig, generics, body) => {
             visitor.visit_generics(generics);
             let kind = FnKind::Fn(ctxt, ident, sig, vis, body.as_deref());
             visitor.visit_fn(kind, span, id);
         }
-        AssocItemKind::TyAlias(generics, bounds, ty) => {
+        AssocItemKind::TyAlias(_, generics, bounds, ty) => {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_ty, ty);
diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout
index bbda63955e0b7..35e418696f17c 100644
--- a/src/test/ui/ast-json/ast-json-output.stdout
+++ b/src/test/ui/ast-json/ast-json-output.stdout
@@ -1 +1 @@
-{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"defaultness":"Final","kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0},"proc_macros":[]}
+{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0},"proc_macros":[]}
diff --git a/src/test/ui/parser/assoc-static-semantic-fail.rs b/src/test/ui/parser/assoc-static-semantic-fail.rs
index da4015a4620ff..215a292131521 100644
--- a/src/test/ui/parser/assoc-static-semantic-fail.rs
+++ b/src/test/ui/parser/assoc-static-semantic-fail.rs
@@ -13,9 +13,11 @@ impl S {
     //~| ERROR associated constant in `impl` without body
     default static IC: u8 = 0;
     //~^ ERROR associated `static` items are not allowed
+    //~| ERROR a static item cannot be `default`
     pub(crate) default static ID: u8;
     //~^ ERROR associated `static` items are not allowed
     //~| ERROR associated constant in `impl` without body
+    //~| ERROR a static item cannot be `default`
 }
 
 trait T {
@@ -25,11 +27,11 @@ trait T {
     //~^ ERROR associated `static` items are not allowed
     default static TC: u8 = 0;
     //~^ ERROR associated `static` items are not allowed
-    //~| ERROR `default` is only allowed on items in
+    //~| ERROR a static item cannot be `default`
     pub(crate) default static TD: u8;
     //~^ ERROR associated `static` items are not allowed
-    //~| ERROR `default` is only allowed on items in
     //~| ERROR unnecessary visibility qualifier
+    //~| ERROR a static item cannot be `default`
 }
 
 impl T for S {
@@ -40,8 +42,10 @@ impl T for S {
     //~| ERROR associated constant in `impl` without body
     default static TC: u8 = 0;
     //~^ ERROR associated `static` items are not allowed
+    //~| ERROR a static item cannot be `default`
     pub default static TD: u8;
     //~^ ERROR associated `static` items are not allowed
     //~| ERROR associated constant in `impl` without body
     //~| ERROR unnecessary visibility qualifier
+    //~| ERROR a static item cannot be `default`
 }
diff --git a/src/test/ui/parser/assoc-static-semantic-fail.stderr b/src/test/ui/parser/assoc-static-semantic-fail.stderr
index ca05b05e9b110..612297c9cd8b1 100644
--- a/src/test/ui/parser/assoc-static-semantic-fail.stderr
+++ b/src/test/ui/parser/assoc-static-semantic-fail.stderr
@@ -10,62 +10,110 @@ error: associated `static` items are not allowed
 LL |     static IB: u8;
    |     ^^^^^^^^^^^^^^
 
+error: a static item cannot be `default`
+  --> $DIR/assoc-static-semantic-fail.rs:14:5
+   |
+LL |     default static IC: u8 = 0;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: associated `static` items are not allowed
   --> $DIR/assoc-static-semantic-fail.rs:14:5
    |
 LL |     default static IC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: a static item cannot be `default`
+  --> $DIR/assoc-static-semantic-fail.rs:17:16
+   |
+LL |     pub(crate) default static ID: u8;
+   |                ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:16:5
+  --> $DIR/assoc-static-semantic-fail.rs:17:5
    |
 LL |     pub(crate) default static ID: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:22:5
+  --> $DIR/assoc-static-semantic-fail.rs:24:5
    |
 LL |     static TA: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:24:5
+  --> $DIR/assoc-static-semantic-fail.rs:26:5
    |
 LL |     static TB: u8;
    |     ^^^^^^^^^^^^^^
 
+error: a static item cannot be `default`
+  --> $DIR/assoc-static-semantic-fail.rs:28:5
+   |
+LL |     default static TC: u8 = 0;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:26:5
+  --> $DIR/assoc-static-semantic-fail.rs:28:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: a static item cannot be `default`
+  --> $DIR/assoc-static-semantic-fail.rs:31:16
+   |
+LL |     pub(crate) default static TD: u8;
+   |                ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:29:5
+  --> $DIR/assoc-static-semantic-fail.rs:31:5
    |
 LL |     pub(crate) default static TD: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:36:5
+  --> $DIR/assoc-static-semantic-fail.rs:38:5
    |
 LL |     static TA: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:38:5
+  --> $DIR/assoc-static-semantic-fail.rs:40:5
    |
 LL |     static TB: u8;
    |     ^^^^^^^^^^^^^^
 
+error: a static item cannot be `default`
+  --> $DIR/assoc-static-semantic-fail.rs:43:5
+   |
+LL |     default static TC: u8 = 0;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:41:5
+  --> $DIR/assoc-static-semantic-fail.rs:43:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: a static item cannot be `default`
+  --> $DIR/assoc-static-semantic-fail.rs:46:9
+   |
+LL |     pub default static TD: u8;
+   |         ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:43:5
+  --> $DIR/assoc-static-semantic-fail.rs:46:5
    |
 LL |     pub default static TD: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -79,37 +127,21 @@ LL |     static IB: u8;
    |                  help: provide a definition for the constant: `= <expr>;`
 
 error: associated constant in `impl` without body
-  --> $DIR/assoc-static-semantic-fail.rs:16:5
+  --> $DIR/assoc-static-semantic-fail.rs:17:5
    |
 LL |     pub(crate) default static ID: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
    |                                     |
    |                                     help: provide a definition for the constant: `= <expr>;`
 
-error: `default` is only allowed on items in `impl` definitions
-  --> $DIR/assoc-static-semantic-fail.rs:26:5
-   |
-LL |     default static TC: u8 = 0;
-   |     -------^^^^^^^^^^^^^^^^^^^
-   |     |
-   |     `default` because of this
-
-error: `default` is only allowed on items in `impl` definitions
-  --> $DIR/assoc-static-semantic-fail.rs:29:5
-   |
-LL |     pub(crate) default static TD: u8;
-   |     ^^^^^^^^^^^-------^^^^^^^^^^^^^^^
-   |                |
-   |                `default` because of this
-
 error[E0449]: unnecessary visibility qualifier
-  --> $DIR/assoc-static-semantic-fail.rs:29:5
+  --> $DIR/assoc-static-semantic-fail.rs:31:5
    |
 LL |     pub(crate) default static TD: u8;
    |     ^^^^^^^^^^
 
 error: associated constant in `impl` without body
-  --> $DIR/assoc-static-semantic-fail.rs:38:5
+  --> $DIR/assoc-static-semantic-fail.rs:40:5
    |
 LL |     static TB: u8;
    |     ^^^^^^^^^^^^^-
@@ -117,7 +149,7 @@ LL |     static TB: u8;
    |                  help: provide a definition for the constant: `= <expr>;`
 
 error: associated constant in `impl` without body
-  --> $DIR/assoc-static-semantic-fail.rs:43:5
+  --> $DIR/assoc-static-semantic-fail.rs:46:5
    |
 LL |     pub default static TD: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -125,11 +157,11 @@ LL |     pub default static TD: u8;
    |                              help: provide a definition for the constant: `= <expr>;`
 
 error[E0449]: unnecessary visibility qualifier
-  --> $DIR/assoc-static-semantic-fail.rs:43:5
+  --> $DIR/assoc-static-semantic-fail.rs:46:5
    |
 LL |     pub default static TD: u8;
    |     ^^^ `pub` not permitted here because it's implied
 
-error: aborting due to 20 previous errors
+error: aborting due to 24 previous errors
 
 For more information about this error, try `rustc --explain E0449`.
diff --git a/src/test/ui/parser/assoc-static-syntactic-fail.rs b/src/test/ui/parser/assoc-static-syntactic-fail.rs
index 8f042767e5503..492f2ea16ef57 100644
--- a/src/test/ui/parser/assoc-static-syntactic-fail.rs
+++ b/src/test/ui/parser/assoc-static-syntactic-fail.rs
@@ -7,7 +7,9 @@ impl S {
     static IA: u8 = 0; //~ ERROR associated `static` items are not allowed
     static IB: u8; //~ ERROR associated `static` items are not allowed
     default static IC: u8 = 0; //~ ERROR associated `static` items are not allowed
+    //~^ ERROR a static item cannot be `default`
     pub(crate) default static ID: u8; //~ ERROR associated `static` items are not allowed
+    //~^ ERROR a static item cannot be `default`
 }
 
 #[cfg(FALSE)]
@@ -15,7 +17,9 @@ trait T {
     static TA: u8 = 0; //~ ERROR associated `static` items are not allowed
     static TB: u8; //~ ERROR associated `static` items are not allowed
     default static TC: u8 = 0; //~ ERROR associated `static` items are not allowed
+    //~^ ERROR a static item cannot be `default`
     pub(crate) default static TD: u8; //~ ERROR associated `static` items are not allowed
+    //~^ ERROR a static item cannot be `default`
 }
 
 #[cfg(FALSE)]
@@ -23,5 +27,7 @@ impl T for S {
     static TA: u8 = 0; //~ ERROR associated `static` items are not allowed
     static TB: u8; //~ ERROR associated `static` items are not allowed
     default static TC: u8 = 0; //~ ERROR associated `static` items are not allowed
+    //~^ ERROR a static item cannot be `default`
     pub default static TD: u8; //~ ERROR associated `static` items are not allowed
+    //~^ ERROR a static item cannot be `default`
 }
diff --git a/src/test/ui/parser/assoc-static-syntactic-fail.stderr b/src/test/ui/parser/assoc-static-syntactic-fail.stderr
index bb1e5c4be2e9c..e972361451235 100644
--- a/src/test/ui/parser/assoc-static-syntactic-fail.stderr
+++ b/src/test/ui/parser/assoc-static-syntactic-fail.stderr
@@ -10,65 +10,113 @@ error: associated `static` items are not allowed
 LL |     static IB: u8;
    |     ^^^^^^^^^^^^^^
 
+error: a static item cannot be `default`
+  --> $DIR/assoc-static-syntactic-fail.rs:9:5
+   |
+LL |     default static IC: u8 = 0;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: associated `static` items are not allowed
   --> $DIR/assoc-static-syntactic-fail.rs:9:5
    |
 LL |     default static IC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: a static item cannot be `default`
+  --> $DIR/assoc-static-syntactic-fail.rs:11:16
+   |
+LL |     pub(crate) default static ID: u8;
+   |                ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-syntactic-fail.rs:10:5
+  --> $DIR/assoc-static-syntactic-fail.rs:11:5
    |
 LL |     pub(crate) default static ID: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-syntactic-fail.rs:15:5
+  --> $DIR/assoc-static-syntactic-fail.rs:17:5
    |
 LL |     static TA: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-syntactic-fail.rs:16:5
+  --> $DIR/assoc-static-syntactic-fail.rs:18:5
    |
 LL |     static TB: u8;
    |     ^^^^^^^^^^^^^^
 
+error: a static item cannot be `default`
+  --> $DIR/assoc-static-syntactic-fail.rs:19:5
+   |
+LL |     default static TC: u8 = 0;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-syntactic-fail.rs:17:5
+  --> $DIR/assoc-static-syntactic-fail.rs:19:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: a static item cannot be `default`
+  --> $DIR/assoc-static-syntactic-fail.rs:21:16
+   |
+LL |     pub(crate) default static TD: u8;
+   |                ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-syntactic-fail.rs:18:5
+  --> $DIR/assoc-static-syntactic-fail.rs:21:5
    |
 LL |     pub(crate) default static TD: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-syntactic-fail.rs:23:5
+  --> $DIR/assoc-static-syntactic-fail.rs:27:5
    |
 LL |     static TA: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-syntactic-fail.rs:24:5
+  --> $DIR/assoc-static-syntactic-fail.rs:28:5
    |
 LL |     static TB: u8;
    |     ^^^^^^^^^^^^^^
 
+error: a static item cannot be `default`
+  --> $DIR/assoc-static-syntactic-fail.rs:29:5
+   |
+LL |     default static TC: u8 = 0;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-syntactic-fail.rs:25:5
+  --> $DIR/assoc-static-syntactic-fail.rs:29:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: a static item cannot be `default`
+  --> $DIR/assoc-static-syntactic-fail.rs:31:9
+   |
+LL |     pub default static TD: u8;
+   |         ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-syntactic-fail.rs:26:5
+  --> $DIR/assoc-static-syntactic-fail.rs:31:5
    |
 LL |     pub default static TD: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 12 previous errors
+error: aborting due to 18 previous errors
 
diff --git a/src/test/ui/parser/default-on-wrong-item-kind.rs b/src/test/ui/parser/default-on-wrong-item-kind.rs
index 47b9e34305f21..982ee6d83b3b8 100644
--- a/src/test/ui/parser/default-on-wrong-item-kind.rs
+++ b/src/test/ui/parser/default-on-wrong-item-kind.rs
@@ -6,135 +6,135 @@ fn main() {}
 
 #[cfg(FALSE)]
 mod free_items {
-    default extern crate foo; //~ ERROR item cannot be `default`
-    default use foo; //~ ERROR item cannot be `default`
-    default static foo: u8; //~ ERROR item cannot be `default`
-    default const foo: u8; //~ ERROR item cannot be `default`
-    default fn foo(); //~ ERROR item cannot be `default`
-    default mod foo {} //~ ERROR item cannot be `default`
-    default extern "C" {} //~ ERROR item cannot be `default`
-    default type foo = u8; //~ ERROR item cannot be `default`
-    default enum foo {} //~ ERROR item cannot be `default`
-    default struct foo {} //~ ERROR item cannot be `default`
-    default union foo {} //~ ERROR item cannot be `default`
-    default trait foo {} //~ ERROR item cannot be `default`
-    default trait foo = Ord; //~ ERROR item cannot be `default`
+    default extern crate foo; //~ ERROR an extern crate cannot be `default`
+    default use foo; //~ ERROR a `use` import cannot be `default`
+    default static foo: u8; //~ ERROR a static item cannot be `default`
+    default const foo: u8;
+    default fn foo();
+    default mod foo {} //~ ERROR a module cannot be `default`
+    default extern "C" {} //~ ERROR an extern block cannot be `default`
+    default type foo = u8;
+    default enum foo {} //~ ERROR an enum cannot be `default`
+    default struct foo {} //~ ERROR a struct cannot be `default`
+    default union foo {} //~ ERROR a union cannot be `default`
+    default trait foo {} //~ ERROR a trait cannot be `default`
+    default trait foo = Ord; //~ ERROR a trait alias cannot be `default`
     default impl foo {}
     default!();
     default::foo::bar!();
-    default default!(); //~ ERROR item cannot be `default`
-    default default::foo::bar!(); //~ ERROR item cannot be `default`
-    default macro foo {} //~ ERROR item cannot be `default`
-    default macro_rules! foo {} //~ ERROR item cannot be `default`
+    default default!(); //~ ERROR an item macro invocation cannot be `default`
+    default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default`
+    default macro foo {} //~ ERROR a macro definition cannot be `default`
+    default macro_rules! foo {} //~ ERROR a macro definition cannot be `default`
 }
 
 #[cfg(FALSE)]
 extern "C" {
-    default extern crate foo; //~ ERROR item cannot be `default`
+    default extern crate foo; //~ ERROR an extern crate cannot be `default`
     //~^ ERROR extern crate not supported in `extern` block
-    default use foo; //~ ERROR item cannot be `default`
+    default use foo; //~ ERROR a `use` import cannot be `default`
     //~^ ERROR `use` import not supported in `extern` block
-    default static foo: u8; //~ ERROR item cannot be `default`
-    default const foo: u8; //~ ERROR item cannot be `default`
+    default static foo: u8; //~ ERROR a static item cannot be `default`
+    default const foo: u8;
     //~^ ERROR extern items cannot be `const`
-    default fn foo(); //~ ERROR item cannot be `default`
-    default mod foo {} //~ ERROR item cannot be `default`
+    default fn foo();
+    default mod foo {} //~ ERROR a module cannot be `default`
     //~^ ERROR module not supported in `extern` block
-    default extern "C" {} //~ ERROR item cannot be `default`
+    default extern "C" {} //~ ERROR an extern block cannot be `default`
     //~^ ERROR extern block not supported in `extern` block
-    default type foo = u8; //~ ERROR item cannot be `default`
-    default enum foo {} //~ ERROR item cannot be `default`
+    default type foo = u8;
+    default enum foo {} //~ ERROR an enum cannot be `default`
     //~^ ERROR enum not supported in `extern` block
-    default struct foo {} //~ ERROR item cannot be `default`
+    default struct foo {} //~ ERROR a struct cannot be `default`
     //~^ ERROR struct not supported in `extern` block
-    default union foo {} //~ ERROR item cannot be `default`
+    default union foo {} //~ ERROR a union cannot be `default`
     //~^ ERROR union not supported in `extern` block
-    default trait foo {} //~ ERROR item cannot be `default`
+    default trait foo {} //~ ERROR a trait cannot be `default`
     //~^ ERROR trait not supported in `extern` block
-    default trait foo = Ord; //~ ERROR item cannot be `default`
+    default trait foo = Ord; //~ ERROR a trait alias cannot be `default`
     //~^ ERROR trait alias not supported in `extern` block
     default impl foo {}
     //~^ ERROR implementation not supported in `extern` block
     default!();
     default::foo::bar!();
-    default default!(); //~ ERROR item cannot be `default`
-    default default::foo::bar!(); //~ ERROR item cannot be `default`
-    default macro foo {} //~ ERROR item cannot be `default`
+    default default!(); //~ ERROR an item macro invocation cannot be `default`
+    default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default`
+    default macro foo {} //~ ERROR a macro definition cannot be `default`
     //~^ ERROR macro definition not supported in `extern` block
-    default macro_rules! foo {} //~ ERROR item cannot be `default`
+    default macro_rules! foo {} //~ ERROR a macro definition cannot be `default`
     //~^ ERROR macro definition not supported in `extern` block
 }
 
 #[cfg(FALSE)]
 impl S {
-    default extern crate foo;
+    default extern crate foo; //~ ERROR an extern crate cannot be `default`
     //~^ ERROR extern crate not supported in `trait` or `impl`
-    default use foo;
+    default use foo; //~ ERROR a `use` import cannot be `default`
     //~^ ERROR `use` import not supported in `trait` or `impl`
-    default static foo: u8;
+    default static foo: u8; //~ ERROR a static item cannot be `default`
     //~^ ERROR associated `static` items are not allowed
     default const foo: u8;
     default fn foo();
-    default mod foo {}
+    default mod foo {}//~ ERROR a module cannot be `default`
     //~^ ERROR module not supported in `trait` or `impl`
-    default extern "C" {}
+    default extern "C" {} //~ ERROR an extern block cannot be `default`
     //~^ ERROR extern block not supported in `trait` or `impl`
     default type foo = u8;
-    default enum foo {}
+    default enum foo {} //~ ERROR an enum cannot be `default`
     //~^ ERROR enum not supported in `trait` or `impl`
-    default struct foo {}
+    default struct foo {} //~ ERROR a struct cannot be `default`
     //~^ ERROR struct not supported in `trait` or `impl`
-    default union foo {}
+    default union foo {} //~ ERROR a union cannot be `default`
     //~^ ERROR union not supported in `trait` or `impl`
-    default trait foo {}
+    default trait foo {} //~ ERROR a trait cannot be `default`
     //~^ ERROR trait not supported in `trait` or `impl`
-    default trait foo = Ord;
+    default trait foo = Ord; //~ ERROR a trait alias cannot be `default`
     //~^ ERROR trait alias not supported in `trait` or `impl`
     default impl foo {}
     //~^ ERROR implementation not supported in `trait` or `impl`
     default!();
     default::foo::bar!();
-    default default!();
-    default default::foo::bar!();
-    default macro foo {}
+    default default!(); //~ ERROR an item macro invocation cannot be `default`
+    default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default`
+    default macro foo {} //~ ERROR a macro definition cannot be `default`
     //~^ ERROR macro definition not supported in `trait` or `impl`
-    default macro_rules! foo {}
+    default macro_rules! foo {} //~ ERROR a macro definition cannot be `default`
     //~^ ERROR macro definition not supported in `trait` or `impl`
 }
 
 #[cfg(FALSE)]
 trait T {
-    default extern crate foo;
+    default extern crate foo; //~ ERROR an extern crate cannot be `default`
     //~^ ERROR extern crate not supported in `trait` or `impl`
-    default use foo;
+    default use foo; //~ ERROR a `use` import cannot be `default`
     //~^ ERROR `use` import not supported in `trait` or `impl`
-    default static foo: u8;
+    default static foo: u8; //~ ERROR a static item cannot be `default`
     //~^ ERROR associated `static` items are not allowed
     default const foo: u8;
     default fn foo();
-    default mod foo {}
+    default mod foo {}//~ ERROR a module cannot be `default`
     //~^ ERROR module not supported in `trait` or `impl`
-    default extern "C" {}
+    default extern "C" {} //~ ERROR an extern block cannot be `default`
     //~^ ERROR extern block not supported in `trait` or `impl`
     default type foo = u8;
-    default enum foo {}
+    default enum foo {} //~ ERROR an enum cannot be `default`
     //~^ ERROR enum not supported in `trait` or `impl`
-    default struct foo {}
+    default struct foo {} //~ ERROR a struct cannot be `default`
     //~^ ERROR struct not supported in `trait` or `impl`
-    default union foo {}
+    default union foo {} //~ ERROR a union cannot be `default`
     //~^ ERROR union not supported in `trait` or `impl`
-    default trait foo {}
+    default trait foo {} //~ ERROR a trait cannot be `default`
     //~^ ERROR trait not supported in `trait` or `impl`
-    default trait foo = Ord;
+    default trait foo = Ord; //~ ERROR a trait alias cannot be `default`
     //~^ ERROR trait alias not supported in `trait` or `impl`
     default impl foo {}
     //~^ ERROR implementation not supported in `trait` or `impl`
     default!();
     default::foo::bar!();
-    default default!();
-    default default::foo::bar!();
-    default macro foo {}
+    default default!(); //~ ERROR an item macro invocation cannot be `default`
+    default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default`
+    default macro foo {} //~ ERROR a macro definition cannot be `default`
     //~^ ERROR macro definition not supported in `trait` or `impl`
-    default macro_rules! foo {}
+    default macro_rules! foo {} //~ ERROR a macro definition cannot be `default`
     //~^ ERROR macro definition not supported in `trait` or `impl`
 }
diff --git a/src/test/ui/parser/default-on-wrong-item-kind.stderr b/src/test/ui/parser/default-on-wrong-item-kind.stderr
index ec569b43d700d..d0f3ad4d72b04 100644
--- a/src/test/ui/parser/default-on-wrong-item-kind.stderr
+++ b/src/test/ui/parser/default-on-wrong-item-kind.stderr
@@ -1,4 +1,4 @@
-error: item cannot be `default`
+error: an extern crate cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:9:5
    |
 LL |     default extern crate foo;
@@ -6,7 +6,7 @@ LL |     default extern crate foo;
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item cannot be `default`
+error: a `use` import cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:10:5
    |
 LL |     default use foo;
@@ -14,7 +14,7 @@ LL |     default use foo;
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item cannot be `default`
+error: a static item cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:11:5
    |
 LL |     default static foo: u8;
@@ -22,23 +22,7 @@ LL |     default static foo: u8;
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:12:5
-   |
-LL |     default const foo: u8;
-   |     ^^^^^^^ `default` because of this
-   |
-   = note: only associated `fn`, `const`, and `type` items can be `default`
-
-error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:13:5
-   |
-LL |     default fn foo();
-   |     ^^^^^^^ `default` because of this
-   |
-   = note: only associated `fn`, `const`, and `type` items can be `default`
-
-error: item cannot be `default`
+error: a module cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:14:5
    |
 LL |     default mod foo {}
@@ -46,7 +30,7 @@ LL |     default mod foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item cannot be `default`
+error: an extern block cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:15:5
    |
 LL |     default extern "C" {}
@@ -54,15 +38,7 @@ LL |     default extern "C" {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:16:5
-   |
-LL |     default type foo = u8;
-   |     ^^^^^^^ `default` because of this
-   |
-   = note: only associated `fn`, `const`, and `type` items can be `default`
-
-error: item cannot be `default`
+error: an enum cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:17:5
    |
 LL |     default enum foo {}
@@ -70,7 +46,7 @@ LL |     default enum foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item cannot be `default`
+error: a struct cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:18:5
    |
 LL |     default struct foo {}
@@ -78,7 +54,7 @@ LL |     default struct foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item cannot be `default`
+error: a union cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:19:5
    |
 LL |     default union foo {}
@@ -86,7 +62,7 @@ LL |     default union foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item cannot be `default`
+error: a trait cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:20:5
    |
 LL |     default trait foo {}
@@ -94,7 +70,7 @@ LL |     default trait foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item cannot be `default`
+error: a trait alias cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:21:5
    |
 LL |     default trait foo = Ord;
@@ -102,7 +78,7 @@ LL |     default trait foo = Ord;
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item cannot be `default`
+error: an item macro invocation cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:25:5
    |
 LL |     default default!();
@@ -110,7 +86,7 @@ LL |     default default!();
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item cannot be `default`
+error: an item macro invocation cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:26:5
    |
 LL |     default default::foo::bar!();
@@ -118,7 +94,7 @@ LL |     default default::foo::bar!();
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item cannot be `default`
+error: a macro definition cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:27:5
    |
 LL |     default macro foo {}
@@ -126,7 +102,7 @@ LL |     default macro foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item cannot be `default`
+error: a macro definition cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:28:5
    |
 LL |     default macro_rules! foo {}
@@ -134,7 +110,7 @@ LL |     default macro_rules! foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item cannot be `default`
+error: an extern crate cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:33:5
    |
 LL |     default extern crate foo;
@@ -148,7 +124,7 @@ error: extern crate not supported in `extern` block
 LL |     default extern crate foo;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: item cannot be `default`
+error: a `use` import cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:35:5
    |
 LL |     default use foo;
@@ -162,7 +138,7 @@ error: `use` import not supported in `extern` block
 LL |     default use foo;
    |     ^^^^^^^^^^^^^^^^
 
-error: item cannot be `default`
+error: a static item cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:37:5
    |
 LL |     default static foo: u8;
@@ -170,14 +146,6 @@ LL |     default static foo: u8;
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:38:5
-   |
-LL |     default const foo: u8;
-   |     ^^^^^^^ `default` because of this
-   |
-   = note: only associated `fn`, `const`, and `type` items can be `default`
-
 error: extern items cannot be `const`
   --> $DIR/default-on-wrong-item-kind.rs:38:19
    |
@@ -188,15 +156,7 @@ LL |     default const foo: u8;
    |
    = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
 
-error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:40:5
-   |
-LL |     default fn foo();
-   |     ^^^^^^^ `default` because of this
-   |
-   = note: only associated `fn`, `const`, and `type` items can be `default`
-
-error: item cannot be `default`
+error: a module cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:41:5
    |
 LL |     default mod foo {}
@@ -210,7 +170,7 @@ error: module not supported in `extern` block
 LL |     default mod foo {}
    |     ^^^^^^^^^^^^^^^
 
-error: item cannot be `default`
+error: an extern block cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:43:5
    |
 LL |     default extern "C" {}
@@ -224,15 +184,7 @@ error: extern block not supported in `extern` block
 LL |     default extern "C" {}
    |     ^^^^^^^^^^^^^^^^^^
 
-error: item cannot be `default`
-  --> $DIR/default-on-wrong-item-kind.rs:45:5
-   |
-LL |     default type foo = u8;
-   |     ^^^^^^^ `default` because of this
-   |
-   = note: only associated `fn`, `const`, and `type` items can be `default`
-
-error: item cannot be `default`
+error: an enum cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:46:5
    |
 LL |     default enum foo {}
@@ -246,7 +198,7 @@ error: enum not supported in `extern` block
 LL |     default enum foo {}
    |     ^^^^^^^^^^^^^^^^
 
-error: item cannot be `default`
+error: a struct cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:48:5
    |
 LL |     default struct foo {}
@@ -260,7 +212,7 @@ error: struct not supported in `extern` block
 LL |     default struct foo {}
    |     ^^^^^^^^^^^^^^^^^^
 
-error: item cannot be `default`
+error: a union cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:50:5
    |
 LL |     default union foo {}
@@ -274,7 +226,7 @@ error: union not supported in `extern` block
 LL |     default union foo {}
    |     ^^^^^^^^^^^^^^^^^
 
-error: item cannot be `default`
+error: a trait cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:52:5
    |
 LL |     default trait foo {}
@@ -288,7 +240,7 @@ error: trait not supported in `extern` block
 LL |     default trait foo {}
    |     ^^^^^^^^^^^^^^^^^
 
-error: item cannot be `default`
+error: a trait alias cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:54:5
    |
 LL |     default trait foo = Ord;
@@ -308,7 +260,7 @@ error: implementation not supported in `extern` block
 LL |     default impl foo {}
    |     ^^^^^^^^^^^^^^^^
 
-error: item cannot be `default`
+error: an item macro invocation cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:60:5
    |
 LL |     default default!();
@@ -316,7 +268,7 @@ LL |     default default!();
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item cannot be `default`
+error: an item macro invocation cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:61:5
    |
 LL |     default default::foo::bar!();
@@ -324,7 +276,7 @@ LL |     default default::foo::bar!();
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: item cannot be `default`
+error: a macro definition cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:62:5
    |
 LL |     default macro foo {}
@@ -338,7 +290,7 @@ error: macro definition not supported in `extern` block
 LL |     default macro foo {}
    |     ^^^^^^^^^^^^^^^^^
 
-error: item cannot be `default`
+error: a macro definition cannot be `default`
   --> $DIR/default-on-wrong-item-kind.rs:64:5
    |
 LL |     default macro_rules! foo {}
@@ -352,60 +304,140 @@ error: macro definition not supported in `extern` block
 LL |     default macro_rules! foo {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: an extern crate cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:70:5
+   |
+LL |     default extern crate foo;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: extern crate not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:70:5
    |
 LL |     default extern crate foo;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: a `use` import cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:72:5
+   |
+LL |     default use foo;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: `use` import not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:72:5
    |
 LL |     default use foo;
    |     ^^^^^^^^^^^^^^^^
 
+error: a static item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:74:5
+   |
+LL |     default static foo: u8;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: associated `static` items are not allowed
   --> $DIR/default-on-wrong-item-kind.rs:74:5
    |
 LL |     default static foo: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
+error: a module cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:78:5
+   |
+LL |     default mod foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: module not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:78:5
    |
 LL |     default mod foo {}
    |     ^^^^^^^^^^^^^^^
 
+error: an extern block cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:80:5
+   |
+LL |     default extern "C" {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: extern block not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:80:5
    |
 LL |     default extern "C" {}
    |     ^^^^^^^^^^^^^^^^^^
 
+error: an enum cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:83:5
+   |
+LL |     default enum foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: enum not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:83:5
    |
 LL |     default enum foo {}
    |     ^^^^^^^^^^^^^^^^
 
+error: a struct cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:85:5
+   |
+LL |     default struct foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: struct not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:85:5
    |
 LL |     default struct foo {}
    |     ^^^^^^^^^^^^^^^^^^
 
+error: a union cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:87:5
+   |
+LL |     default union foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: union not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:87:5
    |
 LL |     default union foo {}
    |     ^^^^^^^^^^^^^^^^^
 
+error: a trait cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:89:5
+   |
+LL |     default trait foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: trait not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:89:5
    |
 LL |     default trait foo {}
    |     ^^^^^^^^^^^^^^^^^
 
+error: a trait alias cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:91:5
+   |
+LL |     default trait foo = Ord;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: trait alias not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:91:5
    |
@@ -418,72 +450,184 @@ error: implementation not supported in `trait` or `impl`
 LL |     default impl foo {}
    |     ^^^^^^^^^^^^^^^^
 
+error: an item macro invocation cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:97:5
+   |
+LL |     default default!();
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: an item macro invocation cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:98:5
+   |
+LL |     default default::foo::bar!();
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: a macro definition cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:99:5
+   |
+LL |     default macro foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: macro definition not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:99:5
    |
 LL |     default macro foo {}
    |     ^^^^^^^^^^^^^^^^^
 
+error: a macro definition cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:101:5
+   |
+LL |     default macro_rules! foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: macro definition not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:101:5
    |
 LL |     default macro_rules! foo {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: an extern crate cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:107:5
+   |
+LL |     default extern crate foo;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: extern crate not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:107:5
    |
 LL |     default extern crate foo;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: a `use` import cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:109:5
+   |
+LL |     default use foo;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: `use` import not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:109:5
    |
 LL |     default use foo;
    |     ^^^^^^^^^^^^^^^^
 
+error: a static item cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:111:5
+   |
+LL |     default static foo: u8;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: associated `static` items are not allowed
   --> $DIR/default-on-wrong-item-kind.rs:111:5
    |
 LL |     default static foo: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
+error: a module cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:115:5
+   |
+LL |     default mod foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: module not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:115:5
    |
 LL |     default mod foo {}
    |     ^^^^^^^^^^^^^^^
 
+error: an extern block cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:117:5
+   |
+LL |     default extern "C" {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: extern block not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:117:5
    |
 LL |     default extern "C" {}
    |     ^^^^^^^^^^^^^^^^^^
 
+error: an enum cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:120:5
+   |
+LL |     default enum foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: enum not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:120:5
    |
 LL |     default enum foo {}
    |     ^^^^^^^^^^^^^^^^
 
+error: a struct cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:122:5
+   |
+LL |     default struct foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: struct not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:122:5
    |
 LL |     default struct foo {}
    |     ^^^^^^^^^^^^^^^^^^
 
+error: a union cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:124:5
+   |
+LL |     default union foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: union not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:124:5
    |
 LL |     default union foo {}
    |     ^^^^^^^^^^^^^^^^^
 
+error: a trait cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:126:5
+   |
+LL |     default trait foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: trait not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:126:5
    |
 LL |     default trait foo {}
    |     ^^^^^^^^^^^^^^^^^
 
+error: a trait alias cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:128:5
+   |
+LL |     default trait foo = Ord;
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: trait alias not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:128:5
    |
@@ -496,17 +640,49 @@ error: implementation not supported in `trait` or `impl`
 LL |     default impl foo {}
    |     ^^^^^^^^^^^^^^^^
 
+error: an item macro invocation cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:134:5
+   |
+LL |     default default!();
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: an item macro invocation cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:135:5
+   |
+LL |     default default::foo::bar!();
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
+error: a macro definition cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:136:5
+   |
+LL |     default macro foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: macro definition not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:136:5
    |
 LL |     default macro foo {}
    |     ^^^^^^^^^^^^^^^^^
 
+error: a macro definition cannot be `default`
+  --> $DIR/default-on-wrong-item-kind.rs:138:5
+   |
+LL |     default macro_rules! foo {}
+   |     ^^^^^^^ `default` because of this
+   |
+   = note: only associated `fn`, `const`, and `type` items can be `default`
+
 error: macro definition not supported in `trait` or `impl`
   --> $DIR/default-on-wrong-item-kind.rs:138:5
    |
 LL |     default macro_rules! foo {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 73 previous errors
+error: aborting due to 95 previous errors
 

From e66a39bb65eb4a7fb1813993e10fc1af5bdac9bc Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sun, 23 Feb 2020 11:52:57 +0100
Subject: [PATCH 15/17] parse: tweak `parse_item_` for more reuse.

---
 src/librustc_parse/parser/item.rs | 24 +++++++-----------------
 src/librustc_parse/parser/stmt.rs |  4 ++--
 2 files changed, 9 insertions(+), 19 deletions(-)

diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 451f1fdf14a07..c85b4c22d010a 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -25,21 +25,15 @@ pub(super) type ItemInfo = (Ident, ItemKind);
 
 impl<'a> Parser<'a> {
     pub fn parse_item(&mut self) -> PResult<'a, Option<P<Item>>> {
-        let attrs = self.parse_outer_attributes()?;
-        self.parse_item_(attrs, true, false)
+        self.parse_item_(|_| true).map(|i| i.map(P))
     }
 
-    pub(super) fn parse_item_(
-        &mut self,
-        attrs: Vec<Attribute>,
-        macros_allowed: bool,
-        attributes_allowed: bool,
-    ) -> PResult<'a, Option<P<Item>>> {
-        let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed, |_| true)?;
-        Ok(item.map(P))
+    fn parse_item_(&mut self, req_name: ReqName) -> PResult<'a, Option<Item>> {
+        let attrs = self.parse_outer_attributes()?;
+        self.parse_item_common(attrs, true, false, req_name)
     }
 
-    fn parse_item_common(
+    pub(super) fn parse_item_common(
         &mut self,
         mut attrs: Vec<Attribute>,
         mac_allowed: bool,
@@ -653,9 +647,7 @@ impl<'a> Parser<'a> {
 
     /// Parses associated items.
     fn parse_assoc_item(&mut self, req_name: ReqName) -> PResult<'a, Option<Option<P<AssocItem>>>> {
-        let attrs = self.parse_outer_attributes()?;
-        let it = self.parse_item_common(attrs, true, false, req_name)?;
-        Ok(it.map(|Item { attrs, id, span, vis, ident, kind, tokens }| {
+        Ok(self.parse_item_(req_name)?.map(|Item { attrs, id, span, vis, ident, kind, tokens }| {
             let kind = match kind {
                 ItemKind::Mac(a) => AssocItemKind::Macro(a),
                 ItemKind::Fn(a, b, c, d) => AssocItemKind::Fn(a, b, c, d),
@@ -844,9 +836,7 @@ impl<'a> Parser<'a> {
     pub fn parse_foreign_item(&mut self) -> PResult<'a, Option<Option<P<ForeignItem>>>> {
         maybe_whole!(self, NtForeignItem, |item| Some(Some(item)));
 
-        let attrs = self.parse_outer_attributes()?;
-        let item = self.parse_item_common(attrs, true, false, |_| true)?;
-        Ok(item.map(|Item { attrs, id, span, vis, ident, kind, tokens }| {
+        Ok(self.parse_item_(|_| true)?.map(|Item { attrs, id, span, vis, ident, kind, tokens }| {
             let kind = match kind {
                 ItemKind::Mac(a) => ForeignItemKind::Macro(a),
                 ItemKind::Fn(a, b, c, d) => ForeignItemKind::Fn(a, b, c, d),
diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index 0ce0e0df66aa4..bbfbe9c20df94 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -81,11 +81,11 @@ impl<'a> Parser<'a> {
         // FIXME: Bad copy of attrs
         let old_directory_ownership =
             mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
-        let item = self.parse_item_(attrs.clone(), false, true)?;
+        let item = self.parse_item_common(attrs.clone(), false, true, |_| true)?;
         self.directory.ownership = old_directory_ownership;
 
         if let Some(item) = item {
-            return Ok(Some(self.mk_stmt(lo.to(item.span), StmtKind::Item(item))));
+            return Ok(Some(self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item)))));
         }
 
         // Do not attempt to parse an expression if we're done here.

From fde5939d1c843c3ede7f6ea0eef704f52854b45d Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sun, 23 Feb 2020 12:54:00 +0100
Subject: [PATCH 16/17] parse: tweak diagnostic wordings

---
 src/librustc_parse/parser/item.rs             | 10 +--
 .../ui/parser/default-on-wrong-item-kind.rs   | 72 +++++++++----------
 .../parser/default-on-wrong-item-kind.stderr  | 72 +++++++++----------
 src/test/ui/parser/default-unmatched-assoc.rs |  4 +-
 .../ui/parser/default-unmatched-assoc.stderr  |  4 +-
 .../ui/parser/default-unmatched-extern.rs     |  2 +-
 .../ui/parser/default-unmatched-extern.stderr |  2 +-
 src/test/ui/parser/default-unmatched.rs       |  2 +-
 src/test/ui/parser/default-unmatched.stderr   |  2 +-
 src/test/ui/parser/default.rs                 |  2 +-
 src/test/ui/parser/default.stderr             |  2 +-
 src/test/ui/parser/duplicate-visibility.rs    |  2 +-
 .../ui/parser/duplicate-visibility.stderr     |  2 +-
 src/test/ui/parser/impl-parsing.rs            |  2 +-
 src/test/ui/parser/impl-parsing.stderr        |  2 +-
 src/test/ui/parser/issue-41155.rs             |  2 +-
 src/test/ui/parser/issue-41155.stderr         |  2 +-
 .../missing-close-brace-in-impl-trait.rs      |  4 +-
 .../missing-close-brace-in-impl-trait.stderr  |  4 +-
 .../missing-close-brace-in-trait.rs           |  4 +-
 .../missing-close-brace-in-trait.stderr       |  4 +-
 src/test/ui/pub/pub-restricted-error-fn.rs    |  2 +-
 .../ui/pub/pub-restricted-error-fn.stderr     |  2 +-
 23 files changed, 103 insertions(+), 103 deletions(-)

diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index c85b4c22d010a..d6da627054196 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -112,7 +112,7 @@ impl<'a> Parser<'a> {
         }
         let vs = pprust::vis_to_string(&vis);
         let vs = vs.trim_end();
-        self.struct_span_err(vis.span, &format!("visibility `{}` not followed by an item", vs))
+        self.struct_span_err(vis.span, &format!("visibility `{}` is not followed by an item", vs))
             .span_label(vis.span, "the visibility")
             .help(&format!("you likely meant to define an item, e.g., `{} fn foo() {{}}`", vs))
             .emit();
@@ -121,7 +121,7 @@ impl<'a> Parser<'a> {
     /// Error in-case a `default` was parsed but no item followed.
     fn error_on_unmatched_defaultness(&self, def: Defaultness) {
         if let Defaultness::Default(sp) = def {
-            self.struct_span_err(sp, "`default` not followed by an item")
+            self.struct_span_err(sp, "`default` is not followed by an item")
                 .span_label(sp, "the `default` qualifier")
                 .note("only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`")
                 .emit();
@@ -657,7 +657,7 @@ impl<'a> Parser<'a> {
                     self.struct_span_err(span, "associated `static` items are not allowed").emit();
                     AssocItemKind::Const(Defaultness::Final, a, b)
                 }
-                _ => return self.error_bad_item_kind(span, &kind, "`trait` or `impl`"),
+                _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
             };
             Some(P(Item { attrs, id, span, vis, ident, kind, tokens }))
         }))
@@ -846,7 +846,7 @@ impl<'a> Parser<'a> {
                     self.error_on_foreign_const(span, ident);
                     ForeignItemKind::Static(a, Mutability::Not, b)
                 }
-                _ => return self.error_bad_item_kind(span, &kind, "`extern` block"),
+                _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
             };
             Some(P(Item { attrs, id, span, vis, ident, kind, tokens }))
         }))
@@ -854,7 +854,7 @@ impl<'a> Parser<'a> {
 
     fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &str) -> Option<T> {
         let span = self.sess.source_map().def_span(span);
-        let msg = format!("{} not supported in {}", kind.descr(), ctx);
+        let msg = format!("{} is not supported in {}", kind.descr(), ctx);
         self.struct_span_err(span, &msg).emit();
         return None;
     }
diff --git a/src/test/ui/parser/default-on-wrong-item-kind.rs b/src/test/ui/parser/default-on-wrong-item-kind.rs
index 982ee6d83b3b8..98a95cfa35a9e 100644
--- a/src/test/ui/parser/default-on-wrong-item-kind.rs
+++ b/src/test/ui/parser/default-on-wrong-item-kind.rs
@@ -31,110 +31,110 @@ mod free_items {
 #[cfg(FALSE)]
 extern "C" {
     default extern crate foo; //~ ERROR an extern crate cannot be `default`
-    //~^ ERROR extern crate not supported in `extern` block
+    //~^ ERROR extern crate is not supported in `extern` blocks
     default use foo; //~ ERROR a `use` import cannot be `default`
-    //~^ ERROR `use` import not supported in `extern` block
+    //~^ ERROR `use` import is not supported in `extern` blocks
     default static foo: u8; //~ ERROR a static item cannot be `default`
     default const foo: u8;
     //~^ ERROR extern items cannot be `const`
     default fn foo();
     default mod foo {} //~ ERROR a module cannot be `default`
-    //~^ ERROR module not supported in `extern` block
+    //~^ ERROR module is not supported in `extern` blocks
     default extern "C" {} //~ ERROR an extern block cannot be `default`
-    //~^ ERROR extern block not supported in `extern` block
+    //~^ ERROR extern block is not supported in `extern` blocks
     default type foo = u8;
     default enum foo {} //~ ERROR an enum cannot be `default`
-    //~^ ERROR enum not supported in `extern` block
+    //~^ ERROR enum is not supported in `extern` blocks
     default struct foo {} //~ ERROR a struct cannot be `default`
-    //~^ ERROR struct not supported in `extern` block
+    //~^ ERROR struct is not supported in `extern` blocks
     default union foo {} //~ ERROR a union cannot be `default`
-    //~^ ERROR union not supported in `extern` block
+    //~^ ERROR union is not supported in `extern` blocks
     default trait foo {} //~ ERROR a trait cannot be `default`
-    //~^ ERROR trait not supported in `extern` block
+    //~^ ERROR trait is not supported in `extern` blocks
     default trait foo = Ord; //~ ERROR a trait alias cannot be `default`
-    //~^ ERROR trait alias not supported in `extern` block
+    //~^ ERROR trait alias is not supported in `extern` blocks
     default impl foo {}
-    //~^ ERROR implementation not supported in `extern` block
+    //~^ ERROR implementation is not supported in `extern` blocks
     default!();
     default::foo::bar!();
     default default!(); //~ ERROR an item macro invocation cannot be `default`
     default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default`
     default macro foo {} //~ ERROR a macro definition cannot be `default`
-    //~^ ERROR macro definition not supported in `extern` block
+    //~^ ERROR macro definition is not supported in `extern` blocks
     default macro_rules! foo {} //~ ERROR a macro definition cannot be `default`
-    //~^ ERROR macro definition not supported in `extern` block
+    //~^ ERROR macro definition is not supported in `extern` blocks
 }
 
 #[cfg(FALSE)]
 impl S {
     default extern crate foo; //~ ERROR an extern crate cannot be `default`
-    //~^ ERROR extern crate not supported in `trait` or `impl`
+    //~^ ERROR extern crate is not supported in `trait`s or `impl`s
     default use foo; //~ ERROR a `use` import cannot be `default`
-    //~^ ERROR `use` import not supported in `trait` or `impl`
+    //~^ ERROR `use` import is not supported in `trait`s or `impl`s
     default static foo: u8; //~ ERROR a static item cannot be `default`
     //~^ ERROR associated `static` items are not allowed
     default const foo: u8;
     default fn foo();
     default mod foo {}//~ ERROR a module cannot be `default`
-    //~^ ERROR module not supported in `trait` or `impl`
+    //~^ ERROR module is not supported in `trait`s or `impl`s
     default extern "C" {} //~ ERROR an extern block cannot be `default`
-    //~^ ERROR extern block not supported in `trait` or `impl`
+    //~^ ERROR extern block is not supported in `trait`s or `impl`s
     default type foo = u8;
     default enum foo {} //~ ERROR an enum cannot be `default`
-    //~^ ERROR enum not supported in `trait` or `impl`
+    //~^ ERROR enum is not supported in `trait`s or `impl`s
     default struct foo {} //~ ERROR a struct cannot be `default`
-    //~^ ERROR struct not supported in `trait` or `impl`
+    //~^ ERROR struct is not supported in `trait`s or `impl`s
     default union foo {} //~ ERROR a union cannot be `default`
-    //~^ ERROR union not supported in `trait` or `impl`
+    //~^ ERROR union is not supported in `trait`s or `impl`s
     default trait foo {} //~ ERROR a trait cannot be `default`
-    //~^ ERROR trait not supported in `trait` or `impl`
+    //~^ ERROR trait is not supported in `trait`s or `impl`s
     default trait foo = Ord; //~ ERROR a trait alias cannot be `default`
-    //~^ ERROR trait alias not supported in `trait` or `impl`
+    //~^ ERROR trait alias is not supported in `trait`s or `impl`s
     default impl foo {}
-    //~^ ERROR implementation not supported in `trait` or `impl`
+    //~^ ERROR implementation is not supported in `trait`s or `impl`s
     default!();
     default::foo::bar!();
     default default!(); //~ ERROR an item macro invocation cannot be `default`
     default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default`
     default macro foo {} //~ ERROR a macro definition cannot be `default`
-    //~^ ERROR macro definition not supported in `trait` or `impl`
+    //~^ ERROR macro definition is not supported in `trait`s or `impl`s
     default macro_rules! foo {} //~ ERROR a macro definition cannot be `default`
-    //~^ ERROR macro definition not supported in `trait` or `impl`
+    //~^ ERROR macro definition is not supported in `trait`s or `impl`s
 }
 
 #[cfg(FALSE)]
 trait T {
     default extern crate foo; //~ ERROR an extern crate cannot be `default`
-    //~^ ERROR extern crate not supported in `trait` or `impl`
+    //~^ ERROR extern crate is not supported in `trait`s or `impl`s
     default use foo; //~ ERROR a `use` import cannot be `default`
-    //~^ ERROR `use` import not supported in `trait` or `impl`
+    //~^ ERROR `use` import is not supported in `trait`s or `impl`s
     default static foo: u8; //~ ERROR a static item cannot be `default`
     //~^ ERROR associated `static` items are not allowed
     default const foo: u8;
     default fn foo();
     default mod foo {}//~ ERROR a module cannot be `default`
-    //~^ ERROR module not supported in `trait` or `impl`
+    //~^ ERROR module is not supported in `trait`s or `impl`s
     default extern "C" {} //~ ERROR an extern block cannot be `default`
-    //~^ ERROR extern block not supported in `trait` or `impl`
+    //~^ ERROR extern block is not supported in `trait`s or `impl`s
     default type foo = u8;
     default enum foo {} //~ ERROR an enum cannot be `default`
-    //~^ ERROR enum not supported in `trait` or `impl`
+    //~^ ERROR enum is not supported in `trait`s or `impl`s
     default struct foo {} //~ ERROR a struct cannot be `default`
-    //~^ ERROR struct not supported in `trait` or `impl`
+    //~^ ERROR struct is not supported in `trait`s or `impl`s
     default union foo {} //~ ERROR a union cannot be `default`
-    //~^ ERROR union not supported in `trait` or `impl`
+    //~^ ERROR union is not supported in `trait`s or `impl`s
     default trait foo {} //~ ERROR a trait cannot be `default`
-    //~^ ERROR trait not supported in `trait` or `impl`
+    //~^ ERROR trait is not supported in `trait`s or `impl`s
     default trait foo = Ord; //~ ERROR a trait alias cannot be `default`
-    //~^ ERROR trait alias not supported in `trait` or `impl`
+    //~^ ERROR trait alias is not supported in `trait`s or `impl`s
     default impl foo {}
-    //~^ ERROR implementation not supported in `trait` or `impl`
+    //~^ ERROR implementation is not supported in `trait`s or `impl`s
     default!();
     default::foo::bar!();
     default default!(); //~ ERROR an item macro invocation cannot be `default`
     default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default`
     default macro foo {} //~ ERROR a macro definition cannot be `default`
-    //~^ ERROR macro definition not supported in `trait` or `impl`
+    //~^ ERROR macro definition is not supported in `trait`s or `impl`s
     default macro_rules! foo {} //~ ERROR a macro definition cannot be `default`
-    //~^ ERROR macro definition not supported in `trait` or `impl`
+    //~^ ERROR macro definition is not supported in `trait`s or `impl`s
 }
diff --git a/src/test/ui/parser/default-on-wrong-item-kind.stderr b/src/test/ui/parser/default-on-wrong-item-kind.stderr
index d0f3ad4d72b04..9788bd64725b8 100644
--- a/src/test/ui/parser/default-on-wrong-item-kind.stderr
+++ b/src/test/ui/parser/default-on-wrong-item-kind.stderr
@@ -118,7 +118,7 @@ LL |     default extern crate foo;
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: extern crate not supported in `extern` block
+error: extern crate is not supported in `extern` blocks
   --> $DIR/default-on-wrong-item-kind.rs:33:5
    |
 LL |     default extern crate foo;
@@ -132,7 +132,7 @@ LL |     default use foo;
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: `use` import not supported in `extern` block
+error: `use` import is not supported in `extern` blocks
   --> $DIR/default-on-wrong-item-kind.rs:35:5
    |
 LL |     default use foo;
@@ -164,7 +164,7 @@ LL |     default mod foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: module not supported in `extern` block
+error: module is not supported in `extern` blocks
   --> $DIR/default-on-wrong-item-kind.rs:41:5
    |
 LL |     default mod foo {}
@@ -178,7 +178,7 @@ LL |     default extern "C" {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: extern block not supported in `extern` block
+error: extern block is not supported in `extern` blocks
   --> $DIR/default-on-wrong-item-kind.rs:43:5
    |
 LL |     default extern "C" {}
@@ -192,7 +192,7 @@ LL |     default enum foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: enum not supported in `extern` block
+error: enum is not supported in `extern` blocks
   --> $DIR/default-on-wrong-item-kind.rs:46:5
    |
 LL |     default enum foo {}
@@ -206,7 +206,7 @@ LL |     default struct foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: struct not supported in `extern` block
+error: struct is not supported in `extern` blocks
   --> $DIR/default-on-wrong-item-kind.rs:48:5
    |
 LL |     default struct foo {}
@@ -220,7 +220,7 @@ LL |     default union foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: union not supported in `extern` block
+error: union is not supported in `extern` blocks
   --> $DIR/default-on-wrong-item-kind.rs:50:5
    |
 LL |     default union foo {}
@@ -234,7 +234,7 @@ LL |     default trait foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: trait not supported in `extern` block
+error: trait is not supported in `extern` blocks
   --> $DIR/default-on-wrong-item-kind.rs:52:5
    |
 LL |     default trait foo {}
@@ -248,13 +248,13 @@ LL |     default trait foo = Ord;
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: trait alias not supported in `extern` block
+error: trait alias is not supported in `extern` blocks
   --> $DIR/default-on-wrong-item-kind.rs:54:5
    |
 LL |     default trait foo = Ord;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: implementation not supported in `extern` block
+error: implementation is not supported in `extern` blocks
   --> $DIR/default-on-wrong-item-kind.rs:56:5
    |
 LL |     default impl foo {}
@@ -284,7 +284,7 @@ LL |     default macro foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: macro definition not supported in `extern` block
+error: macro definition is not supported in `extern` blocks
   --> $DIR/default-on-wrong-item-kind.rs:62:5
    |
 LL |     default macro foo {}
@@ -298,7 +298,7 @@ LL |     default macro_rules! foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: macro definition not supported in `extern` block
+error: macro definition is not supported in `extern` blocks
   --> $DIR/default-on-wrong-item-kind.rs:64:5
    |
 LL |     default macro_rules! foo {}
@@ -312,7 +312,7 @@ LL |     default extern crate foo;
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: extern crate not supported in `trait` or `impl`
+error: extern crate is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:70:5
    |
 LL |     default extern crate foo;
@@ -326,7 +326,7 @@ LL |     default use foo;
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: `use` import not supported in `trait` or `impl`
+error: `use` import is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:72:5
    |
 LL |     default use foo;
@@ -354,7 +354,7 @@ LL |     default mod foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: module not supported in `trait` or `impl`
+error: module is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:78:5
    |
 LL |     default mod foo {}
@@ -368,7 +368,7 @@ LL |     default extern "C" {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: extern block not supported in `trait` or `impl`
+error: extern block is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:80:5
    |
 LL |     default extern "C" {}
@@ -382,7 +382,7 @@ LL |     default enum foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: enum not supported in `trait` or `impl`
+error: enum is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:83:5
    |
 LL |     default enum foo {}
@@ -396,7 +396,7 @@ LL |     default struct foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: struct not supported in `trait` or `impl`
+error: struct is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:85:5
    |
 LL |     default struct foo {}
@@ -410,7 +410,7 @@ LL |     default union foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: union not supported in `trait` or `impl`
+error: union is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:87:5
    |
 LL |     default union foo {}
@@ -424,7 +424,7 @@ LL |     default trait foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: trait not supported in `trait` or `impl`
+error: trait is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:89:5
    |
 LL |     default trait foo {}
@@ -438,13 +438,13 @@ LL |     default trait foo = Ord;
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: trait alias not supported in `trait` or `impl`
+error: trait alias is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:91:5
    |
 LL |     default trait foo = Ord;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: implementation not supported in `trait` or `impl`
+error: implementation is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:93:5
    |
 LL |     default impl foo {}
@@ -474,7 +474,7 @@ LL |     default macro foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: macro definition not supported in `trait` or `impl`
+error: macro definition is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:99:5
    |
 LL |     default macro foo {}
@@ -488,7 +488,7 @@ LL |     default macro_rules! foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: macro definition not supported in `trait` or `impl`
+error: macro definition is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:101:5
    |
 LL |     default macro_rules! foo {}
@@ -502,7 +502,7 @@ LL |     default extern crate foo;
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: extern crate not supported in `trait` or `impl`
+error: extern crate is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:107:5
    |
 LL |     default extern crate foo;
@@ -516,7 +516,7 @@ LL |     default use foo;
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: `use` import not supported in `trait` or `impl`
+error: `use` import is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:109:5
    |
 LL |     default use foo;
@@ -544,7 +544,7 @@ LL |     default mod foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: module not supported in `trait` or `impl`
+error: module is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:115:5
    |
 LL |     default mod foo {}
@@ -558,7 +558,7 @@ LL |     default extern "C" {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: extern block not supported in `trait` or `impl`
+error: extern block is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:117:5
    |
 LL |     default extern "C" {}
@@ -572,7 +572,7 @@ LL |     default enum foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: enum not supported in `trait` or `impl`
+error: enum is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:120:5
    |
 LL |     default enum foo {}
@@ -586,7 +586,7 @@ LL |     default struct foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: struct not supported in `trait` or `impl`
+error: struct is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:122:5
    |
 LL |     default struct foo {}
@@ -600,7 +600,7 @@ LL |     default union foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: union not supported in `trait` or `impl`
+error: union is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:124:5
    |
 LL |     default union foo {}
@@ -614,7 +614,7 @@ LL |     default trait foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: trait not supported in `trait` or `impl`
+error: trait is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:126:5
    |
 LL |     default trait foo {}
@@ -628,13 +628,13 @@ LL |     default trait foo = Ord;
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: trait alias not supported in `trait` or `impl`
+error: trait alias is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:128:5
    |
 LL |     default trait foo = Ord;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: implementation not supported in `trait` or `impl`
+error: implementation is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:130:5
    |
 LL |     default impl foo {}
@@ -664,7 +664,7 @@ LL |     default macro foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: macro definition not supported in `trait` or `impl`
+error: macro definition is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:136:5
    |
 LL |     default macro foo {}
@@ -678,7 +678,7 @@ LL |     default macro_rules! foo {}
    |
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
-error: macro definition not supported in `trait` or `impl`
+error: macro definition is not supported in `trait`s or `impl`s
   --> $DIR/default-on-wrong-item-kind.rs:138:5
    |
 LL |     default macro_rules! foo {}
diff --git a/src/test/ui/parser/default-unmatched-assoc.rs b/src/test/ui/parser/default-unmatched-assoc.rs
index 0c8ee0f7800d8..168ea3e76f648 100644
--- a/src/test/ui/parser/default-unmatched-assoc.rs
+++ b/src/test/ui/parser/default-unmatched-assoc.rs
@@ -3,7 +3,7 @@ fn main() {}
 trait Foo {
     default!(); //~ ERROR cannot find macro `default` in this scope
     default do
-    //~^ ERROR `default` not followed by an item
+    //~^ ERROR `default` is not followed by an item
     //~| ERROR non-item in item list
 }
 
@@ -11,6 +11,6 @@ struct S;
 impl S {
     default!(); //~ ERROR cannot find macro `default` in this scope
     default do
-    //~^ ERROR `default` not followed by an item
+    //~^ ERROR `default` is not followed by an item
     //~| ERROR non-item in item list
 }
diff --git a/src/test/ui/parser/default-unmatched-assoc.stderr b/src/test/ui/parser/default-unmatched-assoc.stderr
index 22db46d63dffb..c8d1769cb5a2a 100644
--- a/src/test/ui/parser/default-unmatched-assoc.stderr
+++ b/src/test/ui/parser/default-unmatched-assoc.stderr
@@ -1,4 +1,4 @@
-error: `default` not followed by an item
+error: `default` is not followed by an item
   --> $DIR/default-unmatched-assoc.rs:5:5
    |
 LL |     default do
@@ -18,7 +18,7 @@ LL |     default do
 LL | }
    | - item list ends here
 
-error: `default` not followed by an item
+error: `default` is not followed by an item
   --> $DIR/default-unmatched-assoc.rs:13:5
    |
 LL |     default do
diff --git a/src/test/ui/parser/default-unmatched-extern.rs b/src/test/ui/parser/default-unmatched-extern.rs
index 784df9bc77e57..8d0ea590f573f 100644
--- a/src/test/ui/parser/default-unmatched-extern.rs
+++ b/src/test/ui/parser/default-unmatched-extern.rs
@@ -3,6 +3,6 @@ fn main() {}
 extern "C" {
     default!(); //~ ERROR cannot find macro `default` in this scope
     default do
-    //~^ ERROR `default` not followed by an item
+    //~^ ERROR `default` is not followed by an item
     //~| ERROR non-item in item list
 }
diff --git a/src/test/ui/parser/default-unmatched-extern.stderr b/src/test/ui/parser/default-unmatched-extern.stderr
index ffbfbc73c18d4..bb4efd51631e4 100644
--- a/src/test/ui/parser/default-unmatched-extern.stderr
+++ b/src/test/ui/parser/default-unmatched-extern.stderr
@@ -1,4 +1,4 @@
-error: `default` not followed by an item
+error: `default` is not followed by an item
   --> $DIR/default-unmatched-extern.rs:5:5
    |
 LL |     default do
diff --git a/src/test/ui/parser/default-unmatched.rs b/src/test/ui/parser/default-unmatched.rs
index 796e184a0d815..49346e5c6318d 100644
--- a/src/test/ui/parser/default-unmatched.rs
+++ b/src/test/ui/parser/default-unmatched.rs
@@ -1,6 +1,6 @@
 mod foo {
     default!(); // OK.
     default do
-    //~^ ERROR `default` not followed by an item
+    //~^ ERROR `default` is not followed by an item
     //~| ERROR expected item, found reserved keyword `do`
 }
diff --git a/src/test/ui/parser/default-unmatched.stderr b/src/test/ui/parser/default-unmatched.stderr
index 2601255776108..331e003f63c0f 100644
--- a/src/test/ui/parser/default-unmatched.stderr
+++ b/src/test/ui/parser/default-unmatched.stderr
@@ -1,4 +1,4 @@
-error: `default` not followed by an item
+error: `default` is not followed by an item
   --> $DIR/default-unmatched.rs:3:5
    |
 LL |     default do
diff --git a/src/test/ui/parser/default.rs b/src/test/ui/parser/default.rs
index 6cfa141478e4a..64ba4b5531184 100644
--- a/src/test/ui/parser/default.rs
+++ b/src/test/ui/parser/default.rs
@@ -20,7 +20,7 @@ impl Foo for u16 {
 
 impl Foo for u32 { //~ ERROR not all trait items implemented, missing: `foo`
     default pub fn foo<T: Default>() -> T { T::default() }
-    //~^ ERROR `default` not followed by an item
+    //~^ ERROR `default` is not followed by an item
     //~| ERROR non-item in item list
 }
 
diff --git a/src/test/ui/parser/default.stderr b/src/test/ui/parser/default.stderr
index 96b14b42767a3..15c49e8b6270b 100644
--- a/src/test/ui/parser/default.stderr
+++ b/src/test/ui/parser/default.stderr
@@ -1,4 +1,4 @@
-error: `default` not followed by an item
+error: `default` is not followed by an item
   --> $DIR/default.rs:22:5
    |
 LL |     default pub fn foo<T: Default>() -> T { T::default() }
diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs
index edea2d1e5e2f3..31318ae3a096c 100644
--- a/src/test/ui/parser/duplicate-visibility.rs
+++ b/src/test/ui/parser/duplicate-visibility.rs
@@ -2,6 +2,6 @@ fn main() {}
 
 extern {
     pub pub fn foo();
-    //~^ ERROR visibility `pub` not followed by an item
+    //~^ ERROR visibility `pub` is not followed by an item
     //~| ERROR non-item in item list
 }
diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr
index d8e38046a6c15..36b9efd9dca6e 100644
--- a/src/test/ui/parser/duplicate-visibility.stderr
+++ b/src/test/ui/parser/duplicate-visibility.stderr
@@ -1,4 +1,4 @@
-error: visibility `pub` not followed by an item
+error: visibility `pub` is not followed by an item
   --> $DIR/duplicate-visibility.rs:4:5
    |
 LL |     pub pub fn foo();
diff --git a/src/test/ui/parser/impl-parsing.rs b/src/test/ui/parser/impl-parsing.rs
index c2ed7531a9432..80ce888557078 100644
--- a/src/test/ui/parser/impl-parsing.rs
+++ b/src/test/ui/parser/impl-parsing.rs
@@ -7,4 +7,4 @@ impl ?Sized for Type {} //~ ERROR expected a trait, found type
 impl ?Sized for .. {} //~ ERROR expected a trait, found type
 
 default unsafe FAIL //~ ERROR expected item, found keyword `unsafe`
-//~^ ERROR `default` not followed by an item
+//~^ ERROR `default` is not followed by an item
diff --git a/src/test/ui/parser/impl-parsing.stderr b/src/test/ui/parser/impl-parsing.stderr
index ce673765aba1d..755addf14527a 100644
--- a/src/test/ui/parser/impl-parsing.stderr
+++ b/src/test/ui/parser/impl-parsing.stderr
@@ -22,7 +22,7 @@ error: expected a trait, found type
 LL | impl ?Sized for .. {}
    |      ^^^^^^
 
-error: `default` not followed by an item
+error: `default` is not followed by an item
   --> $DIR/impl-parsing.rs:9:1
    |
 LL | default unsafe FAIL
diff --git a/src/test/ui/parser/issue-41155.rs b/src/test/ui/parser/issue-41155.rs
index 5bfbe0c5e6890..5a7488e6ffcb4 100644
--- a/src/test/ui/parser/issue-41155.rs
+++ b/src/test/ui/parser/issue-41155.rs
@@ -1,7 +1,7 @@
 struct S;
 
 impl S {
-    pub //~ ERROR visibility `pub` not followed by an item
+    pub //~ ERROR visibility `pub` is not followed by an item
 } //~ ERROR non-item in item list
 
 fn main() {}
diff --git a/src/test/ui/parser/issue-41155.stderr b/src/test/ui/parser/issue-41155.stderr
index 09bbee51800d9..8491afae23004 100644
--- a/src/test/ui/parser/issue-41155.stderr
+++ b/src/test/ui/parser/issue-41155.stderr
@@ -1,4 +1,4 @@
-error: visibility `pub` not followed by an item
+error: visibility `pub` is not followed by an item
   --> $DIR/issue-41155.rs:4:5
    |
 LL |     pub
diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs
index b26e5134db6cc..8f46970b1af4d 100644
--- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs
+++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs
@@ -4,10 +4,10 @@ impl T for () { //~ ERROR cannot find trait `T` in this scope
 
 fn foo(&self) {}
 
-trait T { //~ ERROR trait not supported in `trait` or `impl`
+trait T { //~ ERROR trait is not supported in `trait`s or `impl`s
     fn foo(&self);
 }
 
-pub(crate) struct Bar<T>(); //~ ERROR struct not supported in `trait` or `impl`
+pub(crate) struct Bar<T>(); //~ ERROR struct is not supported in `trait`s or `impl`s
 
 //~ ERROR this file contains an unclosed delimiter
diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
index b1bd1a784be34..1655a96839569 100644
--- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
+++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
@@ -7,13 +7,13 @@ LL | impl T for () {
 LL |
    |                                                    ^
 
-error: trait not supported in `trait` or `impl`
+error: trait is not supported in `trait`s or `impl`s
   --> $DIR/missing-close-brace-in-impl-trait.rs:7:1
    |
 LL | trait T {
    | ^^^^^^^
 
-error: struct not supported in `trait` or `impl`
+error: struct is not supported in `trait`s or `impl`s
   --> $DIR/missing-close-brace-in-impl-trait.rs:11:1
    |
 LL | pub(crate) struct Bar<T>();
diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs
index d52add273981d..b6932deb5c0a6 100644
--- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs
+++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs
@@ -2,10 +2,10 @@ trait T {
     fn foo(&self);
 
 pub(crate) struct Bar<T>();
-//~^ ERROR struct not supported in `trait` or `impl`
+//~^ ERROR struct is not supported in `trait`s or `impl`s
 
 impl T for Bar<usize> {
-//~^ ERROR implementation not supported in `trait` or `impl`
+//~^ ERROR implementation is not supported in `trait`s or `impl`s
 fn foo(&self) {}
 }
 
diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
index 49c685f254956..43a3883357a75 100644
--- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
+++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
@@ -7,13 +7,13 @@ LL | trait T {
 LL | fn main() {}
    |                                                                 ^
 
-error: struct not supported in `trait` or `impl`
+error: struct is not supported in `trait`s or `impl`s
   --> $DIR/missing-close-brace-in-trait.rs:4:1
    |
 LL | pub(crate) struct Bar<T>();
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: implementation not supported in `trait` or `impl`
+error: implementation is not supported in `trait`s or `impl`s
   --> $DIR/missing-close-brace-in-trait.rs:7:1
    |
 LL | impl T for Bar<usize> {
diff --git a/src/test/ui/pub/pub-restricted-error-fn.rs b/src/test/ui/pub/pub-restricted-error-fn.rs
index 73806fdfe72b9..fc1aeae2b0cf4 100644
--- a/src/test/ui/pub/pub-restricted-error-fn.rs
+++ b/src/test/ui/pub/pub-restricted-error-fn.rs
@@ -1,2 +1,2 @@
-pub(crate) () fn foo() {} //~ ERROR visibility `pub(crate)` not followed by an item
+pub(crate) () fn foo() {} //~ ERROR visibility `pub(crate)` is not followed by an item
 //~^ ERROR expected item, found `(`
diff --git a/src/test/ui/pub/pub-restricted-error-fn.stderr b/src/test/ui/pub/pub-restricted-error-fn.stderr
index 42d03941e411f..0511a821a7afd 100644
--- a/src/test/ui/pub/pub-restricted-error-fn.stderr
+++ b/src/test/ui/pub/pub-restricted-error-fn.stderr
@@ -1,4 +1,4 @@
-error: visibility `pub(crate)` not followed by an item
+error: visibility `pub(crate)` is not followed by an item
   --> $DIR/pub-restricted-error-fn.rs:1:1
    |
 LL | pub(crate) () fn foo() {}

From 1c75f5aaa177734c8dbdab91612a8d59b519bf07 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sun, 23 Feb 2020 13:04:46 +0100
Subject: [PATCH 17/17] parse: test bad variants wrt. issue 48137.

---
 ...not-interpolate-impl-items-bad-variants.rs | 44 +++++++++++++++
 ...interpolate-impl-items-bad-variants.stderr | 53 +++++++++++++++++++
 2 files changed, 97 insertions(+)
 create mode 100644 src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs
 create mode 100644 src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr

diff --git a/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs b/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs
new file mode 100644
index 0000000000000..48a679b2d098d
--- /dev/null
+++ b/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs
@@ -0,0 +1,44 @@
+fn main() {}
+
+macro_rules! expand_to_enum {
+    () => {
+        enum BadE {}
+        //~^ ERROR enum is not supported in `trait`s or `impl`s
+        //~| ERROR enum is not supported in `trait`s or `impl`s
+        //~| ERROR enum is not supported in `extern` blocks
+    };
+}
+
+macro_rules! mac_impl {
+    ($($i:item)*) => {
+        struct S;
+        impl S { $($i)* }
+    }
+}
+
+mac_impl! {
+    struct BadS; //~ ERROR struct is not supported in `trait`s or `impl`s
+    expand_to_enum!();
+}
+
+macro_rules! mac_trait {
+    ($($i:item)*) => {
+        trait T { $($i)* }
+    }
+}
+
+mac_trait! {
+    struct BadS; //~ ERROR struct is not supported in `trait`s or `impl`s
+    expand_to_enum!();
+}
+
+macro_rules! mac_extern {
+    ($($i:item)*) => {
+        extern "C" { $($i)* }
+    }
+}
+
+mac_extern! {
+    struct BadS; //~ ERROR struct is not supported in `extern` blocks
+    expand_to_enum!();
+}
diff --git a/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr b/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr
new file mode 100644
index 0000000000000..bfd27a1a41e13
--- /dev/null
+++ b/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr
@@ -0,0 +1,53 @@
+error: struct is not supported in `trait`s or `impl`s
+  --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:20:5
+   |
+LL |     struct BadS;
+   |     ^^^^^^^^^^^^
+
+error: enum is not supported in `trait`s or `impl`s
+  --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:5:9
+   |
+LL |         enum BadE {}
+   |         ^^^^^^^^^
+...
+LL |     expand_to_enum!();
+   |     ------------------ in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: struct is not supported in `trait`s or `impl`s
+  --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:31:5
+   |
+LL |     struct BadS;
+   |     ^^^^^^^^^^^^
+
+error: enum is not supported in `trait`s or `impl`s
+  --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:5:9
+   |
+LL |         enum BadE {}
+   |         ^^^^^^^^^
+...
+LL |     expand_to_enum!();
+   |     ------------------ in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: struct is not supported in `extern` blocks
+  --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:42:5
+   |
+LL |     struct BadS;
+   |     ^^^^^^^^^^^^
+
+error: enum is not supported in `extern` blocks
+  --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:5:9
+   |
+LL |         enum BadE {}
+   |         ^^^^^^^^^
+...
+LL |     expand_to_enum!();
+   |     ------------------ in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 6 previous errors
+