@@ -242,6 +242,63 @@ impl<'a> Parser<'a> {
242
242
expected. sort_by_cached_key ( |x| x. to_string ( ) ) ;
243
243
expected. dedup ( ) ;
244
244
245
+ let sm = self . sess . source_map ( ) ;
246
+ let msg = format ! ( "expected `;`, found {}" , super :: token_descr( & self . token) ) ;
247
+ let appl = Applicability :: MachineApplicable ;
248
+ if expected. contains ( & TokenType :: Token ( token:: Semi ) ) {
249
+ if self . token . span == DUMMY_SP || self . prev_token . span == DUMMY_SP {
250
+ // Likely inside a macro, can't provide meaningful suggestions.
251
+ } else if !sm. is_multiline ( self . prev_token . span . until ( self . token . span ) ) {
252
+ // The current token is in the same line as the prior token, not recoverable.
253
+ } else if [ token:: Comma , token:: Colon ] . contains ( & self . token . kind )
254
+ && self . prev_token . kind == token:: CloseDelim ( token:: Paren )
255
+ {
256
+ // Likely typo: The current token is on a new line and is expected to be
257
+ // `.`, `;`, `?`, or an operator after a close delimiter token.
258
+ //
259
+ // let a = std::process::Command::new("echo")
260
+ // .arg("1")
261
+ // ,arg("2")
262
+ // ^
263
+ // https://github.com/rust-lang/rust/issues/72253
264
+ } else if self . look_ahead ( 1 , |t| {
265
+ t == & token:: CloseDelim ( token:: Brace )
266
+ || t. can_begin_expr ( ) && t. kind != token:: Colon
267
+ } ) && [ token:: Comma , token:: Colon ] . contains ( & self . token . kind )
268
+ {
269
+ // Likely typo: `,` → `;` or `:` → `;`. This is triggered if the current token is
270
+ // either `,` or `:`, and the next token could either start a new statement or is a
271
+ // block close. For example:
272
+ //
273
+ // let x = 32:
274
+ // let y = 42;
275
+ self . bump ( ) ;
276
+ let sp = self . prev_token . span ;
277
+ self . struct_span_err ( sp, & msg)
278
+ . span_suggestion_short ( sp, "change this to `;`" , ";" . to_string ( ) , appl)
279
+ . emit ( ) ;
280
+ return Ok ( false ) ;
281
+ } else if self . look_ahead ( 0 , |t| {
282
+ t == & token:: CloseDelim ( token:: Brace )
283
+ || (
284
+ t. can_begin_expr ( ) && t != & token:: Semi && t != & token:: Pound
285
+ // Avoid triggering with too many trailing `#` in raw string.
286
+ )
287
+ } ) {
288
+ // Missing semicolon typo. This is triggered if the next token could either start a
289
+ // new statement or is a block close. For example:
290
+ //
291
+ // let x = 32
292
+ // let y = 42;
293
+ let sp = self . prev_token . span . shrink_to_hi ( ) ;
294
+ self . struct_span_err ( sp, & msg)
295
+ . span_label ( self . token . span , "unexpected token" )
296
+ . span_suggestion_short ( sp, "add `;` here" , ";" . to_string ( ) , appl)
297
+ . emit ( ) ;
298
+ return Ok ( false ) ;
299
+ }
300
+ }
301
+
245
302
let expect = tokens_to_string ( & expected[ ..] ) ;
246
303
let actual = super :: token_descr ( & self . token ) ;
247
304
let ( msg_exp, ( label_sp, label_exp) ) = if expected. len ( ) > 1 {
@@ -303,7 +360,6 @@ impl<'a> Parser<'a> {
303
360
return Err ( err) ;
304
361
}
305
362
306
- let sm = self . sess . source_map ( ) ;
307
363
if self . prev_token . span == DUMMY_SP {
308
364
// Account for macro context where the previous span might not be
309
365
// available to avoid incorrect output (#54841).
@@ -1144,62 +1200,6 @@ impl<'a> Parser<'a> {
1144
1200
if self . eat ( & token:: Semi ) {
1145
1201
return Ok ( ( ) ) ;
1146
1202
}
1147
- let sm = self . sess . source_map ( ) ;
1148
- let msg = format ! ( "expected `;`, found {}" , super :: token_descr( & self . token) ) ;
1149
- let appl = Applicability :: MachineApplicable ;
1150
- if self . token . span == DUMMY_SP || self . prev_token . span == DUMMY_SP {
1151
- // Likely inside a macro, can't provide meaningful suggestions.
1152
- return self . expect ( & token:: Semi ) . map ( drop) ;
1153
- } else if !sm. is_multiline ( self . prev_token . span . until ( self . token . span ) ) {
1154
- // The current token is in the same line as the prior token, not recoverable.
1155
- } else if [ token:: Comma , token:: Colon ] . contains ( & self . token . kind )
1156
- && self . prev_token . kind == token:: CloseDelim ( token:: Paren )
1157
- {
1158
- // Likely typo: The current token is on a new line and is expected to be
1159
- // `.`, `;`, `?`, or an operator after a close delimiter token.
1160
- //
1161
- // let a = std::process::Command::new("echo")
1162
- // .arg("1")
1163
- // ,arg("2")
1164
- // ^
1165
- // https://github.com/rust-lang/rust/issues/72253
1166
- self . expect ( & token:: Semi ) ?;
1167
- return Ok ( ( ) ) ;
1168
- } else if self . look_ahead ( 1 , |t| {
1169
- t == & token:: CloseDelim ( token:: Brace ) || t. can_begin_expr ( ) && t. kind != token:: Colon
1170
- } ) && [ token:: Comma , token:: Colon ] . contains ( & self . token . kind )
1171
- {
1172
- // Likely typo: `,` → `;` or `:` → `;`. This is triggered if the current token is
1173
- // either `,` or `:`, and the next token could either start a new statement or is a
1174
- // block close. For example:
1175
- //
1176
- // let x = 32:
1177
- // let y = 42;
1178
- self . bump ( ) ;
1179
- let sp = self . prev_token . span ;
1180
- self . struct_span_err ( sp, & msg)
1181
- . span_suggestion_short ( sp, "change this to `;`" , ";" . to_string ( ) , appl)
1182
- . emit ( ) ;
1183
- return Ok ( ( ) ) ;
1184
- } else if self . look_ahead ( 0 , |t| {
1185
- t == & token:: CloseDelim ( token:: Brace )
1186
- || (
1187
- t. can_begin_expr ( ) && t != & token:: Semi && t != & token:: Pound
1188
- // Avoid triggering with too many trailing `#` in raw string.
1189
- )
1190
- } ) {
1191
- // Missing semicolon typo. This is triggered if the next token could either start a
1192
- // new statement or is a block close. For example:
1193
- //
1194
- // let x = 32
1195
- // let y = 42;
1196
- let sp = self . prev_token . span . shrink_to_hi ( ) ;
1197
- self . struct_span_err ( sp, & msg)
1198
- . span_label ( self . token . span , "unexpected token" )
1199
- . span_suggestion_short ( sp, "add `;` here" , ";" . to_string ( ) , appl)
1200
- . emit ( ) ;
1201
- return Ok ( ( ) ) ;
1202
- }
1203
1203
self . expect ( & token:: Semi ) . map ( drop) // Error unconditionally
1204
1204
}
1205
1205
0 commit comments