You're right that it looks like the implementation of Bar is being copied into Foo, because that's exactly what happens right now in a lot of cases: swift/GenRecord.h at main · apple/swift · GitHub. IRGen essentially does a depth first tree traversal of the type and generates the code it need inline. This cause other issues because the copies end up interspersed with retains/releases, so llvm is never able to group the copies into a memcpy and it ends up generating a bunch of loads and movs.
Swift's IRGen lowering for value types is pretty naive in a lot of places. I haven't personally looked too deep into why outlining doesn't help as much as one might think it would. My initial theory was that the GEPs that it produces for sub fields are different enough that the outliner isn't able to handle them, but when I experimented with some GEP lifting work @plotfi was working on, I still didn't see too much of a difference, so there might be more going on there than just the geps.
The typeinfo lowering does do some manual IR level outlining. It creates "outlined assignWithCopy" functions which you'll see as 'WO' mangled names (https://github.com/apple/swift/blame/main/docs/ABI/Mangling.rst#L299). These seem to help, but could probably be more aggressive.
Other than that, I've been working on a way to have value witness functions call into a runtime interpreter which should completely eliminate the codegen size. But I'm still a few months away from something that's upstreamable. Current status is that I've got a prototype working, but need to do a bunch of testing to see how much it helps and how much runtime impact it has.