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