I have a struct Point which does not derive Clone or Copy and am attempting to add a unary negation operation like below
impl<'a> std::ops::Neg for &'a Point {
type Output = Point;
fn neg(self) -> Self::Output {
Point {
x: -self.x, // f64
y: -self.y, // f64
z: -self.z, // f64
}
}
}
However, even after specifying the output type, using the operator returns a &Point in practice. This works correctly for other operations such as Add or Sub
let p = Point { x, y, z };
let neg = -p; // this is a &Point
Questions are
Are there notable performance improvements for defining reference operations instead of copying?
What am I doing wrong for negation that somehow works for other operations?
In my Limited experience, for small POD types the compiler will replaced/introduce references as it likes, and will inline many simple functions, so this is not too important.
But, as.always, measure your use-case.
You seem to be thinking of references as "not copying". Rust's references are for "not owning", which is a different thing with very important implications.
You should not use references to merely avoid copying, because they don't just add a level of indirection, but they also add memory management restrictions and bind items to a scope. It's also impossible to create a new object and return it via Rust reference, because Rust reference doesn't mean "here, have it via pointer", but means "it's stored over there, you can have a look", which is not true for new object you're trying to return and haven't stored anywhere permanently.
Rust's type for returning by reference is Box (e.g. Box<Point>), but for a tiny object like Point the cost of a heap allocation required to get a non-temporary pointer you can return is very high relatively to just copying the Point itself.
Finally, for a trivial operation like neg, your function will get inlined. Whether you take or return a reference or not doesn't matter to LLVM — it will obliterate all such details and do it however it thinks is faster anyway.
Thanks for the quick replies! I really appreciate all your responses as a beginner.
@scottmcm I tried to reproduce and isolate the error on Rust playground but found myself unsuccessful - maybe I made it too complicated: Rust Playground
I'm trying to emulate the same test setup so it might seem weird
I had to leave links to my actual code in the comments as I can't post multiple links yet
@kornel thanks for the detailed response! I mostly work in weakly typed languages so I'm still trying to wrap my head around some of the concepts you mentioned but I'll definitely read over the Rust book again