rustc_parse/parser/
path.rs

1use std::mem;
2
3use ast::token::IdentIsRaw;
4use rustc_ast::ptr::P;
5use rustc_ast::token::{self, MetaVarKind, Token, TokenKind};
6use rustc_ast::{
7    self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocItemConstraint,
8    AssocItemConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs,
9    Path, PathSegment, QSelf,
10};
11use rustc_errors::{Applicability, Diag, PResult};
12use rustc_span::{BytePos, Ident, Span, kw, sym};
13use thin_vec::ThinVec;
14use tracing::debug;
15
16use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
17use super::{Parser, Restrictions, TokenType};
18use crate::ast::{PatKind, TyKind};
19use crate::errors::{
20    self, FnPathFoundNamedParams, PathFoundAttributeInParams, PathFoundCVariadicParams,
21    PathSingleColon, PathTripleColon,
22};
23use crate::exp;
24use crate::parser::{CommaRecoveryMode, RecoverColon, RecoverComma};
25
26/// Specifies how to parse a path.
27#[derive(Copy, Clone, PartialEq)]
28pub(super) enum PathStyle {
29    /// In some contexts, notably in expressions, paths with generic arguments are ambiguous
30    /// with something else. For example, in expressions `segment < ....` can be interpreted
31    /// as a comparison and `segment ( ....` can be interpreted as a function call.
32    /// In all such contexts the non-path interpretation is preferred by default for practical
33    /// reasons, but the path interpretation can be forced by the disambiguator `::`, e.g.
34    /// `x<y>` - comparisons, `x::<y>` - unambiguously a path.
35    ///
36    /// Also, a path may never be followed by a `:`. This means that we can eagerly recover if
37    /// we encounter it.
38    Expr,
39    /// The same as `Expr`, but may be followed by a `:`.
40    /// For example, this code:
41    /// ```rust
42    /// struct S;
43    ///
44    /// let S: S;
45    /// //  ^ Followed by a `:`
46    /// ```
47    Pat,
48    /// In other contexts, notably in types, no ambiguity exists and paths can be written
49    /// without the disambiguator, e.g., `x<y>` - unambiguously a path.
50    /// Paths with disambiguators are still accepted, `x::<Y>` - unambiguously a path too.
51    Type,
52    /// A path with generic arguments disallowed, e.g., `foo::bar::Baz`, used in imports,
53    /// visibilities or attributes.
54    /// Technically, this variant is unnecessary and e.g., `Expr` can be used instead
55    /// (paths in "mod" contexts have to be checked later for absence of generic arguments
56    /// anyway, due to macros), but it is used to avoid weird suggestions about expected
57    /// tokens when something goes wrong.
58    Mod,
59}
60
61impl PathStyle {
62    fn has_generic_ambiguity(&self) -> bool {
63        matches!(self, Self::Expr | Self::Pat)
64    }
65}
66
67impl<'a> Parser<'a> {
68    /// Parses a qualified path.
69    /// Assumes that the leading `<` has been parsed already.
70    ///
71    /// `qualified_path = <type [as trait_ref]>::path`
72    ///
73    /// # Examples
74    /// `<T>::default`
75    /// `<T as U>::a`
76    /// `<T as U>::F::a<S>` (without disambiguator)
77    /// `<T as U>::F::a::<S>` (with disambiguator)
78    pub(super) fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (P<QSelf>, Path)> {
79        let lo = self.prev_token.span;
80        let ty = self.parse_ty()?;
81
82        // `path` will contain the prefix of the path up to the `>`,
83        // if any (e.g., `U` in the `<T as U>::*` examples
84        // above). `path_span` has the span of that path, or an empty
85        // span in the case of something like `<T>::Bar`.
86        let (mut path, path_span);
87        if self.eat_keyword(exp!(As)) {
88            let path_lo = self.token.span;
89            path = self.parse_path(PathStyle::Type)?;
90            path_span = path_lo.to(self.prev_token.span);
91        } else {
92            path_span = self.token.span.to(self.token.span);
93            path = ast::Path { segments: ThinVec::new(), span: path_span, tokens: None };
94        }
95
96        // See doc comment for `unmatched_angle_bracket_count`.
97        self.expect(exp!(Gt))?;
98        if self.unmatched_angle_bracket_count > 0 {
99            self.unmatched_angle_bracket_count -= 1;
100            debug!("parse_qpath: (decrement) count={:?}", self.unmatched_angle_bracket_count);
101        }
102
103        let is_import_coupler = self.is_import_coupler();
104        if !is_import_coupler && !self.recover_colon_before_qpath_proj() {
105            self.expect(exp!(PathSep))?;
106        }
107
108        let qself = P(QSelf { ty, path_span, position: path.segments.len() });
109        if !is_import_coupler {
110            self.parse_path_segments(&mut path.segments, style, None)?;
111        }
112
113        Ok((
114            qself,
115            Path { segments: path.segments, span: lo.to(self.prev_token.span), tokens: None },
116        ))
117    }
118
119    /// Recover from an invalid single colon, when the user likely meant a qualified path.
120    /// We avoid emitting this if not followed by an identifier, as our assumption that the user
121    /// intended this to be a qualified path may not be correct.
122    ///
123    /// ```ignore (diagnostics)
124    /// <Bar as Baz<T>>:Qux
125    ///                ^ help: use double colon
126    /// ```
127    fn recover_colon_before_qpath_proj(&mut self) -> bool {
128        if !self.check_noexpect(&TokenKind::Colon)
129            || self.look_ahead(1, |t| !t.is_ident() || t.is_reserved_ident())
130        {
131            return false;
132        }
133
134        self.bump(); // colon
135
136        self.dcx()
137            .struct_span_err(
138                self.prev_token.span,
139                "found single colon before projection in qualified path",
140            )
141            .with_span_suggestion(
142                self.prev_token.span,
143                "use double colon",
144                "::",
145                Applicability::MachineApplicable,
146            )
147            .emit();
148
149        true
150    }
151
152    pub(super) fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> {
153        self.parse_path_inner(style, None)
154    }
155
156    /// Parses simple paths.
157    ///
158    /// `path = [::] segment+`
159    /// `segment = ident | ident[::]<args> | ident[::](args) [-> type]`
160    ///
161    /// # Examples
162    /// `a::b::C<D>` (without disambiguator)
163    /// `a::b::C::<D>` (with disambiguator)
164    /// `Fn(Args)` (without disambiguator)
165    /// `Fn::(Args)` (with disambiguator)
166    pub(super) fn parse_path_inner(
167        &mut self,
168        style: PathStyle,
169        ty_generics: Option<&Generics>,
170    ) -> PResult<'a, Path> {
171        let reject_generics_if_mod_style = |parser: &Parser<'_>, path: Path| {
172            // Ensure generic arguments don't end up in attribute paths, such as:
173            //
174            //     macro_rules! m {
175            //         ($p:path) => { #[$p] struct S; }
176            //     }
177            //
178            //     m!(inline<u8>); //~ ERROR: unexpected generic arguments in path
179            //
180            if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some())
181            {
182                let span = path
183                    .segments
184                    .iter()
185                    .filter_map(|segment| segment.args.as_ref())
186                    .map(|arg| arg.span())
187                    .collect::<Vec<_>>();
188                parser.dcx().emit_err(errors::GenericsInPath { span });
189                // Ignore these arguments to prevent unexpected behaviors.
190                let segments = path
191                    .segments
192                    .iter()
193                    .map(|segment| PathSegment { ident: segment.ident, id: segment.id, args: None })
194                    .collect();
195                Path { segments, ..path }
196            } else {
197                path
198            }
199        };
200
201        if let Some(path) =
202            self.eat_metavar_seq(MetaVarKind::Path, |this| this.parse_path(PathStyle::Type))
203        {
204            return Ok(reject_generics_if_mod_style(self, path));
205        }
206
207        // If we have a `ty` metavar in the form of a path, reparse it directly as a path, instead
208        // of reparsing it as a `ty` and then extracting the path.
209        if let Some(path) = self.eat_metavar_seq(MetaVarKind::Ty { is_path: true }, |this| {
210            this.parse_path(PathStyle::Type)
211        }) {
212            return Ok(reject_generics_if_mod_style(self, path));
213        }
214
215        let lo = self.token.span;
216        let mut segments = ThinVec::new();
217        let mod_sep_ctxt = self.token.span.ctxt();
218        if self.eat_path_sep() {
219            segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
220        }
221        self.parse_path_segments(&mut segments, style, ty_generics)?;
222        Ok(Path { segments, span: lo.to(self.prev_token.span), tokens: None })
223    }
224
225    pub(super) fn parse_path_segments(
226        &mut self,
227        segments: &mut ThinVec<PathSegment>,
228        style: PathStyle,
229        ty_generics: Option<&Generics>,
230    ) -> PResult<'a, ()> {
231        loop {
232            let segment = self.parse_path_segment(style, ty_generics)?;
233            if style.has_generic_ambiguity() {
234                // In order to check for trailing angle brackets, we must have finished
235                // recursing (`parse_path_segment` can indirectly call this function),
236                // that is, the next token must be the highlighted part of the below example:
237                //
238                // `Foo::<Bar as Baz<T>>::Qux`
239                //                      ^ here
240                //
241                // As opposed to the below highlight (if we had only finished the first
242                // recursion):
243                //
244                // `Foo::<Bar as Baz<T>>::Qux`
245                //                     ^ here
246                //
247                // `PathStyle::Expr` is only provided at the root invocation and never in
248                // `parse_path_segment` to recurse and therefore can be checked to maintain
249                // this invariant.
250                self.check_trailing_angle_brackets(&segment, &[exp!(PathSep)]);
251            }
252            segments.push(segment);
253
254            if self.is_import_coupler() || !self.eat_path_sep() {
255                // IMPORTANT: We can *only ever* treat single colons as typo'ed double colons in
256                // expression contexts (!) since only there paths cannot possibly be followed by
257                // a colon and still form a syntactically valid construct. In pattern contexts,
258                // a path may be followed by a type annotation. E.g., `let pat:ty`. In type
259                // contexts, a path may be followed by a list of bounds. E.g., `where ty:bound`.
260                if self.may_recover()
261                    && style == PathStyle::Expr // (!)
262                    && self.token == token::Colon
263                    && self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
264                {
265                    // Emit a special error message for `a::b:c` to help users
266                    // otherwise, `a: c` might have meant to introduce a new binding
267                    if self.token.span.lo() == self.prev_token.span.hi()
268                        && self.look_ahead(1, |token| self.token.span.hi() == token.span.lo())
269                    {
270                        self.bump(); // bump past the colon
271                        self.dcx().emit_err(PathSingleColon {
272                            span: self.prev_token.span,
273                            suggestion: self.prev_token.span.shrink_to_hi(),
274                        });
275                    }
276                    continue;
277                }
278
279                return Ok(());
280            }
281        }
282    }
283
284    /// Eat `::` or, potentially, `:::`.
285    #[must_use]
286    pub(super) fn eat_path_sep(&mut self) -> bool {
287        let result = self.eat(exp!(PathSep));
288        if result && self.may_recover() {
289            if self.eat_noexpect(&token::Colon) {
290                self.dcx().emit_err(PathTripleColon { span: self.prev_token.span });
291            }
292        }
293        result
294    }
295
296    pub(super) fn parse_path_segment(
297        &mut self,
298        style: PathStyle,
299        ty_generics: Option<&Generics>,
300    ) -> PResult<'a, PathSegment> {
301        let ident = self.parse_path_segment_ident()?;
302        let is_args_start = |token: &Token| {
303            matches!(token.kind, token::Lt | token::Shl | token::OpenParen | token::LArrow)
304        };
305        let check_args_start = |this: &mut Self| {
306            this.expected_token_types.insert(TokenType::Lt);
307            this.expected_token_types.insert(TokenType::OpenParen);
308            is_args_start(&this.token)
309        };
310
311        Ok(
312            if style == PathStyle::Type && check_args_start(self)
313                || style != PathStyle::Mod && self.check_path_sep_and_look_ahead(is_args_start)
314            {
315                // We use `style == PathStyle::Expr` to check if this is in a recursion or not. If
316                // it isn't, then we reset the unmatched angle bracket count as we're about to start
317                // parsing a new path.
318                if style == PathStyle::Expr {
319                    self.unmatched_angle_bracket_count = 0;
320                }
321
322                // Generic arguments are found - `<`, `(`, `::<` or `::(`.
323                // First, eat `::` if it exists.
324                let _ = self.eat_path_sep();
325
326                let lo = self.token.span;
327                let args = if self.eat_lt() {
328                    // `<'a, T, A = U>`
329                    let args = self.parse_angle_args_with_leading_angle_bracket_recovery(
330                        style,
331                        lo,
332                        ty_generics,
333                    )?;
334                    self.expect_gt().map_err(|mut err| {
335                        // Try to recover a `:` into a `::`
336                        if self.token == token::Colon
337                            && self.look_ahead(1, |token| {
338                                token.is_ident() && !token.is_reserved_ident()
339                            })
340                        {
341                            err.cancel();
342                            err = self.dcx().create_err(PathSingleColon {
343                                span: self.token.span,
344                                suggestion: self.prev_token.span.shrink_to_hi(),
345                            });
346                        }
347                        // Attempt to find places where a missing `>` might belong.
348                        else if let Some(arg) = args
349                            .iter()
350                            .rev()
351                            .find(|arg| !matches!(arg, AngleBracketedArg::Constraint(_)))
352                        {
353                            err.span_suggestion_verbose(
354                                arg.span().shrink_to_hi(),
355                                "you might have meant to end the type parameters here",
356                                ">",
357                                Applicability::MaybeIncorrect,
358                            );
359                        }
360                        err
361                    })?;
362                    let span = lo.to(self.prev_token.span);
363                    AngleBracketedArgs { args, span }.into()
364                } else if self.token == token::OpenParen
365                    // FIXME(return_type_notation): Could also recover `...` here.
366                    && self.look_ahead(1, |t| *t == token::DotDot)
367                {
368                    self.bump(); // (
369                    self.bump(); // ..
370                    self.expect(exp!(CloseParen))?;
371                    let span = lo.to(self.prev_token.span);
372
373                    self.psess.gated_spans.gate(sym::return_type_notation, span);
374
375                    let prev_lo = self.prev_token.span.shrink_to_hi();
376                    if self.eat_noexpect(&token::RArrow) {
377                        let lo = self.prev_token.span;
378                        let ty = self.parse_ty()?;
379                        let span = lo.to(ty.span);
380                        let suggestion = prev_lo.to(ty.span);
381                        self.dcx()
382                            .emit_err(errors::BadReturnTypeNotationOutput { span, suggestion });
383                    }
384
385                    P(ast::GenericArgs::ParenthesizedElided(span))
386                } else {
387                    // `(T, U) -> R`
388
389                    let prev_token_before_parsing = self.prev_token;
390                    let token_before_parsing = self.token;
391                    let mut snapshot = None;
392                    if self.may_recover()
393                        && prev_token_before_parsing == token::PathSep
394                        && (style == PathStyle::Expr && self.token.can_begin_expr()
395                            || style == PathStyle::Pat
396                                && self.token.can_begin_pattern(token::NtPatKind::PatParam {
397                                    inferred: false,
398                                }))
399                    {
400                        snapshot = Some(self.create_snapshot_for_diagnostic());
401                    }
402
403                    let dcx = self.dcx();
404                    let parse_params_result = self.parse_paren_comma_seq(|p| {
405                        let param = p.parse_param_general(|_| false, false, false);
406                        param.map(move |param| {
407                            if !matches!(param.pat.kind, PatKind::Missing) {
408                                dcx.emit_err(FnPathFoundNamedParams {
409                                    named_param_span: param.pat.span,
410                                });
411                            }
412                            if matches!(param.ty.kind, TyKind::CVarArgs) {
413                                dcx.emit_err(PathFoundCVariadicParams { span: param.pat.span });
414                            }
415                            if !param.attrs.is_empty() {
416                                dcx.emit_err(PathFoundAttributeInParams {
417                                    span: param.attrs[0].span,
418                                });
419                            }
420                            param.ty
421                        })
422                    });
423
424                    let (inputs, _) = match parse_params_result {
425                        Ok(output) => output,
426                        Err(mut error) if prev_token_before_parsing == token::PathSep => {
427                            error.span_label(
428                                prev_token_before_parsing.span.to(token_before_parsing.span),
429                                "while parsing this parenthesized list of type arguments starting here",
430                            );
431
432                            if let Some(mut snapshot) = snapshot {
433                                snapshot.recover_fn_call_leading_path_sep(
434                                    style,
435                                    prev_token_before_parsing,
436                                    &mut error,
437                                )
438                            }
439
440                            return Err(error);
441                        }
442                        Err(error) => return Err(error),
443                    };
444                    let inputs_span = lo.to(self.prev_token.span);
445                    let output =
446                        self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
447                    let span = ident.span.to(self.prev_token.span);
448                    ParenthesizedArgs { span, inputs, inputs_span, output }.into()
449                };
450
451                PathSegment { ident, args: Some(args), id: ast::DUMMY_NODE_ID }
452            } else {
453                // Generic arguments are not found.
454                PathSegment::from_ident(ident)
455            },
456        )
457    }
458
459    pub(super) fn parse_path_segment_ident(&mut self) -> PResult<'a, Ident> {
460        match self.token.ident() {
461            Some((ident, IdentIsRaw::No)) if ident.is_path_segment_keyword() => {
462                self.bump();
463                Ok(ident)
464            }
465            _ => self.parse_ident(),
466        }
467    }
468
469    /// Recover `$path::(...)` as `$path(...)`.
470    ///
471    /// ```ignore (diagnostics)
472    /// foo::(420, "bar")
473    ///    ^^ remove extra separator to make the function call
474    /// // or
475    /// match x {
476    ///    Foo::(420, "bar") => { ... },
477    ///       ^^ remove extra separator to turn this into tuple struct pattern
478    ///    _ => { ... },
479    /// }
480    /// ```
481    fn recover_fn_call_leading_path_sep(
482        &mut self,
483        style: PathStyle,
484        prev_token_before_parsing: Token,
485        error: &mut Diag<'_>,
486    ) {
487        match style {
488            PathStyle::Expr
489                if let Ok(_) = self
490                    .parse_paren_comma_seq(|p| p.parse_expr())
491                    .map_err(|error| error.cancel()) => {}
492            PathStyle::Pat
493                if let Ok(_) = self
494                    .parse_paren_comma_seq(|p| {
495                        p.parse_pat_allow_top_guard(
496                            None,
497                            RecoverComma::No,
498                            RecoverColon::No,
499                            CommaRecoveryMode::LikelyTuple,
500                        )
501                    })
502                    .map_err(|error| error.cancel()) => {}
503            _ => {
504                return;
505            }
506        }
507
508        if let token::PathSep | token::RArrow = self.token.kind {
509            return;
510        }
511
512        error.span_suggestion_verbose(
513            prev_token_before_parsing.span,
514            format!(
515                "consider removing the `::` here to {}",
516                match style {
517                    PathStyle::Expr => "call the expression",
518                    PathStyle::Pat => "turn this into a tuple struct pattern",
519                    _ => {
520                        return;
521                    }
522                }
523            ),
524            "",
525            Applicability::MaybeIncorrect,
526        );
527    }
528
529    /// Parses generic args (within a path segment) with recovery for extra leading angle brackets.
530    /// For the purposes of understanding the parsing logic of generic arguments, this function
531    /// can be thought of being the same as just calling `self.parse_angle_args()` if the source
532    /// had the correct amount of leading angle brackets.
533    ///
534    /// ```ignore (diagnostics)
535    /// bar::<<<<T as Foo>::Output>();
536    ///      ^^ help: remove extra angle brackets
537    /// ```
538    fn parse_angle_args_with_leading_angle_bracket_recovery(
539        &mut self,
540        style: PathStyle,
541        lo: Span,
542        ty_generics: Option<&Generics>,
543    ) -> PResult<'a, ThinVec<AngleBracketedArg>> {
544        // We need to detect whether there are extra leading left angle brackets and produce an
545        // appropriate error and suggestion. This cannot be implemented by looking ahead at
546        // upcoming tokens for a matching `>` character - if there are unmatched `<` tokens
547        // then there won't be matching `>` tokens to find.
548        //
549        // To explain how this detection works, consider the following example:
550        //
551        // ```ignore (diagnostics)
552        // bar::<<<<T as Foo>::Output>();
553        //      ^^ help: remove extra angle brackets
554        // ```
555        //
556        // Parsing of the left angle brackets starts in this function. We start by parsing the
557        // `<` token (incrementing the counter of unmatched angle brackets on `Parser` via
558        // `eat_lt`):
559        //
560        // *Upcoming tokens:* `<<<<T as Foo>::Output>;`
561        // *Unmatched count:* 1
562        // *`parse_path_segment` calls deep:* 0
563        //
564        // This has the effect of recursing as this function is called if a `<` character
565        // is found within the expected generic arguments:
566        //
567        // *Upcoming tokens:* `<<<T as Foo>::Output>;`
568        // *Unmatched count:* 2
569        // *`parse_path_segment` calls deep:* 1
570        //
571        // Eventually we will have recursed until having consumed all of the `<` tokens and
572        // this will be reflected in the count:
573        //
574        // *Upcoming tokens:* `T as Foo>::Output>;`
575        // *Unmatched count:* 4
576        // `parse_path_segment` calls deep:* 3
577        //
578        // The parser will continue until reaching the first `>` - this will decrement the
579        // unmatched angle bracket count and return to the parent invocation of this function
580        // having succeeded in parsing:
581        //
582        // *Upcoming tokens:* `::Output>;`
583        // *Unmatched count:* 3
584        // *`parse_path_segment` calls deep:* 2
585        //
586        // This will continue until the next `>` character which will also return successfully
587        // to the parent invocation of this function and decrement the count:
588        //
589        // *Upcoming tokens:* `;`
590        // *Unmatched count:* 2
591        // *`parse_path_segment` calls deep:* 1
592        //
593        // At this point, this function will expect to find another matching `>` character but
594        // won't be able to and will return an error. This will continue all the way up the
595        // call stack until the first invocation:
596        //
597        // *Upcoming tokens:* `;`
598        // *Unmatched count:* 2
599        // *`parse_path_segment` calls deep:* 0
600        //
601        // In doing this, we have managed to work out how many unmatched leading left angle
602        // brackets there are, but we cannot recover as the unmatched angle brackets have
603        // already been consumed. To remedy this, we keep a snapshot of the parser state
604        // before we do the above. We can then inspect whether we ended up with a parsing error
605        // and unmatched left angle brackets and if so, restore the parser state before we
606        // consumed any `<` characters to emit an error and consume the erroneous tokens to
607        // recover by attempting to parse again.
608        //
609        // In practice, the recursion of this function is indirect and there will be other
610        // locations that consume some `<` characters - as long as we update the count when
611        // this happens, it isn't an issue.
612
613        let is_first_invocation = style == PathStyle::Expr;
614        // Take a snapshot before attempting to parse - we can restore this later.
615        let snapshot = is_first_invocation.then(|| self.clone());
616
617        self.angle_bracket_nesting += 1;
618        debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)");
619        match self.parse_angle_args(ty_generics) {
620            Ok(args) => {
621                self.angle_bracket_nesting -= 1;
622                Ok(args)
623            }
624            Err(e) if self.angle_bracket_nesting > 10 => {
625                self.angle_bracket_nesting -= 1;
626                // When encountering severely malformed code where there are several levels of
627                // nested unclosed angle args (`f::<f::<f::<f::<...`), we avoid severe O(n^2)
628                // behavior by bailing out earlier (#117080).
629                e.emit().raise_fatal();
630            }
631            Err(e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => {
632                self.angle_bracket_nesting -= 1;
633
634                // Swap `self` with our backup of the parser state before attempting to parse
635                // generic arguments.
636                let snapshot = mem::replace(self, snapshot.unwrap());
637
638                // Eat the unmatched angle brackets.
639                let all_angle_brackets = (0..snapshot.unmatched_angle_bracket_count)
640                    .fold(true, |a, _| a && self.eat_lt());
641
642                if !all_angle_brackets {
643                    // If there are other tokens in between the extraneous `<`s, we cannot simply
644                    // suggest to remove them. This check also prevents us from accidentally ending
645                    // up in the middle of a multibyte character (issue #84104).
646                    let _ = mem::replace(self, snapshot);
647                    Err(e)
648                } else {
649                    // Cancel error from being unable to find `>`. We know the error
650                    // must have been this due to a non-zero unmatched angle bracket
651                    // count.
652                    e.cancel();
653
654                    debug!(
655                        "parse_generic_args_with_leading_angle_bracket_recovery: (snapshot failure) \
656                         snapshot.count={:?}",
657                        snapshot.unmatched_angle_bracket_count,
658                    );
659
660                    // Make a span over ${unmatched angle bracket count} characters.
661                    // This is safe because `all_angle_brackets` ensures that there are only `<`s,
662                    // i.e. no multibyte characters, in this range.
663                    let span = lo
664                        .with_hi(lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count.into()));
665                    self.dcx().emit_err(errors::UnmatchedAngle {
666                        span,
667                        plural: snapshot.unmatched_angle_bracket_count > 1,
668                    });
669
670                    // Try again without unmatched angle bracket characters.
671                    self.parse_angle_args(ty_generics)
672                }
673            }
674            Err(e) => {
675                self.angle_bracket_nesting -= 1;
676                Err(e)
677            }
678        }
679    }
680
681    /// Parses (possibly empty) list of generic arguments / associated item constraints,
682    /// possibly including trailing comma.
683    pub(super) fn parse_angle_args(
684        &mut self,
685        ty_generics: Option<&Generics>,
686    ) -> PResult<'a, ThinVec<AngleBracketedArg>> {
687        let mut args = ThinVec::new();
688        while let Some(arg) = self.parse_angle_arg(ty_generics)? {
689            args.push(arg);
690            if !self.eat(exp!(Comma)) {
691                if self.check_noexpect(&TokenKind::Semi)
692                    && self.look_ahead(1, |t| t.is_ident() || t.is_lifetime())
693                {
694                    // Add `>` to the list of expected tokens.
695                    self.check(exp!(Gt));
696                    // Handle `,` to `;` substitution
697                    let mut err = self.unexpected().unwrap_err();
698                    self.bump();
699                    err.span_suggestion_verbose(
700                        self.prev_token.span.until(self.token.span),
701                        "use a comma to separate type parameters",
702                        ", ",
703                        Applicability::MachineApplicable,
704                    );
705                    err.emit();
706                    continue;
707                }
708                if !self.token.kind.should_end_const_arg()
709                    && self.handle_ambiguous_unbraced_const_arg(&mut args)?
710                {
711                    // We've managed to (partially) recover, so continue trying to parse
712                    // arguments.
713                    continue;
714                }
715                break;
716            }
717        }
718        Ok(args)
719    }
720
721    /// Parses a single argument in the angle arguments `<...>` of a path segment.
722    fn parse_angle_arg(
723        &mut self,
724        ty_generics: Option<&Generics>,
725    ) -> PResult<'a, Option<AngleBracketedArg>> {
726        let lo = self.token.span;
727        let arg = self.parse_generic_arg(ty_generics)?;
728        match arg {
729            Some(arg) => {
730                // we are using noexpect here because we first want to find out if either `=` or `:`
731                // is present and then use that info to push the other token onto the tokens list
732                let separated =
733                    self.check_noexpect(&token::Colon) || self.check_noexpect(&token::Eq);
734                if separated && (self.check(exp!(Colon)) | self.check(exp!(Eq))) {
735                    let arg_span = arg.span();
736                    let (binder, ident, gen_args) = match self.get_ident_from_generic_arg(&arg) {
737                        Ok(ident_gen_args) => ident_gen_args,
738                        Err(()) => return Ok(Some(AngleBracketedArg::Arg(arg))),
739                    };
740                    if binder {
741                        // FIXME(compiler-errors): this could be improved by suggesting lifting
742                        // this up to the trait, at least before this becomes real syntax.
743                        // e.g. `Trait<for<'a> Assoc = Ty>` -> `for<'a> Trait<Assoc = Ty>`
744                        return Err(self.dcx().struct_span_err(
745                            arg_span,
746                            "`for<...>` is not allowed on associated type bounds",
747                        ));
748                    }
749                    let kind = if self.eat(exp!(Colon)) {
750                        AssocItemConstraintKind::Bound { bounds: self.parse_generic_bounds()? }
751                    } else if self.eat(exp!(Eq)) {
752                        self.parse_assoc_equality_term(
753                            ident,
754                            gen_args.as_ref(),
755                            self.prev_token.span,
756                        )?
757                    } else {
758                        unreachable!();
759                    };
760
761                    let span = lo.to(self.prev_token.span);
762
763                    let constraint =
764                        AssocItemConstraint { id: ast::DUMMY_NODE_ID, ident, gen_args, kind, span };
765                    Ok(Some(AngleBracketedArg::Constraint(constraint)))
766                } else {
767                    // we only want to suggest `:` and `=` in contexts where the previous token
768                    // is an ident and the current token or the next token is an ident
769                    if self.prev_token.is_ident()
770                        && (self.token.is_ident() || self.look_ahead(1, |token| token.is_ident()))
771                    {
772                        self.check(exp!(Colon));
773                        self.check(exp!(Eq));
774                    }
775                    Ok(Some(AngleBracketedArg::Arg(arg)))
776                }
777            }
778            _ => Ok(None),
779        }
780    }
781
782    /// Parse the term to the right of an associated item equality constraint.
783    ///
784    /// That is, parse `$term` in `Item = $term` where `$term` is a type or
785    /// a const expression (wrapped in curly braces if complex).
786    fn parse_assoc_equality_term(
787        &mut self,
788        ident: Ident,
789        gen_args: Option<&GenericArgs>,
790        eq: Span,
791    ) -> PResult<'a, AssocItemConstraintKind> {
792        let arg = self.parse_generic_arg(None)?;
793        let span = ident.span.to(self.prev_token.span);
794        let term = match arg {
795            Some(GenericArg::Type(ty)) => ty.into(),
796            Some(GenericArg::Const(c)) => {
797                self.psess.gated_spans.gate(sym::associated_const_equality, span);
798                c.into()
799            }
800            Some(GenericArg::Lifetime(lt)) => {
801                let guar = self.dcx().emit_err(errors::LifetimeInEqConstraint {
802                    span: lt.ident.span,
803                    lifetime: lt.ident,
804                    binding_label: span,
805                    colon_sugg: gen_args
806                        .map_or(ident.span, |args| args.span())
807                        .between(lt.ident.span),
808                });
809                self.mk_ty(lt.ident.span, ast::TyKind::Err(guar)).into()
810            }
811            None => {
812                let after_eq = eq.shrink_to_hi();
813                let before_next = self.token.span.shrink_to_lo();
814                let mut err = self
815                    .dcx()
816                    .struct_span_err(after_eq.to(before_next), "missing type to the right of `=`");
817                if matches!(self.token.kind, token::Comma | token::Gt) {
818                    err.span_suggestion(
819                        self.psess.source_map().next_point(eq).to(before_next),
820                        "to constrain the associated type, add a type after `=`",
821                        " TheType",
822                        Applicability::HasPlaceholders,
823                    );
824                    err.span_suggestion(
825                        eq.to(before_next),
826                        format!("remove the `=` if `{ident}` is a type"),
827                        "",
828                        Applicability::MaybeIncorrect,
829                    )
830                } else {
831                    err.span_label(
832                        self.token.span,
833                        format!("expected type, found {}", super::token_descr(&self.token)),
834                    )
835                };
836                return Err(err);
837            }
838        };
839        Ok(AssocItemConstraintKind::Equality { term })
840    }
841
842    /// We do not permit arbitrary expressions as const arguments. They must be one of:
843    /// - An expression surrounded in `{}`.
844    /// - A literal.
845    /// - A numeric literal prefixed by `-`.
846    /// - A single-segment path.
847    pub(super) fn expr_is_valid_const_arg(&self, expr: &P<rustc_ast::Expr>) -> bool {
848        match &expr.kind {
849            ast::ExprKind::Block(_, _)
850            | ast::ExprKind::Lit(_)
851            | ast::ExprKind::IncludedBytes(..) => true,
852            ast::ExprKind::Unary(ast::UnOp::Neg, expr) => {
853                matches!(expr.kind, ast::ExprKind::Lit(_))
854            }
855            // We can only resolve single-segment paths at the moment, because multi-segment paths
856            // require type-checking: see `visit_generic_arg` in `src/librustc_resolve/late.rs`.
857            ast::ExprKind::Path(None, path)
858                if let [segment] = path.segments.as_slice()
859                    && segment.args.is_none() =>
860            {
861                true
862            }
863            _ => false,
864        }
865    }
866
867    /// Parse a const argument, e.g. `<3>`. It is assumed the angle brackets will be parsed by
868    /// the caller.
869    pub(super) fn parse_const_arg(&mut self) -> PResult<'a, AnonConst> {
870        // Parse const argument.
871        let value = if self.token.kind == token::OpenBrace {
872            self.parse_expr_block(None, self.token.span, BlockCheckMode::Default)?
873        } else {
874            self.handle_unambiguous_unbraced_const_arg()?
875        };
876        Ok(AnonConst { id: ast::DUMMY_NODE_ID, value })
877    }
878
879    /// Parse a generic argument in a path segment.
880    /// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`.
881    pub(super) fn parse_generic_arg(
882        &mut self,
883        ty_generics: Option<&Generics>,
884    ) -> PResult<'a, Option<GenericArg>> {
885        let start = self.token.span;
886        let arg = if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
887            // Parse lifetime argument.
888            GenericArg::Lifetime(self.expect_lifetime())
889        } else if self.check_const_arg() {
890            // Parse const argument.
891            GenericArg::Const(self.parse_const_arg()?)
892        } else if self.check_type() {
893            // Parse type argument.
894
895            // Proactively create a parser snapshot enabling us to rewind and try to reparse the
896            // input as a const expression in case we fail to parse a type. If we successfully
897            // do so, we will report an error that it needs to be wrapped in braces.
898            let mut snapshot = None;
899            if self.may_recover() && self.token.can_begin_expr() {
900                snapshot = Some(self.create_snapshot_for_diagnostic());
901            }
902
903            match self.parse_ty() {
904                Ok(ty) => {
905                    // Since the type parser recovers from some malformed slice and array types and
906                    // successfully returns a type, we need to look for `TyKind::Err`s in the
907                    // type to determine if error recovery has occurred and if the input is not a
908                    // syntactically valid type after all.
909                    if let ast::TyKind::Slice(inner_ty) | ast::TyKind::Array(inner_ty, _) = &ty.kind
910                        && let ast::TyKind::Err(_) = inner_ty.kind
911                        && let Some(snapshot) = snapshot
912                        && let Some(expr) =
913                            self.recover_unbraced_const_arg_that_can_begin_ty(snapshot)
914                    {
915                        return Ok(Some(
916                            self.dummy_const_arg_needs_braces(
917                                self.dcx()
918                                    .struct_span_err(expr.span, "invalid const generic expression"),
919                                expr.span,
920                            ),
921                        ));
922                    }
923
924                    GenericArg::Type(ty)
925                }
926                Err(err) => {
927                    if let Some(snapshot) = snapshot
928                        && let Some(expr) =
929                            self.recover_unbraced_const_arg_that_can_begin_ty(snapshot)
930                    {
931                        return Ok(Some(self.dummy_const_arg_needs_braces(err, expr.span)));
932                    }
933                    // Try to recover from possible `const` arg without braces.
934                    return self.recover_const_arg(start, err).map(Some);
935                }
936            }
937        } else if self.token.is_keyword(kw::Const) {
938            return self.recover_const_param_declaration(ty_generics);
939        } else {
940            // Fall back by trying to parse a const-expr expression. If we successfully do so,
941            // then we should report an error that it needs to be wrapped in braces.
942            let snapshot = self.create_snapshot_for_diagnostic();
943            let attrs = self.parse_outer_attributes()?;
944            match self.parse_expr_res(Restrictions::CONST_EXPR, attrs) {
945                Ok((expr, _)) => {
946                    return Ok(Some(self.dummy_const_arg_needs_braces(
947                        self.dcx().struct_span_err(expr.span, "invalid const generic expression"),
948                        expr.span,
949                    )));
950                }
951                Err(err) => {
952                    self.restore_snapshot(snapshot);
953                    err.cancel();
954                    return Ok(None);
955                }
956            }
957        };
958        Ok(Some(arg))
959    }
960
961    /// Given a arg inside of generics, we try to destructure it as if it were the LHS in
962    /// `LHS = ...`, i.e. an associated item binding.
963    /// This returns a bool indicating if there are any `for<'a, 'b>` binder args, the
964    /// identifier, and any GAT arguments.
965    fn get_ident_from_generic_arg(
966        &self,
967        gen_arg: &GenericArg,
968    ) -> Result<(bool, Ident, Option<GenericArgs>), ()> {
969        if let GenericArg::Type(ty) = gen_arg {
970            if let ast::TyKind::Path(qself, path) = &ty.kind
971                && qself.is_none()
972                && let [seg] = path.segments.as_slice()
973            {
974                return Ok((false, seg.ident, seg.args.as_deref().cloned()));
975            } else if let ast::TyKind::TraitObject(bounds, ast::TraitObjectSyntax::None) = &ty.kind
976                && let [ast::GenericBound::Trait(trait_ref)] = bounds.as_slice()
977                && trait_ref.modifiers == ast::TraitBoundModifiers::NONE
978                && let [seg] = trait_ref.trait_ref.path.segments.as_slice()
979            {
980                return Ok((true, seg.ident, seg.args.as_deref().cloned()));
981            }
982        }
983        Err(())
984    }
985}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy