-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Separate fn signature from fn body in HIR #35078
Comments
The body is a block and those are in the HIR map already, so I think the only missing thing is keeping an ID instead of a reference, and looking up that ID every time. |
I'm currently looking into this, and I think I've got the general idea, but I've got a few questions to make sure I'm on the right track:
|
@flodiebold great! Sorry I haven't had a chance to respond yet. Let me start by giving a few quick answers, I only have a few minutes just now.
I would expect it to be a different kind of
The
Yes, I think so.
Well, we could, but we don't use privacy much for LIR; I would be inclined to move it into separate array myself.
See above. I think it probably makes sense, just so that
Yeah, that's a tricky one. I'd say add the visitor and -- to start -- visit the block by default. That should preserve the existing behavior, and you can test and make sure everything is working. Then we can debate changing the default; it'd require going through the visitors a bit to see what they do. |
If I may make a suggestion, there is a more useful abstraction here than function bodies, that I keep needing time and time again, that is, definitions that have associated MIR (just "bodies"?). |
@eddyb interesting. It seems like all the same benefits for incr comp would apply to most of those cases too. I wonder if the right type for these "bodies" would be expressions and not blocks, so that they can be used everywhere. |
So I got stuck in a place where I really really needed an unified way to refer to those bodies, so I tried moving all of them to For some reason, if I have It's not clear to me as to why this would be the case, since I might be able to fix this now, although I'm still not sure what the correct behavior should be, really. |
@eddyb I think I expect there to be both a |
Update: it was these few lines which are both no longer necessary and require a |
@flodiebold (so, I want to clarify something. I think that we should consider factoring out statics, constants, closure bodies, etc as a second step -- it makes sense to just focus on fn bodies first, we can refactor as a follow-up if we choose.) |
This is more complex than I expected, but I hope to have one or two commits soon that can be cherry-picked. |
@flodiebold Here you go: eddyb@203ccaf - should apply relatively cleanly on master. I wanted to add a |
Great! I'm taking a look. |
@eddyb Ok, I've cherry-picked the commit without big conflicts. But I'm now getting two spurious 'unreachable statement' warnings in libsyntax when compiling stage 2, failing the build :( The lines the compiler says are unreachable are here and here. |
@flodiebold Oops, I never tried building stage2. The crater run I just started will probably catch it. Yeah, those cases are almost unreachable, looks like |
@flodiebold Alright, that was only a leak from "then" to "else". Fixed commit is eddyb@75269d2. EDIT: still broken (this time in |
Can patterns from fn parameters be moved into the function body somehow? (Probably in HIR?)
=>
|
@petrochenkov Yeah, the argument types and the patterns can be split into two lists. |
@flodiebold @nikomatsakis Good news! You can just rebase on top of #37412 now. |
Prohibit patterns in trait methods without bodies They are not properly type checked ```rust trait Tr { fn f(&a: u8); // <- This compiles } ``` , mostly rejected by the parser already and generally don't make much sense. This PR is kind of a missing part of rust-lang#35015. Needs crater run. cc rust-lang#35078 (comment) rust-lang#35015 rust-lang/rfcs#1685 rust-lang#35203 r? @eddyb
Prohibit patterns in trait methods without bodies They are not properly type checked ```rust trait Tr { fn f(&a: u8); // <- This compiles } ``` , mostly rejected by the parser already and generally don't make much sense. This PR is kind of a missing part of #35015. Given the [statistics from crater](#37378 (comment)), the effect of this PR is mostly equivalent to improving `unused_mut` lint. cc #35078 (comment) #35015 rust-lang/rfcs#1685 #35203 r? @eddyb
Ok, I'm making some progress. Two snags I ran into:
Currently, my main problem is the following: Compilation of librand fails because I think the compiler is trying to const-eval a function from libcore, for which it needs the HIR of the body, and that's not saved in the crate metadata anymore. So I'll probably need to add the function bodies somewhere in the crate metadata, but I'm not yet sure how to approach that. My current state is here. |
@flodiebold The only thing that's needed is the body, you might be able to change astencode to only work on bodies. |
Great to hear! In the meantime, I've been working on #36349, and I'm making good progress there I think. Some of the things you are describing overlap.
Yeah, this is sort of annoying. =) In principle we should be able to use specialization here to make this a touch more ergonomic, though some key features are missing. So I did something to these traits too =). What I did is to separate out items and impl-items into the category of "Item-like" (I should probably factor our trait-items too). Then the
To address this very last bullet point, and this seems relevant to what you were writing, I was contemplating having a Then again, it'd be better to avoid walking nested things like that by default, just to make the code more intentional. My preference in this refactoring, btw, would be to have the nested case implement some other trait ( |
cc me |
Still working on this. I've got something which passes |
@flodiebold nice! I hope to have my PR up today -- but I'm cleaning up the last bit, which is taking longer than I wanted. If you want to check out my current branch, it's here |
[6/n] rustc: transition HIR function bodies from Block to Expr. _This is part of a series ([prev](rust-lang#37408) | [next](rust-lang#37676)) of patches designed to rework rustc into an out-of-order on-demand pipeline model for both better feature support (e.g. [MIR-based](https://github.com/solson/miri) early constant evaluation) and incremental execution of compiler passes (e.g. type-checking), with beneficial consequences to IDE support as well. If any motivation is unclear, please ask for additional PR description clarifications or code comments._ <hr> The main change here is that functions and closures both use `Expr` instead of `Block` for their bodies. For closures this actually allows a honest representation of brace-less closure bodies, e.g. `|x| x + 1` is now distinguishable from `|x| { x + 1 }`, therefore this PR is `[syntax-breaking]` (cc @Manishearth). Using `Expr` allows more logic to be shared between constant bodies and function bodies, with some small such changes already part of this PR, and eventually easing rust-lang#35078 and per-body type tables. Incidentally, there used to be some corners cut here and there and as such I had to (re)write divergence tracking for type-checking so that it is capable of understanding basic structured control-flow: ``` rust fn a(x: bool) -> i32 { // match also works (as long as all arms diverge) if x { panic!("true") } else { return 1; } 0 // "unreachable expression" after this PR } ``` And since liveness' "not all control paths return a value" moved to type-checking we can have nice things: ``` rust // before & after: fn b() -> i32 { 0; } // help: consider removing this semicolon // only after this PR fn c() -> i32 { { 0; } } // help: consider removing this semicolon fn d() { let x: i32 = { 0; }; } // help: consider removing this semicolon fn e() { f({ 0; }); } // help: consider removing this semicolon ```
@flodiebold hey, how's it going? I think this is one of the major blockers. |
I've had very little time over the last week, but this weekend I have time and hope to make good progress, maybe even get a pull request ready :) I assume your changes will also be merged until then, so I can rebase on top of that. |
@flodiebold yes, hopefully! I'm tracking down an annoying windows problem, but now that I know what it is (paths too long) we can hopefully resolve it and get the PR landed. |
ok, in that case I'll leave off. |
Separate impl items from the parent impl This change separates impl item bodies out of the impl itself. This gives incremental more resolution. In so doing, it refactors how the visitors work, and cleans up a bit of the collect/check logic (mostly by moving things out of collect that didn't really belong there, because they were just checking conditions). However, this is not as effective as I expected, for a kind of frustrating reason. In particular, when invoking `foo.bar()` you still wind up with dependencies on private items. The problem is that the method resolution code scans that list for methods with the name `bar` -- and this winds up touching *all* the methods, even private ones. I can imagine two obvious ways to fix this: - separating fn bodies from fn sigs (#35078, currently being pursued by @flodiebold) - a more aggressive model of incremental that @michaelwoerister has been advocating, in which we hash the intermediate results (e.g., the outputs of collect) so that we can see that the intermediate result hasn't changed, even if a particular impl item has changed. So all in all I'm not quite sure whether to land this or not. =) It still seems like it has to be a win in some cases, but not with the test cases we have just now. I can try to gin up some test cases, but I'm not sure if they will be totally realistic. On the other hand, some of the early refactorings to the visitor trait seem worthwhile to me regardless. cc #36349 -- well, this is basically a fix for that issue, I guess r? @michaelwoerister NB: Based atop of @eddyb's PR #37402; don't land until that lands.
@nikomatsakis So, I'm rebasing and integrating my visitor changes with yours. Obviously, I also want to use |
@flodiebold so I think it is plausible that visitors should visit the item body by default. At least i'd be fine with landing a change that did this by default. After all, if the visitor does not try to recurse, it won't register as a read, and I think it will be the common case -- most checkers want to check the signature+body together. |
@flodiebold well, in any case, I'd be happy to land a PR where existing behavior is preserved and then we can tinker later, if we see a need. |
Ok, I guess I'll just make the PR. |
Separate function bodies from their signatures in HIR Also give them their own dep map node. I'm still unhappy with the handling of inlined items (1452edc1), but maybe you have a suggestion how to improve it. Fixes #35078. r? @nikomatsakis
Currently, getting access to a HIR item gives you access to both the function signature and its body. This makes the incremental compilation graph more coarse than it should be. To fix this, the best thing would be to separate things out so that the item is just the external signature, and you have to separately load (e.g., from the HIR map) the body for a fn item. This way we could record that you actually accessed the fn body and track that separately.
The text was updated successfully, but these errors were encountered: