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, InvalidCVariadicType, InvalidDynKeyword, LifetimeAfterMut,
19 NeedPlusAfterTraitObjectLifetime, NestedCVariadicType, ReturnTypesUseThinArrow,
20};
21use crate::parser::item::FrontMatterParsingMode;
22use crate::parser::{FnContext, FnParseMode};
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, Box<Ty>> {
109 if self.token == token::DotDotDot {
110 let span = self.token.span;
114 self.bump();
115 let kind = TyKind::Err(self.dcx().emit_err(InvalidCVariadicType { span }));
116 return Ok(self.mk_ty(span, kind));
117 }
118 ensure_sufficient_stack(|| {
120 self.parse_ty_common(
121 AllowPlus::Yes,
122 AllowCVariadic::No,
123 RecoverQPath::Yes,
124 RecoverReturnSign::Yes,
125 None,
126 RecoverQuestionMark::Yes,
127 )
128 })
129 }
130
131 pub(super) fn parse_ty_with_generics_recovery(
132 &mut self,
133 ty_params: &Generics,
134 ) -> PResult<'a, Box<Ty>> {
135 self.parse_ty_common(
136 AllowPlus::Yes,
137 AllowCVariadic::No,
138 RecoverQPath::Yes,
139 RecoverReturnSign::Yes,
140 Some(ty_params),
141 RecoverQuestionMark::Yes,
142 )
143 }
144
145 pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, Box<Ty>> {
149 let ty = self.parse_ty_common(
150 AllowPlus::Yes,
151 AllowCVariadic::Yes,
152 RecoverQPath::Yes,
153 RecoverReturnSign::Yes,
154 None,
155 RecoverQuestionMark::Yes,
156 )?;
157
158 if self.may_recover()
160 && self.check_noexpect(&token::Eq)
161 && self.look_ahead(1, |tok| tok.can_begin_expr())
162 {
163 let snapshot = self.create_snapshot_for_diagnostic();
164 self.bump();
165 let eq_span = self.prev_token.span;
166 match self.parse_expr() {
167 Ok(e) => {
168 self.dcx()
169 .struct_span_err(eq_span.to(e.span), "parameter defaults are not supported")
170 .emit();
171 }
172 Err(diag) => {
173 diag.cancel();
174 self.restore_snapshot(snapshot);
175 }
176 }
177 }
178
179 Ok(ty)
180 }
181
182 pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, Box<Ty>> {
189 self.parse_ty_common(
190 AllowPlus::No,
191 AllowCVariadic::No,
192 RecoverQPath::Yes,
193 RecoverReturnSign::Yes,
194 None,
195 RecoverQuestionMark::Yes,
196 )
197 }
198
199 pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, Box<Ty>> {
202 self.parse_ty_common(
203 AllowPlus::No,
204 AllowCVariadic::No,
205 RecoverQPath::Yes,
206 RecoverReturnSign::Yes,
207 None,
208 RecoverQuestionMark::No,
209 )
210 }
211
212 pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, Box<Ty>> {
213 self.parse_ty_common(
214 AllowPlus::Yes,
215 AllowCVariadic::No,
216 RecoverQPath::Yes,
217 RecoverReturnSign::Yes,
218 None,
219 RecoverQuestionMark::No,
220 )
221 }
222
223 pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, Box<Ty>> {
226 self.parse_ty_common(
227 AllowPlus::Yes,
228 AllowCVariadic::No,
229 RecoverQPath::Yes,
230 RecoverReturnSign::OnlyFatArrow,
231 None,
232 RecoverQuestionMark::Yes,
233 )
234 }
235
236 pub(super) fn parse_ret_ty(
238 &mut self,
239 allow_plus: AllowPlus,
240 recover_qpath: RecoverQPath,
241 recover_return_sign: RecoverReturnSign,
242 ) -> PResult<'a, FnRetTy> {
243 let lo = self.prev_token.span;
244 Ok(if self.eat(exp!(RArrow)) {
245 let ty = self.parse_ty_common(
247 allow_plus,
248 AllowCVariadic::No,
249 recover_qpath,
250 recover_return_sign,
251 None,
252 RecoverQuestionMark::Yes,
253 )?;
254 FnRetTy::Ty(ty)
255 } else if recover_return_sign.can_recover(&self.token.kind) {
256 self.bump();
259 self.dcx().emit_err(ReturnTypesUseThinArrow {
260 span: self.prev_token.span,
261 suggestion: lo.between(self.token.span),
262 });
263 let ty = self.parse_ty_common(
264 allow_plus,
265 AllowCVariadic::No,
266 recover_qpath,
267 recover_return_sign,
268 None,
269 RecoverQuestionMark::Yes,
270 )?;
271 FnRetTy::Ty(ty)
272 } else {
273 FnRetTy::Default(self.prev_token.span.shrink_to_hi())
274 })
275 }
276
277 fn parse_ty_common(
278 &mut self,
279 allow_plus: AllowPlus,
280 allow_c_variadic: AllowCVariadic,
281 recover_qpath: RecoverQPath,
282 recover_return_sign: RecoverReturnSign,
283 ty_generics: Option<&Generics>,
284 recover_question_mark: RecoverQuestionMark,
285 ) -> PResult<'a, Box<Ty>> {
286 let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
287 maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
288 if self.token == token::Pound && self.look_ahead(1, |t| *t == token::OpenBracket) {
289 let attrs_wrapper = self.parse_outer_attributes()?;
290 let raw_attrs = attrs_wrapper.take_for_recovery(self.psess);
291 let attr_span = raw_attrs[0].span.to(raw_attrs.last().unwrap().span);
292 let (full_span, guar) = match self.parse_ty() {
293 Ok(ty) => {
294 let full_span = attr_span.until(ty.span);
295 let guar = self
296 .dcx()
297 .emit_err(AttributeOnType { span: attr_span, fix_span: full_span });
298 (attr_span, guar)
299 }
300 Err(err) => {
301 err.cancel();
302 let guar = self.dcx().emit_err(AttributeOnEmptyType { span: attr_span });
303 (attr_span, guar)
304 }
305 };
306
307 return Ok(self.mk_ty(full_span, TyKind::Err(guar)));
308 }
309 if let Some(ty) = self.eat_metavar_seq_with_matcher(
310 |mv_kind| matches!(mv_kind, MetaVarKind::Ty { .. }),
311 |this| this.parse_ty_no_question_mark_recover(),
312 ) {
313 return Ok(ty);
314 }
315
316 let lo = self.token.span;
317 let mut impl_dyn_multi = false;
318 let kind = if self.check(exp!(OpenParen)) {
319 self.parse_ty_tuple_or_parens(lo, allow_plus)?
320 } else if self.eat(exp!(Bang)) {
321 TyKind::Never
323 } else if self.eat(exp!(Star)) {
324 self.parse_ty_ptr()?
325 } else if self.eat(exp!(OpenBracket)) {
326 self.parse_array_or_slice_ty()?
327 } else if self.check(exp!(And)) || self.check(exp!(AndAnd)) {
328 self.expect_and()?;
330 self.parse_borrowed_pointee()?
331 } else if self.eat_keyword_noexpect(kw::Typeof) {
332 self.parse_typeof_ty()?
333 } else if self.eat_keyword(exp!(Underscore)) {
334 TyKind::Infer
336 } else if self.check_fn_front_matter(false, Case::Sensitive) {
337 self.parse_ty_fn_ptr(lo, ThinVec::new(), None, recover_return_sign)?
339 } else if self.check_keyword(exp!(For)) {
340 let (bound_vars, _) = self.parse_higher_ranked_binder()?;
344 if self.check_fn_front_matter(false, Case::Sensitive) {
345 self.parse_ty_fn_ptr(
346 lo,
347 bound_vars,
348 Some(self.prev_token.span.shrink_to_lo()),
349 recover_return_sign,
350 )?
351 } else {
352 if self.may_recover()
354 && (self.eat_keyword_noexpect(kw::Impl) || self.eat_keyword_noexpect(kw::Dyn))
355 {
356 let kw = self.prev_token.ident().unwrap().0;
357 let removal_span = kw.span.with_hi(self.token.span.lo());
358 let path = self.parse_path(PathStyle::Type)?;
359 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
360 let kind = self.parse_remaining_bounds_path(
361 bound_vars,
362 path,
363 lo,
364 parse_plus,
365 ast::Parens::No,
366 )?;
367 let err = self.dcx().create_err(errors::TransposeDynOrImpl {
368 span: kw.span,
369 kw: kw.name.as_str(),
370 sugg: errors::TransposeDynOrImplSugg {
371 removal_span,
372 insertion_span: lo.shrink_to_lo(),
373 kw: kw.name.as_str(),
374 },
375 });
376
377 let kind = match (kind, kw.name) {
380 (TyKind::TraitObject(bounds, _), kw::Dyn) => {
381 TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)
382 }
383 (TyKind::TraitObject(bounds, _), kw::Impl) => {
384 TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)
385 }
386 _ => return Err(err),
387 };
388 err.emit();
389 kind
390 } else {
391 let path = self.parse_path(PathStyle::Type)?;
392 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
393 self.parse_remaining_bounds_path(
394 bound_vars,
395 path,
396 lo,
397 parse_plus,
398 ast::Parens::No,
399 )?
400 }
401 }
402 } else if self.eat_keyword(exp!(Impl)) {
403 self.parse_impl_ty(&mut impl_dyn_multi)?
404 } else if self.is_explicit_dyn_type() {
405 self.parse_dyn_ty(&mut impl_dyn_multi)?
406 } else if self.eat_lt() {
407 let (qself, path) = self.parse_qpath(PathStyle::Type)?;
409 TyKind::Path(Some(qself), path)
410 } else if self.check_path() {
411 self.parse_path_start_ty(lo, allow_plus, ty_generics)?
412 } else if self.can_begin_bound() {
413 self.parse_bare_trait_object(lo, allow_plus)?
414 } else if self.eat(exp!(DotDotDot)) {
415 match allow_c_variadic {
416 AllowCVariadic::Yes => TyKind::CVarArgs,
417 AllowCVariadic::No => {
418 let guar = self.dcx().emit_err(NestedCVariadicType { span: lo });
422 TyKind::Err(guar)
423 }
424 }
425 } else if self.check_keyword(exp!(Unsafe))
426 && self.look_ahead(1, |tok| tok.kind == token::Lt)
427 {
428 self.parse_unsafe_binder_ty()?
429 } else {
430 let msg = format!("expected type, found {}", super::token_descr(&self.token));
431 let mut err = self.dcx().struct_span_err(lo, msg);
432 err.span_label(lo, "expected type");
433 return Err(err);
434 };
435
436 let span = lo.to(self.prev_token.span);
437 let mut ty = self.mk_ty(span, kind);
438
439 match allow_plus {
441 AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?,
442 AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty),
443 }
444 if let RecoverQuestionMark::Yes = recover_question_mark {
445 ty = self.maybe_recover_from_question_mark(ty);
446 }
447 if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
448 }
449
450 fn parse_unsafe_binder_ty(&mut self) -> PResult<'a, TyKind> {
451 let lo = self.token.span;
452 assert!(self.eat_keyword(exp!(Unsafe)));
453 self.expect_lt()?;
454 let generic_params = self.parse_generic_params()?;
455 self.expect_gt()?;
456 let inner_ty = self.parse_ty()?;
457 let span = lo.to(self.prev_token.span);
458 self.psess.gated_spans.gate(sym::unsafe_binders, span);
459
460 Ok(TyKind::UnsafeBinder(Box::new(UnsafeBinderTy { generic_params, inner_ty })))
461 }
462
463 fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
467 let mut trailing_plus = false;
468 let (ts, trailing) = self.parse_paren_comma_seq(|p| {
469 let ty = p.parse_ty()?;
470 trailing_plus = p.prev_token == TokenKind::Plus;
471 Ok(ty)
472 })?;
473
474 if ts.len() == 1 && matches!(trailing, Trailing::No) {
475 let ty = ts.into_iter().next().unwrap();
476 let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus();
477 match ty.kind {
478 TyKind::Path(None, path) if maybe_bounds => self.parse_remaining_bounds_path(
480 ThinVec::new(),
481 path,
482 lo,
483 true,
484 ast::Parens::Yes,
485 ),
486 TyKind::TraitObject(bounds, TraitObjectSyntax::None)
490 if maybe_bounds && bounds.len() == 1 && !trailing_plus =>
491 {
492 self.parse_remaining_bounds(bounds, true)
493 }
494 _ => Ok(TyKind::Paren(ty)),
496 }
497 } else {
498 Ok(TyKind::Tup(ts))
499 }
500 }
501
502 fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
503 if self.token.is_lifetime() && !self.look_ahead(1, |t| t.is_like_plus()) {
505 if self.psess.edition.at_least_rust_2021() {
509 let lt = self.expect_lifetime();
510 let mut err = self.dcx().struct_span_err(lo, "expected type, found lifetime");
511 err.span_label(lo, "expected type");
512 return Ok(match self.maybe_recover_ref_ty_no_leading_ampersand(lt, lo, err) {
513 Ok(ref_ty) => ref_ty,
514 Err(err) => TyKind::Err(err.emit()),
515 });
516 }
517
518 self.dcx().emit_err(NeedPlusAfterTraitObjectLifetime {
519 span: lo,
520 suggestion: lo.shrink_to_hi(),
521 });
522 }
523 Ok(TyKind::TraitObject(
524 self.parse_generic_bounds_common(allow_plus)?,
525 TraitObjectSyntax::None,
526 ))
527 }
528
529 fn maybe_recover_ref_ty_no_leading_ampersand<'cx>(
530 &mut self,
531 lt: Lifetime,
532 lo: Span,
533 mut err: Diag<'cx>,
534 ) -> Result<TyKind, Diag<'cx>> {
535 if !self.may_recover() {
536 return Err(err);
537 }
538 let snapshot = self.create_snapshot_for_diagnostic();
539 let mutbl = self.parse_mutability();
540 match self.parse_ty_no_plus() {
541 Ok(ty) => {
542 err.span_suggestion_verbose(
543 lo.shrink_to_lo(),
544 "you might have meant to write a reference type here",
545 "&",
546 Applicability::MaybeIncorrect,
547 );
548 err.emit();
549 Ok(TyKind::Ref(Some(lt), MutTy { ty, mutbl }))
550 }
551 Err(diag) => {
552 diag.cancel();
553 self.restore_snapshot(snapshot);
554 Err(err)
555 }
556 }
557 }
558
559 fn parse_remaining_bounds_path(
560 &mut self,
561 generic_params: ThinVec<GenericParam>,
562 path: ast::Path,
563 lo: Span,
564 parse_plus: bool,
565 parens: ast::Parens,
566 ) -> PResult<'a, TyKind> {
567 let poly_trait_ref = PolyTraitRef::new(
568 generic_params,
569 path,
570 TraitBoundModifiers::NONE,
571 lo.to(self.prev_token.span),
572 parens,
573 );
574 let bounds = vec![GenericBound::Trait(poly_trait_ref)];
575 self.parse_remaining_bounds(bounds, parse_plus)
576 }
577
578 fn parse_remaining_bounds(
580 &mut self,
581 mut bounds: GenericBounds,
582 plus: bool,
583 ) -> PResult<'a, TyKind> {
584 if plus {
585 self.eat_plus(); bounds.append(&mut self.parse_generic_bounds()?);
587 }
588 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
589 }
590
591 fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
593 let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
594 let span = self.prev_token.span;
595 self.dcx().emit_err(ExpectedMutOrConstInRawPointerType {
596 span,
597 after_asterisk: span.shrink_to_hi(),
598 });
599 Mutability::Not
600 });
601 let ty = self.parse_ty_no_plus()?;
602 Ok(TyKind::Ptr(MutTy { ty, mutbl }))
603 }
604
605 fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {
608 let elt_ty = match self.parse_ty() {
609 Ok(ty) => ty,
610 Err(err)
611 if self.look_ahead(1, |t| *t == token::CloseBracket)
612 | self.look_ahead(1, |t| *t == token::Semi) =>
613 {
614 self.bump();
616 let guar = err.emit();
617 self.mk_ty(self.prev_token.span, TyKind::Err(guar))
618 }
619 Err(err) => return Err(err),
620 };
621
622 let ty = if self.eat(exp!(Semi)) {
623 let mut length = self.parse_expr_anon_const()?;
624 if let Err(e) = self.expect(exp!(CloseBracket)) {
625 self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
627 self.expect(exp!(CloseBracket))?;
628 }
629 TyKind::Array(elt_ty, length)
630 } else if self.eat(exp!(CloseBracket)) {
631 TyKind::Slice(elt_ty)
632 } else {
633 self.maybe_recover_array_ty_without_semi(elt_ty)?
634 };
635
636 Ok(ty)
637 }
638
639 fn maybe_recover_array_ty_without_semi(&mut self, elt_ty: Box<Ty>) -> PResult<'a, TyKind> {
646 let span = self.token.span;
647 let token_descr = super::token_descr(&self.token);
648 let mut err =
649 self.dcx().struct_span_err(span, format!("expected `;` or `]`, found {}", token_descr));
650 err.span_label(span, "expected `;` or `]`");
651 err.note("you might have meant to write a slice or array type");
652
653 if !self.may_recover() {
655 return Err(err);
656 }
657
658 let snapshot = self.create_snapshot_for_diagnostic();
659
660 let suggestion_span = if self.eat(exp!(Comma)) || self.eat(exp!(Star)) {
661 self.prev_token.span
663 } else {
664 self.token.span.shrink_to_lo()
665 };
666
667 let length = match self.parse_expr_anon_const() {
669 Ok(length) => length,
670 Err(e) => {
671 e.cancel();
672 self.restore_snapshot(snapshot);
673 return Err(err);
674 }
675 };
676
677 if let Err(e) = self.expect(exp!(CloseBracket)) {
678 e.cancel();
679 self.restore_snapshot(snapshot);
680 return Err(err);
681 }
682
683 err.span_suggestion_verbose(
684 suggestion_span,
685 "you might have meant to use `;` as the separator",
686 ";",
687 Applicability::MaybeIncorrect,
688 );
689 err.emit();
690 Ok(TyKind::Array(elt_ty, length))
691 }
692
693 fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
694 let and_span = self.prev_token.span;
695 let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());
696 let (pinned, mut mutbl) = match self.parse_pin_and_mut() {
697 Some(pin_mut) => pin_mut,
698 None => (Pinnedness::Not, self.parse_mutability()),
699 };
700 if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
701 if !self.look_ahead(1, |t| t.is_like_plus()) {
707 let lifetime_span = self.token.span;
708 let span = and_span.to(lifetime_span);
709
710 let (suggest_lifetime, snippet) =
711 if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
712 (Some(span), lifetime_src)
713 } else {
714 (None, String::new())
715 };
716 self.dcx().emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });
717
718 opt_lifetime = Some(self.expect_lifetime());
719 }
720 } else if self.token.is_keyword(kw::Dyn)
721 && mutbl == Mutability::Not
722 && self.look_ahead(1, |t| t.is_keyword(kw::Mut))
723 {
724 let span = and_span.to(self.look_ahead(1, |t| t.span));
726 self.dcx().emit_err(DynAfterMut { span });
727
728 mutbl = Mutability::Mut;
730 let (dyn_tok, dyn_tok_sp) = (self.token, self.token_spacing);
731 self.bump();
732 self.bump_with((dyn_tok, dyn_tok_sp));
733 }
734 let ty = self.parse_ty_no_plus()?;
735 Ok(match pinned {
736 Pinnedness::Not => TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }),
737 Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl }),
738 })
739 }
740
741 pub(crate) fn parse_pin_and_mut(&mut self) -> Option<(Pinnedness, Mutability)> {
745 if self.token.is_ident_named(sym::pin) {
746 let result = self.look_ahead(1, |token| {
747 if token.is_keyword(kw::Const) {
748 Some((Pinnedness::Pinned, Mutability::Not))
749 } else if token.is_keyword(kw::Mut) {
750 Some((Pinnedness::Pinned, Mutability::Mut))
751 } else {
752 None
753 }
754 });
755 if result.is_some() {
756 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
757 self.bump();
758 self.bump();
759 }
760 result
761 } else {
762 None
763 }
764 }
765
766 fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> {
769 self.expect(exp!(OpenParen))?;
770 let expr = self.parse_expr_anon_const()?;
771 self.expect(exp!(CloseParen))?;
772 Ok(TyKind::Typeof(expr))
773 }
774
775 fn parse_ty_fn_ptr(
785 &mut self,
786 lo: Span,
787 mut params: ThinVec<GenericParam>,
788 param_insertion_point: Option<Span>,
789 recover_return_sign: RecoverReturnSign,
790 ) -> PResult<'a, TyKind> {
791 let inherited_vis = rustc_ast::Visibility {
792 span: rustc_span::DUMMY_SP,
793 kind: rustc_ast::VisibilityKind::Inherited,
794 tokens: None,
795 };
796 let span_start = self.token.span;
797 let ast::FnHeader { ext, safety, .. } = self.parse_fn_front_matter(
798 &inherited_vis,
799 Case::Sensitive,
800 FrontMatterParsingMode::FunctionPtrType,
801 )?;
802 if self.may_recover() && self.token == TokenKind::Lt {
803 self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
804 }
805 let mode = crate::parser::item::FnParseMode {
806 req_name: |_| false,
807 context: FnContext::Free,
808 req_body: false,
809 };
810 let decl = self.parse_fn_decl(&mode, AllowPlus::No, recover_return_sign)?;
811
812 let decl_span = span_start.to(self.prev_token.span);
813 Ok(TyKind::FnPtr(Box::new(FnPtrTy {
814 ext,
815 safety,
816 generic_params: params,
817 decl,
818 decl_span,
819 })))
820 }
821
822 fn recover_fn_ptr_with_generics(
824 &mut self,
825 lo: Span,
826 params: &mut ThinVec<GenericParam>,
827 param_insertion_point: Option<Span>,
828 ) -> PResult<'a, ()> {
829 let generics = self.parse_generics()?;
830 let arity = generics.params.len();
831
832 let mut lifetimes: ThinVec<_> = generics
833 .params
834 .into_iter()
835 .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime))
836 .collect();
837
838 let sugg = if !lifetimes.is_empty() {
839 let snippet =
840 lifetimes.iter().map(|param| param.ident.as_str()).intersperse(", ").collect();
841
842 let (left, snippet) = if let Some(span) = param_insertion_point {
843 (span, if params.is_empty() { snippet } else { format!(", {snippet}") })
844 } else {
845 (lo.shrink_to_lo(), format!("for<{snippet}> "))
846 };
847
848 Some(FnPtrWithGenericsSugg {
849 left,
850 snippet,
851 right: generics.span,
852 arity,
853 for_param_list_exists: param_insertion_point.is_some(),
854 })
855 } else {
856 None
857 };
858
859 self.dcx().emit_err(FnPtrWithGenerics { span: generics.span, sugg });
860 params.append(&mut lifetimes);
861 Ok(())
862 }
863
864 fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
866 if self.token.is_lifetime() {
867 self.look_ahead(1, |t| {
868 if let token::Ident(sym, _) = t.kind {
869 self.dcx().emit_err(errors::MissingPlusBounds {
872 span: self.token.span,
873 hi: self.token.span.shrink_to_hi(),
874 sym,
875 });
876 }
877 })
878 }
879
880 let bounds = self.parse_generic_bounds()?;
882
883 *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
884
885 Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))
886 }
887
888 fn parse_use_bound(&mut self, lo: Span, parens: ast::Parens) -> PResult<'a, GenericBound> {
895 self.expect_lt()?;
896 let (args, _, _) = self.parse_seq_to_before_tokens(
897 &[exp!(Gt)],
898 &[&TokenKind::Ge, &TokenKind::Shr, &TokenKind::Shr],
899 SeqSep::trailing_allowed(exp!(Comma)),
900 |self_| {
901 if self_.check_keyword(exp!(SelfUpper)) {
902 self_.bump();
903 Ok(PreciseCapturingArg::Arg(
904 ast::Path::from_ident(self_.prev_token.ident().unwrap().0),
905 DUMMY_NODE_ID,
906 ))
907 } else if self_.check_ident() {
908 Ok(PreciseCapturingArg::Arg(
909 ast::Path::from_ident(self_.parse_ident()?),
910 DUMMY_NODE_ID,
911 ))
912 } else if self_.check_lifetime() {
913 Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))
914 } else {
915 self_.unexpected_any()
916 }
917 },
918 )?;
919 self.expect_gt()?;
920
921 if let ast::Parens::Yes = parens {
922 self.expect(exp!(CloseParen))?;
923 self.report_parenthesized_bound(lo, self.prev_token.span, "precise capturing lists");
924 }
925
926 Ok(GenericBound::Use(args, lo.to(self.prev_token.span)))
927 }
928
929 fn is_explicit_dyn_type(&mut self) -> bool {
931 self.check_keyword(exp!(Dyn))
932 && (self.token_uninterpolated_span().at_least_rust_2018()
933 || self.look_ahead(1, |t| {
934 (can_begin_dyn_bound_in_edition_2015(t) || *t == TokenKind::Star)
935 && !can_continue_type_after_non_fn_ident(t)
936 }))
937 }
938
939 fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
943 self.bump(); let syntax = TraitObjectSyntax::Dyn;
947
948 let bounds = self.parse_generic_bounds()?;
950 *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
951 Ok(TyKind::TraitObject(bounds, syntax))
952 }
953
954 fn parse_path_start_ty(
961 &mut self,
962 lo: Span,
963 allow_plus: AllowPlus,
964 ty_generics: Option<&Generics>,
965 ) -> PResult<'a, TyKind> {
966 let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
968 if self.eat(exp!(Bang)) {
969 Ok(TyKind::MacCall(Box::new(MacCall { path, args: self.parse_delim_args()? })))
971 } else if allow_plus == AllowPlus::Yes && self.check_plus() {
972 self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true, ast::Parens::No)
974 } else {
975 Ok(TyKind::Path(None, path))
977 }
978 }
979
980 pub(super) fn parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds> {
981 self.parse_generic_bounds_common(AllowPlus::Yes)
982 }
983
984 fn parse_generic_bounds_common(&mut self, allow_plus: AllowPlus) -> PResult<'a, GenericBounds> {
989 let mut bounds = Vec::new();
990
991 while self.can_begin_bound()
997 || (self.may_recover()
998 && (self.token.can_begin_type()
999 || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))))
1000 {
1001 if self.token.is_keyword(kw::Dyn) {
1002 self.bump();
1004 self.dcx().emit_err(InvalidDynKeyword {
1005 span: self.prev_token.span,
1006 suggestion: self.prev_token.span.until(self.token.span),
1007 });
1008 }
1009 bounds.push(self.parse_generic_bound()?);
1010 if allow_plus == AllowPlus::No || !self.eat_plus() {
1011 break;
1012 }
1013 }
1014
1015 Ok(bounds)
1016 }
1017
1018 fn can_begin_bound(&mut self) -> bool {
1020 self.check_path()
1021 || self.check_lifetime()
1022 || self.check(exp!(Bang))
1023 || self.check(exp!(Question))
1024 || self.check(exp!(Tilde))
1025 || self.check_keyword(exp!(For))
1026 || self.check(exp!(OpenParen))
1027 || self.can_begin_maybe_const_bound()
1028 || self.check_keyword(exp!(Const))
1029 || self.check_keyword(exp!(Async))
1030 || self.check_keyword(exp!(Use))
1031 }
1032
1033 fn can_begin_maybe_const_bound(&mut self) -> bool {
1034 self.check(exp!(OpenBracket))
1035 && self.look_ahead(1, |t| t.is_keyword(kw::Const))
1036 && self.look_ahead(2, |t| *t == token::CloseBracket)
1037 }
1038
1039 fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
1045 let leading_token = self.prev_token;
1046 let lo = self.token.span;
1047
1048 let parens = if self.eat(exp!(OpenParen)) { ast::Parens::Yes } else { ast::Parens::No };
1054
1055 if self.token.is_lifetime() {
1056 self.parse_lifetime_bound(lo, parens)
1057 } else if self.eat_keyword(exp!(Use)) {
1058 self.parse_use_bound(lo, parens)
1059 } else {
1060 self.parse_trait_bound(lo, parens, &leading_token)
1061 }
1062 }
1063
1064 fn parse_lifetime_bound(&mut self, lo: Span, parens: ast::Parens) -> PResult<'a, GenericBound> {
1070 let lt = self.expect_lifetime();
1071
1072 if let ast::Parens::Yes = parens {
1073 self.expect(exp!(CloseParen))?;
1074 self.report_parenthesized_bound(lo, self.prev_token.span, "lifetime bounds");
1075 }
1076
1077 Ok(GenericBound::Outlives(lt))
1078 }
1079
1080 fn report_parenthesized_bound(&self, lo: Span, hi: Span, kind: &str) -> ErrorGuaranteed {
1081 let mut diag =
1082 self.dcx().struct_span_err(lo.to(hi), format!("{kind} may not be parenthesized"));
1083 diag.multipart_suggestion(
1084 "remove the parentheses",
1085 vec![(lo, String::new()), (hi, String::new())],
1086 Applicability::MachineApplicable,
1087 );
1088 diag.emit()
1089 }
1090
1091 fn error_lt_bound_with_modifiers(
1093 &self,
1094 modifiers: TraitBoundModifiers,
1095 binder_span: Option<Span>,
1096 ) -> ErrorGuaranteed {
1097 let TraitBoundModifiers { constness, asyncness, polarity } = modifiers;
1098
1099 match constness {
1100 BoundConstness::Never => {}
1101 BoundConstness::Always(span) | BoundConstness::Maybe(span) => {
1102 return self
1103 .dcx()
1104 .emit_err(errors::ModifierLifetime { span, modifier: constness.as_str() });
1105 }
1106 }
1107
1108 match polarity {
1109 BoundPolarity::Positive => {}
1110 BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => {
1111 return self
1112 .dcx()
1113 .emit_err(errors::ModifierLifetime { span, modifier: polarity.as_str() });
1114 }
1115 }
1116
1117 match asyncness {
1118 BoundAsyncness::Normal => {}
1119 BoundAsyncness::Async(span) => {
1120 return self
1121 .dcx()
1122 .emit_err(errors::ModifierLifetime { span, modifier: asyncness.as_str() });
1123 }
1124 }
1125
1126 if let Some(span) = binder_span {
1127 return self.dcx().emit_err(errors::ModifierLifetime { span, modifier: "for<...>" });
1128 }
1129
1130 unreachable!("lifetime bound intercepted in `parse_generic_ty_bound` but no modifiers?")
1131 }
1132
1133 fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
1145 let modifier_lo = self.token.span;
1146 let constness = self.parse_bound_constness()?;
1147
1148 let asyncness = if self.token_uninterpolated_span().at_least_rust_2018()
1149 && self.eat_keyword(exp!(Async))
1150 {
1151 self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
1152 BoundAsyncness::Async(self.prev_token.span)
1153 } else if self.may_recover()
1154 && self.token_uninterpolated_span().is_rust_2015()
1155 && self.is_kw_followed_by_ident(kw::Async)
1156 {
1157 self.bump(); self.dcx().emit_err(errors::AsyncBoundModifierIn2015 {
1159 span: self.prev_token.span,
1160 help: HelpUseLatestEdition::new(),
1161 });
1162 self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
1163 BoundAsyncness::Async(self.prev_token.span)
1164 } else {
1165 BoundAsyncness::Normal
1166 };
1167 let modifier_hi = self.prev_token.span;
1168
1169 let polarity = if self.eat(exp!(Question)) {
1170 BoundPolarity::Maybe(self.prev_token.span)
1171 } else if self.eat(exp!(Bang)) {
1172 self.psess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);
1173 BoundPolarity::Negative(self.prev_token.span)
1174 } else {
1175 BoundPolarity::Positive
1176 };
1177
1178 match polarity {
1180 BoundPolarity::Positive => {
1181 }
1183 BoundPolarity::Maybe(polarity_span) | BoundPolarity::Negative(polarity_span) => {
1184 match (asyncness, constness) {
1185 (BoundAsyncness::Normal, BoundConstness::Never) => {
1186 }
1188 (_, _) => {
1189 let constness = constness.as_str();
1190 let asyncness = asyncness.as_str();
1191 let glue =
1192 if !constness.is_empty() && !asyncness.is_empty() { " " } else { "" };
1193 let modifiers_concatenated = format!("{constness}{glue}{asyncness}");
1194 self.dcx().emit_err(errors::PolarityAndModifiers {
1195 polarity_span,
1196 polarity: polarity.as_str(),
1197 modifiers_span: modifier_lo.to(modifier_hi),
1198 modifiers_concatenated,
1199 });
1200 }
1201 }
1202 }
1203 }
1204
1205 Ok(TraitBoundModifiers { constness, asyncness, polarity })
1206 }
1207
1208 pub fn parse_bound_constness(&mut self) -> PResult<'a, BoundConstness> {
1209 Ok(if self.eat(exp!(Tilde)) {
1212 let tilde = self.prev_token.span;
1213 self.expect_keyword(exp!(Const))?;
1214 let span = tilde.to(self.prev_token.span);
1215 self.psess.gated_spans.gate(sym::const_trait_impl, span);
1216 BoundConstness::Maybe(span)
1217 } else if self.can_begin_maybe_const_bound() {
1218 let start = self.token.span;
1219 self.bump();
1220 self.expect_keyword(exp!(Const)).unwrap();
1221 self.bump();
1222 let span = start.to(self.prev_token.span);
1223 self.psess.gated_spans.gate(sym::const_trait_impl, span);
1224 BoundConstness::Maybe(span)
1225 } else if self.eat_keyword(exp!(Const)) {
1226 self.psess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span);
1227 BoundConstness::Always(self.prev_token.span)
1228 } else {
1229 BoundConstness::Never
1230 })
1231 }
1232
1233 fn parse_trait_bound(
1242 &mut self,
1243 lo: Span,
1244 parens: ast::Parens,
1245 leading_token: &Token,
1246 ) -> PResult<'a, GenericBound> {
1247 let (mut bound_vars, binder_span) = self.parse_higher_ranked_binder()?;
1248
1249 let modifiers_lo = self.token.span;
1250 let modifiers = self.parse_trait_bound_modifiers()?;
1251 let modifiers_span = modifiers_lo.to(self.prev_token.span);
1252
1253 if let Some(binder_span) = binder_span {
1254 match modifiers.polarity {
1255 BoundPolarity::Negative(polarity_span) | BoundPolarity::Maybe(polarity_span) => {
1256 self.dcx().emit_err(errors::BinderAndPolarity {
1257 binder_span,
1258 polarity_span,
1259 polarity: modifiers.polarity.as_str(),
1260 });
1261 }
1262 BoundPolarity::Positive => {}
1263 }
1264 }
1265
1266 if self.token.is_lifetime() {
1269 let _: ErrorGuaranteed = self.error_lt_bound_with_modifiers(modifiers, binder_span);
1270 return self.parse_lifetime_bound(lo, parens);
1271 }
1272
1273 if let (more_bound_vars, Some(binder_span)) = self.parse_higher_ranked_binder()? {
1274 bound_vars.extend(more_bound_vars);
1275 self.dcx().emit_err(errors::BinderBeforeModifiers { binder_span, modifiers_span });
1276 }
1277
1278 let mut path = if self.token.is_keyword(kw::Fn)
1279 && self.look_ahead(1, |t| *t == TokenKind::OpenParen)
1280 && let Some(path) = self.recover_path_from_fn()
1281 {
1282 path
1283 } else if !self.token.is_path_start() && self.token.can_begin_type() {
1284 let ty = self.parse_ty_no_plus()?;
1285 let mut err = self.dcx().struct_span_err(ty.span, "expected a trait, found type");
1287
1288 let path = if self.may_recover() {
1293 let (span, message, sugg, path, applicability) = match &ty.kind {
1294 TyKind::Ptr(..) | TyKind::Ref(..)
1295 if let TyKind::Path(_, path) = &ty.peel_refs().kind =>
1296 {
1297 (
1298 ty.span.until(path.span),
1299 "consider removing the indirection",
1300 "",
1301 path,
1302 Applicability::MaybeIncorrect,
1303 )
1304 }
1305 TyKind::ImplTrait(_, bounds)
1306 if let [GenericBound::Trait(tr, ..), ..] = bounds.as_slice() =>
1307 {
1308 (
1309 ty.span.until(tr.span),
1310 "use the trait bounds directly",
1311 "",
1312 &tr.trait_ref.path,
1313 Applicability::MachineApplicable,
1314 )
1315 }
1316 _ => return Err(err),
1317 };
1318
1319 err.span_suggestion_verbose(span, message, sugg, applicability);
1320
1321 path.clone()
1322 } else {
1323 return Err(err);
1324 };
1325
1326 err.emit();
1327
1328 path
1329 } else {
1330 self.parse_path(PathStyle::Type)?
1331 };
1332
1333 if self.may_recover() && self.token == TokenKind::OpenParen {
1334 self.recover_fn_trait_with_lifetime_params(&mut path, &mut bound_vars)?;
1335 }
1336
1337 if let ast::Parens::Yes = parens {
1338 if self.token.is_like_plus() && leading_token.is_keyword(kw::Dyn) {
1341 let bounds = vec![];
1342 self.parse_remaining_bounds(bounds, true)?;
1343 self.expect(exp!(CloseParen))?;
1344 self.dcx().emit_err(errors::IncorrectParensTraitBounds {
1345 span: vec![lo, self.prev_token.span],
1346 sugg: errors::IncorrectParensTraitBoundsSugg {
1347 wrong_span: leading_token.span.shrink_to_hi().to(lo),
1348 new_span: leading_token.span.shrink_to_lo(),
1349 },
1350 });
1351 } else {
1352 self.expect(exp!(CloseParen))?;
1353 }
1354 }
1355
1356 let poly_trait =
1357 PolyTraitRef::new(bound_vars, path, modifiers, lo.to(self.prev_token.span), parens);
1358 Ok(GenericBound::Trait(poly_trait))
1359 }
1360
1361 fn recover_path_from_fn(&mut self) -> Option<ast::Path> {
1363 let fn_token_span = self.token.span;
1364 self.bump();
1365 let args_lo = self.token.span;
1366 let snapshot = self.create_snapshot_for_diagnostic();
1367 let mode = FnParseMode { req_name: |_| false, context: FnContext::Free, req_body: false };
1368 match self.parse_fn_decl(&mode, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
1369 Ok(decl) => {
1370 self.dcx().emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
1371 Some(ast::Path {
1372 span: fn_token_span.to(self.prev_token.span),
1373 segments: thin_vec![ast::PathSegment {
1374 ident: Ident::new(sym::Fn, fn_token_span),
1375 id: DUMMY_NODE_ID,
1376 args: Some(Box::new(ast::GenericArgs::Parenthesized(
1377 ast::ParenthesizedArgs {
1378 span: args_lo.to(self.prev_token.span),
1379 inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(),
1380 inputs_span: args_lo.until(decl.output.span()),
1381 output: decl.output.clone(),
1382 }
1383 ))),
1384 }],
1385 tokens: None,
1386 })
1387 }
1388 Err(diag) => {
1389 diag.cancel();
1390 self.restore_snapshot(snapshot);
1391 None
1392 }
1393 }
1394 }
1395
1396 pub(super) fn parse_higher_ranked_binder(
1402 &mut self,
1403 ) -> PResult<'a, (ThinVec<GenericParam>, Option<Span>)> {
1404 if self.eat_keyword(exp!(For)) {
1405 let lo = self.token.span;
1406 self.expect_lt()?;
1407 let params = self.parse_generic_params()?;
1408 self.expect_gt()?;
1409 Ok((params, Some(lo.to(self.prev_token.span))))
1412 } else {
1413 Ok((ThinVec::new(), None))
1414 }
1415 }
1416
1417 fn recover_fn_trait_with_lifetime_params(
1421 &mut self,
1422 fn_path: &mut ast::Path,
1423 lifetime_defs: &mut ThinVec<GenericParam>,
1424 ) -> PResult<'a, ()> {
1425 let fn_path_segment = fn_path.segments.last_mut().unwrap();
1426 let generic_args = if let Some(p_args) = &fn_path_segment.args {
1427 *p_args.clone()
1428 } else {
1429 return Ok(());
1432 };
1433 let lifetimes =
1434 if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) =
1435 &generic_args
1436 {
1437 args.into_iter()
1438 .filter_map(|arg| {
1439 if let ast::AngleBracketedArg::Arg(generic_arg) = arg
1440 && let ast::GenericArg::Lifetime(lifetime) = generic_arg
1441 {
1442 Some(lifetime)
1443 } else {
1444 None
1445 }
1446 })
1447 .collect()
1448 } else {
1449 Vec::new()
1450 };
1451 if lifetimes.is_empty() {
1453 return Ok(());
1454 }
1455
1456 let inputs_lo = self.token.span;
1458 let mode = FnParseMode { req_name: |_| false, context: FnContext::Free, req_body: false };
1459 let inputs: ThinVec<_> =
1460 self.parse_fn_params(&mode)?.into_iter().map(|input| input.ty).collect();
1461 let inputs_span = inputs_lo.to(self.prev_token.span);
1462 let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
1463 let args = ast::ParenthesizedArgs {
1464 span: fn_path_segment.span().to(self.prev_token.span),
1465 inputs,
1466 inputs_span,
1467 output,
1468 }
1469 .into();
1470 *fn_path_segment = ast::PathSegment {
1471 ident: fn_path_segment.ident,
1472 args: Some(args),
1473 id: ast::DUMMY_NODE_ID,
1474 };
1475
1476 let mut generic_params = lifetimes
1478 .iter()
1479 .map(|lt| GenericParam {
1480 id: lt.id,
1481 ident: lt.ident,
1482 attrs: ast::AttrVec::new(),
1483 bounds: Vec::new(),
1484 is_placeholder: false,
1485 kind: ast::GenericParamKind::Lifetime,
1486 colon_span: None,
1487 })
1488 .collect::<ThinVec<GenericParam>>();
1489 lifetime_defs.append(&mut generic_params);
1490
1491 let generic_args_span = generic_args.span();
1492 let snippet = format!(
1493 "for<{}> ",
1494 lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),
1495 );
1496 let before_fn_path = fn_path.span.shrink_to_lo();
1497 self.dcx()
1498 .struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters")
1499 .with_multipart_suggestion(
1500 "consider using a higher-ranked trait bound instead",
1501 vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
1502 Applicability::MaybeIncorrect,
1503 )
1504 .emit();
1505 Ok(())
1506 }
1507
1508 pub(super) fn check_lifetime(&mut self) -> bool {
1509 self.expected_token_types.insert(TokenType::Lifetime);
1510 self.token.is_lifetime()
1511 }
1512
1513 pub(super) fn expect_lifetime(&mut self) -> Lifetime {
1515 if let Some((ident, is_raw)) = self.token.lifetime() {
1516 if matches!(is_raw, IdentIsRaw::No)
1517 && ident.without_first_quote().is_reserved_lifetime()
1518 {
1519 self.dcx().emit_err(errors::KeywordLifetime { span: ident.span });
1520 }
1521
1522 self.bump();
1523 Lifetime { ident, id: ast::DUMMY_NODE_ID }
1524 } else {
1525 self.dcx().span_bug(self.token.span, "not a lifetime")
1526 }
1527 }
1528
1529 pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> Box<Ty> {
1530 Box::new(Ty { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
1531 }
1532}