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