This isn't actually quite correct, as this is still a compile error:
const fn f(lhs: &'static [u8], rhs: &'static [u8]) -> bool { lhs == rhs }
error[E0277]: can't compare `[u8]` with `_` in const contexts
--> src/lib.rs:1:66
|
1 | const fn f(lhs: &'static [u8], rhs: &'static [u8]) -> bool { lhs == rhs }
| ^^ no implementation for `[u8] == _`
|
= help: the trait `~const PartialEq<_>` is not implemented for `[u8]`
note: the trait `PartialEq<_>` is implemented for `[u8]`, but that implementation is not `const`
--> src/lib.rs:1:66
|
1 | const fn f(lhs: &'static [u8], rhs: &'static [u8]) -> bool { lhs == rhs }
| ^^
= note: required for `&[u8]` to implement `~const PartialEq<&_>`
(The error is clearer now than it used to be, although it's not ideal that it's referring to unstable ~const syntax rather than just saying the trait implementation cannot be used in const contexts.)
It is interesting that it works in a match, though:
const X: &[u8] = b"";
const fn f(s: &'static [u8]) -> bool {
match s {
X => true,
_ => false,
}
}
AIUI the reason this occurs is because matching on &str goes through the derive(PartialEq) implementation, whereas matching on &[_] actually becomes a slice pattern instead, and the primitive matching on both slices and u8 can be used on const contexts as they don't go through PartialEq/StructuralEq.
You can see this in effect on the playground by choosing to show MIR:
pub fn str(s: &'static str) -> bool {
match s {
"" => true,
_ => false,
}
}
pub fn u8s(s: &'static [u8]) -> bool {
match s {
b"" => true,
_ => false,
}
}
// WARNING: This output format is intended for human consumers only
// and is subject to change without notice. Knock yourself out.
// Editorialized by @CAD97
fn str(_s: &str) -> bool {
let _return: bool;
let _eq: bool; // tmp
bb0: {
_eq = <str as PartialEq>::eq(_s, const "") -> bb1;
}
bb1: {
switchInt(move _eq) -> [false: bb2, otherwise: bb3];
}
bb2: {
_return = const false;
goto -> bb4;
}
bb3: {
_return = const true;
goto -> bb4;
}
bb4: {
return;
}
}
fn u8s(_s: &[u8]) -> bool {
let _return: bool;
let _len_s: usize;
let _len_pat: usize;
let _4: bool;
bb0: {
_len_s = Len((*_s));
_len_pat = const 0_usize;
_eq = Eq(move _len_s, move _len_pat);
switchInt(move _4) -> [false: bb1, otherwise: bb2];
}
bb1: {
_return = const false;
goto -> bb3;
}
bb2: {
_return = const true;
goto -> bb3;
}
bb3: {
return;
}
}