@@ -1744,54 +1744,74 @@ impl<'a> Parser<'a> {
1744
1744
fn parse_arg_general ( & mut self , require_name : bool ) -> PResult < ' a , Arg > {
1745
1745
maybe_whole ! ( self , NtArg , |x| x) ;
1746
1746
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) ;
1762
1750
let pat = self . parse_pat ( ) ?;
1751
+
1763
1752
self . expect ( & token:: Colon ) ?;
1764
1753
( 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
+ } ;
1766
1767
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)
1792
1810
}
1793
1811
}
1794
- }
1812
+ } ;
1813
+
1814
+ Ok ( Arg { ty, pat, id: ast:: DUMMY_NODE_ID } )
1795
1815
}
1796
1816
1797
1817
/// Parse a single function argument
0 commit comments