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

feat!: Allow CustomConsts to (optionally) be hashable #1397

Merged
merged 13 commits into from
Sep 11, 2024
Merged

Conversation

acl-cqc
Copy link
Contributor

@acl-cqc acl-cqc commented Aug 6, 2024

  • Add trait TryHash as prereq for CustomConst
  • Automatically impl'd if your const impl's Hash
  • Can also trivially implement (i.e. impl TryHash for Foo { }) to say "no, not hashable"
  • Derive Hash for most consts, but not ConstF64

BREAKING CHANGE: any impl CustomConst will need to either impl Hash or impl MaybeHash

@acl-cqc acl-cqc changed the title feat!: Add trait MaybeHash as prereq for CustomConst; impl Hash for most feat!: Allow hashing of appropriate CustomConsts Aug 6, 2024
Copy link

codecov bot commented Aug 6, 2024

Codecov Report

Attention: Patch coverage is 82.75862% with 10 lines in your changes missing coverage. Please review.

Project coverage is 87.28%. Comparing base (6bf6c82) to head (af7a75d).

Files with missing lines Patch % Lines
hugr-core/src/std_extensions/collections.rs 0.00% 5 Missing ⚠️
hugr-core/src/extension/prelude.rs 25.00% 1 Missing and 2 partials ⚠️
hugr-core/src/ops/constant.rs 94.44% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1397   +/-   ##
=======================================
  Coverage   87.28%   87.28%           
=======================================
  Files         128      128           
  Lines       21721    21774   +53     
  Branches    18721    18774   +53     
=======================================
+ Hits        18959    19006   +47     
- Misses       1990     1996    +6     
  Partials      772      772           
Flag Coverage Δ
python 92.46% <ø> (ø)
rust 86.46% <82.75%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@acl-cqc acl-cqc changed the title feat!: Allow hashing of appropriate CustomConsts feat!: Allow CustomConsts to be hashable (optionally) Aug 6, 2024
@acl-cqc acl-cqc changed the title feat!: Allow CustomConsts to be hashable (optionally) feat!: Allow CustomConsts to (optionally) be hashable Aug 6, 2024
@acl-cqc acl-cqc changed the title feat!: Allow CustomConsts to (optionally) be hashable feat!: [NonUrgent/RFC] Allow CustomConsts to (optionally) be hashable Aug 6, 2024
@acl-cqc acl-cqc requested a review from aborgna-q August 6, 2024 17:23
@acl-cqc acl-cqc marked this pull request as ready for review August 6, 2024 17:23
@acl-cqc acl-cqc requested a review from a team as a code owner August 6, 2024 17:23
@acl-cqc
Copy link
Contributor Author

acl-cqc commented Aug 6, 2024

This is not really needed yet but seems like a very good thing to have for dataflow analysis and not a bad idea anyway: most constants are hashable!

The approach taken with MaybeHash contrasts with equal_consts which requires every custom-const struct that impls PartialEq to also override equal_consts using the downcast_equal_consts helper, avoided here. (Instead, those that don't implement Hash have to empty-implement MaybeHash, so it's not a free lunch, but that effort is pretty minimal and applies only in the minority of cases, whereas downcast_equal_consts has to be used in the majority of cases...

Hence, picking @aborgna-q out here as he may know of better/rustier ways here. Can we Downcast to see if a thing impl's Hash ??

Comment on lines 104 to 105
/// Note: this uses `dyn` rather than being parametrized by `<H: Hasher>` so that we can
/// still use `dyn CustomConst`.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I.e. wee need the trait to be object safe

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Comment updated.

@aborgna-q
Copy link
Collaborator

There is no reflection in Rust, so there's no way to branch on whether a type implements a trait or not (not with stable code at least).

This looks like a good alternative. We can discuss whether to define a new trait vs adding another trait method to CustomConst (more verbose vs less clear), but they are the same solution.

I may suggest renaming it to TryHash instead, to follow the existing name convention (e.g. TryFrom).

Copy link
Collaborator

@aborgna-q aborgna-q left a comment

Choose a reason for hiding this comment

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

Drop all those allocations!

hugr-core/src/ops/constant.rs Outdated Show resolved Hide resolved
Comment on lines 112 to 113
fn maybe_hash(&self, st: &mut dyn Hasher) -> bool {
Hash::hash(self, &mut Box::new(st));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
fn maybe_hash(&self, st: &mut dyn Hasher) -> bool {
Hash::hash(self, &mut Box::new(st));
fn maybe_hash(&self, mut st: &mut dyn Hasher) -> bool {
Hash::hash(self, &mut st);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That gives me:

error[E0277]: the size for values of type `dyn Hasher` cannot be known at compilation time
   --> hugr-core/src/ops/constant/custom.rs:113:26
    |
113 |         Hash::hash(self, &mut *st);
    |         ----------       ^^^^^^^^ doesn't have a size known at compile-time
    |         |
    |         required by a bound introduced by this call
    |
    = help: the trait `Sized` is not implemented for `dyn Hasher`

which I admit is odd - I'm not trying to pass a Hasher, only a &mut to it. Am I missing something?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah sorry I'd put in an extra *

Copy link
Collaborator

@aborgna-q aborgna-q Aug 7, 2024

Choose a reason for hiding this comment

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

*st is trying to dereference an unsized value into the stack.
The suggestion avoids that by using T : Hasher $\implies$ &mut T : Hasher

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This does look to me as if I'm passing a mutable reference to a mutable reference!

hugr-core/src/ops/constant/custom.rs Outdated Show resolved Hide resolved
hugr-core/src/std_extensions/collections.rs Outdated Show resolved Hide resolved
@CQCL CQCL deleted a comment from hugrbot Aug 7, 2024
@acl-cqc
Copy link
Contributor Author

acl-cqc commented Aug 7, 2024

There is no reflection in Rust, so there's no way to branch on whether a type implements a trait or not (not with stable code at least).

This looks like a good alternative. We can discuss whether to define a new trait vs adding another trait method to CustomConst (more verbose vs less clear), but they are the same solution.

I may suggest renaming it to TryHash instead, to follow the existing name convention (e.g. TryFrom).

I like TryHash, and indeed try_hash.

Also I admit I'm not really clear why we don't require PartialEq as a prereq for CustomConst. You can always implement with return false, which is what CustomConst will give you by default if you don't...

@acl-cqc acl-cqc changed the title feat!: [NonUrgent/RFC] Allow CustomConsts to (optionally) be hashable feat!: Allow CustomConsts to (optionally) be hashable Sep 2, 2024
Copy link
Collaborator

@aborgna-q aborgna-q left a comment

Choose a reason for hiding this comment

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

Patch coverage is 4.76190%

🫠

@acl-cqc
Copy link
Contributor Author

acl-cqc commented Sep 9, 2024

Patch coverage is 4.76190%

🫠

Sorry, I really did think there was already some code hashing lists. Maybe I got confused with stuff in a previous iteration of "const_fold2" 😅 ...anyway, I've added enough to make it green, could dup much of that into collections too I suppose to get a final few percent.

@acl-cqc acl-cqc added this pull request to the merge queue Sep 11, 2024
Merged via the queue into main with commit 07b2f58 Sep 11, 2024
21 checks passed
@acl-cqc acl-cqc deleted the acl/hash_consts branch September 11, 2024 14:03
@hugrbot hugrbot mentioned this pull request Sep 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants