-
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
Enable compiler consumers to obtain mir::Body with Polonius facts. #86977
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
r=me but we need a comment somewhere about overriding borrow_check
query for now (eventually we should find a better solution)
Hmm, actually, I wonder if we can think about how to test this? |
I'd be ok to land without tests, but it would be nice to have a "working example" (that tests the corner case, too!) that we can point people at. Maybe add it to a run-make test? |
Mildly revising my opinion. I think I would like such a test before landing, but it doesn't have to deeply inspect the facts or anything. |
9750b60
to
b913a45
Compare
I have added a test that just calls the function and in this way checks that it does not panic. By the way, I did not find a good example on which I could base my |
@@ -0,0 +1,37 @@ | |||
//! This file provides API for compiler consumers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how stable do you hope this API to be ? whether it'd be the polonius facts structure (e.g. relation names, or types), their contents, or the polonius output
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For Prusti, we are upgrading the Rust compiler version twice a month. My hope is that we do not spend more than 3-4 person-hours per upgrade. (Currently, it is about 1 hour on average.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way, Prusti is already using Polonius, but in a very hacky way. So, this PR should only reduce our maintenance efforts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok.
I'll add this as a point of discussion for next week's polonius sprint (I didn't expect we'd have users that rely on all these polonius implementation details) and probably need to maintain some stability to not break prusti.
(Yeah, I remember you told me you were parsing the fact dumps when we talked with oli on how to improve this.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add this as a point of discussion for next week's polonius sprint (I didn't expect we'd have users that rely on all these polonius implementation details) and probably need to maintain some stability to not break prusti.
Thanks! However, I would not worry too much because I think that the data we need is fundamental (in the sense that you will not be able to implement the borrow checker without it).
By the way, feel free to tag me on the discussion. I will be happy to comment on whether the planned changes affect us.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean more for hypotheticals like changing implementation like we talked about in barcelona: "what if we need to change the whole facts to something other than flat relations", or "don't compute all the loans in all the origins at all points", or "what if we move away from datalog one day" that kinda thing 😅
In the close future I wouldn't worry too much about that, for sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the long term, the goal would be to make Prusti use optimized_mir
or some other version of MIR that is used by all compiler consumers. Then how Polonius works should not matter anymore.
@bors r+ |
📌 Commit e5e6acd has been approved by |
⌛ Testing commit e5e6acd with merge 3fbd225b9e340a1c2aee3a4a1eb315d027082b51... |
This comment has been minimized.
This comment has been minimized.
💔 Test failed - checks-actions |
The test succeeds now for me with |
@bors r+ |
📌 Commit 9142d6d has been approved by |
☀️ Test successful - checks-actions |
It seems like the exported facts reference a number of data types that are private to rustc. For example, |
I had a version of Prusti that passes our tests with this PR. Let me check whether something went wrong. |
@vakaras I also was able to use this PR to extract the first two fields of the outlives-constraints. So it's not broken per se. But I can't explicitly reference the type of the third field of the outlives-constraint tuple. I'm a bit surprised this isn't a "private type in public interface" error -- I'm guessing because there's some levels of indirections through generics and associated types? See: https://github.com/willcrichton/flowistry/blob/master/src/slicing/mod.rs#L275-L283 |
@willcrichton You need to do that in a slightly round-about way: willcrichton/flowistry#1. |
Ah I see, thanks @vakaras! |
One other question -- when I call |
It should be populated, but it is possible that I mixed something up. |
I built from master and the issue seems to have been fixed. I think it's just a gap between nightly and master, so false alarm. |
…call, r=ecstatic-morse Allow calling `get_body_with_borrowck_facts` without `-Z polonius` For my [static analysis tool](https://github.com/willcrichton/flowistry), I need to access the set of outlives-constraints. Recently, rust-lang#86977 merged a way to access these facts via Polonius. However, the merged implementation requires `-Z polonius` to be provided to use this feature. This uses Polonius for borrow checking on the entire crate, which as described [here](https://rust-lang.zulipchat.com/#narrow/stream/186049-t-compiler.2Fwg-polonius/topic/Polonius.20performance.20in.20a.20rustc.20plugin/near/251301631), is very slow. This PR allows `get_body_with_borrowck_facts` to be called without `-Z polonius`. This is essential for my tool to run in a sensible length of time. This is a temporary patch as the Polonius-related APIs develop -- I can update my code as future changes happen. Additionally, this PR also makes public two APIs that were previously public but then became private after `rustc_mir` got broken up: `rustc_mir_dataflow::framework::graphviz` and `rustc_mir_transform::MirPass`. I need both of these for my analysis tool. (I can break this change into a separate PR if necessary.)
…call, r=ecstatic-morse Allow calling `get_body_with_borrowck_facts` without `-Z polonius` For my [static analysis tool](https://github.com/willcrichton/flowistry), I need to access the set of outlives-constraints. Recently, rust-lang#86977 merged a way to access these facts via Polonius. However, the merged implementation requires `-Z polonius` to be provided to use this feature. This uses Polonius for borrow checking on the entire crate, which as described [here](https://rust-lang.zulipchat.com/#narrow/stream/186049-t-compiler.2Fwg-polonius/topic/Polonius.20performance.20in.20a.20rustc.20plugin/near/251301631), is very slow. This PR allows `get_body_with_borrowck_facts` to be called without `-Z polonius`. This is essential for my tool to run in a sensible length of time. This is a temporary patch as the Polonius-related APIs develop -- I can update my code as future changes happen. Additionally, this PR also makes public two APIs that were previously public but then became private after `rustc_mir` got broken up: `rustc_mir_dataflow::framework::graphviz` and `rustc_mir_transform::MirPass`. I need both of these for my analysis tool. (I can break this change into a separate PR if necessary.)
…call, r=ecstatic-morse Allow calling `get_body_with_borrowck_facts` without `-Z polonius` For my [static analysis tool](https://github.com/willcrichton/flowistry), I need to access the set of outlives-constraints. Recently, rust-lang#86977 merged a way to access these facts via Polonius. However, the merged implementation requires `-Z polonius` to be provided to use this feature. This uses Polonius for borrow checking on the entire crate, which as described [here](https://rust-lang.zulipchat.com/#narrow/stream/186049-t-compiler.2Fwg-polonius/topic/Polonius.20performance.20in.20a.20rustc.20plugin/near/251301631), is very slow. This PR allows `get_body_with_borrowck_facts` to be called without `-Z polonius`. This is essential for my tool to run in a sensible length of time. This is a temporary patch as the Polonius-related APIs develop -- I can update my code as future changes happen. Additionally, this PR also makes public two APIs that were previously public but then became private after `rustc_mir` got broken up: `rustc_mir_dataflow::framework::graphviz` and `rustc_mir_transform::MirPass`. I need both of these for my analysis tool. (I can break this change into a separate PR if necessary.)
…facts-flag, r=ecstatic-morse Populate liveness facts when calling `get_body_with_borrowck_facts` without `-Z polonius` For a new feature of [Flowistry](https://github.com/willcrichton/flowistry), a static-analysis tool, we need to obtain a `mir::Body`'s liveness facts using `get_body_with_borrowck_facts` (added in rust-lang#86977). We'd like to do this without passing `-Z polonius` as a compiler arg to avoid borrow checking the entire crate. Support for doing this was added in rust-lang#88983, but the Polonius input facts used for liveness analysis are empty. This happens because the liveness input facts are populated in `liveness::generate` depending only on the value of `AllFacts::enabled` (which is toggled via compiler args). This PR propagates the [`use_polonius`](https://github.com/rust-lang/rust/blob/8b09ba6a5d5c644fe0f1c27c7f9c80b334241707/compiler/rustc_borrowck/src/nll.rs#L168) flag to `liveness::generate` to support populating liveness facts without requiring the `-Z polonius` flag. This fix is somewhat patchy - if it'd be better to add more widely-accessible state (like `AllFacts::enabled`) I'd be open to ideas!
…facts-flag, r=ecstatic-morse Populate liveness facts when calling `get_body_with_borrowck_facts` without `-Z polonius` For a new feature of [Flowistry](https://github.com/willcrichton/flowistry), a static-analysis tool, we need to obtain a `mir::Body`'s liveness facts using `get_body_with_borrowck_facts` (added in rust-lang#86977). We'd like to do this without passing `-Z polonius` as a compiler arg to avoid borrow checking the entire crate. Support for doing this was added in rust-lang#88983, but the Polonius input facts used for liveness analysis are empty. This happens because the liveness input facts are populated in `liveness::generate` depending only on the value of `AllFacts::enabled` (which is toggled via compiler args). This PR propagates the [`use_polonius`](https://github.com/rust-lang/rust/blob/8b09ba6a5d5c644fe0f1c27c7f9c80b334241707/compiler/rustc_borrowck/src/nll.rs#L168) flag to `liveness::generate` to support populating liveness facts without requiring the `-Z polonius` flag. This fix is somewhat patchy - if it'd be better to add more widely-accessible state (like `AllFacts::enabled`) I'd be open to ideas!
Expose more information in `get_body_with_borrowck_facts` Verification tools for Rust such as, for example, Creusot or Prusti would benefit from having access to more information computed by the borrow checker. As a first step in that direction, rust-lang#86977 added the `get_body_with_borrowck_facts` API, allowing compiler consumers to obtain a `mir::Body` with accompanying borrow checker information. At RustVerify 2023, multiple people working on verification tools expressed their need for a more comprehensive API. While eventually borrow information could be part of Stable MIR, in the meantime, this PR proposes a more limited approach, extending the existing `get_body_with_borrowck_facts` API. In summary, we propose the following changes: - Permit obtaining the borrow-checked body without necessarily running Polonius - Return the `BorrowSet` and the `RegionInferenceContext` in `BodyWithBorrowckFacts` - Provide a way to compute the `borrows_out_of_scope_at_location` map - Make some helper methods public This is similar to rust-lang#108328 but smaller in scope. `@smoelius` Do you think these changes would also be sufficient for your needs? r? `@oli-obk` cc `@JonasAlaif`
This PR adds a function (
get_body_with_borrowck_facts
) that can be used by compiler consumers to obtainmir::Body
with accompanying borrow checker information.The most important borrow checker information that our verifier called Prusti needs is lifetime constraints. I have not found a reasonable way to compute the lifetime constraints on the Prusti side. In the compiler, the constraints are computed during the borrow checking phase and then dropped. This PR adds an additional parameter to the
do_mir_borrowck
function that tells it to return the computed information instead of dropping it.The additionally returned information by
do_mir_borrowck
contains amir::Body
with non-erased lifetime regions and Polonius facts. I have decided to reuse the Polonius facts because this way I needed fewer changes to the compiler and Polonius facts contains other useful information that we otherwise would need to recompute.Just FYI: up to now, Prusti was obtaining this information by parsing the compiler logs. This is not only a hacky approach, but we also reached its limits.
r? @nikomatsakis