Consider this code:
fn funA() {
let v1: Vec<i32> = vec![1, 2, 3];
funB(&v1); // question_A
v1.iter(); // question_B
}
fn funB(slice: &[i32]) {
// slice type is &[i32] by sure
}
I'm confused because funB
requires type &[i32]
, while caller using type &Vec<i32>
. Here is part of invoke stack, I can see there is kind of deref
and as_ptr
actions, but not sure how it works.
core::ptr::mut_ptr::<impl *mut T>::is_null (@core::ptr::mut_ptr::<impl *mut T>::is_null:42)
alloc::vec::Vec<T,A>::as_ptr (@<alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref:19)
<alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref (@<alloc::vec::Vec<T,A> as core::ops::deref::Deref>::deref:11)
hello_cargo::funA (/Users/path-to-hello_cargo/src/main.rs:15)
...
main (@main:12)
start (@start:639)
Does it auto-convert? Is it "optimized" by the compiler? What's the difference to Vec::as_slice()
?
It is called Deref
coercion
/// Vec<T> implements Deref as follows
impl Deref for Vec<T> {
type Target = &[T];
fn deref(&self) -> &Self::Target;
}
// meaning you can call
let vector: Vec<T> = ...
let slice: &[T] = vector.deref();
// Rust can call .deref() automatically whenever needed (coercion)
You can read about it more here