@@ -1780,27 +1780,32 @@ impl<'a> Parser<'a> {
17801780 ( pat, self . parse_ty ( ) ?)
17811781 } else {
17821782 debug ! ( "parse_arg_general ident_to_pat" ) ;
1783+ let parser_snapshot_before_ty = self . clone ( ) ;
1784+ let mut ty = self . parse_ty ( ) ;
1785+ if ty. is_ok ( ) && self . token == token:: Colon {
1786+ // This wasn't actually a type, but a pattern looking like a type,
1787+ // so we are going to rollback and re-parse for recovery.
1788+ ty = self . unexpected ( ) ;
1789+ }
1790+ match ty {
1791+ Ok ( ty) => {
1792+ let ident = Ident :: new ( keywords:: Invalid . name ( ) , self . prev_span ) ;
1793+ let pat = P ( Pat {
1794+ id : ast:: DUMMY_NODE_ID ,
1795+ node : PatKind :: Ident (
1796+ BindingMode :: ByValue ( Mutability :: Immutable ) , ident, None ) ,
1797+ span : ty. span ,
1798+ } ) ;
1799+ ( pat, ty)
1800+ }
1801+ Err ( mut err) => {
1802+ // Recover from attempting to parse the argument as a type without pattern.
1803+ err. cancel ( ) ;
1804+ mem:: replace ( self , parser_snapshot_before_ty) ;
1805+ let pat = self . parse_pat ( ) ?;
1806+ self . expect ( & token:: Colon ) ?;
1807+ let ty = self . parse_ty ( ) ?;
17831808
1784- let parser_snapshot_before_pat = self . clone ( ) ;
1785-
1786- // Once we can use edition 2018 in the compiler,
1787- // replace this with real try blocks.
1788- macro_rules! try_block {
1789- ( $( $inside: tt) * ) => (
1790- ( ||{ :: std:: ops:: Try :: from_ok( { $( $inside) * } ) } ) ( )
1791- )
1792- }
1793-
1794- // We're going to try parsing the argument as a pattern (even though it's not
1795- // allowed). This way we can provide better errors to the user.
1796- let pat_arg: PResult < ' a , _ > = try_block ! {
1797- let pat = self . parse_pat( ) ?;
1798- self . expect( & token:: Colon ) ?;
1799- ( pat, self . parse_ty( ) ?)
1800- } ;
1801-
1802- match pat_arg {
1803- Ok ( ( pat, ty) ) => {
18041809 let mut err = self . diagnostic ( ) . struct_span_err_with_code (
18051810 pat. span ,
18061811 "patterns aren't allowed in methods without bodies" ,
@@ -1813,6 +1818,7 @@ impl<'a> Parser<'a> {
18131818 Applicability :: MachineApplicable ,
18141819 ) ;
18151820 err. emit ( ) ;
1821+
18161822 // Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
18171823 let pat = P ( Pat {
18181824 node : PatKind :: Wild ,
@@ -1821,22 +1827,6 @@ impl<'a> Parser<'a> {
18211827 } ) ;
18221828 ( pat, ty)
18231829 }
1824- Err ( mut err) => {
1825- err. cancel ( ) ;
1826- // Recover from attempting to parse the argument as a pattern. This means
1827- // the type is alone, with no name, e.g. `fn foo(u32)`.
1828- mem:: replace ( self , parser_snapshot_before_pat) ;
1829- debug ! ( "parse_arg_general ident_to_pat" ) ;
1830- let ident = Ident :: new ( keywords:: Invalid . name ( ) , self . prev_span ) ;
1831- let ty = self . parse_ty ( ) ?;
1832- let pat = P ( Pat {
1833- id : ast:: DUMMY_NODE_ID ,
1834- node : PatKind :: Ident (
1835- BindingMode :: ByValue ( Mutability :: Immutable ) , ident, None ) ,
1836- span : ty. span ,
1837- } ) ;
1838- ( pat, ty)
1839- }
18401830 }
18411831 } ;
18421832
0 commit comments