I'm relatively sure that this compiles to an equivalent of (1, 5) where these names are typenames and not functions of any kind. The thing is, that things like these get "compressed" from what is seen in code. What else would there be to store, other than (1, 5)? Rust has no runtime type info built into data structures' representations in memory, so realistically Foo(x, y)is just(x, y).
Note that adding a #[repr(transparent)] ensures that types collapse into each other like that, without dummy padding or anything, while usually useful for ffi or transmuting.
The first four bytes are those of the i32, in little-endian representation (in practice it would be native endianness; it just so happens that the Playground's platform is natively little endian);
The following byte is the u8;
And the last three bytes are padding bytes (whose contents are always undefined, IIRC).
I am unsure whether those padding bytes will always be there, since I suspect they exist so that the size of a NewType(i32, u8), remains a multiple of the alignment, given that types cannot currently have a stride greater than their size.
(In a slice, for all but the first element to be properly aligned, each "previous element", (i.e., every element except the last one) may have extra padding).
The layout isn't guaranteed across compilations. If your accessing a nested field directly there is no additional overhead. (Compiler could even optimise further; instead of having to use an offset calculation, have a more direct result; down to aliasing knowledge.)