parser/grammar/
params.rs

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