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