Deconstructing `Option` in const context

⚓ Rust    📅 2026-01-08    👤 surdeus    👁️ 4      

surdeus

This doesn't compile:

const fn f<T>(slot: &mut MaybeUninit<T>, value: Option<T>) {
    if let Some(value) = value {
        // use value somehow
        slot.write(value);
    }
}
error[E0493]: destructor of `Option<T>` cannot be evaluated at compile-time
  --> src/lib.rs:38:42
   |
38 | const fn f<T>(slot: &mut MaybeUninit<T>, value: Option<T>) {
   |                                          ^^^^^ the destructor for this type cannot be evaluated in constant functions

We can unsafely duplicate T if the value is Some<T>, and forget the Option<T> to make the compiler happy:

const fn f<T>(slot: &mut MaybeUninit<T>, value: Option<T>) {
    if let Some(value) = value.as_ref() {
        let value = unsafe { std::ptr::read(value) };
        // use value somehow
        slot.write(value);
    }
    std::mem::forget(value);
}

However, depending on what you do with the value a panic could cause a double free. So I thought let's forget the value first:

const fn option_manually_drop<T>(value: Option<T>) -> Option<std::mem::ManuallyDrop<T>> {
    let out = match value.as_ref() {
        Some(v) => Some(std::mem::ManuallyDrop::new(unsafe { std::ptr::read(v) })),
        None => None,
    };
    std::mem::forget(value);
    out
}

const fn f<T>(slot: &mut MaybeUninit<T>, value: Option<T>) {
    if let Some(value) = option_manually_drop(value) {
        let value = std::mem::ManuallyDrop::into_inner(value);
        // use value somehow
        slot.write(value);
    }
}

Am I overcomplicating this? Is there a better solution/implementation?

2 posts - 1 participant

Read full topic

🏷️ Rust_feed