• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::grammar::attributes::ATTRIBUTE_FIRST;
2 
3 use super::*;
4 
opt_generic_param_list(p: &mut Parser<'_>)5 pub(super) fn opt_generic_param_list(p: &mut Parser<'_>) {
6     if p.at(T![<]) {
7         generic_param_list(p);
8     }
9 }
10 
11 // test generic_param_list
12 // fn f<T: Clone>() {}
generic_param_list(p: &mut Parser<'_>)13 fn generic_param_list(p: &mut Parser<'_>) {
14     assert!(p.at(T![<]));
15     let m = p.start();
16     delimited(p, T![<], T![>], T![,], GENERIC_PARAM_FIRST.union(ATTRIBUTE_FIRST), |p| {
17         // test generic_param_attribute
18         // fn foo<#[lt_attr] 'a, #[t_attr] T>() {}
19         let m = p.start();
20         attributes::outer_attrs(p);
21         generic_param(p, m)
22     });
23 
24     m.complete(p, GENERIC_PARAM_LIST);
25 }
26 
27 const GENERIC_PARAM_FIRST: TokenSet = TokenSet::new(&[IDENT, LIFETIME_IDENT, T![const]]);
28 
generic_param(p: &mut Parser<'_>, m: Marker) -> bool29 fn generic_param(p: &mut Parser<'_>, m: Marker) -> bool {
30     match p.current() {
31         LIFETIME_IDENT => lifetime_param(p, m),
32         IDENT => type_param(p, m),
33         T![const] => const_param(p, m),
34         _ => {
35             m.abandon(p);
36             p.err_and_bump("expected generic parameter");
37             return false;
38         }
39     }
40     true
41 }
42 
43 // test lifetime_param
44 // fn f<'a: 'b>() {}
lifetime_param(p: &mut Parser<'_>, m: Marker)45 fn lifetime_param(p: &mut Parser<'_>, m: Marker) {
46     assert!(p.at(LIFETIME_IDENT));
47     lifetime(p);
48     if p.at(T![:]) {
49         lifetime_bounds(p);
50     }
51     m.complete(p, LIFETIME_PARAM);
52 }
53 
54 // test type_param
55 // fn f<T: Clone>() {}
type_param(p: &mut Parser<'_>, m: Marker)56 fn type_param(p: &mut Parser<'_>, m: Marker) {
57     assert!(p.at(IDENT));
58     name(p);
59     if p.at(T![:]) {
60         bounds(p);
61     }
62     if p.at(T![=]) {
63         // test type_param_default
64         // struct S<T = i32>;
65         p.bump(T![=]);
66         types::type_(p);
67     }
68     m.complete(p, TYPE_PARAM);
69 }
70 
71 // test const_param
72 // struct S<const N: u32>;
const_param(p: &mut Parser<'_>, m: Marker)73 fn const_param(p: &mut Parser<'_>, m: Marker) {
74     p.bump(T![const]);
75     name(p);
76     if p.at(T![:]) {
77         types::ascription(p);
78     } else {
79         p.error("missing type for const parameter");
80     }
81 
82     if p.at(T![=]) {
83         // test const_param_default_literal
84         // struct A<const N: i32 = -1>;
85         p.bump(T![=]);
86 
87         // test const_param_default_expression
88         // struct A<const N: i32 = { 1 }>;
89 
90         // test const_param_default_path
91         // struct A<const N: i32 = i32::MAX>;
92         generic_args::const_arg_expr(p);
93     }
94 
95     m.complete(p, CONST_PARAM);
96 }
97 
lifetime_bounds(p: &mut Parser<'_>)98 fn lifetime_bounds(p: &mut Parser<'_>) {
99     assert!(p.at(T![:]));
100     p.bump(T![:]);
101     while p.at(LIFETIME_IDENT) {
102         lifetime(p);
103         if !p.eat(T![+]) {
104             break;
105         }
106     }
107 }
108 
109 // test type_param_bounds
110 // struct S<T: 'a + ?Sized + (Copy) + ~const Drop>;
bounds(p: &mut Parser<'_>)111 pub(super) fn bounds(p: &mut Parser<'_>) {
112     assert!(p.at(T![:]));
113     p.bump(T![:]);
114     bounds_without_colon(p);
115 }
116 
bounds_without_colon(p: &mut Parser<'_>)117 pub(super) fn bounds_without_colon(p: &mut Parser<'_>) {
118     let m = p.start();
119     bounds_without_colon_m(p, m);
120 }
121 
bounds_without_colon_m(p: &mut Parser<'_>, marker: Marker) -> CompletedMarker122 pub(super) fn bounds_without_colon_m(p: &mut Parser<'_>, marker: Marker) -> CompletedMarker {
123     while type_bound(p) {
124         if !p.eat(T![+]) {
125             break;
126         }
127     }
128     marker.complete(p, TYPE_BOUND_LIST)
129 }
130 
type_bound(p: &mut Parser<'_>) -> bool131 fn type_bound(p: &mut Parser<'_>) -> bool {
132     let m = p.start();
133     let has_paren = p.eat(T!['(']);
134     match p.current() {
135         LIFETIME_IDENT => lifetime(p),
136         T![for] => types::for_type(p, false),
137         T![?] if p.nth_at(1, T![for]) => {
138             // test question_for_type_trait_bound
139             // fn f<T>() where T: ?for<> Sized {}
140             p.bump_any();
141             types::for_type(p, false)
142         }
143         current => {
144             match current {
145                 T![?] => p.bump_any(),
146                 T![~] => {
147                     p.bump_any();
148                     p.expect(T![const]);
149                 }
150                 _ => (),
151             }
152             if paths::is_use_path_start(p) {
153                 types::path_type_(p, false);
154             } else {
155                 m.abandon(p);
156                 return false;
157             }
158         }
159     }
160     if has_paren {
161         p.expect(T![')']);
162     }
163     m.complete(p, TYPE_BOUND);
164 
165     true
166 }
167 
168 // test where_clause
169 // fn foo()
170 // where
171 //    'a: 'b + 'c,
172 //    T: Clone + Copy + 'static,
173 //    Iterator::Item: 'a,
174 //    <T as Iterator>::Item: 'a
175 // {}
opt_where_clause(p: &mut Parser<'_>)176 pub(super) fn opt_where_clause(p: &mut Parser<'_>) {
177     if !p.at(T![where]) {
178         return;
179     }
180     let m = p.start();
181     p.bump(T![where]);
182 
183     while is_where_predicate(p) {
184         where_predicate(p);
185 
186         let comma = p.eat(T![,]);
187 
188         match p.current() {
189             T!['{'] | T![;] | T![=] => break,
190             _ => (),
191         }
192 
193         if !comma {
194             p.error("expected comma");
195         }
196     }
197 
198     m.complete(p, WHERE_CLAUSE);
199 
200     fn is_where_predicate(p: &mut Parser<'_>) -> bool {
201         match p.current() {
202             LIFETIME_IDENT => true,
203             T![impl] => false,
204             token => types::TYPE_FIRST.contains(token),
205         }
206     }
207 }
208 
where_predicate(p: &mut Parser<'_>)209 fn where_predicate(p: &mut Parser<'_>) {
210     let m = p.start();
211     match p.current() {
212         LIFETIME_IDENT => {
213             lifetime(p);
214             if p.at(T![:]) {
215                 bounds(p);
216             } else {
217                 p.error("expected colon");
218             }
219         }
220         T![impl] => {
221             p.error("expected lifetime or type");
222         }
223         _ => {
224             if p.at(T![for]) {
225                 // test where_pred_for
226                 // fn for_trait<F>()
227                 // where
228                 //    for<'a> F: Fn(&'a str)
229                 // { }
230                 types::for_binder(p);
231             }
232 
233             types::type_(p);
234 
235             if p.at(T![:]) {
236                 bounds(p);
237             } else {
238                 p.error("expected colon");
239             }
240         }
241     }
242     m.complete(p, WHERE_PRED);
243 }
244