Print type sizes

What's the story with the unstable print-type-sizes rustc option? It was recently extremely useful for me in diagnosing and shrinking the size of a giant future. But it doesn't even merit a section in the unstable book. Is it ever going to be stabilized?

4 Likes

No. It's an internal flag.

Some compiler devs want it to be able to be stable, but it would need a champion. Maybe ask on Zulip or make an ACP to inquire about getting a tracking issue started.

There is a tracking issue for a related rustdoc feature.

1 Like

Thanks for the links. This almost comes up in the discussion but annotations seem less usable; how do they interact with generics, types defined by async blocks and functions, etc.? (Though the compiler flag only gives you information about the types you actually instantiate, which may have other problems.) A giant report on the other hand is very valuable (if you save it to a file).

If you have explicit size constraint requirements, you can rely on the following to assert that a type hasn't changed size:

const _: [(); $size] = [(); core::mem::size_of::<$ty>()];

or

const { if core::mem::size_of::<$ty>() != $size { panic!("") } }

As a vaguely related offtopic, I have recently learnt about the unstable #[rustc_layout] attribute. It causes the compiler to print the full type layout as a compiler error message. It can also be applied to type aliases, including those of opaque types.

I wish there were a more stable and principled way to query type layout, but this is good enough for occasional investigations.

How does this work with unnameable types? I specifically needed help with an async function and the future it returned. The print-type-sizes flag is really great at this; you really need the full report (at least I did).

You can put the #[rustc_layout] on a TAIT: Rust Playground

1 Like

You can forge a dbgsize!() macro like this:

macro_rules! dbgsize {
    ($val:expr) => {
        // copied from std::dbg!
        // `match` here is intentional because it affects the lifetimes of temporaries
        match $val {
            tmp => {
                let file = file!();
                let line = line!();
                let column = column!();
                let val = stringify!($val);
                let size = core::mem::size_of_val(&tmp);
                eprintln!("[{file}:{line}:{column}] size_of_val({val}) = {size}");
                tmp
            }
        }
    };
}

Usage:

async fn hello_rust() {
    println!("Hello, Rust!");
}

#[tokio::main]
async fn main() {
    dbgsize!(hello_rust()).await;
}