Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the return type of this method a slice or a borrowed array?

I am working through the Rust book, specifically the "Departments" exercise in section 8.3.

I've become a little confused by what is being returned from a method I've created.

#[derive(Debug, PartialEq, Eq, Hash)]
enum Department {
    Sales,
    Engineering,
}

#[derive(Debug)]
struct Company {
    users: HashMap<Department, Vec<String>>,
}

impl Company {
    fn add_user_to_department(&mut self, department: Department, employee: String) {
        let users = self.users.entry(department).or_insert(Vec::new());
        users.push(employee);
    }

    fn get_users_in_department(&self, department: Department) -> &[String] {
        match self.users.get(&department) {
            Some(u) => &u,
            None => &[]
        }
    }
}

At first I thought the method get_users_in_department is returning a slice of the Vec (or in the case of None a static literal).

But in my match statement I am not using the slice syntax, I am returning a borrowed reference to the Vec.

match self.users.get(&department) {
    Some(u) => &u,
    None => &[]
}

If I was returning a slice wouldn't I have to return Some(u) => &u[..],

I guess my confusion boils down to what the return type of get_users_in_department is. Is it returning a reference to an array of String, or a slice of an array of String. Are these two types interchangeable due to some sort of coercion? If it's possible to differentiate between the two, how and when would I want to return one or the other?

like image 377
user715374 Avatar asked Dec 07 '20 23:12

user715374


Video Answer


1 Answers

From Type Coercions in The Rust Reference:

Type coercions are implicit operations that change the type of a value. They happen automatically at specific locations and are highly restricted in what types actually coerce.

Coercion is allowed between the following types:

  • &T or &mut T to &U if T implements Deref<Target = U>.

This kind of type coercion is called a deref coercion. Relevant example: Vec<T> implements Deref<Target = [T]> so &Vec<T> can be coerced into &[T].

A coercion can only occur at certain coercion sites in a program; these are typically places where the desired type is explicit or can be derived by propagation from explicit types (without type inference). Possible coercion sites are:

  • Function results—either the final line of a block if it is not semicolon-terminated or any expression in a return statement.

Example:

// no type coercion
fn vec_to_vec<T>(vec: &Vec<T>) -> &Vec<T> {
    vec
}

// &Vec<T> coerced to &[T] via deref coercion
fn vec_to_slice<T>(vec: &Vec<T>) -> &[T] {
    vec
}

playground

To answer your question more directly, the type of &u inside get_users_in_department is &Vec<String> but it's being coerced into &[String] by the compiler for you.

like image 145
pretzelhammer Avatar answered Oct 19 '22 01:10

pretzelhammer