-
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
Avoid sorting predicates by DefId
#83074
Conversation
r? @oli-obk (rust-highfive has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
@@ -942,7 +942,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { | |||
let mut bounds = Bounds::default(); | |||
|
|||
self.add_bounds(param_ty, ast_bounds, &mut bounds); | |||
bounds.trait_bounds.sort_by_key(|(t, _, _)| t.def_id()); |
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.
This code appears to date back to 2014 from PR #15985:
rust/src/librustc/middle/typeck/collect.rs
Line 1221 in 08f033b
param_bounds.trait_bounds.sort_by(|a,b| a.def_id.cmp(&b.def_id)); |
Thanks for the detailed analysis. I think we should merge this PR quickly, without addressing the two additional protection mechanisms you mentioned. These can then get added to the issue and be addressed independently |
I'm a little surprised that removing the sorting of auto traits does anything, given that we sort the predicates later: CI looks good, so r=me assuming my comments above don't spark any thoughts/concerns. |
Yeah, I'm not quite sure what's going on there. However, this fixes the current miscompilation - once we start verifying the hashes, we'll find out if that sorting has any impact.
I tried this in #83005, but it ended up making the UI test output dependent on whether debuginfo/debug-assertions were enabled in the |
@bors r=jackh726 |
📌 Commit 4c0ba8cc0f9f76a95706d6bd5f7dd34ba3cf583d has been approved by |
I've added a regression test. @bors r=jackh726 |
📌 Commit 50bd1e9cb1dff6985330b6a24f6b542d771134ac has been approved by |
This comment has been minimized.
This comment has been minimized.
Fixes issue rust-lang#82920 Even if an item does not change between compilation sessions, it may end up with a different `DefId`, since inserting/deleting an item affects the `DefId`s of all subsequent items. Therefore, we use a `DefPathHash` in the incremental compilation system, which is stable in the face of changes to unrelated items. In particular, the query system will consider the inputs to a query to be unchanged if any `DefId`s in the inputs have their `DefPathHash`es unchanged. Queries are pure functions, so the query result should be unchanged if the query inputs are unchanged. Unfortunately, it's possible to inadvertantly make a query result incorrectly change across compilations, by relying on the specific value of a `DefId`. Specifically, if the query result is a slice that gets sorted by `DefId`, the precise order will depend on how the `DefId`s got assigned in a particular compilation session. If some definitions end up with different `DefId`s (but the same `DefPathHash`es) in a subsequent compilation session, we will end up re-computing a *different* value for the query, even though the query system expects the result to unchanged due to the unchanged inputs. It turns out that we have been sorting the predicates computed during `astconv` by their `DefId`. These predicates make their way into the `super_predicates_that_define_assoc_type`, which ends up getting used to compute the vtables of trait objects. This, re-ordering these predicates between compilation sessions can lead to undefined behavior at runtime - the query system will re-use code built with a *differently ordered* vtable, resulting in the wrong method being invoked at runtime. This PR avoids sorting by `DefId` in `astconv`, fixing the miscompilation. However, it's possible that other instances of this issue exist - they could also be easily introduced in the future. To fully fix this issue, we should 1. Turn on `-Z incremental-verify-ich` by default. This will cause the compiler to ICE whenver an 'unchanged' query result changes between compilation sessions, instead of causing a miscompilation. 2. Remove the `Ord` impls for `CrateNum` and `DefId`. This will make it difficult to introduce ICEs in the first place.
@bors r=jackh726 |
📌 Commit 06546d4 has been approved by |
Avoid sorting predicates by `DefId` Fixes issue rust-lang#82920 Even if an item does not change between compilation sessions, it may end up with a different `DefId`, since inserting/deleting an item affects the `DefId`s of all subsequent items. Therefore, we use a `DefPathHash` in the incremental compilation system, which is stable in the face of changes to unrelated items. In particular, the query system will consider the inputs to a query to be unchanged if any `DefId`s in the inputs have their `DefPathHash`es unchanged. Queries are pure functions, so the query result should be unchanged if the query inputs are unchanged. Unfortunately, it's possible to inadvertantly make a query result incorrectly change across compilations, by relying on the specific value of a `DefId`. Specifically, if the query result is a slice that gets sorted by `DefId`, the precise order will depend on how the `DefId`s got assigned in a particular compilation session. If some definitions end up with different `DefId`s (but the same `DefPathHash`es) in a subsequent compilation session, we will end up re-computing a *different* value for the query, even though the query system expects the result to unchanged due to the unchanged inputs. It turns out that we have been sorting the predicates computed during `astconv` by their `DefId`. These predicates make their way into the `super_predicates_that_define_assoc_type`, which ends up getting used to compute the vtables of trait objects. This, re-ordering these predicates between compilation sessions can lead to undefined behavior at runtime - the query system will re-use code built with a *differently ordered* vtable, resulting in the wrong method being invoked at runtime. This PR avoids sorting by `DefId` in `astconv`, fixing the miscompilation. However, it's possible that other instances of this issue exist - they could also be easily introduced in the future. To fully fix this issue, we should 1. Turn on `-Z incremental-verify-ich` by default. This will cause the compiler to ICE whenver an 'unchanged' query result changes between compilation sessions, instead of causing a miscompilation. 2. Remove the `Ord` impls for `CrateNum` and `DefId`. This will make it difficult to introduce ICEs in the first place.
Heads up: This rollup failure (#83096 (comment)) may be related to this PR. I'm uncertain and not going to r- but it'd be great if someone could check it. |
@bors rollup=iffy |
💔 Test failed - checks-actions |
@bors r=jackh726 |
📌 Commit 94604706122cb3b4ae21b79a66d5e3a5fbe105f8 has been approved by |
⌛ Testing commit 94604706122cb3b4ae21b79a66d5e3a5fbe105f8 with merge 9b3d7d5d8658f518007dd1c485a63d8d14aa1517... |
This comment has been minimized.
This comment has been minimized.
💔 Test failed - checks-actions |
This is needed to get rustdoc to succeed on `dist-x86_64-linux-alt`
@bors r=jackh726 rollup=never |
📌 Commit 18f8979 has been approved by |
☀️ Test successful - checks-actions |
Avoid sorting by DefId for `necessary_variants()` Follow-up to rust-lang#83074. Originally I tried removing `impl Ord for DefId` but that hit *lots* of errors 😅 so I thought I would start with easy things. I am not sure whether this could actually cause invalid query results, but this is used from `MarkSymbolVisitor::visit_arm` so it's at least feasible. r? `@Aaron1011`
Avoid sorting by DefId for `necessary_variants()` Follow-up to rust-lang#83074. Originally I tried removing `impl Ord for DefId` but that hit *lots* of errors 😅 so I thought I would start with easy things. I am not sure whether this could actually cause invalid query results, but this is used from `MarkSymbolVisitor::visit_arm` so it's at least feasible. r? ``@Aaron1011``
Avoid sorting by DefId for `necessary_variants()` Follow-up to rust-lang#83074. Originally I tried removing `impl Ord for DefId` but that hit *lots* of errors 😅 so I thought I would start with easy things. I am not sure whether this could actually cause invalid query results, but this is used from `MarkSymbolVisitor::visit_arm` so it's at least feasible. r? `@Aaron1011`
Fixes issue #82920
Even if an item does not change between compilation sessions, it may end
up with a different
DefId
, since inserting/deleting an item affectsthe
DefId
s of all subsequent items. Therefore, we use aDefPathHash
in the incremental compilation system, which is stable in the face of
changes to unrelated items.
In particular, the query system will consider the inputs to a query to
be unchanged if any
DefId
s in the inputs have theirDefPathHash
esunchanged. Queries are pure functions, so the query result should be
unchanged if the query inputs are unchanged.
Unfortunately, it's possible to inadvertantly make a query result
incorrectly change across compilations, by relying on the specific value
of a
DefId
. Specifically, if the query result is a slice that getssorted by
DefId
, the precise order will depend on how theDefId
s gotassigned in a particular compilation session. If some definitions end up
with different
DefId
s (but the sameDefPathHash
es) in a subsequentcompilation session, we will end up re-computing a different value for
the query, even though the query system expects the result to unchanged
due to the unchanged inputs.
It turns out that we have been sorting the predicates computed during
astconv
by theirDefId
. These predicates make their way into thesuper_predicates_that_define_assoc_type
, which ends up getting used tocompute the vtables of trait objects. This, re-ordering these predicates
between compilation sessions can lead to undefined behavior at runtime -
the query system will re-use code built with a differently ordered
vtable, resulting in the wrong method being invoked at runtime.
This PR avoids sorting by
DefId
inastconv
, fixing themiscompilation. However, it's possible that other instances of this
issue exist - they could also be easily introduced in the future.
To fully fix this issue, we should
-Z incremental-verify-ich
by default. This will cause thecompiler to ICE whenver an 'unchanged' query result changes between
compilation sessions, instead of causing a miscompilation.
Ord
impls forCrateNum
andDefId
. This will make itdifficult to introduce ICEs in the first place.