@@ -14,6 +14,9 @@ use errors::{Applicability, DiagnosticBuilder};
1414
1515type Expected = Option < & ' static str > ;
1616
17+ /// `Expected` for function and lambda parameter patterns.
18+ pub ( super ) const PARAM_EXPECTED : Expected = Some ( "parameter name" ) ;
19+
1720/// Whether or not an or-pattern should be gated when occurring in the current context.
1821#[ derive( PartialEq ) ]
1922pub enum GateOr { Yes , No }
@@ -49,7 +52,7 @@ impl<'a> Parser<'a> {
4952 let gated_leading_vert = self . eat_or_separator ( ) && gate_or == GateOr :: Yes ;
5053
5154 // Parse the possibly-or-pattern.
52- let pat = self . parse_pat_with_or ( gate_or, TopLevel :: Yes ) ?;
55+ let pat = self . parse_pat_with_or ( None , gate_or, TopLevel :: Yes ) ?;
5356
5457 // If we parsed a leading `|` which should be gated,
5558 // and no other gated or-pattern has been parsed thus far,
@@ -65,11 +68,38 @@ impl<'a> Parser<'a> {
6568 Ok ( pat)
6669 }
6770
71+ /// Parse the pattern for a function or function pointer parameter.
72+ /// Special recovery is provided for or-patterns and leading `|`.
73+ pub ( super ) fn parse_fn_param_pat ( & mut self ) -> PResult < ' a , P < Pat > > {
74+ self . recover_leading_vert ( "not allowed in a parameter pattern" ) ;
75+ let pat = self . parse_pat_with_or ( PARAM_EXPECTED , GateOr :: No , TopLevel :: No ) ?;
76+
77+ if let PatKind :: Or ( ..) = & pat. node {
78+ self . ban_illegal_fn_param_or_pat ( & pat) ;
79+ }
80+
81+ Ok ( pat)
82+ }
83+
84+ /// Ban `A | B` immediately in a parameter pattern and suggest wrapping in parens.
85+ fn ban_illegal_fn_param_or_pat ( & self , pat : & Pat ) {
86+ let msg = "wrap the pattern in parenthesis" ;
87+ let fix = format ! ( "({})" , pprust:: pat_to_string( pat) ) ;
88+ self . struct_span_err ( pat. span , "an or-pattern parameter must be wrapped in parenthesis" )
89+ . span_suggestion ( pat. span , msg, fix, Applicability :: MachineApplicable )
90+ . emit ( ) ;
91+ }
92+
6893 /// Parses a pattern, that may be a or-pattern (e.g. `Foo | Bar` in `Some(Foo | Bar)`).
6994 /// Corresponds to `pat<allow_top_alt>` in RFC 2535.
70- fn parse_pat_with_or ( & mut self , gate_or : GateOr , top_level : TopLevel ) -> PResult < ' a , P < Pat > > {
95+ fn parse_pat_with_or (
96+ & mut self ,
97+ expected : Expected ,
98+ gate_or : GateOr ,
99+ top_level : TopLevel ,
100+ ) -> PResult < ' a , P < Pat > > {
71101 // Parse the first pattern.
72- let first_pat = self . parse_pat ( None ) ?;
102+ let first_pat = self . parse_pat ( expected ) ?;
73103 self . maybe_recover_unexpected_comma ( first_pat. span , top_level) ?;
74104
75105 // If the next token is not a `|`,
@@ -81,7 +111,7 @@ impl<'a> Parser<'a> {
81111 let lo = first_pat. span ;
82112 let mut pats = vec ! [ first_pat] ;
83113 while self . eat_or_separator ( ) {
84- let pat = self . parse_pat ( None ) . map_err ( |mut err| {
114+ let pat = self . parse_pat ( expected ) . map_err ( |mut err| {
85115 err. span_label ( lo, "while parsing this or-pattern staring here" ) ;
86116 err
87117 } ) ?;
@@ -176,18 +206,18 @@ impl<'a> Parser<'a> {
176206 /// Recursive possibly-or-pattern parser with recovery for an erroneous leading `|`.
177207 /// See `parse_pat_with_or` for details on parsing or-patterns.
178208 fn parse_pat_with_or_inner ( & mut self ) -> PResult < ' a , P < Pat > > {
179- self . recover_inner_leading_vert ( ) ;
180- self . parse_pat_with_or ( GateOr :: Yes , TopLevel :: No )
209+ self . recover_leading_vert ( "only allowed in a top-level pattern" ) ;
210+ self . parse_pat_with_or ( None , GateOr :: Yes , TopLevel :: No )
181211 }
182212
183213 /// Recover if `|` or `||` is here.
184214 /// The user is thinking that a leading `|` is allowed in this position.
185- fn recover_inner_leading_vert ( & mut self ) {
215+ fn recover_leading_vert ( & mut self , ctx : & str ) {
186216 if let token:: BinOp ( token:: Or ) | token:: OrOr = self . token . kind {
187217 let span = self . token . span ;
188218 let rm_msg = format ! ( "remove the `{}`" , pprust:: token_to_string( & self . token) ) ;
189219
190- self . struct_span_err ( span, "a leading `|` is only allowed in a top-level pattern" )
220+ self . struct_span_err ( span, & format ! ( "a leading `|` is {}" , ctx ) )
191221 . span_suggestion ( span, & rm_msg, String :: new ( ) , Applicability :: MachineApplicable )
192222 . emit ( ) ;
193223
0 commit comments