Skip to content

Commit b806dcc

Browse files
committed
const-in-pattern: test that the PartialEq impl does not need to be const
1 parent c528b8c commit b806dcc

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

+4
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,10 @@ fn type_has_partial_eq_impl<'tcx>(
491491
// `PartialEq` for some lifetime but *not* for `'static`? If this ever becomes a problem
492492
// we'll need to leave some sort of trace of this requirement in the MIR so that borrowck
493493
// can ensure that the type really implements `PartialEq`.
494+
// We also do *not* require `const PartialEq`, not even in `const fn`. This violates the model
495+
// that patterns can only do things that the code could also do without patterns, but it is
496+
// needed for backwards compatibility. The actual pattern matching compares primitive values,
497+
// `PartialEq::eq` never gets invoked, so there's no risk of us running non-const code.
494498
(
495499
infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation),
496500
automatically_derived,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//! Ensure that a `const fn` can match on constants of a type that is `PartialEq`
2+
//! but not `const PartialEq`. This is accepted for backwards compatibility reasons.
3+
//@ check-pass
4+
#![feature(const_trait_impl)]
5+
6+
#[derive(Eq, PartialEq)]
7+
pub struct Y(u8);
8+
pub const GREEN: Y = Y(4);
9+
pub const fn is_green(x: Y) -> bool {
10+
match x { GREEN => true, _ => false }
11+
}
12+
13+
struct CustomEq;
14+
15+
impl Eq for CustomEq {}
16+
impl PartialEq for CustomEq {
17+
fn eq(&self, _: &Self) -> bool {
18+
false
19+
}
20+
}
21+
22+
#[derive(PartialEq, Eq)]
23+
#[allow(unused)]
24+
enum Foo {
25+
Bar,
26+
Baz,
27+
Qux(CustomEq),
28+
}
29+
30+
const BAR_BAZ: Foo = if 42 == 42 {
31+
Foo::Bar
32+
} else {
33+
Foo::Qux(CustomEq) // dead arm
34+
};
35+
36+
const EMPTY: &[CustomEq] = &[];
37+
38+
const fn test() {
39+
// BAR_BAZ itself is fine but the enum has other variants
40+
// that are non-structural. Still, this should be accepted.
41+
match Foo::Qux(CustomEq) {
42+
BAR_BAZ => panic!(),
43+
_ => {}
44+
}
45+
46+
// Similarly, an empty slice of a type that is non-structural
47+
// is accepted.
48+
match &[CustomEq] as &[CustomEq] {
49+
EMPTY => panic!(),
50+
_ => {},
51+
}
52+
}
53+
54+
fn main() {}

0 commit comments

Comments
 (0)