You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Rollup merge of rust-lang#68728 - Centril:towards-fn-merge, r=petrochenkov
parse: merge `fn` syntax + cleanup item parsing
Here we continue the work in rust-lang#67131 in particular to merge the grammars of `fn` items in various positions.
A list of *language level* changes (as sanctioned by the language team in rust-lang#65041 (comment) and rust-lang#67131):
- `self` parameters are now *syntactically* allowed as the first parameter irrespective of item context (and in function pointers). Instead, semantic validation (`ast_validation`) is used.
- Syntactically, `fn` items in `extern { ... }` blocks can now have bodies (`fn foo() { ... }` as opposed to `fn foo();`). As above, we use semantic restrictions instead.
- Syntactically, `fn` items in free contexts (directly in a file or a module) can now be without bodies (`fn foo();` as opposed to `fn foo() { ... }`. As above, we use semantic restrictions instead, including for non-ident parameter patterns.
- `const extern fn` feature gating is now done post-expansion such that we do not have conditional compatibilities of function qualifiers *in parsing*.
- The `FnFrontMatter` grammar becomes:
```rust
Extern = "extern" StringLit ;
FnQual = "const"? "async"? "unsafe"? Extern? ;
FnFrontMatter = FnQual "fn" ;
```
That is, all item contexts now *syntactically* allow `const async unsafe extern "C" fn` and use semantic restrictions to rule out combinations previously prevented syntactically. The semantic restrictions include in particular:
- `fn`s in `extern { ... }` can have no qualifiers.
- `const` and `async` cannot be combined.
- To fuse the list-of-items parsing in the 4 contexts that items are allowed, we now must permit inner attributes (`#![attr]`) inside `trait Foo { ... }` definitions. That is, we now allow e.g. `trait Foo { #![attr] }`. This was probably an oversight due to not using a uniform parsing mechanism, which we now do have (`fn parse_item_list`). The semantic support (including e.g. for linting) falls out directly from the attributes infrastructure. To ensure this, we include a test for lints.
Put together, these grammar changes allow us to substantially reduce the complexity of item parsing and its grammar. There are however some other non-language improvements that allow the compression to take place.
A list of *compiler-internal* changes (in particular noting the parser-external data-structure changes):
- We use `enum AllowPlus/RecoverQPath/AllowCVariadic { Yes, No }` in `parser/ty.rs` instead of passing around 3 different `bool`s. I felt this was necessary as it was becoming mentally taxing to track which-is-which.
- `fn visit_trait_item` and `fn visit_impl_item` are merged into `fn visit_assoc_item` which now is passed an `AssocCtxt` to check which one it is.
- We change `FnKind` to:
```rust
pub enum FnKind<'a> {
Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, Option<&'a Block>),
Closure(&'a FnDecl, &'a Expr),
}
```
with:
```rust
pub enum FnCtxt {
Free,
Foreign,
Assoc(AssocCtxt),
}
```
This is then taken advantage of in tweaking the various semantic restrictions as well as in pretty printing.
- In `ItemKind::Fn`, we change `P<Block>` to `Option<P<Block>>`.
- In `ForeignItemKind::Fn`, we change `P<FnDecl>` to `FnSig` and `P<Block>` to `Option<P<Block>>`.
- We change `ast::{Unsafety, Spanned<Constness>}>` into `enum ast::{Unsafe, Const} { Yes(Span), No }` respectively. This change in formulation allow us to exclude `Span` in the case of `No`, which facilitates parsing. Moreover, we also add a `Span` to `IsAsync` which is renamed to `Async`. The new `Span`s in `Unsafety` and `Async` are then taken advantage of for better diagnostics. A reason this change was made is to have a more uniform and clear naming scheme.
The HIR keeps the structures in AST (with those definitions moved into HIR) for now to avoid regressing perf.
- Various cleanups, bug fixes, and diagnostics improvements are made along the way. It is probably best to understand those via the diffs.
I would recommend reviewing this commit-by-commit with whitespace changes hidden.
r? @estebank@petrochenkov
0 commit comments