1 use super::ty::{AllowPlus, RecoverQPath};
2 use super::{Parser, TokenType};
3 use crate::maybe_whole;
5 self, AngleBracketedArgs, Ident, ParenthesizedArgs, Path, PathSegment, QSelf,
8 AnonConst, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode, GenericArg,
10 use rustc_ast::token::{self, Token};
11 use rustc_errors::{pluralize, Applicability, PResult};
12 use rustc_span::source_map::{BytePos, Span};
13 use rustc_span::symbol::{kw, sym};
18 /// Specifies how to parse a path.
19 #[derive(Copy, Clone, PartialEq)]
21 /// In some contexts, notably in expressions, paths with generic arguments are ambiguous
22 /// with something else. For example, in expressions `segment < ....` can be interpreted
23 /// as a comparison and `segment ( ....` can be interpreted as a function call.
24 /// In all such contexts the non-path interpretation is preferred by default for practical
25 /// reasons, but the path interpretation can be forced by the disambiguator `::`, e.g.
26 /// `x<y>` - comparisons, `x::<y>` - unambiguously a path.
28 /// In other contexts, notably in types, no ambiguity exists and paths can be written
29 /// without the disambiguator, e.g., `x<y>` - unambiguously a path.
30 /// Paths with disambiguators are still accepted, `x::<Y>` - unambiguously a path too.
32 /// A path with generic arguments disallowed, e.g., `foo::bar::Baz`, used in imports,
33 /// visibilities or attributes.
34 /// Technically, this variant is unnecessary and e.g., `Expr` can be used instead
35 /// (paths in "mod" contexts have to be checked later for absence of generic arguments
36 /// anyway, due to macros), but it is used to avoid weird suggestions about expected
37 /// tokens when something goes wrong.
42 /// Parses a qualified path.
43 /// Assumes that the leading `<` has been parsed already.
45 /// `qualified_path = <type [as trait_ref]>::path`
50 /// `<T as U>::F::a<S>` (without disambiguator)
51 /// `<T as U>::F::a::<S>` (with disambiguator)
52 pub(super) fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (QSelf, Path)> {
53 let lo = self.prev_span;
54 let ty = self.parse_ty()?;
56 // `path` will contain the prefix of the path up to the `>`,
57 // if any (e.g., `U` in the `<T as U>::*` examples
58 // above). `path_span` has the span of that path, or an empty
59 // span in the case of something like `<T>::Bar`.
60 let (mut path, path_span);
61 if self.eat_keyword(kw::As) {
62 let path_lo = self.token.span;
63 path = self.parse_path(PathStyle::Type)?;
64 path_span = path_lo.to(self.prev_span);
66 path_span = self.token.span.to(self.token.span);
67 path = ast::Path { segments: Vec::new(), span: path_span };
70 // See doc comment for `unmatched_angle_bracket_count`.
71 self.expect(&token::Gt)?;
72 if self.unmatched_angle_bracket_count > 0 {
73 self.unmatched_angle_bracket_count -= 1;
74 debug!("parse_qpath: (decrement) count={:?}", self.unmatched_angle_bracket_count);
77 if !self.recover_colon_before_qpath_proj() {
78 self.expect(&token::ModSep)?;
81 let qself = QSelf { ty, path_span, position: path.segments.len() };
82 self.parse_path_segments(&mut path.segments, style)?;
84 Ok((qself, Path { segments: path.segments, span: lo.to(self.prev_span) }))
87 /// Recover from an invalid single colon, when the user likely meant a qualified path.
88 /// We avoid emitting this if not followed by an identifier, as our assumption that the user
89 /// intended this to be a qualified path may not be correct.
91 /// ```ignore (diagnostics)
92 /// <Bar as Baz<T>>:Qux
93 /// ^ help: use double colon
95 fn recover_colon_before_qpath_proj(&mut self) -> bool {
96 if self.token.kind != token::Colon
97 || self.look_ahead(1, |t| !t.is_ident() || t.is_reserved_ident())
102 self.bump(); // colon
107 "found single colon before projection in qualified path",
113 Applicability::MachineApplicable,
120 /// Parses simple paths.
122 /// `path = [::] segment+`
123 /// `segment = ident | ident[::]<args> | ident[::](args) [-> type]`
126 /// `a::b::C<D>` (without disambiguator)
127 /// `a::b::C::<D>` (with disambiguator)
128 /// `Fn(Args)` (without disambiguator)
129 /// `Fn::(Args)` (with disambiguator)
130 pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> {
131 maybe_whole!(self, NtPath, |path| {
132 if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some())
134 self.struct_span_err(path.span, "unexpected generic arguments in path").emit();
139 let lo = self.token.span;
140 let mut segments = Vec::new();
141 let mod_sep_ctxt = self.token.span.ctxt();
142 if self.eat(&token::ModSep) {
143 segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
145 self.parse_path_segments(&mut segments, style)?;
147 Ok(Path { segments, span: lo.to(self.prev_span) })
150 pub(super) fn parse_path_segments(
152 segments: &mut Vec<PathSegment>,
154 ) -> PResult<'a, ()> {
156 let segment = self.parse_path_segment(style)?;
157 if style == PathStyle::Expr {
158 // In order to check for trailing angle brackets, we must have finished
159 // recursing (`parse_path_segment` can indirectly call this function),
160 // that is, the next token must be the highlighted part of the below example:
162 // `Foo::<Bar as Baz<T>>::Qux`
165 // As opposed to the below highlight (if we had only finished the first
168 // `Foo::<Bar as Baz<T>>::Qux`
171 // `PathStyle::Expr` is only provided at the root invocation and never in
172 // `parse_path_segment` to recurse and therefore can be checked to maintain
174 self.check_trailing_angle_brackets(&segment, token::ModSep);
176 segments.push(segment);
178 if self.is_import_coupler() || !self.eat(&token::ModSep) {
184 pub(super) fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> {
185 let ident = self.parse_path_segment_ident()?;
187 let is_args_start = |token: &Token| match token.kind {
189 | token::BinOp(token::Shl)
190 | token::OpenDelim(token::Paren)
191 | token::LArrow => true,
194 let check_args_start = |this: &mut Self| {
195 this.expected_tokens.extend_from_slice(&[
196 TokenType::Token(token::Lt),
197 TokenType::Token(token::OpenDelim(token::Paren)),
199 is_args_start(&this.token)
203 if style == PathStyle::Type && check_args_start(self)
204 || style != PathStyle::Mod
205 && self.check(&token::ModSep)
206 && self.look_ahead(1, |t| is_args_start(t))
208 // We use `style == PathStyle::Expr` to check if this is in a recursion or not. If
209 // it isn't, then we reset the unmatched angle bracket count as we're about to start
210 // parsing a new path.
211 if style == PathStyle::Expr {
212 self.unmatched_angle_bracket_count = 0;
213 self.max_angle_bracket_count = 0;
216 // Generic arguments are found - `<`, `(`, `::<` or `::(`.
217 self.eat(&token::ModSep);
218 let lo = self.token.span;
219 let args = if self.eat_lt() {
221 let (args, constraints) =
222 self.parse_generic_args_with_leading_angle_bracket_recovery(style, lo)?;
224 let span = lo.to(self.prev_span);
225 AngleBracketedArgs { args, constraints, span }.into()
228 let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
229 let span = ident.span.to(self.prev_span);
230 let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No)?;
231 ParenthesizedArgs { inputs, output, span }.into()
234 PathSegment { ident, args, id: ast::DUMMY_NODE_ID }
236 // Generic arguments are not found.
237 PathSegment::from_ident(ident)
242 pub(super) fn parse_path_segment_ident(&mut self) -> PResult<'a, Ident> {
243 match self.normalized_token.kind {
244 token::Ident(name, _) if name.is_path_segment_keyword() => {
246 Ok(Ident::new(name, self.normalized_prev_token.span))
248 _ => self.parse_ident(),
252 /// Parses generic args (within a path segment) with recovery for extra leading angle brackets.
253 /// For the purposes of understanding the parsing logic of generic arguments, this function
254 /// can be thought of being the same as just calling `self.parse_generic_args()` if the source
255 /// had the correct amount of leading angle brackets.
257 /// ```ignore (diagnostics)
258 /// bar::<<<<T as Foo>::Output>();
259 /// ^^ help: remove extra angle brackets
261 fn parse_generic_args_with_leading_angle_bracket_recovery(
265 ) -> PResult<'a, (Vec<GenericArg>, Vec<AssocTyConstraint>)> {
266 // We need to detect whether there are extra leading left angle brackets and produce an
267 // appropriate error and suggestion. This cannot be implemented by looking ahead at
268 // upcoming tokens for a matching `>` character - if there are unmatched `<` tokens
269 // then there won't be matching `>` tokens to find.
271 // To explain how this detection works, consider the following example:
273 // ```ignore (diagnostics)
274 // bar::<<<<T as Foo>::Output>();
275 // ^^ help: remove extra angle brackets
278 // Parsing of the left angle brackets starts in this function. We start by parsing the
279 // `<` token (incrementing the counter of unmatched angle brackets on `Parser` via
282 // *Upcoming tokens:* `<<<<T as Foo>::Output>;`
283 // *Unmatched count:* 1
284 // *`parse_path_segment` calls deep:* 0
286 // This has the effect of recursing as this function is called if a `<` character
287 // is found within the expected generic arguments:
289 // *Upcoming tokens:* `<<<T as Foo>::Output>;`
290 // *Unmatched count:* 2
291 // *`parse_path_segment` calls deep:* 1
293 // Eventually we will have recursed until having consumed all of the `<` tokens and
294 // this will be reflected in the count:
296 // *Upcoming tokens:* `T as Foo>::Output>;`
297 // *Unmatched count:* 4
298 // `parse_path_segment` calls deep:* 3
300 // The parser will continue until reaching the first `>` - this will decrement the
301 // unmatched angle bracket count and return to the parent invocation of this function
302 // having succeeded in parsing:
304 // *Upcoming tokens:* `::Output>;`
305 // *Unmatched count:* 3
306 // *`parse_path_segment` calls deep:* 2
308 // This will continue until the next `>` character which will also return successfully
309 // to the parent invocation of this function and decrement the count:
311 // *Upcoming tokens:* `;`
312 // *Unmatched count:* 2
313 // *`parse_path_segment` calls deep:* 1
315 // At this point, this function will expect to find another matching `>` character but
316 // won't be able to and will return an error. This will continue all the way up the
317 // call stack until the first invocation:
319 // *Upcoming tokens:* `;`
320 // *Unmatched count:* 2
321 // *`parse_path_segment` calls deep:* 0
323 // In doing this, we have managed to work out how many unmatched leading left angle
324 // brackets there are, but we cannot recover as the unmatched angle brackets have
325 // already been consumed. To remedy this, we keep a snapshot of the parser state
326 // before we do the above. We can then inspect whether we ended up with a parsing error
327 // and unmatched left angle brackets and if so, restore the parser state before we
328 // consumed any `<` characters to emit an error and consume the erroneous tokens to
329 // recover by attempting to parse again.
331 // In practice, the recursion of this function is indirect and there will be other
332 // locations that consume some `<` characters - as long as we update the count when
333 // this happens, it isn't an issue.
335 let is_first_invocation = style == PathStyle::Expr;
336 // Take a snapshot before attempting to parse - we can restore this later.
337 let snapshot = if is_first_invocation { Some(self.clone()) } else { None };
339 debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)");
340 match self.parse_generic_args() {
341 Ok(value) => Ok(value),
342 Err(ref mut e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => {
343 // Cancel error from being unable to find `>`. We know the error
344 // must have been this due to a non-zero unmatched angle bracket
348 // Swap `self` with our backup of the parser state before attempting to parse
349 // generic arguments.
350 let snapshot = mem::replace(self, snapshot.unwrap());
353 "parse_generic_args_with_leading_angle_bracket_recovery: (snapshot failure) \
354 snapshot.count={:?}",
355 snapshot.unmatched_angle_bracket_count,
358 // Eat the unmatched angle brackets.
359 for _ in 0..snapshot.unmatched_angle_bracket_count {
363 // Make a span over ${unmatched angle bracket count} characters.
364 let span = lo.with_hi(lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count));
365 self.struct_span_err(
368 "unmatched angle bracket{}",
369 pluralize!(snapshot.unmatched_angle_bracket_count)
375 "remove extra angle bracket{}",
376 pluralize!(snapshot.unmatched_angle_bracket_count)
379 Applicability::MachineApplicable,
383 // Try again without unmatched angle bracket characters.
384 self.parse_generic_args()
390 /// Parses (possibly empty) list of lifetime and type arguments and associated type bindings,
391 /// possibly including trailing comma.
392 fn parse_generic_args(&mut self) -> PResult<'a, (Vec<GenericArg>, Vec<AssocTyConstraint>)> {
393 let mut args = Vec::new();
394 let mut constraints = Vec::new();
395 let mut misplaced_assoc_ty_constraints: Vec<Span> = Vec::new();
396 let mut assoc_ty_constraints: Vec<Span> = Vec::new();
398 let args_lo = self.token.span;
401 if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) {
402 // Parse lifetime argument.
403 args.push(GenericArg::Lifetime(self.expect_lifetime()));
404 misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints);
405 } else if self.check_ident()
406 && self.look_ahead(1, |t| t == &token::Eq || t == &token::Colon)
408 // Parse associated type constraint.
409 let lo = self.token.span;
410 let ident = self.parse_ident()?;
411 let kind = if self.eat(&token::Eq) {
412 AssocTyConstraintKind::Equality { ty: self.parse_ty()? }
413 } else if self.eat(&token::Colon) {
414 AssocTyConstraintKind::Bound {
415 bounds: self.parse_generic_bounds(Some(self.prev_span))?,
421 let span = lo.to(self.prev_span);
423 // Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
424 if let AssocTyConstraintKind::Bound { .. } = kind {
425 self.sess.gated_spans.gate(sym::associated_type_bounds, span);
428 constraints.push(AssocTyConstraint { id: ast::DUMMY_NODE_ID, ident, kind, span });
429 assoc_ty_constraints.push(span);
430 } else if self.check_const_arg() {
431 // Parse const argument.
432 let expr = if let token::OpenDelim(token::Brace) = self.token.kind {
433 self.parse_block_expr(
436 BlockCheckMode::Default,
439 } else if self.token.is_ident() {
440 // FIXME(const_generics): to distinguish between idents for types and consts,
441 // we should introduce a GenericArg::Ident in the AST and distinguish when
442 // lowering to the HIR. For now, idents for const args are not permitted.
443 if self.token.is_bool_lit() {
444 self.parse_literal_maybe_minus()?
446 let span = self.token.span;
447 let msg = "identifiers may currently not be used for const generics";
448 self.struct_span_err(span, msg).emit();
449 let block = self.mk_block_err(span);
450 self.mk_expr(span, ast::ExprKind::Block(block, None), ast::AttrVec::new())
453 self.parse_literal_maybe_minus()?
455 let value = AnonConst { id: ast::DUMMY_NODE_ID, value: expr };
456 args.push(GenericArg::Const(value));
457 misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints);
458 } else if self.check_type() {
459 // Parse type argument.
460 args.push(GenericArg::Type(self.parse_ty()?));
461 misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints);
466 if !self.eat(&token::Comma) {
471 // FIXME: we would like to report this in ast_validation instead, but we currently do not
472 // preserve ordering of generic parameters with respect to associated type binding, so we
473 // lose that information after parsing.
474 if !misplaced_assoc_ty_constraints.is_empty() {
475 let mut err = self.struct_span_err(
476 args_lo.to(self.prev_span),
477 "associated type bindings must be declared after generic parameters",
479 for span in misplaced_assoc_ty_constraints {
482 "this associated type binding should be moved after the generic parameters",
488 Ok((args, constraints))