1
1
use super :: diagnostics:: { dummy_arg, ConsumeClosingDelim } ;
2
2
use super :: ty:: { AllowPlus , RecoverQPath , RecoverReturnSign } ;
3
3
use super :: {
4
- AttrWrapper , FollowedByType , ForceCollect , Parser , PathStyle , Trailing , TrailingToken ,
4
+ AttemptLocalParseRecovery , AttrWrapper , FollowedByType , ForceCollect , Parser , PathStyle ,
5
+ Trailing , TrailingToken ,
5
6
} ;
6
7
use crate :: errors:: { self , MacroExpandsToAdtField } ;
7
8
use crate :: fluent_generated as fluent;
@@ -40,6 +41,7 @@ impl<'a> Parser<'a> {
40
41
let mod_kind = if self . eat ( & token:: Semi ) {
41
42
ModKind :: Unloaded
42
43
} else {
44
+ // mod blocks are parsed recursively
43
45
self . expect ( & token:: OpenDelim ( Delimiter :: Brace ) ) ?;
44
46
let ( inner_attrs, items, inner_span) =
45
47
self . parse_mod ( & token:: CloseDelim ( Delimiter :: Brace ) ) ?;
@@ -72,28 +74,84 @@ impl<'a> Parser<'a> {
72
74
}
73
75
74
76
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
76
79
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 ( ) ?;
90
81
}
91
82
}
92
83
93
84
let inject_use_span = post_attr_lo. data ( ) . with_hi ( post_attr_lo. lo ( ) ) ;
94
85
let mod_spans = ModSpans { inner_span : lo. to ( self . prev_token . span ) , inject_use_span } ;
95
86
Ok ( ( attrs, items, mod_spans) )
96
87
}
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
+ _ => {
132
+ err. span_label ( span, "unexpected expression" ) . help ( format ! (
133
+ "consider putting it inside a function: fn foo() {{ {} }}" ,
134
+ pprust:: expr_to_string( expr)
135
+ ) ) ;
136
+ }
137
+ } ;
138
+ }
139
+ StmtKind :: MacCall ( _) => {
140
+ err. span_label ( span, "unexpected macro call at this position" ) ;
141
+ }
142
+ StmtKind :: Item ( _) => {
143
+ err. span_label ( span, "unexpected item at this position" ) ;
144
+ }
145
+ StmtKind :: Empty => {
146
+ unreachable ! ( "should have been handled by maybe_consume_incorrect_semicolon" ) ;
147
+ }
148
+ } ;
149
+ }
150
+
151
+ err. note ( "for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>" ) ;
152
+
153
+ return Err ( err) ;
154
+ }
97
155
}
98
156
99
157
pub ( super ) type ItemInfo = ( Ident , ItemKind ) ;
@@ -2289,10 +2347,18 @@ impl<'a> Parser<'a> {
2289
2347
vis : & Visibility ,
2290
2348
case : Case ,
2291
2349
) -> PResult < ' a , ( Ident , FnSig , Generics , Option < P < Block > > ) > {
2350
+ // Let's have an example function
2351
+ // const unsafe fn <'a, T> foo(arg: &'a T) -> i32
2352
+ // where T: Send {
2353
+ // 1+1
2354
+ // }
2355
+
2292
2356
let fn_span = self . token . span ;
2293
- let header = self . parse_fn_front_matter ( vis, case) ?; // `const ... fn `
2357
+ let header = self . parse_fn_front_matter ( vis, case) ?; // `const unsafe `
2294
2358
let ident = self . parse_ident ( ) ?; // `foo`
2295
- let mut generics = self . parse_generics ( ) ?; // `<'a, T, ...>`
2359
+ let mut generics = self . parse_generics ( ) ?; // `<'a, T>`
2360
+
2361
+ // (arg: &'a T) -> i32
2296
2362
let decl = match self . parse_fn_decl (
2297
2363
fn_parse_mode. req_name ,
2298
2364
AllowPlus :: Yes ,
@@ -2309,10 +2375,10 @@ impl<'a> Parser<'a> {
2309
2375
}
2310
2376
}
2311
2377
} ;
2312
- generics. where_clause = self . parse_where_clause ( ) ?; // `where T: Ord `
2378
+ generics. where_clause = self . parse_where_clause ( ) ?; // `where T: Send `
2313
2379
2314
2380
let mut sig_hi = self . prev_token . span ;
2315
- let body = self . parse_fn_body ( attrs, & ident, & mut sig_hi, fn_parse_mode. req_body ) ?; // `;` or `{ ... }`.
2381
+ let body = self . parse_fn_body ( attrs, & ident, & mut sig_hi, fn_parse_mode. req_body ) ?; // `{ 1+1 }` but could also be `;`
2316
2382
let fn_sig_span = sig_lo. to ( sig_hi) ;
2317
2383
Ok ( ( ident, FnSig { header, decl, span : fn_sig_span } , generics, body) )
2318
2384
}
0 commit comments