I have some experience in C, but I'm new to Rust. What happens under the hood when I pass a struct into a function and I return a struct from a function? It seems it doesn't "copy" the struct, but if it isn't copied, where is the struct created? Is it in the stack of the outer function?
struct Point {
x: i32,
y: i32,
}
// I know it's better to pass in a reference here,
// but I just want to clarify the point.
fn copy_struct(p: Point) {
// Is this return value created in the outer stack
// so it won't be cleaned up while exiting this function?
Point {.. p}
}
fn test() {
let p1 = Point { x: 1, y: 2 };
// Will p1 be copied or does copy_struct
// just use a reference of the one created on the outer stack?
let p2 = copy_struct(p1);
}
As a long time C programmer also playing with Rust recently, I understand where you're coming from. For me the important thing to understand was that in Rust value vs reference are about ownership, and the compiler can adjust the calling conventions to optimize around move semantics.
So you can pass a value without it making a copy on the stack, but this moves the ownership to the called function. It's still in the calling functions stack frame, and from a C ABI perspective it's passing a pointer, but the compiler enforces that the value is never used again upon return.
There's also return value optimization, where the calling function allocates space and the pointer is passed to the caller which can fill out the return value there directly. This is the sort of thing a C programmer would be used to handling manually.
So the safety of the ownership rules and borrow checker, combined with the lack of a fixed guaranteed ABI/calling convention, allow the compiler to generate efficient call sites. And generally you worry more about ownership and lifetime, then needing to try and be clever about function call stack behavior.
I’m not sure what you are asking.
If your question is about what happens with the value you created from the point of view of you as a programmer, then the answer is it is moved (unless it implements
Copy
). You might want to go through some basic rust tutorials to grasp this concept.If you are asking about what happens under the hood, then I’m afraid there might be no single answer. I believe, conceptually, the value is being copied using something like
memcpy
, but then the optimizer might kick in and eliminate this. I don’t think there is something like a specification regarding this, and it might be better to consider this an implementation detail.