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?
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
ifT
implementsDeref<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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With