4 ms·
It’s not that complicated. Just think of it as the compiler transforming a function “fn new(x: arg) -> Foo” to “fn new(x: arg, result: &mut Foo)”. In practice,
by slaymaker1907 7y ago
It’s not that complicated. Just think of it as the compiler transforming a function “fn new(x: arg) -> Foo” to “fn new(x: arg, result: &mut Foo)”. In practice, it is fancier than this since it isn’t passing Foo as a pointer, but that is a small difference.
You are not allowed to read this object directly obviously, but you effectively give it a value by the return statement so you can replace the return with an assignment. Then, the compiler really doesn’t need to do anything fancy and can just apply transitivity to get rid of most unnecessary copies.
The only time this gets really tricky is when you want to use this shadow memory directly for some complex initialization since it can be overwritten arbitrarily.
Personally, I don’t think this is really necessary as an an addition to Rust since I don’t think it results in much savings most of the time and you can emulate this pretty easily by writing the second form directly and forcing callers to pass an empty version of the object directly. There is a potential extra cost of an additional pointer, but if your function is that sensitive it should probably be inlined or written in assembly.