1
Fork 0

Add pub as optional check_front_matter

async-pub check created a regression for default
This commit is contained in:
Ivan Tham 2020-12-08 00:32:13 +08:00
parent c44a5feb05
commit 21c157442c
5 changed files with 39 additions and 25 deletions

View file

@ -204,6 +204,7 @@ impl<'a> Parser<'a> {
def: &mut Defaultness,
req_name: ReqName,
) -> PResult<'a, Option<ItemInfo>> {
let def_final = def == &Defaultness::Final;
let mut def = || mem::replace(def, Defaultness::Final);
let info = if self.eat_keyword(kw::Use) {
@ -226,7 +227,7 @@ impl<'a> Parser<'a> {
}
(Ident::invalid(), ItemKind::Use(tree))
} else if self.check_fn_front_matter() {
} else if self.check_fn_front_matter(def_final) {
// FUNCTION ITEM
let (ident, sig, generics, body) = self.parse_fn(attrs, req_name, lo)?;
(ident, ItemKind::Fn(box FnKind(def(), sig, generics, body)))
@ -1636,19 +1637,27 @@ impl<'a> Parser<'a> {
}
/// Is the current token the start of an `FnHeader` / not a valid parse?
pub(super) fn check_fn_front_matter(&mut self) -> bool {
///
/// `check_pub` adds additional `pub` to the checks in case users place it
/// wrongly, can be used to ensure `pub` never comes after `default`.
pub(super) fn check_fn_front_matter(&mut self, check_pub: bool) -> bool {
// We use an over-approximation here.
// `const const`, `fn const` won't parse, but we're not stepping over other syntax either.
// `pub` is added in case users got confused with the ordering like `async pub fn`.
const QUALS: [Symbol; 5] = [kw::Pub, kw::Const, kw::Async, kw::Unsafe, kw::Extern];
// `pub` is added in case users got confused with the ordering like `async pub fn`,
// only if it wasn't preceeded by `default` as `default pub` is invalid.
let quals: &[Symbol] = if check_pub {
&[kw::Pub, kw::Const, kw::Async, kw::Unsafe, kw::Extern]
} else {
&[kw::Const, kw::Async, kw::Unsafe, kw::Extern]
};
self.check_keyword(kw::Fn) // Definitely an `fn`.
// `$qual fn` or `$qual $qual`:
|| QUALS.iter().any(|&kw| self.check_keyword(kw))
|| quals.iter().any(|&kw| self.check_keyword(kw))
&& self.look_ahead(1, |t| {
// `$qual fn`, e.g. `const fn` or `async fn`.
t.is_keyword(kw::Fn)
// Two qualifiers `$qual $qual` is enough, e.g. `async unsafe`.
|| t.is_non_raw_ident_where(|i| QUALS.contains(&i.name)
|| t.is_non_raw_ident_where(|i| quals.contains(&i.name)
// Rule out 2015 `const async: T = val`.
&& i.is_reserved()
// Rule out unsafe extern block.

View file

@ -209,7 +209,7 @@ impl<'a> Parser<'a> {
} else if self.eat_keyword(kw::Underscore) {
// A type to be inferred `_`
TyKind::Infer
} else if self.check_fn_front_matter() {
} else if self.check_fn_front_matter(false) {
// Function pointer type
self.parse_ty_bare_fn(lo, Vec::new(), recover_return_sign)?
} else if self.check_keyword(kw::For) {
@ -217,7 +217,7 @@ impl<'a> Parser<'a> {
// `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
// `for<'lt> Trait1<'lt> + Trait2 + 'a`
let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
if self.check_fn_front_matter() {
if self.check_fn_front_matter(false) {
self.parse_ty_bare_fn(lo, lifetime_defs, recover_return_sign)?
} else {
let path = self.parse_path(PathStyle::Type)?;