@@ -14,6 +14,9 @@ use errors::{Applicability, DiagnosticBuilder};
14
14
15
15
type Expected = Option < & ' static str > ;
16
16
17
+ /// `Expected` for function and lambda parameter patterns.
18
+ pub ( super ) const PARAM_EXPECTED : Expected = Some ( "parameter name" ) ;
19
+
17
20
/// Whether or not an or-pattern should be gated when occurring in the current context.
18
21
#[ derive( PartialEq ) ]
19
22
pub enum GateOr { Yes , No }
@@ -49,7 +52,7 @@ impl<'a> Parser<'a> {
49
52
let gated_leading_vert = self . eat_or_separator ( ) && gate_or == GateOr :: Yes ;
50
53
51
54
// 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 ) ?;
53
56
54
57
// If we parsed a leading `|` which should be gated,
55
58
// and no other gated or-pattern has been parsed thus far,
@@ -65,11 +68,38 @@ impl<'a> Parser<'a> {
65
68
Ok ( pat)
66
69
}
67
70
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
+
68
93
/// Parses a pattern, that may be a or-pattern (e.g. `Foo | Bar` in `Some(Foo | Bar)`).
69
94
/// 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 > > {
71
101
// Parse the first pattern.
72
- let first_pat = self . parse_pat ( None ) ?;
102
+ let first_pat = self . parse_pat ( expected ) ?;
73
103
self . maybe_recover_unexpected_comma ( first_pat. span , top_level) ?;
74
104
75
105
// If the next token is not a `|`,
@@ -81,7 +111,7 @@ impl<'a> Parser<'a> {
81
111
let lo = first_pat. span ;
82
112
let mut pats = vec ! [ first_pat] ;
83
113
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| {
85
115
err. span_label ( lo, "while parsing this or-pattern staring here" ) ;
86
116
err
87
117
} ) ?;
@@ -176,18 +206,18 @@ impl<'a> Parser<'a> {
176
206
/// Recursive possibly-or-pattern parser with recovery for an erroneous leading `|`.
177
207
/// See `parse_pat_with_or` for details on parsing or-patterns.
178
208
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 )
181
211
}
182
212
183
213
/// Recover if `|` or `||` is here.
184
214
/// 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 ) {
186
216
if let token:: BinOp ( token:: Or ) | token:: OrOr = self . token . kind {
187
217
let span = self . token . span ;
188
218
let rm_msg = format ! ( "remove the `{}`" , pprust:: token_to_string( & self . token) ) ;
189
219
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 ) )
191
221
. span_suggestion ( span, & rm_msg, String :: new ( ) , Applicability :: MachineApplicable )
192
222
. emit ( ) ;
193
223
0 commit comments