1
Fork 0

Rollup merge of #135064 - RalfJung:const-in-pat-partial-eq-not-const, r=compiler-errors

const-in-pattern: test that the PartialEq impl does not need to be const

Fixes https://github.com/rust-lang/rust/issues/119398 by adding a test.

`@compiler-errors`  is there some place in the code where we could add a comment saying "as a backcompat hack, here we only require `PartialEq` and not `const PartialEq`"?

r? `@compiler-errors`
This commit is contained in:
Matthias Krüger 2025-01-04 09:54:38 +01:00 committed by GitHub
commit 966a5be559
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 58 additions and 0 deletions

View file

@ -491,6 +491,10 @@ fn type_has_partial_eq_impl<'tcx>(
// `PartialEq` for some lifetime but *not* for `'static`? If this ever becomes a problem
// we'll need to leave some sort of trace of this requirement in the MIR so that borrowck
// can ensure that the type really implements `PartialEq`.
// We also do *not* require `const PartialEq`, not even in `const fn`. This violates the model
// that patterns can only do things that the code could also do without patterns, but it is
// needed for backwards compatibility. The actual pattern matching compares primitive values,
// `PartialEq::eq` never gets invoked, so there's no risk of us running non-const code.
(
infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation),
automatically_derived,

View file

@ -0,0 +1,54 @@
//! Ensure that a `const fn` can match on constants of a type that is `PartialEq`
//! but not `const PartialEq`. This is accepted for backwards compatibility reasons.
//@ check-pass
#![feature(const_trait_impl)]
#[derive(Eq, PartialEq)]
pub struct Y(u8);
pub const GREEN: Y = Y(4);
pub const fn is_green(x: Y) -> bool {
match x { GREEN => true, _ => false }
}
struct CustomEq;
impl Eq for CustomEq {}
impl PartialEq for CustomEq {
fn eq(&self, _: &Self) -> bool {
false
}
}
#[derive(PartialEq, Eq)]
#[allow(unused)]
enum Foo {
Bar,
Baz,
Qux(CustomEq),
}
const BAR_BAZ: Foo = if 42 == 42 {
Foo::Bar
} else {
Foo::Qux(CustomEq) // dead arm
};
const EMPTY: &[CustomEq] = &[];
const fn test() {
// BAR_BAZ itself is fine but the enum has other variants
// that are non-structural. Still, this should be accepted.
match Foo::Qux(CustomEq) {
BAR_BAZ => panic!(),
_ => {}
}
// Similarly, an empty slice of a type that is non-structural
// is accepted.
match &[CustomEq] as &[CustomEq] {
EMPTY => panic!(),
_ => {},
}
}
fn main() {}