@@ -44,7 +44,7 @@ use ast::{RangeEnd, RangeSyntax};
44
44
use { ast, attr} ;
45
45
use codemap:: { self , CodeMap , Spanned , respan} ;
46
46
use syntax_pos:: { self , Span , MultiSpan , BytePos , FileName , edition:: Edition } ;
47
- use errors:: { self , Applicability , DiagnosticBuilder } ;
47
+ use errors:: { self , Applicability , DiagnosticBuilder , DiagnosticId } ;
48
48
use parse:: { self , SeqSep , classify, token} ;
49
49
use parse:: lexer:: TokenAndSpan ;
50
50
use parse:: lexer:: comments:: { doc_comment_style, strip_doc_comment_decoration} ;
@@ -1371,7 +1371,7 @@ impl<'a> Parser<'a> {
1371
1371
let ident = self . parse_ident ( ) ?;
1372
1372
let mut generics = self . parse_generics ( ) ?;
1373
1373
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 > | {
1375
1375
// This is somewhat dubious; We don't want to allow
1376
1376
// argument names to be left off if there is a
1377
1377
// definition...
@@ -1753,21 +1753,59 @@ impl<'a> Parser<'a> {
1753
1753
( pat, self . parse_ty ( ) ?)
1754
1754
} else {
1755
1755
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
+ }
1764
1806
} ;
1765
1807
1766
- Ok ( Arg {
1767
- ty,
1768
- pat,
1769
- id : ast:: DUMMY_NODE_ID ,
1770
- } )
1808
+ Ok ( Arg { ty, pat, id: ast:: DUMMY_NODE_ID } )
1771
1809
}
1772
1810
1773
1811
/// Parse a single function argument
0 commit comments