1
1
use super :: ty:: { AllowPlus , RecoverQPath , RecoverReturnSign } ;
2
2
use super :: { Parser , Restrictions , TokenType } ;
3
3
use crate :: errors:: PathSingleColon ;
4
+ use crate :: parser:: { CommaRecoveryMode , RecoverColon , RecoverComma } ;
4
5
use crate :: { errors, maybe_whole} ;
5
6
use ast:: token:: IdentIsRaw ;
6
7
use rustc_ast:: ptr:: P ;
@@ -10,7 +11,7 @@ use rustc_ast::{
10
11
AssocConstraintKind , BlockCheckMode , GenericArg , GenericArgs , Generics , ParenthesizedArgs ,
11
12
Path , PathSegment , QSelf ,
12
13
} ;
13
- use rustc_errors:: { Applicability , PResult } ;
14
+ use rustc_errors:: { Applicability , Diag , PResult } ;
14
15
use rustc_span:: symbol:: { kw, sym, Ident } ;
15
16
use rustc_span:: { BytePos , Span } ;
16
17
use std:: mem;
@@ -373,7 +374,38 @@ impl<'a> Parser<'a> {
373
374
. into ( )
374
375
} else {
375
376
// `(T, U) -> R`
376
- let ( inputs, _) = self . parse_paren_comma_seq ( |p| p. parse_ty ( ) ) ?;
377
+
378
+ let prev_token_before_parsing = self . prev_token . clone ( ) ;
379
+ let token_before_parsing = self . token . clone ( ) ;
380
+ let mut snapshot = None ;
381
+ if self . may_recover ( )
382
+ && prev_token_before_parsing. kind == token:: ModSep
383
+ && ( style == PathStyle :: Expr && self . token . can_begin_expr ( )
384
+ || style == PathStyle :: Pat && self . token . can_begin_pattern ( ) )
385
+ {
386
+ snapshot = Some ( self . create_snapshot_for_diagnostic ( ) ) ;
387
+ }
388
+
389
+ let ( inputs, _) = match self . parse_paren_comma_seq ( |p| p. parse_ty ( ) ) {
390
+ Ok ( output) => output,
391
+ Err ( mut error) if prev_token_before_parsing. kind == token:: ModSep => {
392
+ error. span_label (
393
+ prev_token_before_parsing. span . to ( token_before_parsing. span ) ,
394
+ "while parsing this parenthesized list of type arguments starting here" ,
395
+ ) ;
396
+
397
+ if let Some ( mut snapshot) = snapshot {
398
+ snapshot. recover_fn_call_leading_path_sep (
399
+ style,
400
+ prev_token_before_parsing,
401
+ & mut error,
402
+ )
403
+ }
404
+
405
+ return Err ( error) ;
406
+ }
407
+ Err ( error) => return Err ( error) ,
408
+ } ;
377
409
let inputs_span = lo. to ( self . prev_token . span ) ;
378
410
let output =
379
411
self . parse_ret_ty ( AllowPlus :: No , RecoverQPath :: No , RecoverReturnSign :: No ) ?;
@@ -399,6 +431,56 @@ impl<'a> Parser<'a> {
399
431
}
400
432
}
401
433
434
+ /// Recover `$path::(...)` as `$path(...)`.
435
+ ///
436
+ /// ```ignore (diagnostics)
437
+ /// foo::(420, "bar")
438
+ /// ^^ remove extra separator to make the function call
439
+ /// // or
440
+ /// match x {
441
+ /// Foo::(420, "bar") => { ... },
442
+ /// ^^ remove extra separator to turn this into tuple struct pattern
443
+ /// _ => { ... },
444
+ /// }
445
+ /// ```
446
+ fn recover_fn_call_leading_path_sep (
447
+ & mut self ,
448
+ style : PathStyle ,
449
+ prev_token_before_parsing : Token ,
450
+ error : & mut Diag < ' _ > ,
451
+ ) {
452
+ if ( ( style == PathStyle :: Expr && self . parse_paren_comma_seq ( |p| p. parse_expr ( ) ) . is_ok ( ) )
453
+ || ( style == PathStyle :: Pat
454
+ && self
455
+ . parse_paren_comma_seq ( |p| {
456
+ p. parse_pat_allow_top_alt (
457
+ None ,
458
+ RecoverComma :: No ,
459
+ RecoverColon :: No ,
460
+ CommaRecoveryMode :: LikelyTuple ,
461
+ )
462
+ } )
463
+ . is_ok ( ) ) )
464
+ && !matches ! ( self . token. kind, token:: ModSep | token:: RArrow )
465
+ {
466
+ error. span_suggestion_verbose (
467
+ prev_token_before_parsing. span ,
468
+ format ! (
469
+ "consider removing the `::` here to {}" ,
470
+ match style {
471
+ PathStyle :: Expr => "call the expresion" ,
472
+ PathStyle :: Pat => "turn this into a tuple struct pattern" ,
473
+ _ => {
474
+ return ;
475
+ }
476
+ }
477
+ ) ,
478
+ "" ,
479
+ Applicability :: MaybeIncorrect ,
480
+ ) ;
481
+ }
482
+ }
483
+
402
484
/// Parses generic args (within a path segment) with recovery for extra leading angle brackets.
403
485
/// For the purposes of understanding the parsing logic of generic arguments, this function
404
486
/// can be thought of being the same as just calling `self.parse_angle_args()` if the source
0 commit comments