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