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