Weird!
I would expect all to work, but also, none are guaranteed to work. I haven't examined the compiled code, but as a first guess, I would blame BTreeMap for it being the least trivial data structure. Both Vec and HashMap (at least last time I checked) store their internal data in one place, and then have a big allocated array of data elements. BTreeMap, on the other hand, has a whole set of different allocated nodes, and each node stores both an array of pointers and an array of data. This is an excellent case study on it's implementation, if you're interested.
Maybe the fact that BTreeMap stores pointers and data together makes it particularly susceptible to the compiler deciding to rearrange its field?
Really though, if your goal is to get this working, I wouldn't recommend spending too much effort on this. None of these structures are guaranteed to work across different binaries, and trying to guess/debug why they fail will likely read to exploring compiler and stdlib internals, and maybe finding a workaround which breaks later.
The only things that should work here are #[repr(C)]
structures. Repr rust things, including structures defined by the standard library, are subject to being arbitrarily different between different binaries. Rustc can and will optimize things differently, reorder strict fields, change podding, etc. It's undefined behavior to try this with any of these data structures, so you're rolling the dice every compile, even doing this with something as simple as Vec
. Undefined behavior is undefined.
If your goal is exploring why this fails, then by all means, go ahead! I recommend using gdb to step through the outer program, and examining what a BTreeMap looks like in memory in the inner and outer binaries.
If you want to make this work, and reliably work, I'd recommend adding a dependency on abi_stable. It has some macros, along with a whole set of #[repr(C)]
replacements for std types and collections. Admittedly no BTreeMap, but at least it has other types which ore guaranteed to work.