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, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnRetTy,
6 GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability,
7 Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty,
8 TyKind, UnsafeBinderTy,
9};
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, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
17 FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg,
18 HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
19 NestedCVariadicType, ReturnTypesUseThinArrow,
20};
21use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
22
23#[derive(Copy, Clone, PartialEq)]
29pub(super) enum AllowPlus {
30 Yes,
31 No,
32}
33
34#[derive(PartialEq)]
35pub(super) enum RecoverQPath {
36 Yes,
37 No,
38}
39
40pub(super) enum RecoverQuestionMark {
41 Yes,
42 No,
43}
44
45#[derive(Copy, Clone, PartialEq)]
56pub(super) enum RecoverReturnSign {
57 Yes,
58 OnlyFatArrow,
59 No,
60}
61
62impl RecoverReturnSign {
63 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}
75
76#[derive(PartialEq)]
78enum AllowCVariadic {
79 Yes,
80 No,
81}
82
83fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
89 t == &token::PathSep || t == &token::Lt || t == &token::Shl
90}
91
92fn can_begin_dyn_bound_in_edition_2015(t: &Token) -> bool {
93 t.is_path_start()
98 || t.is_lifetime()
99 || t == &TokenKind::Question
100 || t.is_keyword(kw::For)
101 || t == &TokenKind::OpenParen
102}
103
104impl<'a> Parser<'a> {
105 pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
107 self.parse_ty_common(
108 AllowPlus::Yes,
109 AllowCVariadic::No,
110 RecoverQPath::Yes,
111 RecoverReturnSign::Yes,
112 None,
113 RecoverQuestionMark::Yes,
114 )
115 }
116
117 pub(super) fn parse_ty_with_generics_recovery(
118 &mut self,
119 ty_params: &Generics,
120 ) -> PResult<'a, P<Ty>> {
121 self.parse_ty_common(
122 AllowPlus::Yes,
123 AllowCVariadic::No,
124 RecoverQPath::Yes,
125 RecoverReturnSign::Yes,
126 Some(ty_params),
127 RecoverQuestionMark::Yes,
128 )
129 }
130
131 pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> {
135 self.parse_ty_common(
136 AllowPlus::Yes,
137 AllowCVariadic::Yes,
138 RecoverQPath::Yes,
139 RecoverReturnSign::Yes,
140 None,
141 RecoverQuestionMark::Yes,
142 )
143 }
144
145 pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
152 self.parse_ty_common(
153 AllowPlus::No,
154 AllowCVariadic::No,
155 RecoverQPath::Yes,
156 RecoverReturnSign::Yes,
157 None,
158 RecoverQuestionMark::Yes,
159 )
160 }
161
162 pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, P<Ty>> {
165 self.parse_ty_common(
166 AllowPlus::No,
167 AllowCVariadic::No,
168 RecoverQPath::Yes,
169 RecoverReturnSign::Yes,
170 None,
171 RecoverQuestionMark::No,
172 )
173 }
174
175 pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
176 self.parse_ty_common(
177 AllowPlus::Yes,
178 AllowCVariadic::No,
179 RecoverQPath::Yes,
180 RecoverReturnSign::Yes,
181 None,
182 RecoverQuestionMark::No,
183 )
184 }
185
186 pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
189 self.parse_ty_common(
190 AllowPlus::Yes,
191 AllowCVariadic::No,
192 RecoverQPath::Yes,
193 RecoverReturnSign::OnlyFatArrow,
194 None,
195 RecoverQuestionMark::Yes,
196 )
197 }
198
199 pub(super) fn parse_ret_ty(
201 &mut self,
202 allow_plus: AllowPlus,
203 recover_qpath: RecoverQPath,
204 recover_return_sign: RecoverReturnSign,
205 ) -> PResult<'a, FnRetTy> {
206 let lo = self.prev_token.span;
207 Ok(if self.eat(exp!(RArrow)) {
208 let ty = self.parse_ty_common(
210 allow_plus,
211 AllowCVariadic::No,
212 recover_qpath,
213 recover_return_sign,
214 None,
215 RecoverQuestionMark::Yes,
216 )?;
217 FnRetTy::Ty(ty)
218 } else if recover_return_sign.can_recover(&self.token.kind) {
219 self.bump();
222 self.dcx().emit_err(ReturnTypesUseThinArrow {
223 span: self.prev_token.span,
224 suggestion: lo.between(self.token.span),
225 });
226 let ty = self.parse_ty_common(
227 allow_plus,
228 AllowCVariadic::No,
229 recover_qpath,
230 recover_return_sign,
231 None,
232 RecoverQuestionMark::Yes,
233 )?;
234 FnRetTy::Ty(ty)
235 } else {
236 FnRetTy::Default(self.prev_token.span.shrink_to_hi())
237 })
238 }
239
240 fn parse_ty_common(
241 &mut self,
242 allow_plus: AllowPlus,
243 allow_c_variadic: AllowCVariadic,
244 recover_qpath: RecoverQPath,
245 recover_return_sign: RecoverReturnSign,
246 ty_generics: Option<&Generics>,
247 recover_question_mark: RecoverQuestionMark,
248 ) -> PResult<'a, P<Ty>> {
249 let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
250 maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
251
252 if let Some(ty) = self.eat_metavar_seq_with_matcher(
253 |mv_kind| matches!(mv_kind, MetaVarKind::Ty { .. }),
254 |this| this.parse_ty_no_question_mark_recover(),
255 ) {
256 return Ok(ty);
257 }
258
259 let lo = self.token.span;
260 let mut impl_dyn_multi = false;
261 let kind = if self.check(exp!(OpenParen)) {
262 self.parse_ty_tuple_or_parens(lo, allow_plus)?
263 } else if self.eat(exp!(Bang)) {
264 TyKind::Never
266 } else if self.eat(exp!(Star)) {
267 self.parse_ty_ptr()?
268 } else if self.eat(exp!(OpenBracket)) {
269 self.parse_array_or_slice_ty()?
270 } else if self.check(exp!(And)) || self.check(exp!(AndAnd)) {
271 self.expect_and()?;
273 self.parse_borrowed_pointee()?
274 } else if self.eat_keyword_noexpect(kw::Typeof) {
275 self.parse_typeof_ty()?
276 } else if self.eat_keyword(exp!(Underscore)) {
277 TyKind::Infer
279 } else if self.check_fn_front_matter(false, Case::Sensitive) {
280 self.parse_ty_bare_fn(lo, ThinVec::new(), None, recover_return_sign)?
282 } else if self.check_keyword(exp!(For)) {
283 let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?;
287 if self.check_fn_front_matter(false, Case::Sensitive) {
288 self.parse_ty_bare_fn(
289 lo,
290 lifetime_defs,
291 Some(self.prev_token.span.shrink_to_lo()),
292 recover_return_sign,
293 )?
294 } else {
295 if self.may_recover()
297 && (self.eat_keyword_noexpect(kw::Impl) || self.eat_keyword_noexpect(kw::Dyn))
298 {
299 let kw = self.prev_token.ident().unwrap().0;
300 let removal_span = kw.span.with_hi(self.token.span.lo());
301 let path = self.parse_path(PathStyle::Type)?;
302 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
303 let kind =
304 self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?;
305 let err = self.dcx().create_err(errors::TransposeDynOrImpl {
306 span: kw.span,
307 kw: kw.name.as_str(),
308 sugg: errors::TransposeDynOrImplSugg {
309 removal_span,
310 insertion_span: lo.shrink_to_lo(),
311 kw: kw.name.as_str(),
312 },
313 });
314
315 let kind = match (kind, kw.name) {
318 (TyKind::TraitObject(bounds, _), kw::Dyn) => {
319 TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)
320 }
321 (TyKind::TraitObject(bounds, _), kw::Impl) => {
322 TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)
323 }
324 _ => return Err(err),
325 };
326 err.emit();
327 kind
328 } else {
329 let path = self.parse_path(PathStyle::Type)?;
330 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
331 self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?
332 }
333 }
334 } else if self.eat_keyword(exp!(Impl)) {
335 self.parse_impl_ty(&mut impl_dyn_multi)?
336 } else if self.is_explicit_dyn_type() {
337 self.parse_dyn_ty(&mut impl_dyn_multi)?
338 } else if self.eat_lt() {
339 let (qself, path) = self.parse_qpath(PathStyle::Type)?;
341 TyKind::Path(Some(qself), path)
342 } else if self.check_path() {
343 self.parse_path_start_ty(lo, allow_plus, ty_generics)?
344 } else if self.can_begin_bound() {
345 self.parse_bare_trait_object(lo, allow_plus)?
346 } else if self.eat(exp!(DotDotDot)) {
347 match allow_c_variadic {
348 AllowCVariadic::Yes => TyKind::CVarArgs,
349 AllowCVariadic::No => {
350 let guar = self.dcx().emit_err(NestedCVariadicType { span: lo });
354 TyKind::Err(guar)
355 }
356 }
357 } else if self.check_keyword(exp!(Unsafe))
358 && self.look_ahead(1, |tok| tok.kind == token::Lt)
359 {
360 self.parse_unsafe_binder_ty()?
361 } else {
362 let msg = format!("expected type, found {}", super::token_descr(&self.token));
363 let mut err = self.dcx().struct_span_err(lo, msg);
364 err.span_label(lo, "expected type");
365 return Err(err);
366 };
367
368 let span = lo.to(self.prev_token.span);
369 let mut ty = self.mk_ty(span, kind);
370
371 match allow_plus {
373 AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?,
374 AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty),
375 }
376 if let RecoverQuestionMark::Yes = recover_question_mark {
377 ty = self.maybe_recover_from_question_mark(ty);
378 }
379 if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
380 }
381
382 fn parse_unsafe_binder_ty(&mut self) -> PResult<'a, TyKind> {
383 let lo = self.token.span;
384 assert!(self.eat_keyword(exp!(Unsafe)));
385 self.expect_lt()?;
386 let generic_params = self.parse_generic_params()?;
387 self.expect_gt()?;
388 let inner_ty = self.parse_ty()?;
389 let span = lo.to(self.prev_token.span);
390 self.psess.gated_spans.gate(sym::unsafe_binders, span);
391
392 Ok(TyKind::UnsafeBinder(P(UnsafeBinderTy { generic_params, inner_ty })))
393 }
394
395 fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
399 let mut trailing_plus = false;
400 let (ts, trailing) = self.parse_paren_comma_seq(|p| {
401 let ty = p.parse_ty()?;
402 trailing_plus = p.prev_token == TokenKind::Plus;
403 Ok(ty)
404 })?;
405
406 if ts.len() == 1 && matches!(trailing, Trailing::No) {
407 let ty = ts.into_iter().next().unwrap().into_inner();
408 let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus();
409 match ty.kind {
410 TyKind::Path(None, path) if maybe_bounds => {
412 self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true)
413 }
414 TyKind::TraitObject(bounds, TraitObjectSyntax::None)
418 if maybe_bounds && bounds.len() == 1 && !trailing_plus =>
419 {
420 self.parse_remaining_bounds(bounds, true)
421 }
422 _ => Ok(TyKind::Paren(P(ty))),
424 }
425 } else {
426 Ok(TyKind::Tup(ts))
427 }
428 }
429
430 fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
431 if self.token.is_lifetime() && !self.look_ahead(1, |t| t.is_like_plus()) {
433 if self.psess.edition.at_least_rust_2021() {
437 let lt = self.expect_lifetime();
438 let mut err = self.dcx().struct_span_err(lo, "expected type, found lifetime");
439 err.span_label(lo, "expected type");
440 return Ok(match self.maybe_recover_ref_ty_no_leading_ampersand(lt, lo, err) {
441 Ok(ref_ty) => ref_ty,
442 Err(err) => TyKind::Err(err.emit()),
443 });
444 }
445
446 self.dcx().emit_err(NeedPlusAfterTraitObjectLifetime {
447 span: lo,
448 suggestion: lo.shrink_to_hi(),
449 });
450 }
451 Ok(TyKind::TraitObject(
452 self.parse_generic_bounds_common(allow_plus)?,
453 TraitObjectSyntax::None,
454 ))
455 }
456
457 fn maybe_recover_ref_ty_no_leading_ampersand<'cx>(
458 &mut self,
459 lt: Lifetime,
460 lo: Span,
461 mut err: Diag<'cx>,
462 ) -> Result<TyKind, Diag<'cx>> {
463 if !self.may_recover() {
464 return Err(err);
465 }
466 let snapshot = self.create_snapshot_for_diagnostic();
467 let mutbl = self.parse_mutability();
468 match self.parse_ty_no_plus() {
469 Ok(ty) => {
470 err.span_suggestion_verbose(
471 lo.shrink_to_lo(),
472 "you might have meant to write a reference type here",
473 "&",
474 Applicability::MaybeIncorrect,
475 );
476 err.emit();
477 Ok(TyKind::Ref(Some(lt), MutTy { ty, mutbl }))
478 }
479 Err(diag) => {
480 diag.cancel();
481 self.restore_snapshot(snapshot);
482 Err(err)
483 }
484 }
485 }
486
487 fn parse_remaining_bounds_path(
488 &mut self,
489 generic_params: ThinVec<GenericParam>,
490 path: ast::Path,
491 lo: Span,
492 parse_plus: bool,
493 ) -> PResult<'a, TyKind> {
494 let poly_trait_ref = PolyTraitRef::new(
495 generic_params,
496 path,
497 TraitBoundModifiers::NONE,
498 lo.to(self.prev_token.span),
499 );
500 let bounds = vec![GenericBound::Trait(poly_trait_ref)];
501 self.parse_remaining_bounds(bounds, parse_plus)
502 }
503
504 fn parse_remaining_bounds(
506 &mut self,
507 mut bounds: GenericBounds,
508 plus: bool,
509 ) -> PResult<'a, TyKind> {
510 if plus {
511 self.eat_plus(); bounds.append(&mut self.parse_generic_bounds()?);
513 }
514 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
515 }
516
517 fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
519 let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
520 let span = self.prev_token.span;
521 self.dcx().emit_err(ExpectedMutOrConstInRawPointerType {
522 span,
523 after_asterisk: span.shrink_to_hi(),
524 });
525 Mutability::Not
526 });
527 let ty = self.parse_ty_no_plus()?;
528 Ok(TyKind::Ptr(MutTy { ty, mutbl }))
529 }
530
531 fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {
534 let elt_ty = match self.parse_ty() {
535 Ok(ty) => ty,
536 Err(err)
537 if self.look_ahead(1, |t| *t == token::CloseBracket)
538 | self.look_ahead(1, |t| *t == token::Semi) =>
539 {
540 self.bump();
542 let guar = err.emit();
543 self.mk_ty(self.prev_token.span, TyKind::Err(guar))
544 }
545 Err(err) => return Err(err),
546 };
547
548 let ty = if self.eat(exp!(Semi)) {
549 let mut length = self.parse_expr_anon_const()?;
550 if let Err(e) = self.expect(exp!(CloseBracket)) {
551 self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
553 self.expect(exp!(CloseBracket))?;
554 }
555 TyKind::Array(elt_ty, length)
556 } else {
557 self.expect(exp!(CloseBracket))?;
558 TyKind::Slice(elt_ty)
559 };
560
561 Ok(ty)
562 }
563
564 fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
565 let and_span = self.prev_token.span;
566 let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());
567 let (pinned, mut mutbl) = match self.parse_pin_and_mut() {
568 Some(pin_mut) => pin_mut,
569 None => (Pinnedness::Not, self.parse_mutability()),
570 };
571 if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
572 if !self.look_ahead(1, |t| t.is_like_plus()) {
578 let lifetime_span = self.token.span;
579 let span = and_span.to(lifetime_span);
580
581 let (suggest_lifetime, snippet) =
582 if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
583 (Some(span), lifetime_src)
584 } else {
585 (None, String::new())
586 };
587 self.dcx().emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });
588
589 opt_lifetime = Some(self.expect_lifetime());
590 }
591 } else if self.token.is_keyword(kw::Dyn)
592 && mutbl == Mutability::Not
593 && self.look_ahead(1, |t| t.is_keyword(kw::Mut))
594 {
595 let span = and_span.to(self.look_ahead(1, |t| t.span));
597 self.dcx().emit_err(DynAfterMut { span });
598
599 mutbl = Mutability::Mut;
601 let (dyn_tok, dyn_tok_sp) = (self.token, self.token_spacing);
602 self.bump();
603 self.bump_with((dyn_tok, dyn_tok_sp));
604 }
605 let ty = self.parse_ty_no_plus()?;
606 Ok(match pinned {
607 Pinnedness::Not => TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }),
608 Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl }),
609 })
610 }
611
612 pub(crate) fn parse_pin_and_mut(&mut self) -> Option<(Pinnedness, Mutability)> {
616 if self.token.is_ident_named(sym::pin) {
617 let result = self.look_ahead(1, |token| {
618 if token.is_keyword(kw::Const) {
619 Some((Pinnedness::Pinned, Mutability::Not))
620 } else if token.is_keyword(kw::Mut) {
621 Some((Pinnedness::Pinned, Mutability::Mut))
622 } else {
623 None
624 }
625 });
626 if result.is_some() {
627 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
628 self.bump();
629 self.bump();
630 }
631 result
632 } else {
633 None
634 }
635 }
636
637 fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> {
640 self.expect(exp!(OpenParen))?;
641 let expr = self.parse_expr_anon_const()?;
642 self.expect(exp!(CloseParen))?;
643 Ok(TyKind::Typeof(expr))
644 }
645
646 fn parse_ty_bare_fn(
656 &mut self,
657 lo: Span,
658 mut params: ThinVec<GenericParam>,
659 param_insertion_point: Option<Span>,
660 recover_return_sign: RecoverReturnSign,
661 ) -> PResult<'a, TyKind> {
662 let inherited_vis = rustc_ast::Visibility {
663 span: rustc_span::DUMMY_SP,
664 kind: rustc_ast::VisibilityKind::Inherited,
665 tokens: None,
666 };
667 let span_start = self.token.span;
668 let ast::FnHeader { ext, safety, constness, coroutine_kind } =
669 self.parse_fn_front_matter(&inherited_vis, Case::Sensitive)?;
670 let fn_start_lo = self.prev_token.span.lo();
671 if self.may_recover() && self.token == TokenKind::Lt {
672 self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
673 }
674 let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
675 let whole_span = lo.to(self.prev_token.span);
676
677 if let ast::Const::Yes(const_span) = constness {
686 let next_token_lo = if let Some(
687 ast::CoroutineKind::Async { span, .. }
688 | ast::CoroutineKind::Gen { span, .. }
689 | ast::CoroutineKind::AsyncGen { span, .. },
690 ) = coroutine_kind
691 {
692 span.lo()
693 } else if let ast::Safety::Unsafe(span) | ast::Safety::Safe(span) = safety {
694 span.lo()
695 } else if let ast::Extern::Implicit(span) | ast::Extern::Explicit(_, span) = ext {
696 span.lo()
697 } else {
698 fn_start_lo
699 };
700 let sugg_span = const_span.with_hi(next_token_lo);
701 self.dcx().emit_err(FnPointerCannotBeConst {
702 span: whole_span,
703 qualifier: const_span,
704 suggestion: sugg_span,
705 });
706 }
707 if let Some(ast::CoroutineKind::Async { span: async_span, .. }) = coroutine_kind {
708 let next_token_lo = if let ast::Safety::Unsafe(span) | ast::Safety::Safe(span) = safety
709 {
710 span.lo()
711 } else if let ast::Extern::Implicit(span) | ast::Extern::Explicit(_, span) = ext {
712 span.lo()
713 } else {
714 fn_start_lo
715 };
716 let sugg_span = async_span.with_hi(next_token_lo);
717 self.dcx().emit_err(FnPointerCannotBeAsync {
718 span: whole_span,
719 qualifier: async_span,
720 suggestion: sugg_span,
721 });
722 }
723 let decl_span = span_start.to(self.prev_token.span);
725 Ok(TyKind::BareFn(P(BareFnTy { ext, safety, generic_params: params, decl, decl_span })))
726 }
727
728 fn recover_fn_ptr_with_generics(
730 &mut self,
731 lo: Span,
732 params: &mut ThinVec<GenericParam>,
733 param_insertion_point: Option<Span>,
734 ) -> PResult<'a, ()> {
735 let generics = self.parse_generics()?;
736 let arity = generics.params.len();
737
738 let mut lifetimes: ThinVec<_> = generics
739 .params
740 .into_iter()
741 .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime))
742 .collect();
743
744 let sugg = if !lifetimes.is_empty() {
745 let snippet =
746 lifetimes.iter().map(|param| param.ident.as_str()).intersperse(", ").collect();
747
748 let (left, snippet) = if let Some(span) = param_insertion_point {
749 (span, if params.is_empty() { snippet } else { format!(", {snippet}") })
750 } else {
751 (lo.shrink_to_lo(), format!("for<{snippet}> "))
752 };
753
754 Some(FnPtrWithGenericsSugg {
755 left,
756 snippet,
757 right: generics.span,
758 arity,
759 for_param_list_exists: param_insertion_point.is_some(),
760 })
761 } else {
762 None
763 };
764
765 self.dcx().emit_err(FnPtrWithGenerics { span: generics.span, sugg });
766 params.append(&mut lifetimes);
767 Ok(())
768 }
769
770 fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
772 if self.token.is_lifetime() {
773 self.look_ahead(1, |t| {
774 if let token::Ident(sym, _) = t.kind {
775 self.dcx().emit_err(errors::MissingPlusBounds {
778 span: self.token.span,
779 hi: self.token.span.shrink_to_hi(),
780 sym,
781 });
782 }
783 })
784 }
785
786 let bounds = self.parse_generic_bounds()?;
788
789 *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
790
791 Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))
792 }
793
794 fn parse_precise_capturing_args(
795 &mut self,
796 ) -> PResult<'a, (ThinVec<PreciseCapturingArg>, Span)> {
797 let lo = self.token.span;
798 self.expect_lt()?;
799 let (args, _, _) = self.parse_seq_to_before_tokens(
800 &[exp!(Gt)],
801 &[&TokenKind::Ge, &TokenKind::Shr, &TokenKind::Shr],
802 SeqSep::trailing_allowed(exp!(Comma)),
803 |self_| {
804 if self_.check_keyword(exp!(SelfUpper)) {
805 self_.bump();
806 Ok(PreciseCapturingArg::Arg(
807 ast::Path::from_ident(self_.prev_token.ident().unwrap().0),
808 DUMMY_NODE_ID,
809 ))
810 } else if self_.check_ident() {
811 Ok(PreciseCapturingArg::Arg(
812 ast::Path::from_ident(self_.parse_ident()?),
813 DUMMY_NODE_ID,
814 ))
815 } else if self_.check_lifetime() {
816 Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))
817 } else {
818 self_.unexpected_any()
819 }
820 },
821 )?;
822 self.expect_gt()?;
823 Ok((args, lo.to(self.prev_token.span)))
824 }
825
826 fn is_explicit_dyn_type(&mut self) -> bool {
828 self.check_keyword(exp!(Dyn))
829 && (self.token_uninterpolated_span().at_least_rust_2018()
830 || self.look_ahead(1, |t| {
831 (can_begin_dyn_bound_in_edition_2015(t) || *t == TokenKind::Star)
832 && !can_continue_type_after_non_fn_ident(t)
833 }))
834 }
835
836 fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
840 let lo = self.token.span;
841 self.bump(); let syntax = if self.eat(exp!(Star)) {
845 self.psess.gated_spans.gate(sym::dyn_star, lo.to(self.prev_token.span));
846 TraitObjectSyntax::DynStar
847 } else {
848 TraitObjectSyntax::Dyn
849 };
850
851 let bounds = self.parse_generic_bounds()?;
853 *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
854 Ok(TyKind::TraitObject(bounds, syntax))
855 }
856
857 fn parse_path_start_ty(
864 &mut self,
865 lo: Span,
866 allow_plus: AllowPlus,
867 ty_generics: Option<&Generics>,
868 ) -> PResult<'a, TyKind> {
869 let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
871 if self.eat(exp!(Bang)) {
872 Ok(TyKind::MacCall(P(MacCall { path, args: self.parse_delim_args()? })))
874 } else if allow_plus == AllowPlus::Yes && self.check_plus() {
875 self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true)
877 } else {
878 Ok(TyKind::Path(None, path))
880 }
881 }
882
883 pub(super) fn parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds> {
884 self.parse_generic_bounds_common(AllowPlus::Yes)
885 }
886
887 fn parse_generic_bounds_common(&mut self, allow_plus: AllowPlus) -> PResult<'a, GenericBounds> {
891 let mut bounds = Vec::new();
892
893 while self.can_begin_bound()
899 || (self.may_recover()
900 && (self.token.can_begin_type()
901 || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))))
902 {
903 if self.token.is_keyword(kw::Dyn) {
904 self.bump();
906 self.dcx().emit_err(InvalidDynKeyword {
907 span: self.prev_token.span,
908 suggestion: self.prev_token.span.until(self.token.span),
909 });
910 }
911 bounds.push(self.parse_generic_bound()?);
912 if allow_plus == AllowPlus::No || !self.eat_plus() {
913 break;
914 }
915 }
916
917 Ok(bounds)
918 }
919
920 fn can_begin_bound(&mut self) -> bool {
922 self.check_path()
923 || self.check_lifetime()
924 || self.check(exp!(Bang))
925 || self.check(exp!(Question))
926 || self.check(exp!(Tilde))
927 || self.check_keyword(exp!(For))
928 || self.check(exp!(OpenParen))
929 || self.check_keyword(exp!(Const))
930 || self.check_keyword(exp!(Async))
931 || self.check_keyword(exp!(Use))
932 }
933
934 fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
939 let lo = self.token.span;
940 let leading_token = self.prev_token;
941 let has_parens = self.eat(exp!(OpenParen));
942
943 let bound = if self.token.is_lifetime() {
944 self.parse_generic_lt_bound(lo, has_parens)?
945 } else if self.eat_keyword(exp!(Use)) {
946 let use_span = self.prev_token.span;
950 let (args, args_span) = self.parse_precise_capturing_args()?;
951 GenericBound::Use(args, use_span.to(args_span))
952 } else {
953 self.parse_generic_ty_bound(lo, has_parens, &leading_token)?
954 };
955
956 Ok(bound)
957 }
958
959 fn parse_generic_lt_bound(&mut self, lo: Span, has_parens: bool) -> PResult<'a, GenericBound> {
964 let lt = self.expect_lifetime();
965 let bound = GenericBound::Outlives(lt);
966 if has_parens {
967 self.recover_paren_lifetime(lo)?;
970 }
971 Ok(bound)
972 }
973
974 fn error_lt_bound_with_modifiers(
976 &self,
977 modifiers: TraitBoundModifiers,
978 binder_span: Option<Span>,
979 ) -> ErrorGuaranteed {
980 let TraitBoundModifiers { constness, asyncness, polarity } = modifiers;
981
982 match constness {
983 BoundConstness::Never => {}
984 BoundConstness::Always(span) | BoundConstness::Maybe(span) => {
985 return self
986 .dcx()
987 .emit_err(errors::ModifierLifetime { span, modifier: constness.as_str() });
988 }
989 }
990
991 match polarity {
992 BoundPolarity::Positive => {}
993 BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => {
994 return self
995 .dcx()
996 .emit_err(errors::ModifierLifetime { span, modifier: polarity.as_str() });
997 }
998 }
999
1000 match asyncness {
1001 BoundAsyncness::Normal => {}
1002 BoundAsyncness::Async(span) => {
1003 return self
1004 .dcx()
1005 .emit_err(errors::ModifierLifetime { span, modifier: asyncness.as_str() });
1006 }
1007 }
1008
1009 if let Some(span) = binder_span {
1010 return self.dcx().emit_err(errors::ModifierLifetime { span, modifier: "for<...>" });
1011 }
1012
1013 unreachable!("lifetime bound intercepted in `parse_generic_ty_bound` but no modifiers?")
1014 }
1015
1016 fn recover_paren_lifetime(&mut self, lo: Span) -> PResult<'a, ()> {
1018 self.expect(exp!(CloseParen))?;
1019 let span = lo.to(self.prev_token.span);
1020 let sugg = errors::RemoveParens { lo, hi: self.prev_token.span };
1021
1022 self.dcx().emit_err(errors::ParenthesizedLifetime { span, sugg });
1023 Ok(())
1024 }
1025
1026 fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
1038 let modifier_lo = self.token.span;
1039 let constness = if self.eat(exp!(Tilde)) {
1040 let tilde = self.prev_token.span;
1041 self.expect_keyword(exp!(Const))?;
1042 let span = tilde.to(self.prev_token.span);
1043 self.psess.gated_spans.gate(sym::const_trait_impl, span);
1044 BoundConstness::Maybe(span)
1045 } else if self.eat_keyword(exp!(Const)) {
1046 self.psess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span);
1047 BoundConstness::Always(self.prev_token.span)
1048 } else {
1049 BoundConstness::Never
1050 };
1051
1052 let asyncness = if self.token_uninterpolated_span().at_least_rust_2018()
1053 && self.eat_keyword(exp!(Async))
1054 {
1055 self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
1056 BoundAsyncness::Async(self.prev_token.span)
1057 } else if self.may_recover()
1058 && self.token_uninterpolated_span().is_rust_2015()
1059 && self.is_kw_followed_by_ident(kw::Async)
1060 {
1061 self.bump(); self.dcx().emit_err(errors::AsyncBoundModifierIn2015 {
1063 span: self.prev_token.span,
1064 help: HelpUseLatestEdition::new(),
1065 });
1066 self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
1067 BoundAsyncness::Async(self.prev_token.span)
1068 } else {
1069 BoundAsyncness::Normal
1070 };
1071 let modifier_hi = self.prev_token.span;
1072
1073 let polarity = if self.eat(exp!(Question)) {
1074 BoundPolarity::Maybe(self.prev_token.span)
1075 } else if self.eat(exp!(Bang)) {
1076 self.psess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);
1077 BoundPolarity::Negative(self.prev_token.span)
1078 } else {
1079 BoundPolarity::Positive
1080 };
1081
1082 match polarity {
1084 BoundPolarity::Positive => {
1085 }
1087 BoundPolarity::Maybe(polarity_span) | BoundPolarity::Negative(polarity_span) => {
1088 match (asyncness, constness) {
1089 (BoundAsyncness::Normal, BoundConstness::Never) => {
1090 }
1092 (_, _) => {
1093 let constness = constness.as_str();
1094 let asyncness = asyncness.as_str();
1095 let glue =
1096 if !constness.is_empty() && !asyncness.is_empty() { " " } else { "" };
1097 let modifiers_concatenated = format!("{constness}{glue}{asyncness}");
1098 self.dcx().emit_err(errors::PolarityAndModifiers {
1099 polarity_span,
1100 polarity: polarity.as_str(),
1101 modifiers_span: modifier_lo.to(modifier_hi),
1102 modifiers_concatenated,
1103 });
1104 }
1105 }
1106 }
1107 }
1108
1109 Ok(TraitBoundModifiers { constness, asyncness, polarity })
1110 }
1111
1112 fn parse_generic_ty_bound(
1120 &mut self,
1121 lo: Span,
1122 has_parens: bool,
1123 leading_token: &Token,
1124 ) -> PResult<'a, GenericBound> {
1125 let (mut lifetime_defs, binder_span) = self.parse_late_bound_lifetime_defs()?;
1126
1127 let modifiers_lo = self.token.span;
1128 let modifiers = self.parse_trait_bound_modifiers()?;
1129 let modifiers_span = modifiers_lo.to(self.prev_token.span);
1130
1131 if let Some(binder_span) = binder_span {
1132 match modifiers.polarity {
1133 BoundPolarity::Negative(polarity_span) | BoundPolarity::Maybe(polarity_span) => {
1134 self.dcx().emit_err(errors::BinderAndPolarity {
1135 binder_span,
1136 polarity_span,
1137 polarity: modifiers.polarity.as_str(),
1138 });
1139 }
1140 BoundPolarity::Positive => {}
1141 }
1142 }
1143
1144 if self.token.is_lifetime() {
1147 let _: ErrorGuaranteed = self.error_lt_bound_with_modifiers(modifiers, binder_span);
1148 return self.parse_generic_lt_bound(lo, has_parens);
1149 }
1150
1151 if let (more_lifetime_defs, Some(binder_span)) = self.parse_late_bound_lifetime_defs()? {
1152 lifetime_defs.extend(more_lifetime_defs);
1153 self.dcx().emit_err(errors::BinderBeforeModifiers { binder_span, modifiers_span });
1154 }
1155
1156 let mut path = if self.token.is_keyword(kw::Fn)
1157 && self.look_ahead(1, |t| *t == TokenKind::OpenParen)
1158 && let Some(path) = self.recover_path_from_fn()
1159 {
1160 path
1161 } else if !self.token.is_path_start() && self.token.can_begin_type() {
1162 let ty = self.parse_ty_no_plus()?;
1163 let mut err = self.dcx().struct_span_err(ty.span, "expected a trait, found type");
1165
1166 let path = if self.may_recover() {
1171 let (span, message, sugg, path, applicability) = match &ty.kind {
1172 TyKind::Ptr(..) | TyKind::Ref(..)
1173 if let TyKind::Path(_, path) = &ty.peel_refs().kind =>
1174 {
1175 (
1176 ty.span.until(path.span),
1177 "consider removing the indirection",
1178 "",
1179 path,
1180 Applicability::MaybeIncorrect,
1181 )
1182 }
1183 TyKind::ImplTrait(_, bounds)
1184 if let [GenericBound::Trait(tr, ..), ..] = bounds.as_slice() =>
1185 {
1186 (
1187 ty.span.until(tr.span),
1188 "use the trait bounds directly",
1189 "",
1190 &tr.trait_ref.path,
1191 Applicability::MachineApplicable,
1192 )
1193 }
1194 _ => return Err(err),
1195 };
1196
1197 err.span_suggestion_verbose(span, message, sugg, applicability);
1198
1199 path.clone()
1200 } else {
1201 return Err(err);
1202 };
1203
1204 err.emit();
1205
1206 path
1207 } else {
1208 self.parse_path(PathStyle::Type)?
1209 };
1210
1211 if self.may_recover() && self.token == TokenKind::OpenParen {
1212 self.recover_fn_trait_with_lifetime_params(&mut path, &mut lifetime_defs)?;
1213 }
1214
1215 if has_parens {
1216 if self.token.is_like_plus() && leading_token.is_keyword(kw::Dyn) {
1219 let bounds = vec![];
1220 self.parse_remaining_bounds(bounds, true)?;
1221 self.expect(exp!(CloseParen))?;
1222 self.dcx().emit_err(errors::IncorrectParensTraitBounds {
1223 span: vec![lo, self.prev_token.span],
1224 sugg: errors::IncorrectParensTraitBoundsSugg {
1225 wrong_span: leading_token.span.shrink_to_hi().to(lo),
1226 new_span: leading_token.span.shrink_to_lo(),
1227 },
1228 });
1229 } else {
1230 self.expect(exp!(CloseParen))?;
1231 }
1232 }
1233
1234 let poly_trait =
1235 PolyTraitRef::new(lifetime_defs, path, modifiers, lo.to(self.prev_token.span));
1236 Ok(GenericBound::Trait(poly_trait))
1237 }
1238
1239 fn recover_path_from_fn(&mut self) -> Option<ast::Path> {
1241 let fn_token_span = self.token.span;
1242 self.bump();
1243 let args_lo = self.token.span;
1244 let snapshot = self.create_snapshot_for_diagnostic();
1245 match self.parse_fn_decl(|_| false, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
1246 Ok(decl) => {
1247 self.dcx().emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
1248 Some(ast::Path {
1249 span: fn_token_span.to(self.prev_token.span),
1250 segments: thin_vec![ast::PathSegment {
1251 ident: Ident::new(sym::Fn, fn_token_span),
1252 id: DUMMY_NODE_ID,
1253 args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs {
1254 span: args_lo.to(self.prev_token.span),
1255 inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(),
1256 inputs_span: args_lo.until(decl.output.span()),
1257 output: decl.output.clone(),
1258 }))),
1259 }],
1260 tokens: None,
1261 })
1262 }
1263 Err(diag) => {
1264 diag.cancel();
1265 self.restore_snapshot(snapshot);
1266 None
1267 }
1268 }
1269 }
1270
1271 pub(super) fn parse_late_bound_lifetime_defs(
1273 &mut self,
1274 ) -> PResult<'a, (ThinVec<GenericParam>, Option<Span>)> {
1275 if self.eat_keyword(exp!(For)) {
1276 let lo = self.token.span;
1277 self.expect_lt()?;
1278 let params = self.parse_generic_params()?;
1279 self.expect_gt()?;
1280 Ok((params, Some(lo.to(self.prev_token.span))))
1283 } else {
1284 Ok((ThinVec::new(), None))
1285 }
1286 }
1287
1288 fn recover_fn_trait_with_lifetime_params(
1292 &mut self,
1293 fn_path: &mut ast::Path,
1294 lifetime_defs: &mut ThinVec<GenericParam>,
1295 ) -> PResult<'a, ()> {
1296 let fn_path_segment = fn_path.segments.last_mut().unwrap();
1297 let generic_args = if let Some(p_args) = &fn_path_segment.args {
1298 p_args.clone().into_inner()
1299 } else {
1300 return Ok(());
1303 };
1304 let lifetimes =
1305 if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) =
1306 &generic_args
1307 {
1308 args.into_iter()
1309 .filter_map(|arg| {
1310 if let ast::AngleBracketedArg::Arg(generic_arg) = arg
1311 && let ast::GenericArg::Lifetime(lifetime) = generic_arg
1312 {
1313 Some(lifetime)
1314 } else {
1315 None
1316 }
1317 })
1318 .collect()
1319 } else {
1320 Vec::new()
1321 };
1322 if lifetimes.is_empty() {
1324 return Ok(());
1325 }
1326
1327 let inputs_lo = self.token.span;
1329 let inputs: ThinVec<_> =
1330 self.parse_fn_params(|_| false)?.into_iter().map(|input| input.ty).collect();
1331 let inputs_span = inputs_lo.to(self.prev_token.span);
1332 let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
1333 let args = ast::ParenthesizedArgs {
1334 span: fn_path_segment.span().to(self.prev_token.span),
1335 inputs,
1336 inputs_span,
1337 output,
1338 }
1339 .into();
1340 *fn_path_segment = ast::PathSegment {
1341 ident: fn_path_segment.ident,
1342 args: Some(args),
1343 id: ast::DUMMY_NODE_ID,
1344 };
1345
1346 let mut generic_params = lifetimes
1348 .iter()
1349 .map(|lt| GenericParam {
1350 id: lt.id,
1351 ident: lt.ident,
1352 attrs: ast::AttrVec::new(),
1353 bounds: Vec::new(),
1354 is_placeholder: false,
1355 kind: ast::GenericParamKind::Lifetime,
1356 colon_span: None,
1357 })
1358 .collect::<ThinVec<GenericParam>>();
1359 lifetime_defs.append(&mut generic_params);
1360
1361 let generic_args_span = generic_args.span();
1362 let snippet = format!(
1363 "for<{}> ",
1364 lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),
1365 );
1366 let before_fn_path = fn_path.span.shrink_to_lo();
1367 self.dcx()
1368 .struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters")
1369 .with_multipart_suggestion(
1370 "consider using a higher-ranked trait bound instead",
1371 vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
1372 Applicability::MaybeIncorrect,
1373 )
1374 .emit();
1375 Ok(())
1376 }
1377
1378 pub(super) fn check_lifetime(&mut self) -> bool {
1379 self.expected_token_types.insert(TokenType::Lifetime);
1380 self.token.is_lifetime()
1381 }
1382
1383 pub(super) fn expect_lifetime(&mut self) -> Lifetime {
1385 if let Some((ident, is_raw)) = self.token.lifetime() {
1386 if matches!(is_raw, IdentIsRaw::No)
1387 && ident.without_first_quote().is_reserved()
1388 && ![kw::UnderscoreLifetime, kw::StaticLifetime].contains(&ident.name)
1389 {
1390 self.dcx().emit_err(errors::KeywordLifetime { span: ident.span });
1391 }
1392
1393 self.bump();
1394 Lifetime { ident, id: ast::DUMMY_NODE_ID }
1395 } else {
1396 self.dcx().span_bug(self.token.span, "not a lifetime")
1397 }
1398 }
1399
1400 pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> P<Ty> {
1401 P(Ty { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
1402 }
1403}