@@ -1744,54 +1744,74 @@ impl<'a> Parser<'a> {
17441744 fn parse_arg_general ( & mut self , require_name : bool ) -> PResult < ' a , Arg > {
17451745 maybe_whole ! ( self , NtArg , |x| x) ;
17461746
1747- // If we see `ident :`, then we know that the argument is not just of the
1748- // form `type`, which means we won't need to recover from parsing a
1749- // pattern and so we don't need to store a parser snapshot.
1750- let parser_snapshot_before_pat = if
1751- self . look_ahead ( 1 , |t| t. is_ident ( ) ) &&
1752- self . look_ahead ( 2 , |t| t == & token:: Colon ) {
1753- None
1754- } else {
1755- Some ( self . clone ( ) )
1756- } ;
1757-
1758- // We're going to try parsing the argument as a pattern (even if it's not
1759- // allowed, such as for trait methods without bodies). This way we can provide
1760- // better errors to the user.
1761- let pat_arg: PResult < ' a , ( P < Pat > , P < Ty > ) > = do catch {
1747+ let ( pat, ty) = if require_name || self . is_named_argument ( ) {
1748+ debug ! ( "parse_arg_general parse_pat (require_name:{})" ,
1749+ require_name) ;
17621750 let pat = self . parse_pat ( ) ?;
1751+
17631752 self . expect ( & token:: Colon ) ?;
17641753 ( pat, self . parse_ty ( ) ?)
1765- } ;
1754+ } else {
1755+ debug ! ( "parse_arg_general ident_to_pat" ) ;
1756+
1757+ // If we see `ident :`, then we know that the argument is not just of the
1758+ // form `type`, which means we won't need to recover from parsing a
1759+ // pattern and so we don't need to store a parser snapshot.
1760+ let parser_snapshot_before_pat = if
1761+ self . look_ahead ( 1 , |t| t. is_ident ( ) ) &&
1762+ self . look_ahead ( 2 , |t| t == & token:: Colon ) {
1763+ None
1764+ } else {
1765+ Some ( self . clone ( ) )
1766+ } ;
17661767
1767- match pat_arg {
1768- Ok ( ( pat, ty) ) => {
1769- Ok ( Arg { ty, pat, id: ast:: DUMMY_NODE_ID } )
1770- }
1771- Err ( mut err) => {
1772- match ( require_name || self . is_named_argument ( ) , parser_snapshot_before_pat) {
1773- ( true , _) | ( _, None ) => {
1774- Err ( err)
1775- }
1776- ( false , Some ( parser_snapshot_before_pat) ) => {
1777- err. cancel ( ) ;
1778- // Recover from attempting to parse the argument as a pattern. This means
1779- // the type is alone, with no name, e.g. `fn foo(u32)`.
1780- mem:: replace ( self , parser_snapshot_before_pat) ;
1781- debug ! ( "parse_arg_general ident_to_pat" ) ;
1782- let ident = Ident :: new ( keywords:: Invalid . name ( ) , self . prev_span ) ;
1783- let ty = self . parse_ty ( ) ?;
1784- let pat = P ( Pat {
1785- id : ast:: DUMMY_NODE_ID ,
1786- node : PatKind :: Ident (
1787- BindingMode :: ByValue ( Mutability :: Immutable ) , ident, None ) ,
1788- span : ty. span ,
1789- } ) ;
1790- Ok ( Arg { ty, pat, id : ast:: DUMMY_NODE_ID } )
1791- }
1768+ // We're going to try parsing the argument as a pattern (even though it's not
1769+ // allowed). This way we can provide better errors to the user.
1770+ let pat_arg: PResult < ' a , _ > = do catch {
1771+ let pat = self . parse_pat ( ) ?;
1772+ self . expect ( & token:: Colon ) ?;
1773+ ( pat, self . parse_ty ( ) ?)
1774+ } ;
1775+
1776+ match pat_arg {
1777+ Ok ( ( pat, ty) ) => {
1778+ let mut err = self . diagnostic ( )
1779+ . struct_span_err ( pat. span , "patterns aren't allowed in trait methods" ) ;
1780+ err. span_suggestion_short_with_applicability (
1781+ pat. span ,
1782+ "give this argument a name or use an underscore to ignore it" ,
1783+ "_" . to_owned ( ) ,
1784+ Applicability :: MachineApplicable ,
1785+ ) ;
1786+ err. emit ( ) ;
1787+ // Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
1788+ let pat = P ( Pat {
1789+ node : PatKind :: Wild ,
1790+ span : pat. span ,
1791+ id : ast:: DUMMY_NODE_ID
1792+ } ) ;
1793+ ( pat, ty)
1794+ }
1795+ Err ( mut err) => {
1796+ err. cancel ( ) ;
1797+ // Recover from attempting to parse the argument as a pattern. This means
1798+ // the type is alone, with no name, e.g. `fn foo(u32)`.
1799+ mem:: replace ( self , parser_snapshot_before_pat. unwrap ( ) ) ;
1800+ debug ! ( "parse_arg_general ident_to_pat" ) ;
1801+ let ident = Ident :: new ( keywords:: Invalid . name ( ) , self . prev_span ) ;
1802+ let ty = self . parse_ty ( ) ?;
1803+ let pat = P ( Pat {
1804+ id : ast:: DUMMY_NODE_ID ,
1805+ node : PatKind :: Ident (
1806+ BindingMode :: ByValue ( Mutability :: Immutable ) , ident, None ) ,
1807+ span : ty. span ,
1808+ } ) ;
1809+ ( pat, ty)
17921810 }
17931811 }
1794- }
1812+ } ;
1813+
1814+ Ok ( Arg { ty, pat, id: ast:: DUMMY_NODE_ID } )
17951815 }
17961816
17971817 /// Parse a single function argument
0 commit comments