]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_parse/src/parser/generics.rs
New upstream version 1.69.0+dfsg1
[rustc.git] / compiler / rustc_parse / src / parser / generics.rs
1 use crate::errors::{
2 MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters,
3 UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody,
4 WhereClauseBeforeTupleStructBodySugg,
5 };
6
7 use super::{ForceCollect, Parser, TrailingToken};
8
9 use ast::token::Delimiter;
10 use rustc_ast::token;
11 use rustc_ast::{
12 self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, TyKind, WhereClause,
13 };
14 use rustc_errors::{Applicability, PResult};
15 use rustc_span::symbol::{kw, Ident};
16 use rustc_span::Span;
17 use thin_vec::ThinVec;
18
19 enum PredicateOrStructBody {
20 Predicate(ast::WherePredicate),
21 StructBody(ThinVec<ast::FieldDef>),
22 }
23
24 impl<'a> Parser<'a> {
25 /// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
26 ///
27 /// ```text
28 /// BOUND = LT_BOUND (e.g., `'a`)
29 /// ```
30 fn parse_lt_param_bounds(&mut self) -> GenericBounds {
31 let mut lifetimes = Vec::new();
32 while self.check_lifetime() {
33 lifetimes.push(ast::GenericBound::Outlives(self.expect_lifetime()));
34
35 if !self.eat_plus() {
36 break;
37 }
38 }
39 lifetimes
40 }
41
42 /// Matches `typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?`.
43 fn parse_ty_param(&mut self, preceding_attrs: AttrVec) -> PResult<'a, GenericParam> {
44 let ident = self.parse_ident()?;
45
46 // Parse optional colon and param bounds.
47 let mut colon_span = None;
48 let bounds = if self.eat(&token::Colon) {
49 colon_span = Some(self.prev_token.span);
50 // recover from `impl Trait` in type param bound
51 if self.token.is_keyword(kw::Impl) {
52 let impl_span = self.token.span;
53 let snapshot = self.create_snapshot_for_diagnostic();
54 match self.parse_ty() {
55 Ok(p) => {
56 if let TyKind::ImplTrait(_, bounds) = &(*p).kind {
57 let span = impl_span.to(self.token.span.shrink_to_lo());
58 let mut err = self.struct_span_err(
59 span,
60 "expected trait bound, found `impl Trait` type",
61 );
62 err.span_label(span, "not a trait");
63 if let [bound, ..] = &bounds[..] {
64 err.span_suggestion_verbose(
65 impl_span.until(bound.span()),
66 "use the trait bounds directly",
67 String::new(),
68 Applicability::MachineApplicable,
69 );
70 }
71 err.emit();
72 return Err(err);
73 }
74 }
75 Err(err) => {
76 err.cancel();
77 }
78 }
79 self.restore_snapshot(snapshot);
80 }
81 self.parse_generic_bounds(colon_span)?
82 } else {
83 Vec::new()
84 };
85
86 let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
87 Ok(GenericParam {
88 ident,
89 id: ast::DUMMY_NODE_ID,
90 attrs: preceding_attrs,
91 bounds,
92 kind: GenericParamKind::Type { default },
93 is_placeholder: false,
94 colon_span,
95 })
96 }
97
98 pub(crate) fn parse_const_param(
99 &mut self,
100 preceding_attrs: AttrVec,
101 ) -> PResult<'a, GenericParam> {
102 let const_span = self.token.span;
103
104 self.expect_keyword(kw::Const)?;
105 let ident = self.parse_ident()?;
106 self.expect(&token::Colon)?;
107 let ty = self.parse_ty()?;
108
109 // Parse optional const generics default value.
110 let default = if self.eat(&token::Eq) { Some(self.parse_const_arg()?) } else { None };
111
112 Ok(GenericParam {
113 ident,
114 id: ast::DUMMY_NODE_ID,
115 attrs: preceding_attrs,
116 bounds: Vec::new(),
117 kind: GenericParamKind::Const { ty, kw_span: const_span, default },
118 is_placeholder: false,
119 colon_span: None,
120 })
121 }
122
123 /// Parses a (possibly empty) list of lifetime and type parameters, possibly including
124 /// a trailing comma and erroneous trailing attributes.
125 pub(super) fn parse_generic_params(&mut self) -> PResult<'a, ThinVec<ast::GenericParam>> {
126 let mut params = ThinVec::new();
127 let mut done = false;
128 while !done {
129 let attrs = self.parse_outer_attributes()?;
130 let param =
131 self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
132 if this.eat_keyword_noexpect(kw::SelfUpper) {
133 // `Self` as a generic param is invalid. Here we emit the diagnostic and continue parsing
134 // as if `Self` never existed.
135 this.sess.emit_err(UnexpectedSelfInGenericParameters {
136 span: this.prev_token.span,
137 });
138
139 this.eat(&token::Comma);
140 }
141
142 let param = if this.check_lifetime() {
143 let lifetime = this.expect_lifetime();
144 // Parse lifetime parameter.
145 let (colon_span, bounds) = if this.eat(&token::Colon) {
146 (Some(this.prev_token.span), this.parse_lt_param_bounds())
147 } else {
148 (None, Vec::new())
149 };
150
151 if this.check_noexpect(&token::Eq)
152 && this.look_ahead(1, |t| t.is_lifetime())
153 {
154 let lo = this.token.span;
155 // Parse `= 'lifetime`.
156 this.bump(); // `=`
157 this.bump(); // `'lifetime`
158 let span = lo.to(this.prev_token.span);
159 this.sess.emit_err(
160 UnexpectedDefaultValueForLifetimeInGenericParameters { span },
161 );
162 }
163
164 Some(ast::GenericParam {
165 ident: lifetime.ident,
166 id: lifetime.id,
167 attrs,
168 bounds,
169 kind: ast::GenericParamKind::Lifetime,
170 is_placeholder: false,
171 colon_span,
172 })
173 } else if this.check_keyword(kw::Const) {
174 // Parse const parameter.
175 Some(this.parse_const_param(attrs)?)
176 } else if this.check_ident() {
177 // Parse type parameter.
178 Some(this.parse_ty_param(attrs)?)
179 } else if this.token.can_begin_type() {
180 // Trying to write an associated type bound? (#26271)
181 let snapshot = this.create_snapshot_for_diagnostic();
182 match this.parse_ty_where_predicate() {
183 Ok(where_predicate) => {
184 this.struct_span_err(
185 where_predicate.span(),
186 "bounds on associated types do not belong here",
187 )
188 .span_label(where_predicate.span(), "belongs in `where` clause")
189 .emit();
190 // FIXME - try to continue parsing other generics?
191 return Ok((None, TrailingToken::None));
192 }
193 Err(err) => {
194 err.cancel();
195 // FIXME - maybe we should overwrite 'self' outside of `collect_tokens`?
196 this.restore_snapshot(snapshot);
197 return Ok((None, TrailingToken::None));
198 }
199 }
200 } else {
201 // Check for trailing attributes and stop parsing.
202 if !attrs.is_empty() {
203 if !params.is_empty() {
204 this.struct_span_err(
205 attrs[0].span,
206 "trailing attribute after generic parameter",
207 )
208 .span_label(attrs[0].span, "attributes must go before parameters")
209 .emit();
210 } else {
211 this.struct_span_err(
212 attrs[0].span,
213 "attribute without generic parameters",
214 )
215 .span_label(
216 attrs[0].span,
217 "attributes are only permitted when preceding parameters",
218 )
219 .emit();
220 }
221 }
222 return Ok((None, TrailingToken::None));
223 };
224
225 if !this.eat(&token::Comma) {
226 done = true;
227 }
228 // We just ate the comma, so no need to use `TrailingToken`
229 Ok((param, TrailingToken::None))
230 })?;
231
232 if let Some(param) = param {
233 params.push(param);
234 } else {
235 break;
236 }
237 }
238 Ok(params)
239 }
240
241 /// Parses a set of optional generic type parameter declarations. Where
242 /// clauses are not parsed here, and must be added later via
243 /// `parse_where_clause()`.
244 ///
245 /// matches generics = ( ) | ( < > ) | ( < typaramseq ( , )? > ) | ( < lifetimes ( , )? > )
246 /// | ( < lifetimes , typaramseq ( , )? > )
247 /// where typaramseq = ( typaram ) | ( typaram , typaramseq )
248 pub(super) fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
249 let span_lo = self.token.span;
250 let (params, span) = if self.eat_lt() {
251 let params = self.parse_generic_params()?;
252 self.expect_gt()?;
253 (params, span_lo.to(self.prev_token.span))
254 } else {
255 (ThinVec::new(), self.prev_token.span.shrink_to_hi())
256 };
257 Ok(ast::Generics {
258 params,
259 where_clause: WhereClause {
260 has_where_token: false,
261 predicates: ThinVec::new(),
262 span: self.prev_token.span.shrink_to_hi(),
263 },
264 span,
265 })
266 }
267
268 /// Parses an optional where-clause.
269 ///
270 /// ```ignore (only-for-syntax-highlight)
271 /// where T : Trait<U, V> + 'b, 'a : 'b
272 /// ```
273 pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
274 self.parse_where_clause_common(None).map(|(clause, _)| clause)
275 }
276
277 pub(super) fn parse_struct_where_clause(
278 &mut self,
279 struct_name: Ident,
280 body_insertion_point: Span,
281 ) -> PResult<'a, (WhereClause, Option<ThinVec<ast::FieldDef>>)> {
282 self.parse_where_clause_common(Some((struct_name, body_insertion_point)))
283 }
284
285 fn parse_where_clause_common(
286 &mut self,
287 struct_: Option<(Ident, Span)>,
288 ) -> PResult<'a, (WhereClause, Option<ThinVec<ast::FieldDef>>)> {
289 let mut where_clause = WhereClause {
290 has_where_token: false,
291 predicates: ThinVec::new(),
292 span: self.prev_token.span.shrink_to_hi(),
293 };
294 let mut tuple_struct_body = None;
295
296 if !self.eat_keyword(kw::Where) {
297 return Ok((where_clause, None));
298 }
299 where_clause.has_where_token = true;
300 let where_lo = self.prev_token.span;
301
302 // We are considering adding generics to the `where` keyword as an alternative higher-rank
303 // parameter syntax (as in `where<'a>` or `where<T>`. To avoid that being a breaking
304 // change we parse those generics now, but report an error.
305 if self.choose_generics_over_qpath(0) {
306 let generics = self.parse_generics()?;
307 self.struct_span_err(
308 generics.span,
309 "generic parameters on `where` clauses are reserved for future use",
310 )
311 .span_label(generics.span, "currently unsupported")
312 .emit();
313 }
314
315 loop {
316 let where_sp = where_lo.to(self.prev_token.span);
317 let pred_lo = self.token.span;
318 if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
319 let lifetime = self.expect_lifetime();
320 // Bounds starting with a colon are mandatory, but possibly empty.
321 self.expect(&token::Colon)?;
322 let bounds = self.parse_lt_param_bounds();
323 where_clause.predicates.push(ast::WherePredicate::RegionPredicate(
324 ast::WhereRegionPredicate {
325 span: pred_lo.to(self.prev_token.span),
326 lifetime,
327 bounds,
328 },
329 ));
330 } else if self.check_type() {
331 match self.parse_ty_where_predicate_or_recover_tuple_struct_body(
332 struct_, pred_lo, where_sp,
333 )? {
334 PredicateOrStructBody::Predicate(pred) => where_clause.predicates.push(pred),
335 PredicateOrStructBody::StructBody(body) => {
336 tuple_struct_body = Some(body);
337 break;
338 }
339 }
340 } else {
341 break;
342 }
343
344 let prev_token = self.prev_token.span;
345 let ate_comma = self.eat(&token::Comma);
346
347 if self.eat_keyword_noexpect(kw::Where) {
348 self.sess.emit_err(MultipleWhereClauses {
349 span: self.token.span,
350 previous: pred_lo,
351 between: prev_token.shrink_to_hi().to(self.prev_token.span),
352 });
353 } else if !ate_comma {
354 break;
355 }
356 }
357
358 where_clause.span = where_lo.to(self.prev_token.span);
359 Ok((where_clause, tuple_struct_body))
360 }
361
362 fn parse_ty_where_predicate_or_recover_tuple_struct_body(
363 &mut self,
364 struct_: Option<(Ident, Span)>,
365 pred_lo: Span,
366 where_sp: Span,
367 ) -> PResult<'a, PredicateOrStructBody> {
368 let mut snapshot = None;
369
370 if let Some(struct_) = struct_
371 && self.may_recover()
372 && self.token.kind == token::OpenDelim(Delimiter::Parenthesis)
373 {
374 snapshot = Some((struct_, self.create_snapshot_for_diagnostic()));
375 };
376
377 match self.parse_ty_where_predicate() {
378 Ok(pred) => Ok(PredicateOrStructBody::Predicate(pred)),
379 Err(type_err) => {
380 let Some(((struct_name, body_insertion_point), mut snapshot)) = snapshot else {
381 return Err(type_err);
382 };
383
384 // Check if we might have encountered an out of place tuple struct body.
385 match snapshot.parse_tuple_struct_body() {
386 // Since we don't know the exact reason why we failed to parse the
387 // predicate (we might have stumbled upon something bogus like `(T): ?`),
388 // employ a simple heuristic to weed out some pathological cases:
389 // Look for a semicolon (strong indicator) or anything that might mark
390 // the end of the item (weak indicator) following the body.
391 Ok(body)
392 if matches!(snapshot.token.kind, token::Semi | token::Eof)
393 || snapshot.token.can_begin_item() =>
394 {
395 type_err.cancel();
396
397 let body_sp = pred_lo.to(snapshot.prev_token.span);
398 let map = self.sess.source_map();
399
400 self.sess.emit_err(WhereClauseBeforeTupleStructBody {
401 span: where_sp,
402 name: struct_name.span,
403 body: body_sp,
404 sugg: map.span_to_snippet(body_sp).ok().map(|body| {
405 WhereClauseBeforeTupleStructBodySugg {
406 left: body_insertion_point.shrink_to_hi(),
407 snippet: body,
408 right: map.end_point(where_sp).to(body_sp),
409 }
410 }),
411 });
412
413 self.restore_snapshot(snapshot);
414 Ok(PredicateOrStructBody::StructBody(body))
415 }
416 Ok(_) => Err(type_err),
417 Err(body_err) => {
418 body_err.cancel();
419 Err(type_err)
420 }
421 }
422 }
423 }
424 }
425
426 fn parse_ty_where_predicate(&mut self) -> PResult<'a, ast::WherePredicate> {
427 let lo = self.token.span;
428 // Parse optional `for<'a, 'b>`.
429 // This `for` is parsed greedily and applies to the whole predicate,
430 // the bounded type can have its own `for` applying only to it.
431 // Examples:
432 // * `for<'a> Trait1<'a>: Trait2<'a /* ok */>`
433 // * `(for<'a> Trait1<'a>): Trait2<'a /* not ok */>`
434 // * `for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /* ok */, 'b /* not ok */>`
435 let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
436
437 // Parse type with mandatory colon and (possibly empty) bounds,
438 // or with mandatory equality sign and the second type.
439 let ty = self.parse_ty_for_where_clause()?;
440 if self.eat(&token::Colon) {
441 let bounds = self.parse_generic_bounds(Some(self.prev_token.span))?;
442 Ok(ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
443 span: lo.to(self.prev_token.span),
444 bound_generic_params: lifetime_defs,
445 bounded_ty: ty,
446 bounds,
447 }))
448 // FIXME: Decide what should be used here, `=` or `==`.
449 // FIXME: We are just dropping the binders in lifetime_defs on the floor here.
450 } else if self.eat(&token::Eq) || self.eat(&token::EqEq) {
451 let rhs_ty = self.parse_ty()?;
452 Ok(ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
453 span: lo.to(self.prev_token.span),
454 lhs_ty: ty,
455 rhs_ty,
456 }))
457 } else {
458 self.maybe_recover_bounds_doubled_colon(&ty)?;
459 self.unexpected()
460 }
461 }
462
463 pub(super) fn choose_generics_over_qpath(&self, start: usize) -> bool {
464 // There's an ambiguity between generic parameters and qualified paths in impls.
465 // If we see `<` it may start both, so we have to inspect some following tokens.
466 // The following combinations can only start generics,
467 // but not qualified paths (with one exception):
468 // `<` `>` - empty generic parameters
469 // `<` `#` - generic parameters with attributes
470 // `<` (LIFETIME|IDENT) `>` - single generic parameter
471 // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
472 // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
473 // `<` (LIFETIME|IDENT) `=` - generic parameter with a default
474 // `<` const - generic const parameter
475 // The only truly ambiguous case is
476 // `<` IDENT `>` `::` IDENT ...
477 // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
478 // because this is what almost always expected in practice, qualified paths in impls
479 // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
480 self.look_ahead(start, |t| t == &token::Lt)
481 && (self.look_ahead(start + 1, |t| t == &token::Pound || t == &token::Gt)
482 || self.look_ahead(start + 1, |t| t.is_lifetime() || t.is_ident())
483 && self.look_ahead(start + 2, |t| {
484 matches!(t.kind, token::Gt | token::Comma | token::Colon | token::Eq)
485 })
486 || self.is_keyword_ahead(start + 1, &[kw::Const]))
487 }
488 }