]> git.lizzy.rs Git - rust.git/blob - crates/parser/src/grammar/params.rs
01ee26a5304e972a552ab32392765ede1a032bc1
[rust.git] / crates / parser / src / grammar / params.rs
1 use super::*;
2
3 // test param_list
4 // fn a() {}
5 // fn b(x: i32) {}
6 // fn c(x: i32, ) {}
7 // fn d(x: i32, y: ()) {}
8 pub(super) fn param_list_fn_def(p: &mut Parser) {
9     list_(p, Flavor::FnDef)
10 }
11
12 // test param_list_opt_patterns
13 // fn foo<F: FnMut(&mut Foo<'a>)>(){}
14 pub(super) fn param_list_fn_trait(p: &mut Parser) {
15     list_(p, Flavor::FnTrait)
16 }
17
18 pub(super) fn param_list_fn_ptr(p: &mut Parser) {
19     list_(p, Flavor::FnPointer)
20 }
21
22 pub(super) fn param_list_closure(p: &mut Parser) {
23     list_(p, Flavor::Closure)
24 }
25
26 #[derive(Debug, Clone, Copy)]
27 enum Flavor {
28     FnDef,   // Includes trait fn params; omitted param idents are not supported
29     FnTrait, // Params for `Fn(...)`/`FnMut(...)`/`FnOnce(...)` annotations
30     FnPointer,
31     Closure,
32 }
33
34 fn list_(p: &mut Parser, flavor: Flavor) {
35     use Flavor::*;
36
37     let (bra, ket) = match flavor {
38         Closure => (T![|], T![|]),
39         FnDef | FnTrait | FnPointer => (T!['('], T![')']),
40     };
41
42     let list_marker = p.start();
43     p.bump(bra);
44
45     let mut param_marker = None;
46     if let FnDef = flavor {
47         // test self_param_outer_attr
48         // fn f(#[must_use] self) {}
49         let m = p.start();
50         attributes::outer_attrs(p);
51         match opt_self_param(p, m) {
52             Ok(()) => {}
53             Err(m) => param_marker = Some(m),
54         }
55     }
56
57     while !p.at(EOF) && !p.at(ket) {
58         // test param_outer_arg
59         // fn f(#[attr1] pat: Type) {}
60         let m = match param_marker.take() {
61             Some(m) => m,
62             None => {
63                 let m = p.start();
64                 attributes::outer_attrs(p);
65                 m
66             }
67         };
68
69         if !p.at_ts(PARAM_FIRST) {
70             p.error("expected value parameter");
71             m.abandon(p);
72             break;
73         }
74         let param = param(p, m, flavor);
75         if !p.at(ket) {
76             p.expect(T![,]);
77         }
78         if let Variadic(true) = param {
79             break;
80         }
81     }
82
83     if let Some(m) = param_marker {
84         m.abandon(p);
85     }
86
87     p.expect(ket);
88     list_marker.complete(p, PARAM_LIST);
89 }
90
91 const PARAM_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST);
92
93 struct Variadic(bool);
94
95 fn param(p: &mut Parser, m: Marker, flavor: Flavor) -> Variadic {
96     let mut res = Variadic(false);
97     match flavor {
98         // test param_list_vararg
99         // extern "C" { fn printf(format: *const i8, ...) -> i32; }
100         Flavor::FnDef | Flavor::FnPointer if p.eat(T![...]) => res = Variadic(true),
101
102         // test fn_def_param
103         // fn foo((x, y): (i32, i32)) {}
104         Flavor::FnDef => {
105             patterns::pattern(p);
106             if variadic_param(p) {
107                 res = Variadic(true)
108             } else {
109                 types::ascription(p);
110             }
111         }
112         // test value_parameters_no_patterns
113         // type F = Box<Fn(i32, &i32, &i32, ())>;
114         Flavor::FnTrait => {
115             types::type_(p);
116         }
117         // test fn_pointer_param_ident_path
118         // type Foo = fn(Bar::Baz);
119         // type Qux = fn(baz: Bar::Baz);
120
121         // test fn_pointer_unnamed_arg
122         // type Foo = fn(_: bar);
123         Flavor::FnPointer => {
124             if (p.at(IDENT) || p.at(UNDERSCORE)) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) {
125                 patterns::pattern_single(p);
126                 if variadic_param(p) {
127                     res = Variadic(true)
128                 } else {
129                     types::ascription(p);
130                 }
131             } else {
132                 types::type_(p);
133             }
134         }
135         // test closure_params
136         // fn main() {
137         //    let foo = |bar, baz: Baz, qux: Qux::Quux| ();
138         // }
139         Flavor::Closure => {
140             patterns::pattern_single(p);
141             if p.at(T![:]) && !p.at(T![::]) {
142                 types::ascription(p);
143             }
144         }
145     }
146     m.complete(p, PARAM);
147     res
148 }
149
150 fn variadic_param(p: &mut Parser) -> bool {
151     if p.at(T![:]) && p.nth_at(1, T![...]) {
152         p.bump(T![:]);
153         p.bump(T![...]);
154         true
155     } else {
156         false
157     }
158 }
159
160 // test self_param
161 // impl S {
162 //     fn a(self) {}
163 //     fn b(&self,) {}
164 //     fn c(&'a self,) {}
165 //     fn d(&'a mut self, x: i32) {}
166 //     fn e(mut self) {}
167 // }
168 fn opt_self_param(p: &mut Parser, m: Marker) -> Result<(), Marker> {
169     if p.at(T![self]) || p.at(T![mut]) && p.nth(1) == T![self] {
170         p.eat(T![mut]);
171         self_as_name(p);
172         // test arb_self_types
173         // impl S {
174         //     fn a(self: &Self) {}
175         //     fn b(mut self: Box<Self>) {}
176         // }
177         if p.at(T![:]) {
178             types::ascription(p);
179         }
180     } else {
181         let la1 = p.nth(1);
182         let la2 = p.nth(2);
183         let la3 = p.nth(3);
184         if !matches!(
185             (p.current(), la1, la2, la3),
186             (T![&], T![self], _, _)
187                 | (T![&], T![mut], T![self], _)
188                 | (T![&], LIFETIME_IDENT, T![self], _)
189                 | (T![&], LIFETIME_IDENT, T![mut], T![self])
190         ) {
191             return Err(m);
192         }
193         p.bump(T![&]);
194         if p.at(LIFETIME_IDENT) {
195             lifetime(p);
196         }
197         p.eat(T![mut]);
198         self_as_name(p);
199     }
200     m.complete(p, SELF_PARAM);
201     if !p.at(T![')']) {
202         p.expect(T![,]);
203     }
204     Ok(())
205 }
206
207 fn self_as_name(p: &mut Parser) {
208     let m = p.start();
209     p.bump(T![self]);
210     m.complete(p, NAME);
211 }