Closed
Description
Given the following code (playground:
use std::borrow::Cow;
fn main() {
let foo = Foo { inner: "foo".into() };
println!("{}", match foo {
FOO => "match",
_ => "no"
});
}
#[derive(PartialEq, Eq)]
struct Foo {
inner: Cow<'static, str>,
}
const FOO: Foo = Foo { inner: Cow::Borrowed("foo") };
The current output is:
error: to use a constant of type `Cow` in a pattern, `Cow` must be annotated with `#[derive(PartialEq, Eq)]`
--> src/main.rs:6:9
|
6 | FOO => "match",
| ^^^
Surprisingly to me at least, using a custom PartialEq
implementation still results in the same issue (playground):
struct Foo {
inner: Cow<'static, str>,
}
impl PartialEq for Foo {
fn eq(&self, other: &Self) -> bool {
self.inner.as_ref() == other.inner.as_ref()
}
}
impl Eq for Foo {}
This seems pretty unclear:
- Why is the compiler telling me I should derive
PartialEq
forCow
when I'm comparing matching againstFoo
? - Why is the compiler telling me to derive
PartialEq
instead of having a custom impl?
I don't know exactly what kind of contract match
depends on, but I would have thought any kind of PartialEq
impl (that is, even non-const) would be enough here.
Original issue here: open-telemetry/opentelemetry-rust#685. This also links to a potential fix in sfackler/rust-postgres@05a0643 (involving adding another layer of indirection), but I'd really like to understand why that is even necessary.
(To be clear: the diagnostic is unclear here, but maybe there's an actual compiler problem here, too?)
cc @estebank
Activity
fee1-dead commentedon Dec 31, 2021
This is because
Cow
is not "StructualEq
" (because it compares the borrowed version only and it is possible forCow::Owned
to be equal to aCow::Borrowed
) so constants of that type cannot be used in matches. I do believe the diagnostic should be improved.cc @rust-lang/wg-const-eval
djc commentedon Dec 31, 2021
@fee1-dead that's helpful, my intuition was that it had something to do with const stuff.
Still, it seems this story is still really hard to explain:
StructuralEq
?StructuralEq
if you deriveEq
?Eq
and keep my customPartialEq
, that's not sufficient eitherThis all seems really weird because apparently
StructuralEq
is not just a trait implemented by a type but also something that must be present for all of its inner types... or something?RalfJung commentedon Jan 1, 2022
StructuralEq is kind of a mess currently and something we want to clean up. Also see #74446.
djc commentedon Jan 1, 2022
Okay, but then we should definitely improve diagnostics such that the messiness from an unstable filter leak out into stable Rust via crappy errors (especially as there seems to be no clear/fast path towards stabilization).
raphaelcohn commentedon Apr 20, 2022
Just took an hour googling to end up here with the same error message. Anything that at least adds a bit more information (eg 'can not be structurally equal' or includes a compiler error number) would be much appreciated.
RalfJung commentedon Nov 15, 2023
The error explicitly says
#[derive(PartialEq, Eq)]
. So it doesn't explain why, but it does explain that your assumption here is wrong.See rust-lang/lang-team#220 for some recent discussion of the subject. The current plan is to keep this a hard error.
estebank commentedon Jan 11, 2025
Current output:
Auto merge of rust-lang#135360 - RalfJung:structural-partial-eq, r=co…
Auto merge of rust-lang#135360 - RalfJung:structural-partial-eq, r=co…