Skip to main content

rustc_parse/parser/
generics.rs

1use rustc_ast::{
2    self as ast, AttrVec, DUMMY_NODE_ID, GenericBounds, GenericParam, GenericParamKind, TyKind,
3    WhereClause, token,
4};
5use rustc_errors::{Applicability, PResult};
6use rustc_span::{Ident, Span, kw, sym};
7use thin_vec::ThinVec;
8
9use super::{ForceCollect, Parser, Trailing, UsePreAttrPos};
10use crate::errors::{
11    self, MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters,
12    UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody,
13    WhereClauseBeforeTupleStructBodySugg,
14};
15use crate::exp;
16
17enum PredicateKindOrStructBody {
18    PredicateKind(ast::WherePredicateKind),
19    StructBody(ThinVec<ast::FieldDef>),
20}
21
22impl<'a> Parser<'a> {
23    /// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
24    ///
25    /// ```text
26    /// BOUND = LT_BOUND (e.g., `'a`)
27    /// ```
28    fn parse_lt_param_bounds(&mut self) -> GenericBounds {
29        let mut lifetimes = Vec::new();
30        while self.check_lifetime() {
31            lifetimes.push(ast::GenericBound::Outlives(self.expect_lifetime()));
32
33            if !self.eat_plus() {
34                break;
35            }
36        }
37        lifetimes
38    }
39
40    /// Matches `typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?`.
41    fn parse_ty_param(&mut self, preceding_attrs: AttrVec) -> PResult<'a, GenericParam> {
42        let ident = self.parse_ident()?;
43
44        // We might have a typo'd `Const` that was parsed as a type parameter.
45        if self.may_recover()
46            && ident.name.as_str().to_ascii_lowercase() == kw::Const.as_str()
47            && self.check_ident()
48        // `Const` followed by IDENT
49        {
50            return self.recover_const_param_with_mistyped_const(preceding_attrs, ident);
51        }
52
53        // Parse optional colon and param bounds.
54        let mut colon_span = None;
55        let bounds = if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Colon,
    token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)) {
56            colon_span = Some(self.prev_token.span);
57            // recover from `impl Trait` in type param bound
58            if self.token.is_keyword(kw::Impl) {
59                let impl_span = self.token.span;
60                let snapshot = self.create_snapshot_for_diagnostic();
61                match self.parse_ty() {
62                    Ok(p) => {
63                        if let TyKind::ImplTrait(_, bounds) = &p.kind {
64                            let span = impl_span.to(self.token.span.shrink_to_lo());
65                            let mut err = self.dcx().struct_span_err(
66                                span,
67                                "expected trait bound, found `impl Trait` type",
68                            );
69                            err.span_label(span, "not a trait");
70                            if let [bound, ..] = &bounds[..] {
71                                err.span_suggestion_verbose(
72                                    impl_span.until(bound.span()),
73                                    "use the trait bounds directly",
74                                    String::new(),
75                                    Applicability::MachineApplicable,
76                                );
77                            }
78                            return Err(err);
79                        }
80                    }
81                    Err(err) => {
82                        err.cancel();
83                    }
84                }
85                self.restore_snapshot(snapshot);
86            }
87            self.parse_generic_bounds()?
88        } else {
89            Vec::new()
90        };
91
92        let default = if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Eq,
    token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) { Some(self.parse_ty()?) } else { None };
93        Ok(GenericParam {
94            ident,
95            id: ast::DUMMY_NODE_ID,
96            attrs: preceding_attrs,
97            bounds,
98            kind: GenericParamKind::Type { default },
99            is_placeholder: false,
100            colon_span,
101        })
102    }
103
104    pub(crate) fn parse_const_param(
105        &mut self,
106        preceding_attrs: AttrVec,
107    ) -> PResult<'a, GenericParam> {
108        let const_span = self.token.span;
109
110        self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Const,
    token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const))?;
111        let ident = self.parse_ident()?;
112        if let Err(mut err) = self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Colon,
    token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)) {
113            return if self.token.kind == token::Comma || self.token.kind == token::Gt {
114                // Recover parse from `<const N>` where the type is missing.
115                let span = const_span.to(ident.span);
116                err.span_suggestion_verbose(
117                    ident.span.shrink_to_hi(),
118                    "you likely meant to write the type of the const parameter here",
119                    ": /* Type */".to_string(),
120                    Applicability::HasPlaceholders,
121                );
122                let kind = TyKind::Err(err.emit());
123                let ty = self.mk_ty(span, kind);
124                Ok(GenericParam {
125                    ident,
126                    id: ast::DUMMY_NODE_ID,
127                    attrs: preceding_attrs,
128                    bounds: Vec::new(),
129                    kind: GenericParamKind::Const { ty, span, default: None },
130                    is_placeholder: false,
131                    colon_span: None,
132                })
133            } else {
134                Err(err)
135            };
136        }
137        let ty = self.parse_ty()?;
138
139        // Parse optional const generics default value.
140        let default = if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Eq,
    token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) { Some(self.parse_const_arg()?) } else { None };
141        let span = if let Some(ref default) = default {
142            const_span.to(default.value.span)
143        } else {
144            const_span.to(ty.span)
145        };
146
147        Ok(GenericParam {
148            ident,
149            id: ast::DUMMY_NODE_ID,
150            attrs: preceding_attrs,
151            bounds: Vec::new(),
152            kind: GenericParamKind::Const { ty, span, default },
153            is_placeholder: false,
154            colon_span: None,
155        })
156    }
157
158    pub(crate) fn recover_const_param_with_mistyped_const(
159        &mut self,
160        preceding_attrs: AttrVec,
161        mistyped_const_ident: Ident,
162    ) -> PResult<'a, GenericParam> {
163        let ident = self.parse_ident()?;
164        self.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Colon,
    token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon))?;
165        let ty = self.parse_ty()?;
166
167        // Parse optional const generics default value.
168        let default = if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Eq,
    token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) { Some(self.parse_const_arg()?) } else { None };
169        let span = if let Some(ref default) = default {
170            mistyped_const_ident.span.to(default.value.span)
171        } else {
172            mistyped_const_ident.span.to(ty.span)
173        };
174
175        self.dcx()
176            .struct_span_err(
177                mistyped_const_ident.span,
178                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`const` keyword was mistyped as `{0}`",
                mistyped_const_ident.as_str()))
    })format!("`const` keyword was mistyped as `{}`", mistyped_const_ident.as_str()),
179            )
180            .with_span_suggestion_verbose(
181                mistyped_const_ident.span,
182                "use the `const` keyword",
183                kw::Const,
184                Applicability::MachineApplicable,
185            )
186            .emit();
187
188        Ok(GenericParam {
189            ident,
190            id: ast::DUMMY_NODE_ID,
191            attrs: preceding_attrs,
192            bounds: Vec::new(),
193            kind: GenericParamKind::Const { ty, span, default },
194            is_placeholder: false,
195            colon_span: None,
196        })
197    }
198
199    /// Parse a (possibly empty) list of generic (lifetime, type, const) parameters.
200    ///
201    /// ```ebnf
202    /// GenericParams = (GenericParam ("," GenericParam)* ","?)?
203    /// ```
204    pub(super) fn parse_generic_params(&mut self) -> PResult<'a, ThinVec<ast::GenericParam>> {
205        let mut params = ThinVec::new();
206        let mut done = false;
207        let prev = self.parsing_generics;
208        self.parsing_generics = true;
209        while !done {
210            let attrs = self.parse_outer_attributes()?;
211            let param = match self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
212                if this.eat_keyword_noexpect(kw::SelfUpper) {
213                    // `Self` as a generic param is invalid. Here we emit the diagnostic and continue parsing
214                    // as if `Self` never existed.
215                    this.dcx()
216                        .emit_err(UnexpectedSelfInGenericParameters { span: this.prev_token.span });
217
218                    // Eat a trailing comma, if it exists.
219                    let _ = this.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Comma,
    token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma));
220                }
221
222                let param = if this.check_lifetime() {
223                    let lifetime = this.expect_lifetime();
224                    // Parse lifetime parameter.
225                    let (colon_span, bounds) = if this.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Colon,
    token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)) {
226                        (Some(this.prev_token.span), this.parse_lt_param_bounds())
227                    } else {
228                        (None, Vec::new())
229                    };
230
231                    if this.check_noexpect(&token::Eq) && this.look_ahead(1, |t| t.is_lifetime()) {
232                        let lo = this.token.span;
233                        // Parse `= 'lifetime`.
234                        this.bump(); // `=`
235                        this.bump(); // `'lifetime`
236                        let span = lo.to(this.prev_token.span);
237                        this.dcx().emit_err(UnexpectedDefaultValueForLifetimeInGenericParameters {
238                            span,
239                        });
240                    }
241
242                    Some(ast::GenericParam {
243                        ident: lifetime.ident,
244                        id: lifetime.id,
245                        attrs,
246                        bounds,
247                        kind: ast::GenericParamKind::Lifetime,
248                        is_placeholder: false,
249                        colon_span,
250                    })
251                } else if this.check_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Const,
    token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const)) {
252                    // Parse const parameter.
253                    Some(this.parse_const_param(attrs)?)
254                } else if this.check_ident() {
255                    // Parse type parameter.
256                    Some(this.parse_ty_param(attrs)?)
257                } else if this.token.can_begin_type() {
258                    // Trying to write an associated type bound? (#26271)
259                    let snapshot = this.create_snapshot_for_diagnostic();
260                    let lo = this.token.span;
261                    match this.parse_ty_where_predicate_kind() {
262                        Ok(_) => {
263                            this.dcx().emit_err(errors::BadAssocTypeBounds {
264                                span: lo.to(this.prev_token.span),
265                            });
266                            // FIXME - try to continue parsing other generics?
267                        }
268                        Err(err) => {
269                            err.cancel();
270                            // FIXME - maybe we should overwrite 'self' outside of `collect_tokens`?
271                            this.restore_snapshot(snapshot);
272                        }
273                    }
274                    return Ok((None, Trailing::No, UsePreAttrPos::No));
275                } else {
276                    // Check for trailing attributes and stop parsing.
277                    if !attrs.is_empty() {
278                        if !params.is_empty() {
279                            this.dcx().emit_err(errors::AttrAfterGeneric { span: attrs[0].span });
280                        } else {
281                            this.dcx()
282                                .emit_err(errors::AttrWithoutGenerics { span: attrs[0].span });
283                        }
284                    }
285                    return Ok((None, Trailing::No, UsePreAttrPos::No));
286                };
287
288                if !this.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Comma,
    token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma)) {
289                    done = true;
290                }
291                // We just ate the comma, so no need to capture the trailing token.
292                Ok((param, Trailing::No, UsePreAttrPos::No))
293            }) {
294                Ok(param) => param,
295                Err(err) => {
296                    self.parsing_generics = prev;
297                    return Err(err);
298                }
299            };
300
301            if let Some(param) = param {
302                params.push(param);
303            } else {
304                break;
305            }
306        }
307        self.parsing_generics = prev;
308        Ok(params)
309    }
310
311    /// Parses a set of optional generic type parameter declarations. Where
312    /// clauses are not parsed here, and must be added later via
313    /// `parse_where_clause()`.
314    ///
315    /// matches generics = ( ) | ( < > ) | ( < typaramseq ( , )? > ) | ( < lifetimes ( , )? > )
316    ///                  | ( < lifetimes , typaramseq ( , )? > )
317    /// where   typaramseq = ( typaram ) | ( typaram , typaramseq )
318    pub(super) fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
319        // invalid path separator `::` in function definition
320        // for example `fn invalid_path_separator::<T>() {}`
321        if self.eat_noexpect(&token::PathSep) {
322            self.dcx()
323                .emit_err(errors::InvalidPathSepInFnDefinition { span: self.prev_token.span });
324        }
325
326        let span_lo = self.token.span;
327        let (params, span) = if self.eat_lt() {
328            let params = self.parse_generic_params()?;
329            self.expect_gt_or_maybe_suggest_closing_generics(&params)?;
330            (params, span_lo.to(self.prev_token.span))
331        } else {
332            (ThinVec::new(), self.prev_token.span.shrink_to_hi())
333        };
334        Ok(ast::Generics {
335            params,
336            where_clause: WhereClause {
337                has_where_token: false,
338                predicates: ThinVec::new(),
339                span: self.prev_token.span.shrink_to_hi(),
340            },
341            span,
342        })
343    }
344
345    /// Parses an experimental fn contract
346    /// (`contract_requires(WWW) contract_ensures(ZZZ)`)
347    pub(super) fn parse_contract(&mut self) -> PResult<'a, Option<Box<ast::FnContract>>> {
348        let (declarations, requires) = self.parse_contract_requires()?;
349        let ensures = self.parse_contract_ensures()?;
350
351        if requires.is_none() && ensures.is_none() {
352            Ok(None)
353        } else {
354            Ok(Some(Box::new(ast::FnContract { declarations, requires, ensures })))
355        }
356    }
357
358    fn parse_contract_requires(
359        &mut self,
360    ) -> PResult<'a, (ThinVec<rustc_ast::Stmt>, Option<Box<rustc_ast::Expr>>)> {
361        Ok(if self.eat_keyword_noexpect(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::ContractRequires,
    token_type: crate::parser::token_type::TokenType::KwContractRequires,
}exp!(ContractRequires).kw) {
362            self.psess.gated_spans.gate(sym::contracts_internals, self.prev_token.span);
363            let mut decls_and_precond = self.parse_block()?;
364
365            let precond = match decls_and_precond.stmts.pop() {
366                Some(precond) => match precond.kind {
367                    rustc_ast::StmtKind::Expr(expr) => expr,
368                    // Insert dummy node that will be rejected by typechecker to
369                    // avoid reinventing an error
370                    _ => self.mk_unit_expr(decls_and_precond.span),
371                },
372                None => self.mk_unit_expr(decls_and_precond.span),
373            };
374            let precond = self.mk_closure_expr(precond.span, precond);
375            let decls = decls_and_precond.stmts;
376            (decls, Some(precond))
377        } else {
378            (Default::default(), None)
379        })
380    }
381
382    fn parse_contract_ensures(&mut self) -> PResult<'a, Option<Box<rustc_ast::Expr>>> {
383        Ok(if self.eat_keyword_noexpect(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::ContractEnsures,
    token_type: crate::parser::token_type::TokenType::KwContractEnsures,
}exp!(ContractEnsures).kw) {
384            self.psess.gated_spans.gate(sym::contracts_internals, self.prev_token.span);
385            let postcond = self.parse_expr()?;
386            Some(postcond)
387        } else {
388            None
389        })
390    }
391
392    /// Parses an optional where-clause.
393    ///
394    /// ```ignore (only-for-syntax-highlight)
395    /// where T : Trait<U, V> + 'b, 'a : 'b
396    /// ```
397    pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
398        self.parse_where_clause_common(None).map(|(clause, _)| clause)
399    }
400
401    pub(super) fn parse_struct_where_clause(
402        &mut self,
403        struct_name: Ident,
404        body_insertion_point: Span,
405    ) -> PResult<'a, (WhereClause, Option<ThinVec<ast::FieldDef>>)> {
406        self.parse_where_clause_common(Some((struct_name, body_insertion_point)))
407    }
408
409    fn parse_where_clause_common(
410        &mut self,
411        struct_: Option<(Ident, Span)>,
412    ) -> PResult<'a, (WhereClause, Option<ThinVec<ast::FieldDef>>)> {
413        let mut where_clause = WhereClause {
414            has_where_token: false,
415            predicates: ThinVec::new(),
416            span: self.prev_token.span.shrink_to_hi(),
417        };
418        let mut tuple_struct_body = None;
419
420        if !self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
    kw: rustc_span::symbol::kw::Where,
    token_type: crate::parser::token_type::TokenType::KwWhere,
}exp!(Where)) {
421            return Ok((where_clause, None));
422        }
423
424        if self.eat_noexpect(&token::Colon) {
425            let colon_span = self.prev_token.span;
426            self.dcx()
427                .struct_span_err(colon_span, "unexpected colon after `where`")
428                .with_span_suggestion_short(
429                    colon_span,
430                    "remove the colon",
431                    "",
432                    Applicability::MachineApplicable,
433                )
434                .emit();
435        }
436
437        where_clause.has_where_token = true;
438        let where_lo = self.prev_token.span;
439
440        // We are considering adding generics to the `where` keyword as an alternative higher-rank
441        // parameter syntax (as in `where<'a>` or `where<T>`. To avoid that being a breaking
442        // change we parse those generics now, but report an error.
443        if self.choose_generics_over_qpath(0) {
444            let generics = self.parse_generics()?;
445            self.dcx().emit_err(errors::WhereOnGenerics { span: generics.span });
446        }
447
448        loop {
449            let where_sp = where_lo.to(self.prev_token.span);
450            let attrs = self.parse_outer_attributes()?;
451            let pred_lo = self.token.span;
452            let predicate = self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
453                for attr in &attrs {
454                    self.psess.gated_spans.gate(sym::where_clause_attrs, attr.span);
455                }
456                let kind = if this.check_lifetime() && this.look_ahead(1, |t| !t.is_like_plus()) {
457                    let lifetime = this.expect_lifetime();
458                    // Bounds starting with a colon are mandatory, but possibly empty.
459                    this.expect(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Colon,
    token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon))?;
460                    let bounds = this.parse_lt_param_bounds();
461                    Some(ast::WherePredicateKind::RegionPredicate(ast::WhereRegionPredicate {
462                        lifetime,
463                        bounds,
464                    }))
465                } else if this.check_type() {
466                    match this.parse_ty_where_predicate_kind_or_recover_tuple_struct_body(
467                        struct_, pred_lo, where_sp,
468                    )? {
469                        PredicateKindOrStructBody::PredicateKind(kind) => Some(kind),
470                        PredicateKindOrStructBody::StructBody(body) => {
471                            tuple_struct_body = Some(body);
472                            None
473                        }
474                    }
475                } else {
476                    None
477                };
478                let predicate = kind.map(|kind| ast::WherePredicate {
479                    attrs,
480                    kind,
481                    id: DUMMY_NODE_ID,
482                    span: pred_lo.to(this.prev_token.span),
483                    is_placeholder: false,
484                });
485                Ok((predicate, Trailing::No, UsePreAttrPos::No))
486            })?;
487            match predicate {
488                Some(predicate) => where_clause.predicates.push(predicate),
489                None => break,
490            }
491
492            let prev_token = self.prev_token.span;
493            let ate_comma = self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Comma,
    token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma));
494
495            if self.eat_keyword_noexpect(kw::Where) {
496                self.dcx().emit_err(MultipleWhereClauses {
497                    span: self.token.span,
498                    previous: pred_lo,
499                    between: prev_token.shrink_to_hi().to(self.prev_token.span),
500                });
501            } else if !ate_comma {
502                break;
503            }
504        }
505
506        where_clause.span = where_lo.to(self.prev_token.span);
507        Ok((where_clause, tuple_struct_body))
508    }
509
510    fn parse_ty_where_predicate_kind_or_recover_tuple_struct_body(
511        &mut self,
512        struct_: Option<(Ident, Span)>,
513        pred_lo: Span,
514        where_sp: Span,
515    ) -> PResult<'a, PredicateKindOrStructBody> {
516        let mut snapshot = None;
517
518        if let Some(struct_) = struct_
519            && self.may_recover()
520            && self.token == token::OpenParen
521        {
522            snapshot = Some((struct_, self.create_snapshot_for_diagnostic()));
523        };
524
525        match self.parse_ty_where_predicate_kind() {
526            Ok(pred) => Ok(PredicateKindOrStructBody::PredicateKind(pred)),
527            Err(type_err) => {
528                let Some(((struct_name, body_insertion_point), mut snapshot)) = snapshot else {
529                    return Err(type_err);
530                };
531
532                // Check if we might have encountered an out of place tuple struct body.
533                match snapshot.parse_tuple_struct_body() {
534                    // Since we don't know the exact reason why we failed to parse the
535                    // predicate (we might have stumbled upon something bogus like `(T): ?`),
536                    // employ a simple heuristic to weed out some pathological cases:
537                    // Look for a semicolon (strong indicator) or anything that might mark
538                    // the end of the item (weak indicator) following the body.
539                    Ok(body)
540                        if #[allow(non_exhaustive_omitted_patterns)] match snapshot.token.kind {
    token::Semi | token::Eof => true,
    _ => false,
}matches!(snapshot.token.kind, token::Semi | token::Eof)
541                            || snapshot.token.can_begin_item() =>
542                    {
543                        type_err.cancel();
544
545                        let body_sp = pred_lo.to(snapshot.prev_token.span);
546                        let map = self.psess.source_map();
547
548                        self.dcx().emit_err(WhereClauseBeforeTupleStructBody {
549                            span: where_sp,
550                            name: struct_name.span,
551                            body: body_sp,
552                            sugg: map.span_to_snippet(body_sp).ok().map(|body| {
553                                WhereClauseBeforeTupleStructBodySugg {
554                                    left: body_insertion_point.shrink_to_hi(),
555                                    snippet: body,
556                                    right: map.end_point(where_sp).to(body_sp),
557                                }
558                            }),
559                        });
560
561                        self.restore_snapshot(snapshot);
562                        Ok(PredicateKindOrStructBody::StructBody(body))
563                    }
564                    Ok(_) => Err(type_err),
565                    Err(body_err) => {
566                        body_err.cancel();
567                        Err(type_err)
568                    }
569                }
570            }
571        }
572    }
573
574    fn parse_ty_where_predicate_kind(&mut self) -> PResult<'a, ast::WherePredicateKind> {
575        // Parse optional `for<'a, 'b>`.
576        // This `for` is parsed greedily and applies to the whole predicate,
577        // the bounded type can have its own `for` applying only to it.
578        // Examples:
579        // * `for<'a> Trait1<'a>: Trait2<'a /* ok */>`
580        // * `(for<'a> Trait1<'a>): Trait2<'a /* not ok */>`
581        // * `for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /* ok */, 'b /* not ok */>`
582        let (bound_vars, _) = self.parse_higher_ranked_binder()?;
583
584        // Parse type with mandatory colon and (possibly empty) bounds,
585        // or with mandatory equality sign and the second type.
586        let ty = self.parse_ty_for_where_clause()?;
587        if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Colon,
    token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)) {
588            let bounds = self.parse_generic_bounds()?;
589            Ok(ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate {
590                bound_generic_params: bound_vars,
591                bounded_ty: ty,
592                bounds,
593            }))
594        // FIXME: Decide what should be used here, `=` or `==`.
595        // FIXME: We are just dropping the binders in lifetime_defs on the floor here.
596        } else if self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::Eq,
    token_type: crate::parser::token_type::TokenType::Eq,
}exp!(Eq)) || self.eat(crate::parser::token_type::ExpTokenPair {
    tok: rustc_ast::token::EqEq,
    token_type: crate::parser::token_type::TokenType::EqEq,
}exp!(EqEq)) {
597            let rhs_ty = self.parse_ty()?;
598            Ok(ast::WherePredicateKind::EqPredicate(ast::WhereEqPredicate { lhs_ty: ty, rhs_ty }))
599        } else {
600            self.maybe_recover_bounds_doubled_colon(&ty)?;
601            self.unexpected_any()
602        }
603    }
604
605    pub(super) fn choose_generics_over_qpath(&self, start: usize) -> bool {
606        // There's an ambiguity between generic parameters and qualified paths in impls.
607        // If we see `<` it may start both, so we have to inspect some following tokens.
608        // The following combinations can only start generics,
609        // but not qualified paths (with one exception):
610        //     `<` `>` - empty generic parameters
611        //     `<` `#` - generic parameters with attributes
612        //     `<` (LIFETIME|IDENT) `>` - single generic parameter
613        //     `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
614        //     `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
615        //     `<` (LIFETIME|IDENT) `=` - generic parameter with a default
616        //     `<` const                - generic const parameter
617        //     `<` IDENT `?`            - RECOVERY for `impl<T ?Bound` missing a `:`, meant to
618        //                                avoid the `T?` to `Option<T>` recovery for types.
619        // The only truly ambiguous case is
620        //     `<` IDENT `>` `::` IDENT ...
621        // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
622        // because this is what almost always expected in practice, qualified paths in impls
623        // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
624        self.look_ahead(start, |t| t == &token::Lt)
625            && (self.look_ahead(start + 1, |t| t == &token::Pound || t == &token::Gt)
626                || self.look_ahead(start + 1, |t| t.is_lifetime() || t.is_ident())
627                    && self.look_ahead(start + 2, |t| {
628                        #[allow(non_exhaustive_omitted_patterns)] match t.kind {
    token::Gt | token::Comma | token::Colon | token::Eq => true,
    _ => false,
}matches!(t.kind, token::Gt | token::Comma | token::Colon | token::Eq)
629                        // Recovery-only branch -- this could be removed,
630                        // since it only affects diagnostics currently.
631                            || t.kind == token::Question
632                    })
633                || self.is_keyword_ahead(start + 1, &[kw::Const]))
634    }
635}