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