]> git.proxmox.com Git - rustc.git/blame - src/libsyntax/parse/parser/generics.rs
New upstream version 1.40.0+dfsg1
[rustc.git] / src / libsyntax / parse / parser / generics.rs
CommitLineData
416331ca
XL
1use super::{Parser, PResult};
2
3use crate::ast::{self, WhereClause, GenericParam, GenericParamKind, GenericBounds, Attribute};
4use crate::parse::token;
5use crate::source_map::DUMMY_SP;
6use crate::symbol::kw;
7
8impl<'a> Parser<'a> {
9 /// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
10 ///
11 /// ```
12 /// BOUND = LT_BOUND (e.g., `'a`)
13 /// ```
14 fn parse_lt_param_bounds(&mut self) -> GenericBounds {
15 let mut lifetimes = Vec::new();
16 while self.check_lifetime() {
17 lifetimes.push(ast::GenericBound::Outlives(self.expect_lifetime()));
18
19 if !self.eat_plus() {
20 break
21 }
22 }
23 lifetimes
24 }
25
26 /// Matches `typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?`.
27 fn parse_ty_param(&mut self,
28 preceding_attrs: Vec<Attribute>)
29 -> PResult<'a, GenericParam> {
30 let ident = self.parse_ident()?;
31
32 // Parse optional colon and param bounds.
33 let bounds = if self.eat(&token::Colon) {
34 self.parse_generic_bounds(Some(self.prev_span))?
35 } else {
36 Vec::new()
37 };
38
39 let default = if self.eat(&token::Eq) {
40 Some(self.parse_ty()?)
41 } else {
42 None
43 };
44
45 Ok(GenericParam {
46 ident,
47 id: ast::DUMMY_NODE_ID,
48 attrs: preceding_attrs.into(),
49 bounds,
50 kind: GenericParamKind::Type {
51 default,
e1599b0c
XL
52 },
53 is_placeholder: false
416331ca
XL
54 })
55 }
56
57 fn parse_const_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, GenericParam> {
e74abb32
XL
58 let lo = self.token.span;
59
416331ca
XL
60 self.expect_keyword(kw::Const)?;
61 let ident = self.parse_ident()?;
62 self.expect(&token::Colon)?;
63 let ty = self.parse_ty()?;
64
e74abb32
XL
65 self.sess.gated_spans.const_generics.borrow_mut().push(lo.to(self.prev_span));
66
416331ca
XL
67 Ok(GenericParam {
68 ident,
69 id: ast::DUMMY_NODE_ID,
70 attrs: preceding_attrs.into(),
71 bounds: Vec::new(),
72 kind: GenericParamKind::Const {
73 ty,
e1599b0c
XL
74 },
75 is_placeholder: false
416331ca
XL
76 })
77 }
78
79 /// Parses a (possibly empty) list of lifetime and type parameters, possibly including
80 /// a trailing comma and erroneous trailing attributes.
e74abb32 81 pub(super) fn parse_generic_params(&mut self) -> PResult<'a, Vec<ast::GenericParam>> {
416331ca
XL
82 let mut params = Vec::new();
83 loop {
84 let attrs = self.parse_outer_attributes()?;
85 if self.check_lifetime() {
86 let lifetime = self.expect_lifetime();
87 // Parse lifetime parameter.
88 let bounds = if self.eat(&token::Colon) {
89 self.parse_lt_param_bounds()
90 } else {
91 Vec::new()
92 };
93 params.push(ast::GenericParam {
94 ident: lifetime.ident,
95 id: lifetime.id,
96 attrs: attrs.into(),
97 bounds,
98 kind: ast::GenericParamKind::Lifetime,
e1599b0c 99 is_placeholder: false
416331ca
XL
100 });
101 } else if self.check_keyword(kw::Const) {
102 // Parse const parameter.
103 params.push(self.parse_const_param(attrs)?);
104 } else if self.check_ident() {
105 // Parse type parameter.
106 params.push(self.parse_ty_param(attrs)?);
e1599b0c
XL
107 } else if self.token.can_begin_type() {
108 // Trying to write an associated type bound? (#26271)
109 let snapshot = self.clone();
110 match self.parse_ty_where_predicate() {
111 Ok(where_predicate) => {
112 self.struct_span_err(
113 where_predicate.span(),
114 "bounds on associated types do not belong here",
115 )
116 .span_label(where_predicate.span(), "belongs in `where` clause")
117 .emit();
118 }
119 Err(mut err) => {
120 err.cancel();
121 std::mem::replace(self, snapshot);
122 break
123 }
124 }
416331ca
XL
125 } else {
126 // Check for trailing attributes and stop parsing.
127 if !attrs.is_empty() {
128 if !params.is_empty() {
129 self.struct_span_err(
130 attrs[0].span,
e1599b0c 131 "trailing attribute after generic parameter",
416331ca
XL
132 )
133 .span_label(attrs[0].span, "attributes must go before parameters")
134 .emit();
135 } else {
136 self.struct_span_err(
137 attrs[0].span,
138 &format!("attribute without generic parameters"),
139 )
140 .span_label(
141 attrs[0].span,
142 "attributes are only permitted when preceding parameters",
143 )
144 .emit();
145 }
146 }
147 break
148 }
149
150 if !self.eat(&token::Comma) {
151 break
152 }
153 }
154 Ok(params)
155 }
156
157 /// Parses a set of optional generic type parameter declarations. Where
158 /// clauses are not parsed here, and must be added later via
159 /// `parse_where_clause()`.
160 ///
161 /// matches generics = ( ) | ( < > ) | ( < typaramseq ( , )? > ) | ( < lifetimes ( , )? > )
162 /// | ( < lifetimes , typaramseq ( , )? > )
163 /// where typaramseq = ( typaram ) | ( typaram , typaramseq )
164 pub(super) fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
165 let span_lo = self.token.span;
166 let (params, span) = if self.eat_lt() {
167 let params = self.parse_generic_params()?;
168 self.expect_gt()?;
169 (params, span_lo.to(self.prev_span))
170 } else {
171 (vec![], self.prev_span.between(self.token.span))
172 };
173 Ok(ast::Generics {
174 params,
175 where_clause: WhereClause {
176 predicates: Vec::new(),
177 span: DUMMY_SP,
178 },
179 span,
180 })
181 }
182
183 /// Parses an optional where-clause and places it in `generics`.
184 ///
185 /// ```ignore (only-for-syntax-highlight)
186 /// where T : Trait<U, V> + 'b, 'a : 'b
187 /// ```
188 pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
189 let mut where_clause = WhereClause {
190 predicates: Vec::new(),
191 span: self.prev_span.to(self.prev_span),
192 };
193
194 if !self.eat_keyword(kw::Where) {
195 return Ok(where_clause);
196 }
197 let lo = self.prev_span;
198
199 // We are considering adding generics to the `where` keyword as an alternative higher-rank
200 // parameter syntax (as in `where<'a>` or `where<T>`. To avoid that being a breaking
201 // change we parse those generics now, but report an error.
202 if self.choose_generics_over_qpath() {
203 let generics = self.parse_generics()?;
204 self.struct_span_err(
205 generics.span,
206 "generic parameters on `where` clauses are reserved for future use",
207 )
208 .span_label(generics.span, "currently unsupported")
209 .emit();
210 }
211
212 loop {
213 let lo = self.token.span;
214 if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
215 let lifetime = self.expect_lifetime();
216 // Bounds starting with a colon are mandatory, but possibly empty.
217 self.expect(&token::Colon)?;
218 let bounds = self.parse_lt_param_bounds();
219 where_clause.predicates.push(ast::WherePredicate::RegionPredicate(
220 ast::WhereRegionPredicate {
221 span: lo.to(self.prev_span),
222 lifetime,
223 bounds,
224 }
225 ));
226 } else if self.check_type() {
e1599b0c 227 where_clause.predicates.push(self.parse_ty_where_predicate()?);
416331ca
XL
228 } else {
229 break
230 }
231
232 if !self.eat(&token::Comma) {
233 break
234 }
235 }
236
237 where_clause.span = lo.to(self.prev_span);
238 Ok(where_clause)
239 }
240
e1599b0c
XL
241 fn parse_ty_where_predicate(&mut self) -> PResult<'a, ast::WherePredicate> {
242 let lo = self.token.span;
243 // Parse optional `for<'a, 'b>`.
244 // This `for` is parsed greedily and applies to the whole predicate,
245 // the bounded type can have its own `for` applying only to it.
246 // Examples:
247 // * `for<'a> Trait1<'a>: Trait2<'a /* ok */>`
248 // * `(for<'a> Trait1<'a>): Trait2<'a /* not ok */>`
249 // * `for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /* ok */, 'b /* not ok */>`
250 let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
251
252 // Parse type with mandatory colon and (possibly empty) bounds,
253 // or with mandatory equality sign and the second type.
254 let ty = self.parse_ty()?;
255 if self.eat(&token::Colon) {
256 let bounds = self.parse_generic_bounds(Some(self.prev_span))?;
257 Ok(ast::WherePredicate::BoundPredicate(
258 ast::WhereBoundPredicate {
259 span: lo.to(self.prev_span),
260 bound_generic_params: lifetime_defs,
261 bounded_ty: ty,
262 bounds,
263 }
264 ))
265 // FIXME: Decide what should be used here, `=` or `==`.
266 // FIXME: We are just dropping the binders in lifetime_defs on the floor here.
267 } else if self.eat(&token::Eq) || self.eat(&token::EqEq) {
268 let rhs_ty = self.parse_ty()?;
269 Ok(ast::WherePredicate::EqPredicate(
270 ast::WhereEqPredicate {
271 span: lo.to(self.prev_span),
272 lhs_ty: ty,
273 rhs_ty,
274 id: ast::DUMMY_NODE_ID,
275 }
276 ))
277 } else {
278 self.unexpected()
279 }
280 }
281
416331ca
XL
282 pub(super) fn choose_generics_over_qpath(&self) -> bool {
283 // There's an ambiguity between generic parameters and qualified paths in impls.
284 // If we see `<` it may start both, so we have to inspect some following tokens.
285 // The following combinations can only start generics,
286 // but not qualified paths (with one exception):
287 // `<` `>` - empty generic parameters
288 // `<` `#` - generic parameters with attributes
289 // `<` (LIFETIME|IDENT) `>` - single generic parameter
290 // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
291 // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
292 // `<` (LIFETIME|IDENT) `=` - generic parameter with a default
293 // `<` const - generic const parameter
294 // The only truly ambiguous case is
295 // `<` IDENT `>` `::` IDENT ...
296 // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
297 // because this is what almost always expected in practice, qualified paths in impls
298 // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
299 self.token == token::Lt &&
300 (self.look_ahead(1, |t| t == &token::Pound || t == &token::Gt) ||
301 self.look_ahead(1, |t| t.is_lifetime() || t.is_ident()) &&
302 self.look_ahead(2, |t| t == &token::Gt || t == &token::Comma ||
303 t == &token::Colon || t == &token::Eq) ||
304 self.is_keyword_ahead(1, &[kw::Const]))
305 }
306}