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

Make declarative macro expansion a part of query system (cont. of #125356) #128605

Closed
wants to merge 4 commits into from

Conversation

futile
Copy link
Contributor

@futile futile commented Aug 3, 2024

This is a continuation of the effort to make declarative macro expansion a part of the query system from #125356 by @SparrowLii.

Description from that PR:

This is an attempt to make the macro expansion a part of incremental compilation.

Processing of procedural macros is difficult since they may involve interactions with the external environment. Declaring macros is a good start.

It is not yet possible to test the effect of this PR on incremental compilation since the new query is declared as eval_always.

Status of this PR:

  • It is rebased against a much more recent master commit
  • It contains the original commits from make declarative macro expansion a part of query system #125356 (in a rebased form)
  • It adds the missing implementation for retrying macro matching that provides (better) error diagnostics
    • This was done by refactoring rustc_expand::mbe::diagnostics::failed_to_match_macro() to only require a ParseSess instead of an ExtCtxt. Otherwise, ExtCtxt would need to be in the interface of TcxMacroExpander, which is not possible, because ExtCtxt is part of rustc_expand, which depends on the crate that contains TcxMacroExpander, rustc_middle, and thus would introduce a circular dependency.
    • This refactoring moved the retrying down into the impl TcxMacroExpander for MacroRulesMacroExpander (this is just a change compared to the original PR, otherwise not important to know).
  • This PR passes ./x test tests/ui, which produced errors before that were all due to the missing implementation of retry macro matching.
  • This PR does not yet contain changes for the open discussions from make declarative macro expansion a part of query system #125356. I wanted to fix the tests first before tackling them, and I also need to figure out what the best solutions for them are. I'd welcome any help/support with this, e.g., opening up a corresponding discussion on this PR with a summary/the final decided fix if available :)

In general, I'm new to working on rustc, so would be thankful for a bit more background/explanations in discussions and comments :) Thanks! :)

(tangentially relevant: #99515)

@rustbot
Copy link
Collaborator

rustbot commented Aug 3, 2024

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @pnkfelix (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
Copy link
Collaborator

rustbot commented Aug 3, 2024

⚠️ Warning ⚠️

  • These commits modify submodules.

@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 3, 2024
@rustbot
Copy link
Collaborator

rustbot commented Aug 3, 2024

Some changes occurred in src/tools/cargo

cc @ehuss

These commits modify the Cargo.lock file. Unintentional changes to Cargo.lock can be introduced when switching branches and rebasing PRs.

If this was unintentional then you should revert the changes before this PR is merged.
Otherwise, you can ignore this comment.

@futile
Copy link
Contributor Author

futile commented Aug 3, 2024

Did a rebase, to no longer contain changes to submodules (wow rust is moving fast 🙈).

@futile
Copy link
Contributor Author

futile commented Aug 3, 2024

r? @petrochenkov

Since you reviewed and self-assigned the original PR, I thought this would be ok/maybe a better fit than auto-assignment.

Please feel free to re-/unassign if that's not the case!

@rustbot rustbot assigned petrochenkov and unassigned pnkfelix Aug 3, 2024
@rust-log-analyzer

This comment has been minimized.

@futile
Copy link
Contributor Author

futile commented Aug 3, 2024

Oof, no idea where that error comes from, seems a dependency is broken/flaky? It's in stage0-checking, so can't be due to my changes yet I think? :O

@compiler-errors
Copy link
Member

You need to revert the changes you've made to submodules in this PR.

@futile
Copy link
Contributor Author

futile commented Aug 3, 2024

You need to revert the changes you've made to submodules in this PR.

Thank you very much! Was a bit finicky, but I think it's correct now, the changes don't appear in the commit that had them anymore.

@rustbot rustbot added 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. labels Aug 4, 2024
@rustbot
Copy link
Collaborator

rustbot commented Aug 4, 2024

There are merge commits (commits with multiple parents) in your changes. We have a no merge policy so these commits will need to be removed for this pull request to be merged.

You can start a rebase with the following commands:

$ # rebase
$ git pull --rebase https://github.com/rust-lang/rust.git master
$ git push --force-with-lease

The following commits are merge commits:

@rustbot rustbot removed 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. labels Aug 4, 2024
@petrochenkov
Copy link
Contributor

petrochenkov commented Aug 6, 2024

I'm not sure what I should do with this PR.
Do you plan to work on merging this change instead of @SparrowLii, test whether it actually enables incremental reuse, and answer the questions from #125356? Then we can close that PR.

If some changes are refactorings orthogonal to #125356, then we can merge them in a separate PR before #125356 instead of on top of it (feel free to assign such a PR to me).

@petrochenkov
Copy link
Contributor

Hmm, we can actually run benchmarks on this versions, since there are no CI failures anymore.
@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Aug 6, 2024
@petrochenkov petrochenkov removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 6, 2024
@bors
Copy link
Contributor

bors commented Aug 6, 2024

⌛ Trying commit 6134b01 with merge 3866917...

bors added a commit to rust-lang-ci/rust that referenced this pull request Aug 6, 2024
Make declarative macro expansion a part of query system (cont. of rust-lang#125356)

This is a continuation of the effort to make declarative macro expansion a part of the query system from rust-lang#125356 by `@SparrowLii.`

#### Description from that PR:

> This is an attempt to make the macro expansion a part of incremental compilation.
>
> Processing of procedural macros is difficult since they may involve interactions with the external environment. Declaring macros is a good start.
>
> **It is not yet possible to test the effect of this PR on incremental compilation since the new query is declared as eval_always.**

#### Status of this PR:

* It is rebased against a much more recent `master` commit
* It contains the original commits from rust-lang#125356 (in a rebased form)
* It adds the missing implementation for retrying macro matching that provides (better) error diagnostics
  * This was done by refactoring `rustc_expand::mbe::diagnostics::failed_to_match_macro()` to only require a `ParseSess` instead of an `ExtCtxt`. Otherwise, `ExtCtxt` would need to be in the interface of `TcxMacroExpander`, which is not possible, because `ExtCtxt` is part of `rustc_expand`, which depends on the crate that contains `TcxMacroExpander`, `rustc_middle`, and thus would introduce a circular dependency.
  * This refactoring moved the retrying down into the `impl TcxMacroExpander for MacroRulesMacroExpander` (this is just a change compared to the original PR, otherwise not important to know).
* This PR passes `./x test tests/ui`, which produced errors before that were all due to the missing implementation of retry macro matching.
* This PR does **not** yet contain changes for the open discussions from rust-lang#125356. I wanted to fix the tests first before tackling them, and I also need to figure out what the best solutions for them are. I'd welcome any help/support with this, e.g., opening up a corresponding discussion on this PR with a summary/the final decided fix if available :)

In general, I'm new to working on rustc, so would be thankful for a bit more background/explanations in discussions and comments :) Thanks! :)

(tangentially relevant: rust-lang#99515)
@futile
Copy link
Contributor Author

futile commented Aug 6, 2024

Thanks for taking a look!

I'm not sure what I should do with this PR. Do you plan to work on merging this change instead of @SparrowLii, test whether it actually enables incremental reuse, and answer the questions from #125356? Then we can close that PR.

I do intend to finish this, and have already started testing whether this enables incremental reuse (see futile/rust@expand1-cont...futile:rust:cache-decl-macros), and am also up to (try to) answer the questions from the other PR. (I think incremental reuse will have to wait for #124141 though, more on that below. Actually might have found a way, see below.)

However, I want to make sure that I'm not taking away @SparrowLii's work here, but I haven't heard back from them yet, so not sure what to do about that.

If some changes are refactorings orthogonal to #125356, then we can merge them in a separate PR before #125356 instead of on top of it (feel free to assign me).

Maybe the changes in rustc_expand::mbe::diagnostics, see here?

They make the module depend less on ExtCtxt, and instead use ParseSess and DiagCtx directly. I can't judge how useful that refactoring is outside the scope of this PR, or if it's actually going in the wrong direction. But that would be one thing I see.


So, on the topic of incremental reuse. This will, somewhat obviously, require also making the macro arguments, a TokenStream, part of the key used for the query/caching. Otherwise changed arguments will not trigger recompilation, and instead reuse the old macro expansion result, which is wrong.

However. This will require us to somehow hash the TokenStream, which I thought was not (easily) possible, due to Nonterminals (which can contain parts of the AST). This was also discussed in the original PR: #125356 (comment).

In practice this triggered this panic when compiling core:

impl<CTX> HashStable<CTX> for Nonterminal
where
CTX: crate::HashStableContext,
{
fn hash_stable(&self, _hcx: &mut CTX, _hasher: &mut StableHasher) {
panic!("interpolated tokens should not be present in the HIR")
}
}

However! If I, instead, stable-hash the flattened TokenStream, using TokenStream::flattened(), it seems to actually JustWork™. Meaning, ./x test tests/incremental passes. Wow, just stumbled on that, awesome. I'll probably open a draft PR for the version with incremental reuse, to get full CI. Edit: PR is up here: #128747. Edit 2: CI is green on that PR as well!

That said, I'm not sure if it might make sense to wait for #124141 here anyway, since that should (trivially) enable stable-hashing the TokenStream. But I can't judge if using TokenStream::flattened() instead is wrong/slow/suboptimal for other reasons/etc.

Also ty for the perf run, hope it'll go well! :)

@bors
Copy link
Contributor

bors commented Aug 6, 2024

☀️ Try build successful - checks-actions
Build commit: 3866917 (38669170c439fc753c04a96a366d3418552933ae)

@rust-timer

This comment has been minimized.

bors added a commit to rust-lang-ci/rust that referenced this pull request Aug 6, 2024
Cache declarative macro expansion on disk (for incremental comp.). Based on rust-lang#128605

## NOTE: Don't merge yet, mostly here for CI, also rebased on top of rust-lang#128605!

This PR enables on-disk caching for incremental compilation of declarative macro expansions. The base mechanism is added in rust-lang#128605, but not enabled for incremental comp. there yet.

r? `@petrochenkov` since you are in the loop here, but feel free to un-/reassign.
@petrochenkov
Copy link
Contributor

Maybe the changes in rustc_expand::mbe::diagnostics, see here?

Yes, from a brief look that's the part that can be split.

However! If I, instead, stable-hash the flattened TokenStream, using TokenStream::flattened(), it seems to actually JustWork™.

Yes, the flattening should work in the meantime.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (3866917): comparison URL.

Overall result: ❌ regressions - ACTION NEEDED

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please indicate this with @rustbot label: +perf-regression-triaged along with sufficient written justification. If you cannot justify the regressions please fix the regressions and do another perf run. If the next run shows neutral or positive results, the label will be automatically removed.

@bors rollup=never
@rustbot label: -S-waiting-on-perf +perf-regression

Instruction count

This is a highly reliable metric that was used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
1.2% [0.2%, 5.3%] 60
Regressions ❌
(secondary)
0.7% [0.1%, 1.7%] 14
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 1.2% [0.2%, 5.3%] 60

Max RSS (memory usage)

Results (primary 5.6%, secondary 27.7%)

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
5.6% [0.8%, 22.8%] 114
Regressions ❌
(secondary)
27.7% [1.3%, 93.4%] 32
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 5.6% [0.8%, 22.8%] 114

Cycles

Results (primary 3.0%, secondary 3.9%)

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
3.3% [1.3%, 8.5%] 21
Regressions ❌
(secondary)
6.4% [1.9%, 12.4%] 13
Improvements ✅
(primary)
-2.9% [-2.9%, -2.9%] 1
Improvements ✅
(secondary)
-2.3% [-2.7%, -2.1%] 5
All ❌✅ (primary) 3.0% [-2.9%, 8.5%] 22

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 760.99s -> 762.113s (0.15%)
Artifact size: 336.87 MiB -> 337.09 MiB (0.07%)

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Aug 6, 2024
@futile
Copy link
Contributor Author

futile commented Aug 6, 2024

Dang, but yeah, makes sense that it's a regression, since the path through the query system probably adds some overhead/instructions compared to the direct path. But ~1% on average is sadly a pretty hard hit 🙈

Let's wait what the perf results for #128747 will be, but having these results is nice to have a baseline for the caching cost.

But given these regressions it probably doesn't make sense to merge this without actual re-use, either through #128747 or another approach, which then also has to show an actual performance improvement.

@SparrowLii
Copy link
Member

SparrowLii commented Aug 7, 2024

@futile Thank you very much for your work. I can't spend much time on continuing the incremental compilation work for the time being due to some other work. Feel free to close #125356 if your work can replace it. (Notify me or @petrochenkov )

(I was waiting for #124141 to be finished. According to oli's opinion, using TokenStream as the query input parameter may be a better way.)

@petrochenkov
Copy link
Contributor

I'll close this in favor of #128747 to reduce the number of open PRs.
Landing any of this (*) is premature anyway until the whole system is ready and gives some perf benefits.

(*) Except for refactorings (6134b01, maybe something else).

tgross35 added a commit to tgross35/rust that referenced this pull request Aug 8, 2024
…=petrochenkov

refactor(rustc_expand::mbe): Don't require full ExtCtxt when not necessary

Refactor `mbe::diagnostics::failed_to_match_macro()` to not require a full `ExtCtxt`, but only a `&ParseSess`. It hard-required the `ExtCtxt` only for a call to `cx.trace_macros_diag()`, which we move instead to the only call-site of the function.

Note: This could be a potential change in observed behavior, because a call to `cx.trace_macros_diag()` now always happens after `failed_to_match_macro()` was called, where before it was only called at the end of the main return path of the function. But since `trace_macros_diag()` "flushes" out any not-yet-reported errors, it should be ok to call it for all paths, since there shouldn't be any on the non-main paths I think. However, I don't know the rest of the codebase well enough to say that with 100% confidence, but `tests/ui` still pass, which gives at least some confidence in the change.

Also concretize the return type from `Box<dyn MacResult>` to `(Span, ErrorGuaranteed)`, because this function will _always_ return an error, and never any other kind of result.

Was part of rust-lang#128605 and rust-lang#128747, but is a standalone refactoring.

r? ``@petrochenkov``
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Aug 8, 2024
Rollup merge of rust-lang#128798 - futile:refactor/mbe-diagnostics, r=petrochenkov

refactor(rustc_expand::mbe): Don't require full ExtCtxt when not necessary

Refactor `mbe::diagnostics::failed_to_match_macro()` to not require a full `ExtCtxt`, but only a `&ParseSess`. It hard-required the `ExtCtxt` only for a call to `cx.trace_macros_diag()`, which we move instead to the only call-site of the function.

Note: This could be a potential change in observed behavior, because a call to `cx.trace_macros_diag()` now always happens after `failed_to_match_macro()` was called, where before it was only called at the end of the main return path of the function. But since `trace_macros_diag()` "flushes" out any not-yet-reported errors, it should be ok to call it for all paths, since there shouldn't be any on the non-main paths I think. However, I don't know the rest of the codebase well enough to say that with 100% confidence, but `tests/ui` still pass, which gives at least some confidence in the change.

Also concretize the return type from `Box<dyn MacResult>` to `(Span, ErrorGuaranteed)`, because this function will _always_ return an error, and never any other kind of result.

Was part of rust-lang#128605 and rust-lang#128747, but is a standalone refactoring.

r? ``@petrochenkov``
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
perf-regression Performance regression. 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.

9 participants