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

Store a MirSource inside every Body #77430

Merged
merged 4 commits into from
Oct 4, 2020

Conversation

ecstatic-morse
Copy link
Contributor

Resolves #77427.

r? @ghost

@ecstatic-morse
Copy link
Contributor Author

@lcnr I don't understand how to use WithOptConstParam. What's going wrong here?

@ecstatic-morse
Copy link
Contributor Author

ecstatic-morse commented Oct 2, 2020

r? @lcnr I guess. I was expecting this to be a straightforward refactoring, but #74113 has made me a bit frustrated

It feels like we could make WithOptConstParam less invasive when it comes to the *_mir queries. A MIR body either comes from an AnonConst or not, and that doesn't change as we progress through the optimization pipeline. Given that, why does this type infect everything?

Copy link
Contributor

@lcnr lcnr left a comment

Choose a reason for hiding this comment

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

So WithOptConstParam is used if we ever call type_of for the mir body.

As we call type_of in some annoyingly annoying places, we have to somehow get the DefId of the relevant const param there.
Once we build a Body with the correct WithOptConstParam, we should then be able to use that mir_source in the remaining mir_* queries.

WithOptConstParam infects all of the mir queries as we call optimized_mir during typeck (which is where the cycle errors are the problem) so we have to somehome thread these calls down to mir_built which uses type_of. Not sure if type_of is called in some other mir queries

@@ -740,6 +750,7 @@ fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'t
impl<'a, 'tcx> Builder<'a, 'tcx> {
fn new(
hir: Cx<'a, 'tcx>,
def_id: DefId,
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
def_id: DefId,
def: ty::WithOptConstParam<DefId>,

I think it should be easier to already pass the correct WithOptConstParam into this builder.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's the part I'm not understanding. What are the invariants of WithOptConstParam? When is it okay to be unknown? Do I have to call try_upgrade manually?

Copy link
Contributor

Choose a reason for hiding this comment

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

The invariant of WithOptConstParam is that if self.const_param_did.is_some(), then self.const_param_did == tcx.opt_const_param_of(self.did). To prevent cycle errors self.const_param_did should also be Some if it is used during typeck, did is a const argument and we want to know tcx.type_of(did), which we then replace with tcx.type_of(def.def_id_for_type_of()).

You should never have to call try_upgrade except at the start of a query taking ty::WithOptConstParam so that we only evaluate it once.

It is okay to use unknown if we are either done with typeck or tcx.opt_const_param_of(self.did) would/did return None.

Looks like it might be worth it to add a section to the rustc-dev-guide about WithOptConstParam 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks like it might be worth it to add a section to the rustc-dev-guide about WithOptConstParam thinking

As I've alluded to, I think time would be better spent better encapsulating this system. I don't particularly want to think about it when writing MIR transformations. I realize I'm being a bit curmudgeonly here and that this is in service of a feature which I'm super excited about (thanks BTW!), but technical debt is a real concern, especially in mir-opt land.

Is there anything we could do to reduce the surface area here? We can discuss this in a separate issue I guess.

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like I didn't send the message I wanted to send here 😅

While working on this I experimented with some different approaches and the less invasive ones all ended up being unsound in the face of incremental compilation. So I would be glad - and a bit annoyed 😆 - if you are able to come up with a less invasive solution here, but do think that this will be quite hard to do

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have some ideas, but if you've already explored alternatives, it's unlikely that I'll be able to do better. I've not given up quite yet though 😄.

compiler/rustc_middle/src/mir/mod.rs Outdated Show resolved Hide resolved
}

impl<'tcx> MirSource<'tcx> {
pub fn item(def_id: DefId) -> Self {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
pub fn item(def_id: DefId) -> Self {
pub fn item(def: ty::WithOptParam<DefId>) -> Self {

my personal preference, makes it harder to get this wrong

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This isn't mine. I've just moved it from transform/mod.rs.

Copy link
Contributor

Choose a reason for hiding this comment

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

yeah, I still think that this would be a good change though 🤔 you don't have to do this in this PR

add_moves_for_packed_drops(tcx, body, src.def_id());
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
debug!("add_moves_for_packed_drops({:?} @ {:?})", body.source, body.span);
add_moves_for_packed_drops(tcx, body, body.source.def_id());
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
add_moves_for_packed_drops(tcx, body, body.source.def_id());
add_moves_for_packed_drops(tcx, body);

we only use to body source in add_moves_for_packed_drops, don't we?

let mut opt_finder = RemoveUnneededDropsOptimizationFinder {
tcx,
body,
optimizations: vec![],
def_id: source.def_id().expect_local(),
def_id: body.source.def_id().expect_local(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
def_id: body.source.def_id().expect_local(),

Can we instead use the body def_id here?

@bors
Copy link
Contributor

bors commented Oct 2, 2020

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

Note that reviewers usually do not review pull requests until merge conflicts are resolved! Once you resolve the conflicts, you should change the labels applied by bors to indicate that your PR is ready for review. Post this as a comment to change the labels:

@rustbot modify labels: +S-waiting-on-review -S-waiting-on-author

@bors bors added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Oct 2, 2020
@ecstatic-morse
Copy link
Contributor Author

There's a follow-up to #77427, which is to remove the DefId from all (DefId, Body) pairs in function signatures. I'm not going to it as part of this PR (though I think I did a few functions by accident in pretty.rs) since it's already prone to merge conflicts.

Comment on lines -32 to +38
tcx.alloc_steal_mir(mir_build(tcx, def))
let mut body = mir_build(tcx, def);
if def.const_param_did.is_some() {
assert!(matches!(body.source.instance, ty::InstanceDef::Item(_)));
body.source = MirSource::from_instance(ty::InstanceDef::Item(def.to_global()));
}

tcx.alloc_steal_mir(body)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@lcnr what should this look like in your eyes? It seems like we should do this when the MIR is built instead, but that means calling try_upgrade outside of a query?

Copy link
Contributor

@lcnr lcnr Oct 2, 2020

Choose a reason for hiding this comment

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

let body = mir_built(txc, def);
tcx.alloc_steal_mir(body)

Copy link
Contributor

Choose a reason for hiding this comment

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

we already have def as an input to mir_built, so we should be able to use the correct source right from the start here.

Copy link
Contributor Author

@ecstatic-morse ecstatic-morse Oct 2, 2020

Choose a reason for hiding this comment

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

That causes cycle errors during type-checking.

edit: Sorry, I see my force-push erased the run results for the version of this PR without this commit. I'll try to find the failing test.

Copy link
Contributor

Choose a reason for hiding this comment

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

why do you think that we should call try_upgrade here?

Copy link
Contributor

Choose a reason for hiding this comment

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

I meant inside rustc_mir_builder::Builder::build() or so.

yeah, we should never have to call try_upgrade inside of mir_built after the initial call at the start of the query. If you can get the failing state again I would gladly look into what's going wrong there

Copy link
Contributor Author

Choose a reason for hiding this comment

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

error[E0391]: cycle detected when type-checking `main`
  --> /home/mackendy/src/rust/rust/alt/src/test/ui/const-generics/slice-const-param-mismatch.rs:18:33
   |
LL |     let _: ConstBytes<b"AAA"> = ConstBytes::<{&[0x41, 0x41, 0x41]}>;
   |                                 ^^^^^^^^^^^^^
   |
note: ...which requires simplifying constant for the type system `main::{constant#9}`...
  --> /home/mackendy/src/rust/rust/alt/src/test/ui/const-generics/slice-const-param-mismatch.rs:18:46
   |
LL |     let _: ConstBytes<b"AAA"> = ConstBytes::<{&[0x41, 0x41, 0x41]}>;
   |                                              ^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `main::{constant#9}`...
  --> /home/mackendy/src/rust/rust/alt/src/test/ui/const-generics/slice-const-param-mismatch.rs:18:46
   |
LL |     let _: ConstBytes<b"AAA"> = ConstBytes::<{&[0x41, 0x41, 0x41]}>;
   |                                              ^^^^^^^^^^^^^^^^^^^^^
   = note: ...which requires normalizing `main::{constant#9}::promoted[0]`...
note: ...which requires resolving instance `main::{constant#9}`...
  --> /home/mackendy/src/rust/rust/alt/src/test/ui/const-generics/slice-const-param-mismatch.rs:18:46
   |
LL |     let _: ConstBytes<b"AAA"> = ConstBytes::<{&[0x41, 0x41, 0x41]}>;
   |                                              ^^^^^^^^^^^^^^^^^^^^^
note: ...which requires computing the optional const parameter of `main::{constant#9}`...
  --> /home/mackendy/src/rust/rust/alt/src/test/ui/const-generics/slice-const-param-mismatch.rs:18:46
   |
LL |     let _: ConstBytes<b"AAA"> = ConstBytes::<{&[0x41, 0x41, 0x41]}>;
   |                                              ^^^^^^^^^^^^^^^^^^^^^
   = note: ...which again requires type-checking `main`, completing the cycle
   = note: cycle used when type-checking all item bodies

error: aborting due to 4 previous errors

Some errors have detailed explanations: E0308, E0391.
For more information about an error, try `rustc --explain E0308`.

------------------------------------------



failures:
    [ui] ui/const-generics/slice-const-param-mismatch.rs#full
    [ui] ui/const-generics/slice-const-param.rs#full

Cycle along with the two failing tests. This is what happens with just the first commit.

Copy link
Contributor

Choose a reason for hiding this comment

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

   = note: ...which requires normalizing `main::{constant#9}::promoted[0]`...

Is probably where this goes wrong, so we somehow are not using the full def for promoteds.

Not at home rn, will look at where exactly this goes wrong tomorrow.

Copy link
Contributor

@lcnr lcnr Oct 4, 2020

Choose a reason for hiding this comment

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

So your solution is probably the easiest for now...

The actual mir builder currently only uses a DefId and has quite a few entry points.
After we merge this I am going to look into a good way to start with the correct WithOptConstParam in the build::Builder.
The way I expect to do this is a bit like the following but without using WithOptConstParam::unknown there, which is a bit more invasive than I would like in this PR: lcnr@9061538

Copy link
Contributor

Choose a reason for hiding this comment

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

Apart from this I think this is mostly ready for merge 🤔 is there still something you want to do in that PR?

There's a cleaner way of doing this, but it involves passing
`WithOptConstParam` around in more places. We're going to try to explore
different approaches before committing to that.
@ecstatic-morse ecstatic-morse marked this pull request as ready for review October 4, 2020 18:05
@ecstatic-morse
Copy link
Contributor Author

@bors p=1 rollup=never

(prone to merge conflicts)

@lcnr I cleaned up the commit messages and rebased. Nothing else has changed. This should be ready for the queue now.

@lcnr
Copy link
Contributor

lcnr commented Oct 4, 2020

yeah, let's fix the remaining nits in followup PRs

@bors r+

@bors
Copy link
Contributor

bors commented Oct 4, 2020

📌 Commit 606655e has been approved by lcnr

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 4, 2020
@bors
Copy link
Contributor

bors commented Oct 4, 2020

⌛ Testing commit 606655e with merge 4ccf5f7...

@bors
Copy link
Contributor

bors commented Oct 4, 2020

☀️ Test successful - checks-actions, checks-azure
Approved by: lcnr
Pushing 4ccf5f7 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Oct 4, 2020
@bors bors merged commit 4ccf5f7 into rust-lang:master Oct 4, 2020
@rustbot rustbot added this to the 1.49.0 milestone Oct 4, 2020
@RalfJung
Copy link
Member

RalfJung commented Oct 5, 2020

This PR introduced an ICE for mir-opt-level 2 and above: #77564.

@@ -300,7 +301,7 @@ impl Inliner<'tcx> {

// FIXME: Give a bonus to functions with only a single caller

let param_env = tcx.param_env(self.source.def_id());
let param_env = tcx.param_env(callee_body.source.def_id());
Copy link
Contributor

Choose a reason for hiding this comment

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

@ecstatic-morse this is the wrong source, will open a PR for this

Copy link
Contributor

Choose a reason for hiding this comment

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

opened #77568

bors added a commit to rust-lang-ci/rust that referenced this pull request Oct 5, 2020
Replace `(Body, DefId)` with `Body` where possible

Follow-up to rust-lang#77430.

I `grep`-ed for parameter lists in which a `Body` appeared within a few lines of a `DefId`, so it's possible that I missed some cases, but this should be pretty complete. Most of these changes were mechanical, but there's a few places where I started calling things "caller" and "callee" when multiple `DefId`s were in-scope at once. Also, we should probably have a helper function on `Body` that returns a `LocalDefId`. I can do that in this PR or in a follow-up.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Oct 6, 2020
…morse

inliner: use caller param_env

We used the callee param env instead of the caller param env by accident in rust-lang#77430, this PR fixes that and caches it in the `Inliner` struct.

fixes rust-lang#77564

r? @ecstatic-morse
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Every Body should remember its MirSource
5 participants