Description
Currently, this code:
#[derive(Debug)]
pub enum ErrorKind {
A,
B,
C,
}
Expands to this:
#[automatically_derived]
impl ::core::fmt::Debug for ErrorKind {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
ErrorKind::A => ::core::fmt::Formatter::write_str(f, "A"),
ErrorKind::B => ::core::fmt::Formatter::write_str(f, "B"),
ErrorKind::C => ::core::fmt::Formatter::write_str(f, "C"),
}
}
}
It should expand to this instead:
#[automatically_derived]
impl ::core::fmt::Debug for ErrorKind {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, match self {
ErrorKind::A => "A",
ErrorKind::B => "B",
ErrorKind::C => "C",
})
}
}
The current version compiles to MIR that looks like this:
bb3: {
_4 = &mut (*_2);
_6 = const "A";
_5 = _6;
_0 = Formatter::<'_>::write_str(move _4, move _5) -> bb5; // bb5 is the return block
}
Hoisting the write_str
out of the match should dramatically reduce the amount of MIR we generate.
@Kixiron suggested that storing all the string literals in an array and indexing into it with the discriminant might be even better, with the extra requirement that the discriminants are consecutive. That sounds more complicated to me in implementation, though it would have the nice extra benefit of generating a function body that is O(1) with respect to the number of variants in the enum.
This is similar to #88793, the change I'm looking for here would let such an optimization apply.
@rustbot label +C-enhancement +A-macros +A-proc-macros