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