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