Uh oh!
There was an error while loading. Please reload this page.
Avoid sorting predicates by DefId - #83074
Conversation
rust-highfive
commented
Mar 13, 2021
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.
There was a problem hiding this comment.
This code appears to date back to 2014 from PR #15985:
rust/src/librustc/middle/typeck/collect.rs
Line 1221 in 08f033b
Uh oh!
There was an error while loading. Please reload this page.
oli-obk
commented
Mar 13, 2021
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 |
jackh726
commented
Mar 13, 2021
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. |
Aaron1011
commented
Mar 13, 2021
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 |
Aaron1011
commented
Mar 13, 2021
@bors r=jackh726 |
bors
commented
Mar 13, 2021
📌 Commit 4c0ba8cc0f9f76a95706d6bd5f7dd34ba3cf583d has been approved by |
Aaron1011
commented
Mar 13, 2021
I've added a regression test. @bors r=jackh726 |
bors
commented
Mar 13, 2021
📌 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.
Aaron1011
commented
Mar 13, 2021
@bors r=jackh726 |
bors
commented
Mar 13, 2021
📌 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.
JohnTitor
commented
Mar 14, 2021
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. |
Aaron1011
commented
Mar 14, 2021
@bors rollup=iffy |
bors
commented
Mar 14, 2021
💔 Test failed - checks-actions |
Aaron1011
commented
Mar 14, 2021
@bors r=jackh726 |
bors
commented
Mar 14, 2021
📌 Commit 94604706122cb3b4ae21b79a66d5e3a5fbe105f8 has been approved by |
bors
commented
Mar 14, 2021
⌛ Testing commit 94604706122cb3b4ae21b79a66d5e3a5fbe105f8 with merge 9b3d7d5d8658f518007dd1c485a63d8d14aa1517... |
This comment has been minimized.
This comment has been minimized.
bors
commented
Mar 14, 2021
💔 Test failed - checks-actions |
This is needed to get rustdoc to succeed on `dist-x86_64-linux-alt`
Aaron1011
commented
Mar 15, 2021
@bors r=jackh726 rollup=never |
bors
commented
Mar 15, 2021
📌 Commit 18f8979 has been approved by |
bors
commented
Mar 15, 2021
bors
commented
Mar 15, 2021
☀️ 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
DefIds of all subsequent items. Therefore, we use aDefPathHashin 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
DefIds in the inputs have theirDefPathHashesunchanged. 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 theDefIds gotassigned in a particular compilation session. If some definitions end up
with different
DefIds (but the sameDefPathHashes) 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
astconvby 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
DefIdinastconv, 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-ichby default. This will cause thecompiler to ICE whenver an 'unchanged' query result changes between
compilation sessions, instead of causing a miscompilation.
Ordimpls forCrateNumandDefId. This will make itdifficult to introduce ICEs in the first place.