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