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