Skip to content
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

Fix HashStable implementation on AllocId #93472

Closed

Conversation

compiler-errors
Copy link
Member

@compiler-errors compiler-errors commented Jan 30, 2022

(take 2:)

This PR removes the HashStable implementation from AllocId, and fixes the HashStable implementation on ConstValue, ConstAlloc, and Allocation so that their Eq and HashStable implementations agree (as required by HashStable).

Fixes #93470

r? @oli-obk

@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jan 30, 2022
@rust-highfive
Copy link
Collaborator

Some changes occured to the CTFE / Miri engine

cc @rust-lang/miri

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 30, 2022
@compiler-errors
Copy link
Member Author

compiler-errors commented Jan 30, 2022

Ok this definitely doesn't work :^) Of course I should've checked the incremental tests before putting this up, lol.

@compiler-errors
Copy link
Member Author

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 30, 2022
@oli-obk
Copy link
Contributor

oli-obk commented Jan 30, 2022

The easy solution here is to remove the HashStable impl entirely and instead add a manual impl for ConstAlloc and ConstValue and other types that have an alloc id and require HashStable. Alternatively create a convenience wrapper type around AllodID with manual partialeq and stablehash impls and use it in those places.

@compiler-errors
Copy link
Member Author

compiler-errors commented Jan 31, 2022

The easy solution here is to remove the HashStable impl entirely and instead add a manual impl for ConstAlloc and ConstValue and other types that have an alloc id and require HashStable.

@oli-obk, I took an initial stab at that suggestion of yours. In order to implement HashStable correctly on those types mentioned above, I had to reimplement Eq (and friends) to agree with the HashStable implementation (that compares the allocation behind the AllocId). However, this isn't a complete solution.. evident by the fact that I'm having trouble building stage1 std due to some const-eval issues:

error[E0080]: it is undefined behavior to use this value                                                                                                                                                                 
   --> /home/michael/.cargo/registry/src/github.com-1ecc6299db9ec823/getopts-0.2.21/src/lib.rs:927:1                                                                                                                     
    |                                                                                                                                                                                                                    
927 | fn is_arg(arg: &str) -> bool {                                                                                                                                                                                     
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.<enum-variant(Some)>.0.<deref>: encountered (potentially part of) a pointer, but expected plain (non-pointer) bytes                                
    |                                                                                                                                                                                                                    
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {                                                                                                                                                          
                ╾──────alloc1253──────╼                         │ ╾──────╼                                                                                                                                               
            }                                                                                                                                                                                                            
                                                                                                                                                                                                                         
For more information about this error, try `rustc --explain E0080`.                                                                                                                                                      

I'm assuming some const eval code depends on that compare-alloc-by-id behavior, but I can't track it down. 🤷

@rust-log-analyzer

This comment has been minimized.

@@ -634,7 +634,8 @@ fn check_const_value_eq<'tcx, R: TypeRelation<'tcx>>(
ConstValue::Scalar(Scalar::Ptr(a_val, _a_size)),
ConstValue::Scalar(Scalar::Ptr(b_val, _b_size)),
) => {
a_val == b_val
// FIXME(compiler-errors): This is highly suspicious
a_val.provenance.0 == b_val.provenance.0
Copy link
Member Author

@compiler-errors compiler-errors Jan 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is to preserve the old "equate AllocId by value" behavior.

edit: actually I don't need this change anymore, I'll revert it when I clean up this PR.

@compiler-errors
Copy link
Member Author

compiler-errors commented Jan 31, 2022

Alright, this definitely has to do with some code relying on relocations in Allocation being compared by id.

--

As I learn more about this code, I think I was silly to think Allocation should have the HashStable/Eq behavior I implemented here. I wonder if I could leave Allocation's Eq and Hash implementations alone (and remove its HashStable impl as well), and instead implement a "correct" HashStable/Eq on GlobalAlloc instead.

@compiler-errors
Copy link
Member Author

Well this is a rough set of working changes. I can clean it up tomorrow...

@oli-obk
Copy link
Contributor

oli-obk commented Jan 31, 2022

Ah yes, sorry. I completely forgot about allocations themselves. Remove their HashStable impl and make it a free/inherent function. Then you can just keep calling it from ConstAlloc's impl

@oli-obk
Copy link
Contributor

oli-obk commented Jan 31, 2022

Oh, my browser didn't refresh. Ignore the previous comment. Reading the impl now

@rust-log-analyzer

This comment has been minimized.

@oli-obk
Copy link
Contributor

oli-obk commented Jan 31, 2022

Looks like most of these manual impls will be gone when we get valtrees... so I am somewhat inclined to roll with the general idea.

I was considering just swapping out the AllocId type (Scalar and Allocation are generic over it) so we could keep all derives but the one on whatever we use instead of AllocId.

@RalfJung
Copy link
Member

I am a bit worried about considering allocations equal when their contents are equal (but their ID is not) -- this might make sense for some allocations, but certainly not for all of them (e.g., static). And moreover, the fact that the type system depends on this equality at all is a bug that we need to fix anyway (by using valtrees). So is it really worth introducing subtle and risky changes that won't fix the actual problem?

@oli-obk
Copy link
Contributor

oli-obk commented Jan 31, 2022

I am a bit worried about considering allocations equal when their contents are equal (but their ID is not)

we're def not going to do that :) I'm more than worried about something like this. Hash/Eq should just be plain derives on Allocation and AllocId, but HashStable should not be implemented for either of them, and the surrounding types must handle that manually.

@compiler-errors
Copy link
Member Author

I was considering just swapping out the AllocId type (Scalar and Allocation are generic over it) so we could keep all derives but the one on whatever we use instead of AllocId.

@oli-obk: yeah, I considered that too, especially because Tag is generic all over the place, but (at least if I understand it correctly) then there's a deep-copy you need to perform when converting between AllocId and "AllocId that hashes/equates according to its contents"..

@oli-obk
Copy link
Contributor

oli-obk commented Feb 1, 2022

Yea, I agree it would kill perf, so let's keep doing what you were doing

let (ptr, offset) = ptr.into_parts();
tcx.get_global_alloc(ptr).hash_stable(hcx, hasher);
offset.hash_stable(hcx, hasher);
size.hash_stable(hcx, hasher);
Copy link
Contributor

@b-naber b-naber Feb 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it really necessary to hash size? This is the pointer size of the target, so identical for all pointers. Why would we need to hash this too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, but I'd rather implement a correct implementation of HashStable than an optimized one first. I'll leave a FIXME and get back to it.

@compiler-errors
Copy link
Member Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 1, 2022
@rust-log-analyzer

This comment has been minimized.

@compiler-errors
Copy link
Member Author

-                ╾─allocN─╼ ╾─allocN─╼                         │ ╾──╼╾──╼
+                ╾─allocN──╼ ╾─allocN─╼                         │ ╾──╼╾──╼

Literally don't know what's going on with these tests. I don't even understand what these diagrams are trying to convey 😵‍💫.

I guess something is hashing one of these types that I fixed in the example and using them for diagnostics?

@oli-obk
Copy link
Contributor

oli-obk commented Feb 2, 2022

😄 these are normalized to hide the actual id, but that doesn't account for IDs with different number of digits.

Also you need to bless tests with --target i686_unknown_linux_gnu or whatever the appropriate 32 bit target is

@compiler-errors
Copy link
Member Author

I'll try to take a stab at fixing these CI failures in a few days.

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 3, 2022
@RalfJung
Copy link
Member

RalfJung commented Feb 4, 2022

we're def not going to do that :)

Good. :) In that case I guess I don't understand what actually is being done here.

Hash/Eq should just be plain derives on Allocation and AllocId, but HashStable should not be implemented for either of them, and the surrounding types must handle that manually.

Should we have Hash/Eq at all on Allocation? Seems a bit odd to be comparing allocations, TBH.

@compiler-errors
Copy link
Member Author

Well looks like CI is happy once I blessed the 32-bit tests, so

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 6, 2022
@oli-obk
Copy link
Contributor

oli-obk commented Feb 6, 2022

Is this PR still necessary with the realization in https://rust-lang.zulipchat.com/#narrow/stream/260443-project-const-generics/topic/valtrees/near/270830218 that we don't need to put alloc IDs into query keys?

@compiler-errors
Copy link
Member Author

we don't need to put alloc IDs into query keys?

my understanding is that this PR mostly addresses hashing the structs that are returned by various queries, not the ones used as keys

@oli-obk
Copy link
Contributor

oli-obk commented Feb 6, 2022

Right, but most of these will become obsolete with valtrees.

The ones that don't, should actually be using alloc IDs by their identity, as otherwise static items may get the deduplication, too, and that is bad. We have existing bugs around this for mutable references in static mut (and probably interior mut ones in plain statics)

@compiler-errors
Copy link
Member Author

I am not opposed to closing this PR in favor of waiting for valtrees to be the proper fix of representing stable const values returned by queries. Lemme know if that's what you mean and I can close this out.

@oli-obk
Copy link
Contributor

oli-obk commented Feb 6, 2022

I do. Closing then, thanks for trying it out!

@oli-obk oli-obk closed this Feb 6, 2022
@compiler-errors compiler-errors deleted the alloc-id-hash branch April 7, 2022 04:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ICE on match of const variables: destructure_const
7 participants