1use rustc_ast::token::{self, IdentIsRaw, 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, MutTy, Mutability,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, AttributeOnEmptyType, AttributeOnType, DynAfterMut, ExpectedFnPathFoundFnKeyword,16 ExpectedMutOrConstInRawPointerType, FnPtrWithGenerics, FnPtrWithGenericsSugg,17 HelpUseLatestEdition, InvalidCVariadicType, InvalidDynKeyword, LifetimeAfterMut,18 NeedPlusAfterTraitObjectLifetime, NestedCVariadicType, 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_edition_2015(t: Token) -> bool {87 if t.is_path_start() {88 // In `dyn::x`, `dyn<X>` and `dyn<<X>::Y>`, `dyn` should (continue to) denote a regular path89 // segment for backward compatibility. We make an exception for `dyn(X)` which used to be90 // interpreted as a path with parenthesized generic arguments which can be semantically91 // well-formed (consider: `use std::ops::Fn as dyn;`). Instead, we treat it as a trait92 // object type whose first bound is parenthesized.93 return t != token::PathSep && t != token::Lt && t != token::Shl;94 }9596 // Contrary to `Parser::can_begin_bound`, `!`, `const`, `[` and `async` are deliberately not97 // part of this list to contain the number of potential regressions esp. in MBE code.98 // `const` and `[` would regress UI test `macro-dyn-const-2015.rs` and99 // `!` would regress `dyn!(...)` macro calls in Rust 2015 for example.100 t == token::OpenParen || t == token::Question || t.is_lifetime() || t.is_keyword(kw::For)101}102103impl<'a> Parser<'a> {104 /// Parses a type.105 pub fn parse_ty(&mut self) -> PResult<'a, Box<Ty>> {106 if self.token == token::DotDotDot {107 // We special case this so that we don't talk about "nested C-variadics" in types.108 // We still pass in `AllowCVariadic::No` so that `parse_ty_common` can complain about109 // things like `Vec<...>`.110 let span = self.token.span;111 self.bump();112 let kind = TyKind::Err(self.dcx().emit_err(InvalidCVariadicType { span }));113 return Ok(self.mk_ty(span, kind));114 }115 self.parse_ty_common(116 AllowPlus::Yes,117 AllowCVariadic::No,118 RecoverQPath::Yes,119 RecoverReturnSign::Yes,120 None,121 RecoverQuestionMark::Yes,122 )123 }124125 pub(super) fn parse_ty_with_generics_recovery(126 &mut self,127 ty_params: &Generics,128 ) -> PResult<'a, Box<Ty>> {129 self.parse_ty_common(130 AllowPlus::Yes,131 AllowCVariadic::No,132 RecoverQPath::Yes,133 RecoverReturnSign::Yes,134 Some(ty_params),135 RecoverQuestionMark::Yes,136 )137 }138139 /// Parse a type suitable for a function or function pointer parameter.140 /// The difference from `parse_ty` is that this version allows `...`141 /// (`CVarArgs`) at the top level of the type.142 pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, Box<Ty>> {143 let ty = self.parse_ty_common(144 AllowPlus::Yes,145 AllowCVariadic::Yes,146 RecoverQPath::Yes,147 RecoverReturnSign::Yes,148 None,149 RecoverQuestionMark::Yes,150 )?;151152 // Recover a trailing `= EXPR` if present.153 if self.may_recover()154 && self.check_noexpect(&token::Eq)155 && self.look_ahead(1, |tok| tok.can_begin_expr())156 {157 let snapshot = self.create_snapshot_for_diagnostic();158 self.bump();159 let eq_span = self.prev_token.span;160 match self.parse_expr() {161 Ok(e) => {162 self.dcx()163 .struct_span_err(eq_span.to(e.span), "parameter defaults are not supported")164 .emit();165 }166 Err(diag) => {167 diag.cancel();168 self.restore_snapshot(snapshot);169 }170 }171 }172173 Ok(ty)174 }175176 /// Parses a type in restricted contexts where `+` is not permitted.177 ///178 /// Example 1: `&'a TYPE`179 /// `+` is prohibited to maintain operator priority (P(+) < P(&)).180 /// Example 2: `value1 as TYPE + value2`181 /// `+` is prohibited to avoid interactions with expression grammar.182 pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, Box<Ty>> {183 self.parse_ty_common(184 AllowPlus::No,185 AllowCVariadic::No,186 RecoverQPath::Yes,187 RecoverReturnSign::Yes,188 None,189 RecoverQuestionMark::Yes,190 )191 }192193 /// Parses a type following an `as` cast. Similar to `parse_ty_no_plus`, but signaling origin194 /// for better diagnostics involving `?`.195 pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, Box<Ty>> {196 self.parse_ty_common(197 AllowPlus::No,198 AllowCVariadic::No,199 RecoverQPath::Yes,200 RecoverReturnSign::Yes,201 None,202 RecoverQuestionMark::No,203 )204 }205206 pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, Box<Ty>> {207 self.parse_ty_common(208 AllowPlus::Yes,209 AllowCVariadic::No,210 RecoverQPath::Yes,211 RecoverReturnSign::Yes,212 None,213 RecoverQuestionMark::No,214 )215 }216217 /// Parse a type without recovering `:` as `->` to avoid breaking code such218 /// as `where fn() : for<'a>`.219 pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, Box<Ty>> {220 self.parse_ty_common(221 AllowPlus::Yes,222 AllowCVariadic::No,223 RecoverQPath::Yes,224 RecoverReturnSign::OnlyFatArrow,225 None,226 RecoverQuestionMark::Yes,227 )228 }229230 /// Parses an optional return type `[ -> TY ]` in a function declaration.231 pub(super) fn parse_ret_ty(232 &mut self,233 allow_plus: AllowPlus,234 recover_qpath: RecoverQPath,235 recover_return_sign: RecoverReturnSign,236 ) -> PResult<'a, FnRetTy> {237 let lo = self.prev_token.span;238 Ok(if self.eat(exp!(RArrow)) {239 // FIXME(Centril): Can we unconditionally `allow_plus`?240 let ty = self.parse_ty_common(241 allow_plus,242 AllowCVariadic::No,243 recover_qpath,244 recover_return_sign,245 None,246 RecoverQuestionMark::Yes,247 )?;248 FnRetTy::Ty(ty)249 } else if recover_return_sign.can_recover(&self.token.kind) {250 // Don't `eat` to prevent `=>` from being added as an expected token which isn't251 // actually expected and could only confuse users252 self.bump();253 self.dcx().emit_err(ReturnTypesUseThinArrow {254 span: self.prev_token.span,255 suggestion: lo.between(self.token.span),256 });257 let ty = self.parse_ty_common(258 allow_plus,259 AllowCVariadic::No,260 recover_qpath,261 recover_return_sign,262 None,263 RecoverQuestionMark::Yes,264 )?;265 FnRetTy::Ty(ty)266 } else {267 FnRetTy::Default(self.prev_token.span.shrink_to_hi())268 })269 }270271 fn parse_ty_common(272 &mut self,273 allow_plus: AllowPlus,274 allow_c_variadic: AllowCVariadic,275 recover_qpath: RecoverQPath,276 recover_return_sign: RecoverReturnSign,277 ty_generics: Option<&Generics>,278 recover_question_mark: RecoverQuestionMark,279 ) -> PResult<'a, Box<Ty>> {280 let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;281 maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);282 if self.token == token::Pound && self.look_ahead(1, |t| *t == token::OpenBracket) {283 let attrs_wrapper = self.parse_outer_attributes()?;284 let raw_attrs = attrs_wrapper.take_for_recovery(self.psess);285 let attr_span = raw_attrs[0].span.to(raw_attrs.last().unwrap().span);286 let (full_span, guar) = match self.parse_ty() {287 Ok(ty) => {288 let full_span = attr_span.until(ty.span);289 let guar = self290 .dcx()291 .emit_err(AttributeOnType { span: attr_span, fix_span: full_span });292 (attr_span, guar)293 }294 Err(err) => {295 err.cancel();296 let guar = self.dcx().emit_err(AttributeOnEmptyType { span: attr_span });297 (attr_span, guar)298 }299 };300301 return Ok(self.mk_ty(full_span, TyKind::Err(guar)));302 }303 if let Some(ty) = self.eat_metavar_seq_with_matcher(304 |mv_kind| matches!(mv_kind, MetaVarKind::Ty { .. }),305 |this| this.parse_ty_no_question_mark_recover(),306 ) {307 return Ok(ty);308 }309310 let lo = self.token.span;311 let mut impl_dyn_multi = false;312 let kind = if self.check(exp!(OpenParen)) {313 self.parse_ty_tuple_or_parens(lo, allow_plus)?314 } else if self.eat(exp!(Bang)) {315 // Never type `!`316 TyKind::Never317 } else if self.eat(exp!(Star)) {318 self.parse_ty_ptr()?319 } else if self.eat(exp!(OpenBracket)) {320 self.parse_array_or_slice_ty()?321 } else if self.check(exp!(And)) || self.check(exp!(AndAnd)) {322 // Reference323 self.expect_and()?;324 self.parse_borrowed_pointee()?325 } else if self.eat_keyword_noexpect(kw::Typeof) {326 self.parse_typeof_ty(lo)?327 } else if self.is_builtin() {328 self.parse_builtin_ty()?329 } else if self.eat_keyword(exp!(Underscore)) {330 // A type to be inferred `_`331 TyKind::Infer332 } else if self.check_fn_front_matter(false, Case::Sensitive) {333 // Function pointer type334 self.parse_ty_fn_ptr(lo, ThinVec::new(), None, recover_return_sign)?335 } else if self.check_keyword(exp!(For)) {336 // Function pointer type or bound list (trait object type) starting with a poly-trait.337 // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`338 // `for<'lt> Trait1<'lt> + Trait2 + 'a`339 let (bound_vars, _) = self.parse_higher_ranked_binder()?;340 if self.check_fn_front_matter(false, Case::Sensitive) {341 self.parse_ty_fn_ptr(342 lo,343 bound_vars,344 Some(self.prev_token.span.shrink_to_lo()),345 recover_return_sign,346 )?347 } else {348 // Try to recover `for<'a> dyn Trait` or `for<'a> impl Trait`.349 if self.may_recover()350 && (self.eat_keyword_noexpect(kw::Impl) || self.eat_keyword_noexpect(kw::Dyn))351 {352 let kw = self.prev_token.ident().unwrap().0;353 let removal_span = kw.span.with_hi(self.token.span.lo());354 let path = self.parse_path(PathStyle::Type)?;355 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();356 let kind = self.parse_remaining_bounds_path(357 bound_vars,358 path,359 lo,360 parse_plus,361 ast::Parens::No,362 )?;363 let err = self.dcx().create_err(diagnostics::TransposeDynOrImpl {364 span: kw.span,365 kw: kw.name.as_str(),366 sugg: diagnostics::TransposeDynOrImplSugg {367 removal_span,368 insertion_span: lo.shrink_to_lo(),369 kw: kw.name.as_str(),370 },371 });372373 // Take the parsed bare trait object and turn it either374 // into a `dyn` object or an `impl Trait`.375 let kind = match (kind, kw.name) {376 (TyKind::TraitObject(bounds, _), kw::Dyn) => {377 TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)378 }379 (TyKind::TraitObject(bounds, _), kw::Impl) => {380 TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)381 }382 _ => return Err(err),383 };384 err.emit();385 kind386 } else {387 let path = self.parse_path(PathStyle::Type)?;388 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();389 self.parse_remaining_bounds_path(390 bound_vars,391 path,392 lo,393 parse_plus,394 ast::Parens::No,395 )?396 }397 }398 } else if self.eat_keyword(exp!(Impl)) {399 self.parse_impl_ty(&mut impl_dyn_multi)?400 } else if self.is_explicit_dyn_type() {401 self.parse_dyn_ty(&mut impl_dyn_multi)?402 } else if self.eat_lt() {403 // Qualified path404 let (qself, path) = self.parse_qpath(PathStyle::Type)?;405 TyKind::Path(Some(qself), path)406 } else if (self.token.is_keyword(kw::Const) || self.token.is_keyword(kw::Mut))407 && self.look_ahead(1, |t| *t == token::Star)408 {409 self.parse_ty_c_style_pointer()?410 } else if self.check_path() {411 self.parse_path_start_ty(lo, allow_plus, ty_generics)?412 } else if self.can_begin_bound() {413 self.parse_bare_trait_object(lo, allow_plus)?414 } else if self.eat(exp!(DotDotDot)) {415 match allow_c_variadic {416 AllowCVariadic::Yes => TyKind::CVarArgs,417 AllowCVariadic::No => {418 // FIXME(c_variadic): Should we just allow `...` syntactically419 // anywhere in a type and use semantic restrictions instead?420 // NOTE: This may regress certain MBE calls if done incorrectly.421 let guar = self.dcx().emit_err(NestedCVariadicType { span: lo });422 TyKind::Err(guar)423 }424 }425 } else if self.check_keyword(exp!(Unsafe))426 && self.look_ahead(1, |tok| tok.kind == token::Lt)427 {428 self.parse_unsafe_binder_ty()?429 } else {430 let msg = format!("expected type, found {}", super::token_descr(&self.token));431 let mut err = self.dcx().struct_span_err(lo, msg);432 err.span_label(lo, "expected type");433 return Err(err);434 };435436 let span = lo.to(self.prev_token.span);437 let mut ty = self.mk_ty(span, kind);438439 // Try to recover from use of `+` with incorrect priority.440 match allow_plus {441 AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?,442 AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty),443 }444 if let RecoverQuestionMark::Yes = recover_question_mark {445 ty = self.maybe_recover_from_question_mark(ty);446 }447 if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }448 }449450 fn parse_unsafe_binder_ty(&mut self) -> PResult<'a, TyKind> {451 let lo = self.token.span;452 assert!(self.eat_keyword(exp!(Unsafe)));453 self.expect_lt()?;454 let generic_params = self.parse_generic_params()?;455 self.expect_gt()?;456 let inner_ty = self.parse_ty()?;457 let span = lo.to(self.prev_token.span);458 self.psess.gated_spans.gate(sym::unsafe_binders, span);459460 Ok(TyKind::UnsafeBinder(Box::new(UnsafeBinderTy { generic_params, inner_ty })))461 }462463 /// Parses either:464 /// - `(TYPE)`, a parenthesized type.465 /// - `(TYPE,)`, a tuple with a single field of type TYPE.466 fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {467 let mut trailing_plus = false;468 let (ts, trailing) = self.parse_paren_comma_seq(|p| {469 let ty = p.parse_ty()?;470 trailing_plus = p.prev_token == TokenKind::Plus;471 Ok(ty)472 })?;473474 if ts.len() == 1 && matches!(trailing, Trailing::No) {475 let ty = ts.into_iter().next().unwrap();476 let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus();477 match ty.kind {478 // `"(" BareTraitBound ")" "+" Bound "+" ...`.479 TyKind::Path(None, path) if maybe_bounds => self.parse_remaining_bounds_path(480 ThinVec::new(),481 path,482 lo,483 true,484 ast::Parens::Yes,485 ),486 // For `('a) + …`, we know that `'a` in type position already lead to an error being487 // emitted. To reduce output, let's indirectly suppress E0178 (bad `+` in type) and488 // other irrelevant consequential errors.489 TyKind::TraitObject(bounds, TraitObjectSyntax::None)490 if maybe_bounds && bounds.len() == 1 && !trailing_plus =>491 {492 self.parse_remaining_bounds(bounds, true)493 }494 // `(TYPE)`495 _ => Ok(TyKind::Paren(ty)),496 }497 } else {498 Ok(TyKind::Tup(ts))499 }500 }501502 fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {503 // A lifetime only begins a bare trait object type if it is followed by `+`!504 if self.token.is_lifetime() && !self.look_ahead(1, |t| t.is_like_plus()) {505 // In Rust 2021 and beyond, we assume that the user didn't intend to write a bare trait506 // object type with a leading lifetime bound since that seems very unlikely given the507 // fact that `dyn`-less trait objects are *semantically* invalid.508 if self.psess.edition.at_least_rust_2021() {509 let lt = self.expect_lifetime();510 let mut err = self.dcx().struct_span_err(lo, "expected type, found lifetime");511 err.span_label(lo, "expected type");512 return Ok(match self.maybe_recover_ref_ty_no_leading_ampersand(lt, lo, err) {513 Ok(ref_ty) => ref_ty,514 Err(err) => TyKind::Err(err.emit()),515 });516 }517518 self.dcx().emit_err(NeedPlusAfterTraitObjectLifetime {519 span: lo,520 suggestion: lo.shrink_to_hi(),521 });522 }523 Ok(TyKind::TraitObject(524 self.parse_generic_bounds_common(allow_plus)?,525 TraitObjectSyntax::None,526 ))527 }528529 fn maybe_recover_ref_ty_no_leading_ampersand<'cx>(530 &mut self,531 lt: Lifetime,532 lo: Span,533 mut err: Diag<'cx>,534 ) -> Result<TyKind, Diag<'cx>> {535 if !self.may_recover() {536 return Err(err);537 }538 let snapshot = self.create_snapshot_for_diagnostic();539 let mutbl = self.parse_mutability();540 match self.parse_ty_no_plus() {541 Ok(ty) => {542 err.span_suggestion_verbose(543 lo.shrink_to_lo(),544 "you might have meant to write a reference type here",545 "&",546 Applicability::MaybeIncorrect,547 );548 err.emit();549 Ok(TyKind::Ref(Some(lt), MutTy { ty, mutbl }))550 }551 Err(diag) => {552 diag.cancel();553 self.restore_snapshot(snapshot);554 Err(err)555 }556 }557 }558559 fn parse_remaining_bounds_path(560 &mut self,561 generic_params: ThinVec<GenericParam>,562 path: ast::Path,563 lo: Span,564 parse_plus: bool,565 parens: ast::Parens,566 ) -> PResult<'a, TyKind> {567 let poly_trait_ref = PolyTraitRef::new(568 generic_params,569 path,570 TraitBoundModifiers::NONE,571 lo.to(self.prev_token.span),572 parens,573 );574 let bounds = thin_vec![GenericBound::Trait(poly_trait_ref)];575 self.parse_remaining_bounds(bounds, parse_plus)576 }577578 /// Parse the remainder of a bare trait object type given an already parsed list.579 fn parse_remaining_bounds(580 &mut self,581 mut bounds: GenericBounds,582 plus: bool,583 ) -> PResult<'a, TyKind> {584 if plus {585 self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded586 bounds.append(&mut self.parse_generic_bounds()?);587 }588 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))589 }590591 /// Parses a raw pointer with a C-style typo592 fn parse_ty_c_style_pointer(&mut self) -> PResult<'a, TyKind> {593 let kw_span = self.token.span;594 let mutbl = self.parse_mut_or_const();595596 if let Some(mutbl) = mutbl597 && self.eat(exp!(Star))598 {599 let star_span = self.prev_token.span;600601 let mutability = match mutbl {602 Mutability::Not => "const",603 Mutability::Mut => "mut",604 };605606 let ty = self.parse_ty_no_question_mark_recover()?;607608 self.dcx()609 .struct_span_err(610 kw_span,611 format!("raw pointer types must be written as `*{mutability} T`"),612 )613 .with_multipart_suggestion(614 format!("put the `*` before `{mutability}`"),615 vec![(star_span, String::new()), (kw_span.shrink_to_lo(), "*".to_string())],616 Applicability::MachineApplicable,617 )618 .emit();619620 return Ok(TyKind::Ptr(MutTy { ty, mutbl }));621 }622 // This is unreachable because we always get into if above and return from it623 unreachable!("this could never happen")624 }625626 /// Parses a raw pointer type: `*[const | mut] $type`.627 fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {628 let mutbl = self.parse_mut_or_const().unwrap_or_else(|| {629 let span = self.prev_token.span;630 self.dcx().emit_err(ExpectedMutOrConstInRawPointerType {631 span,632 after_asterisk: span.shrink_to_hi(),633 });634 Mutability::Not635 });636 let ty = self.parse_ty_no_plus()?;637 Ok(TyKind::Ptr(MutTy { ty, mutbl }))638 }639640 /// Parses an array (`[TYPE; EXPR]`) or slice (`[TYPE]`) type.641 /// The opening `[` bracket is already eaten.642 fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {643 let elt_ty = match self.parse_ty() {644 Ok(ty) => ty,645 Err(err)646 if self.look_ahead(1, |t| *t == token::CloseBracket)647 | self.look_ahead(1, |t| *t == token::Semi) =>648 {649 // Recover from `[LIT; EXPR]` and `[LIT]`650 self.bump();651 let guar = err.emit();652 self.mk_ty(self.prev_token.span, TyKind::Err(guar))653 }654 Err(err) => return Err(err),655 };656657 let ty = if self.eat(exp!(Semi)) {658 let mut length = self.parse_expr_anon_const()?;659660 if let Err(e) = self.expect(exp!(CloseBracket)) {661 // Try to recover from `X<Y, ...>` when `X::<Y, ...>` works662 self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;663 self.expect(exp!(CloseBracket))?;664 }665 TyKind::Array(elt_ty, length)666 } else if self.eat(exp!(CloseBracket)) {667 TyKind::Slice(elt_ty)668 } else {669 self.maybe_recover_array_ty_without_semi(elt_ty)?670 };671672 Ok(ty)673 }674675 /// Recover from malformed array type syntax.676 ///677 /// This method attempts to recover from cases like:678 /// - `[u8, 5]` → suggests using `;`, return a Array type679 /// - `[u8 5]` → suggests using `;`, return a Array type680 /// Consider to add more cases in the future.681 fn maybe_recover_array_ty_without_semi(&mut self, elt_ty: Box<Ty>) -> PResult<'a, TyKind> {682 let span = self.token.span;683 let token_descr = super::token_descr(&self.token);684 let mut err =685 self.dcx().struct_span_err(span, format!("expected `;` or `]`, found {}", token_descr));686 err.span_label(span, "expected `;` or `]`");687688 // If we cannot recover, return the error immediately.689 if !self.may_recover() {690 return Err(err);691 }692693 let snapshot = self.create_snapshot_for_diagnostic();694695 // Consume common erroneous separators.696 let hi = self.prev_token.span.hi();697 _ = self.eat(exp!(Comma)) || self.eat(exp!(Colon)) || self.eat(exp!(Star));698 let suggestion_span = self.prev_token.span.with_lo(hi);699700 // FIXME(mgca): recovery is broken for `const {` args701 // we first try to parse pattern like `[u8 5]`702 let length = match self.parse_expr_anon_const() {703 Ok(length) => length,704 Err(e) => {705 e.cancel();706 self.restore_snapshot(snapshot);707 return Err(err);708 }709 };710711 if let Err(e) = self.expect(exp!(CloseBracket)) {712 e.cancel();713 self.restore_snapshot(snapshot);714 return Err(err);715 }716717 err.span_suggestion_verbose(718 suggestion_span,719 "you might have meant to use `;` as the separator",720 ";",721 Applicability::MaybeIncorrect,722 );723 err.emit();724 Ok(TyKind::Array(elt_ty, length))725 }726727 fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {728 let and_span = self.prev_token.span;729 let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());730 let (pinned, mut mutbl) = self.parse_pin_and_mut();731 if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {732 // A lifetime is invalid here: it would be part of a bare trait bound, which requires733 // it to be followed by a plus, but we disallow plus in the pointee type.734 // So we can handle this case as an error here, and suggest `'a mut`.735 // If there *is* a plus next though, handling the error later provides better suggestions736 // (like adding parentheses)737 if !self.look_ahead(1, |t| t.is_like_plus()) {738 let lifetime_span = self.token.span;739 let span = and_span.to(lifetime_span);740741 let (suggest_lifetime, snippet) =742 if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {743 (Some(span), lifetime_src)744 } else {745 (None, String::new())746 };747 self.dcx().emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });748749 opt_lifetime = Some(self.expect_lifetime());750 }751 } else if self.token.is_keyword(kw::Dyn)752 && mutbl == Mutability::Not753 && self.look_ahead(1, |t| t.is_keyword(kw::Mut))754 {755 // We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.756 let span = and_span.to(self.look_ahead(1, |t| t.span));757 self.dcx().emit_err(DynAfterMut { span });758759 // Recovery760 mutbl = Mutability::Mut;761 let (dyn_tok, dyn_tok_sp) = (self.token, self.token_spacing);762 self.bump();763 self.bump_with((dyn_tok, dyn_tok_sp));764 }765 let ty = self.parse_ty_no_plus()?;766 Ok(match pinned {767 Pinnedness::Not => TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }),768 Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl }),769 })770 }771772 /// Parse nothing, mutability or `pin` followed by "explicit" mutability.773 ///774 /// ```ebnf775 /// PinAndMut = "pin" MutOrConst | "mut"776 /// ```777 pub(crate) fn parse_pin_and_mut(&mut self) -> (Pinnedness, Mutability) {778 if self.token.is_ident_named(sym::pin) && self.look_ahead(1, Token::is_mutability) {779 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);780 assert!(self.eat_keyword(exp!(Pin)));781 let mutbl = self.parse_mut_or_const().unwrap();782 (Pinnedness::Pinned, mutbl)783 } else {784 (Pinnedness::Not, self.parse_mutability())785 }786 }787788 /// Parses the `typeof(EXPR)` for better diagnostics before returning789 /// an error type.790 fn parse_typeof_ty(&mut self, lo: Span) -> PResult<'a, TyKind> {791 self.expect(exp!(OpenParen))?;792 let _expr = self.parse_expr_anon_const()?;793 self.expect(exp!(CloseParen))?;794 let span = lo.to(self.prev_token.span);795 let guar = self796 .dcx()797 .struct_span_err(span, "`typeof` is a reserved keyword but unimplemented")798 .with_note("consider replacing `typeof(...)` with an actual type")799 .with_code(E0516)800 .emit();801 Ok(TyKind::Err(guar))802 }803804 fn parse_builtin_ty(&mut self) -> PResult<'a, TyKind> {805 self.parse_builtin(|this, lo, ident| {806 Ok(match ident.name {807 sym::field_of => Some(this.parse_ty_field_of(lo)?),808 _ => None,809 })810 })811 }812813 pub(crate) fn parse_ty_field_of(&mut self, _lo: Span) -> PResult<'a, TyKind> {814 let container = self.parse_ty()?;815 self.expect(exp!(Comma))?;816817 let fields = self.parse_floating_field_access()?;818 let trailing_comma = self.eat_noexpect(&TokenKind::Comma);819820 if let Err(mut e) = self.expect_one_of(&[], &[exp!(CloseParen)]) {821 if trailing_comma {822 e.note("unexpected third argument to field_of");823 } else {824 e.note("field_of expects dot-separated field and variant names");825 }826 e.emit();827 }828829 // Eat tokens until the macro call ends.830 if self.may_recover() {831 while !self.token.kind.is_close_delim_or_eof() {832 self.bump();833 }834 }835836 match *fields {837 [] => Err(self.dcx().struct_span_err(838 self.token.span,839 "`field_of!` expects dot-separated field and variant names",840 )),841 [field] => Ok(TyKind::FieldOf(container, None, field)),842 [variant, field] => Ok(TyKind::FieldOf(container, Some(variant), field)),843 _ => Err(self.dcx().struct_span_err(844 fields.iter().map(|f| f.span).collect::<Vec<_>>(),845 "`field_of!` only supports a single field or a variant with a field",846 )),847 }848 }849850 /// Parses a function pointer type (`TyKind::FnPtr`).851 /// ```ignore (illustrative)852 /// [unsafe] [extern "ABI"] fn (S) -> T853 /// // ^~~~~^ ^~~~^ ^~^ ^854 /// // | | | |855 /// // | | | Return type856 /// // Function Style ABI Parameter types857 /// ```858 /// We actually parse `FnHeader FnDecl`, but we error on `const` and `async` qualifiers.859 fn parse_ty_fn_ptr(860 &mut self,861 lo: Span,862 mut params: ThinVec<GenericParam>,863 param_insertion_point: Option<Span>,864 recover_return_sign: RecoverReturnSign,865 ) -> PResult<'a, TyKind> {866 let inherited_vis = rustc_ast::Visibility {867 span: rustc_span::DUMMY_SP,868 kind: rustc_ast::VisibilityKind::Inherited,869 };870 let span_start = self.token.span;871 let ast::FnHeader { ext, safety, .. } = self.parse_fn_front_matter(872 &inherited_vis,873 Case::Sensitive,874 FrontMatterParsingMode::FunctionPtrType,875 )?;876 if self.may_recover() && self.token == TokenKind::Lt {877 self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;878 }879 let mode = crate::parser::FnParseMode {880 req_name: |_, _| false,881 context: FnContext::FunctionPtrType,882 req_body: false,883 };884 let decl = self.parse_fn_decl(&mode, AllowPlus::No, recover_return_sign)?;885886 let decl_span = span_start.to(self.prev_token.span);887 Ok(TyKind::FnPtr(Box::new(FnPtrTy {888 ext,889 safety,890 generic_params: params,891 decl,892 decl_span,893 })))894 }895896 /// Recover from function pointer types with a generic parameter list (e.g. `fn<'a>(&'a str)`).897 fn recover_fn_ptr_with_generics(898 &mut self,899 lo: Span,900 params: &mut ThinVec<GenericParam>,901 param_insertion_point: Option<Span>,902 ) -> PResult<'a, ()> {903 let generics = self.parse_generics()?;904 let arity = generics.params.len();905906 let mut lifetimes: ThinVec<_> = generics907 .params908 .into_iter()909 .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime))910 .collect();911912 let sugg = if !lifetimes.is_empty() {913 let snippet =914 lifetimes.iter().map(|param| param.ident.as_str()).intersperse(", ").collect();915916 let (left, snippet) = if let Some(span) = param_insertion_point {917 (span, if params.is_empty() { snippet } else { format!(", {snippet}") })918 } else {919 (lo.shrink_to_lo(), format!("for<{snippet}> "))920 };921922 Some(FnPtrWithGenericsSugg {923 left,924 snippet,925 right: generics.span,926 arity,927 for_param_list_exists: param_insertion_point.is_some(),928 })929 } else {930 None931 };932933 self.dcx().emit_err(FnPtrWithGenerics { span: generics.span, sugg });934 params.append(&mut lifetimes);935 Ok(())936 }937938 /// Parses an `impl B0 + ... + Bn` type.939 fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {940 if self.token.is_lifetime() {941 self.look_ahead(1, |t| {942 if let token::Ident(sym, _) = t.kind {943 // parse pattern with "'a Sized" we're supposed to give suggestion like944 // "'a + Sized"945 self.dcx().emit_err(diagnostics::MissingPlusBounds {946 span: self.token.span,947 hi: self.token.span.shrink_to_hi(),948 sym,949 });950 }951 })952 }953954 // Always parse bounds greedily for better error recovery.955 let bounds = self.parse_generic_bounds()?;956957 *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;958959 Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))960 }961962 /// Parse a use-bound aka precise capturing list.963 ///964 /// ```ebnf965 /// UseBound = "use" "<" (PreciseCapture ("," PreciseCapture)* ","?)? ">"966 /// PreciseCapture = "Self" | Ident | Lifetime967 /// ```968 fn parse_use_bound(&mut self, lo: Span, parens: ast::Parens) -> PResult<'a, GenericBound> {969 self.expect_lt()?;970 let (args, _, _) = self.parse_seq_to_before_tokens(971 &[exp!(Gt)],972 &[&TokenKind::Ge, &TokenKind::Shr, &TokenKind::Shr],973 SeqSep::trailing_allowed(exp!(Comma)),974 |self_| {975 if self_.check_keyword(exp!(SelfUpper)) {976 self_.bump();977 Ok(PreciseCapturingArg::Arg(978 ast::Path::from_ident(self_.prev_token.ident().unwrap().0),979 DUMMY_NODE_ID,980 ))981 } else if self_.check_ident() {982 Ok(PreciseCapturingArg::Arg(983 ast::Path::from_ident(self_.parse_ident()?),984 DUMMY_NODE_ID,985 ))986 } else if self_.check_lifetime() {987 Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))988 } else {989 self_.unexpected_any()990 }991 },992 )?;993 self.expect_gt()?;994995 if let ast::Parens::Yes = parens {996 self.expect(exp!(CloseParen))?;997 self.report_parenthesized_bound(lo, self.prev_token.span, "precise capturing lists");998 }9991000 Ok(GenericBound::Use(args, lo.to(self.prev_token.span)))1001 }10021003 /// Is a `dyn B0 + ... + Bn` type allowed here?1004 fn is_explicit_dyn_type(&mut self) -> bool {1005 self.check_keyword(exp!(Dyn))1006 && (self.token_uninterpolated_span().at_least_rust_2018()1007 || self.look_ahead(1, |&t| can_begin_dyn_bound_in_edition_2015(t)))1008 }10091010 /// Parses a `dyn B0 + ... + Bn` type.1011 ///1012 /// Note that this does *not* parse bare trait objects.1013 fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {1014 self.bump(); // `dyn`10151016 // Always parse bounds greedily for better error recovery.1017 let bounds = self.parse_generic_bounds()?;1018 *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;10191020 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn))1021 }10221023 /// Parses a type starting with a path.1024 ///1025 /// This can be:1026 /// 1. a type macro, `mac!(...)`,1027 /// 2. a bare trait object, `B0 + ... + Bn`,1028 /// 3. or a path, `path::to::MyType`.1029 fn parse_path_start_ty(1030 &mut self,1031 lo: Span,1032 allow_plus: AllowPlus,1033 ty_generics: Option<&Generics>,1034 ) -> PResult<'a, TyKind> {1035 // Simple path1036 let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;1037 if self.eat(exp!(Bang)) {1038 // Macro invocation in type position1039 Ok(TyKind::MacCall(Box::new(MacCall { path, args: self.parse_delim_args()? })))1040 } else if allow_plus == AllowPlus::Yes && self.check_plus() {1041 // `Trait1 + Trait2 + 'a`1042 self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true, ast::Parens::No)1043 } else {1044 // Just a type path.1045 Ok(TyKind::Path(None, path))1046 }1047 }10481049 pub(super) fn parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds> {1050 self.parse_generic_bounds_common(AllowPlus::Yes)1051 }10521053 /// Parse generic bounds.1054 ///1055 /// Only if `allow_plus` this parses a `+`-separated list of bounds (trailing `+` is admitted).1056 /// Otherwise, this only parses a single bound or none.1057 fn parse_generic_bounds_common(&mut self, allow_plus: AllowPlus) -> PResult<'a, GenericBounds> {1058 let mut bounds = ThinVec::new();10591060 // In addition to looping while we find generic bounds:1061 // We continue even if we find a keyword. This is necessary for error recovery on,1062 // for example, `impl fn()`. The only keyword that can go after generic bounds is1063 // `where`, so stop if it's it.1064 // We also continue if we find types (not traits), again for error recovery.1065 while self.can_begin_bound()1066 || (self.may_recover()1067 && (self.token.can_begin_type()1068 || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))))1069 {1070 if self.token.is_keyword(kw::Dyn) && self.token.span.edition().at_least_rust_2018() {1071 // Account for `&dyn Trait + dyn Other`.1072 self.bump();1073 self.dcx().emit_err(InvalidDynKeyword {1074 span: self.prev_token.span,1075 suggestion: self.prev_token.span.until(self.token.span),1076 });1077 }1078 bounds.push(self.parse_generic_bound()?);1079 if allow_plus == AllowPlus::No || !self.eat_plus() {1080 break;1081 }1082 }10831084 Ok(bounds)1085 }10861087 /// Can the current token begin a bound?1088 fn can_begin_bound(&mut self) -> bool {1089 self.check_path()1090 || self.check_lifetime()1091 || self.check(exp!(Bang))1092 || self.check(exp!(Question))1093 || self.check(exp!(Tilde))1094 || self.check_keyword(exp!(For))1095 || self.check(exp!(OpenParen))1096 || self.can_begin_maybe_const_bound()1097 || self.check_keyword(exp!(Const))1098 || self.check_keyword(exp!(Async))1099 || self.check_keyword(exp!(Use))1100 }11011102 fn can_begin_maybe_const_bound(&mut self) -> bool {1103 self.check(exp!(OpenBracket))1104 && self.look_ahead(1, |t| t.is_keyword(kw::Const))1105 && self.look_ahead(2, |t| *t == token::CloseBracket)1106 }11071108 /// Parse a bound.1109 ///1110 /// ```ebnf1111 /// Bound = LifetimeBound | UseBound | TraitBound1112 /// ```1113 fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {1114 let leading_token = self.prev_token;1115 let lo = self.token.span;11161117 // We only admit parenthesized *trait* bounds. However, we want to gracefully recover from1118 // other kinds of parenthesized bounds, so parse the opening parenthesis *here*.1119 //1120 // In the future we might want to lift this syntactic restriction and1121 // introduce "`GenericBound::Paren(Box<GenericBound>)`".1122 let parens = if self.eat(exp!(OpenParen)) { ast::Parens::Yes } else { ast::Parens::No };11231124 if self.token.is_lifetime() {1125 self.parse_lifetime_bound(lo, parens)1126 } else if self.eat_keyword(exp!(Use)) {1127 self.parse_use_bound(lo, parens)1128 } else {1129 self.parse_trait_bound(lo, parens, &leading_token)1130 }1131 }11321133 /// Parse a lifetime-bound aka outlives-bound.1134 ///1135 /// ```ebnf1136 /// LifetimeBound = Lifetime1137 /// ```1138 fn parse_lifetime_bound(&mut self, lo: Span, parens: ast::Parens) -> PResult<'a, GenericBound> {1139 let lt = self.expect_lifetime();11401141 if let ast::Parens::Yes = parens {1142 self.expect(exp!(CloseParen))?;1143 self.report_parenthesized_bound(lo, self.prev_token.span, "lifetime bounds");1144 }11451146 Ok(GenericBound::Outlives(lt))1147 }11481149 fn report_parenthesized_bound(&self, lo: Span, hi: Span, kind: &str) -> ErrorGuaranteed {1150 let mut diag =1151 self.dcx().struct_span_err(lo.to(hi), format!("{kind} may not be parenthesized"));1152 diag.multipart_suggestion(1153 "remove the parentheses",1154 vec![(lo, String::new()), (hi, String::new())],1155 Applicability::MachineApplicable,1156 );1157 diag.emit()1158 }11591160 /// Emits an error if any trait bound modifiers were present.1161 fn error_lt_bound_with_modifiers(1162 &self,1163 modifiers: TraitBoundModifiers,1164 binder_span: Option<Span>,1165 ) -> ErrorGuaranteed {1166 let TraitBoundModifiers { constness, asyncness, polarity } = modifiers;11671168 match constness {1169 BoundConstness::Never => {}1170 BoundConstness::Always(span) | BoundConstness::Maybe(span) => {1171 return self.dcx().emit_err(diagnostics::ModifierLifetime {1172 span,1173 modifier: constness.as_str(),1174 });1175 }1176 }11771178 match polarity {1179 BoundPolarity::Positive => {}1180 BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => {1181 return self1182 .dcx()1183 .emit_err(diagnostics::ModifierLifetime { span, modifier: polarity.as_str() });1184 }1185 }11861187 match asyncness {1188 BoundAsyncness::Normal => {}1189 BoundAsyncness::Async(span) => {1190 return self.dcx().emit_err(diagnostics::ModifierLifetime {1191 span,1192 modifier: asyncness.as_str(),1193 });1194 }1195 }11961197 if let Some(span) = binder_span {1198 return self1199 .dcx()1200 .emit_err(diagnostics::ModifierLifetime { span, modifier: "for<...>" });1201 }12021203 unreachable!("lifetime bound intercepted in `parse_generic_ty_bound` but no modifiers?")1204 }12051206 /// Parses the modifiers that may precede a trait in a bound, e.g. `?Trait` or `[const] Trait`.1207 ///1208 /// If no modifiers are present, this does not consume any tokens.1209 ///1210 /// ```ebnf1211 /// Constness = ("const" | "[" "const" "]")?1212 /// Asyncness = "async"?1213 /// Polarity = ("?" | "!")?1214 /// ```1215 ///1216 /// See `parse_trait_bound` for more context.1217 fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {1218 let modifier_lo = self.token.span;1219 let constness = self.parse_bound_constness()?;12201221 let asyncness = if self.token_uninterpolated_span().at_least_rust_2018()1222 && self.eat_keyword(exp!(Async))1223 {1224 self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);1225 BoundAsyncness::Async(self.prev_token.span)1226 } else if self.may_recover()1227 && self.token_uninterpolated_span().is_rust_2015()1228 && self.is_kw_followed_by_ident(kw::Async)1229 {1230 self.bump(); // eat `async`1231 self.dcx().emit_err(diagnostics::AsyncBoundModifierIn2015 {1232 span: self.prev_token.span,1233 help: HelpUseLatestEdition::new(),1234 });1235 self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);1236 BoundAsyncness::Async(self.prev_token.span)1237 } else {1238 BoundAsyncness::Normal1239 };1240 let modifier_hi = self.prev_token.span;12411242 let polarity = if self.eat(exp!(Question)) {1243 BoundPolarity::Maybe(self.prev_token.span)1244 } else if self.eat(exp!(Bang)) {1245 self.psess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);1246 BoundPolarity::Negative(self.prev_token.span)1247 } else {1248 BoundPolarity::Positive1249 };12501251 // Enforce the mutual-exclusivity of `const`/`async` and `?`/`!`.1252 match polarity {1253 BoundPolarity::Positive => {1254 // All trait bound modifiers allowed to combine with positive polarity1255 }1256 BoundPolarity::Maybe(polarity_span) | BoundPolarity::Negative(polarity_span) => {1257 match (asyncness, constness) {1258 (BoundAsyncness::Normal, BoundConstness::Never) => {1259 // Ok, no modifiers.1260 }1261 (_, _) => {1262 let constness = constness.as_str();1263 let asyncness = asyncness.as_str();1264 let glue =1265 if !constness.is_empty() && !asyncness.is_empty() { " " } else { "" };1266 let modifiers_concatenated = format!("{constness}{glue}{asyncness}");1267 self.dcx().emit_err(diagnostics::PolarityAndModifiers {1268 polarity_span,1269 polarity: polarity.as_str(),1270 modifiers_span: modifier_lo.to(modifier_hi),1271 modifiers_concatenated,1272 });1273 }1274 }1275 }1276 }12771278 Ok(TraitBoundModifiers { constness, asyncness, polarity })1279 }12801281 pub fn parse_bound_constness(&mut self) -> PResult<'a, BoundConstness> {1282 // FIXME(const_trait_impl): remove `~const` parser support once bootstrap has the new syntax1283 // in rustfmt1284 Ok(if self.eat(exp!(Tilde)) {1285 let tilde = self.prev_token.span;1286 self.expect_keyword(exp!(Const))?;1287 let span = tilde.to(self.prev_token.span);1288 self.psess.gated_spans.gate(sym::const_trait_impl, span);1289 BoundConstness::Maybe(span)1290 } else if self.can_begin_maybe_const_bound() {1291 let start = self.token.span;1292 self.bump();1293 self.expect_keyword(exp!(Const)).unwrap();1294 self.bump();1295 let span = start.to(self.prev_token.span);1296 self.psess.gated_spans.gate(sym::const_trait_impl, span);1297 BoundConstness::Maybe(span)1298 } else if self.eat_keyword(exp!(Const)) {1299 self.psess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span);1300 BoundConstness::Always(self.prev_token.span)1301 } else {1302 BoundConstness::Never1303 })1304 }13051306 /// Parse a trait bound.1307 ///1308 /// ```ebnf1309 /// TraitBound = BareTraitBound | "(" BareTraitBound ")"1310 /// BareTraitBound =1311 /// (HigherRankedBinder Constness Asyncness | Polarity)1312 /// TypePath1313 /// ```1314 fn parse_trait_bound(1315 &mut self,1316 lo: Span,1317 parens: ast::Parens,1318 leading_token: &Token,1319 ) -> PResult<'a, GenericBound> {1320 let (mut bound_vars, binder_span) = self.parse_higher_ranked_binder()?;13211322 let modifiers_lo = self.token.span;1323 let modifiers = self.parse_trait_bound_modifiers()?;1324 let modifiers_span = modifiers_lo.to(self.prev_token.span);13251326 if let Some(binder_span) = binder_span {1327 match modifiers.polarity {1328 BoundPolarity::Negative(polarity_span) | BoundPolarity::Maybe(polarity_span) => {1329 self.dcx().emit_err(diagnostics::BinderAndPolarity {1330 binder_span,1331 polarity_span,1332 polarity: modifiers.polarity.as_str(),1333 });1334 }1335 BoundPolarity::Positive => {}1336 }1337 }13381339 // Recover erroneous lifetime bound with modifiers or binder.1340 // e.g. `T: for<'a> 'a` or `T: [const] 'a`.1341 if self.token.is_lifetime() {1342 let _: ErrorGuaranteed = self.error_lt_bound_with_modifiers(modifiers, binder_span);1343 return self.parse_lifetime_bound(lo, parens);1344 }13451346 if let (more_bound_vars, Some(binder_span)) = self.parse_higher_ranked_binder()? {1347 bound_vars.extend(more_bound_vars);1348 self.dcx().emit_err(diagnostics::BinderBeforeModifiers { binder_span, modifiers_span });1349 }13501351 let mut path = if self.token.is_keyword(kw::Fn)1352 && self.look_ahead(1, |t| *t == TokenKind::OpenParen)1353 && let Some(path) = self.recover_path_from_fn()1354 {1355 path1356 } else if !self.token.is_path_start() && self.token.can_begin_type() {1357 let ty = self.parse_ty_no_plus()?;1358 // Instead of finding a path (a trait), we found a type.1359 let mut err = self.dcx().struct_span_err(ty.span, "expected a trait, found type");13601361 // If we can recover, try to extract a path from the type. Note1362 // that we do not use the try operator when parsing the type because1363 // if it fails then we get a parser error which we don't want (we're trying1364 // to recover from errors, not make more).1365 let path = if self.may_recover() {1366 let (span, message, sugg, path, applicability) = match &ty.kind {1367 TyKind::Ptr(..) | TyKind::Ref(..)1368 if let TyKind::Path(_, path) = &ty.peel_refs().kind =>1369 {1370 (1371 ty.span.until(path.span),1372 "consider removing the indirection",1373 "",1374 path,1375 Applicability::MaybeIncorrect,1376 )1377 }1378 TyKind::ImplTrait(_, bounds)1379 if let [GenericBound::Trait(tr, ..), ..] = bounds.as_slice() =>1380 {1381 (1382 ty.span.until(tr.span),1383 "use the trait bounds directly",1384 "",1385 &tr.trait_ref.path,1386 Applicability::MachineApplicable,1387 )1388 }1389 _ => return Err(err),1390 };13911392 err.span_suggestion_verbose(span, message, sugg, applicability);13931394 path.clone()1395 } else {1396 return Err(err);1397 };13981399 err.emit();14001401 path1402 } else {1403 self.parse_path(PathStyle::Type)?1404 };14051406 if self.may_recover() && self.token == TokenKind::OpenParen {1407 self.recover_fn_trait_with_lifetime_params(&mut path, &mut bound_vars)?;1408 }14091410 if let ast::Parens::Yes = parens {1411 // Someone has written something like `&dyn (Trait + Other)`. The correct code1412 // would be `&(dyn Trait + Other)`1413 if self.token.is_like_plus() && leading_token.is_keyword(kw::Dyn) {1414 let bounds = thin_vec![];1415 self.parse_remaining_bounds(bounds, true)?;1416 self.expect(exp!(CloseParen))?;1417 self.dcx().emit_err(diagnostics::IncorrectParensTraitBounds {1418 span: vec![lo, self.prev_token.span],1419 sugg: diagnostics::IncorrectParensTraitBoundsSugg {1420 wrong_span: leading_token.span.shrink_to_hi().to(lo),1421 new_span: leading_token.span.shrink_to_lo(),1422 },1423 });1424 } else {1425 self.expect(exp!(CloseParen))?;1426 }1427 }14281429 let poly_trait =1430 PolyTraitRef::new(bound_vars, path, modifiers, lo.to(self.prev_token.span), parens);1431 Ok(GenericBound::Trait(poly_trait))1432 }14331434 // recovers a `Fn(..)` parenthesized-style path from `fn(..)`1435 fn recover_path_from_fn(&mut self) -> Option<ast::Path> {1436 let fn_token_span = self.token.span;1437 self.bump();1438 let args_lo = self.token.span;1439 let snapshot = self.create_snapshot_for_diagnostic();1440 let mode =1441 FnParseMode { req_name: |_, _| false, context: FnContext::Free, req_body: false };1442 match self.parse_fn_decl(&mode, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {1443 Ok(decl) => {1444 self.dcx().emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });1445 Some(ast::Path {1446 span: fn_token_span.to(self.prev_token.span),1447 segments: thin_vec![ast::PathSegment {1448 ident: Ident::new(sym::Fn, fn_token_span),1449 id: DUMMY_NODE_ID,1450 args: Some(Box::new(ast::GenericArgs::Parenthesized(1451 ast::ParenthesizedArgs {1452 span: args_lo.to(self.prev_token.span),1453 inputs: decl.inputs.iter().map(|a| a.clone()).collect(),1454 inputs_span: args_lo.until(decl.output.span()),1455 output: decl.output.clone(),1456 }1457 ))),1458 }],1459 })1460 }1461 Err(diag) => {1462 diag.cancel();1463 self.restore_snapshot(snapshot);1464 None1465 }1466 }1467 }14681469 /// Parse an optional higher-ranked binder.1470 ///1471 /// ```ebnf1472 /// HigherRankedBinder = ("for" "<" GenericParams ">")?1473 /// ```1474 pub(super) fn parse_higher_ranked_binder(1475 &mut self,1476 ) -> PResult<'a, (ThinVec<GenericParam>, Option<Span>)> {1477 if self.eat_keyword(exp!(For)) {1478 let lo = self.token.span;1479 self.expect_lt()?;1480 let params = self.parse_generic_params()?;1481 self.expect_gt()?;1482 // We rely on AST validation to rule out invalid cases: There must not be1483 // type or const parameters, and parameters must not have bounds.1484 Ok((params, Some(lo.to(self.prev_token.span))))1485 } else {1486 Ok((ThinVec::new(), None))1487 }1488 }14891490 /// Recover from `Fn`-family traits (Fn, FnMut, FnOnce) with lifetime arguments1491 /// (e.g. `FnOnce<'a>(&'a str) -> bool`). Up to generic arguments have already1492 /// been eaten.1493 fn recover_fn_trait_with_lifetime_params(1494 &mut self,1495 fn_path: &mut ast::Path,1496 lifetime_defs: &mut ThinVec<GenericParam>,1497 ) -> PResult<'a, ()> {1498 let fn_path_segment = fn_path.segments.last_mut().unwrap();1499 let generic_args = if let Some(p_args) = &fn_path_segment.args {1500 *p_args.clone()1501 } else {1502 // Normally it wouldn't come here because the upstream should have parsed1503 // generic parameters (otherwise it's impossible to call this function).1504 return Ok(());1505 };1506 let lifetimes =1507 if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) =1508 &generic_args1509 {1510 args.into_iter()1511 .filter_map(|arg| {1512 if let ast::AngleBracketedArg::Arg(generic_arg) = arg1513 && let ast::GenericArg::Lifetime(lifetime) = generic_arg1514 {1515 Some(lifetime)1516 } else {1517 None1518 }1519 })1520 .collect()1521 } else {1522 Vec::new()1523 };1524 // Only try to recover if the trait has lifetime params.1525 if lifetimes.is_empty() {1526 return Ok(());1527 }15281529 let snapshot = if self.parsing_generics {1530 // The snapshot is only relevant if we're parsing the generics of an `fn` to avoid1531 // incorrect recovery.1532 Some(self.create_snapshot_for_diagnostic())1533 } else {1534 None1535 };1536 // Parse `(T, U) -> R`.1537 let inputs_lo = self.token.span;1538 let mode =1539 FnParseMode { req_name: |_, _| false, context: FnContext::Free, req_body: false };1540 let inputs = match self.parse_fn_params(&mode) {1541 Ok(params) => params,1542 Err(err) => {1543 if let Some(snapshot) = snapshot {1544 self.restore_snapshot(snapshot);1545 err.cancel();1546 return Ok(());1547 } else {1548 return Err(err);1549 }1550 }1551 };1552 let inputs_span = inputs_lo.to(self.prev_token.span);1553 let output = match self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)1554 {1555 Ok(output) => output,1556 Err(err) => {1557 if let Some(snapshot) = snapshot {1558 self.restore_snapshot(snapshot);1559 err.cancel();1560 return Ok(());1561 } else {1562 return Err(err);1563 }1564 }1565 };1566 let args = ast::ParenthesizedArgs {1567 span: fn_path_segment.span().to(self.prev_token.span),1568 inputs,1569 inputs_span,1570 output,1571 }1572 .into();15731574 if let Some(snapshot) = snapshot1575 && ![token::Comma, token::Gt, token::Plus].contains(&self.token.kind)1576 {1577 // We would expect another bound or the end of type params by now. Most likely we've1578 // encountered a `(` *not* representing `Trait()`, but rather the start of the `fn`'s1579 // argument list where the generic param list wasn't properly closed.1580 self.restore_snapshot(snapshot);1581 return Ok(());1582 }15831584 *fn_path_segment = ast::PathSegment {1585 ident: fn_path_segment.ident,1586 args: Some(args),1587 id: ast::DUMMY_NODE_ID,1588 };15891590 // Convert parsed `<'a>` in `Fn<'a>` into `for<'a>`.1591 let mut generic_params = lifetimes1592 .iter()1593 .map(|lt| GenericParam {1594 id: lt.id,1595 ident: lt.ident,1596 attrs: ast::AttrVec::new(),1597 bounds: ThinVec::new(),1598 is_placeholder: false,1599 kind: ast::GenericParamKind::Lifetime,1600 colon_span: None,1601 })1602 .collect::<ThinVec<GenericParam>>();1603 lifetime_defs.append(&mut generic_params);16041605 let generic_args_span = generic_args.span();1606 let snippet = format!(1607 "for<{}> ",1608 lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),1609 );1610 let before_fn_path = fn_path.span.shrink_to_lo();1611 self.dcx()1612 .struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters")1613 .with_multipart_suggestion(1614 "consider using a higher-ranked trait bound instead",1615 vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],1616 Applicability::MaybeIncorrect,1617 )1618 .emit();1619 Ok(())1620 }16211622 pub(super) fn check_lifetime(&mut self) -> bool {1623 self.expected_token_types.insert(TokenType::Lifetime);1624 self.token.is_lifetime()1625 }16261627 /// Parses a single lifetime `'a` or panics.1628 pub(super) fn expect_lifetime(&mut self) -> Lifetime {1629 if let Some((ident, is_raw)) = self.token.lifetime() {1630 if is_raw == IdentIsRaw::No && ident.without_first_quote().is_reserved_lifetime() {1631 self.dcx().emit_err(diagnostics::KeywordLifetime { span: ident.span });1632 }16331634 self.bump();1635 Lifetime { ident, id: ast::DUMMY_NODE_ID }1636 } else {1637 self.dcx().span_bug(self.token.span, "not a lifetime")1638 }1639 }16401641 pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> Box<Ty> {1642 Box::new(Ty { kind, span, id: ast::DUMMY_NODE_ID })1643 }1644}