1

From playing with the compiler, I can see that Rust takes the variable item here as type &T:

fn largest<T>(list: &[T]) -> &T 
    where T: PartialOrd {
    let mut largest = &(list[0]);

    for item in list {
        if item > largest {
            largest = item;
        }
    }

    largest
}


fn main() {
    let number_list = vec![34, 50, 25, 100, 65];

    let result = largest(&number_list);

    println!("The largest number is: {}", result);
}

Why? Of course that's what I want, but I didn't specify it. Does Rust just automatically take items as references when taking from references to containers?

Also, why does the code still compile if I change line 7 as follows:


    for item in list {
        if item > largest {
            largest = &item;
        }
    }

Is Rust automatically dereferencing the return value once match the type signature I declared for largest? Without even outputting a warning?

How can I assign &x, where x: &T, to another variable y where y: &T. Certainly I should get a type mismatch: &&T does not match &T?

I've tried reading the documentation but it seems to dodge the question about what's actually going on.

I know Rust does auto reference/dereference on method calls, which makes sense as the type of the receiver is specified explicitly (and who really wants to read something like (&receiver).method(args) in code?). But auto reference/dereference on variable assignments? Surely that can't be what's happening?

  • 1
    tl;dr: Rust isn't really doing anything "automatically" because `list` is a reference (at least, nothing that it doesn't do for non-references). It just works this way because `IntoIterator for &[i32]` says that's what you get when you turn an `&[i32]` into an `Iterator`. As for `largest = &item`, that happens to work here because of [deref coercion](https://stackoverflow.com/questions/53294663/program-with-multiple-ampersand-works-fine/53295232#53295232) and because the compiler can tell that `largest` must be of type `&T`. – trent Aug 20 '20 at 15:49
  • @trentcl Thanks! I thought deref coercion applied to functions and arguments, not to assignments, so I was surprised here. If it applies also to assignments, I don't understand why the documentation makes a very big deal of only specifying it applies to function and method calls. – Marcel Besixdouze Aug 20 '20 at 15:55
  • 2
    _Does Rust just automatically take items as references when taking from references to containers_ Not all the time, please see: https://stackoverflow.com/questions/53692702/why-is-a-reference-variable-accessed-via-auto-deref-moved – Ömer Erden Aug 20 '20 at 15:57
  • 2
    You may have been misled; the documentation isn't perfect. Deref *coercion* can happen at any "coercion site" (incl. assignments, function arguments, constructors...) but *auto-deref* is a vaguely similar feature that only applies to *method* calls and field access using `.`. [This Q&A](/q/53341819/3650362) has a great, concise explanation. – trent Aug 20 '20 at 16:06
  • Closely related: [Do iterators return a reference to items or the value of the items in Rust?](https://stackoverflow.com/q/60780389) – Sven Marnach Aug 20 '20 at 18:30

0 Answers0