Open
Description
This is originated from ~const Drop
, but is applicable to non-const functions as well. The problem is best seen as the MIR output for two implementations of Result::ok
with a minor change: (play)
pub fn wildcard<T, E>(res: Result<T, E>) -> Option<T> {
match res {
Ok(x) => Some(x),
Err(_) => None,
}
}
pub fn bind_to_variable<T, E>(res: Result<T, E>) -> Option<T> {
match res {
Ok(x) => Some(x),
Err(_x) => None,
}
}
I won't post the whole MIR output here, but let me illustrate this issue with a handwritten control flow graph:
wildcard
|
switch on discriminant for `res` ------------ `Ok(x)`
| |
`Err` Move `x` into return value as `Some(x)`
| |
Set return value as `None` /
|---------------------------------
|
switch on discriminant for `res` ------------ `Ok`
| |
`Err` |
| |
`drop(res: Result<T, E>)` /
|---------------------------------
|
return
bind_to_variable
|
switch on discriminant for `res` ------------- `Ok(x)`
| |
`Err` Move `x` into return value as `Some(x)`
| |
Move value in `Err` to `_x` |
| |
`drop(_x: E)` |
| |
Set return value as `None` /
|----------------------------------
|
return
wildcard
is unexpectedly more complex and performs switchInt
on x
for two times instead of one. I think ideally we should always generate MIR as the second graph.
See #92433 (comment) and Zulip