-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Overhaul syntax::fold::Folder
.
#58061
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Conversation
@bors try |
⌛ Trying commit b4a6b98fb425e66926941efa55dce39aea400914 with merge 4d27e368a336fc53353c891ee0dc425399c612c0... |
@nnethercote |
☀️ Test successful - checks-travis |
I hadn't seen #57662. It's definitely overlapping with this PR. Notable differences, judging from a quick skim:
|
The reason the new approach is faster is that an existing noop fold overwrites all the nodes with the same values. There are no reallocations due to the use of |
@rust-timer build 4d27e368a336fc53353c891ee0dc425399c612c0 |
Success: Queued 4d27e368a336fc53353c891ee0dc425399c612c0 with parent 23d8d0c, comparison URL. |
Finished benchmarking try commit 4d27e368a336fc53353c891ee0dc425399c612c0 |
The perf results are similar to what I saw locally. Widespread improvements, mostly on "clean incremental" runs, with a best result of -3.4%. |
Comparing this PR with #57662 some more, the handling of the The handling of the other cases is where the differences are bigger. This PR keeps the existing structure for ones like In contrast, #57662 introduces the |
A final summary! This PR:
Overall, I think this PR is more complete while involving less changes. But I'm biased :) Let me know if I've gotten any of the details wrong. |
b4a6b98
to
d05b178
Compare
I have updated the code. It's now complete except for one thing: as the "njn:" comment in the code says, I think the r? @petrochenkov: the code is ready to review, but as well as making the main change, I have made a bunch of minor clean-ups. If you like I could pull out those clean-ups into separate commits preceding the main commit. |
Great work, thanks. I think I prefer this PRs trajectory. Why:
|
Regarding naming. |
If that's not too annoying, could you split the PR into two commits
|
d05b178
to
f9d6e3e
Compare
Specifically: - Remove dead methods: fold_usize, fold_meta_items, fold_opt_bounds. - Remove useless methods: fold_global_asm, fold_range_end. - Inline and remove unnecessary methods: fold_item_simple, fold_foreign_item_simple.
It doesn't need to return an `Option`.
It's simpler that way.
By eliminating some unnecessary methods, and moving/renaming some functions that look like they might be methods but aren't.
f9d6e3e
to
3263f02
Compare
@petrochenkov: the new code is up.
|
The usual solution is to move the file renaming into a separate commit. |
r=me with the file renaming moved into a separate commit or without it. |
This commit changes `syntax::fold::Folder` from a functional style (where most methods take a `T` and produce a new `T`) to a more imperative style (where most methods take and modify a `&mut T`), and renames it `syntax::mut_visit::MutVisitor`. The first benefit is speed. The functional style does not require any reallocations, due to the use of `P::map` and `MoveMap::move_{,flat_}map`. However, every field in the AST must be overwritten; even those fields that are unchanged are overwritten with the same value. This causes a lot of unnecessary memory writes. The imperative style reduces instruction counts by 1--3% across a wide range of workloads, particularly incremental workloads. The second benefit is conciseness; the imperative style is usually more concise. E.g. compare the old functional style: ``` fn fold_abc(&mut self, abc: ABC) { ABC { a: fold_a(abc.a), b: fold_b(abc.b), c: abc.c, } } ``` with the imperative style: ``` fn visit_abc(&mut self, ABC { a, b, c: _ }: &mut ABC) { visit_a(a); visit_b(b); } ``` (The reductions get larger in more complex examples.) Overall, the patch removes over 200 lines of code -- even though the new code has more comments -- and a lot of the remaining lines have fewer characters. Some notes: - The old style used methods called `fold_*`. The new style mostly uses methods called `visit_*`, but there are a few methods that map a `T` to something other than a `T`, which are called `flat_map_*` (`T` maps to multiple `T`s) or `filter_map_*` (`T` maps to 0 or 1 `T`s). - `move_map.rs`/`MoveMap`/`move_map`/`move_flat_map` are renamed `map_in_place.rs`/`MapInPlace`/`map_in_place`/`flat_map_in_place` to reflect their slightly changed signatures. - Although this commit renames the `fold` module as `mut_visit`, it keeps it in the `fold.rs` file, so as not to confuse git. The next commit will rename the file.
3263f02
to
bfcbd23
Compare
Thank you for the suggestion, I did that. @bors r=petrochenkov |
📌 Commit bfcbd23 has been approved by |
…nkov Overhaul `syntax::fold::Folder`. This PR changes `syntax::fold::Folder` from a functional style (where most methods take a `T` and produce a new `T`) to a more imperative style (where most methods take and modify a `&mut T`), and renames it `syntax::mut_visit::MutVisitor`. This makes the code faster and more concise.
☀️ Test successful - checks-travis, status-appveyor |
Make `visit_clobber`'s impl safe This was originally introduced in rust-lang#58061 but I didn't see any perf discussion about it, so let's see what perf says. r? `@nnethercote`
Make `visit_clobber`'s impl safe This was originally introduced in rust-lang#58061 but I didn't see any perf discussion about it, so let's see what perf says. r? `@nnethercote`
This PR changes
syntax::fold::Folder
from a functional style(where most methods take a
T
and produce a newT
) to a moreimperative style (where most methods take and modify a
&mut T
), andrenames it
syntax::mut_visit::MutVisitor
.This makes the code faster and more concise.