Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify AST Visitors with a macro like MIR Visitors #128974

Draft
wants to merge 82 commits into
base: master
Choose a base branch
from

Conversation

maxcabrajac
Copy link
Contributor

@maxcabrajac maxcabrajac commented Aug 11, 2024

This is a PR to work on #127615

@rustbot
Copy link
Collaborator

rustbot commented Aug 11, 2024

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @lcnr (or someone else) some time within the next two weeks.

Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (S-waiting-on-review and S-waiting-on-author) stays updated, invoking these commands when appropriate:

  • @rustbot author: the review is finished, PR author should check the comments and take action accordingly
  • @rustbot review: the author is ready for a review, this PR will be queued again in the reviewer's queue

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Aug 11, 2024
@rust-log-analyzer

This comment has been minimized.

@cjgillot cjgillot self-assigned this Aug 11, 2024
@lcnr
Copy link
Contributor

lcnr commented Aug 12, 2024

r? compiler

@rustbot rustbot assigned davidtwco and unassigned cjgillot and lcnr Aug 12, 2024
@lcnr
Copy link
Contributor

lcnr commented Aug 12, 2024

r? @cjgillot woops

@rustbot rustbot assigned cjgillot and unassigned davidtwco Aug 12, 2024
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

Copy link
Contributor

@cjgillot cjgillot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, that's some great work you did @maxcabrajac!
Please take this as an opportunity to simplify stuff. If some distinction has you make weird corner cases, don't hesitate to remove it. My comments are suggestions in this direction.

compiler/rustc_ast/src/visitors.rs Outdated Show resolved Hide resolved
compiler/rustc_ast/src/visitors.rs Outdated Show resolved Hide resolved
compiler/rustc_ast/src/visitors.rs Outdated Show resolved Hide resolved
Comment on lines 320 to 325
make_visit!{P!(Local), visit_local, walk_local}
make_visit!{P!(Pat), visit_pat, walk_pat}
make_visit!{P!(Expr), visit_expr, walk_expr}
make_visit!{P!(Ty), visit_ty, walk_ty}
make_visit!{P!(Block), visit_block, walk_block}
make_visit!{P!(FnDecl), visit_fn_decl, walk_fn_decl}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we remove the P! from all these?

Copy link
Contributor Author

@maxcabrajac maxcabrajac Aug 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I put these P! to maintain all function signatures the same, thus avoiding changes on implementers. I don't know why the original MutVisitor received &mut P<T> instead of &mut T for these types, but I just kept what was being done.

@maxcabrajac
Copy link
Contributor Author

I think it's better to do two passes. Do what can be done without changing the trait API, after that, change what is weird about their original implementation and change all implementers accordingly. What do you think about it?
There is a pretty big roadblock now... Everything around walk_item seems to be pretty different from Visitor to MutVisitor and I really don't know where to start =/. Do you have any advice on that?

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@maxcabrajac
Copy link
Contributor Author

@maxcabrajac To clarify, could you keep the full set of changes in this PR, and make new PRs for the partial changes?

That force push to this PR was just because I missclicked "Sync fork" on the wrong branch and wanted to revert it. I'm keeping this as reference for what to do in the other PRs.

Now I'm doing what can be done before introducing macros, ok?

Upd: could you also refer to this PR from PR descriptions of the other PRs?

Added "related to #this PR" to them.

One last thing:

The macros here look pretty terrifying, TBH.

Is make_visit the one that bothers? One my first try I didn't use this approach, but opted for it when there were 500 lines of just:

fn visit_t(&mut self, t: &$($lt)? $($mut)? T)) -> result!() {
    walk_t(self, t)
}

After already using make_visit for things, I needed to make it pass additional arguments around, which might not have come out great...
That being said, we can either remove or improve make_visit if it fits. =)

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Oct 24, 2024
…trochenkov

Remove visit_expr_post from ast Visitor

`visit_expr_post` is only present in the immutable version of ast Visitors and its default implementation is a noop.
Given that its only implementer is on `rustc_lint/src/early.rs` and its name follows the same naming convention as some other lints (`_post`), it seems that `visit_expr_post` being in `Visitor` was a little mistake.

r? `@petrochenkov`

related to rust-lang#128974
@petrochenkov
Copy link
Contributor

Now I'm doing what can be done before introducing macros, ok?

👍

Is make_visit the one that bothers?

I didn't look into much detail yet, just a general feeling (e.g. there are multiple layers of macros, a dozen of helper macros, etc).

rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Oct 24, 2024
Rollup merge of rust-lang#132107 - maxcabrajac:remove_expr_post, r=petrochenkov

Remove visit_expr_post from ast Visitor

`visit_expr_post` is only present in the immutable version of ast Visitors and its default implementation is a noop.
Given that its only implementer is on `rustc_lint/src/early.rs` and its name follows the same naming convention as some other lints (`_post`), it seems that `visit_expr_post` being in `Visitor` was a little mistake.

r? `@petrochenkov`

related to rust-lang#128974
@bors
Copy link
Contributor

bors commented Oct 24, 2024

☔ The latest upstream changes (presumably #132116) made this pull request unmergeable. Please resolve the merge conflicts.

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Oct 25, 2024
Pass Ident by reference in ast Visitor

`MutVisitor`'s version of `visit_ident` passes around `&Ident`, but `Visitor` copies `Ident`. This PR changes that

r? `@petrochenkov`

related to rust-lang#128974
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Oct 25, 2024
Rollup merge of rust-lang#132106 - maxcabrajac:ident_ref, r=petrochenkov

Pass Ident by reference in ast Visitor

`MutVisitor`'s version of `visit_ident` passes around `&Ident`, but `Visitor` copies `Ident`. This PR changes that

r? `@petrochenkov`

related to rust-lang#128974
@Dylan-DPC
Copy link
Member

@maxcabrajac any updates on this? thanks

@maxcabrajac
Copy link
Contributor Author

Hi @Dylan-DPC!
I haven't worked on it this past week =/
Last week, I was trying to remove P<> wrappers from some functions that didn't seem to need it on rustc_expand.
But I came to the conclusion that removing them might be either harmful or too much for me.

The motivation for doing it was functions like this:

(found in: https://github.com/rust-lang/rust/blob/3d1dba830a564d1118361345d7ada47a05241f45/compiler/rustc_expand/src/placeholders.rs#L303C1-L308C6)

 fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
     match expr.kind {
         ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_expr(),
         _ => walk_expr(self, expr),
     }
 }

In the code above the P<Expr> that is in expr is dropped and substituted by the one received from make_expr(). This throws away the the first allocation and uses the new one.

After removing the wrapper from visit_expr the same code turns into this:

 fn visit_expr(&mut self, expr: &mut ast::Expr) {
     match expr.kind {
         ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_expr().into_inner(),
         _ => walk_expr(self, expr),
     }
 }

This reuses the previous allocation, but throws away the one make_expr made and introduces one additional Expr move (as the Expr is now copied from new to old memory in the assignment) . So I thought: "what about changing make_expr() to return an unwrapped Expr and make the callee wrap it if they need to."

But changing this requires a huge amount of other changes and thinking about whether each callee requires the wrapper or should also return an unwrapped Expr.
On the other hand, this might introduce a bunch of places where Exprs are moved in the stack itself, which might outweigh the benefits of not doing some temporary allocations.

All of this multiplied by the amount of structs that are wrapped in P<>s (6 or 7 if I'm not mistaken)

I still think removing the wrappers from the visit_* is a good idea for standardization between versions of Visitor.
What do you think about it?

There are still other unrelated changes to do. I'll focus on them for now. =)

flip1995 pushed a commit to flip1995/rust that referenced this pull request Nov 7, 2024
Pass Ident by reference in ast Visitor

`MutVisitor`'s version of `visit_ident` passes around `&Ident`, but `Visitor` copies `Ident`. This PR changes that

r? `@petrochenkov`

related to rust-lang#128974
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Nov 15, 2024
…g_arg, r=compiler-errors

Change Visitor::visit_precise_capturing_arg so it returns a Visitor::Result

r? `@petrochenkov`

related to rust-lang#128974
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Nov 15, 2024
…ochenkov

Add visit_coroutine_kind to ast::Visitor

r? `@petrochenkov`

related to rust-lang#128974
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Nov 15, 2024
Rollup merge of rust-lang#133049 - maxcabrajac:visit_precise_capturing_arg, r=compiler-errors

Change Visitor::visit_precise_capturing_arg so it returns a Visitor::Result

r? `@petrochenkov`

related to rust-lang#128974
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this pull request Nov 15, 2024
…ochenkov

Add visit_coroutine_kind to ast::Visitor

r? `@petrochenkov`

related to rust-lang#128974
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this pull request Nov 15, 2024
…ochenkov

Add visit_coroutine_kind to ast::Visitor

r? ``@petrochenkov``

related to rust-lang#128974
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Nov 16, 2024
Rollup merge of rust-lang#132956 - maxcabrajac:coroutine_kind, r=petrochenkov

Add visit_coroutine_kind to ast::Visitor

r? ``@petrochenkov``

related to rust-lang#128974
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Nov 16, 2024
Unify FnKind between AST visitors and make WalkItemKind more straight forward

Unifying `FnKind` requires a bunch of changes to `WalkItemKind::walk` signature so I'll change them in one go

related to rust-lang#128974

r? `@petrochenkov`
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Nov 17, 2024
Rollup merge of rust-lang#132787 - maxcabrajac:fnctxt, r=petrochenkov

Unify FnKind between AST visitors and make WalkItemKind more straight forward

Unifying `FnKind` requires a bunch of changes to `WalkItemKind::walk` signature so I'll change them in one go

related to rust-lang#128974

r? `@petrochenkov`
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Nov 19, 2024
…chenkov

Add `visit` methods to ast nodes that already have `walk`s on ast visitors

Some `walk` functions are called directly, because there were no correspondent visit functions.

related to rust-lang#128974 & rust-lang#127615

r? `@petrochenkov`
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Nov 20, 2024
Rollup merge of rust-lang#133188 - maxcabrajac:walk_no_visit, r=petrochenkov

Add `visit` methods to ast nodes that already have `walk`s on ast visitors

Some `walk` functions are called directly, because there were no correspondent visit functions.

related to rust-lang#128974 & rust-lang#127615

r? `@petrochenkov`
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Nov 21, 2024
Add visits to nodes that already have flat_maps in ast::MutVisitor

This PR aims to add `visit_` methods for every node that has a `flat_map_` in MutVisitor, giving implementers free choice over overriding `flat_map` for 1-to-n conversions or `visit` for a 1-to-1.

There is one major problem: `flat_map_stmt`.
While all other default implementations of `flat_map`s are 1-to-1 conversion, as they either only call visits or a internal 1-to-many conversions are natural, `flat_map_stmt` doesn't follow this pattern.

`flat_map_stmt`'s default implementation is a 1-to-n conversion that panics if n > 1 (effectively being a 1-to-[0;1]). This means that it cannot be used as is for a default `visit_stmt`, which would be required to be a 1-to-1.

Implementing `visit_stmt` without runtime checks would require it to reach over a potential `flat_map_item` or `filter_map_expr` overrides and call for their `visit` counterparts directly.
Other than that, if we want to keep the behavior of `flat_map_stmt` it cannot call `visit_stmt` internally.

To me, it seems reasonable to make all default implementations 1-to-1 conversions and let implementers handle `visit_stmt` if they need it, but I don't know if calling `visit` directly when a 1-to-1 is required is ok or not.

related to rust-lang#128974 & rust-lang#127615

r? `@petrochenkov`
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Nov 21, 2024
Add visits to nodes that already have flat_maps in ast::MutVisitor

This PR aims to add `visit_` methods for every node that has a `flat_map_` in MutVisitor, giving implementers free choice over overriding `flat_map` for 1-to-n conversions or `visit` for a 1-to-1.

There is one major problem: `flat_map_stmt`.
While all other default implementations of `flat_map`s are 1-to-1 conversion, as they either only call visits or a internal 1-to-many conversions are natural, `flat_map_stmt` doesn't follow this pattern.

`flat_map_stmt`'s default implementation is a 1-to-n conversion that panics if n > 1 (effectively being a 1-to-[0;1]). This means that it cannot be used as is for a default `visit_stmt`, which would be required to be a 1-to-1.

Implementing `visit_stmt` without runtime checks would require it to reach over a potential `flat_map_item` or `filter_map_expr` overrides and call for their `visit` counterparts directly.
Other than that, if we want to keep the behavior of `flat_map_stmt` it cannot call `visit_stmt` internally.

To me, it seems reasonable to make all default implementations 1-to-1 conversions and let implementers handle `visit_stmt` if they need it, but I don't know if calling `visit` directly when a 1-to-1 is required is ok or not.

related to rust-lang#128974 & rust-lang#127615

r? ``@petrochenkov``
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Nov 21, 2024
Rollup merge of rust-lang#133153 - maxcabrajac:flat_maps, r=petrochenkov

Add visits to nodes that already have flat_maps in ast::MutVisitor

This PR aims to add `visit_` methods for every node that has a `flat_map_` in MutVisitor, giving implementers free choice over overriding `flat_map` for 1-to-n conversions or `visit` for a 1-to-1.

There is one major problem: `flat_map_stmt`.
While all other default implementations of `flat_map`s are 1-to-1 conversion, as they either only call visits or a internal 1-to-many conversions are natural, `flat_map_stmt` doesn't follow this pattern.

`flat_map_stmt`'s default implementation is a 1-to-n conversion that panics if n > 1 (effectively being a 1-to-[0;1]). This means that it cannot be used as is for a default `visit_stmt`, which would be required to be a 1-to-1.

Implementing `visit_stmt` without runtime checks would require it to reach over a potential `flat_map_item` or `filter_map_expr` overrides and call for their `visit` counterparts directly.
Other than that, if we want to keep the behavior of `flat_map_stmt` it cannot call `visit_stmt` internally.

To me, it seems reasonable to make all default implementations 1-to-1 conversions and let implementers handle `visit_stmt` if they need it, but I don't know if calling `visit` directly when a 1-to-1 is required is ok or not.

related to rust-lang#128974 & rust-lang#127615

r? ``@petrochenkov``
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants