Skip to content

Commit 011dd54

Browse files
author
Orion Gonzalez
committed
save
1 parent 44722bd commit 011dd54

File tree

2 files changed

+78
-28
lines changed
  • compiler

2 files changed

+78
-28
lines changed

compiler/rustc_ast_pretty/src/pprust/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::borrow::Cow;
77
use rustc_ast as ast;
88
use rustc_ast::token::{Nonterminal, Token, TokenKind};
99
use rustc_ast::tokenstream::{TokenStream, TokenTree};
10-
pub use state::{AnnNode, Comments, PpAnn, PrintState, State, print_crate};
10+
pub use state::{print_crate, AnnNode, Comments, PpAnn, PrintState, State};
1111

1212
pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
1313
State::new().nonterminal_to_string(nt)
@@ -63,6 +63,10 @@ pub fn path_segment_to_string(p: &ast::PathSegment) -> String {
6363
State::new().path_segment_to_string(p)
6464
}
6565

66+
pub fn stmt_to_string(p: &ast::Stmt) -> String {
67+
State::new().stmt_to_string(p)
68+
}
69+
6670
pub fn vis_to_string(v: &ast::Visibility) -> String {
6771
State::new().vis_to_string(v)
6872
}

compiler/rustc_parse/src/parser/item.rs

Lines changed: 73 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,19 @@ use rustc_ast::util::case::Case;
1010
use rustc_ast::{self as ast};
1111
use rustc_ast_pretty::pprust;
1212
use rustc_errors::codes::*;
13-
use rustc_errors::{Applicability, PResult, StashKey, struct_span_code_err};
13+
use rustc_errors::{struct_span_code_err, Applicability, PResult, StashKey};
1414
use rustc_span::edit_distance::edit_distance;
1515
use rustc_span::edition::Edition;
16-
use rustc_span::symbol::{Ident, Symbol, kw, sym};
17-
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, source_map};
18-
use thin_vec::{ThinVec, thin_vec};
16+
use rustc_span::symbol::{kw, sym, Ident, Symbol};
17+
use rustc_span::{source_map, ErrorGuaranteed, Span, DUMMY_SP};
18+
use thin_vec::{thin_vec, ThinVec};
1919
use tracing::debug;
2020

21-
use super::diagnostics::{ConsumeClosingDelim, dummy_arg};
21+
use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
2222
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
2323
use super::{
24-
AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, Trailing, UsePreAttrPos,
24+
AttemptLocalParseRecovery, AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle,
25+
Trailing, UsePreAttrPos,
2526
};
2627
use crate::errors::{self, MacroExpandsToAdtField};
2728
use crate::{fluent_generated as fluent, maybe_whole};
@@ -75,20 +76,8 @@ impl<'a> Parser<'a> {
7576
}
7677

7778
if !self.eat(term) {
78-
let token_str = super::token_descr(&self.token);
7979
if !self.maybe_consume_incorrect_semicolon(items.last().map(|x| &**x)) {
80-
let msg = format!("expected item, found {token_str}");
81-
let mut err = self.dcx().struct_span_err(self.token.span, msg);
82-
let span = self.token.span;
83-
if self.is_kw_followed_by_ident(kw::Let) {
84-
err.span_label(
85-
span,
86-
"consider using `const` or `static` instead of `let` for global variables",
87-
);
88-
} else {
89-
err.span_label(span, "expected item")
90-
.note("for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>");
91-
};
80+
let err = self.fallback_incorrect_item();
9281
return Err(err);
9382
}
9483
}
@@ -97,6 +86,55 @@ impl<'a> Parser<'a> {
9786
let mod_spans = ModSpans { inner_span: lo.to(self.prev_token.span), inject_use_span };
9887
Ok((attrs, items, mod_spans))
9988
}
89+
90+
/// Tries to parse the item as a statement to provide further diagnostics.
91+
fn fallback_incorrect_item(&mut self) -> rustc_errors::Diag<'a> {
92+
let token_str = super::token_descr(&self.token);
93+
let mut err = self
94+
.dcx()
95+
.struct_span_err(self.token.span, format!("expected item, found {token_str}"));
96+
97+
match self.parse_full_stmt(AttemptLocalParseRecovery::No) {
98+
Ok(Some(stmt)) => {
99+
let span = stmt.span;
100+
match &stmt.kind {
101+
StmtKind::Let(_) => {
102+
err.span_label(span, "unexpected `let` binding outside of a function")
103+
.help(format!("consider using `const` or `static` instead of `let` for global variables, or put it inside of a function: fn foo() {{ {} }}",
104+
pprust::stmt_to_string(&stmt)));
105+
}
106+
StmtKind::Semi(expr) => {
107+
err.span_label(span, "unexpected expression").help(format!(
108+
"consider putting it inside a function: fn foo() {{ {}; }}",
109+
pprust::expr_to_string(expr)
110+
));
111+
}
112+
StmtKind::Expr(expr) => {
113+
err.span_label(span, "unexpected expression").help(format!(
114+
"consider putting it inside a function: fn foo() {{ {} }}",
115+
pprust::expr_to_string(expr)
116+
));
117+
}
118+
StmtKind::Empty => {
119+
unreachable!(
120+
"Should have been handled by maybe_consume_incorrect_semicolon"
121+
);
122+
}
123+
StmtKind::Item(_) | StmtKind::MacCall(_) => {
124+
unreachable!("These should be valid.")
125+
}
126+
};
127+
}
128+
Ok(None) => {} // It's not a statement, not much we can do.
129+
Err(e) => {
130+
// We don't really care about an error parsing this statement.
131+
e.cancel();
132+
}
133+
}
134+
err.note("for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>");
135+
136+
err
137+
}
100138
}
101139

102140
pub(super) type ItemInfo = (Ident, ItemKind);
@@ -452,7 +490,11 @@ impl<'a> Parser<'a> {
452490
None
453491
};
454492

455-
if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) }
493+
if let Some(err) = err {
494+
Err(self.dcx().create_err(err))
495+
} else {
496+
Ok(())
497+
}
456498
}
457499

458500
fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemInfo>> {
@@ -1112,7 +1154,11 @@ impl<'a> Parser<'a> {
11121154
}
11131155

11141156
fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
1115-
if self.eat_keyword(kw::As) { self.parse_ident_or_underscore().map(Some) } else { Ok(None) }
1157+
if self.eat_keyword(kw::As) {
1158+
self.parse_ident_or_underscore().map(Some)
1159+
} else {
1160+
Ok(None)
1161+
}
11161162
}
11171163

11181164
fn parse_ident_or_underscore(&mut self) -> PResult<'a, Ident> {
@@ -1195,7 +1241,7 @@ impl<'a> Parser<'a> {
11951241
mut safety: Safety,
11961242
) -> PResult<'a, ItemInfo> {
11971243
let abi = self.parse_abi(); // ABI?
1198-
// FIXME: This recovery should be tested better.
1244+
// FIXME: This recovery should be tested better.
11991245
if safety == Safety::Default
12001246
&& self.token.is_keyword(kw::Unsafe)
12011247
&& self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace))
@@ -1897,10 +1943,10 @@ impl<'a> Parser<'a> {
18971943
// Try to recover extra trailing angle brackets
18981944
if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind {
18991945
if let Some(last_segment) = segments.last() {
1900-
let guar = self.check_trailing_angle_brackets(last_segment, &[
1901-
&token::Comma,
1902-
&token::CloseDelim(Delimiter::Brace),
1903-
]);
1946+
let guar = self.check_trailing_angle_brackets(
1947+
last_segment,
1948+
&[&token::Comma, &token::CloseDelim(Delimiter::Brace)],
1949+
);
19041950
if let Some(_guar) = guar {
19051951
// Handle a case like `Vec<u8>>,` where we can continue parsing fields
19061952
// after the comma
@@ -2107,7 +2153,7 @@ impl<'a> Parser<'a> {
21072153
self.unexpected()?;
21082154
}
21092155
let body = self.parse_token_tree(); // `MacBody`
2110-
// Convert `MacParams MacBody` into `{ MacParams => MacBody }`.
2156+
// Convert `MacParams MacBody` into `{ MacParams => MacBody }`.
21112157
let bspan = body.span();
21122158
let arrow = TokenTree::token_alone(token::FatArrow, pspan.between(bspan)); // `=>`
21132159
let tokens = TokenStream::new(vec![params, arrow, body]);

0 commit comments

Comments
 (0)