Using Vec::contains currently only works if the contains parameter is of the same &Type as the Vector elements. This means the parameter must be converted to the vec-item-type even though it is comparable with the type in the first place.
e.g. following code does not work, even though impl<'a, 'b> PartialEq<str> for String
exists:
fn main() {
let mut v: Vec<String> = Vec::new();
v.contains("mystring");
}
The Error:
error[E0308]: mismatched types
--> <anon>:3:16
|
3 | v.contains("mystring");
| ^^^^^^^^^^ expected struct `std::string::String`, found str
|
= note: expected type `&std::string::String`
found type `&'static str`
I'd be better if Vec::contains had definition like:
fn contains<U>(&self, value: &U) where T: PartialEq<U>, U: ?Sized
You could use v.iter().any(|x| x == "mystring")
as a workaround, you don't need to convert the &str
to String
.
I'm aware of this workaround, but isn't that what "contains" should be in the first place?
There was an attempt to fix this in #43020 but it has caused some major inference failure.
Is the alternative mentioned in https://github.com/rust-lang/rust/pull/43020#issuecomment-314650930 any better with respect to the inference failure?
Tagging C-feature-accepted to follow up on the approach in https://github.com/rust-lang/rust/pull/43020#issuecomment-314650930. Please submit a PR with an implementation and tests. We will need to confirm that this causes less breakage than the original Borrow
-based approach.
This was attempted using the other approach in https://github.com/rust-lang/rust/pull/46934. Unfortunately, it too causes too much breakage in downstream crates. Even though this API change would be significantly nicer, it doesn't seem plausible unless this breakage is acceptable (maybe for a later epoch).
Note that the problems mentioned here are the same as those in https://github.com/rust-lang/rust/issues/20063.
Shouldn't this issue and a workaround be mentioned in Vec::contains
documentation?
Relabeling as a documentation issue. contains
is probably not fixable as it stands today but documenting the workaround would be good.
I'm not sure when it was added, but the docs do mention the workaround. Perhaps this issue should be closed?
How about adding a new method alongside contains
?
Something like fn contains_ref<U>(&self, x: &U) -> bool where T: PartialEq<U>
I am willing to do the work about contains_ref
but would it be accepted ? Creating it means ensuring it works forever, but if someone from the relevant team can confirm it is ok for contains_ref
to be added, I will tackle it.
Can someone review this?
Most helpful comment
I'm aware of this workaround, but isn't that what "contains" should be in the first place?