about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2020-02-22 06:57:31 +0100
committerMazdak Farrokhzad <twingoow@gmail.com>2020-02-24 00:59:38 +0100
commita63f35daeefc4ae89ba5b6bd0323d97bb0d050e6 (patch)
treefdfa0e3a90f8a0ec12979c3a960f884bacaa7300 /src
parenta920a056035d3aa8f5e90ff174764a886366d379 (diff)
downloadrust-a63f35daeefc4ae89ba5b6bd0323d97bb0d050e6.tar.gz
rust-a63f35daeefc4ae89ba5b6bd0323d97bb0d050e6.zip
parse: use `parse_item_common` in `parse_foreign_item`.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_expand/expand.rs4
-rw-r--r--src/librustc_parse/parser/item.rs81
-rw-r--r--src/test/ui/macros/issue-54441.rs3
-rw-r--r--src/test/ui/macros/issue-54441.stderr16
-rw-r--r--src/test/ui/parser/default-on-wrong-item-kind.rs36
-rw-r--r--src/test/ui/parser/default-on-wrong-item-kind.stderr234
-rw-r--r--src/test/ui/parser/default-unmatched-extern.rs8
-rw-r--r--src/test/ui/parser/default-unmatched-extern.stderr26
-rw-r--r--src/test/ui/parser/duplicate-visibility.rs3
-rw-r--r--src/test/ui/parser/duplicate-visibility.stderr21
-rw-r--r--src/test/ui/parser/extern-no-fn.rs3
-rw-r--r--src/test/ui/parser/extern-no-fn.stderr11
-rw-r--r--src/test/ui/parser/foreign-const-semantic-fail.rs1
-rw-r--r--src/test/ui/parser/foreign-const-semantic-fail.stderr15
14 files changed, 392 insertions, 70 deletions
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index ba26780dea2..df2753813f9 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 184956e1065..ecd2049963b 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 5570f081b15..b24d7e1f6be 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 5857aacb431..752916e6655 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 f7d390eb8a2..0fe20473587 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 d279fd962bb..e089bbbddde 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 00000000000..fbf87a892f0
--- /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 00000000000..00c8898e2ce
--- /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 f6e7f7e6abe..949b6e1dc24 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 398ba65c9e1..2c79a343d05 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 dc47f741073..d9f35e0eb5c 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 8d55eefc8d0..02320125014 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 d28b6414282..82978e655ba 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 f364f11bb03..f529b3ad87b 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