Why does calling Result::as_ref() avoid doing a memcpy?
⚓ Rust 📅 2025-10-10 👤 surdeus 👁️ 3In this code for example:
struct BigStruct([u8; 10000]);
pub fn foo1() -> Result<(), bool> {
baz(&blah()?); // does a memcpy?
Ok(())
}
pub fn foo2() -> Result<(), bool> {
baz(blah().as_ref().map_err(|x| *x)?); // no memcpy?
Ok(())
}
unsafe extern "Rust" {
safe fn blah() -> Result<BigStruct, bool>;
safe fn baz(big_struct: &BigStruct);
}
The ? in foo1 triggers a memcpy of the BigStruct while the .as_ref().map_err(|x| *x)? in foo2 avoids it. See here on Compiler Explorer: Compiler Explorer.
I would expect that rustc would be able to see that BigStruct doesn't need to be moved in foo1 and generate the same code as foo2. There are no calls to as_ref or map_err in the output so it does appear to have sufficient inlining.
I noticed this while dealing with Result<DirEntry>/Result<Metadata>/Result<ReadDir> which depending on the platform are quite large because they contain an inline buffer for the file name resulting in expensive moves unless you .as_ref() first.
3 posts - 2 participants
🏷️ Rust_feed