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