Skip to content

Commit

Permalink
Rollup merge of #135064 - RalfJung:const-in-pat-partial-eq-not-const,…
Browse files Browse the repository at this point in the history
… r=compiler-errors

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

Fixes #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`
  • Loading branch information
matthiaskrgr authored Jan 4, 2025
2 parents b0b54f2 + b806dcc commit 966a5be
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 0 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
54 changes: 54 additions & 0 deletions tests/ui/traits/const-traits/pattern-custom-partial-eq.rs
Original file line number Diff line number Diff line change
@@ -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() {}

0 comments on commit 966a5be

Please sign in to comment.