-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Verify Borrow<T> semantics for types that implement Hash, Borrow<str> and Borrow<[u8]>. #11781
Conversation
r? @xFrednet (rustbot has picked a reviewer for you, use r? to override) |
Okay, so as far as I understand, this needs to be a latelint. We could do this on the early pass and check for impl of all three, but that could cause issues if there are name conflicts. e.g. Two Structs with the same name in different modules, both impl Hash and Borrow, except one is Borrow and the other is Borrow<[u8]>. So instead we do a latelint, and check that for the type we don't have both impls. |
Welcome to Clippy and thank you for the PR. I didn't have time to look at this until now, but it seems like you found some excellent help on Zulip, which is awesome. @y21 would you like to take over the review, since you already helped on Zulip? Once you're done, I can do the final review and r+ for us two :) |
I see this is still in draft mode. I can give some feedback now, or do you want me to wait until this is marked ready? |
This usually depends on the author of the PR. Some use draft mode, when they are still working on the PR and some use it, to request feedback. @partiallytyped posted some questions here, which makes me guess that they wanted to get feedback on their questions. However, they have also asked them on Zulip where you have been helpful. In this case, I would monitor the PR or ask the author if they would already like to have a review: :) |
I think we can go ahead with the review while I do some finishing touch ups on the notes :D @y21 has been very very helpful over on Zulip! |
I think this issue pretty much opens a whole branch of checks. This one is specific to |
There are merge commits (commits with multiple parents) in your changes. We have a no merge policy so these commits will need to be removed for this pull request to be merged. You can start a rebase with the following commands:
The following commits are merge commits: |
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.
Some initial feedback :)
(Sorry for the chaotic order, had to jump around a bit in the code)
@rustbot ready Hmmm seems like the bot doesn't work if S-waiting-on-review is already there. |
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.
Last few things from my side and then I think it looks good to me!
Does this also work when the |
It does! :D |
Looks like there are still merge commits somehow, according to rustbot. I think you can just rebase onto master to fix that. |
There are merge commits (commits with multiple parents) in your changes. We have a no merge policy so these commits will need to be removed for this pull request to be merged. You can start a rebase with the following commands:
The following commits are merge commits (since this message was last posted): |
This should do it. Thanks @y21! For all the help :D |
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.
Thought about it for a bit and I left some last comments. Most of them are just nits or non-blocking questions/possible improvements though 🙃
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.
Just some minor documentation nits. Thanks for your patience here.
I'm going to tag @xFrednet since these are probably my last comments.
Aside from the small things in the documentation, this looks great!
It's a very nice lint to have.
Don't worry about it :D it shows how much you care for this which makes me more excited to help :D |
The start of my week is quite full, it might take until Thursday or the weekend until I have time to give you a full review. Hope that's okay with you :) Already, a big thanks for the review @y21! I highly appreciate it |
☔ The latest upstream changes (presumably #11791) made this pull request unmergeable. Please resolve the merge conflicts. |
There are merge commits (commits with multiple parents) in your changes. We have a no merge policy so these commits will need to be removed for this pull request to be merged. You can start a rebase with the following commands:
The following commits are merge commits (since this message was last posted): |
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.
The lint logic looks good to me. I have some remarks regarding the cosmetics of the lint. Afterward, it should be good to go.
Thank you for waiting on my reivew :)
Implements a lint to prevent implementation of Hash, Borrow<str> and Borrow<[u8]> as it breaks Borrow<T> "semantics". According to the book, types that implement Borrow<A> and Borrow<B> must ensure equality of borrow results under Eq,Ord and Hash. > In particular Eq, Ord and Hash must be equivalent for borrowed and owned values: x.borrow() == y.borrow() should give the same result as x == y. In the same way, hash(x) == hash(x as Borrow<[u8]>) != hash(x as Borrow<str>). changelog: newlint [`impl_hash_with_borrow_str_and_bytes`]
LGTM, thank you for the update! @bors r+ |
Verify Borrow<T> semantics for types that implement Hash, Borrow<str> and Borrow<[u8]>. Fixes #11710 The essence of the issue is that types that implement Borrow<T> provide a facet or a representation of the underlying type. Under these semantics `hash(a) == hash(a.borrow())`. This is a problem when a type implements `Borrow<str>`, `Borrow<[u8]>` and Hash, it is expected that the hash of all three types is identical. The problem is that the hash of [u8] is not the same as that of a String, even when the byte reference ([u8]) is derived from `.as_bytes()` - [x] Followed [lint naming conventions][lint_naming] - [x] Added passing UI tests (including committed `.stderr` file) - [x] `cargo test` passes locally - [x] Executed `cargo dev update_lints` - [x] Added lint documentation - [x] Run `cargo dev fmt` --- - [x] Explanation of the issue in the code - [x] Tests reproducing the issue - [x] Lint rule and emission
💔 Test failed - checks-action_test |
@bors retry |
☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test |
Fixes #11710
The essence of the issue is that types that implement Borrow provide a facet or a representation of the underlying type. Under these semantics
hash(a) == hash(a.borrow())
.This is a problem when a type implements
Borrow<str>
,Borrow<[u8]>
and Hash, it is expected that the hash of all three types is identical. The problem is that the hash of [u8] is not the same as that of a String, even when the byte reference ([u8]) is derived from.as_bytes()
.stderr
file)cargo test
passes locallycargo dev update_lints
cargo dev fmt
changelog: New lint: [
impl_hash_borrow_with_str_and_bytes
]#11781