I tried to match on a generic Result<&mut T, T>
inside of a const fn
, but the compiler did not let me. It would require being able to drop the value at the end of the scope, which is
currently not possible inside of a const fn
.
I truncated my code a bit and finally landed on this snipped. It still gives the same error, with the same reason, but is no longer generic.
struct Dummy;
impl Drop for Dummy {
fn drop(&mut self) {
println!("dropped");
}
}
const fn const_match(result: Result<Dummy, ()>) -> Result<Dummy, ()> {
match result { //^^^^^^ the destructor for this type cannot be evaluated in constant functions
Ok(ok) => Ok(ok),
Err(err) => Err(err),
}
} // <- value is dropped here
The compiler gives me the following error message:
error[E0493]: destructor of `Result<Dummy, ()>` cannot be evaluated at compile-time
--> <source>:9:22
|
9 | const fn const_match(result: Result<Dummy, ()>) -> Result<Dummy, ()> {
| ^^^^^^ the destructor for this type cannot be evaluated in constant functions
...
14 | }
| - value is dropped here
By removing the const
everything compiles flawlessly, so I created a test to check if the value really ever gets dropped inside of this function.
struct Dummy;
impl Drop for Dummy {
fn drop(&mut self) {
println!("dropped");
}
}
fn const_match(result: Result<Dummy, ()>) -> Result<Dummy, ()> {
match result {
Ok(ok) => Ok(ok),
Err(err) => Err(err),
}
}
fn main() {
let dummy = const_match(Ok(Dummy));
let err = const_match(Err(()));
std::mem::forget(dummy);
}
Here's the godbolt link to an identical code sample.
As expected it produces no output, so the destructor never gets run inside of const_match
.
Why does the destructor need to be able to run?
It seems const
evaluation still has growing pains. There is a tracking issue for more precise drop analysis in const
contexts; if you compile this code on +nightly with:
#![feature(const_precise_live_drops)]
then it passes (playground).
The feature appears functional for simple cases but from the issue comments it may not have been stabilized yet in favor of a more complete solution. Since the core of the problem seems to be around destructuring patterns, I'm not sure there's a workaround on +stable.