@@ -2052,9 +2052,23 @@ impl<'a> Parser<'a> {
20522052 while self . token != token:: CloseDelim ( token:: Paren ) {
20532053 es. push ( match self . parse_expr ( ) {
20542054 Ok ( es) => es,
2055- Err ( err) => {
2055+ Err ( mut err) => {
20562056 // recover from parse error in tuple list
2057- return Ok ( self . recover_seq_parse_error ( token:: Paren , lo, Err ( err) ) ) ;
2057+ match self . token . kind {
2058+ token:: Ident ( name, false )
2059+ if name == kw:: Underscore && self . look_ahead ( 1 , |t| {
2060+ t == & token:: Comma
2061+ } ) => {
2062+ // Special-case handling of `Foo<(_, _, _)>`
2063+ err. emit ( ) ;
2064+ let sp = self . token . span ;
2065+ self . bump ( ) ;
2066+ self . mk_expr ( sp, ExprKind :: Err , ThinVec :: new ( ) )
2067+ }
2068+ _ => return Ok (
2069+ self . recover_seq_parse_error ( token:: Paren , lo, Err ( err) ) ,
2070+ ) ,
2071+ }
20582072 }
20592073 } ) ;
20602074 recovered = self . expect_one_of (
@@ -2456,37 +2470,35 @@ impl<'a> Parser<'a> {
24562470 }
24572471
24582472 /// Parses `a.b` or `a(13)` or `a[4]` or just `a`.
2459- fn parse_dot_or_call_expr ( & mut self ,
2460- already_parsed_attrs : Option < ThinVec < Attribute > > )
2461- -> PResult < ' a , P < Expr > > {
2473+ fn parse_dot_or_call_expr (
2474+ & mut self ,
2475+ already_parsed_attrs : Option < ThinVec < Attribute > > ,
2476+ ) -> PResult < ' a , P < Expr > > {
24622477 let attrs = self . parse_or_use_outer_attributes ( already_parsed_attrs) ?;
24632478
24642479 let b = self . parse_bottom_expr ( ) ;
24652480 let ( span, b) = self . interpolated_or_expr_span ( b) ?;
24662481 self . parse_dot_or_call_expr_with ( b, span, attrs)
24672482 }
24682483
2469- fn parse_dot_or_call_expr_with ( & mut self ,
2470- e0 : P < Expr > ,
2471- lo : Span ,
2472- mut attrs : ThinVec < Attribute > )
2473- -> PResult < ' a , P < Expr > > {
2484+ fn parse_dot_or_call_expr_with (
2485+ & mut self ,
2486+ e0 : P < Expr > ,
2487+ lo : Span ,
2488+ mut attrs : ThinVec < Attribute > ,
2489+ ) -> PResult < ' a , P < Expr > > {
24742490 // Stitch the list of outer attributes onto the return value.
24752491 // A little bit ugly, but the best way given the current code
24762492 // structure
2477- self . parse_dot_or_call_expr_with_ ( e0, lo)
2478- . map ( |expr|
2493+ self . parse_dot_or_call_expr_with_ ( e0, lo) . map ( |expr|
24792494 expr. map ( |mut expr| {
24802495 attrs. extend :: < Vec < _ > > ( expr. attrs . into ( ) ) ;
24812496 expr. attrs = attrs;
24822497 match expr. node {
24832498 ExprKind :: If ( ..) if !expr. attrs . is_empty ( ) => {
24842499 // Just point to the first attribute in there...
24852500 let span = expr. attrs [ 0 ] . span ;
2486-
2487- self . span_err ( span,
2488- "attributes are not yet allowed on `if` \
2489- expressions") ;
2501+ self . span_err ( span, "attributes are not yet allowed on `if` expressions" ) ;
24902502 }
24912503 _ => { }
24922504 }
@@ -2624,7 +2636,24 @@ impl<'a> Parser<'a> {
26242636 }
26252637
26262638 fn parse_paren_expr_seq ( & mut self ) -> PResult < ' a , Vec < P < Expr > > > {
2627- self . parse_paren_comma_seq ( |p| p. parse_expr ( ) ) . map ( |( r, _) | r)
2639+ self . parse_paren_comma_seq ( |p| {
2640+ match p. parse_expr ( ) {
2641+ Ok ( expr) => Ok ( expr) ,
2642+ Err ( mut err) => match p. token . kind {
2643+ token:: Ident ( name, false )
2644+ if name == kw:: Underscore && p. look_ahead ( 1 , |t| {
2645+ t == & token:: Comma
2646+ } ) => {
2647+ // Special-case handling of `foo(_, _, _)`
2648+ err. emit ( ) ;
2649+ let sp = p. token . span ;
2650+ p. bump ( ) ;
2651+ Ok ( p. mk_expr ( sp, ExprKind :: Err , ThinVec :: new ( ) ) )
2652+ }
2653+ _ => Err ( err) ,
2654+ } ,
2655+ }
2656+ } ) . map ( |( r, _) | r)
26282657 }
26292658
26302659 crate fn process_potential_macro_variable ( & mut self ) {
@@ -2806,9 +2835,10 @@ impl<'a> Parser<'a> {
28062835 /// This parses an expression accounting for associativity and precedence of the operators in
28072836 /// the expression.
28082837 #[ inline]
2809- fn parse_assoc_expr ( & mut self ,
2810- already_parsed_attrs : Option < ThinVec < Attribute > > )
2811- -> PResult < ' a , P < Expr > > {
2838+ fn parse_assoc_expr (
2839+ & mut self ,
2840+ already_parsed_attrs : Option < ThinVec < Attribute > > ,
2841+ ) -> PResult < ' a , P < Expr > > {
28122842 self . parse_assoc_expr_with ( 0 , already_parsed_attrs. into ( ) )
28132843 }
28142844
0 commit comments