1use rustc_ast::token::{self, IdentKind, MetaVarKind, Token, TokenKind};2use rustc_ast::util::case::Case;3use rustc_ast::{4 self as ast, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnPtrTy, FnRetTy,5 GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, Mutability, Path,6 Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty,7 TyKind, UnsafeBinderTy,8};9use rustc_errors::{Applicability, Diag, E0516, PResult};10use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};11use thin_vec::{ThinVec, thin_vec};1213use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};14use crate::diagnostics::{15 self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,16 FnPtrWithGenerics, FnPtrWithGenericsSugg, HelpUseLatestEdition, InvalidCVariadicType,17 InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, NestedCVariadicType,18 ReturnTypesUseThinArrow,19};20use crate::parser::{FnContext, FnParseMode, FrontMatterParsingMode};21use crate::{exp, maybe_recover_from_interpolated_ty_qpath};2223/// Signals whether parsing a type should allow `+`.24///25/// For example, let T be the type `impl Default + 'static`26/// With `AllowPlus::Yes`, T will be parsed successfully27/// With `AllowPlus::No`, parsing T will return a parse error28#[derive(Copy, Clone, PartialEq)]29pub(super) enum AllowPlus {30 Yes,31 No,32}3334#[derive(PartialEq)]35pub(super) enum RecoverQPath {36 Yes,37 No,38}3940pub(super) enum RecoverQuestionMark {41 Yes,42 No,43}4445/// Signals whether parsing a type should recover `->`.46///47/// More specifically, when parsing a function like:48/// ```compile_fail49/// fn foo() => u8 { 0 }50/// fn bar(): u8 { 0 }51/// ```52/// The compiler will try to recover interpreting `foo() => u8` as `foo() -> u8` when calling53/// `parse_ty` with anything except `RecoverReturnSign::No`, and it will try to recover `bar(): u8`54/// as `bar() -> u8` when passing `RecoverReturnSign::Yes` to `parse_ty`55#[derive(Copy, Clone, PartialEq)]56pub(super) enum RecoverReturnSign {57 Yes,58 OnlyFatArrow,59 No,60}6162impl RecoverReturnSign {63 /// [RecoverReturnSign::Yes] allows for recovering `fn foo() => u8` and `fn foo(): u8`,64 /// [RecoverReturnSign::OnlyFatArrow] allows for recovering only `fn foo() => u8` (recovering65 /// colons can cause problems when parsing where clauses), and66 /// [RecoverReturnSign::No] doesn't allow for any recovery of the return type arrow67 fn can_recover(self, token: &TokenKind) -> bool {68 match self {69 Self::Yes => matches!(token, token::FatArrow | token::Colon),70 Self::OnlyFatArrow => matches!(token, token::FatArrow),71 Self::No => false,72 }73 }74}7576// Is `...` (`CVarArgs`) legal at this level of type parsing?77#[derive(PartialEq)]78enum AllowCVariadic {79 Yes,80 No,81}8283/// Determine if the given token can begin a bound assuming it follows Rust 2015 identifier `dyn`.84///85/// In Rust 2015, `dyn` is a contextual keyword, not a full one.86fn can_begin_dyn_bound_in_rust_2015(t: Token) -> bool {87 // In `dyn::x`, `dyn<X>` and `dyn<<X>::Y>`, `dyn` should (continue to) denote a regular path88 // segment for backward compatibility. We make an exception for `dyn(X)` which used to be89 // interpreted as a path with parenthesized generic arguments which can be semantically90 // well-formed (consider: `use std::ops::Fn as dyn;`). Instead, we treat it as a trait91 // object type whose first bound is parenthesized.9293 // Contrary to `Parser::can_begin_bound`, `!`, `const`, `[` and `async` are deliberately not94 // part of this list to contain the number of potential regressions esp. in MBE code.95 // `const` and `[` would regress UI test `macro-dyn-const-2015.rs` and96 // `!` would regress `dyn!(...)` macro calls in Rust 2015 for example.9798 if t.is_path_start() {99 return t != token::PathSep && t != token::Lt && t != token::Shl;100 }101102 t == token::OpenParen || t == token::Question || t.is_lifetime() || t.is_keyword(kw::For)103}104105impl<'a> Parser<'a> {106 /// Parses a type.107 pub fn parse_ty(&mut self) -> PResult<'a, Box<Ty>> {108 if self.token == token::DotDotDot {109 // We special case this so that we don't talk about "nested C-variadics" in types.110 // We still pass in `AllowCVariadic::No` so that `parse_ty_common` can complain about111 // things like `Vec<...>`.112 let span = self.token.span;113 self.bump();114 let kind = TyKind::Err(self.dcx().emit_err(InvalidCVariadicType { span }));115 return Ok(self.mk_ty(span, kind));116 }117 self.parse_ty_common(118 AllowPlus::Yes,119 AllowCVariadic::No,120 RecoverQPath::Yes,121 RecoverReturnSign::Yes,122 None,123 RecoverQuestionMark::Yes,124 )125 }126127 pub(super) fn parse_ty_with_generics_recovery(128 &mut self,129 ty_params: &Generics,130 ) -> PResult<'a, Box<Ty>> {131 self.parse_ty_common(132 AllowPlus::Yes,133 AllowCVariadic::No,134 RecoverQPath::Yes,135 RecoverReturnSign::Yes,136 Some(ty_params),137 RecoverQuestionMark::Yes,138 )139 }140141 /// Parse a type suitable for a function or function pointer parameter.142 /// The difference from `parse_ty` is that this version allows `...`143 /// (`CVarArgs`) at the top level of the type.144 pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, Box<Ty>> {145 let ty = self.parse_ty_common(146 AllowPlus::Yes,147 AllowCVariadic::Yes,148 RecoverQPath::Yes,149 RecoverReturnSign::Yes,150 None,151 RecoverQuestionMark::Yes,152 )?;153154 // Recover a trailing `= EXPR` if present.155 if self.may_recover()156 && self.check_noexpect(&token::Eq)157 && self.look_ahead(1, |tok| tok.can_begin_expr())158 {159 let snapshot = self.create_snapshot_for_diagnostic();160 self.bump();161 let eq_span = self.prev_token.span;162 match self.parse_expr() {163 Ok(e) => {164 self.dcx()165 .struct_span_err(eq_span.to(e.span), "parameter defaults are not supported")166 .emit();167 }168 Err(diag) => {169 diag.cancel();170 self.restore_snapshot(snapshot);171 }172 }173 }174175 Ok(ty)176 }177178 /// Parses a type in restricted contexts where `+` is not permitted.179 ///180 /// Example 1: `&'a TYPE`181 /// `+` is prohibited to maintain operator priority (P(+) < P(&)).182 /// Example 2: `value1 as TYPE + value2`183 /// `+` is prohibited to avoid interactions with expression grammar.184 pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, Box<Ty>> {185 self.parse_ty_common(186 AllowPlus::No,187 AllowCVariadic::No,188 RecoverQPath::Yes,189 RecoverReturnSign::Yes,190 None,191 RecoverQuestionMark::Yes,192 )193 }194195 /// Parses a type following an `as` cast. Similar to `parse_ty_no_plus`, but signaling origin196 /// for better diagnostics involving `?`.197 pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, Box<Ty>> {198 self.parse_ty_common(199 AllowPlus::No,200 AllowCVariadic::No,201 RecoverQPath::Yes,202 RecoverReturnSign::Yes,203 None,204 RecoverQuestionMark::No,205 )206 }207208 pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, Box<Ty>> {209 self.parse_ty_common(210 AllowPlus::Yes,211 AllowCVariadic::No,212 RecoverQPath::Yes,213 RecoverReturnSign::Yes,214 None,215 RecoverQuestionMark::No,216 )217 }218219 /// Parse a type without recovering `:` as `->` to avoid breaking code such220 /// as `where fn() : for<'a>`.221 pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, Box<Ty>> {222 self.parse_ty_common(223 AllowPlus::Yes,224 AllowCVariadic::No,225 RecoverQPath::Yes,226 RecoverReturnSign::OnlyFatArrow,227 None,228 RecoverQuestionMark::Yes,229 )230 }231232 /// Parses an optional return type `[ -> TY ]` in a function declaration.233 pub(super) fn parse_ret_ty(234 &mut self,235 allow_plus: AllowPlus,236 recover_qpath: RecoverQPath,237 recover_return_sign: RecoverReturnSign,238 ) -> PResult<'a, FnRetTy> {239 let lo = self.prev_token.span;240 Ok(if self.eat(exp!(RArrow)) {241 // FIXME(Centril): Can we unconditionally `allow_plus`?242 let ty = self.parse_ty_common(243 allow_plus,244 AllowCVariadic::No,245 recover_qpath,246 recover_return_sign,247 None,248 RecoverQuestionMark::Yes,249 )?;250 FnRetTy::Ty(ty)251 } else if recover_return_sign.can_recover(&self.token.kind) {252 // Don't `eat` to prevent `=>` from being added as an expected token which isn't253 // actually expected and could only confuse users254 self.bump();255 self.dcx().emit_err(ReturnTypesUseThinArrow {256 span: self.prev_token.span,257 suggestion: lo.between(self.token.span),258 });259 let ty = self.parse_ty_common(260 allow_plus,261 AllowCVariadic::No,262 recover_qpath,263 recover_return_sign,264 None,265 RecoverQuestionMark::Yes,266 )?;267 FnRetTy::Ty(ty)268 } else {269 FnRetTy::Default(self.prev_token.span.shrink_to_hi())270 })271 }272273 fn parse_ty_common(274 &mut self,275 allow_plus: AllowPlus,276 allow_c_variadic: AllowCVariadic,277 recover_qpath: RecoverQPath,278 recover_return_sign: RecoverReturnSign,279 ty_generics: Option<&Generics>,280 recover_question_mark: RecoverQuestionMark,281 ) -> PResult<'a, Box<Ty>> {282 let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;283 maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);284285 if let Some(ty) = self.eat_metavar_seq_with_matcher(286 |mv_kind| matches!(mv_kind, MetaVarKind::Ty { .. }),287 |this| this.parse_ty_no_question_mark_recover(),288 ) {289 return Ok(ty);290 }291292 self.recover_from_outer_attributes("types")?;293294 let lo = self.token.span;295 let mut impl_dyn_multi = false;296 let kind = if self.check(exp!(OpenParen)) {297 self.parse_paren_start_ty(lo, allow_plus)?298 } else if self.eat(exp!(Bang)) {299 // Never type `!`300 TyKind::Never301 } else if self.eat(exp!(Star)) {302 self.parse_ty_ptr()?303 } else if self.eat(exp!(OpenBracket)) {304 self.parse_array_or_slice_ty()?305 } else if self.check(exp!(And)) || self.check(exp!(AndAnd)) {306 // Reference307 self.expect_and()?;308 self.parse_borrowed_pointee()?309 } else if self.eat_keyword_noexpect(kw::Typeof) {310 self.parse_typeof_ty(lo)?311 } else if self.is_builtin() {312 self.parse_builtin_ty()?313 } else if self.eat_keyword(exp!(Underscore)) {314 // A type to be inferred `_`315 TyKind::Infer316 } else if self.check_fn_front_matter(false, Case::Sensitive) {317 // Function pointer type318 self.parse_ty_fn_ptr(lo, ThinVec::new(), None, recover_return_sign)?319 } else if self.check_keyword(exp!(For)) {320 // Function pointer type or bound list (trait object type) starting with a poly-trait.321 // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`322 // `for<'lt> Trait1<'lt> + Trait2 + 'a`323 let (bound_vars, _) = self.parse_higher_ranked_binder()?;324 if self.check_fn_front_matter(false, Case::Sensitive) {325 self.parse_ty_fn_ptr(326 lo,327 bound_vars,328 Some(self.prev_token.span.shrink_to_lo()),329 recover_return_sign,330 )?331 } else {332 // Try to recover `for<'a> dyn Trait` or `for<'a> impl Trait`.333 if self.may_recover()334 && (self.token.is_keyword(kw::Impl) || self.can_begin_dyn_ty())335 {336 self.bump();337 let (kw, _) = self.prev_token.ident().unwrap();338 let removal_span = kw.span.with_hi(self.token.span.lo());339 let path = self.parse_path(PathStyle::Type)?;340 let mut bounds = thin_vec![GenericBound::Trait(PolyTraitRef::new(341 bound_vars,342 path,343 TraitBoundModifiers::NONE,344 lo.to(self.prev_token.span),345 ast::Parens::No,346 ))];347 if allow_plus == AllowPlus::Yes && self.check_plus() {348 self.eat_plus();349 bounds.append(&mut self.parse_generic_bounds()?);350 }351 self.dcx().emit_err(diagnostics::TransposeDynOrImpl {352 span: kw.span,353 kw: kw.name.as_str(),354 sugg: diagnostics::TransposeDynOrImplSugg {355 removal_span,356 insertion_span: lo.shrink_to_lo(),357 kw: kw.name.as_str(),358 },359 });360 match kw.name {361 kw::Dyn => TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn),362 kw::Impl => TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds),363 _ => unreachable!(),364 }365 } else {366 let path = self.parse_path(PathStyle::Type)?;367 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();368 self.finish_parsing_bare_trait_object_ty(369 bound_vars,370 path,371 lo,372 parse_plus,373 ast::Parens::No,374 )?375 }376 }377 } else if self.eat_keyword(exp!(Impl)) {378 self.parse_impl_ty(&mut impl_dyn_multi)?379 } else if self.can_begin_dyn_ty() {380 self.parse_dyn_ty(&mut impl_dyn_multi)?381 } else if self.eat_lt() {382 // Qualified path383 let (qself, path) = self.parse_qpath(PathStyle::Type)?;384 TyKind::Path(Some(qself), path)385 } else if (self.token.is_keyword(kw::Const) || self.token.is_keyword(kw::Mut))386 && self.look_ahead(1, |t| *t == token::Star)387 {388 self.parse_ty_c_style_pointer()?389 } else if self.check_path() {390 self.parse_path_start_ty(lo, allow_plus, ty_generics)?391 } else if self.can_begin_bound() {392 self.parse_bare_trait_object_ty(lo, allow_plus)?393 } else if self.eat(exp!(DotDotDot)) {394 match allow_c_variadic {395 AllowCVariadic::Yes => TyKind::CVarArgs,396 AllowCVariadic::No => {397 // FIXME(c_variadic): Should we just allow `...` syntactically398 // anywhere in a type and use semantic restrictions instead?399 // NOTE: This may regress certain MBE calls if done incorrectly.400 let guar = self.dcx().emit_err(NestedCVariadicType { span: lo });401 TyKind::Err(guar)402 }403 }404 } else if self.check_keyword(exp!(Unsafe))405 && self.look_ahead(1, |tok| tok.kind == token::Lt)406 {407 self.parse_unsafe_binder_ty()?408 } else {409 let msg = format!("expected type, found {}", super::token_descr(&self.token));410 let mut err = self.dcx().struct_span_err(lo, msg);411 err.span_label(lo, "expected type");412 if self.may_recover()413 && (self.eat_keyword_noexpect(kw::True) || self.eat_keyword_noexpect(kw::False))414 {415 err.span_suggestion(416 self.prev_token.span,417 "the type is called",418 "bool",419 Applicability::MachineApplicable,420 );421 err.emit();422 TyKind::Path(423 None,424 Path::from_ident(Ident { span: self.prev_token.span, name: sym::bool }),425 )426 } else {427 return Err(err);428 }429 };430431 let span = lo.to(self.prev_token.span);432 let mut ty = self.mk_ty(span, kind);433434 // Try to recover from use of `+` with incorrect priority.435 match allow_plus {436 AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?,437 AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty),438 }439 if let RecoverQuestionMark::Yes = recover_question_mark {440 ty = self.maybe_recover_from_question_mark(ty);441 }442 if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }443 }444445 fn parse_unsafe_binder_ty(&mut self) -> PResult<'a, TyKind> {446 let lo = self.token.span;447 assert!(self.eat_keyword(exp!(Unsafe)));448 self.expect_lt()?;449 let generic_params = self.parse_generic_params()?;450 self.expect_gt()?;451 let inner_ty = self.parse_ty()?;452 let span = lo.to(self.prev_token.span);453 self.psess.gated_spans.gate(sym::unsafe_binders, span);454455 Ok(TyKind::UnsafeBinder(Box::new(UnsafeBinderTy { generic_params, inner_ty })))456 }457458 /// Parse a type that begins with an opening parenthesis `(`.459 ///460 /// More specifically, it parses one of the following:461 ///462 /// 1. parenthesized type463 /// 2. tuple type464 /// 3. bare trait object type where the first trait bound is parenthesized465 fn parse_paren_start_ty(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {466 let mut inside_has_trailing_plus = false;467 let (ts, trailing_comma) = self.parse_paren_comma_seq(|p| {468 let ty = p.parse_ty()?;469 inside_has_trailing_plus = p.prev_token == TokenKind::Plus;470 Ok(ty)471 })?;472473 if ts.len() == 1 && matches!(trailing_comma, Trailing::No) {474 let ty = ts.into_iter().next().unwrap();475476 // Let's check if we actually have a bare trait object type where the first trait bound477 // is parenthesized. That's the case if the parentheses are followed by a `+` and if478 // what's contained between the parentheses resembles a *BareTraitBound*.479 //480 // For context, looking at bounds in general (see *Bound*), only trait bounds are481 // allowed to be wrapped in parentheses, not however outlives and use bounds.482 let outside_has_eligible_trailing_plus =483 allow_plus == AllowPlus::Yes && self.token.is_like_plus();484 match ty.kind {485 // `"(" TypePath ")" "+"`486 TyKind::Path(None, path) if outside_has_eligible_trailing_plus => self487 .finish_parsing_bare_trait_object_ty(488 ThinVec::new(),489 path,490 lo,491 true,492 ast::Parens::Yes,493 ),494 // `"(" BareTraitBound\TypePath ")" "+"`495 //496 // We actually accept outlives bounds here, too, purely to reduce diagnostic output497 // for ill-formed code like `('a)+`: We know for a fact that the `parse_ty` above498 // has already emitted an error for the inner `'a` as it's not followed by `+`.499 // This way we indirectly suppress unhelpful follow-up diagnostics like E0178500 // ("bad `+` in type") and E0224 ("no trait bound in trait object type").501 TyKind::TraitObject(mut bounds, TraitObjectSyntax::None)502 if outside_has_eligible_trailing_plus503 && !inside_has_trailing_plus504 && let [ast::GenericBound::Trait(_) | ast::GenericBound::Outlives(_)] =505 bounds.as_slice() =>506 {507 self.eat_plus();508 bounds.append(&mut self.parse_generic_bounds()?);509 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))510 }511 _ => Ok(TyKind::Paren(ty)),512 }513 } else {514 Ok(TyKind::Tup(ts))515 }516 }517518 fn parse_bare_trait_object_ty(519 &mut self,520 lo: Span,521 allow_plus: AllowPlus,522 ) -> PResult<'a, TyKind> {523 // A lifetime only begins a bare trait object type if it is followed by `+`!524 if self.token.is_lifetime() && !self.look_ahead(1, |t| t.is_like_plus()) {525 // In Rust 2021 and beyond, we assume that the user didn't intend to write a bare trait526 // object type with a leading lifetime bound since that seems very unlikely given the527 // fact that `dyn`-less trait objects are *semantically* invalid.528 if self.psess.edition.at_least_rust_2021() {529 let lt = self.expect_lifetime();530 let mut err = self.dcx().struct_span_err(lo, "expected type, found lifetime");531 err.span_label(lo, "expected type");532 return Ok(match self.maybe_recover_ref_ty_no_leading_ampersand(lt, lo, err) {533 Ok(ref_ty) => ref_ty,534 Err(err) => TyKind::Err(err.emit_err()),535 });536 }537538 self.dcx().emit_err(NeedPlusAfterTraitObjectLifetime {539 span: lo,540 suggestion: lo.shrink_to_hi(),541 });542 }543 Ok(TyKind::TraitObject(544 self.parse_generic_bounds_common(allow_plus)?,545 TraitObjectSyntax::None,546 ))547 }548549 pub(super) fn parse_ref_ty_no_leading_ampersand(&mut self) -> (Mutability, Option<Box<Ty>>) {550 let mutbl = self.parse_mutability();551 match self.parse_ty_no_plus() {552 Ok(ty) => (mutbl, Some(ty)),553 Err(err) => {554 err.cancel();555 (mutbl, None)556 }557 }558 }559560 fn maybe_recover_ref_ty_no_leading_ampersand<'cx>(561 &mut self,562 lt: Lifetime,563 lo: Span,564 mut err: Diag<'cx>,565 ) -> Result<TyKind, Diag<'cx>> {566 if !self.may_recover() {567 return Err(err);568 }569 let snapshot = self.create_snapshot_for_diagnostic();570 match self.parse_ref_ty_no_leading_ampersand() {571 (_, None) => {572 self.restore_snapshot(snapshot);573 Err(err)574 }575 (mutbl, Some(ty)) => {576 err.span_suggestion_verbose(577 lo.shrink_to_lo(),578 "you might have meant to write a reference type here",579 "&",580 Applicability::MaybeIncorrect,581 );582 err.emit();583 Ok(TyKind::Ref(Some(lt), ty, mutbl))584 }585 }586 }587588 fn finish_parsing_bare_trait_object_ty(589 &mut self,590 generic_params: ThinVec<GenericParam>,591 path: ast::Path,592 lo: Span,593 parse_plus: bool,594 parens: ast::Parens,595 ) -> PResult<'a, TyKind> {596 let mut bounds = thin_vec![GenericBound::Trait(PolyTraitRef::new(597 generic_params,598 path,599 TraitBoundModifiers::NONE,600 lo.to(self.prev_token.span),601 parens,602 ))];603 if parse_plus {604 self.eat_plus();605 bounds.append(&mut self.parse_generic_bounds()?);606 }607 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))608 }609610 /// Parses a raw pointer with a C-style typo611 fn parse_ty_c_style_pointer(&mut self) -> PResult<'a, TyKind> {612 let kw_span = self.token.span;613 let mutbl = self.parse_mut_or_const();614615 if let Some(mutbl) = mutbl616 && self.eat(exp!(Star))617 {618 let star_span = self.prev_token.span;619620 let mutability = match mutbl {621 Mutability::Not => "const",622 Mutability::Mut => "mut",623 };624625 let ty = self.parse_ty_no_question_mark_recover()?;626627 self.dcx()628 .struct_span_err(629 kw_span,630 format!("raw pointer types must be written as `*{mutability} T`"),631 )632 .with_multipart_suggestion(633 format!("put the `*` before `{mutability}`"),634 vec![(star_span, String::new()), (kw_span.shrink_to_lo(), "*".to_string())],635 Applicability::MachineApplicable,636 )637 .emit();638639 return Ok(TyKind::Ptr(ty, mutbl));640 }641 // This is unreachable because we always get into if above and return from it642 unreachable!("this could never happen")643 }644645 /// Parses a raw pointer type: `*[const | mut] $type`.646 fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {647 let mutbl = self.parse_mut_or_const().unwrap_or_else(|| {648 let span = self.prev_token.span;649 self.dcx().emit_err(ExpectedMutOrConstInRawPointerType {650 span,651 after_asterisk: span.shrink_to_hi(),652 });653 Mutability::Not654 });655 let ty = self.parse_ty_no_plus()?;656 Ok(TyKind::Ptr(ty, mutbl))657 }658659 /// Parses an array (`[TYPE; EXPR]`) or slice (`[TYPE]`) type.660 /// The opening `[` bracket is already eaten.661 fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {662 let elt_ty = self.parse_ty()?;663664 let ty = if self.eat(exp!(Semi)) {665 let mut length = self.parse_expr_anon_const()?;666667 if let Err(e) = self.expect(exp!(CloseBracket)) {668 // Try to recover from `X<Y, ...>` when `X::<Y, ...>` works669 self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;670 self.expect(exp!(CloseBracket))?;671 }672 TyKind::Array(elt_ty, length)673 } else if self.eat(exp!(CloseBracket)) {674 TyKind::Slice(elt_ty)675 } else {676 self.maybe_recover_array_ty_without_semi(elt_ty)?677 };678679 Ok(ty)680 }681682 /// Recover from malformed array type syntax.683 ///684 /// This method attempts to recover from cases like:685 /// - `[u8, 5]` → suggests using `;`, return a Array type686 /// - `[u8 5]` → suggests using `;`, return a Array type687 /// Consider to add more cases in the future.688 fn maybe_recover_array_ty_without_semi(&mut self, elt_ty: Box<Ty>) -> PResult<'a, TyKind> {689 let span = self.token.span;690 let token_descr = super::token_descr(&self.token);691 let mut err =692 self.dcx().struct_span_err(span, format!("expected `;` or `]`, found {}", token_descr));693 err.span_label(span, "expected `;` or `]`");694695 // If we cannot recover, return the error immediately.696 if !self.may_recover() {697 return Err(err);698 }699700 let snapshot = self.create_snapshot_for_diagnostic();701702 // Consume common erroneous separators.703 let hi = self.prev_token.span.hi();704 _ = self.eat(exp!(Comma)) || self.eat(exp!(Colon)) || self.eat(exp!(Star));705 let suggestion_span = self.prev_token.span.with_lo(hi);706707 // FIXME(mgca): recovery is broken for `const {` args708 // we first try to parse pattern like `[u8 5]`709 let length = match self.parse_expr_anon_const() {710 Ok(length) => length,711 Err(e) => {712 e.cancel();713 self.restore_snapshot(snapshot);714 return Err(err);715 }716 };717718 if let Err(e) = self.expect(exp!(CloseBracket)) {719 e.cancel();720 self.restore_snapshot(snapshot);721 return Err(err);722 }723724 err.span_suggestion_verbose(725 suggestion_span,726 "you might have meant to use `;` as the separator",727 ";",728 Applicability::MaybeIncorrect,729 );730 err.emit();731 Ok(TyKind::Array(elt_ty, length))732 }733734 fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {735 let and_span = self.prev_token.span;736 let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());737 let (pinned, mut mutbl) = self.parse_pin_and_mut();738 if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {739 // A lifetime is invalid here: it would be part of a bare trait bound, which requires740 // it to be followed by a plus, but we disallow plus in the pointee type.741 // So we can handle this case as an error here, and suggest `'a mut`.742 // If there *is* a plus next though, handling the error later provides better suggestions743 // (like adding parentheses)744 if !self.look_ahead(1, |t| t.is_like_plus()) {745 let lifetime_span = self.token.span;746 let span = and_span.to(lifetime_span);747748 let (suggest_lifetime, snippet) =749 if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {750 (Some(span), lifetime_src)751 } else {752 (None, String::new())753 };754 self.dcx().emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });755756 opt_lifetime = Some(self.expect_lifetime());757 }758 } else if self.token.is_keyword(kw::Dyn)759 && mutbl == Mutability::Not760 && self.look_ahead(1, |t| t.is_keyword(kw::Mut))761 {762 // We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.763 let span = and_span.to(self.look_ahead(1, |t| t.span));764 self.dcx().emit_err(DynAfterMut { span });765766 // Recovery767 mutbl = Mutability::Mut;768 let (dyn_tok, dyn_tok_sp) = (self.token, self.token_spacing);769 self.bump();770 self.bump_with((dyn_tok, dyn_tok_sp));771 }772 let ty = self.parse_ty_no_plus()?;773 Ok(match pinned {774 Pinnedness::Not => TyKind::Ref(opt_lifetime, ty, mutbl),775 Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, ty, mutbl),776 })777 }778779 /// Parse nothing, mutability or `pin` followed by "explicit" mutability.780 ///781 /// ```ebnf782 /// PinAndMut = "pin" MutOrConst | "mut"783 /// ```784 pub(crate) fn parse_pin_and_mut(&mut self) -> (Pinnedness, Mutability) {785 if self.token.is_keyword(kw::Pin) && self.look_ahead(1, Token::is_mutability) {786 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);787 assert!(self.eat_keyword(exp!(Pin)));788 let mutbl = self.parse_mut_or_const().unwrap();789 (Pinnedness::Pinned, mutbl)790 } else {791 (Pinnedness::Not, self.parse_mutability())792 }793 }794795 /// Parses the `typeof(EXPR)` for better diagnostics before returning796 /// an error type.797 fn parse_typeof_ty(&mut self, lo: Span) -> PResult<'a, TyKind> {798 self.expect(exp!(OpenParen))?;799 let _expr = self.parse_expr_anon_const()?;800 self.expect(exp!(CloseParen))?;801 let span = lo.to(self.prev_token.span);802 let guar = self803 .dcx()804 .struct_span_err(span, "`typeof` is a reserved keyword but unimplemented")805 .with_note("consider replacing `typeof(...)` with an actual type")806 .with_code(E0516)807 .emit_err();808 Ok(TyKind::Err(guar))809 }810811 fn parse_builtin_ty(&mut self) -> PResult<'a, TyKind> {812 self.parse_builtin(|this, lo, ident| {813 Ok(match ident.name {814 sym::field_of => Some(this.parse_ty_field_of(lo)?),815 _ => None,816 })817 })818 }819820 pub(crate) fn parse_ty_field_of(&mut self, _lo: Span) -> PResult<'a, TyKind> {821 let container = self.parse_ty()?;822 self.expect(exp!(Comma))?;823824 let fields = self.parse_floating_field_access()?;825 let trailing_comma = self.eat_noexpect(&TokenKind::Comma);826827 if let Err(mut e) = self.expect_one_of(&[], &[exp!(CloseParen)]) {828 if trailing_comma {829 e.note("unexpected third argument to field_of");830 } else {831 e.note("field_of expects dot-separated field and variant names");832 }833 e.emit();834 }835836 // Eat tokens until the macro call ends.837 if self.may_recover() {838 while !self.token.kind.is_close_delim_or_eof() {839 self.bump();840 }841 }842843 match *fields {844 [] => Err(self.dcx().struct_span_err(845 self.token.span,846 "`field_of!` expects dot-separated field and variant names",847 )),848 [field] => Ok(TyKind::FieldOf(container, None, field)),849 [variant, field] => Ok(TyKind::FieldOf(container, Some(variant), field)),850 _ => Err(self.dcx().struct_span_err(851 fields.iter().map(|f| f.span).collect::<Vec<_>>(),852 "`field_of!` only supports a single field or a variant with a field",853 )),854 }855 }856857 /// Parses a function pointer type (`TyKind::FnPtr`).858 /// ```ignore (illustrative)859 /// [unsafe] [extern "ABI"] fn (S) -> T860 /// // ^~~~~^ ^~~~^ ^~^ ^861 /// // | | | |862 /// // | | | Return type863 /// // Function Style ABI Parameter types864 /// ```865 /// We actually parse `FnHeader FnDecl`, but we error on `const` and `async` qualifiers.866 fn parse_ty_fn_ptr(867 &mut self,868 lo: Span,869 mut params: ThinVec<GenericParam>,870 param_insertion_point: Option<Span>,871 recover_return_sign: RecoverReturnSign,872 ) -> PResult<'a, TyKind> {873 let inherited_vis = rustc_ast::Visibility {874 span: rustc_span::DUMMY_SP,875 kind: rustc_ast::VisibilityKind::Inherited,876 };877 let span_start = self.token.span;878 let ast::FnHeader { ext, safety, .. } = self.parse_fn_front_matter(879 &inherited_vis,880 Case::Sensitive,881 FrontMatterParsingMode::FunctionPtrType,882 )?;883 if self.may_recover() && self.token == TokenKind::Lt {884 self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;885 }886 let mode = crate::parser::FnParseMode {887 req_name: |_, _| false,888 context: FnContext::FunctionPtrType,889 req_body: false,890 allow_const_params: false,891 };892 let decl = self.parse_fn_decl(&mode, AllowPlus::No, recover_return_sign)?;893 let decl = Box::new(decl);894895 let decl_span = span_start.to(self.prev_token.span);896 Ok(TyKind::FnPtr(Box::new(FnPtrTy {897 ext,898 safety,899 generic_params: params,900 decl,901 decl_span,902 })))903 }904905 /// Recover from function pointer types with a generic parameter list (e.g. `fn<'a>(&'a str)`).906 fn recover_fn_ptr_with_generics(907 &mut self,908 lo: Span,909 params: &mut ThinVec<GenericParam>,910 param_insertion_point: Option<Span>,911 ) -> PResult<'a, ()> {912 let generics = self.parse_generics()?;913 let arity = generics.params.len();914915 let mut lifetimes: ThinVec<_> = generics916 .params917 .into_iter()918 .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime))919 .collect();920921 let sugg = if !lifetimes.is_empty() {922 let snippet =923 lifetimes.iter().map(|param| param.ident.as_str()).intersperse(", ").collect();924925 let (left, snippet) = if let Some(span) = param_insertion_point {926 (span, if params.is_empty() { snippet } else { format!(", {snippet}") })927 } else {928 (lo.shrink_to_lo(), format!("for<{snippet}> "))929 };930931 Some(FnPtrWithGenericsSugg {932 left,933 snippet,934 right: generics.span,935 arity,936 for_param_list_exists: param_insertion_point.is_some(),937 })938 } else {939 None940 };941942 self.dcx().emit_err(FnPtrWithGenerics { span: generics.span, sugg });943 params.append(&mut lifetimes);944 Ok(())945 }946947 /// Parses an `impl B0 + ... + Bn` type.948 fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {949 // If we encounter a type like `impl 'a Sized`, suggest `impl 'a + Sized`.950 if self.token.is_lifetime()951 && let Some(ident) = self.look_ahead(1, |t| t.non_reserved_ident())952 {953 self.dcx().emit_err(diagnostics::MissingPlusBounds {954 span: self.token.span,955 hi: self.token.span.shrink_to_hi(),956 sym: ident.name,957 });958 }959960 // Always parse bounds greedily for better error recovery.961 let bounds = self.parse_generic_bounds()?;962963 *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;964965 Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))966 }967968 /// Parse a use-bound aka precise capturing list.969 ///970 /// ```ebnf971 /// UseBound = "use" "<" (PreciseCapture ("," PreciseCapture)* ","?)? ">"972 /// PreciseCapture = "Self" | Ident | Lifetime973 /// ```974 fn parse_use_bound(&mut self, lo: Span, parens: ast::Parens) -> PResult<'a, GenericBound> {975 self.expect_lt()?;976 let (args, _, _) = self.parse_seq_to_before_tokens(977 &[exp!(Gt)],978 &[&TokenKind::Ge, &TokenKind::Shr, &TokenKind::Shr],979 SeqSep::trailing_allowed(exp!(Comma)),980 |self_| {981 if self_.check_keyword(exp!(SelfUpper)) {982 self_.bump();983 Ok(PreciseCapturingArg::Arg(984 ast::Path::from_ident(self_.prev_token.ident().unwrap().0),985 DUMMY_NODE_ID,986 ))987 } else if self_.check_ident() {988 Ok(PreciseCapturingArg::Arg(989 ast::Path::from_ident(self_.parse_ident()?),990 DUMMY_NODE_ID,991 ))992 } else if self_.check_lifetime() {993 Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))994 } else {995 self_.unexpected_any()996 }997 },998 )?;999 self.expect_gt()?;10001001 if let ast::Parens::Yes = parens {1002 self.expect(exp!(CloseParen))?;1003 self.report_parenthesized_bound(lo, self.prev_token.span, "precise capturing lists");1004 }10051006 Ok(GenericBound::Use(args, lo.to(self.prev_token.span)))1007 }10081009 /// Can the current token begin a `dyn`-prefixed trait object type?1010 fn can_begin_dyn_ty(&mut self) -> bool {1011 self.token.is_keyword(kw::Dyn)1012 && (self.token_uninterpolated_span().at_least_rust_2018()1013 || self.look_ahead(1, |&t| can_begin_dyn_bound_in_rust_2015(t)))1014 }10151016 /// Parse a `dyn`-prefixed trait object type.1017 fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {1018 self.bump(); // `dyn`10191020 // Always parse bounds greedily for better error recovery.1021 let bounds = self.parse_generic_bounds()?;1022 *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;10231024 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn))1025 }10261027 /// Parse a type that begins with a path.1028 ///1029 /// This can be:1030 /// 1. a type macro, `mac!(...)`,1031 /// 2. a bare trait object type, `B0 + ... + Bn`,1032 /// 3. or a path, `path::to::MyType`.1033 fn parse_path_start_ty(1034 &mut self,1035 lo: Span,1036 allow_plus: AllowPlus,1037 ty_generics: Option<&Generics>,1038 ) -> PResult<'a, TyKind> {1039 // Simple path1040 let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;1041 if self.eat(exp!(Bang)) {1042 // Macro invocation in type position1043 Ok(TyKind::MacCall(Box::new(MacCall { path, args: self.parse_delim_args()? })))1044 } else if allow_plus == AllowPlus::Yes && self.check_plus() {1045 // `Trait1 + Trait2 + 'a`1046 self.finish_parsing_bare_trait_object_ty(1047 ThinVec::new(),1048 path,1049 lo,1050 true,1051 ast::Parens::No,1052 )1053 } else {1054 // Just a type path.1055 Ok(TyKind::Path(None, path))1056 }1057 }10581059 pub(super) fn parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds> {1060 self.parse_generic_bounds_common(AllowPlus::Yes)1061 }10621063 /// Parse generic bounds.1064 ///1065 /// Only if `allow_plus` this parses a `+`-separated list of bounds (trailing `+` is admitted).1066 /// Otherwise, this only parses a single bound or none.1067 fn parse_generic_bounds_common(&mut self, allow_plus: AllowPlus) -> PResult<'a, GenericBounds> {1068 let mut bounds = ThinVec::new();10691070 // In addition to looping while we find generic bounds:1071 // We continue even if we find a keyword. This is necessary for error recovery on,1072 // for example, `impl fn()`. The only keyword that can go after generic bounds is1073 // `where`, so stop if it's it.1074 // We also continue if we find types (not traits), again for error recovery.1075 while self.can_begin_bound()1076 || (self.may_recover()1077 && (self.token.can_begin_type()1078 || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))))1079 {1080 // Account for `&dyn Trait + dyn Other`.1081 if self.can_begin_dyn_ty() {1082 self.bump();1083 self.dcx().emit_err(InvalidDynKeyword {1084 span: self.prev_token.span,1085 suggestion: self.prev_token.span.until(self.token.span),1086 });1087 }1088 bounds.push(self.parse_generic_bound()?);1089 if allow_plus == AllowPlus::No || !self.eat_plus() {1090 break;1091 }1092 }10931094 Ok(bounds)1095 }10961097 /// Can the current token begin a bound?1098 fn can_begin_bound(&mut self) -> bool {1099 // NOTE: Tokens `!`, `~`, `const` & `async` which represent the start of currently unstable1100 // trait bound modifiers are intentionally not included in `Token::can_begin_type` to1101 // avoid affecting stable macro matching behavior.11021103 self.check_path()1104 || self.check_lifetime()1105 || self.check(exp!(Bang))1106 || self.check(exp!(Question))1107 || self.check(exp!(Tilde))1108 || self.check_keyword(exp!(For))1109 || self.check(exp!(OpenParen))1110 || self.can_begin_maybe_const_bound()1111 || self.check_keyword(exp!(Const))1112 || self.check_keyword(exp!(Async))1113 || self.check_keyword(exp!(Use))1114 }11151116 fn can_begin_maybe_const_bound(&mut self) -> bool {1117 self.check(exp!(OpenBracket))1118 && self.look_ahead(1, |t| t.is_keyword(kw::Const))1119 && self.look_ahead(2, |t| *t == token::CloseBracket)1120 }11211122 /// Parse a bound.1123 ///1124 /// ```ebnf1125 /// Bound = LifetimeBound | UseBound | TraitBound1126 /// ```1127 fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {1128 let leading_token = self.prev_token;1129 let lo = self.token.span;11301131 // We only admit parenthesized *trait* bounds. However, we want to gracefully recover from1132 // other kinds of parenthesized bounds, so parse the opening parenthesis *here*.1133 //1134 // In the future we might want to lift this syntactic restriction and1135 // introduce "`GenericBound::Paren(Box<GenericBound>)`".1136 let parens = if self.eat(exp!(OpenParen)) { ast::Parens::Yes } else { ast::Parens::No };11371138 if self.token.is_lifetime() {1139 self.parse_lifetime_bound(lo, parens)1140 } else if self.eat_keyword(exp!(Use)) {1141 self.parse_use_bound(lo, parens)1142 } else {1143 self.parse_trait_bound(lo, parens, &leading_token)1144 }1145 }11461147 /// Parse a lifetime-bound aka outlives-bound.1148 ///1149 /// ```ebnf1150 /// LifetimeBound = Lifetime1151 /// ```1152 fn parse_lifetime_bound(&mut self, lo: Span, parens: ast::Parens) -> PResult<'a, GenericBound> {1153 let lt = self.expect_lifetime();11541155 if let ast::Parens::Yes = parens {1156 self.expect(exp!(CloseParen))?;1157 self.report_parenthesized_bound(lo, self.prev_token.span, "lifetime bounds");1158 }11591160 Ok(GenericBound::Outlives(lt))1161 }11621163 fn report_parenthesized_bound(&self, lo: Span, hi: Span, kind: &str) -> ErrorGuaranteed {1164 let mut diag =1165 self.dcx().struct_span_err(lo.to(hi), format!("{kind} may not be parenthesized"));1166 diag.multipart_suggestion(1167 "remove the parentheses",1168 vec![(lo, String::new()), (hi, String::new())],1169 Applicability::MachineApplicable,1170 );1171 diag.emit_err()1172 }11731174 /// Emits an error if any trait bound modifiers were present.1175 fn error_lt_bound_with_modifiers(1176 &self,1177 modifiers: TraitBoundModifiers,1178 binder_span: Option<Span>,1179 ) -> ErrorGuaranteed {1180 let TraitBoundModifiers { constness, asyncness, polarity } = modifiers;11811182 match constness {1183 BoundConstness::Never => {}1184 BoundConstness::Always(span) | BoundConstness::Maybe(span) => {1185 return self.dcx().emit_err(diagnostics::ModifierLifetime {1186 span,1187 modifier: constness.as_str(),1188 });1189 }1190 }11911192 match polarity {1193 BoundPolarity::Positive => {}1194 BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => {1195 return self1196 .dcx()1197 .emit_err(diagnostics::ModifierLifetime { span, modifier: polarity.as_str() });1198 }1199 }12001201 match asyncness {1202 BoundAsyncness::Normal => {}1203 BoundAsyncness::Async(span) => {1204 return self.dcx().emit_err(diagnostics::ModifierLifetime {1205 span,1206 modifier: asyncness.as_str(),1207 });1208 }1209 }12101211 if let Some(span) = binder_span {1212 return self1213 .dcx()1214 .emit_err(diagnostics::ModifierLifetime { span, modifier: "for<...>" });1215 }12161217 unreachable!("lifetime bound intercepted in `parse_generic_ty_bound` but no modifiers?")1218 }12191220 /// Parses the modifiers that may precede a trait in a bound, e.g. `?Trait` or `[const] Trait`.1221 ///1222 /// If no modifiers are present, this does not consume any tokens.1223 ///1224 /// ```ebnf1225 /// Constness = ("const" | "[" "const" "]")?1226 /// Asyncness = "async"?1227 /// Polarity = ("?" | "!")?1228 /// ```1229 ///1230 /// See `parse_trait_bound` for more context.1231 fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {1232 let modifier_lo = self.token.span;1233 let constness = self.parse_bound_constness()?;12341235 let asyncness = if self.token_uninterpolated_span().at_least_rust_2018()1236 && self.eat_keyword(exp!(Async))1237 {1238 self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);1239 BoundAsyncness::Async(self.prev_token.span)1240 } else if self.may_recover()1241 && self.token_uninterpolated_span().is_rust_2015()1242 && self.is_kw_followed_by_ident(kw::Async)1243 {1244 self.bump(); // eat `async`1245 self.dcx().emit_err(diagnostics::AsyncBoundModifierIn2015 {1246 span: self.prev_token.span,1247 help: HelpUseLatestEdition::new(),1248 });1249 self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);1250 BoundAsyncness::Async(self.prev_token.span)1251 } else {1252 BoundAsyncness::Normal1253 };1254 let modifier_hi = self.prev_token.span;12551256 let polarity = if self.eat(exp!(Question)) {1257 BoundPolarity::Maybe(self.prev_token.span)1258 } else if self.eat(exp!(Bang)) {1259 self.psess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);1260 BoundPolarity::Negative(self.prev_token.span)1261 } else {1262 BoundPolarity::Positive1263 };12641265 // Enforce the mutual-exclusivity of `const`/`async` and `?`/`!`.1266 match polarity {1267 BoundPolarity::Positive => {1268 // All trait bound modifiers allowed to combine with positive polarity1269 }1270 BoundPolarity::Maybe(polarity_span) | BoundPolarity::Negative(polarity_span) => {1271 match (asyncness, constness) {1272 (BoundAsyncness::Normal, BoundConstness::Never) => {1273 // Ok, no modifiers.1274 }1275 (_, _) => {1276 let constness = constness.as_str();1277 let asyncness = asyncness.as_str();1278 let glue =1279 if !constness.is_empty() && !asyncness.is_empty() { " " } else { "" };1280 let modifiers_concatenated = format!("{constness}{glue}{asyncness}");1281 self.dcx().emit_err(diagnostics::PolarityAndModifiers {1282 polarity_span,1283 polarity: polarity.as_str(),1284 modifiers_span: modifier_lo.to(modifier_hi),1285 modifiers_concatenated,1286 });1287 }1288 }1289 }1290 }12911292 Ok(TraitBoundModifiers { constness, asyncness, polarity })1293 }12941295 pub fn parse_bound_constness(&mut self) -> PResult<'a, BoundConstness> {1296 // FIXME(const_trait_impl): remove `~const` parser support once bootstrap has the new syntax1297 // in rustfmt1298 Ok(if self.eat(exp!(Tilde)) {1299 let tilde = self.prev_token.span;1300 self.expect_keyword(exp!(Const))?;1301 let span = tilde.to(self.prev_token.span);1302 self.psess.gated_spans.gate(sym::const_trait_impl, span);1303 BoundConstness::Maybe(span)1304 } else if self.can_begin_maybe_const_bound() {1305 let start = self.token.span;1306 self.bump();1307 self.expect_keyword(exp!(Const)).unwrap();1308 self.bump();1309 let span = start.to(self.prev_token.span);1310 self.psess.gated_spans.gate(sym::const_trait_impl, span);1311 BoundConstness::Maybe(span)1312 } else if self.eat_keyword(exp!(Const)) {1313 self.psess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span);1314 BoundConstness::Always(self.prev_token.span)1315 } else {1316 BoundConstness::Never1317 })1318 }13191320 /// Parse a trait bound.1321 ///1322 /// ```ebnf1323 /// TraitBound = BareTraitBound | "(" BareTraitBound ")"1324 /// BareTraitBound =1325 /// (HigherRankedBinder Constness Asyncness | Polarity)1326 /// TypePath1327 /// ```1328 fn parse_trait_bound(1329 &mut self,1330 lo: Span,1331 parens: ast::Parens,1332 leading_token: &Token,1333 ) -> PResult<'a, GenericBound> {1334 let (mut bound_vars, binder_span) = self.parse_higher_ranked_binder()?;13351336 let modifiers_lo = self.token.span;1337 let modifiers = self.parse_trait_bound_modifiers()?;1338 let modifiers_span = modifiers_lo.to(self.prev_token.span);13391340 if let Some(binder_span) = binder_span {1341 match modifiers.polarity {1342 BoundPolarity::Negative(polarity_span) | BoundPolarity::Maybe(polarity_span) => {1343 self.dcx().emit_err(diagnostics::BinderAndPolarity {1344 binder_span,1345 polarity_span,1346 polarity: modifiers.polarity.as_str(),1347 });1348 }1349 BoundPolarity::Positive => {}1350 }1351 }13521353 // Recover erroneous lifetime bound with modifiers or binder.1354 // e.g. `T: for<'a> 'a` or `T: [const] 'a`.1355 if self.token.is_lifetime() {1356 let _: ErrorGuaranteed = self.error_lt_bound_with_modifiers(modifiers, binder_span);1357 return self.parse_lifetime_bound(lo, parens);1358 }13591360 if let (more_bound_vars, Some(binder_span)) = self.parse_higher_ranked_binder()? {1361 bound_vars.extend(more_bound_vars);1362 self.dcx().emit_err(diagnostics::BinderBeforeModifiers { binder_span, modifiers_span });1363 }13641365 let mut path = if self.token.is_keyword(kw::Fn)1366 && self.look_ahead(1, |t| *t == TokenKind::OpenParen)1367 && let Some(path) = self.recover_path_from_fn()1368 {1369 path1370 } else if !self.token.is_path_start() && self.token.can_begin_type() {1371 let ty = self.parse_ty_no_plus()?;1372 // Instead of finding a path (a trait), we found a type.1373 let mut err = self.dcx().struct_span_err(ty.span, "expected a trait, found type");13741375 // If we can recover, try to extract a path from the type. Note1376 // that we do not use the try operator when parsing the type because1377 // if it fails then we get a parser error which we don't want (we're trying1378 // to recover from errors, not make more).1379 let path = if self.may_recover() {1380 let (span, message, sugg, path, applicability) = match &ty.kind {1381 TyKind::Ptr(..) | TyKind::Ref(..)1382 if let TyKind::Path(_, path) = &ty.peel_refs().kind =>1383 {1384 (1385 ty.span.until(path.span),1386 "consider removing the indirection",1387 "",1388 path,1389 Applicability::MaybeIncorrect,1390 )1391 }1392 TyKind::ImplTrait(_, bounds)1393 if let [GenericBound::Trait(tr, ..), ..] = bounds.as_slice() =>1394 {1395 (1396 ty.span.until(tr.span),1397 "use the trait bounds directly",1398 "",1399 &tr.trait_ref.path,1400 Applicability::MachineApplicable,1401 )1402 }1403 _ => return Err(err),1404 };14051406 err.span_suggestion_verbose(span, message, sugg, applicability);14071408 path.clone()1409 } else {1410 return Err(err);1411 };14121413 err.emit();14141415 path1416 } else {1417 self.parse_path(PathStyle::Type)?1418 };14191420 if self.may_recover() && self.token == TokenKind::OpenParen {1421 self.recover_fn_trait_with_lifetime_params(&mut path, &mut bound_vars)?;1422 }14231424 if let ast::Parens::Yes = parens {1425 // Someone has written something like `&dyn (Trait + Other)`. The correct code1426 // would be `&(dyn Trait + Other)`1427 if self.token.is_like_plus() && leading_token.is_keyword(kw::Dyn) {1428 self.eat_plus();1429 self.parse_generic_bounds()?;1430 self.expect(exp!(CloseParen))?;14311432 self.dcx().emit_err(diagnostics::IncorrectParensTraitBounds {1433 span: vec![lo, self.prev_token.span],1434 sugg: diagnostics::IncorrectParensTraitBoundsSugg {1435 wrong_span: leading_token.span.shrink_to_hi().to(lo),1436 new_span: leading_token.span.shrink_to_lo(),1437 },1438 });1439 } else {1440 self.expect(exp!(CloseParen))?;1441 }1442 }14431444 let poly_trait =1445 PolyTraitRef::new(bound_vars, path, modifiers, lo.to(self.prev_token.span), parens);1446 Ok(GenericBound::Trait(poly_trait))1447 }14481449 // recovers a `Fn(..)` parenthesized-style path from `fn(..)`1450 fn recover_path_from_fn(&mut self) -> Option<ast::Path> {1451 let fn_token_span = self.token.span;1452 self.bump();1453 let args_lo = self.token.span;1454 let snapshot = self.create_snapshot_for_diagnostic();1455 let mode = FnParseMode {1456 req_name: |_, _| false,1457 context: FnContext::Free,1458 req_body: false,1459 allow_const_params: false,1460 };1461 match self.parse_fn_decl(&mode, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {1462 Ok(decl) => {1463 self.dcx().emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });1464 Some(ast::Path {1465 span: fn_token_span.to(self.prev_token.span),1466 segments: thin_vec![ast::PathSegment {1467 ident: Ident::new(sym::Fn, fn_token_span),1468 id: DUMMY_NODE_ID,1469 args: Some(Box::new(ast::GenericArgs::Parenthesized(1470 ast::ParenthesizedArgs {1471 span: args_lo.to(self.prev_token.span),1472 inputs: decl.inputs.iter().map(|a| a.clone()).collect(),1473 inputs_span: args_lo.until(decl.output.span()),1474 output: decl.output.clone(),1475 }1476 ))),1477 }],1478 })1479 }1480 Err(diag) => {1481 diag.cancel();1482 self.restore_snapshot(snapshot);1483 None1484 }1485 }1486 }14871488 /// Parse an optional higher-ranked binder.1489 ///1490 /// ```ebnf1491 /// HigherRankedBinder = ("for" "<" GenericParams ">")?1492 /// ```1493 pub(super) fn parse_higher_ranked_binder(1494 &mut self,1495 ) -> PResult<'a, (ThinVec<GenericParam>, Option<Span>)> {1496 if self.eat_keyword(exp!(For)) {1497 let lo = self.token.span;1498 self.expect_lt()?;1499 let params = self.parse_generic_params()?;1500 self.expect_gt()?;1501 // We rely on AST validation to rule out invalid cases: There must not be1502 // type or const parameters, and parameters must not have bounds.1503 Ok((params, Some(lo.to(self.prev_token.span))))1504 } else {1505 Ok((ThinVec::new(), None))1506 }1507 }15081509 /// Recover from `Fn`-family traits (Fn, FnMut, FnOnce) with lifetime arguments1510 /// (e.g. `FnOnce<'a>(&'a str) -> bool`). Up to generic arguments have already1511 /// been eaten.1512 fn recover_fn_trait_with_lifetime_params(1513 &mut self,1514 fn_path: &mut ast::Path,1515 lifetime_defs: &mut ThinVec<GenericParam>,1516 ) -> PResult<'a, ()> {1517 let fn_path_segment = fn_path.segments.last_mut().unwrap();1518 let generic_args = if let Some(p_args) = &fn_path_segment.args {1519 *p_args.clone()1520 } else {1521 // Normally it wouldn't come here because the upstream should have parsed1522 // generic parameters (otherwise it's impossible to call this function).1523 return Ok(());1524 };1525 let lifetimes =1526 if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) =1527 &generic_args1528 {1529 args.into_iter()1530 .filter_map(|arg| {1531 if let ast::AngleBracketedArg::Arg(generic_arg) = arg1532 && let ast::GenericArg::Lifetime(lifetime) = generic_arg1533 {1534 Some(lifetime)1535 } else {1536 None1537 }1538 })1539 .collect()1540 } else {1541 Vec::new()1542 };1543 // Only try to recover if the trait has lifetime params.1544 if lifetimes.is_empty() {1545 return Ok(());1546 }15471548 let snapshot = if self.parsing_generics {1549 // The snapshot is only relevant if we're parsing the generics of an `fn` to avoid1550 // incorrect recovery.1551 Some(self.create_snapshot_for_diagnostic())1552 } else {1553 None1554 };1555 // Parse `(T, U) -> R`.1556 let inputs_lo = self.token.span;1557 let mode = FnParseMode {1558 req_name: |_, _| false,1559 context: FnContext::Free,1560 req_body: false,1561 allow_const_params: false,1562 };1563 let inputs = match self.parse_fn_params(&mode) {1564 Ok(params) => params,1565 Err(err) => {1566 if let Some(snapshot) = snapshot {1567 self.restore_snapshot(snapshot);1568 err.cancel();1569 return Ok(());1570 } else {1571 return Err(err);1572 }1573 }1574 };1575 let inputs_span = inputs_lo.to(self.prev_token.span);1576 let output = match self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)1577 {1578 Ok(output) => output,1579 Err(err) => {1580 if let Some(snapshot) = snapshot {1581 self.restore_snapshot(snapshot);1582 err.cancel();1583 return Ok(());1584 } else {1585 return Err(err);1586 }1587 }1588 };1589 let args = ast::ParenthesizedArgs {1590 span: fn_path_segment.span().to(self.prev_token.span),1591 inputs,1592 inputs_span,1593 output,1594 }1595 .into();15961597 if let Some(snapshot) = snapshot1598 && ![token::Comma, token::Gt, token::Plus].contains(&self.token.kind)1599 {1600 // We would expect another bound or the end of type params by now. Most likely we've1601 // encountered a `(` *not* representing `Trait()`, but rather the start of the `fn`'s1602 // argument list where the generic param list wasn't properly closed.1603 self.restore_snapshot(snapshot);1604 return Ok(());1605 }16061607 *fn_path_segment = ast::PathSegment {1608 ident: fn_path_segment.ident,1609 args: Some(args),1610 id: ast::DUMMY_NODE_ID,1611 };16121613 // Convert parsed `<'a>` in `Fn<'a>` into `for<'a>`.1614 let mut generic_params = lifetimes1615 .iter()1616 .map(|lt| GenericParam {1617 id: lt.id,1618 ident: lt.ident,1619 attrs: ast::AttrVec::new(),1620 bounds: ThinVec::new(),1621 is_placeholder: false,1622 kind: ast::GenericParamKind::Lifetime,1623 colon_span: None,1624 })1625 .collect::<ThinVec<GenericParam>>();1626 lifetime_defs.append(&mut generic_params);16271628 let generic_args_span = generic_args.span();1629 let snippet = format!(1630 "for<{}> ",1631 lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),1632 );1633 let before_fn_path = fn_path.span.shrink_to_lo();1634 self.dcx()1635 .struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters")1636 .with_multipart_suggestion(1637 "consider using a higher-ranked trait bound instead",1638 vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],1639 Applicability::MaybeIncorrect,1640 )1641 .emit();1642 Ok(())1643 }16441645 pub(super) fn check_lifetime(&mut self) -> bool {1646 self.expected_token_types.insert(TokenType::Lifetime);1647 self.token.is_lifetime()1648 }16491650 /// Parses a single lifetime `'a` or panics.1651 pub(super) fn expect_lifetime(&mut self) -> Lifetime {1652 if let Some((ident, kind)) = self.token.lifetime() {1653 if kind == IdentKind::Normal && ident.without_first_quote().is_reserved_lifetime() {1654 self.dcx().emit_err(diagnostics::KeywordLifetime { span: ident.span });1655 }16561657 self.bump();1658 Lifetime { ident, id: ast::DUMMY_NODE_ID }1659 } else {1660 self.dcx().span_bug(self.token.span, "not a lifetime")1661 }1662 }16631664 pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> Box<Ty> {1665 Box::new(Ty { kind, span, id: ast::DUMMY_NODE_ID })1666 }1667}