1use rustc_ast::ptr::P;
2use rustc_ast::token::{self, IdentIsRaw, MetaVarKind, Token, TokenKind};
3use rustc_ast::util::case::Case;
4use rustc_ast::{
5 self as ast, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnPtrTy, FnRetTy,
6 GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability,
7 Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty,
8 TyKind, UnsafeBinderTy,
9};
10use rustc_data_structures::stack::ensure_sufficient_stack;
11use rustc_errors::{Applicability, Diag, PResult};
12use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
13use thin_vec::{ThinVec, thin_vec};
14
15use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
16use crate::errors::{
17 self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
18 FnPtrWithGenerics, FnPtrWithGenericsSugg, HelpUseLatestEdition, InvalidDynKeyword,
19 LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, NestedCVariadicType,
20 ReturnTypesUseThinArrow,
21};
22use crate::parser::item::FrontMatterParsingMode;
23use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
24
25#[derive(Copy, Clone, PartialEq)]
31pub(super) enum AllowPlus {
32 Yes,
33 No,
34}
35
36#[derive(PartialEq)]
37pub(super) enum RecoverQPath {
38 Yes,
39 No,
40}
41
42pub(super) enum RecoverQuestionMark {
43 Yes,
44 No,
45}
46
47#[derive(Copy, Clone, PartialEq)]
58pub(super) enum RecoverReturnSign {
59 Yes,
60 OnlyFatArrow,
61 No,
62}
63
64impl RecoverReturnSign {
65 fn can_recover(self, token: &TokenKind) -> bool {
70 match self {
71 Self::Yes => matches!(token, token::FatArrow | token::Colon),
72 Self::OnlyFatArrow => matches!(token, token::FatArrow),
73 Self::No => false,
74 }
75 }
76}
77
78#[derive(PartialEq)]
80enum AllowCVariadic {
81 Yes,
82 No,
83}
84
85fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
91 t == &token::PathSep || t == &token::Lt || t == &token::Shl
92}
93
94fn can_begin_dyn_bound_in_edition_2015(t: &Token) -> bool {
95 t.is_path_start()
100 || t.is_lifetime()
101 || t == &TokenKind::Question
102 || t.is_keyword(kw::For)
103 || t == &TokenKind::OpenParen
104}
105
106impl<'a> Parser<'a> {
107 pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
109 ensure_sufficient_stack(|| {
111 self.parse_ty_common(
112 AllowPlus::Yes,
113 AllowCVariadic::No,
114 RecoverQPath::Yes,
115 RecoverReturnSign::Yes,
116 None,
117 RecoverQuestionMark::Yes,
118 )
119 })
120 }
121
122 pub(super) fn parse_ty_with_generics_recovery(
123 &mut self,
124 ty_params: &Generics,
125 ) -> PResult<'a, P<Ty>> {
126 self.parse_ty_common(
127 AllowPlus::Yes,
128 AllowCVariadic::No,
129 RecoverQPath::Yes,
130 RecoverReturnSign::Yes,
131 Some(ty_params),
132 RecoverQuestionMark::Yes,
133 )
134 }
135
136 pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> {
140 self.parse_ty_common(
141 AllowPlus::Yes,
142 AllowCVariadic::Yes,
143 RecoverQPath::Yes,
144 RecoverReturnSign::Yes,
145 None,
146 RecoverQuestionMark::Yes,
147 )
148 }
149
150 pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
157 self.parse_ty_common(
158 AllowPlus::No,
159 AllowCVariadic::No,
160 RecoverQPath::Yes,
161 RecoverReturnSign::Yes,
162 None,
163 RecoverQuestionMark::Yes,
164 )
165 }
166
167 pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, P<Ty>> {
170 self.parse_ty_common(
171 AllowPlus::No,
172 AllowCVariadic::No,
173 RecoverQPath::Yes,
174 RecoverReturnSign::Yes,
175 None,
176 RecoverQuestionMark::No,
177 )
178 }
179
180 pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
181 self.parse_ty_common(
182 AllowPlus::Yes,
183 AllowCVariadic::No,
184 RecoverQPath::Yes,
185 RecoverReturnSign::Yes,
186 None,
187 RecoverQuestionMark::No,
188 )
189 }
190
191 pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
194 self.parse_ty_common(
195 AllowPlus::Yes,
196 AllowCVariadic::No,
197 RecoverQPath::Yes,
198 RecoverReturnSign::OnlyFatArrow,
199 None,
200 RecoverQuestionMark::Yes,
201 )
202 }
203
204 pub(super) fn parse_ret_ty(
206 &mut self,
207 allow_plus: AllowPlus,
208 recover_qpath: RecoverQPath,
209 recover_return_sign: RecoverReturnSign,
210 ) -> PResult<'a, FnRetTy> {
211 let lo = self.prev_token.span;
212 Ok(if self.eat(exp!(RArrow)) {
213 let ty = self.parse_ty_common(
215 allow_plus,
216 AllowCVariadic::No,
217 recover_qpath,
218 recover_return_sign,
219 None,
220 RecoverQuestionMark::Yes,
221 )?;
222 FnRetTy::Ty(ty)
223 } else if recover_return_sign.can_recover(&self.token.kind) {
224 self.bump();
227 self.dcx().emit_err(ReturnTypesUseThinArrow {
228 span: self.prev_token.span,
229 suggestion: lo.between(self.token.span),
230 });
231 let ty = self.parse_ty_common(
232 allow_plus,
233 AllowCVariadic::No,
234 recover_qpath,
235 recover_return_sign,
236 None,
237 RecoverQuestionMark::Yes,
238 )?;
239 FnRetTy::Ty(ty)
240 } else {
241 FnRetTy::Default(self.prev_token.span.shrink_to_hi())
242 })
243 }
244
245 fn parse_ty_common(
246 &mut self,
247 allow_plus: AllowPlus,
248 allow_c_variadic: AllowCVariadic,
249 recover_qpath: RecoverQPath,
250 recover_return_sign: RecoverReturnSign,
251 ty_generics: Option<&Generics>,
252 recover_question_mark: RecoverQuestionMark,
253 ) -> PResult<'a, P<Ty>> {
254 let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
255 maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
256
257 if let Some(ty) = self.eat_metavar_seq_with_matcher(
258 |mv_kind| matches!(mv_kind, MetaVarKind::Ty { .. }),
259 |this| this.parse_ty_no_question_mark_recover(),
260 ) {
261 return Ok(ty);
262 }
263
264 let lo = self.token.span;
265 let mut impl_dyn_multi = false;
266 let kind = if self.check(exp!(OpenParen)) {
267 self.parse_ty_tuple_or_parens(lo, allow_plus)?
268 } else if self.eat(exp!(Bang)) {
269 TyKind::Never
271 } else if self.eat(exp!(Star)) {
272 self.parse_ty_ptr()?
273 } else if self.eat(exp!(OpenBracket)) {
274 self.parse_array_or_slice_ty()?
275 } else if self.check(exp!(And)) || self.check(exp!(AndAnd)) {
276 self.expect_and()?;
278 self.parse_borrowed_pointee()?
279 } else if self.eat_keyword_noexpect(kw::Typeof) {
280 self.parse_typeof_ty()?
281 } else if self.eat_keyword(exp!(Underscore)) {
282 TyKind::Infer
284 } else if self.check_fn_front_matter(false, Case::Sensitive) {
285 self.parse_ty_fn_ptr(lo, ThinVec::new(), None, recover_return_sign)?
287 } else if self.check_keyword(exp!(For)) {
288 let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?;
292 if self.check_fn_front_matter(false, Case::Sensitive) {
293 self.parse_ty_fn_ptr(
294 lo,
295 lifetime_defs,
296 Some(self.prev_token.span.shrink_to_lo()),
297 recover_return_sign,
298 )?
299 } else {
300 if self.may_recover()
302 && (self.eat_keyword_noexpect(kw::Impl) || self.eat_keyword_noexpect(kw::Dyn))
303 {
304 let kw = self.prev_token.ident().unwrap().0;
305 let removal_span = kw.span.with_hi(self.token.span.lo());
306 let path = self.parse_path(PathStyle::Type)?;
307 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
308 let kind = self.parse_remaining_bounds_path(
309 lifetime_defs,
310 path,
311 lo,
312 parse_plus,
313 ast::Parens::No,
314 )?;
315 let err = self.dcx().create_err(errors::TransposeDynOrImpl {
316 span: kw.span,
317 kw: kw.name.as_str(),
318 sugg: errors::TransposeDynOrImplSugg {
319 removal_span,
320 insertion_span: lo.shrink_to_lo(),
321 kw: kw.name.as_str(),
322 },
323 });
324
325 let kind = match (kind, kw.name) {
328 (TyKind::TraitObject(bounds, _), kw::Dyn) => {
329 TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)
330 }
331 (TyKind::TraitObject(bounds, _), kw::Impl) => {
332 TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)
333 }
334 _ => return Err(err),
335 };
336 err.emit();
337 kind
338 } else {
339 let path = self.parse_path(PathStyle::Type)?;
340 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
341 self.parse_remaining_bounds_path(
342 lifetime_defs,
343 path,
344 lo,
345 parse_plus,
346 ast::Parens::No,
347 )?
348 }
349 }
350 } else if self.eat_keyword(exp!(Impl)) {
351 self.parse_impl_ty(&mut impl_dyn_multi)?
352 } else if self.is_explicit_dyn_type() {
353 self.parse_dyn_ty(&mut impl_dyn_multi)?
354 } else if self.eat_lt() {
355 let (qself, path) = self.parse_qpath(PathStyle::Type)?;
357 TyKind::Path(Some(qself), path)
358 } else if self.check_path() {
359 self.parse_path_start_ty(lo, allow_plus, ty_generics)?
360 } else if self.can_begin_bound() {
361 self.parse_bare_trait_object(lo, allow_plus)?
362 } else if self.eat(exp!(DotDotDot)) {
363 match allow_c_variadic {
364 AllowCVariadic::Yes => TyKind::CVarArgs,
365 AllowCVariadic::No => {
366 let guar = self.dcx().emit_err(NestedCVariadicType { span: lo });
370 TyKind::Err(guar)
371 }
372 }
373 } else if self.check_keyword(exp!(Unsafe))
374 && self.look_ahead(1, |tok| tok.kind == token::Lt)
375 {
376 self.parse_unsafe_binder_ty()?
377 } else {
378 let msg = format!("expected type, found {}", super::token_descr(&self.token));
379 let mut err = self.dcx().struct_span_err(lo, msg);
380 err.span_label(lo, "expected type");
381 return Err(err);
382 };
383
384 let span = lo.to(self.prev_token.span);
385 let mut ty = self.mk_ty(span, kind);
386
387 match allow_plus {
389 AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?,
390 AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty),
391 }
392 if let RecoverQuestionMark::Yes = recover_question_mark {
393 ty = self.maybe_recover_from_question_mark(ty);
394 }
395 if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
396 }
397
398 fn parse_unsafe_binder_ty(&mut self) -> PResult<'a, TyKind> {
399 let lo = self.token.span;
400 assert!(self.eat_keyword(exp!(Unsafe)));
401 self.expect_lt()?;
402 let generic_params = self.parse_generic_params()?;
403 self.expect_gt()?;
404 let inner_ty = self.parse_ty()?;
405 let span = lo.to(self.prev_token.span);
406 self.psess.gated_spans.gate(sym::unsafe_binders, span);
407
408 Ok(TyKind::UnsafeBinder(P(UnsafeBinderTy { generic_params, inner_ty })))
409 }
410
411 fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
415 let mut trailing_plus = false;
416 let (ts, trailing) = self.parse_paren_comma_seq(|p| {
417 let ty = p.parse_ty()?;
418 trailing_plus = p.prev_token == TokenKind::Plus;
419 Ok(ty)
420 })?;
421
422 if ts.len() == 1 && matches!(trailing, Trailing::No) {
423 let ty = ts.into_iter().next().unwrap();
424 let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus();
425 match ty.kind {
426 TyKind::Path(None, path) if maybe_bounds => self.parse_remaining_bounds_path(
428 ThinVec::new(),
429 path,
430 lo,
431 true,
432 ast::Parens::Yes,
433 ),
434 TyKind::TraitObject(bounds, TraitObjectSyntax::None)
438 if maybe_bounds && bounds.len() == 1 && !trailing_plus =>
439 {
440 self.parse_remaining_bounds(bounds, true)
441 }
442 _ => Ok(TyKind::Paren(ty)),
444 }
445 } else {
446 Ok(TyKind::Tup(ts))
447 }
448 }
449
450 fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
451 if self.token.is_lifetime() && !self.look_ahead(1, |t| t.is_like_plus()) {
453 if self.psess.edition.at_least_rust_2021() {
457 let lt = self.expect_lifetime();
458 let mut err = self.dcx().struct_span_err(lo, "expected type, found lifetime");
459 err.span_label(lo, "expected type");
460 return Ok(match self.maybe_recover_ref_ty_no_leading_ampersand(lt, lo, err) {
461 Ok(ref_ty) => ref_ty,
462 Err(err) => TyKind::Err(err.emit()),
463 });
464 }
465
466 self.dcx().emit_err(NeedPlusAfterTraitObjectLifetime {
467 span: lo,
468 suggestion: lo.shrink_to_hi(),
469 });
470 }
471 Ok(TyKind::TraitObject(
472 self.parse_generic_bounds_common(allow_plus)?,
473 TraitObjectSyntax::None,
474 ))
475 }
476
477 fn maybe_recover_ref_ty_no_leading_ampersand<'cx>(
478 &mut self,
479 lt: Lifetime,
480 lo: Span,
481 mut err: Diag<'cx>,
482 ) -> Result<TyKind, Diag<'cx>> {
483 if !self.may_recover() {
484 return Err(err);
485 }
486 let snapshot = self.create_snapshot_for_diagnostic();
487 let mutbl = self.parse_mutability();
488 match self.parse_ty_no_plus() {
489 Ok(ty) => {
490 err.span_suggestion_verbose(
491 lo.shrink_to_lo(),
492 "you might have meant to write a reference type here",
493 "&",
494 Applicability::MaybeIncorrect,
495 );
496 err.emit();
497 Ok(TyKind::Ref(Some(lt), MutTy { ty, mutbl }))
498 }
499 Err(diag) => {
500 diag.cancel();
501 self.restore_snapshot(snapshot);
502 Err(err)
503 }
504 }
505 }
506
507 fn parse_remaining_bounds_path(
508 &mut self,
509 generic_params: ThinVec<GenericParam>,
510 path: ast::Path,
511 lo: Span,
512 parse_plus: bool,
513 parens: ast::Parens,
514 ) -> PResult<'a, TyKind> {
515 let poly_trait_ref = PolyTraitRef::new(
516 generic_params,
517 path,
518 TraitBoundModifiers::NONE,
519 lo.to(self.prev_token.span),
520 parens,
521 );
522 let bounds = vec![GenericBound::Trait(poly_trait_ref)];
523 self.parse_remaining_bounds(bounds, parse_plus)
524 }
525
526 fn parse_remaining_bounds(
528 &mut self,
529 mut bounds: GenericBounds,
530 plus: bool,
531 ) -> PResult<'a, TyKind> {
532 if plus {
533 self.eat_plus(); bounds.append(&mut self.parse_generic_bounds()?);
535 }
536 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
537 }
538
539 fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
541 let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
542 let span = self.prev_token.span;
543 self.dcx().emit_err(ExpectedMutOrConstInRawPointerType {
544 span,
545 after_asterisk: span.shrink_to_hi(),
546 });
547 Mutability::Not
548 });
549 let ty = self.parse_ty_no_plus()?;
550 Ok(TyKind::Ptr(MutTy { ty, mutbl }))
551 }
552
553 fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {
556 let elt_ty = match self.parse_ty() {
557 Ok(ty) => ty,
558 Err(err)
559 if self.look_ahead(1, |t| *t == token::CloseBracket)
560 | self.look_ahead(1, |t| *t == token::Semi) =>
561 {
562 self.bump();
564 let guar = err.emit();
565 self.mk_ty(self.prev_token.span, TyKind::Err(guar))
566 }
567 Err(err) => return Err(err),
568 };
569
570 let ty = if self.eat(exp!(Semi)) {
571 let mut length = self.parse_expr_anon_const()?;
572 if let Err(e) = self.expect(exp!(CloseBracket)) {
573 self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
575 self.expect(exp!(CloseBracket))?;
576 }
577 TyKind::Array(elt_ty, length)
578 } else if self.eat(exp!(CloseBracket)) {
579 TyKind::Slice(elt_ty)
580 } else {
581 self.maybe_recover_array_ty_without_semi(elt_ty)?
582 };
583
584 Ok(ty)
585 }
586
587 fn maybe_recover_array_ty_without_semi(&mut self, elt_ty: P<Ty>) -> PResult<'a, TyKind> {
594 let span = self.token.span;
595 let token_descr = super::token_descr(&self.token);
596 let mut err =
597 self.dcx().struct_span_err(span, format!("expected `;` or `]`, found {}", token_descr));
598 err.span_label(span, "expected `;` or `]`");
599 err.note("you might have meant to write a slice or array type");
600
601 if !self.may_recover() {
603 return Err(err);
604 }
605
606 let snapshot = self.create_snapshot_for_diagnostic();
607
608 let suggestion_span = if self.eat(exp!(Comma)) || self.eat(exp!(Star)) {
609 self.prev_token.span
611 } else {
612 self.token.span.shrink_to_lo()
613 };
614
615 let length = match self.parse_expr_anon_const() {
617 Ok(length) => length,
618 Err(e) => {
619 e.cancel();
620 self.restore_snapshot(snapshot);
621 return Err(err);
622 }
623 };
624
625 if let Err(e) = self.expect(exp!(CloseBracket)) {
626 e.cancel();
627 self.restore_snapshot(snapshot);
628 return Err(err);
629 }
630
631 err.span_suggestion_verbose(
632 suggestion_span,
633 "you might have meant to use `;` as the separator",
634 ";",
635 Applicability::MaybeIncorrect,
636 );
637 err.emit();
638 Ok(TyKind::Array(elt_ty, length))
639 }
640
641 fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
642 let and_span = self.prev_token.span;
643 let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());
644 let (pinned, mut mutbl) = match self.parse_pin_and_mut() {
645 Some(pin_mut) => pin_mut,
646 None => (Pinnedness::Not, self.parse_mutability()),
647 };
648 if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
649 if !self.look_ahead(1, |t| t.is_like_plus()) {
655 let lifetime_span = self.token.span;
656 let span = and_span.to(lifetime_span);
657
658 let (suggest_lifetime, snippet) =
659 if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
660 (Some(span), lifetime_src)
661 } else {
662 (None, String::new())
663 };
664 self.dcx().emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });
665
666 opt_lifetime = Some(self.expect_lifetime());
667 }
668 } else if self.token.is_keyword(kw::Dyn)
669 && mutbl == Mutability::Not
670 && self.look_ahead(1, |t| t.is_keyword(kw::Mut))
671 {
672 let span = and_span.to(self.look_ahead(1, |t| t.span));
674 self.dcx().emit_err(DynAfterMut { span });
675
676 mutbl = Mutability::Mut;
678 let (dyn_tok, dyn_tok_sp) = (self.token, self.token_spacing);
679 self.bump();
680 self.bump_with((dyn_tok, dyn_tok_sp));
681 }
682 let ty = self.parse_ty_no_plus()?;
683 Ok(match pinned {
684 Pinnedness::Not => TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }),
685 Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl }),
686 })
687 }
688
689 pub(crate) fn parse_pin_and_mut(&mut self) -> Option<(Pinnedness, Mutability)> {
693 if self.token.is_ident_named(sym::pin) {
694 let result = self.look_ahead(1, |token| {
695 if token.is_keyword(kw::Const) {
696 Some((Pinnedness::Pinned, Mutability::Not))
697 } else if token.is_keyword(kw::Mut) {
698 Some((Pinnedness::Pinned, Mutability::Mut))
699 } else {
700 None
701 }
702 });
703 if result.is_some() {
704 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
705 self.bump();
706 self.bump();
707 }
708 result
709 } else {
710 None
711 }
712 }
713
714 fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> {
717 self.expect(exp!(OpenParen))?;
718 let expr = self.parse_expr_anon_const()?;
719 self.expect(exp!(CloseParen))?;
720 Ok(TyKind::Typeof(expr))
721 }
722
723 fn parse_ty_fn_ptr(
733 &mut self,
734 lo: Span,
735 mut params: ThinVec<GenericParam>,
736 param_insertion_point: Option<Span>,
737 recover_return_sign: RecoverReturnSign,
738 ) -> PResult<'a, TyKind> {
739 let inherited_vis = rustc_ast::Visibility {
740 span: rustc_span::DUMMY_SP,
741 kind: rustc_ast::VisibilityKind::Inherited,
742 tokens: None,
743 };
744 let span_start = self.token.span;
745 let ast::FnHeader { ext, safety, .. } = self.parse_fn_front_matter(
746 &inherited_vis,
747 Case::Sensitive,
748 FrontMatterParsingMode::FunctionPtrType,
749 )?;
750 if self.may_recover() && self.token == TokenKind::Lt {
751 self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
752 }
753 let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
754
755 let decl_span = span_start.to(self.prev_token.span);
756 Ok(TyKind::FnPtr(P(FnPtrTy { ext, safety, generic_params: params, decl, decl_span })))
757 }
758
759 fn recover_fn_ptr_with_generics(
761 &mut self,
762 lo: Span,
763 params: &mut ThinVec<GenericParam>,
764 param_insertion_point: Option<Span>,
765 ) -> PResult<'a, ()> {
766 let generics = self.parse_generics()?;
767 let arity = generics.params.len();
768
769 let mut lifetimes: ThinVec<_> = generics
770 .params
771 .into_iter()
772 .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime))
773 .collect();
774
775 let sugg = if !lifetimes.is_empty() {
776 let snippet =
777 lifetimes.iter().map(|param| param.ident.as_str()).intersperse(", ").collect();
778
779 let (left, snippet) = if let Some(span) = param_insertion_point {
780 (span, if params.is_empty() { snippet } else { format!(", {snippet}") })
781 } else {
782 (lo.shrink_to_lo(), format!("for<{snippet}> "))
783 };
784
785 Some(FnPtrWithGenericsSugg {
786 left,
787 snippet,
788 right: generics.span,
789 arity,
790 for_param_list_exists: param_insertion_point.is_some(),
791 })
792 } else {
793 None
794 };
795
796 self.dcx().emit_err(FnPtrWithGenerics { span: generics.span, sugg });
797 params.append(&mut lifetimes);
798 Ok(())
799 }
800
801 fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
803 if self.token.is_lifetime() {
804 self.look_ahead(1, |t| {
805 if let token::Ident(sym, _) = t.kind {
806 self.dcx().emit_err(errors::MissingPlusBounds {
809 span: self.token.span,
810 hi: self.token.span.shrink_to_hi(),
811 sym,
812 });
813 }
814 })
815 }
816
817 let bounds = self.parse_generic_bounds()?;
819
820 *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
821
822 Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))
823 }
824
825 fn parse_precise_capturing_args(
826 &mut self,
827 ) -> PResult<'a, (ThinVec<PreciseCapturingArg>, Span)> {
828 let lo = self.token.span;
829 self.expect_lt()?;
830 let (args, _, _) = self.parse_seq_to_before_tokens(
831 &[exp!(Gt)],
832 &[&TokenKind::Ge, &TokenKind::Shr, &TokenKind::Shr],
833 SeqSep::trailing_allowed(exp!(Comma)),
834 |self_| {
835 if self_.check_keyword(exp!(SelfUpper)) {
836 self_.bump();
837 Ok(PreciseCapturingArg::Arg(
838 ast::Path::from_ident(self_.prev_token.ident().unwrap().0),
839 DUMMY_NODE_ID,
840 ))
841 } else if self_.check_ident() {
842 Ok(PreciseCapturingArg::Arg(
843 ast::Path::from_ident(self_.parse_ident()?),
844 DUMMY_NODE_ID,
845 ))
846 } else if self_.check_lifetime() {
847 Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))
848 } else {
849 self_.unexpected_any()
850 }
851 },
852 )?;
853 self.expect_gt()?;
854 Ok((args, lo.to(self.prev_token.span)))
855 }
856
857 fn is_explicit_dyn_type(&mut self) -> bool {
859 self.check_keyword(exp!(Dyn))
860 && (self.token_uninterpolated_span().at_least_rust_2018()
861 || self.look_ahead(1, |t| {
862 (can_begin_dyn_bound_in_edition_2015(t) || *t == TokenKind::Star)
863 && !can_continue_type_after_non_fn_ident(t)
864 }))
865 }
866
867 fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
871 self.bump(); let syntax = TraitObjectSyntax::Dyn;
875
876 let bounds = self.parse_generic_bounds()?;
878 *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
879 Ok(TyKind::TraitObject(bounds, syntax))
880 }
881
882 fn parse_path_start_ty(
889 &mut self,
890 lo: Span,
891 allow_plus: AllowPlus,
892 ty_generics: Option<&Generics>,
893 ) -> PResult<'a, TyKind> {
894 let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
896 if self.eat(exp!(Bang)) {
897 Ok(TyKind::MacCall(P(MacCall { path, args: self.parse_delim_args()? })))
899 } else if allow_plus == AllowPlus::Yes && self.check_plus() {
900 self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true, ast::Parens::No)
902 } else {
903 Ok(TyKind::Path(None, path))
905 }
906 }
907
908 pub(super) fn parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds> {
909 self.parse_generic_bounds_common(AllowPlus::Yes)
910 }
911
912 fn parse_generic_bounds_common(&mut self, allow_plus: AllowPlus) -> PResult<'a, GenericBounds> {
916 let mut bounds = Vec::new();
917
918 while self.can_begin_bound()
924 || (self.may_recover()
925 && (self.token.can_begin_type()
926 || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))))
927 {
928 if self.token.is_keyword(kw::Dyn) {
929 self.bump();
931 self.dcx().emit_err(InvalidDynKeyword {
932 span: self.prev_token.span,
933 suggestion: self.prev_token.span.until(self.token.span),
934 });
935 }
936 bounds.push(self.parse_generic_bound()?);
937 if allow_plus == AllowPlus::No || !self.eat_plus() {
938 break;
939 }
940 }
941
942 Ok(bounds)
943 }
944
945 fn can_begin_bound(&mut self) -> bool {
947 self.check_path()
948 || self.check_lifetime()
949 || self.check(exp!(Bang))
950 || self.check(exp!(Question))
951 || self.check(exp!(Tilde))
952 || self.check_keyword(exp!(For))
953 || self.check(exp!(OpenParen))
954 || self.check(exp!(OpenBracket))
955 || self.check_keyword(exp!(Const))
956 || self.check_keyword(exp!(Async))
957 || self.check_keyword(exp!(Use))
958 }
959
960 fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
965 let lo = self.token.span;
966 let leading_token = self.prev_token;
967 let parens = if self.eat(exp!(OpenParen)) { ast::Parens::Yes } else { ast::Parens::No };
968
969 let bound = if self.token.is_lifetime() {
970 self.parse_generic_lt_bound(lo, parens)?
971 } else if self.eat_keyword(exp!(Use)) {
972 let use_span = self.prev_token.span;
976 let (args, args_span) = self.parse_precise_capturing_args()?;
977 GenericBound::Use(args, use_span.to(args_span))
978 } else {
979 self.parse_generic_ty_bound(lo, parens, &leading_token)?
980 };
981
982 Ok(bound)
983 }
984
985 fn parse_generic_lt_bound(
990 &mut self,
991 lo: Span,
992 parens: ast::Parens,
993 ) -> PResult<'a, GenericBound> {
994 let lt = self.expect_lifetime();
995 let bound = GenericBound::Outlives(lt);
996 if let ast::Parens::Yes = parens {
997 self.recover_paren_lifetime(lo)?;
1000 }
1001 Ok(bound)
1002 }
1003
1004 fn error_lt_bound_with_modifiers(
1006 &self,
1007 modifiers: TraitBoundModifiers,
1008 binder_span: Option<Span>,
1009 ) -> ErrorGuaranteed {
1010 let TraitBoundModifiers { constness, asyncness, polarity } = modifiers;
1011
1012 match constness {
1013 BoundConstness::Never => {}
1014 BoundConstness::Always(span) | BoundConstness::Maybe(span) => {
1015 return self
1016 .dcx()
1017 .emit_err(errors::ModifierLifetime { span, modifier: constness.as_str() });
1018 }
1019 }
1020
1021 match polarity {
1022 BoundPolarity::Positive => {}
1023 BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => {
1024 return self
1025 .dcx()
1026 .emit_err(errors::ModifierLifetime { span, modifier: polarity.as_str() });
1027 }
1028 }
1029
1030 match asyncness {
1031 BoundAsyncness::Normal => {}
1032 BoundAsyncness::Async(span) => {
1033 return self
1034 .dcx()
1035 .emit_err(errors::ModifierLifetime { span, modifier: asyncness.as_str() });
1036 }
1037 }
1038
1039 if let Some(span) = binder_span {
1040 return self.dcx().emit_err(errors::ModifierLifetime { span, modifier: "for<...>" });
1041 }
1042
1043 unreachable!("lifetime bound intercepted in `parse_generic_ty_bound` but no modifiers?")
1044 }
1045
1046 fn recover_paren_lifetime(&mut self, lo: Span) -> PResult<'a, ()> {
1048 self.expect(exp!(CloseParen))?;
1049 let span = lo.to(self.prev_token.span);
1050 let sugg = errors::RemoveParens { lo, hi: self.prev_token.span };
1051
1052 self.dcx().emit_err(errors::ParenthesizedLifetime { span, sugg });
1053 Ok(())
1054 }
1055
1056 fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
1068 let modifier_lo = self.token.span;
1069 let constness = self.parse_bound_constness()?;
1070
1071 let asyncness = if self.token_uninterpolated_span().at_least_rust_2018()
1072 && self.eat_keyword(exp!(Async))
1073 {
1074 self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
1075 BoundAsyncness::Async(self.prev_token.span)
1076 } else if self.may_recover()
1077 && self.token_uninterpolated_span().is_rust_2015()
1078 && self.is_kw_followed_by_ident(kw::Async)
1079 {
1080 self.bump(); self.dcx().emit_err(errors::AsyncBoundModifierIn2015 {
1082 span: self.prev_token.span,
1083 help: HelpUseLatestEdition::new(),
1084 });
1085 self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
1086 BoundAsyncness::Async(self.prev_token.span)
1087 } else {
1088 BoundAsyncness::Normal
1089 };
1090 let modifier_hi = self.prev_token.span;
1091
1092 let polarity = if self.eat(exp!(Question)) {
1093 BoundPolarity::Maybe(self.prev_token.span)
1094 } else if self.eat(exp!(Bang)) {
1095 self.psess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);
1096 BoundPolarity::Negative(self.prev_token.span)
1097 } else {
1098 BoundPolarity::Positive
1099 };
1100
1101 match polarity {
1103 BoundPolarity::Positive => {
1104 }
1106 BoundPolarity::Maybe(polarity_span) | BoundPolarity::Negative(polarity_span) => {
1107 match (asyncness, constness) {
1108 (BoundAsyncness::Normal, BoundConstness::Never) => {
1109 }
1111 (_, _) => {
1112 let constness = constness.as_str();
1113 let asyncness = asyncness.as_str();
1114 let glue =
1115 if !constness.is_empty() && !asyncness.is_empty() { " " } else { "" };
1116 let modifiers_concatenated = format!("{constness}{glue}{asyncness}");
1117 self.dcx().emit_err(errors::PolarityAndModifiers {
1118 polarity_span,
1119 polarity: polarity.as_str(),
1120 modifiers_span: modifier_lo.to(modifier_hi),
1121 modifiers_concatenated,
1122 });
1123 }
1124 }
1125 }
1126 }
1127
1128 Ok(TraitBoundModifiers { constness, asyncness, polarity })
1129 }
1130
1131 pub fn parse_bound_constness(&mut self) -> PResult<'a, BoundConstness> {
1132 Ok(if self.eat(exp!(Tilde)) {
1135 let tilde = self.prev_token.span;
1136 self.expect_keyword(exp!(Const))?;
1137 let span = tilde.to(self.prev_token.span);
1138 self.psess.gated_spans.gate(sym::const_trait_impl, span);
1139 BoundConstness::Maybe(span)
1140 } else if self.check(exp!(OpenBracket))
1141 && self.look_ahead(1, |t| t.is_keyword(kw::Const))
1142 && self.look_ahead(2, |t| *t == token::CloseBracket)
1143 {
1144 let start = self.token.span;
1145 self.bump();
1146 self.expect_keyword(exp!(Const)).unwrap();
1147 self.bump();
1148 let span = start.to(self.prev_token.span);
1149 self.psess.gated_spans.gate(sym::const_trait_impl, span);
1150 BoundConstness::Maybe(span)
1151 } else if self.eat_keyword(exp!(Const)) {
1152 self.psess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span);
1153 BoundConstness::Always(self.prev_token.span)
1154 } else {
1155 BoundConstness::Never
1156 })
1157 }
1158
1159 fn parse_generic_ty_bound(
1167 &mut self,
1168 lo: Span,
1169 parens: ast::Parens,
1170 leading_token: &Token,
1171 ) -> PResult<'a, GenericBound> {
1172 let (mut lifetime_defs, binder_span) = self.parse_late_bound_lifetime_defs()?;
1173
1174 let modifiers_lo = self.token.span;
1175 let modifiers = self.parse_trait_bound_modifiers()?;
1176 let modifiers_span = modifiers_lo.to(self.prev_token.span);
1177
1178 if let Some(binder_span) = binder_span {
1179 match modifiers.polarity {
1180 BoundPolarity::Negative(polarity_span) | BoundPolarity::Maybe(polarity_span) => {
1181 self.dcx().emit_err(errors::BinderAndPolarity {
1182 binder_span,
1183 polarity_span,
1184 polarity: modifiers.polarity.as_str(),
1185 });
1186 }
1187 BoundPolarity::Positive => {}
1188 }
1189 }
1190
1191 if self.token.is_lifetime() {
1194 let _: ErrorGuaranteed = self.error_lt_bound_with_modifiers(modifiers, binder_span);
1195 return self.parse_generic_lt_bound(lo, parens);
1196 }
1197
1198 if let (more_lifetime_defs, Some(binder_span)) = self.parse_late_bound_lifetime_defs()? {
1199 lifetime_defs.extend(more_lifetime_defs);
1200 self.dcx().emit_err(errors::BinderBeforeModifiers { binder_span, modifiers_span });
1201 }
1202
1203 let mut path = if self.token.is_keyword(kw::Fn)
1204 && self.look_ahead(1, |t| *t == TokenKind::OpenParen)
1205 && let Some(path) = self.recover_path_from_fn()
1206 {
1207 path
1208 } else if !self.token.is_path_start() && self.token.can_begin_type() {
1209 let ty = self.parse_ty_no_plus()?;
1210 let mut err = self.dcx().struct_span_err(ty.span, "expected a trait, found type");
1212
1213 let path = if self.may_recover() {
1218 let (span, message, sugg, path, applicability) = match &ty.kind {
1219 TyKind::Ptr(..) | TyKind::Ref(..)
1220 if let TyKind::Path(_, path) = &ty.peel_refs().kind =>
1221 {
1222 (
1223 ty.span.until(path.span),
1224 "consider removing the indirection",
1225 "",
1226 path,
1227 Applicability::MaybeIncorrect,
1228 )
1229 }
1230 TyKind::ImplTrait(_, bounds)
1231 if let [GenericBound::Trait(tr, ..), ..] = bounds.as_slice() =>
1232 {
1233 (
1234 ty.span.until(tr.span),
1235 "use the trait bounds directly",
1236 "",
1237 &tr.trait_ref.path,
1238 Applicability::MachineApplicable,
1239 )
1240 }
1241 _ => return Err(err),
1242 };
1243
1244 err.span_suggestion_verbose(span, message, sugg, applicability);
1245
1246 path.clone()
1247 } else {
1248 return Err(err);
1249 };
1250
1251 err.emit();
1252
1253 path
1254 } else {
1255 self.parse_path(PathStyle::Type)?
1256 };
1257
1258 if self.may_recover() && self.token == TokenKind::OpenParen {
1259 self.recover_fn_trait_with_lifetime_params(&mut path, &mut lifetime_defs)?;
1260 }
1261
1262 if let ast::Parens::Yes = parens {
1263 if self.token.is_like_plus() && leading_token.is_keyword(kw::Dyn) {
1266 let bounds = vec![];
1267 self.parse_remaining_bounds(bounds, true)?;
1268 self.expect(exp!(CloseParen))?;
1269 self.dcx().emit_err(errors::IncorrectParensTraitBounds {
1270 span: vec![lo, self.prev_token.span],
1271 sugg: errors::IncorrectParensTraitBoundsSugg {
1272 wrong_span: leading_token.span.shrink_to_hi().to(lo),
1273 new_span: leading_token.span.shrink_to_lo(),
1274 },
1275 });
1276 } else {
1277 self.expect(exp!(CloseParen))?;
1278 }
1279 }
1280
1281 let poly_trait =
1282 PolyTraitRef::new(lifetime_defs, path, modifiers, lo.to(self.prev_token.span), parens);
1283 Ok(GenericBound::Trait(poly_trait))
1284 }
1285
1286 fn recover_path_from_fn(&mut self) -> Option<ast::Path> {
1288 let fn_token_span = self.token.span;
1289 self.bump();
1290 let args_lo = self.token.span;
1291 let snapshot = self.create_snapshot_for_diagnostic();
1292 match self.parse_fn_decl(|_| false, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
1293 Ok(decl) => {
1294 self.dcx().emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
1295 Some(ast::Path {
1296 span: fn_token_span.to(self.prev_token.span),
1297 segments: thin_vec![ast::PathSegment {
1298 ident: Ident::new(sym::Fn, fn_token_span),
1299 id: DUMMY_NODE_ID,
1300 args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs {
1301 span: args_lo.to(self.prev_token.span),
1302 inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(),
1303 inputs_span: args_lo.until(decl.output.span()),
1304 output: decl.output.clone(),
1305 }))),
1306 }],
1307 tokens: None,
1308 })
1309 }
1310 Err(diag) => {
1311 diag.cancel();
1312 self.restore_snapshot(snapshot);
1313 None
1314 }
1315 }
1316 }
1317
1318 pub(super) fn parse_late_bound_lifetime_defs(
1320 &mut self,
1321 ) -> PResult<'a, (ThinVec<GenericParam>, Option<Span>)> {
1322 if self.eat_keyword(exp!(For)) {
1323 let lo = self.token.span;
1324 self.expect_lt()?;
1325 let params = self.parse_generic_params()?;
1326 self.expect_gt()?;
1327 Ok((params, Some(lo.to(self.prev_token.span))))
1330 } else {
1331 Ok((ThinVec::new(), None))
1332 }
1333 }
1334
1335 fn recover_fn_trait_with_lifetime_params(
1339 &mut self,
1340 fn_path: &mut ast::Path,
1341 lifetime_defs: &mut ThinVec<GenericParam>,
1342 ) -> PResult<'a, ()> {
1343 let fn_path_segment = fn_path.segments.last_mut().unwrap();
1344 let generic_args = if let Some(p_args) = &fn_path_segment.args {
1345 *p_args.clone()
1346 } else {
1347 return Ok(());
1350 };
1351 let lifetimes =
1352 if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) =
1353 &generic_args
1354 {
1355 args.into_iter()
1356 .filter_map(|arg| {
1357 if let ast::AngleBracketedArg::Arg(generic_arg) = arg
1358 && let ast::GenericArg::Lifetime(lifetime) = generic_arg
1359 {
1360 Some(lifetime)
1361 } else {
1362 None
1363 }
1364 })
1365 .collect()
1366 } else {
1367 Vec::new()
1368 };
1369 if lifetimes.is_empty() {
1371 return Ok(());
1372 }
1373
1374 let inputs_lo = self.token.span;
1376 let inputs: ThinVec<_> =
1377 self.parse_fn_params(|_| false)?.into_iter().map(|input| input.ty).collect();
1378 let inputs_span = inputs_lo.to(self.prev_token.span);
1379 let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
1380 let args = ast::ParenthesizedArgs {
1381 span: fn_path_segment.span().to(self.prev_token.span),
1382 inputs,
1383 inputs_span,
1384 output,
1385 }
1386 .into();
1387 *fn_path_segment = ast::PathSegment {
1388 ident: fn_path_segment.ident,
1389 args: Some(args),
1390 id: ast::DUMMY_NODE_ID,
1391 };
1392
1393 let mut generic_params = lifetimes
1395 .iter()
1396 .map(|lt| GenericParam {
1397 id: lt.id,
1398 ident: lt.ident,
1399 attrs: ast::AttrVec::new(),
1400 bounds: Vec::new(),
1401 is_placeholder: false,
1402 kind: ast::GenericParamKind::Lifetime,
1403 colon_span: None,
1404 })
1405 .collect::<ThinVec<GenericParam>>();
1406 lifetime_defs.append(&mut generic_params);
1407
1408 let generic_args_span = generic_args.span();
1409 let snippet = format!(
1410 "for<{}> ",
1411 lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),
1412 );
1413 let before_fn_path = fn_path.span.shrink_to_lo();
1414 self.dcx()
1415 .struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters")
1416 .with_multipart_suggestion(
1417 "consider using a higher-ranked trait bound instead",
1418 vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
1419 Applicability::MaybeIncorrect,
1420 )
1421 .emit();
1422 Ok(())
1423 }
1424
1425 pub(super) fn check_lifetime(&mut self) -> bool {
1426 self.expected_token_types.insert(TokenType::Lifetime);
1427 self.token.is_lifetime()
1428 }
1429
1430 pub(super) fn expect_lifetime(&mut self) -> Lifetime {
1432 if let Some((ident, is_raw)) = self.token.lifetime() {
1433 if matches!(is_raw, IdentIsRaw::No)
1434 && ident.without_first_quote().is_reserved()
1435 && ![kw::UnderscoreLifetime, kw::StaticLifetime].contains(&ident.name)
1436 {
1437 self.dcx().emit_err(errors::KeywordLifetime { span: ident.span });
1438 }
1439
1440 self.bump();
1441 Lifetime { ident, id: ast::DUMMY_NODE_ID }
1442 } else {
1443 self.dcx().span_bug(self.token.span, "not a lifetime")
1444 }
1445 }
1446
1447 pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> P<Ty> {
1448 P(Ty { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
1449 }
1450}