Sure, we can get bigger closures with edition 2021… but this “regression” still had me confused for a while when trying to reproduce this fun trick involving uninhabited closure types

I’m just stumbling upon the fact that apparently the following approach/code is “broken” by the smart Rust 2021 closures… i.e. the closure is no longer uninhabited, and thus the Option<…closure type…> no longer zero-sized. (The discovery process wasn’t all that trivial, I adapted this code for a reply, and it didn’t work out as expected w.r.t. the sizes; then took a while to nail the relevant difference down to being the choice of edition.)

Looks like

#[inline]
pub fn nop() -> Option<impl Fn(&mut sidoc::Builder)> {
    enum Void {}
    None::<Void>.map(|void| {
        move |_: &mut sidoc::Builder| {
            let _ = &void;
            match void {}
        }
    })
}

works to avoid / work around the problem; nonetheless… that’s kind-of a bad regression, isn’t it?

On the other hand, closures becoming larger with the new capturing logic is nothing unheard of. Even simple cases like

fn main() {
    let x = (1, 2);
    let closure = || {
        (x.0, x.1);
    };
    dbg!(std::mem::size_of_val(&closure)); // 2018: 8 bytes, 2021: 16 bytes
}

can become worse.

Some thoughts you can reply to if you want to :slightly_smiling_face::
I initially wondered whether the uninhabited case should be considered a bug, but I probably wouldn’t go so far anymore. I still think people might be interested in this, so I’m posting it. So… if you have more ideas of concrete cases where closure capturing rules, be it the new ones compared to the old ones, or maybe even both the new and the old ones compared to some alternative (for the concrete example), produce disappointing results, in particular w.r.t. the size of the closure, feel free to share them.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.