Automatic borrowing in function calls

I'm new to rust and I have a question regarding functions that borrow their arguments.

In C ++, only the type signature of a function indicates whether the argument should be taken by reference; the code that calls the function does not have to explicitly indicate that it is passing a reference. As an example:

// The function signature indicates x should be passed by reference.
void increment(int& x) {
    ++x;
}
void main() {
    int y = 0;
    increment(y); // y is implicitly passed by reference
    // y is now 1
}

      

Rust, on the other hand, doesn't seem to allow this. The following code will not compile:

fn output(x: &isize) {
    println!("{}", x);
}

fn main() {
    let y: isize = 0;
    output(y); // Error.
    // output(&y); <- this is ok though
}

      

When using the via method syntax, if the function signature accepts &self

or &mut self

, then these entries occur without the caller using &

or &mut

.

Is there a reason why auto-borrowing does not work for generic function arguments, and if so why does this happen when using method syntax?

+3


source to share


1 answer


Although they are also written with &

and are often called "references", these types in Rust are C ++ pointers. They are first-class values, unlike C ++ references, and thus can (and should, in general) be instantiated and dereferenced explicitly.

However, accessing fields and methods is a very common operation, and often you have methods &self

/ &mut self

, but they own the object, and not just have a reference to it, or a reference to a structure whose fields you need to access. The requirement to explicitly create links and dereference them in these circumstances would lead to a lot of line noise (especially because the operator priority is that you would need to type (&foo).method()

or (*foo).field

) essentially no benefit: getting the link is free and dereferencing for access is considered label worthy even in spartan C ( foo->field

). Therefore, when needed, the automatic field access markups (including smart pointers, by the way) and method call "autoreferences".



Elsewhere (like passing arguments) this is much less necessary and the explanation is sometimes helpful to the reader. In general, the compiler cannot figure out what you meant. This is compounded by the later added "drift constraints" where, for example, &x

for x: Rc<T>

can lead to &T

rather than to &Rc<T>

. There are also autoderef tiebreakers, but they're pretty crisp and usually what you want.

+1


source







All Articles