@@ -44,7 +44,7 @@ use ast::{RangeEnd, RangeSyntax};
4444use  { ast,  attr} ; 
4545use  codemap:: { self ,  CodeMap ,  Spanned ,  respan} ; 
4646use  syntax_pos:: { self ,  Span ,  MultiSpan ,  BytePos ,  FileName ,  edition:: Edition } ; 
47- use  errors:: { self ,  Applicability ,  DiagnosticBuilder } ; 
47+ use  errors:: { self ,  Applicability ,  DiagnosticBuilder ,   DiagnosticId } ; 
4848use  parse:: { self ,  SeqSep ,  classify,  token} ; 
4949use  parse:: lexer:: TokenAndSpan ; 
5050use  parse:: lexer:: comments:: { doc_comment_style,  strip_doc_comment_decoration} ; 
@@ -1371,7 +1371,7 @@ impl<'a> Parser<'a> {
13711371            let  ident = self . parse_ident ( ) ?; 
13721372            let  mut  generics = self . parse_generics ( ) ?; 
13731373
1374-             let  d = self . parse_fn_decl_with_self ( |p :  & mut  Parser < ' a > |{ 
1374+             let  d = self . parse_fn_decl_with_self ( |p :  & mut  Parser < ' a > |  { 
13751375                // This is somewhat dubious; We don't want to allow 
13761376                // argument names to be left off if there is a 
13771377                // definition... 
@@ -1753,21 +1753,59 @@ impl<'a> Parser<'a> {
17531753            ( pat,  self . parse_ty ( ) ?) 
17541754        }  else  { 
17551755            debug ! ( "parse_arg_general ident_to_pat" ) ; 
1756-             let  ident = Ident :: new ( keywords:: Invalid . name ( ) ,  self . prev_span ) ; 
1757-             let  ty = self . parse_ty ( ) ?; 
1758-             let  pat = P ( Pat  { 
1759-                 id :  ast:: DUMMY_NODE_ID , 
1760-                 node :  PatKind :: Ident ( BindingMode :: ByValue ( Mutability :: Immutable ) ,  ident,  None ) , 
1761-                 span :  ty. span , 
1762-             } ) ; 
1763-             ( pat,  ty) 
1756+ 
1757+             let  parser_snapshot_before_pat = self . clone ( ) ; 
1758+ 
1759+             // We're going to try parsing the argument as a pattern (even though it's not 
1760+             // allowed). This way we can provide better errors to the user. 
1761+             let  pat_arg:  PResult < ' a ,  _ >  = do catch { 
1762+                 let pat = self . parse_pat ( ) ?; 
1763+                 self . expect ( & token:: Colon ) ?; 
1764+                 ( pat,  self . parse_ty ( ) ?) 
1765+             } ; 
1766+ 
1767+             match  pat_arg { 
1768+                 Ok ( ( pat,  ty) )  => { 
1769+                     let  mut  err = self . diagnostic ( ) . struct_span_err_with_code ( 
1770+                         pat. span , 
1771+                         "patterns aren't allowed in methods without bodies" , 
1772+                         DiagnosticId :: Error ( "E0642" . into ( ) ) , 
1773+                     ) ; 
1774+                     err. span_suggestion_short_with_applicability ( 
1775+                         pat. span , 
1776+                         "give this argument a name or use an underscore to ignore it" , 
1777+                         "_" . to_owned ( ) , 
1778+                         Applicability :: MachineApplicable , 
1779+                     ) ; 
1780+                     err. emit ( ) ; 
1781+                     // Pretend the pattern is `_`, to avoid duplicate errors from AST validation. 
1782+                     let  pat = P ( Pat  { 
1783+                         node :  PatKind :: Wild , 
1784+                         span :  pat. span , 
1785+                         id :  ast:: DUMMY_NODE_ID 
1786+                     } ) ; 
1787+                     ( pat,  ty) 
1788+                 } 
1789+                 Err ( mut  err)  => { 
1790+                     err. cancel ( ) ; 
1791+                     // Recover from attempting to parse the argument as a pattern. This means 
1792+                     // the type is alone, with no name, e.g. `fn foo(u32)`. 
1793+                     mem:: replace ( self ,  parser_snapshot_before_pat) ; 
1794+                     debug ! ( "parse_arg_general ident_to_pat" ) ; 
1795+                     let  ident = Ident :: new ( keywords:: Invalid . name ( ) ,  self . prev_span ) ; 
1796+                     let  ty = self . parse_ty ( ) ?; 
1797+                     let  pat = P ( Pat  { 
1798+                         id :  ast:: DUMMY_NODE_ID , 
1799+                         node :  PatKind :: Ident ( 
1800+                             BindingMode :: ByValue ( Mutability :: Immutable ) ,  ident,  None ) , 
1801+                         span :  ty. span , 
1802+                     } ) ; 
1803+                     ( pat,  ty) 
1804+                 } 
1805+             } 
17641806        } ; 
17651807
1766-         Ok ( Arg  { 
1767-             ty, 
1768-             pat, 
1769-             id :  ast:: DUMMY_NODE_ID , 
1770-         } ) 
1808+         Ok ( Arg  {  ty,  pat,  id:  ast:: DUMMY_NODE_ID  } ) 
17711809    } 
17721810
17731811    /// Parse a single function argument 
0 commit comments