There's a bit of nuance here. The padding can sometimes result in slightly larger types, because it forces grouping some things together.
struct Inner {
x: u8,
y: u64,
}
struct Outer {
inner1: Inner,
inner2: Inner,
}
struct Inlined {
x1: u8,
y1: u64,
x2: u8,
y2: u64,
}
Inlined
is 24 bytes. Outer
is 32 bytes.
Depends on what you're asking about.
w.r.t. layout optimizations: Yes. I'm fairly certain that rust performs identical layout optimizations to all types in both Debug and Release. I.e. unless there's some #[cfg(debug_assertions)]
fields on a type, one should expect that the size and alignment of a type are always identical between debug and release.
w.r.t. heap allocation: Yes. rust will never, ever, ever in a million years implicitly allocate something from the heap (unless perhaps it is compiling to some unusual target that doesn't have anything that resembles the stack?). Even in debug mode. This would go against its fundamental design goals, and compromise its ability to be used for purposes like writing an operating system.
w.r.t. temporaries on the stack: No. Unlike C++, Rust has no guaranteed copy-elision anywhere in the language. On the one hand, Rust doesn't really need it that badly, because all copies in the language are shallow memcpys (unlike in C++ where they may turn into arbitrary function calls that deeply clone arbitrary resources). The downside is that the unoptimized code emitted by rust does contain a lot of unnecessary temporaries and memcpys, and thus the optimizer has a significantly greater impact.
Thus, something like
let foo = Foo {
bar: Bar { x: 1, y: 1 },
z: 2,
};
may create dedicated stack space for the temporary Bar
before copying it into the Foo
. In theory, it might even create dedicated stack space for the integer constants before copying them into the Bar
. There are no guarantees here.