-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
Regression between nightlies with -Zpolonius
#126520
Comments
Ok that was almost certainly caused by my fix, thanks for finding this. I’ll look into it this week! |
Do we know if this an actual regression or a false negative that was "fixed" by #125652? I myself didn't have time to look at the differences in fact generation produced by the PR, nor test cases that could be impacted -- and I don't know of Amanda's own results there. This looks like the former but And finally, since this pattern is obviously one of our most important use-cases, I'd also be interested in knowing why use the hack to define your lending iterators? Are there other constraints that prevent using regular GATs, or was that maybe a constraint of your own tooling? Footnotes
|
My understanding (though not very firm) was that #125652 should be a no-op for Polonius facts and I’ll have to look into why it isn’t, so this bug is useful in the sense that it proves this belief wrong. In general this code path is too complicated and I’d like to clear it up; this seems like a good motivation to do that now. |
I don't know if this is a valid argument, but I was able to make this code work using polonius_the_crab, which suggests to me that it should be accepted.
Yep, I can't use GATs because a well-known limitation: I want to define a trait alias pub trait TypeWalker:
Sized + LendingIterator + for<'item> LendingIterator<Item<'item> = (&'item mut dyn Any, Event)>
{}
impl<T> TypeWalker for T
where
T: LendingIterator,
T: for<'item> LendingIterator<Item<'item> = (&'item mut dyn Any, Event)>,
{} but if I use real GATs this bound forces |
First things first, I guess: @rustbot claim I have looked into this a bit, and the code I reactivated in #125652 now seems deeply suspicious to me. I'll continue investigations this week.
The results are in!
Specifically, removing the call to |
Heh, I do, however, have a "soundness test", wherein I delegate a proof of soundness of my API to I have produced a smaller repro, at the very least: https://rust.godbolt.org/z/bb6n7b8Yx: trait ForLt { type Of<'__>; }
fn polonius<T, R: ForLt>(
input: &mut T,
f: impl FnOnce(&mut T) -> Option<R::Of<'_>>,
) -> Result<R::Of<'_>, &mut T> {
if let Some(r) = f(input) {
Ok(r)
} else {
Err(input)
}
}
This is indeed an important question! I cannot answer that, but someone here mentioned the word "drop", so I decided to try and rewrite this very snippet in a way that would show the trait ForLt { type Of<'__>; }
fn polonius<T, R: ForLt>(
input: &mut T,
f: impl FnOnce(&mut T) -> Option<R::Of<'_>>,
) -> Result<R::Of<'_>, &mut T> {
if let Some(r) = f(input) {
return Ok(r);
}
// else { drop(f_input) }
Err(input)
} and that one works! So it just looks like the logic is a bit "too" scared of the drop of |
This checks out; I think me connecting a few loose pipes I found in #125652 must have caused too much drop-liveness logic to be applied. I'm very tempted to remove all of it but I'll have to look into it a bit more. So far we don't have a counterexample that shows unsoundness without the extra drop handling, but that doesn't mean one isn't hiding out there somewhere. Anyway, thanks for the smaller repro, that one will be a lot easier to work on. |
Fixes the "future-proofing CI" failures caused by a "false positive regression" in nightly rustc's semantics of `-Zpolonius`. This crate tries to justify its usage of `unsafe` by offering a way to disable it when `-Zpolonius` is used, _via_ its Cargo `--feature polonius`. Indeed, when `-Zpolonius` is being used, there is no need to used any of the API of this crate, which, in fact, includes the very implementation of this crate. So we do precisely that, thereby avoiding the need for any `unsafe`, and thus "proving" that our branch API is sound, _even beyond a `-Zpolonius` context_, since it is proven to be sound there. However, around June, the semantics of `-Zpolonius` changed a bit in `rustc` (nightly), and this non-`unsafe`-`-Zpolonius`-vetted implementation was actually being rejected by it. There is, in fact, an issue about this very thing: - rust-lang/rust#126520 It is unclear whether the rejection is fully legitimate; in this case, and also in the minimization I wrote on that issue, it is a false positive: in the non-dependent branch, there is nothing _dependent_ being dropped "after" our `return` "starts". Still, it may be difficult for the compiler maintainers to properly identify and distinguish this legitimate case from one where the drop could have been problematic (in such cases, the change of `-Zpolonius` semantics was actually a soundness fix!). We thus decide to just work around this tiny "false positive regression" issue by making sure our "drop" of the remainders of the non-dependent value (which happen to be a silly empty ZST (`Placeholder`)) clearly happen, syntactically, before our re-access to the initially (re)borrowed value occurs, when we "start" our `return`.
Fixes the "future-proofing CI" failures caused by a "false positive regression" in nightly rustc's semantics of `-Zpolonius`. This crate tries to justify its usage of `unsafe` by offering a way to disable it when `-Zpolonius` is used, _via_ its Cargo `--feature polonius`. Indeed, when `-Zpolonius` is being used, there is no need to used any of the API of this crate, which, in fact, includes the very implementation of this crate. So we do precisely that, thereby avoiding the need for any `unsafe`, and thus "proving" that our branch API is sound, _even beyond a `-Zpolonius` context_, since it is proven to be sound there. However, around June, the semantics of `-Zpolonius` changed a bit in `rustc` (nightly), and this non-`unsafe`-`-Zpolonius`-vetted implementation was actually being rejected by it. There is, in fact, an issue about this very thing: - rust-lang/rust#126520 It is unclear whether the rejection is fully legitimate; in this case, and also in the minimization I wrote on that issue, it is a false positive: in the non-dependent branch, there is nothing _dependent_ being dropped "after" our `return` "starts". Still, it may be difficult for the compiler maintainer(s) working on this areä to properly identify and distinguish this legitimate case from one where the drop could have been problematic (in such cases, the change of `-Zpolonius` semantics was actually a soundness fix!). We thus decide to just work around this tiny "false positive regression" issue by making sure our "drop" of the remainders of the non-dependent value (which happen to be a silly empty ZST (`Placeholder`)) clearly happen, syntactically, before our re-access to the initially (re)borrowed value occurs, when we "start" our `return`.
Code
I tried this code:
When running this with
-Zpolonius
, this worked with nightly-2024-05-31. With nightly-2024-06-01, I get this error message:Bisection
searched nightlies: from nightly-2024-05-31 to nightly-2024-06-01
regressed nightly: nightly-2024-06-01
searched commit range: 6f3df08...ada5e2c
regressed commit: ada5e2c
bisected with cargo-bisect-rustc v0.6.8
Host triple: x86_64-unknown-linux-gnu
Reproduce with:
This is likely caused by #125652, cc @amandasystems.
The text was updated successfully, but these errors were encountered: