Merge TraitItem
& ImplItem into
AssocItem` by Centril · Pull Request #67131 · rust-lang/rust (original) (raw)
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request
…enkov
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 inextern { ... }
blocks can now have bodies (fn foo() { ... }
as opposed tofn 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 tofn 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: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 inextern { ... }
can have no qualifiers.const
andasync
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]
) insidetrait 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 }
inparser/ty.rs
instead of passing around 3 differentbool
s. I felt this was necessary as it was becoming mentally taxing to track which-is-which.fn visit_trait_item
andfn visit_impl_item
are merged intofn visit_assoc_item
which now is passed anAssocCtxt
to check which one it is.We change
FnKind
to:pub enum FnKind<'a> { Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, Option<&'a Block>), Closure(&'a FnDecl, &'a Expr), }
with:
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 changeP<Block>
toOption<P<Block>>
.In
ForeignItemKind::Fn
, we changeP<FnDecl>
toFnSig
andP<Block>
toOption<P<Block>>
.We change
ast::{Unsafety, Spanned<Constness>}>
intoenum ast::{Unsafe, Const} { Yes(Span), No }
respectively. This change in formulation allow us to excludeSpan
in the case ofNo
, which facilitates parsing. Moreover, we also add aSpan
toIsAsync
which is renamed toAsync
. The newSpan
s inUnsafety
andAsync
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.