11use super :: diagnostics:: { dummy_arg, ConsumeClosingDelim } ;
22use super :: ty:: { AllowPlus , RecoverQPath , RecoverReturnSign } ;
33use super :: {
4- AttrWrapper , FollowedByType , ForceCollect , Parser , PathStyle , Trailing , TrailingToken ,
4+ AttemptLocalParseRecovery , AttrWrapper , FollowedByType , ForceCollect , Parser , PathStyle ,
5+ Trailing , TrailingToken ,
56} ;
67use crate :: errors:: { self , MacroExpandsToAdtField } ;
78use crate :: fluent_generated as fluent;
@@ -40,6 +41,7 @@ impl<'a> Parser<'a> {
4041 let mod_kind = if self . eat ( & token:: Semi ) {
4142 ModKind :: Unloaded
4243 } else {
44+ // mod blocks are parsed recursively
4345 self . expect ( & token:: OpenDelim ( Delimiter :: Brace ) ) ?;
4446 let ( inner_attrs, items, inner_span) =
4547 self . parse_mod ( & token:: CloseDelim ( Delimiter :: Brace ) ) ?;
@@ -72,28 +74,83 @@ impl<'a> Parser<'a> {
7274 }
7375
7476 if !self . eat ( term) {
75- let token_str = super :: token_descr ( & self . token ) ;
77+ // The last token should be `term`: either EOF or `}`. If it's not that means that we've had an error
78+ // parsing an item
7679 if !self . maybe_consume_incorrect_semicolon ( items. last ( ) . map ( |x| & * * x) ) {
77- let msg = format ! ( "expected item, found {token_str}" ) ;
78- let mut err = self . dcx ( ) . struct_span_err ( self . token . span , msg) ;
79- let span = self . token . span ;
80- if self . is_kw_followed_by_ident ( kw:: Let ) {
81- err. span_label (
82- span,
83- "consider using `const` or `static` instead of `let` for global variables" ,
84- ) ;
85- } else {
86- err. span_label ( span, "expected item" )
87- . note ( "for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>" ) ;
88- } ;
89- return Err ( err) ;
80+ self . fallback_incorrect_item ( ) ?;
9081 }
9182 }
9283
9384 let inject_use_span = post_attr_lo. data ( ) . with_hi ( post_attr_lo. lo ( ) ) ;
9485 let mod_spans = ModSpans { inner_span : lo. to ( self . prev_token . span ) , inject_use_span } ;
9586 Ok ( ( attrs, items, mod_spans) )
9687 }
88+
89+ fn fallback_incorrect_item ( & mut self ) -> PResult < ' a , ( ) > {
90+ let token_str = super :: token_descr ( & self . token ) ;
91+ let mut err = self
92+ . dcx ( )
93+ . struct_span_err ( self . token . span , format ! ( "expected item, found {token_str}" ) ) ;
94+
95+ let stmt = match self . parse_full_stmt ( AttemptLocalParseRecovery :: No ) {
96+ Ok ( stmt) => stmt,
97+ Err ( e) => {
98+ // We don't really care about an error parsing this statement.
99+ e. cancel ( ) ;
100+ return Err ( err) ;
101+ }
102+ } ;
103+
104+ if let Some ( stmt) = stmt {
105+ let span = stmt. span ;
106+ match & stmt. kind {
107+ StmtKind :: Let ( _) => {
108+ err. span_label ( span, "unexpected `let` binding outside of a function" )
109+ . help ( format ! ( "consider using `const` or `static` instead of `let` for global variables, or put it inside of a function: fn foo() {{ {} }}" ,
110+ pprust:: stmt_to_string( & stmt) ) ) ;
111+ }
112+ StmtKind :: Semi ( expr) | StmtKind :: Expr ( expr) => {
113+ match expr. kind {
114+ ExprKind :: Err ( _) => {
115+ err. span_label ( expr. span , "error parsing this expression" ) ;
116+ }
117+ ExprKind :: Array ( _) => {
118+ // If it's an array it's possible that it's an attribute
119+ // that is missing a `#`.
120+ err. span_label ( span, "unexpected array" )
121+ . help (
122+ format ! ( "If you wanted an array consider putting it inside a function: fn foo() {{ {} }}" ,
123+ pprust:: expr_to_string( expr) ) )
124+ . span_help ( span. shrink_to_lo ( ) , "If you wanted an attribute consider adding `#`" ) ;
125+ }
126+ ExprKind :: Unary ( UnOp :: Not , _) => {
127+ // This might be an inner attribute wihtout #...
128+ err. span_label ( span, "unexpected expression" ) ;
129+ }
130+ _ => {
131+ err. span_label ( span, "unexpected expression" ) . help ( format ! (
132+ "consider putting it inside a function: fn foo() {{ {} }}" ,
133+ pprust:: expr_to_string( expr)
134+ ) ) ;
135+ }
136+ } ;
137+ }
138+ StmtKind :: MacCall ( _) => {
139+ err. span_label ( span, "unexpected macro call at this position" ) ;
140+ }
141+ StmtKind :: Item ( _) => {
142+ err. span_label ( span, "unexpected item at this position" ) ;
143+ }
144+ StmtKind :: Empty => {
145+ unreachable ! ( "should have been handled by maybe_consume_incorrect_semicolon" ) ;
146+ }
147+ } ;
148+ }
149+
150+ err. note ( "for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>" ) ;
151+
152+ return Err ( err) ;
153+ }
97154}
98155
99156pub ( super ) type ItemInfo = ( Ident , ItemKind ) ;
@@ -2312,10 +2369,18 @@ impl<'a> Parser<'a> {
23122369 vis : & Visibility ,
23132370 case : Case ,
23142371 ) -> PResult < ' a , ( Ident , FnSig , Generics , Option < P < Block > > ) > {
2372+ // Let's have an example function
2373+ // const unsafe fn <'a, T> foo(arg: &'a T) -> i32
2374+ // where T: Send {
2375+ // 1+1
2376+ // }
2377+
23152378 let fn_span = self . token . span ;
2316- let header = self . parse_fn_front_matter ( vis, case) ?; // `const ... fn `
2379+ let header = self . parse_fn_front_matter ( vis, case) ?; // `const unsafe `
23172380 let ident = self . parse_ident ( ) ?; // `foo`
2318- let mut generics = self . parse_generics ( ) ?; // `<'a, T, ...>`
2381+ let mut generics = self . parse_generics ( ) ?; // `<'a, T>`
2382+
2383+ // (arg: &'a T) -> i32
23192384 let decl = match self . parse_fn_decl (
23202385 fn_parse_mode. req_name ,
23212386 AllowPlus :: Yes ,
@@ -2332,10 +2397,10 @@ impl<'a> Parser<'a> {
23322397 }
23332398 }
23342399 } ;
2335- generics. where_clause = self . parse_where_clause ( ) ?; // `where T: Ord `
2400+ generics. where_clause = self . parse_where_clause ( ) ?; // `where T: Send `
23362401
23372402 let mut sig_hi = self . prev_token . span ;
2338- let body = self . parse_fn_body ( attrs, & ident, & mut sig_hi, fn_parse_mode. req_body ) ?; // `;` or `{ ... }`.
2403+ let body = self . parse_fn_body ( attrs, & ident, & mut sig_hi, fn_parse_mode. req_body ) ?; // `{ 1+1 }` but could also be `;`
23392404 let fn_sig_span = sig_lo. to ( sig_hi) ;
23402405 Ok ( ( ident, FnSig { header, decl, span : fn_sig_span } , generics, body) )
23412406 }
0 commit comments