> I would think the Err(err) => return Err(err) line needlessly constructs a copy of result.
You would think wrong. In Rust, everything is move by default. To create a copy, you need to explicitly call .clone() on an object (assuming it implements Clone, of course), or you can implement Copy for the type, which will cause .clone() to be called instead of moving the value.
(I'm not actually sure where the compiler will generate calls to clone() on Copy types in favor of moving. In practice, you're not going to implement Copy for a type that isn't trivially copyable anyways [using the C++ definition], so any optimizer would easily be able to elide any excessive copy operations.)