Skip to content

Commit 8dc6a5d

Browse files
committed
improve maybe_consume_incorrect_semicolon
1 parent bdfd941 commit 8dc6a5d

File tree

6 files changed

+30
-28
lines changed

6 files changed

+30
-28
lines changed

compiler/rustc_ast/src/ast.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3250,6 +3250,7 @@ pub enum ItemKind {
32503250
}
32513251

32523252
impl ItemKind {
3253+
/// "a" or "an"
32533254
pub fn article(&self) -> &'static str {
32543255
use ItemKind::*;
32553256
match self {

compiler/rustc_parse/src/errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ pub(crate) struct IncorrectSemicolon<'a> {
8383
#[suggestion(style = "short", code = "", applicability = "machine-applicable")]
8484
pub span: Span,
8585
#[help]
86-
pub opt_help: Option<()>,
86+
pub show_help: bool,
8787
pub name: &'a str,
8888
}
8989

compiler/rustc_parse/src/parser/diagnostics.rs

+20-23
Original file line numberDiff line numberDiff line change
@@ -1817,34 +1817,31 @@ impl<'a> Parser<'a> {
18171817
Ok(P(T::recovered(Some(P(QSelf { ty, path_span, position: 0 })), path)))
18181818
}
18191819

1820-
pub fn maybe_consume_incorrect_semicolon(&mut self, items: &[P<Item>]) -> bool {
1821-
if self.token.kind == TokenKind::Semi {
1822-
self.bump();
1823-
1824-
let mut err =
1825-
IncorrectSemicolon { span: self.prev_token.span, opt_help: None, name: "" };
1820+
/// This function gets called in places where a semicolon is NOT expected and if there's a
1821+
/// semicolon it emits the appropriate error and returns true.
1822+
pub fn maybe_consume_incorrect_semicolon(&mut self, previous_item: Option<&Item>) -> bool {
1823+
if self.token.kind != TokenKind::Semi {
1824+
return false;
1825+
}
18261826

1827-
if !items.is_empty() {
1828-
let previous_item = &items[items.len() - 1];
1829-
let previous_item_kind_name = match previous_item.kind {
1827+
// Check previous item to add it to the diagnostic, for example to say
1828+
// `enum declarations are not followed by a semicolon`
1829+
let err = match previous_item {
1830+
Some(previous_item) => {
1831+
let name = match previous_item.kind {
18301832
// Say "braced struct" because tuple-structs and
18311833
// braceless-empty-struct declarations do take a semicolon.
1832-
ItemKind::Struct(..) => Some("braced struct"),
1833-
ItemKind::Enum(..) => Some("enum"),
1834-
ItemKind::Trait(..) => Some("trait"),
1835-
ItemKind::Union(..) => Some("union"),
1836-
_ => None,
1834+
ItemKind::Struct(..) => "braced struct",
1835+
_ => previous_item.kind.descr(),
18371836
};
1838-
if let Some(name) = previous_item_kind_name {
1839-
err.opt_help = Some(());
1840-
err.name = name;
1841-
}
1837+
IncorrectSemicolon { span: self.token.span, name, show_help: true }
18421838
}
1843-
self.dcx().emit_err(err);
1844-
true
1845-
} else {
1846-
false
1847-
}
1839+
None => IncorrectSemicolon { span: self.token.span, name: "", show_help: false },
1840+
};
1841+
self.dcx().emit_err(err);
1842+
1843+
self.bump();
1844+
true
18481845
}
18491846

18501847
/// Creates a `Diag` for an unexpected token `t` and tries to recover if it is a

compiler/rustc_parse/src/parser/item.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@ impl<'a> Parser<'a> {
5959
let post_attr_lo = self.token.span;
6060
let mut items = ThinVec::new();
6161
while let Some(item) = self.parse_item(ForceCollect::No)? {
62+
self.maybe_consume_incorrect_semicolon(Some(&item));
6263
items.push(item);
63-
self.maybe_consume_incorrect_semicolon(&items);
6464
}
6565

6666
if !self.eat(term) {
6767
let token_str = super::token_descr(&self.token);
68-
if !self.maybe_consume_incorrect_semicolon(&items) {
68+
if !self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {
6969
let msg = format!("expected item, found {token_str}");
7070
let mut err = self.dcx().struct_span_err(self.token.span, msg);
7171
let span = self.token.span;

src/librustdoc/doctest.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -686,9 +686,9 @@ pub(crate) fn make_test(
686686
}
687687
}
688688

689-
// The supplied slice is only used for diagnostics,
689+
// The supplied item is only used for diagnostics,
690690
// which are swallowed here anyway.
691-
parser.maybe_consume_incorrect_semicolon(&[]);
691+
parser.maybe_consume_incorrect_semicolon(None);
692692
}
693693

694694
// Reset errors so that they won't be reported as compiler bugs when dropping the

tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ error: expected item, found `;`
33
|
44
LL | mod M {};
55
| ^ help: remove this semicolon
6+
|
7+
= help: module declarations are not followed by a semicolon
68

79
error: expected item, found `;`
810
--> $DIR/recover-from-semicolon-trailing-item.rs:4:12
@@ -17,6 +19,8 @@ error: expected item, found `;`
1719
|
1820
LL | fn foo(a: usize) {};
1921
| ^ help: remove this semicolon
22+
|
23+
= help: function declarations are not followed by a semicolon
2024

2125
error[E0308]: mismatched types
2226
--> $DIR/recover-from-semicolon-trailing-item.rs:10:20

0 commit comments

Comments
 (0)