Parsing issues around qualifiers and modifiers
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
Fn vs. trait qualifiers
We fail to parse
const unsafe trait Trait {} //~ ERROR expected one of `extern` or `fn`, found keyword `trait`
and
const unsafe auto trait Trait {} //~ ERROR expected one of `extern` or `fn`, found `auto`
even though check_trait_front_matter would return true here in theory. That's because in parse_item_kind we check_fn_front_matter first which returns true once there are >=2 "fn" qualifiers (†) which most notably includes the sequence const unsafe. Two basic solutions:
- (†):
check_fn_front_matteralready contains certain exceptions likeunsafe extern {,async gen {andasync gen move {; we could extend this with!self.is_trait_front_matter()but that's kind of awful because we would basically check the sequenceconst unsafethree times over. Moreover, we gonna wanna have bothis_*(&self) andcheck_*(&mut self) variants but that means bad duplication. - We could move the
check_trait_front_mattercheck above/before the fn one since it's more strict. However, I wonder if this breaks some soft invariants:check_trait_front_matteris also used elsewhere to determine whether a fn item follows. With this change, it would have "false positives". Likely not a problem in practice though.
Fn ptr ty qualifiers vs. trait bound modifiers in bare trait object tys
What's more, we also use check_fn_front_matter inside parse_ty_common for fn ptr tys but later reject const and async qualifiers in parse_fn_front_matter. Now, since that happens before we check can_begin_bound we incorrectly reject bare trait object tys that start with >=2 trait bound modifiers if they coincide with "fn" qualifiers (thanks to check_fn_front_matter yet again), i.e., async const bare trait object tys:
#![feature(const_trait_impl, async_trait_bounds)]
#[cfg(false)]
type X = (const Trait, async Trait, dyn const async Trait); // OK!
#[cfg(false)]
type Y = const async Trait;
//~^ ERROR an `fn` pointer type cannot be `const`
//~| ERROR an `fn` pointer type cannot be `async`
//~| ERROR expected one of `extern`, `fn`, `gen`, `safe`, or `unsafe`, found `Trait`
Array/slice ty vs. conditional constness inside bare trait object tys
For consistency, the following should get parsed as a bare trait object ty with a conditionally-const trait bound. However, we commit to parsing an array/slice ty before that:
#[cfg(false)] type X = dyn [const] Trait; // OK!
#[cfg(false)] type Y = [const] Trait; //~ ERROR expected identifier, found `]`
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in parse_item_kind and compare the check_fn_front_matter and check_trait_front_matter paths, then inspect parse_ty_common and parse_fn_front_matter for the type cases. Reproduce the issue with the const/unsafe trait, async const bare trait object, and [const] examples. Done means these inputs are classified and parsed according to the expected diagnostics shown in the issue.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100