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, MgcaDisambiguation,
6 MutTy, Mutability, Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers,
7 TraitObjectSyntax, Ty, TyKind, UnsafeBinderTy,
8};
9use rustc_data_structures::stack::ensure_sufficient_stack;
10use rustc_errors::{Applicability, Diag, E0516, PResult};
11use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
12use thin_vec::{ThinVec, thin_vec};
13
14use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
15use crate::errors::{
16 self, AttributeOnEmptyType, AttributeOnType, DynAfterMut, ExpectedFnPathFoundFnKeyword,
17 ExpectedMutOrConstInRawPointerType, FnPtrWithGenerics, FnPtrWithGenericsSugg,
18 HelpUseLatestEdition, InvalidCVariadicType, InvalidDynKeyword, LifetimeAfterMut,
19 NeedPlusAfterTraitObjectLifetime, NestedCVariadicType, ReturnTypesUseThinArrow,
20};
21use crate::parser::item::FrontMatterParsingMode;
22use crate::parser::{FnContext, FnParseMode};
23use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
24
25#[derive(#[automatically_derived]
impl ::core::marker::Copy for AllowPlus { }Copy, #[automatically_derived]
impl ::core::clone::Clone for AllowPlus {
#[inline]
fn clone(&self) -> AllowPlus { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for AllowPlus {
#[inline]
fn eq(&self, other: &AllowPlus) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq)]
31pub(super) enum AllowPlus {
32 Yes,
33 No,
34}
35
36#[derive(#[automatically_derived]
impl ::core::cmp::PartialEq for RecoverQPath {
#[inline]
fn eq(&self, other: &RecoverQPath) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq)]
37pub(super) enum RecoverQPath {
38 Yes,
39 No,
40}
41
42pub(super) enum RecoverQuestionMark {
43 Yes,
44 No,
45}
46
47#[derive(#[automatically_derived]
impl ::core::marker::Copy for RecoverReturnSign { }Copy, #[automatically_derived]
impl ::core::clone::Clone for RecoverReturnSign {
#[inline]
fn clone(&self) -> RecoverReturnSign { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for RecoverReturnSign {
#[inline]
fn eq(&self, other: &RecoverReturnSign) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}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 => #[allow(non_exhaustive_omitted_patterns)] match token {
token::FatArrow | token::Colon => true,
_ => false,
}matches!(token, token::FatArrow | token::Colon),
72 Self::OnlyFatArrow => #[allow(non_exhaustive_omitted_patterns)] match token {
token::FatArrow => true,
_ => false,
}matches!(token, token::FatArrow),
73 Self::No => false,
74 }
75 }
76}
77
78#[derive(#[automatically_derived]
impl ::core::cmp::PartialEq for AllowCVariadic {
#[inline]
fn eq(&self, other: &AllowCVariadic) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq)]
80enum AllowCVariadic {
81 Yes,
82 No,
83}
84
85fn can_begin_dyn_bound_in_edition_2015(t: Token) -> bool {
89 if t.is_path_start() {
90 return t != token::PathSep && t != token::Lt && t != token::Shl;
96 }
97
98 t == token::OpenParen || t == token::Question || t.is_lifetime() || t.is_keyword(kw::For)
103}
104
105impl<'a> Parser<'a> {
106 pub fn parse_ty(&mut self) -> PResult<'a, Box<Ty>> {
108 if self.token == token::DotDotDot {
109 let span = self.token.span;
113 self.bump();
114 let kind = TyKind::Err(self.dcx().emit_err(InvalidCVariadicType { span }));
115 return Ok(self.mk_ty(span, kind));
116 }
117 ensure_sufficient_stack(|| {
119 self.parse_ty_common(
120 AllowPlus::Yes,
121 AllowCVariadic::No,
122 RecoverQPath::Yes,
123 RecoverReturnSign::Yes,
124 None,
125 RecoverQuestionMark::Yes,
126 )
127 })
128 }
129
130 pub(super) fn parse_ty_with_generics_recovery(
131 &mut self,
132 ty_params: &Generics,
133 ) -> PResult<'a, Box<Ty>> {
134 self.parse_ty_common(
135 AllowPlus::Yes,
136 AllowCVariadic::No,
137 RecoverQPath::Yes,
138 RecoverReturnSign::Yes,
139 Some(ty_params),
140 RecoverQuestionMark::Yes,
141 )
142 }
143
144 pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, Box<Ty>> {
148 let ty = self.parse_ty_common(
149 AllowPlus::Yes,
150 AllowCVariadic::Yes,
151 RecoverQPath::Yes,
152 RecoverReturnSign::Yes,
153 None,
154 RecoverQuestionMark::Yes,
155 )?;
156
157 if self.may_recover()
159 && self.check_noexpect(&token::Eq)
160 && self.look_ahead(1, |tok| tok.can_begin_expr())
161 {
162 let snapshot = self.create_snapshot_for_diagnostic();
163 self.bump();
164 let eq_span = self.prev_token.span;
165 match self.parse_expr() {
166 Ok(e) => {
167 self.dcx()
168 .struct_span_err(eq_span.to(e.span), "parameter defaults are not supported")
169 .emit();
170 }
171 Err(diag) => {
172 diag.cancel();
173 self.restore_snapshot(snapshot);
174 }
175 }
176 }
177
178 Ok(ty)
179 }
180
181 pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, Box<Ty>> {
188 self.parse_ty_common(
189 AllowPlus::No,
190 AllowCVariadic::No,
191 RecoverQPath::Yes,
192 RecoverReturnSign::Yes,
193 None,
194 RecoverQuestionMark::Yes,
195 )
196 }
197
198 pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, Box<Ty>> {
201 self.parse_ty_common(
202 AllowPlus::No,
203 AllowCVariadic::No,
204 RecoverQPath::Yes,
205 RecoverReturnSign::Yes,
206 None,
207 RecoverQuestionMark::No,
208 )
209 }
210
211 pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, Box<Ty>> {
212 self.parse_ty_common(
213 AllowPlus::Yes,
214 AllowCVariadic::No,
215 RecoverQPath::Yes,
216 RecoverReturnSign::Yes,
217 None,
218 RecoverQuestionMark::No,
219 )
220 }
221
222 pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, Box<Ty>> {
225 self.parse_ty_common(
226 AllowPlus::Yes,
227 AllowCVariadic::No,
228 RecoverQPath::Yes,
229 RecoverReturnSign::OnlyFatArrow,
230 None,
231 RecoverQuestionMark::Yes,
232 )
233 }
234
235 pub(super) fn parse_ret_ty(
237 &mut self,
238 allow_plus: AllowPlus,
239 recover_qpath: RecoverQPath,
240 recover_return_sign: RecoverReturnSign,
241 ) -> PResult<'a, FnRetTy> {
242 let lo = self.prev_token.span;
243 Ok(if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::RArrow,
token_type: crate::parser::token_type::TokenType::RArrow,
}exp!(RArrow)) {
244 let ty = self.parse_ty_common(
246 allow_plus,
247 AllowCVariadic::No,
248 recover_qpath,
249 recover_return_sign,
250 None,
251 RecoverQuestionMark::Yes,
252 )?;
253 FnRetTy::Ty(ty)
254 } else if recover_return_sign.can_recover(&self.token.kind) {
255 self.bump();
258 self.dcx().emit_err(ReturnTypesUseThinArrow {
259 span: self.prev_token.span,
260 suggestion: lo.between(self.token.span),
261 });
262 let ty = self.parse_ty_common(
263 allow_plus,
264 AllowCVariadic::No,
265 recover_qpath,
266 recover_return_sign,
267 None,
268 RecoverQuestionMark::Yes,
269 )?;
270 FnRetTy::Ty(ty)
271 } else {
272 FnRetTy::Default(self.prev_token.span.shrink_to_hi())
273 })
274 }
275
276 fn parse_ty_common(
277 &mut self,
278 allow_plus: AllowPlus,
279 allow_c_variadic: AllowCVariadic,
280 recover_qpath: RecoverQPath,
281 recover_return_sign: RecoverReturnSign,
282 ty_generics: Option<&Generics>,
283 recover_question_mark: RecoverQuestionMark,
284 ) -> PResult<'a, Box<Ty>> {
285 let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
286 if allow_qpath_recovery && self.may_recover() &&
let Some(mv_kind) = self.token.is_metavar_seq() &&
let token::MetaVarKind::Ty { .. } = mv_kind &&
self.check_noexpect_past_close_delim(&token::PathSep) {
let ty =
self.eat_metavar_seq(mv_kind,
|this|
this.parse_ty_no_question_mark_recover()).expect("metavar seq ty");
return self.maybe_recover_from_bad_qpath_stage_2(self.prev_token.span,
ty);
};maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
287 if self.token == token::Pound && self.look_ahead(1, |t| *t == token::OpenBracket) {
288 let attrs_wrapper = self.parse_outer_attributes()?;
289 let raw_attrs = attrs_wrapper.take_for_recovery(self.psess);
290 let attr_span = raw_attrs[0].span.to(raw_attrs.last().unwrap().span);
291 let (full_span, guar) = match self.parse_ty() {
292 Ok(ty) => {
293 let full_span = attr_span.until(ty.span);
294 let guar = self
295 .dcx()
296 .emit_err(AttributeOnType { span: attr_span, fix_span: full_span });
297 (attr_span, guar)
298 }
299 Err(err) => {
300 err.cancel();
301 let guar = self.dcx().emit_err(AttributeOnEmptyType { span: attr_span });
302 (attr_span, guar)
303 }
304 };
305
306 return Ok(self.mk_ty(full_span, TyKind::Err(guar)));
307 }
308 if let Some(ty) = self.eat_metavar_seq_with_matcher(
309 |mv_kind| #[allow(non_exhaustive_omitted_patterns)] match mv_kind {
MetaVarKind::Ty { .. } => true,
_ => false,
}matches!(mv_kind, MetaVarKind::Ty { .. }),
310 |this| this.parse_ty_no_question_mark_recover(),
311 ) {
312 return Ok(ty);
313 }
314
315 let lo = self.token.span;
316 let mut impl_dyn_multi = false;
317 let kind = if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) {
318 self.parse_ty_tuple_or_parens(lo, allow_plus)?
319 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
320 TyKind::Never
322 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Star,
token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star)) {
323 self.parse_ty_ptr()?
324 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBracket,
token_type: crate::parser::token_type::TokenType::OpenBracket,
}exp!(OpenBracket)) {
325 self.parse_array_or_slice_ty()?
326 } else if self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::And,
token_type: crate::parser::token_type::TokenType::And,
}exp!(And)) || self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::AndAnd,
token_type: crate::parser::token_type::TokenType::AndAnd,
}exp!(AndAnd)) {
327 self.expect_and()?;
329 self.parse_borrowed_pointee()?
330 } else if self.eat_keyword_noexpect(kw::Typeof) {
331 self.parse_typeof_ty(lo)?
332 } else if self.is_builtin() {
333 self.parse_builtin_ty()?
334 } else if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Underscore,
token_type: crate::parser::token_type::TokenType::KwUnderscore,
}exp!(Underscore)) {
335 TyKind::Infer
337 } else if self.check_fn_front_matter(false, Case::Sensitive) {
338 self.parse_ty_fn_ptr(lo, ThinVec::new(), None, recover_return_sign)?
340 } else if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::For,
token_type: crate::parser::token_type::TokenType::KwFor,
}exp!(For)) {
341 let (bound_vars, _) = self.parse_higher_ranked_binder()?;
345 if self.check_fn_front_matter(false, Case::Sensitive) {
346 self.parse_ty_fn_ptr(
347 lo,
348 bound_vars,
349 Some(self.prev_token.span.shrink_to_lo()),
350 recover_return_sign,
351 )?
352 } else {
353 if self.may_recover()
355 && (self.eat_keyword_noexpect(kw::Impl) || self.eat_keyword_noexpect(kw::Dyn))
356 {
357 let kw = self.prev_token.ident().unwrap().0;
358 let removal_span = kw.span.with_hi(self.token.span.lo());
359 let path = self.parse_path(PathStyle::Type)?;
360 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
361 let kind = self.parse_remaining_bounds_path(
362 bound_vars,
363 path,
364 lo,
365 parse_plus,
366 ast::Parens::No,
367 )?;
368 let err = self.dcx().create_err(errors::TransposeDynOrImpl {
369 span: kw.span,
370 kw: kw.name.as_str(),
371 sugg: errors::TransposeDynOrImplSugg {
372 removal_span,
373 insertion_span: lo.shrink_to_lo(),
374 kw: kw.name.as_str(),
375 },
376 });
377
378 let kind = match (kind, kw.name) {
381 (TyKind::TraitObject(bounds, _), kw::Dyn) => {
382 TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)
383 }
384 (TyKind::TraitObject(bounds, _), kw::Impl) => {
385 TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)
386 }
387 _ => return Err(err),
388 };
389 err.emit();
390 kind
391 } else {
392 let path = self.parse_path(PathStyle::Type)?;
393 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
394 self.parse_remaining_bounds_path(
395 bound_vars,
396 path,
397 lo,
398 parse_plus,
399 ast::Parens::No,
400 )?
401 }
402 }
403 } else if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Impl,
token_type: crate::parser::token_type::TokenType::KwImpl,
}exp!(Impl)) {
404 self.parse_impl_ty(&mut impl_dyn_multi)?
405 } else if self.is_explicit_dyn_type() {
406 self.parse_dyn_ty(&mut impl_dyn_multi)?
407 } else if self.eat_lt() {
408 let (qself, path) = self.parse_qpath(PathStyle::Type)?;
410 TyKind::Path(Some(qself), path)
411 } else if (self.token.is_keyword(kw::Const) || self.token.is_keyword(kw::Mut))
412 && self.look_ahead(1, |t| *t == token::Star)
413 {
414 self.parse_ty_c_style_pointer()?
415 } else if self.check_path() {
416 self.parse_path_start_ty(lo, allow_plus, ty_generics)?
417 } else if self.can_begin_bound() {
418 self.parse_bare_trait_object(lo, allow_plus)?
419 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::DotDotDot,
token_type: crate::parser::token_type::TokenType::DotDotDot,
}exp!(DotDotDot)) {
420 match allow_c_variadic {
421 AllowCVariadic::Yes => TyKind::CVarArgs,
422 AllowCVariadic::No => {
423 let guar = self.dcx().emit_err(NestedCVariadicType { span: lo });
427 TyKind::Err(guar)
428 }
429 }
430 } else if self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}exp!(Unsafe))
431 && self.look_ahead(1, |tok| tok.kind == token::Lt)
432 {
433 self.parse_unsafe_binder_ty()?
434 } else {
435 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected type, found {0}",
super::token_descr(&self.token)))
})format!("expected type, found {}", super::token_descr(&self.token));
436 let mut err = self.dcx().struct_span_err(lo, msg);
437 err.span_label(lo, "expected type");
438 return Err(err);
439 };
440
441 let span = lo.to(self.prev_token.span);
442 let mut ty = self.mk_ty(span, kind);
443
444 match allow_plus {
446 AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?,
447 AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty),
448 }
449 if let RecoverQuestionMark::Yes = recover_question_mark {
450 ty = self.maybe_recover_from_question_mark(ty);
451 }
452 if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
453 }
454
455 fn parse_unsafe_binder_ty(&mut self) -> PResult<'a, TyKind> {
456 let lo = self.token.span;
457 if !self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Unsafe,
token_type: crate::parser::token_type::TokenType::KwUnsafe,
}) {
::core::panicking::panic("assertion failed: self.eat_keyword(exp!(Unsafe))")
};assert!(self.eat_keyword(exp!(Unsafe)));
458 self.expect_lt()?;
459 let generic_params = self.parse_generic_params()?;
460 self.expect_gt()?;
461 let inner_ty = self.parse_ty()?;
462 let span = lo.to(self.prev_token.span);
463 self.psess.gated_spans.gate(sym::unsafe_binders, span);
464
465 Ok(TyKind::UnsafeBinder(Box::new(UnsafeBinderTy { generic_params, inner_ty })))
466 }
467
468 fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
472 let mut trailing_plus = false;
473 let (ts, trailing) = self.parse_paren_comma_seq(|p| {
474 let ty = p.parse_ty()?;
475 trailing_plus = p.prev_token == TokenKind::Plus;
476 Ok(ty)
477 })?;
478
479 if ts.len() == 1 && #[allow(non_exhaustive_omitted_patterns)] match trailing {
Trailing::No => true,
_ => false,
}matches!(trailing, Trailing::No) {
480 let ty = ts.into_iter().next().unwrap();
481 let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus();
482 match ty.kind {
483 TyKind::Path(None, path) if maybe_bounds => self.parse_remaining_bounds_path(
485 ThinVec::new(),
486 path,
487 lo,
488 true,
489 ast::Parens::Yes,
490 ),
491 TyKind::TraitObject(bounds, TraitObjectSyntax::None)
495 if maybe_bounds && bounds.len() == 1 && !trailing_plus =>
496 {
497 self.parse_remaining_bounds(bounds, true)
498 }
499 _ => Ok(TyKind::Paren(ty)),
501 }
502 } else {
503 Ok(TyKind::Tup(ts))
504 }
505 }
506
507 fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
508 if self.token.is_lifetime() && !self.look_ahead(1, |t| t.is_like_plus()) {
510 if self.psess.edition.at_least_rust_2021() {
514 let lt = self.expect_lifetime();
515 let mut err = self.dcx().struct_span_err(lo, "expected type, found lifetime");
516 err.span_label(lo, "expected type");
517 return Ok(match self.maybe_recover_ref_ty_no_leading_ampersand(lt, lo, err) {
518 Ok(ref_ty) => ref_ty,
519 Err(err) => TyKind::Err(err.emit()),
520 });
521 }
522
523 self.dcx().emit_err(NeedPlusAfterTraitObjectLifetime {
524 span: lo,
525 suggestion: lo.shrink_to_hi(),
526 });
527 }
528 Ok(TyKind::TraitObject(
529 self.parse_generic_bounds_common(allow_plus)?,
530 TraitObjectSyntax::None,
531 ))
532 }
533
534 fn maybe_recover_ref_ty_no_leading_ampersand<'cx>(
535 &mut self,
536 lt: Lifetime,
537 lo: Span,
538 mut err: Diag<'cx>,
539 ) -> Result<TyKind, Diag<'cx>> {
540 if !self.may_recover() {
541 return Err(err);
542 }
543 let snapshot = self.create_snapshot_for_diagnostic();
544 let mutbl = self.parse_mutability();
545 match self.parse_ty_no_plus() {
546 Ok(ty) => {
547 err.span_suggestion_verbose(
548 lo.shrink_to_lo(),
549 "you might have meant to write a reference type here",
550 "&",
551 Applicability::MaybeIncorrect,
552 );
553 err.emit();
554 Ok(TyKind::Ref(Some(lt), MutTy { ty, mutbl }))
555 }
556 Err(diag) => {
557 diag.cancel();
558 self.restore_snapshot(snapshot);
559 Err(err)
560 }
561 }
562 }
563
564 fn parse_remaining_bounds_path(
565 &mut self,
566 generic_params: ThinVec<GenericParam>,
567 path: ast::Path,
568 lo: Span,
569 parse_plus: bool,
570 parens: ast::Parens,
571 ) -> PResult<'a, TyKind> {
572 let poly_trait_ref = PolyTraitRef::new(
573 generic_params,
574 path,
575 TraitBoundModifiers::NONE,
576 lo.to(self.prev_token.span),
577 parens,
578 );
579 let bounds = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[GenericBound::Trait(poly_trait_ref)]))vec![GenericBound::Trait(poly_trait_ref)];
580 self.parse_remaining_bounds(bounds, parse_plus)
581 }
582
583 fn parse_remaining_bounds(
585 &mut self,
586 mut bounds: GenericBounds,
587 plus: bool,
588 ) -> PResult<'a, TyKind> {
589 if plus {
590 self.eat_plus(); bounds.append(&mut self.parse_generic_bounds()?);
592 }
593 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
594 }
595
596 fn parse_ty_c_style_pointer(&mut self) -> PResult<'a, TyKind> {
598 let kw_span = self.token.span;
599 let mutbl = self.parse_mut_or_const();
600
601 if let Some(mutbl) = mutbl
602 && self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Star,
token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star))
603 {
604 let star_span = self.prev_token.span;
605
606 let mutability = match mutbl {
607 Mutability::Not => "const",
608 Mutability::Mut => "mut",
609 };
610
611 let ty = self.parse_ty_no_question_mark_recover()?;
612
613 self.dcx()
614 .struct_span_err(
615 kw_span,
616 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("raw pointer types must be written as `*{0} T`",
mutability))
})format!("raw pointer types must be written as `*{mutability} T`"),
617 )
618 .with_multipart_suggestion(
619 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("put the `*` before `{0}`",
mutability))
})format!("put the `*` before `{mutability}`"),
620 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(star_span, String::new()),
(kw_span.shrink_to_lo(), "*".to_string())]))vec![(star_span, String::new()), (kw_span.shrink_to_lo(), "*".to_string())],
621 Applicability::MachineApplicable,
622 )
623 .emit();
624
625 return Ok(TyKind::Ptr(MutTy { ty, mutbl }));
626 }
627 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("this could never happen")));
}unreachable!("this could never happen")
629 }
630
631 fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
633 let mutbl = self.parse_mut_or_const().unwrap_or_else(|| {
634 let span = self.prev_token.span;
635 self.dcx().emit_err(ExpectedMutOrConstInRawPointerType {
636 span,
637 after_asterisk: span.shrink_to_hi(),
638 });
639 Mutability::Not
640 });
641 let ty = self.parse_ty_no_plus()?;
642 Ok(TyKind::Ptr(MutTy { ty, mutbl }))
643 }
644
645 fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {
648 let elt_ty = match self.parse_ty() {
649 Ok(ty) => ty,
650 Err(err)
651 if self.look_ahead(1, |t| *t == token::CloseBracket)
652 | self.look_ahead(1, |t| *t == token::Semi) =>
653 {
654 self.bump();
656 let guar = err.emit();
657 self.mk_ty(self.prev_token.span, TyKind::Err(guar))
658 }
659 Err(err) => return Err(err),
660 };
661
662 let ty = if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Semi,
token_type: crate::parser::token_type::TokenType::Semi,
}exp!(Semi)) {
663 let mut length = self.parse_expr_anon_const(|_, _| MgcaDisambiguation::Direct)?;
664
665 if let Err(e) = self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBracket,
token_type: crate::parser::token_type::TokenType::CloseBracket,
}exp!(CloseBracket)) {
666 self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
668 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBracket,
token_type: crate::parser::token_type::TokenType::CloseBracket,
}exp!(CloseBracket))?;
669 }
670 TyKind::Array(elt_ty, length)
671 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBracket,
token_type: crate::parser::token_type::TokenType::CloseBracket,
}exp!(CloseBracket)) {
672 TyKind::Slice(elt_ty)
673 } else {
674 self.maybe_recover_array_ty_without_semi(elt_ty)?
675 };
676
677 Ok(ty)
678 }
679
680 fn maybe_recover_array_ty_without_semi(&mut self, elt_ty: Box<Ty>) -> PResult<'a, TyKind> {
687 let span = self.token.span;
688 let token_descr = super::token_descr(&self.token);
689 let mut err =
690 self.dcx().struct_span_err(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected `;` or `]`, found {0}",
token_descr))
})format!("expected `;` or `]`, found {}", token_descr));
691 err.span_label(span, "expected `;` or `]`");
692
693 if !self.may_recover() {
695 return Err(err);
696 }
697
698 let snapshot = self.create_snapshot_for_diagnostic();
699
700 let hi = self.prev_token.span.hi();
702 _ = self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma)) || self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Colon,
token_type: crate::parser::token_type::TokenType::Colon,
}exp!(Colon)) || self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Star,
token_type: crate::parser::token_type::TokenType::Star,
}exp!(Star));
703 let suggestion_span = self.prev_token.span.with_lo(hi);
704
705 let length = match self.parse_expr_anon_const(|_, _| MgcaDisambiguation::Direct) {
708 Ok(length) => length,
709 Err(e) => {
710 e.cancel();
711 self.restore_snapshot(snapshot);
712 return Err(err);
713 }
714 };
715
716 if let Err(e) = self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseBracket,
token_type: crate::parser::token_type::TokenType::CloseBracket,
}exp!(CloseBracket)) {
717 e.cancel();
718 self.restore_snapshot(snapshot);
719 return Err(err);
720 }
721
722 err.span_suggestion_verbose(
723 suggestion_span,
724 "you might have meant to use `;` as the separator",
725 ";",
726 Applicability::MaybeIncorrect,
727 );
728 err.emit();
729 Ok(TyKind::Array(elt_ty, length))
730 }
731
732 fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
733 let and_span = self.prev_token.span;
734 let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());
735 let (pinned, mut mutbl) = self.parse_pin_and_mut();
736 if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
737 if !self.look_ahead(1, |t| t.is_like_plus()) {
743 let lifetime_span = self.token.span;
744 let span = and_span.to(lifetime_span);
745
746 let (suggest_lifetime, snippet) =
747 if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
748 (Some(span), lifetime_src)
749 } else {
750 (None, String::new())
751 };
752 self.dcx().emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });
753
754 opt_lifetime = Some(self.expect_lifetime());
755 }
756 } else if self.token.is_keyword(kw::Dyn)
757 && mutbl == Mutability::Not
758 && self.look_ahead(1, |t| t.is_keyword(kw::Mut))
759 {
760 let span = and_span.to(self.look_ahead(1, |t| t.span));
762 self.dcx().emit_err(DynAfterMut { span });
763
764 mutbl = Mutability::Mut;
766 let (dyn_tok, dyn_tok_sp) = (self.token, self.token_spacing);
767 self.bump();
768 self.bump_with((dyn_tok, dyn_tok_sp));
769 }
770 let ty = self.parse_ty_no_plus()?;
771 Ok(match pinned {
772 Pinnedness::Not => TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }),
773 Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl }),
774 })
775 }
776
777 pub(crate) fn parse_pin_and_mut(&mut self) -> (Pinnedness, Mutability) {
783 if self.token.is_ident_named(sym::pin) && self.look_ahead(1, Token::is_mutability) {
784 self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span);
785 if !self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::sym::pin,
token_type: crate::parser::token_type::TokenType::SymPin,
}) {
::core::panicking::panic("assertion failed: self.eat_keyword(exp!(Pin))")
};assert!(self.eat_keyword(exp!(Pin)));
786 let mutbl = self.parse_mut_or_const().unwrap();
787 (Pinnedness::Pinned, mutbl)
788 } else {
789 (Pinnedness::Not, self.parse_mutability())
790 }
791 }
792
793 fn parse_typeof_ty(&mut self, lo: Span) -> PResult<'a, TyKind> {
796 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen))?;
797 let _expr = self.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?;
798 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen))?;
799 let span = lo.to(self.prev_token.span);
800 let guar = self
801 .dcx()
802 .struct_span_err(span, "`typeof` is a reserved keyword but unimplemented")
803 .with_note("consider replacing `typeof(...)` with an actual type")
804 .with_code(E0516)
805 .emit();
806 Ok(TyKind::Err(guar))
807 }
808
809 fn parse_builtin_ty(&mut self) -> PResult<'a, TyKind> {
810 self.parse_builtin(|this, lo, ident| {
811 Ok(match ident.name {
812 sym::field_of => Some(this.parse_ty_field_of(lo)?),
813 _ => None,
814 })
815 })
816 }
817
818 pub(crate) fn parse_ty_field_of(&mut self, _lo: Span) -> PResult<'a, TyKind> {
819 let container = self.parse_ty()?;
820 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma))?;
821
822 let fields = self.parse_floating_field_access()?;
823 let trailing_comma = self.eat_noexpect(&TokenKind::Comma);
824
825 if let Err(mut e) = self.expect_one_of(&[], &[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen)]) {
826 if trailing_comma {
827 e.note("unexpected third argument to field_of");
828 } else {
829 e.note("field_of expects dot-separated field and variant names");
830 }
831 e.emit();
832 }
833
834 if self.may_recover() {
836 while !self.token.kind.is_close_delim_or_eof() {
837 self.bump();
838 }
839 }
840
841 match *fields {
842 [] => Err(self.dcx().struct_span_err(
843 self.token.span,
844 "`field_of!` expects dot-separated field and variant names",
845 )),
846 [field] => Ok(TyKind::FieldOf(container, None, field)),
847 [variant, field] => Ok(TyKind::FieldOf(container, Some(variant), field)),
848 _ => Err(self.dcx().struct_span_err(
849 fields.iter().map(|f| f.span).collect::<Vec<_>>(),
850 "`field_of!` only supports a single field or a variant with a field",
851 )),
852 }
853 }
854
855 fn parse_ty_fn_ptr(
865 &mut self,
866 lo: Span,
867 mut params: ThinVec<GenericParam>,
868 param_insertion_point: Option<Span>,
869 recover_return_sign: RecoverReturnSign,
870 ) -> PResult<'a, TyKind> {
871 let inherited_vis = rustc_ast::Visibility {
872 span: rustc_span::DUMMY_SP,
873 kind: rustc_ast::VisibilityKind::Inherited,
874 tokens: None,
875 };
876 let span_start = self.token.span;
877 let ast::FnHeader { ext, safety, .. } = self.parse_fn_front_matter(
878 &inherited_vis,
879 Case::Sensitive,
880 FrontMatterParsingMode::FunctionPtrType,
881 )?;
882 if self.may_recover() && self.token == TokenKind::Lt {
883 self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
884 }
885 let mode = crate::parser::item::FnParseMode {
886 req_name: |_, _| false,
887 context: FnContext::Free,
888 req_body: false,
889 };
890 let decl = self.parse_fn_decl(&mode, AllowPlus::No, recover_return_sign)?;
891
892 let decl_span = span_start.to(self.prev_token.span);
893 Ok(TyKind::FnPtr(Box::new(FnPtrTy {
894 ext,
895 safety,
896 generic_params: params,
897 decl,
898 decl_span,
899 })))
900 }
901
902 fn recover_fn_ptr_with_generics(
904 &mut self,
905 lo: Span,
906 params: &mut ThinVec<GenericParam>,
907 param_insertion_point: Option<Span>,
908 ) -> PResult<'a, ()> {
909 let generics = self.parse_generics()?;
910 let arity = generics.params.len();
911
912 let mut lifetimes: ThinVec<_> = generics
913 .params
914 .into_iter()
915 .filter(|param| #[allow(non_exhaustive_omitted_patterns)] match param.kind {
ast::GenericParamKind::Lifetime => true,
_ => false,
}matches!(param.kind, ast::GenericParamKind::Lifetime))
916 .collect();
917
918 let sugg = if !lifetimes.is_empty() {
919 let snippet =
920 lifetimes.iter().map(|param| param.ident.as_str()).intersperse(", ").collect();
921
922 let (left, snippet) = if let Some(span) = param_insertion_point {
923 (span, if params.is_empty() { snippet } else { ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(", {0}", snippet))
})format!(", {snippet}") })
924 } else {
925 (lo.shrink_to_lo(), ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("for<{0}> ", snippet))
})format!("for<{snippet}> "))
926 };
927
928 Some(FnPtrWithGenericsSugg {
929 left,
930 snippet,
931 right: generics.span,
932 arity,
933 for_param_list_exists: param_insertion_point.is_some(),
934 })
935 } else {
936 None
937 };
938
939 self.dcx().emit_err(FnPtrWithGenerics { span: generics.span, sugg });
940 params.append(&mut lifetimes);
941 Ok(())
942 }
943
944 fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
946 if self.token.is_lifetime() {
947 self.look_ahead(1, |t| {
948 if let token::Ident(sym, _) = t.kind {
949 self.dcx().emit_err(errors::MissingPlusBounds {
952 span: self.token.span,
953 hi: self.token.span.shrink_to_hi(),
954 sym,
955 });
956 }
957 })
958 }
959
960 let bounds = self.parse_generic_bounds()?;
962
963 *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
964
965 Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))
966 }
967
968 fn parse_use_bound(&mut self, lo: Span, parens: ast::Parens) -> PResult<'a, GenericBound> {
975 self.expect_lt()?;
976 let (args, _, _) = self.parse_seq_to_before_tokens(
977 &[crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Gt,
token_type: crate::parser::token_type::TokenType::Gt,
}exp!(Gt)],
978 &[&TokenKind::Ge, &TokenKind::Shr, &TokenKind::Shr],
979 SeqSep::trailing_allowed(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Comma,
token_type: crate::parser::token_type::TokenType::Comma,
}exp!(Comma)),
980 |self_| {
981 if self_.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::SelfUpper,
token_type: crate::parser::token_type::TokenType::KwSelfUpper,
}exp!(SelfUpper)) {
982 self_.bump();
983 Ok(PreciseCapturingArg::Arg(
984 ast::Path::from_ident(self_.prev_token.ident().unwrap().0),
985 DUMMY_NODE_ID,
986 ))
987 } else if self_.check_ident() {
988 Ok(PreciseCapturingArg::Arg(
989 ast::Path::from_ident(self_.parse_ident()?),
990 DUMMY_NODE_ID,
991 ))
992 } else if self_.check_lifetime() {
993 Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))
994 } else {
995 self_.unexpected_any()
996 }
997 },
998 )?;
999 self.expect_gt()?;
1000
1001 if let ast::Parens::Yes = parens {
1002 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen))?;
1003 self.report_parenthesized_bound(lo, self.prev_token.span, "precise capturing lists");
1004 }
1005
1006 Ok(GenericBound::Use(args, lo.to(self.prev_token.span)))
1007 }
1008
1009 fn is_explicit_dyn_type(&mut self) -> bool {
1011 self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Dyn,
token_type: crate::parser::token_type::TokenType::KwDyn,
}exp!(Dyn))
1012 && (self.token_uninterpolated_span().at_least_rust_2018()
1013 || self.look_ahead(1, |&t| can_begin_dyn_bound_in_edition_2015(t)))
1014 }
1015
1016 fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
1020 self.bump(); let bounds = self.parse_generic_bounds()?;
1024 *impl_dyn_multi = bounds.len() > 1 || self.prev_token == TokenKind::Plus;
1025
1026 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn))
1027 }
1028
1029 fn parse_path_start_ty(
1036 &mut self,
1037 lo: Span,
1038 allow_plus: AllowPlus,
1039 ty_generics: Option<&Generics>,
1040 ) -> PResult<'a, TyKind> {
1041 let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
1043 if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
1044 Ok(TyKind::MacCall(Box::new(MacCall { path, args: self.parse_delim_args()? })))
1046 } else if allow_plus == AllowPlus::Yes && self.check_plus() {
1047 self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true, ast::Parens::No)
1049 } else {
1050 Ok(TyKind::Path(None, path))
1052 }
1053 }
1054
1055 pub(super) fn parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds> {
1056 self.parse_generic_bounds_common(AllowPlus::Yes)
1057 }
1058
1059 fn parse_generic_bounds_common(&mut self, allow_plus: AllowPlus) -> PResult<'a, GenericBounds> {
1064 let mut bounds = Vec::new();
1065
1066 while self.can_begin_bound()
1072 || (self.may_recover()
1073 && (self.token.can_begin_type()
1074 || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))))
1075 {
1076 if self.token.is_keyword(kw::Dyn) {
1077 self.bump();
1079 self.dcx().emit_err(InvalidDynKeyword {
1080 span: self.prev_token.span,
1081 suggestion: self.prev_token.span.until(self.token.span),
1082 });
1083 }
1084 bounds.push(self.parse_generic_bound()?);
1085 if allow_plus == AllowPlus::No || !self.eat_plus() {
1086 break;
1087 }
1088 }
1089
1090 Ok(bounds)
1091 }
1092
1093 fn can_begin_bound(&mut self) -> bool {
1095 self.check_path()
1096 || self.check_lifetime()
1097 || self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang))
1098 || self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Question,
token_type: crate::parser::token_type::TokenType::Question,
}exp!(Question))
1099 || self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Tilde,
token_type: crate::parser::token_type::TokenType::Tilde,
}exp!(Tilde))
1100 || self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::For,
token_type: crate::parser::token_type::TokenType::KwFor,
}exp!(For))
1101 || self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen))
1102 || self.can_begin_maybe_const_bound()
1103 || self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const))
1104 || self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Async,
token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async))
1105 || self.check_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Use,
token_type: crate::parser::token_type::TokenType::KwUse,
}exp!(Use))
1106 }
1107
1108 fn can_begin_maybe_const_bound(&mut self) -> bool {
1109 self.check(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenBracket,
token_type: crate::parser::token_type::TokenType::OpenBracket,
}exp!(OpenBracket))
1110 && self.look_ahead(1, |t| t.is_keyword(kw::Const))
1111 && self.look_ahead(2, |t| *t == token::CloseBracket)
1112 }
1113
1114 fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
1120 let leading_token = self.prev_token;
1121 let lo = self.token.span;
1122
1123 let parens = if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::OpenParen,
token_type: crate::parser::token_type::TokenType::OpenParen,
}exp!(OpenParen)) { ast::Parens::Yes } else { ast::Parens::No };
1129
1130 if self.token.is_lifetime() {
1131 self.parse_lifetime_bound(lo, parens)
1132 } else if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Use,
token_type: crate::parser::token_type::TokenType::KwUse,
}exp!(Use)) {
1133 self.parse_use_bound(lo, parens)
1134 } else {
1135 self.parse_trait_bound(lo, parens, &leading_token)
1136 }
1137 }
1138
1139 fn parse_lifetime_bound(&mut self, lo: Span, parens: ast::Parens) -> PResult<'a, GenericBound> {
1145 let lt = self.expect_lifetime();
1146
1147 if let ast::Parens::Yes = parens {
1148 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen))?;
1149 self.report_parenthesized_bound(lo, self.prev_token.span, "lifetime bounds");
1150 }
1151
1152 Ok(GenericBound::Outlives(lt))
1153 }
1154
1155 fn report_parenthesized_bound(&self, lo: Span, hi: Span, kind: &str) -> ErrorGuaranteed {
1156 let mut diag =
1157 self.dcx().struct_span_err(lo.to(hi), ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} may not be parenthesized",
kind))
})format!("{kind} may not be parenthesized"));
1158 diag.multipart_suggestion(
1159 "remove the parentheses",
1160 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(lo, String::new()), (hi, String::new())]))vec![(lo, String::new()), (hi, String::new())],
1161 Applicability::MachineApplicable,
1162 );
1163 diag.emit()
1164 }
1165
1166 fn error_lt_bound_with_modifiers(
1168 &self,
1169 modifiers: TraitBoundModifiers,
1170 binder_span: Option<Span>,
1171 ) -> ErrorGuaranteed {
1172 let TraitBoundModifiers { constness, asyncness, polarity } = modifiers;
1173
1174 match constness {
1175 BoundConstness::Never => {}
1176 BoundConstness::Always(span) | BoundConstness::Maybe(span) => {
1177 return self
1178 .dcx()
1179 .emit_err(errors::ModifierLifetime { span, modifier: constness.as_str() });
1180 }
1181 }
1182
1183 match polarity {
1184 BoundPolarity::Positive => {}
1185 BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => {
1186 return self
1187 .dcx()
1188 .emit_err(errors::ModifierLifetime { span, modifier: polarity.as_str() });
1189 }
1190 }
1191
1192 match asyncness {
1193 BoundAsyncness::Normal => {}
1194 BoundAsyncness::Async(span) => {
1195 return self
1196 .dcx()
1197 .emit_err(errors::ModifierLifetime { span, modifier: asyncness.as_str() });
1198 }
1199 }
1200
1201 if let Some(span) = binder_span {
1202 return self.dcx().emit_err(errors::ModifierLifetime { span, modifier: "for<...>" });
1203 }
1204
1205 {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("lifetime bound intercepted in `parse_generic_ty_bound` but no modifiers?")));
}unreachable!("lifetime bound intercepted in `parse_generic_ty_bound` but no modifiers?")
1206 }
1207
1208 fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
1220 let modifier_lo = self.token.span;
1221 let constness = self.parse_bound_constness()?;
1222
1223 let asyncness = if self.token_uninterpolated_span().at_least_rust_2018()
1224 && self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Async,
token_type: crate::parser::token_type::TokenType::KwAsync,
}exp!(Async))
1225 {
1226 self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
1227 BoundAsyncness::Async(self.prev_token.span)
1228 } else if self.may_recover()
1229 && self.token_uninterpolated_span().is_rust_2015()
1230 && self.is_kw_followed_by_ident(kw::Async)
1231 {
1232 self.bump(); self.dcx().emit_err(errors::AsyncBoundModifierIn2015 {
1234 span: self.prev_token.span,
1235 help: HelpUseLatestEdition::new(),
1236 });
1237 self.psess.gated_spans.gate(sym::async_trait_bounds, self.prev_token.span);
1238 BoundAsyncness::Async(self.prev_token.span)
1239 } else {
1240 BoundAsyncness::Normal
1241 };
1242 let modifier_hi = self.prev_token.span;
1243
1244 let polarity = if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Question,
token_type: crate::parser::token_type::TokenType::Question,
}exp!(Question)) {
1245 BoundPolarity::Maybe(self.prev_token.span)
1246 } else if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Bang,
token_type: crate::parser::token_type::TokenType::Bang,
}exp!(Bang)) {
1247 self.psess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);
1248 BoundPolarity::Negative(self.prev_token.span)
1249 } else {
1250 BoundPolarity::Positive
1251 };
1252
1253 match polarity {
1255 BoundPolarity::Positive => {
1256 }
1258 BoundPolarity::Maybe(polarity_span) | BoundPolarity::Negative(polarity_span) => {
1259 match (asyncness, constness) {
1260 (BoundAsyncness::Normal, BoundConstness::Never) => {
1261 }
1263 (_, _) => {
1264 let constness = constness.as_str();
1265 let asyncness = asyncness.as_str();
1266 let glue =
1267 if !constness.is_empty() && !asyncness.is_empty() { " " } else { "" };
1268 let modifiers_concatenated = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}{2}", constness, glue,
asyncness))
})format!("{constness}{glue}{asyncness}");
1269 self.dcx().emit_err(errors::PolarityAndModifiers {
1270 polarity_span,
1271 polarity: polarity.as_str(),
1272 modifiers_span: modifier_lo.to(modifier_hi),
1273 modifiers_concatenated,
1274 });
1275 }
1276 }
1277 }
1278 }
1279
1280 Ok(TraitBoundModifiers { constness, asyncness, polarity })
1281 }
1282
1283 pub fn parse_bound_constness(&mut self) -> PResult<'a, BoundConstness> {
1284 Ok(if self.eat(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::Tilde,
token_type: crate::parser::token_type::TokenType::Tilde,
}exp!(Tilde)) {
1287 let tilde = self.prev_token.span;
1288 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const))?;
1289 let span = tilde.to(self.prev_token.span);
1290 self.psess.gated_spans.gate(sym::const_trait_impl, span);
1291 BoundConstness::Maybe(span)
1292 } else if self.can_begin_maybe_const_bound() {
1293 let start = self.token.span;
1294 self.bump();
1295 self.expect_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const)).unwrap();
1296 self.bump();
1297 let span = start.to(self.prev_token.span);
1298 self.psess.gated_spans.gate(sym::const_trait_impl, span);
1299 BoundConstness::Maybe(span)
1300 } else if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::Const,
token_type: crate::parser::token_type::TokenType::KwConst,
}exp!(Const)) {
1301 self.psess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span);
1302 BoundConstness::Always(self.prev_token.span)
1303 } else {
1304 BoundConstness::Never
1305 })
1306 }
1307
1308 fn parse_trait_bound(
1317 &mut self,
1318 lo: Span,
1319 parens: ast::Parens,
1320 leading_token: &Token,
1321 ) -> PResult<'a, GenericBound> {
1322 let (mut bound_vars, binder_span) = self.parse_higher_ranked_binder()?;
1323
1324 let modifiers_lo = self.token.span;
1325 let modifiers = self.parse_trait_bound_modifiers()?;
1326 let modifiers_span = modifiers_lo.to(self.prev_token.span);
1327
1328 if let Some(binder_span) = binder_span {
1329 match modifiers.polarity {
1330 BoundPolarity::Negative(polarity_span) | BoundPolarity::Maybe(polarity_span) => {
1331 self.dcx().emit_err(errors::BinderAndPolarity {
1332 binder_span,
1333 polarity_span,
1334 polarity: modifiers.polarity.as_str(),
1335 });
1336 }
1337 BoundPolarity::Positive => {}
1338 }
1339 }
1340
1341 if self.token.is_lifetime() {
1344 let _: ErrorGuaranteed = self.error_lt_bound_with_modifiers(modifiers, binder_span);
1345 return self.parse_lifetime_bound(lo, parens);
1346 }
1347
1348 if let (more_bound_vars, Some(binder_span)) = self.parse_higher_ranked_binder()? {
1349 bound_vars.extend(more_bound_vars);
1350 self.dcx().emit_err(errors::BinderBeforeModifiers { binder_span, modifiers_span });
1351 }
1352
1353 let mut path = if self.token.is_keyword(kw::Fn)
1354 && self.look_ahead(1, |t| *t == TokenKind::OpenParen)
1355 && let Some(path) = self.recover_path_from_fn()
1356 {
1357 path
1358 } else if !self.token.is_path_start() && self.token.can_begin_type() {
1359 let ty = self.parse_ty_no_plus()?;
1360 let mut err = self.dcx().struct_span_err(ty.span, "expected a trait, found type");
1362
1363 let path = if self.may_recover() {
1368 let (span, message, sugg, path, applicability) = match &ty.kind {
1369 TyKind::Ptr(..) | TyKind::Ref(..)
1370 if let TyKind::Path(_, path) = &ty.peel_refs().kind =>
1371 {
1372 (
1373 ty.span.until(path.span),
1374 "consider removing the indirection",
1375 "",
1376 path,
1377 Applicability::MaybeIncorrect,
1378 )
1379 }
1380 TyKind::ImplTrait(_, bounds)
1381 if let [GenericBound::Trait(tr, ..), ..] = bounds.as_slice() =>
1382 {
1383 (
1384 ty.span.until(tr.span),
1385 "use the trait bounds directly",
1386 "",
1387 &tr.trait_ref.path,
1388 Applicability::MachineApplicable,
1389 )
1390 }
1391 _ => return Err(err),
1392 };
1393
1394 err.span_suggestion_verbose(span, message, sugg, applicability);
1395
1396 path.clone()
1397 } else {
1398 return Err(err);
1399 };
1400
1401 err.emit();
1402
1403 path
1404 } else {
1405 self.parse_path(PathStyle::Type)?
1406 };
1407
1408 if self.may_recover() && self.token == TokenKind::OpenParen {
1409 self.recover_fn_trait_with_lifetime_params(&mut path, &mut bound_vars)?;
1410 }
1411
1412 if let ast::Parens::Yes = parens {
1413 if self.token.is_like_plus() && leading_token.is_keyword(kw::Dyn) {
1416 let bounds = ::alloc::vec::Vec::new()vec![];
1417 self.parse_remaining_bounds(bounds, true)?;
1418 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen))?;
1419 self.dcx().emit_err(errors::IncorrectParensTraitBounds {
1420 span: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[lo, self.prev_token.span]))vec![lo, self.prev_token.span],
1421 sugg: errors::IncorrectParensTraitBoundsSugg {
1422 wrong_span: leading_token.span.shrink_to_hi().to(lo),
1423 new_span: leading_token.span.shrink_to_lo(),
1424 },
1425 });
1426 } else {
1427 self.expect(crate::parser::token_type::ExpTokenPair {
tok: rustc_ast::token::CloseParen,
token_type: crate::parser::token_type::TokenType::CloseParen,
}exp!(CloseParen))?;
1428 }
1429 }
1430
1431 let poly_trait =
1432 PolyTraitRef::new(bound_vars, path, modifiers, lo.to(self.prev_token.span), parens);
1433 Ok(GenericBound::Trait(poly_trait))
1434 }
1435
1436 fn recover_path_from_fn(&mut self) -> Option<ast::Path> {
1438 let fn_token_span = self.token.span;
1439 self.bump();
1440 let args_lo = self.token.span;
1441 let snapshot = self.create_snapshot_for_diagnostic();
1442 let mode =
1443 FnParseMode { req_name: |_, _| false, context: FnContext::Free, req_body: false };
1444 match self.parse_fn_decl(&mode, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
1445 Ok(decl) => {
1446 self.dcx().emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
1447 Some(ast::Path {
1448 span: fn_token_span.to(self.prev_token.span),
1449 segments: {
let len = [()].len();
let mut vec = ::thin_vec::ThinVec::with_capacity(len);
vec.push(ast::PathSegment {
ident: Ident::new(sym::Fn, fn_token_span),
id: DUMMY_NODE_ID,
args: Some(Box::new(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs {
span: args_lo.to(self.prev_token.span),
inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(),
inputs_span: args_lo.until(decl.output.span()),
output: decl.output.clone(),
}))),
});
vec
}thin_vec![ast::PathSegment {
1450 ident: Ident::new(sym::Fn, fn_token_span),
1451 id: DUMMY_NODE_ID,
1452 args: Some(Box::new(ast::GenericArgs::Parenthesized(
1453 ast::ParenthesizedArgs {
1454 span: args_lo.to(self.prev_token.span),
1455 inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(),
1456 inputs_span: args_lo.until(decl.output.span()),
1457 output: decl.output.clone(),
1458 }
1459 ))),
1460 }],
1461 tokens: None,
1462 })
1463 }
1464 Err(diag) => {
1465 diag.cancel();
1466 self.restore_snapshot(snapshot);
1467 None
1468 }
1469 }
1470 }
1471
1472 pub(super) fn parse_higher_ranked_binder(
1478 &mut self,
1479 ) -> PResult<'a, (ThinVec<GenericParam>, Option<Span>)> {
1480 if self.eat_keyword(crate::parser::token_type::ExpKeywordPair {
kw: rustc_span::symbol::kw::For,
token_type: crate::parser::token_type::TokenType::KwFor,
}exp!(For)) {
1481 let lo = self.token.span;
1482 self.expect_lt()?;
1483 let params = self.parse_generic_params()?;
1484 self.expect_gt()?;
1485 Ok((params, Some(lo.to(self.prev_token.span))))
1488 } else {
1489 Ok((ThinVec::new(), None))
1490 }
1491 }
1492
1493 fn recover_fn_trait_with_lifetime_params(
1497 &mut self,
1498 fn_path: &mut ast::Path,
1499 lifetime_defs: &mut ThinVec<GenericParam>,
1500 ) -> PResult<'a, ()> {
1501 let fn_path_segment = fn_path.segments.last_mut().unwrap();
1502 let generic_args = if let Some(p_args) = &fn_path_segment.args {
1503 *p_args.clone()
1504 } else {
1505 return Ok(());
1508 };
1509 let lifetimes =
1510 if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) =
1511 &generic_args
1512 {
1513 args.into_iter()
1514 .filter_map(|arg| {
1515 if let ast::AngleBracketedArg::Arg(generic_arg) = arg
1516 && let ast::GenericArg::Lifetime(lifetime) = generic_arg
1517 {
1518 Some(lifetime)
1519 } else {
1520 None
1521 }
1522 })
1523 .collect()
1524 } else {
1525 Vec::new()
1526 };
1527 if lifetimes.is_empty() {
1529 return Ok(());
1530 }
1531
1532 let snapshot = if self.parsing_generics {
1533 Some(self.create_snapshot_for_diagnostic())
1536 } else {
1537 None
1538 };
1539 let inputs_lo = self.token.span;
1541 let mode =
1542 FnParseMode { req_name: |_, _| false, context: FnContext::Free, req_body: false };
1543 let params = match self.parse_fn_params(&mode) {
1544 Ok(params) => params,
1545 Err(err) => {
1546 if let Some(snapshot) = snapshot {
1547 self.restore_snapshot(snapshot);
1548 err.cancel();
1549 return Ok(());
1550 } else {
1551 return Err(err);
1552 }
1553 }
1554 };
1555 let inputs: ThinVec<_> = params.into_iter().map(|input| input.ty).collect();
1556 let inputs_span = inputs_lo.to(self.prev_token.span);
1557 let output = match self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)
1558 {
1559 Ok(output) => output,
1560 Err(err) => {
1561 if let Some(snapshot) = snapshot {
1562 self.restore_snapshot(snapshot);
1563 err.cancel();
1564 return Ok(());
1565 } else {
1566 return Err(err);
1567 }
1568 }
1569 };
1570 let args = ast::ParenthesizedArgs {
1571 span: fn_path_segment.span().to(self.prev_token.span),
1572 inputs,
1573 inputs_span,
1574 output,
1575 }
1576 .into();
1577
1578 if let Some(snapshot) = snapshot
1579 && ![token::Comma, token::Gt, token::Plus].contains(&self.token.kind)
1580 {
1581 self.restore_snapshot(snapshot);
1585 return Ok(());
1586 }
1587
1588 *fn_path_segment = ast::PathSegment {
1589 ident: fn_path_segment.ident,
1590 args: Some(args),
1591 id: ast::DUMMY_NODE_ID,
1592 };
1593
1594 let mut generic_params = lifetimes
1596 .iter()
1597 .map(|lt| GenericParam {
1598 id: lt.id,
1599 ident: lt.ident,
1600 attrs: ast::AttrVec::new(),
1601 bounds: Vec::new(),
1602 is_placeholder: false,
1603 kind: ast::GenericParamKind::Lifetime,
1604 colon_span: None,
1605 })
1606 .collect::<ThinVec<GenericParam>>();
1607 lifetime_defs.append(&mut generic_params);
1608
1609 let generic_args_span = generic_args.span();
1610 let snippet = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("for<{0}> ",
lifetimes.iter().map(|lt|
lt.ident.as_str()).intersperse(", ").collect::<String>()))
})format!(
1611 "for<{}> ",
1612 lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),
1613 );
1614 let before_fn_path = fn_path.span.shrink_to_lo();
1615 self.dcx()
1616 .struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters")
1617 .with_multipart_suggestion(
1618 "consider using a higher-ranked trait bound instead",
1619 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(generic_args_span, "".to_owned()), (before_fn_path, snippet)]))vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
1620 Applicability::MaybeIncorrect,
1621 )
1622 .emit();
1623 Ok(())
1624 }
1625
1626 pub(super) fn check_lifetime(&mut self) -> bool {
1627 self.expected_token_types.insert(TokenType::Lifetime);
1628 self.token.is_lifetime()
1629 }
1630
1631 pub(super) fn expect_lifetime(&mut self) -> Lifetime {
1633 if let Some((ident, is_raw)) = self.token.lifetime() {
1634 if is_raw == IdentIsRaw::No && ident.without_first_quote().is_reserved_lifetime() {
1635 self.dcx().emit_err(errors::KeywordLifetime { span: ident.span });
1636 }
1637
1638 self.bump();
1639 Lifetime { ident, id: ast::DUMMY_NODE_ID }
1640 } else {
1641 self.dcx().span_bug(self.token.span, "not a lifetime")
1642 }
1643 }
1644
1645 pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> Box<Ty> {
1646 Box::new(Ty { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
1647 }
1648}