1 use super::{Parser, PathStyle, TokenType};
2
3 use crate::errors::{
4 self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
5 FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg,
6 InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, NestedCVariadicType,
7 ReturnTypesUseThinArrow,
8 };
9 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
10
11 use ast::DUMMY_NODE_ID;
12 use rustc_ast::ptr::P;
13 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
14 use rustc_ast::util::case::Case;
15 use rustc_ast::{
16 self as ast, BareFnTy, BoundPolarity, FnRetTy, GenericBound, GenericBounds, GenericParam,
17 Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier,
18 TraitObjectSyntax, Ty, TyKind,
19 };
20 use rustc_errors::{Applicability, PResult};
21 use rustc_span::source_map::Span;
22 use rustc_span::symbol::{kw, sym, Ident};
23 use rustc_span::Symbol;
24 use thin_vec::{thin_vec, ThinVec};
25
26 /// Any `?`, `!`, or `~const` modifiers that appear at the start of a bound.
27 struct BoundModifiers {
28 /// `?Trait`.
29 bound_polarity: BoundPolarity,
30
31 /// `~const Trait`.
32 maybe_const: Option<Span>,
33 }
34
35 impl BoundModifiers {
to_trait_bound_modifier(&self) -> TraitBoundModifier36 fn to_trait_bound_modifier(&self) -> TraitBoundModifier {
37 match (self.bound_polarity, self.maybe_const) {
38 (BoundPolarity::Positive, None) => TraitBoundModifier::None,
39 (BoundPolarity::Negative(_), None) => TraitBoundModifier::Negative,
40 (BoundPolarity::Maybe(_), None) => TraitBoundModifier::Maybe,
41 (BoundPolarity::Positive, Some(_)) => TraitBoundModifier::MaybeConst,
42 (BoundPolarity::Negative(_), Some(_)) => TraitBoundModifier::MaybeConstNegative,
43 (BoundPolarity::Maybe(_), Some(_)) => TraitBoundModifier::MaybeConstMaybe,
44 }
45 }
46 }
47
48 #[derive(Copy, Clone, PartialEq)]
49 pub(super) enum AllowPlus {
50 Yes,
51 No,
52 }
53
54 #[derive(PartialEq)]
55 pub(super) enum RecoverQPath {
56 Yes,
57 No,
58 }
59
60 pub(super) enum RecoverQuestionMark {
61 Yes,
62 No,
63 }
64
65 /// Signals whether parsing a type should recover `->`.
66 ///
67 /// More specifically, when parsing a function like:
68 /// ```compile_fail
69 /// fn foo() => u8 { 0 }
70 /// fn bar(): u8 { 0 }
71 /// ```
72 /// The compiler will try to recover interpreting `foo() => u8` as `foo() -> u8` when calling
73 /// `parse_ty` with anything except `RecoverReturnSign::No`, and it will try to recover `bar(): u8`
74 /// as `bar() -> u8` when passing `RecoverReturnSign::Yes` to `parse_ty`
75 #[derive(Copy, Clone, PartialEq)]
76 pub(super) enum RecoverReturnSign {
77 Yes,
78 OnlyFatArrow,
79 No,
80 }
81
82 impl RecoverReturnSign {
83 /// [RecoverReturnSign::Yes] allows for recovering `fn foo() => u8` and `fn foo(): u8`,
84 /// [RecoverReturnSign::OnlyFatArrow] allows for recovering only `fn foo() => u8` (recovering
85 /// colons can cause problems when parsing where clauses), and
86 /// [RecoverReturnSign::No] doesn't allow for any recovery of the return type arrow
can_recover(self, token: &TokenKind) -> bool87 fn can_recover(self, token: &TokenKind) -> bool {
88 match self {
89 Self::Yes => matches!(token, token::FatArrow | token::Colon),
90 Self::OnlyFatArrow => matches!(token, token::FatArrow),
91 Self::No => false,
92 }
93 }
94 }
95
96 // Is `...` (`CVarArgs`) legal at this level of type parsing?
97 #[derive(PartialEq)]
98 enum AllowCVariadic {
99 Yes,
100 No,
101 }
102
103 /// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
104 /// `IDENT<<u8 as Trait>::AssocTy>`.
105 ///
106 /// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes
107 /// that `IDENT` is not the ident of a fn trait.
can_continue_type_after_non_fn_ident(t: &Token) -> bool108 fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
109 t == &token::ModSep || t == &token::Lt || t == &token::BinOp(token::Shl)
110 }
111
112 impl<'a> Parser<'a> {
113 /// Parses a type.
parse_ty(&mut self) -> PResult<'a, P<Ty>>114 pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
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
parse_ty_with_generics_recovery( &mut self, ty_params: &Generics, ) -> PResult<'a, P<Ty>>125 pub(super) fn parse_ty_with_generics_recovery(
126 &mut self,
127 ty_params: &Generics,
128 ) -> PResult<'a, P<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 /// Parse a type suitable for a function or function pointer parameter.
140 /// The difference from `parse_ty` is that this version allows `...`
141 /// (`CVarArgs`) at the top level of the type.
parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>>142 pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> {
143 self.parse_ty_common(
144 AllowPlus::Yes,
145 AllowCVariadic::Yes,
146 RecoverQPath::Yes,
147 RecoverReturnSign::Yes,
148 None,
149 RecoverQuestionMark::Yes,
150 )
151 }
152
153 /// Parses a type in restricted contexts where `+` is not permitted.
154 ///
155 /// Example 1: `&'a TYPE`
156 /// `+` is prohibited to maintain operator priority (P(+) < P(&)).
157 /// Example 2: `value1 as TYPE + value2`
158 /// `+` is prohibited to avoid interactions with expression grammar.
parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>>159 pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
160 self.parse_ty_common(
161 AllowPlus::No,
162 AllowCVariadic::No,
163 RecoverQPath::Yes,
164 RecoverReturnSign::Yes,
165 None,
166 RecoverQuestionMark::Yes,
167 )
168 }
169
170 /// Parses a type following an `as` cast. Similar to `parse_ty_no_plus`, but signaling origin
171 /// for better diagnostics involving `?`.
parse_as_cast_ty(&mut self) -> PResult<'a, P<Ty>>172 pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, P<Ty>> {
173 self.parse_ty_common(
174 AllowPlus::No,
175 AllowCVariadic::No,
176 RecoverQPath::Yes,
177 RecoverReturnSign::Yes,
178 None,
179 RecoverQuestionMark::No,
180 )
181 }
182
parse_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>>183 pub(super) fn parse_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
184 self.parse_ty_common(
185 AllowPlus::Yes,
186 AllowCVariadic::No,
187 RecoverQPath::Yes,
188 RecoverReturnSign::Yes,
189 None,
190 RecoverQuestionMark::No,
191 )
192 }
193
194 /// Parse a type without recovering `:` as `->` to avoid breaking code such as `where fn() : for<'a>`
parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>>195 pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
196 self.parse_ty_common(
197 AllowPlus::Yes,
198 AllowCVariadic::Yes,
199 RecoverQPath::Yes,
200 RecoverReturnSign::OnlyFatArrow,
201 None,
202 RecoverQuestionMark::Yes,
203 )
204 }
205
206 /// Parses an optional return type `[ -> TY ]` in a function declaration.
parse_ret_ty( &mut self, allow_plus: AllowPlus, recover_qpath: RecoverQPath, recover_return_sign: RecoverReturnSign, ) -> PResult<'a, FnRetTy>207 pub(super) fn parse_ret_ty(
208 &mut self,
209 allow_plus: AllowPlus,
210 recover_qpath: RecoverQPath,
211 recover_return_sign: RecoverReturnSign,
212 ) -> PResult<'a, FnRetTy> {
213 Ok(if self.eat(&token::RArrow) {
214 // FIXME(Centril): Can we unconditionally `allow_plus`?
215 let ty = self.parse_ty_common(
216 allow_plus,
217 AllowCVariadic::No,
218 recover_qpath,
219 recover_return_sign,
220 None,
221 RecoverQuestionMark::Yes,
222 )?;
223 FnRetTy::Ty(ty)
224 } else if recover_return_sign.can_recover(&self.token.kind) {
225 // Don't `eat` to prevent `=>` from being added as an expected token which isn't
226 // actually expected and could only confuse users
227 self.bump();
228 self.sess.emit_err(ReturnTypesUseThinArrow { span: self.prev_token.span });
229 let ty = self.parse_ty_common(
230 allow_plus,
231 AllowCVariadic::No,
232 recover_qpath,
233 recover_return_sign,
234 None,
235 RecoverQuestionMark::Yes,
236 )?;
237 FnRetTy::Ty(ty)
238 } else {
239 FnRetTy::Default(self.token.span.shrink_to_lo())
240 })
241 }
242
parse_ty_common( &mut self, allow_plus: AllowPlus, allow_c_variadic: AllowCVariadic, recover_qpath: RecoverQPath, recover_return_sign: RecoverReturnSign, ty_generics: Option<&Generics>, recover_question_mark: RecoverQuestionMark, ) -> PResult<'a, P<Ty>>243 fn parse_ty_common(
244 &mut self,
245 allow_plus: AllowPlus,
246 allow_c_variadic: AllowCVariadic,
247 recover_qpath: RecoverQPath,
248 recover_return_sign: RecoverReturnSign,
249 ty_generics: Option<&Generics>,
250 recover_question_mark: RecoverQuestionMark,
251 ) -> PResult<'a, P<Ty>> {
252 let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
253 maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
254 maybe_whole!(self, NtTy, |x| x);
255
256 let lo = self.token.span;
257 let mut impl_dyn_multi = false;
258 let kind = if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
259 self.parse_ty_tuple_or_parens(lo, allow_plus)?
260 } else if self.eat(&token::Not) {
261 // Never type `!`
262 TyKind::Never
263 } else if self.eat(&token::BinOp(token::Star)) {
264 self.parse_ty_ptr()?
265 } else if self.eat(&token::OpenDelim(Delimiter::Bracket)) {
266 self.parse_array_or_slice_ty()?
267 } else if self.check(&token::BinOp(token::And)) || self.check(&token::AndAnd) {
268 // Reference
269 self.expect_and()?;
270 self.parse_borrowed_pointee()?
271 } else if self.eat_keyword_noexpect(kw::Typeof) {
272 self.parse_typeof_ty()?
273 } else if self.eat_keyword(kw::Underscore) {
274 // A type to be inferred `_`
275 TyKind::Infer
276 } else if self.check_fn_front_matter(false, Case::Sensitive) {
277 // Function pointer type
278 self.parse_ty_bare_fn(lo, ThinVec::new(), None, recover_return_sign)?
279 } else if self.check_keyword(kw::For) {
280 // Function pointer type or bound list (trait object type) starting with a poly-trait.
281 // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
282 // `for<'lt> Trait1<'lt> + Trait2 + 'a`
283 let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
284 if self.check_fn_front_matter(false, Case::Sensitive) {
285 self.parse_ty_bare_fn(
286 lo,
287 lifetime_defs,
288 Some(self.prev_token.span.shrink_to_lo()),
289 recover_return_sign,
290 )?
291 } else {
292 let path = self.parse_path(PathStyle::Type)?;
293 let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
294 self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?
295 }
296 } else if self.eat_keyword(kw::Impl) {
297 self.parse_impl_ty(&mut impl_dyn_multi)?
298 } else if self.is_explicit_dyn_type() {
299 self.parse_dyn_ty(&mut impl_dyn_multi)?
300 } else if self.eat_lt() {
301 // Qualified path
302 let (qself, path) = self.parse_qpath(PathStyle::Type)?;
303 TyKind::Path(Some(qself), path)
304 } else if self.check_path() {
305 self.parse_path_start_ty(lo, allow_plus, ty_generics)?
306 } else if self.can_begin_bound() {
307 self.parse_bare_trait_object(lo, allow_plus)?
308 } else if self.eat(&token::DotDotDot) {
309 match allow_c_variadic {
310 AllowCVariadic::Yes => TyKind::CVarArgs,
311 AllowCVariadic::No => {
312 // FIXME(Centril): Should we just allow `...` syntactically
313 // anywhere in a type and use semantic restrictions instead?
314 self.sess.emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) });
315 TyKind::Err
316 }
317 }
318 } else {
319 let msg = format!("expected type, found {}", super::token_descr(&self.token));
320 let mut err = self.struct_span_err(self.token.span, msg);
321 err.span_label(self.token.span, "expected type");
322 return Err(err);
323 };
324
325 let span = lo.to(self.prev_token.span);
326 let mut ty = self.mk_ty(span, kind);
327
328 // Try to recover from use of `+` with incorrect priority.
329 match allow_plus {
330 AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?,
331 AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty),
332 }
333 if let RecoverQuestionMark::Yes = recover_question_mark {
334 ty = self.maybe_recover_from_question_mark(ty);
335 }
336 if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
337 }
338
339 /// Parses either:
340 /// - `(TYPE)`, a parenthesized type.
341 /// - `(TYPE,)`, a tuple with a single field of type TYPE.
parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind>342 fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
343 let mut trailing_plus = false;
344 let (ts, trailing) = self.parse_paren_comma_seq(|p| {
345 let ty = p.parse_ty()?;
346 trailing_plus = p.prev_token.kind == TokenKind::BinOp(token::Plus);
347 Ok(ty)
348 })?;
349
350 if ts.len() == 1 && !trailing {
351 let ty = ts.into_iter().next().unwrap().into_inner();
352 let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus();
353 match ty.kind {
354 // `(TY_BOUND_NOPAREN) + BOUND + ...`.
355 TyKind::Path(None, path) if maybe_bounds => {
356 self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true)
357 }
358 TyKind::TraitObject(bounds, TraitObjectSyntax::None)
359 if maybe_bounds && bounds.len() == 1 && !trailing_plus =>
360 {
361 self.parse_remaining_bounds(bounds, true)
362 }
363 // `(TYPE)`
364 _ => Ok(TyKind::Paren(P(ty))),
365 }
366 } else {
367 Ok(TyKind::Tup(ts))
368 }
369 }
370
parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind>371 fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
372 let lt_no_plus = self.check_lifetime() && !self.look_ahead(1, |t| t.is_like_plus());
373 let bounds = self.parse_generic_bounds_common(allow_plus)?;
374 if lt_no_plus {
375 self.sess.emit_err(NeedPlusAfterTraitObjectLifetime { span: lo });
376 }
377 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
378 }
379
parse_remaining_bounds_path( &mut self, generic_params: ThinVec<GenericParam>, path: ast::Path, lo: Span, parse_plus: bool, ) -> PResult<'a, TyKind>380 fn parse_remaining_bounds_path(
381 &mut self,
382 generic_params: ThinVec<GenericParam>,
383 path: ast::Path,
384 lo: Span,
385 parse_plus: bool,
386 ) -> PResult<'a, TyKind> {
387 let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_token.span));
388 let bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
389 self.parse_remaining_bounds(bounds, parse_plus)
390 }
391
392 /// Parse the remainder of a bare trait object type given an already parsed list.
parse_remaining_bounds( &mut self, mut bounds: GenericBounds, plus: bool, ) -> PResult<'a, TyKind>393 fn parse_remaining_bounds(
394 &mut self,
395 mut bounds: GenericBounds,
396 plus: bool,
397 ) -> PResult<'a, TyKind> {
398 if plus {
399 self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
400 bounds.append(&mut self.parse_generic_bounds()?);
401 }
402 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
403 }
404
405 /// Parses a raw pointer type: `*[const | mut] $type`.
parse_ty_ptr(&mut self) -> PResult<'a, TyKind>406 fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
407 let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
408 let span = self.prev_token.span;
409 self.sess.emit_err(ExpectedMutOrConstInRawPointerType {
410 span,
411 after_asterisk: span.shrink_to_hi(),
412 });
413 Mutability::Not
414 });
415 let ty = self.parse_ty_no_plus()?;
416 Ok(TyKind::Ptr(MutTy { ty, mutbl }))
417 }
418
419 /// Parses an array (`[TYPE; EXPR]`) or slice (`[TYPE]`) type.
420 /// The opening `[` bracket is already eaten.
parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind>421 fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {
422 let elt_ty = match self.parse_ty() {
423 Ok(ty) => ty,
424 Err(mut err)
425 if self.look_ahead(1, |t| t.kind == token::CloseDelim(Delimiter::Bracket))
426 | self.look_ahead(1, |t| t.kind == token::Semi) =>
427 {
428 // Recover from `[LIT; EXPR]` and `[LIT]`
429 self.bump();
430 err.emit();
431 self.mk_ty(self.prev_token.span, TyKind::Err)
432 }
433 Err(err) => return Err(err),
434 };
435
436 let ty = if self.eat(&token::Semi) {
437 let mut length = self.parse_expr_anon_const()?;
438 if let Err(e) = self.expect(&token::CloseDelim(Delimiter::Bracket)) {
439 // Try to recover from `X<Y, ...>` when `X::<Y, ...>` works
440 self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
441 self.expect(&token::CloseDelim(Delimiter::Bracket))?;
442 }
443 TyKind::Array(elt_ty, length)
444 } else {
445 self.expect(&token::CloseDelim(Delimiter::Bracket))?;
446 TyKind::Slice(elt_ty)
447 };
448
449 Ok(ty)
450 }
451
parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind>452 fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
453 let and_span = self.prev_token.span;
454 let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());
455 let mut mutbl = self.parse_mutability();
456 if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
457 // A lifetime is invalid here: it would be part of a bare trait bound, which requires
458 // it to be followed by a plus, but we disallow plus in the pointee type.
459 // So we can handle this case as an error here, and suggest `'a mut`.
460 // If there *is* a plus next though, handling the error later provides better suggestions
461 // (like adding parentheses)
462 if !self.look_ahead(1, |t| t.is_like_plus()) {
463 let lifetime_span = self.token.span;
464 let span = and_span.to(lifetime_span);
465
466 let (suggest_lifetime, snippet) =
467 if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
468 (Some(span), lifetime_src)
469 } else {
470 (None, String::new())
471 };
472 self.sess.emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });
473
474 opt_lifetime = Some(self.expect_lifetime());
475 }
476 } else if self.token.is_keyword(kw::Dyn)
477 && mutbl == Mutability::Not
478 && self.look_ahead(1, |t| t.is_keyword(kw::Mut))
479 {
480 // We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.
481 let span = and_span.to(self.look_ahead(1, |t| t.span));
482 self.sess.emit_err(DynAfterMut { span });
483
484 // Recovery
485 mutbl = Mutability::Mut;
486 let (dyn_tok, dyn_tok_sp) = (self.token.clone(), self.token_spacing);
487 self.bump();
488 self.bump_with((dyn_tok, dyn_tok_sp));
489 }
490 let ty = self.parse_ty_no_plus()?;
491 Ok(TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }))
492 }
493
494 // Parses the `typeof(EXPR)`.
495 // To avoid ambiguity, the type is surrounded by parentheses.
parse_typeof_ty(&mut self) -> PResult<'a, TyKind>496 fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> {
497 self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
498 let expr = self.parse_expr_anon_const()?;
499 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
500 Ok(TyKind::Typeof(expr))
501 }
502
503 /// Parses a function pointer type (`TyKind::BareFn`).
504 /// ```ignore (illustrative)
505 /// [unsafe] [extern "ABI"] fn (S) -> T
506 /// // ^~~~~^ ^~~~^ ^~^ ^
507 /// // | | | |
508 /// // | | | Return type
509 /// // Function Style ABI Parameter types
510 /// ```
511 /// We actually parse `FnHeader FnDecl`, but we error on `const` and `async` qualifiers.
parse_ty_bare_fn( &mut self, lo: Span, mut params: ThinVec<GenericParam>, param_insertion_point: Option<Span>, recover_return_sign: RecoverReturnSign, ) -> PResult<'a, TyKind>512 fn parse_ty_bare_fn(
513 &mut self,
514 lo: Span,
515 mut params: ThinVec<GenericParam>,
516 param_insertion_point: Option<Span>,
517 recover_return_sign: RecoverReturnSign,
518 ) -> PResult<'a, TyKind> {
519 let inherited_vis = rustc_ast::Visibility {
520 span: rustc_span::DUMMY_SP,
521 kind: rustc_ast::VisibilityKind::Inherited,
522 tokens: None,
523 };
524 let span_start = self.token.span;
525 let ast::FnHeader { ext, unsafety, constness, asyncness } =
526 self.parse_fn_front_matter(&inherited_vis, Case::Sensitive)?;
527 if self.may_recover() && self.token.kind == TokenKind::Lt {
528 self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
529 }
530 let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
531 let whole_span = lo.to(self.prev_token.span);
532 if let ast::Const::Yes(span) = constness {
533 // If we ever start to allow `const fn()`, then update
534 // feature gating for `#![feature(const_extern_fn)]` to
535 // cover it.
536 self.sess.emit_err(FnPointerCannotBeConst { span: whole_span, qualifier: span });
537 }
538 if let ast::Async::Yes { span, .. } = asyncness {
539 self.sess.emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: span });
540 }
541 let decl_span = span_start.to(self.token.span);
542 Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params: params, decl, decl_span })))
543 }
544
545 /// Recover from function pointer types with a generic parameter list (e.g. `fn<'a>(&'a str)`).
recover_fn_ptr_with_generics( &mut self, lo: Span, params: &mut ThinVec<GenericParam>, param_insertion_point: Option<Span>, ) -> PResult<'a, ()>546 fn recover_fn_ptr_with_generics(
547 &mut self,
548 lo: Span,
549 params: &mut ThinVec<GenericParam>,
550 param_insertion_point: Option<Span>,
551 ) -> PResult<'a, ()> {
552 let generics = self.parse_generics()?;
553 let arity = generics.params.len();
554
555 let mut lifetimes: ThinVec<_> = generics
556 .params
557 .into_iter()
558 .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime))
559 .collect();
560
561 let sugg = if !lifetimes.is_empty() {
562 let snippet =
563 lifetimes.iter().map(|param| param.ident.as_str()).intersperse(", ").collect();
564
565 let (left, snippet) = if let Some(span) = param_insertion_point {
566 (span, if params.is_empty() { snippet } else { format!(", {snippet}") })
567 } else {
568 (lo.shrink_to_lo(), format!("for<{snippet}> "))
569 };
570
571 Some(FnPtrWithGenericsSugg {
572 left,
573 snippet,
574 right: generics.span,
575 arity,
576 for_param_list_exists: param_insertion_point.is_some(),
577 })
578 } else {
579 None
580 };
581
582 self.sess.emit_err(FnPtrWithGenerics { span: generics.span, sugg });
583 params.append(&mut lifetimes);
584 Ok(())
585 }
586
587 /// Parses an `impl B0 + ... + Bn` type.
parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind>588 fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
589 // Always parse bounds greedily for better error recovery.
590 if self.token.is_lifetime() {
591 self.look_ahead(1, |t| {
592 if let token::Ident(sym, _) = t.kind {
593 // parse pattern with "'a Sized" we're supposed to give suggestion like
594 // "'a + Sized"
595 self.sess.emit_err(errors::MissingPlusBounds {
596 span: self.token.span,
597 hi: self.token.span.shrink_to_hi(),
598 sym,
599 });
600 }
601 })
602 }
603 let bounds = self.parse_generic_bounds()?;
604 *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus);
605 Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))
606 }
607
608 /// Is a `dyn B0 + ... + Bn` type allowed here?
is_explicit_dyn_type(&mut self) -> bool609 fn is_explicit_dyn_type(&mut self) -> bool {
610 self.check_keyword(kw::Dyn)
611 && (self.token.uninterpolated_span().rust_2018()
612 || self.look_ahead(1, |t| {
613 (t.can_begin_bound() || t.kind == TokenKind::BinOp(token::Star))
614 && !can_continue_type_after_non_fn_ident(t)
615 }))
616 }
617
618 /// Parses a `dyn B0 + ... + Bn` type.
619 ///
620 /// Note that this does *not* parse bare trait objects.
parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind>621 fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
622 let lo = self.token.span;
623 self.bump(); // `dyn`
624
625 // parse dyn* types
626 let syntax = if self.eat(&TokenKind::BinOp(token::Star)) {
627 self.sess.gated_spans.gate(sym::dyn_star, lo.to(self.prev_token.span));
628 TraitObjectSyntax::DynStar
629 } else {
630 TraitObjectSyntax::Dyn
631 };
632
633 // Always parse bounds greedily for better error recovery.
634 let bounds = self.parse_generic_bounds()?;
635 *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus);
636 Ok(TyKind::TraitObject(bounds, syntax))
637 }
638
639 /// Parses a type starting with a path.
640 ///
641 /// This can be:
642 /// 1. a type macro, `mac!(...)`,
643 /// 2. a bare trait object, `B0 + ... + Bn`,
644 /// 3. or a path, `path::to::MyType`.
parse_path_start_ty( &mut self, lo: Span, allow_plus: AllowPlus, ty_generics: Option<&Generics>, ) -> PResult<'a, TyKind>645 fn parse_path_start_ty(
646 &mut self,
647 lo: Span,
648 allow_plus: AllowPlus,
649 ty_generics: Option<&Generics>,
650 ) -> PResult<'a, TyKind> {
651 // Simple path
652 let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
653 if self.eat(&token::Not) {
654 // Macro invocation in type position
655 Ok(TyKind::MacCall(P(MacCall { path, args: self.parse_delim_args()? })))
656 } else if allow_plus == AllowPlus::Yes && self.check_plus() {
657 // `Trait1 + Trait2 + 'a`
658 self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true)
659 } else {
660 // Just a type path.
661 Ok(TyKind::Path(None, path))
662 }
663 }
664
parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds>665 pub(super) fn parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds> {
666 self.parse_generic_bounds_common(AllowPlus::Yes)
667 }
668
669 /// Parses bounds of a type parameter `BOUND + BOUND + ...`, possibly with trailing `+`.
670 ///
671 /// See `parse_generic_bound` for the `BOUND` grammar.
parse_generic_bounds_common(&mut self, allow_plus: AllowPlus) -> PResult<'a, GenericBounds>672 fn parse_generic_bounds_common(&mut self, allow_plus: AllowPlus) -> PResult<'a, GenericBounds> {
673 let mut bounds = Vec::new();
674
675 // In addition to looping while we find generic bounds:
676 // We continue even if we find a keyword. This is necessary for error recovery on,
677 // for example, `impl fn()`. The only keyword that can go after generic bounds is
678 // `where`, so stop if it's it.
679 // We also continue if we find types (not traits), again for error recovery.
680 while self.can_begin_bound()
681 || (self.may_recover()
682 && (self.token.can_begin_type()
683 || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))))
684 {
685 if self.token.is_keyword(kw::Dyn) {
686 // Account for `&dyn Trait + dyn Other`.
687 self.sess.emit_err(InvalidDynKeyword { span: self.token.span });
688 self.bump();
689 }
690 bounds.push(self.parse_generic_bound()?);
691 if allow_plus == AllowPlus::No || !self.eat_plus() {
692 break;
693 }
694 }
695
696 Ok(bounds)
697 }
698
699 /// Can the current token begin a bound?
can_begin_bound(&mut self) -> bool700 fn can_begin_bound(&mut self) -> bool {
701 // This needs to be synchronized with `TokenKind::can_begin_bound`.
702 self.check_path()
703 || self.check_lifetime()
704 || self.check(&token::Not)
705 || self.check(&token::Question)
706 || self.check(&token::Tilde)
707 || self.check_keyword(kw::For)
708 || self.check(&token::OpenDelim(Delimiter::Parenthesis))
709 }
710
711 /// Parses a bound according to the grammar:
712 /// ```ebnf
713 /// BOUND = TY_BOUND | LT_BOUND
714 /// ```
parse_generic_bound(&mut self) -> PResult<'a, GenericBound>715 fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
716 let lo = self.token.span;
717 let has_parens = self.eat(&token::OpenDelim(Delimiter::Parenthesis));
718 let inner_lo = self.token.span;
719
720 let modifiers = self.parse_ty_bound_modifiers()?;
721 let bound = if self.token.is_lifetime() {
722 self.error_lt_bound_with_modifiers(modifiers);
723 self.parse_generic_lt_bound(lo, inner_lo, has_parens)?
724 } else {
725 self.parse_generic_ty_bound(lo, has_parens, modifiers)?
726 };
727
728 Ok(bound)
729 }
730
731 /// Parses a lifetime ("outlives") bound, e.g. `'a`, according to:
732 /// ```ebnf
733 /// LT_BOUND = LIFETIME
734 /// ```
parse_generic_lt_bound( &mut self, lo: Span, inner_lo: Span, has_parens: bool, ) -> PResult<'a, GenericBound>735 fn parse_generic_lt_bound(
736 &mut self,
737 lo: Span,
738 inner_lo: Span,
739 has_parens: bool,
740 ) -> PResult<'a, GenericBound> {
741 let bound = GenericBound::Outlives(self.expect_lifetime());
742 if has_parens {
743 // FIXME(Centril): Consider not erroring here and accepting `('lt)` instead,
744 // possibly introducing `GenericBound::Paren(P<GenericBound>)`?
745 self.recover_paren_lifetime(lo, inner_lo)?;
746 }
747 Ok(bound)
748 }
749
750 /// Emits an error if any trait bound modifiers were present.
error_lt_bound_with_modifiers(&self, modifiers: BoundModifiers)751 fn error_lt_bound_with_modifiers(&self, modifiers: BoundModifiers) {
752 if let Some(span) = modifiers.maybe_const {
753 self.sess.emit_err(errors::TildeConstLifetime { span });
754 }
755
756 match modifiers.bound_polarity {
757 BoundPolarity::Positive => {}
758 BoundPolarity::Negative(span) => {
759 self.sess.emit_err(errors::ModifierLifetime { span, sigil: "!" });
760 }
761 BoundPolarity::Maybe(span) => {
762 self.sess.emit_err(errors::ModifierLifetime { span, sigil: "?" });
763 }
764 }
765 }
766
767 /// Recover on `('lifetime)` with `(` already eaten.
recover_paren_lifetime(&mut self, lo: Span, inner_lo: Span) -> PResult<'a, ()>768 fn recover_paren_lifetime(&mut self, lo: Span, inner_lo: Span) -> PResult<'a, ()> {
769 let inner_span = inner_lo.to(self.prev_token.span);
770 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
771 let span = lo.to(self.prev_token.span);
772 let (sugg, snippet) = if let Ok(snippet) = self.span_to_snippet(inner_span) {
773 (Some(span), snippet)
774 } else {
775 (None, String::new())
776 };
777
778 self.sess.emit_err(errors::ParenthesizedLifetime { span, sugg, snippet });
779 Ok(())
780 }
781
782 /// Parses the modifiers that may precede a trait in a bound, e.g. `?Trait` or `~const Trait`.
783 ///
784 /// If no modifiers are present, this does not consume any tokens.
785 ///
786 /// ```ebnf
787 /// TY_BOUND_MODIFIERS = ["~const"] ["?"]
788 /// ```
parse_ty_bound_modifiers(&mut self) -> PResult<'a, BoundModifiers>789 fn parse_ty_bound_modifiers(&mut self) -> PResult<'a, BoundModifiers> {
790 let maybe_const = if self.eat(&token::Tilde) {
791 let tilde = self.prev_token.span;
792 self.expect_keyword(kw::Const)?;
793 let span = tilde.to(self.prev_token.span);
794 self.sess.gated_spans.gate(sym::const_trait_impl, span);
795 Some(span)
796 } else if self.eat_keyword(kw::Const) {
797 let span = self.prev_token.span;
798 self.sess.gated_spans.gate(sym::const_trait_impl, span);
799 self.sess.emit_err(errors::ConstMissingTilde { span, start: span.shrink_to_lo() });
800
801 Some(span)
802 } else {
803 None
804 };
805
806 let bound_polarity = if self.eat(&token::Question) {
807 BoundPolarity::Maybe(self.prev_token.span)
808 } else if self.eat(&token::Not) {
809 self.sess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);
810 BoundPolarity::Negative(self.prev_token.span)
811 } else {
812 BoundPolarity::Positive
813 };
814
815 Ok(BoundModifiers { bound_polarity, maybe_const })
816 }
817
818 /// Parses a type bound according to:
819 /// ```ebnf
820 /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
821 /// TY_BOUND_NOPAREN = [TY_BOUND_MODIFIERS] [for<LT_PARAM_DEFS>] SIMPLE_PATH
822 /// ```
823 ///
824 /// For example, this grammar accepts `~const ?for<'a: 'b> m::Trait<'a>`.
parse_generic_ty_bound( &mut self, lo: Span, has_parens: bool, modifiers: BoundModifiers, ) -> PResult<'a, GenericBound>825 fn parse_generic_ty_bound(
826 &mut self,
827 lo: Span,
828 has_parens: bool,
829 modifiers: BoundModifiers,
830 ) -> PResult<'a, GenericBound> {
831 let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?;
832 let mut path = if self.token.is_keyword(kw::Fn)
833 && self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis))
834 && let Some(path) = self.recover_path_from_fn()
835 {
836 path
837 } else if !self.token.is_path_start() && self.token.can_begin_type() {
838 let ty = self.parse_ty_no_plus()?;
839 // Instead of finding a path (a trait), we found a type.
840 let mut err = self.struct_span_err(ty.span, "expected a trait, found type");
841
842 // If we can recover, try to extract a path from the type. Note
843 // that we do not use the try operator when parsing the type because
844 // if it fails then we get a parser error which we don't want (we're trying
845 // to recover from errors, not make more).
846 let path = if self.may_recover()
847 && matches!(ty.kind, TyKind::Ptr(..) | TyKind::Ref(..))
848 && let TyKind::Path(_, path) = &ty.peel_refs().kind {
849 // Just get the indirection part of the type.
850 let span = ty.span.until(path.span);
851
852 err.span_suggestion_verbose(
853 span,
854 "consider removing the indirection",
855 "",
856 Applicability::MaybeIncorrect,
857 );
858
859 path.clone()
860 } else {
861 return Err(err);
862 };
863
864 err.emit();
865
866 path
867 } else {
868 self.parse_path(PathStyle::Type)?
869 };
870
871 if self.may_recover() && self.token == TokenKind::OpenDelim(Delimiter::Parenthesis) {
872 self.recover_fn_trait_with_lifetime_params(&mut path, &mut lifetime_defs)?;
873 }
874
875 if has_parens {
876 if self.token.is_like_plus() {
877 // Someone has written something like `&dyn (Trait + Other)`. The correct code
878 // would be `&(dyn Trait + Other)`, but we don't have access to the appropriate
879 // span to suggest that. When written as `&dyn Trait + Other`, an appropriate
880 // suggestion is given.
881 let bounds = vec![];
882 self.parse_remaining_bounds(bounds, true)?;
883 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
884 let sp = vec![lo, self.prev_token.span];
885 self.sess.emit_err(errors::IncorrectBracesTraitBounds {
886 span: sp,
887 sugg: errors::IncorrectBracesTraitBoundsSugg { l: lo, r: self.prev_token.span },
888 });
889 } else {
890 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
891 }
892 }
893
894 let modifier = modifiers.to_trait_bound_modifier();
895 let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_token.span));
896 Ok(GenericBound::Trait(poly_trait, modifier))
897 }
898
899 // recovers a `Fn(..)` parenthesized-style path from `fn(..)`
recover_path_from_fn(&mut self) -> Option<ast::Path>900 fn recover_path_from_fn(&mut self) -> Option<ast::Path> {
901 let fn_token_span = self.token.span;
902 self.bump();
903 let args_lo = self.token.span;
904 let snapshot = self.create_snapshot_for_diagnostic();
905 match self.parse_fn_decl(|_| false, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
906 Ok(decl) => {
907 self.sess.emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
908 Some(ast::Path {
909 span: fn_token_span.to(self.prev_token.span),
910 segments: thin_vec![ast::PathSegment {
911 ident: Ident::new(Symbol::intern("Fn"), fn_token_span),
912 id: DUMMY_NODE_ID,
913 args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs {
914 span: args_lo.to(self.prev_token.span),
915 inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(),
916 inputs_span: args_lo.until(decl.output.span()),
917 output: decl.output.clone(),
918 }))),
919 }],
920 tokens: None,
921 })
922 }
923 Err(diag) => {
924 diag.cancel();
925 self.restore_snapshot(snapshot);
926 None
927 }
928 }
929 }
930
931 /// Optionally parses `for<$generic_params>`.
parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, ThinVec<GenericParam>>932 pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, ThinVec<GenericParam>> {
933 if self.eat_keyword(kw::For) {
934 self.expect_lt()?;
935 let params = self.parse_generic_params()?;
936 self.expect_gt()?;
937 // We rely on AST validation to rule out invalid cases: There must not be type
938 // parameters, and the lifetime parameters must not have bounds.
939 Ok(params)
940 } else {
941 Ok(ThinVec::new())
942 }
943 }
944
945 /// Recover from `Fn`-family traits (Fn, FnMut, FnOnce) with lifetime arguments
946 /// (e.g. `FnOnce<'a>(&'a str) -> bool`). Up to generic arguments have already
947 /// been eaten.
recover_fn_trait_with_lifetime_params( &mut self, fn_path: &mut ast::Path, lifetime_defs: &mut ThinVec<GenericParam>, ) -> PResult<'a, ()>948 fn recover_fn_trait_with_lifetime_params(
949 &mut self,
950 fn_path: &mut ast::Path,
951 lifetime_defs: &mut ThinVec<GenericParam>,
952 ) -> PResult<'a, ()> {
953 let fn_path_segment = fn_path.segments.last_mut().unwrap();
954 let generic_args = if let Some(p_args) = &fn_path_segment.args {
955 p_args.clone().into_inner()
956 } else {
957 // Normally it wouldn't come here because the upstream should have parsed
958 // generic parameters (otherwise it's impossible to call this function).
959 return Ok(());
960 };
961 let lifetimes =
962 if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) =
963 &generic_args
964 {
965 args.into_iter()
966 .filter_map(|arg| {
967 if let ast::AngleBracketedArg::Arg(generic_arg) = arg
968 && let ast::GenericArg::Lifetime(lifetime) = generic_arg {
969 Some(lifetime)
970 } else {
971 None
972 }
973 })
974 .collect()
975 } else {
976 Vec::new()
977 };
978 // Only try to recover if the trait has lifetime params.
979 if lifetimes.is_empty() {
980 return Ok(());
981 }
982
983 // Parse `(T, U) -> R`.
984 let inputs_lo = self.token.span;
985 let inputs: ThinVec<_> =
986 self.parse_fn_params(|_| false)?.into_iter().map(|input| input.ty).collect();
987 let inputs_span = inputs_lo.to(self.prev_token.span);
988 let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
989 let args = ast::ParenthesizedArgs {
990 span: fn_path_segment.span().to(self.prev_token.span),
991 inputs,
992 inputs_span,
993 output,
994 }
995 .into();
996 *fn_path_segment = ast::PathSegment {
997 ident: fn_path_segment.ident,
998 args: Some(args),
999 id: ast::DUMMY_NODE_ID,
1000 };
1001
1002 // Convert parsed `<'a>` in `Fn<'a>` into `for<'a>`.
1003 let mut generic_params = lifetimes
1004 .iter()
1005 .map(|lt| GenericParam {
1006 id: lt.id,
1007 ident: lt.ident,
1008 attrs: ast::AttrVec::new(),
1009 bounds: Vec::new(),
1010 is_placeholder: false,
1011 kind: ast::GenericParamKind::Lifetime,
1012 colon_span: None,
1013 })
1014 .collect::<ThinVec<GenericParam>>();
1015 lifetime_defs.append(&mut generic_params);
1016
1017 let generic_args_span = generic_args.span();
1018 let mut err =
1019 self.struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters");
1020 let snippet = format!(
1021 "for<{}> ",
1022 lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(),
1023 );
1024 let before_fn_path = fn_path.span.shrink_to_lo();
1025 err.multipart_suggestion(
1026 "consider using a higher-ranked trait bound instead",
1027 vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)],
1028 Applicability::MaybeIncorrect,
1029 )
1030 .emit();
1031 Ok(())
1032 }
1033
check_lifetime(&mut self) -> bool1034 pub(super) fn check_lifetime(&mut self) -> bool {
1035 self.expected_tokens.push(TokenType::Lifetime);
1036 self.token.is_lifetime()
1037 }
1038
1039 /// Parses a single lifetime `'a` or panics.
expect_lifetime(&mut self) -> Lifetime1040 pub(super) fn expect_lifetime(&mut self) -> Lifetime {
1041 if let Some(ident) = self.token.lifetime() {
1042 self.bump();
1043 Lifetime { ident, id: ast::DUMMY_NODE_ID }
1044 } else {
1045 self.span_bug(self.token.span, "not a lifetime")
1046 }
1047 }
1048
mk_ty(&self, span: Span, kind: TyKind) -> P<Ty>1049 pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> P<Ty> {
1050 P(Ty { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
1051 }
1052 }
1053