parse_ty_common: use enums instead of bools.

This commit is contained in:
Mazdak Farrokhzad 2020-01-29 01:57:24 +01:00
parent c9290dceee
commit c0b7b41cff
5 changed files with 52 additions and 29 deletions

View File

@ -1,3 +1,4 @@
use super::ty::AllowPlus;
use super::{BlockMode, Parser, PathStyle, SemiColonMode, SeqSep, TokenExpectType, TokenType}; use super::{BlockMode, Parser, PathStyle, SemiColonMode, SeqSep, TokenExpectType, TokenType};
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
@ -693,11 +694,11 @@ impl<'a> Parser<'a> {
pub(super) fn maybe_report_ambiguous_plus( pub(super) fn maybe_report_ambiguous_plus(
&mut self, &mut self,
allow_plus: bool, allow_plus: AllowPlus,
impl_dyn_multi: bool, impl_dyn_multi: bool,
ty: &Ty, 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)); let sum_with_parens = format!("({})", pprust::ty_to_string(&ty));
self.struct_span_err(ty.span, "ambiguous `+` in a type") self.struct_span_err(ty.span, "ambiguous `+` in a type")
.span_suggestion( .span_suggestion(
@ -712,11 +713,11 @@ impl<'a> Parser<'a> {
pub(super) fn maybe_recover_from_bad_type_plus( pub(super) fn maybe_recover_from_bad_type_plus(
&mut self, &mut self,
allow_plus: bool, allow_plus: AllowPlus,
ty: &Ty, ty: &Ty,
) -> PResult<'a, ()> { ) -> PResult<'a, ()> {
// Do not add `+` to expected tokens. // 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(()); return Ok(());
} }

View File

@ -1,4 +1,5 @@
use super::pat::{GateOr, PARAM_EXPECTED}; use super::pat::{GateOr, PARAM_EXPECTED};
use super::ty::{AllowPlus, RecoverQPath};
use super::{BlockMode, Parser, PathStyle, PrevTokenKind, Restrictions, TokenType}; use super::{BlockMode, Parser, PathStyle, PrevTokenKind, Restrictions, TokenType};
use super::{SemiColonMode, SeqSep, TokenExpectType}; use super::{SemiColonMode, SeqSep, TokenExpectType};
use crate::maybe_recover_from_interpolated_ty_qpath; use crate::maybe_recover_from_interpolated_ty_qpath;
@ -1399,7 +1400,7 @@ impl<'a> Parser<'a> {
self.expect_or()?; self.expect_or()?;
args args
}; };
let output = self.parse_ret_ty(true, true)?; let output = self.parse_ret_ty(AllowPlus::Yes, RecoverQPath::Yes)?;
Ok(P(FnDecl { inputs, output })) Ok(P(FnDecl { inputs, output }))
} }

View File

@ -1,4 +1,5 @@
use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error}; use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error};
use super::ty::{AllowPlus, RecoverQPath};
use super::{FollowedByType, Parser, PathStyle}; use super::{FollowedByType, Parser, PathStyle};
use crate::maybe_whole; use crate::maybe_whole;
@ -1839,7 +1840,7 @@ impl<'a> Parser<'a> {
fn parse_fn_sig(&mut self, cfg: &ParamCfg) -> PResult<'a, (Ident, P<FnDecl>, Generics)> { fn parse_fn_sig(&mut self, cfg: &ParamCfg) -> PResult<'a, (Ident, P<FnDecl>, Generics)> {
let ident = self.parse_ident()?; let ident = self.parse_ident()?;
let mut generics = self.parse_generics()?; 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()?; generics.where_clause = self.parse_where_clause()?;
Ok((ident, decl, generics)) Ok((ident, decl, generics))
} }
@ -1848,11 +1849,11 @@ impl<'a> Parser<'a> {
pub(super) fn parse_fn_decl( pub(super) fn parse_fn_decl(
&mut self, &mut self,
cfg: &ParamCfg, cfg: &ParamCfg,
ret_allow_plus: bool, ret_allow_plus: AllowPlus,
) -> PResult<'a, P<FnDecl>> { ) -> PResult<'a, P<FnDecl>> {
Ok(P(FnDecl { Ok(P(FnDecl {
inputs: self.parse_fn_params(cfg)?, 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)?,
})) }))
} }

View File

@ -1,3 +1,4 @@
use super::ty::{AllowPlus, RecoverQPath};
use super::{Parser, TokenType}; use super::{Parser, TokenType};
use crate::maybe_whole; use crate::maybe_whole;
use rustc_errors::{pluralize, Applicability, PResult}; use rustc_errors::{pluralize, Applicability, PResult};
@ -224,7 +225,7 @@ impl<'a> Parser<'a> {
// `(T, U) -> R` // `(T, U) -> R`
let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?; let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
let span = ident.span.to(self.prev_span); 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() ParenthesizedArgs { inputs, output, span }.into()
}; };

View File

@ -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<u8, u8>`, /// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
/// `IDENT<<u8 as Trait>::AssocTy>`. /// `IDENT<<u8 as Trait>::AssocTy>`.
/// ///
@ -48,14 +65,14 @@ fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
impl<'a> Parser<'a> { impl<'a> Parser<'a> {
/// Parses a type. /// Parses a type.
pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> { pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
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. /// Parse a type suitable for a function or function pointer parameter.
/// The difference from `parse_ty` is that this version allows `...` /// The difference from `parse_ty` is that this version allows `...`
/// (`CVarArgs`) at the top level of the the type. /// (`CVarArgs`) at the top level of the the type.
pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> { pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> {
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. /// Parses a type in restricted contexts where `+` is not permitted.
@ -65,18 +82,19 @@ impl<'a> Parser<'a> {
/// Example 2: `value1 as TYPE + value2` /// Example 2: `value1 as TYPE + value2`
/// `+` is prohibited to avoid interactions with expression grammar. /// `+` is prohibited to avoid interactions with expression grammar.
pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> { pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
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. /// Parses an optional return type `[ -> TY ]` in a function declaration.
pub(super) fn parse_ret_ty( pub(super) fn parse_ret_ty(
&mut self, &mut self,
allow_plus: bool, allow_plus: AllowPlus,
allow_qpath_recovery: bool, recover_qpath: RecoverQPath,
) -> PResult<'a, FunctionRetTy> { ) -> PResult<'a, FunctionRetTy> {
Ok(if self.eat(&token::RArrow) { Ok(if self.eat(&token::RArrow) {
// FIXME(Centril): Can we unconditionally `allow_plus`? // 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 { } else {
FunctionRetTy::Default(self.token.span.shrink_to_lo()) FunctionRetTy::Default(self.token.span.shrink_to_lo())
}) })
@ -84,11 +102,11 @@ impl<'a> Parser<'a> {
fn parse_ty_common( fn parse_ty_common(
&mut self, &mut self,
allow_plus: bool, allow_plus: AllowPlus,
allow_qpath_recovery: bool, recover_qpath: RecoverQPath,
// Is `...` (`CVarArgs`) legal in the immediate top level call? allow_c_variadic: AllowCVariadic,
allow_c_variadic: bool,
) -> PResult<'a, P<Ty>> { ) -> PResult<'a, P<Ty>> {
let allow_qpath_recovery = matches!(recover_qpath, RecoverQPath::Yes);
maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery); maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
maybe_whole!(self, NtTy, |x| x); maybe_whole!(self, NtTy, |x| x);
@ -124,7 +142,7 @@ impl<'a> Parser<'a> {
self.parse_ty_bare_fn(lifetime_defs)? self.parse_ty_bare_fn(lifetime_defs)?
} else { } else {
let path = self.parse_path(PathStyle::Type)?; 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)? self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)?
} }
} else if self.eat_keyword(kw::Impl) { } else if self.eat_keyword(kw::Impl) {
@ -144,7 +162,7 @@ impl<'a> Parser<'a> {
} else if self.token.is_path_start() { } else if self.token.is_path_start() {
self.parse_path_start_ty(lo, allow_plus)? self.parse_path_start_ty(lo, allow_plus)?
} else if self.eat(&token::DotDotDot) { } else if self.eat(&token::DotDotDot) {
if allow_c_variadic { if let AllowCVariadic::Yes = allow_c_variadic {
TyKind::CVarArgs TyKind::CVarArgs
} else { } else {
// FIXME(Centril): Should we just allow `...` syntactically // FIXME(Centril): Should we just allow `...` syntactically
@ -172,7 +190,7 @@ impl<'a> Parser<'a> {
/// Parses either: /// Parses either:
/// - `(TYPE)`, a parenthesized type. /// - `(TYPE)`, a parenthesized type.
/// - `(TYPE,)`, a tuple with a single field of type 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 mut trailing_plus = false;
let (ts, trailing) = self.parse_paren_comma_seq(|p| { let (ts, trailing) = self.parse_paren_comma_seq(|p| {
let ty = p.parse_ty()?; let ty = p.parse_ty()?;
@ -182,7 +200,7 @@ impl<'a> Parser<'a> {
if ts.len() == 1 && !trailing { if ts.len() == 1 && !trailing {
let ty = ts.into_iter().nth(0).unwrap().into_inner(); 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 { match ty.kind {
// `(TY_BOUND_NOPAREN) + BOUND + ...`. // `(TY_BOUND_NOPAREN) + BOUND + ...`.
TyKind::Path(None, path) if maybe_bounds => { TyKind::Path(None, path) if maybe_bounds => {
@ -288,7 +306,8 @@ impl<'a> Parser<'a> {
let unsafety = self.parse_unsafety(); let unsafety = self.parse_unsafety();
let ext = self.parse_extern()?; let ext = self.parse_extern()?;
self.expect_keyword(kw::Fn)?; 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 }))) Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params, decl })))
} }
@ -326,7 +345,7 @@ impl<'a> Parser<'a> {
/// 1. a type macro, `mac!(...)`, /// 1. a type macro, `mac!(...)`,
/// 2. a bare trait object, `B0 + ... + Bn`, /// 2. a bare trait object, `B0 + ... + Bn`,
/// 3. or a path, `path::to::MyType`. /// 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 // Simple path
let path = self.parse_path(PathStyle::Type)?; let path = self.parse_path(PathStyle::Type)?;
if self.eat(&token::Not) { if self.eat(&token::Not) {
@ -336,7 +355,7 @@ impl<'a> Parser<'a> {
args: self.parse_mac_args()?, args: self.parse_mac_args()?,
prior_type_ascription: self.last_type_ascription, 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` // `Trait1 + Trait2 + 'a`
self.parse_remaining_bounds(Vec::new(), path, lo, true) self.parse_remaining_bounds(Vec::new(), path, lo, true)
} else { } else {
@ -359,7 +378,7 @@ impl<'a> Parser<'a> {
&mut self, &mut self,
colon_span: Option<Span>, colon_span: Option<Span>,
) -> PResult<'a, GenericBounds> { ) -> 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 `+`. /// 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. /// See `parse_generic_bound` for the `BOUND` grammar.
fn parse_generic_bounds_common( fn parse_generic_bounds_common(
&mut self, &mut self,
allow_plus: bool, allow_plus: AllowPlus,
colon_span: Option<Span>, colon_span: Option<Span>,
) -> PResult<'a, GenericBounds> { ) -> PResult<'a, GenericBounds> {
let mut bounds = Vec::new(); let mut bounds = Vec::new();
@ -377,7 +396,7 @@ impl<'a> Parser<'a> {
Ok(bound) => bounds.push(bound), Ok(bound) => bounds.push(bound),
Err(neg_sp) => negative_bounds.push(neg_sp), Err(neg_sp) => negative_bounds.push(neg_sp),
} }
if !allow_plus || !self.eat_plus() { if matches!(allow_plus, AllowPlus::No) || !self.eat_plus() {
break; break;
} }
} }