Reputation: 50328
Some languages, like Haskell, make no distinction between pass-by-value and pass-by-reference. The compiler can then approximately choose the most efficient calling convention with a heuristic. One example heuristic would be for the Linux x64 ABI: if the size of parameter is greater than 16 bytes, pass a pointer to the stack otherwise pass the value in registers.
What is the advantage of keeping both notions of pass-by-value and pass-by-reference (non-mutable of course) in Rust and forcing the user to choose?
Could it be the case that pass-by-value is syntactic sugar for pass-by-reference + copy if the value is seen to be modified?
Upvotes: 3
Views: 2603
Reputation: 3643
[Edited: changed exampled to work in release mode]
It isn't syntactic sugar, as one can see by looking at the generated code.
Given these functions:
fn by_value(v: (u64, u64)) -> u64 {
v.0 + v.1
}
fn by_ref(v: &(u64, u64)) -> u64 {
v.0 + v.1
}
then if one was syntactic sugar for another, we'd expect them to generate identical assembly code, or at least identical calling conventions. But actually, we find that by_ref
passes v
in the rdi
and rsi
registers, whereas by_value
passes a pointer to v
in the rdi
register and has to follow that pointer to get the value: (see details, use release mode):
by_value:
movq 8(%rdi), %rax
addq (%rdi), %rax
retq
by_ref:
leaq (%rdi,%rsi), %rax
retq
Upvotes: 0
Reputation: 15559
Two things:
In other words, in Rust, these two forms have different semantics. That doesn't preclude also doing the optimization, though.
Upvotes: 12