diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index b1cab591fd9..5f148fa6ba2 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -1,3 +1,4 @@ +use super::ty::AllowPlus; use super::{BlockMode, Parser, PathStyle, SemiColonMode, SeqSep, TokenExpectType, TokenType}; use rustc_ast_pretty::pprust; @@ -693,11 +694,11 @@ impl<'a> Parser<'a> { pub(super) fn maybe_report_ambiguous_plus( &mut self, - allow_plus: bool, + allow_plus: AllowPlus, impl_dyn_multi: bool, ty: &Ty, ) { - if !allow_plus && impl_dyn_multi { + if matches!(allow_plus, AllowPlus::No) && impl_dyn_multi { let sum_with_parens = format!("({})", pprust::ty_to_string(&ty)); self.struct_span_err(ty.span, "ambiguous `+` in a type") .span_suggestion( @@ -712,11 +713,11 @@ impl<'a> Parser<'a> { pub(super) fn maybe_recover_from_bad_type_plus( &mut self, - allow_plus: bool, + allow_plus: AllowPlus, ty: &Ty, ) -> PResult<'a, ()> { // Do not add `+` to expected tokens. - if !allow_plus || !self.token.is_like_plus() { + if matches!(allow_plus, AllowPlus::No) || !self.token.is_like_plus() { return Ok(()); } diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 0d12f8cf6c0..d9832141695 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1,4 +1,5 @@ use super::pat::{GateOr, PARAM_EXPECTED}; +use super::ty::{AllowPlus, RecoverQPath}; use super::{BlockMode, Parser, PathStyle, PrevTokenKind, Restrictions, TokenType}; use super::{SemiColonMode, SeqSep, TokenExpectType}; use crate::maybe_recover_from_interpolated_ty_qpath; @@ -1399,7 +1400,7 @@ impl<'a> Parser<'a> { self.expect_or()?; args }; - let output = self.parse_ret_ty(true, true)?; + let output = self.parse_ret_ty(AllowPlus::Yes, RecoverQPath::Yes)?; Ok(P(FnDecl { inputs, output })) } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index b7f299e56ae..87a6aa76f57 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1,4 +1,5 @@ use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error}; +use super::ty::{AllowPlus, RecoverQPath}; use super::{FollowedByType, Parser, PathStyle}; use crate::maybe_whole; @@ -1839,7 +1840,7 @@ impl<'a> Parser<'a> { fn parse_fn_sig(&mut self, cfg: &ParamCfg) -> PResult<'a, (Ident, P, Generics)> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; - let decl = self.parse_fn_decl(cfg, true)?; + let decl = self.parse_fn_decl(cfg, AllowPlus::Yes)?; generics.where_clause = self.parse_where_clause()?; Ok((ident, decl, generics)) } @@ -1848,11 +1849,11 @@ impl<'a> Parser<'a> { pub(super) fn parse_fn_decl( &mut self, cfg: &ParamCfg, - ret_allow_plus: bool, + ret_allow_plus: AllowPlus, ) -> PResult<'a, P> { Ok(P(FnDecl { inputs: self.parse_fn_params(cfg)?, - output: self.parse_ret_ty(ret_allow_plus, true)?, + output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes)?, })) } diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs index a09eb42dcfe..cb14ffb4bd0 100644 --- a/src/librustc_parse/parser/path.rs +++ b/src/librustc_parse/parser/path.rs @@ -1,3 +1,4 @@ +use super::ty::{AllowPlus, RecoverQPath}; use super::{Parser, TokenType}; use crate::maybe_whole; use rustc_errors::{pluralize, Applicability, PResult}; @@ -224,7 +225,7 @@ impl<'a> Parser<'a> { // `(T, U) -> R` let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?; let span = ident.span.to(self.prev_span); - let output = self.parse_ret_ty(false, false)?; + let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No)?; ParenthesizedArgs { inputs, output, span }.into() }; diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index c9c2cbb98ca..1ed80ed7350 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -36,6 +36,23 @@ impl BoundModifiers { } } +#[derive(Copy, Clone)] +pub(super) enum AllowPlus { + Yes, + No, +} + +pub(super) enum RecoverQPath { + Yes, + No, +} + +// Is `...` (`CVarArgs`) legal at this level of type parsing? +enum AllowCVariadic { + Yes, + No, +} + /// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT`, /// `IDENT<::AssocTy>`. /// @@ -48,14 +65,14 @@ fn can_continue_type_after_non_fn_ident(t: &Token) -> bool { impl<'a> Parser<'a> { /// Parses a type. pub fn parse_ty(&mut self) -> PResult<'a, P> { - self.parse_ty_common(true, true, false) + self.parse_ty_common(AllowPlus::Yes, RecoverQPath::Yes, AllowCVariadic::No) } /// Parse a type suitable for a function or function pointer parameter. /// The difference from `parse_ty` is that this version allows `...` /// (`CVarArgs`) at the top level of the the type. pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P> { - self.parse_ty_common(true, true, true) + self.parse_ty_common(AllowPlus::Yes, RecoverQPath::Yes, AllowCVariadic::Yes) } /// Parses a type in restricted contexts where `+` is not permitted. @@ -65,18 +82,19 @@ impl<'a> Parser<'a> { /// Example 2: `value1 as TYPE + value2` /// `+` is prohibited to avoid interactions with expression grammar. pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P> { - self.parse_ty_common(false, true, false) + self.parse_ty_common(AllowPlus::No, RecoverQPath::Yes, AllowCVariadic::No) } /// Parses an optional return type `[ -> TY ]` in a function declaration. pub(super) fn parse_ret_ty( &mut self, - allow_plus: bool, - allow_qpath_recovery: bool, + allow_plus: AllowPlus, + recover_qpath: RecoverQPath, ) -> PResult<'a, FunctionRetTy> { Ok(if self.eat(&token::RArrow) { // FIXME(Centril): Can we unconditionally `allow_plus`? - FunctionRetTy::Ty(self.parse_ty_common(allow_plus, allow_qpath_recovery, false)?) + let ty = self.parse_ty_common(allow_plus, recover_qpath, AllowCVariadic::No)?; + FunctionRetTy::Ty(ty) } else { FunctionRetTy::Default(self.token.span.shrink_to_lo()) }) @@ -84,11 +102,11 @@ impl<'a> Parser<'a> { fn parse_ty_common( &mut self, - allow_plus: bool, - allow_qpath_recovery: bool, - // Is `...` (`CVarArgs`) legal in the immediate top level call? - allow_c_variadic: bool, + allow_plus: AllowPlus, + recover_qpath: RecoverQPath, + allow_c_variadic: AllowCVariadic, ) -> PResult<'a, P> { + let allow_qpath_recovery = matches!(recover_qpath, RecoverQPath::Yes); maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); maybe_whole!(self, NtTy, |x| x); @@ -124,7 +142,7 @@ impl<'a> Parser<'a> { self.parse_ty_bare_fn(lifetime_defs)? } else { let path = self.parse_path(PathStyle::Type)?; - let parse_plus = allow_plus && self.check_plus(); + let parse_plus = matches!(allow_plus, AllowPlus::Yes) && self.check_plus(); self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)? } } else if self.eat_keyword(kw::Impl) { @@ -144,7 +162,7 @@ impl<'a> Parser<'a> { } else if self.token.is_path_start() { self.parse_path_start_ty(lo, allow_plus)? } else if self.eat(&token::DotDotDot) { - if allow_c_variadic { + if let AllowCVariadic::Yes = allow_c_variadic { TyKind::CVarArgs } else { // FIXME(Centril): Should we just allow `...` syntactically @@ -172,7 +190,7 @@ impl<'a> Parser<'a> { /// Parses either: /// - `(TYPE)`, a parenthesized type. /// - `(TYPE,)`, a tuple with a single field of type TYPE. - fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: bool) -> PResult<'a, TyKind> { + fn parse_ty_tuple_or_parens(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> { let mut trailing_plus = false; let (ts, trailing) = self.parse_paren_comma_seq(|p| { let ty = p.parse_ty()?; @@ -182,7 +200,7 @@ impl<'a> Parser<'a> { if ts.len() == 1 && !trailing { let ty = ts.into_iter().nth(0).unwrap().into_inner(); - let maybe_bounds = allow_plus && self.token.is_like_plus(); + let maybe_bounds = matches!(allow_plus, AllowPlus::Yes) && self.token.is_like_plus(); match ty.kind { // `(TY_BOUND_NOPAREN) + BOUND + ...`. TyKind::Path(None, path) if maybe_bounds => { @@ -288,7 +306,8 @@ impl<'a> Parser<'a> { let unsafety = self.parse_unsafety(); let ext = self.parse_extern()?; self.expect_keyword(kw::Fn)?; - let decl = self.parse_fn_decl(&ParamCfg { is_name_required: |_| false }, false)?; + let cfg = ParamCfg { is_name_required: |_| false }; + let decl = self.parse_fn_decl(&cfg, AllowPlus::No)?; Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params, decl }))) } @@ -326,7 +345,7 @@ impl<'a> Parser<'a> { /// 1. a type macro, `mac!(...)`, /// 2. a bare trait object, `B0 + ... + Bn`, /// 3. or a path, `path::to::MyType`. - fn parse_path_start_ty(&mut self, lo: Span, allow_plus: bool) -> PResult<'a, TyKind> { + fn parse_path_start_ty(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> { // Simple path let path = self.parse_path(PathStyle::Type)?; if self.eat(&token::Not) { @@ -336,7 +355,7 @@ impl<'a> Parser<'a> { args: self.parse_mac_args()?, prior_type_ascription: self.last_type_ascription, })) - } else if allow_plus && self.check_plus() { + } else if matches!(allow_plus, AllowPlus::Yes) && self.check_plus() { // `Trait1 + Trait2 + 'a` self.parse_remaining_bounds(Vec::new(), path, lo, true) } else { @@ -359,7 +378,7 @@ impl<'a> Parser<'a> { &mut self, colon_span: Option, ) -> PResult<'a, GenericBounds> { - self.parse_generic_bounds_common(true, colon_span) + self.parse_generic_bounds_common(AllowPlus::Yes, colon_span) } /// Parses bounds of a type parameter `BOUND + BOUND + ...`, possibly with trailing `+`. @@ -367,7 +386,7 @@ impl<'a> Parser<'a> { /// See `parse_generic_bound` for the `BOUND` grammar. fn parse_generic_bounds_common( &mut self, - allow_plus: bool, + allow_plus: AllowPlus, colon_span: Option, ) -> PResult<'a, GenericBounds> { let mut bounds = Vec::new(); @@ -377,7 +396,7 @@ impl<'a> Parser<'a> { Ok(bound) => bounds.push(bound), Err(neg_sp) => negative_bounds.push(neg_sp), } - if !allow_plus || !self.eat_plus() { + if matches!(allow_plus, AllowPlus::No) || !self.eat_plus() { break; } }