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