Understand the behavior of empty structs
Empty structs currently compile but don't always behave well at runtime. For example, the script below panics with a MemoryOverflow
script;
use std::vec::Vec;
struct S {
}
fn main() {
let mut v = ~Vec::new();
v.push(S { });
}
On the other hand, the script below does not panic and the return receipt contains [{"ReturnData":{"data":""... (Note the empty data here because retd actually returns data of length 0).
script;
struct S {
}
fn main() -> S {
S { }
}
This behaviour is currently inconsistent with empty tuples (which work fine in both cases above) because empty tuples are unit types in IR/codegen and actually have a non-zero size (1 word), unlike empty structs above. That being said, we do rely on the fact that empty structs don't require any storage slots because we need StorageMap and StorageVec not to require extra reads/writes for every method called (like insert, get, push, etc.).
There is also a somewhat related issue about enums: https://github.com/FuelLabs/sway/issues/1697.
Just creating this issue to start a discussion on the desired behaviour. I haven't looked at what Rust does yet but we should probably start there.
So we definitely need empty structs (which we probably should be able to declare struct S; like Rust) and we definitely need them to be zero sized for storage's sake. Is there any further discussion? The MemoryOverflow example at the top just needs to be fixed.
Yeah we're probably okay! I just wanted to make sure that we're not missing anything... like what happens if we pass empty structs as function or ABI method arguments? I also don't particularly like that empty structs and empty tuples behave differently, but maybe that's okay?
Well, we can write a tonne of integration testing for these cases and switch Unit to be an empty tuple in the IR to restore consistency.