Why I can use sort_by_key with a Vec?

2019-08-13 10:25发布

问题:

Taking this example

fn main() {

    let mut test: Vec<u32> = Vec::new(); 

    test.push(5);
    test.push(8);
    test.push(0);

    test.sort_by_key(|k| k.abs());
}

I searched the source code for Vec, but I do not see a trait or something like derive.

trait SomeTrait {
    fn sort_by_key...
}

impl SomeTrait for Vec... { }

The IntelliSense of my IDE did not detect sort_by_key either.

I searched the Rust Github and found this implementation in slice.rs:

pub fn sort_by_key<B, F>(&mut self, mut f: F)
    where F: FnMut(&T) -> B, B: Ord
{
    self.sort_by(|a, b| f(a).cmp(&f(b)))
}

But I can not see how Vec relates to a slice and how Vec can access sort_by_key.

I saw this constructor in vec.rs:

pub fn new() -> Vec<T> {
    Vec {
        buf: RawVec::new(),
        len: 0,
    }
} 

I navigated the struct but I fail to understand where sort_by_key comes from.


After the response by Jascha

I can not understand the documentation as my English is not very good. I understand that by using Deref, the struct that implements Deref can access methods to which it applies, in this case a slice, but it could be another?


I found this url which helps me understand my follow up question and may help others:

struct Foo;
impl Foo {
     fn foo(&self) { }
}

struct Bar {
    foo: Foo,
}

impl std::ops::Deref for Bar {
     type Target = Foo;

    fn deref(&self) -> &Foo {
        &self.foo
    }
}

fn main() {
    let test: Bar = Bar { foo: Foo }; 
    test.foo();  
}

I think this is very cool

回答1:

Vec<T> implements Deref<Target=[T]> ([T] is a slice). You can find more about deref coercions here. The API documentation even lists all methods accessible through Deref.



回答2:

As Jascha mentioned, Vec<T> implements Deref<Target=[T]> and DerefMut.

Note the specific syntax here: Target is an associated type of Deref (not an input) and the implementation looks like:

impl<T> Deref for Vec<T> {
    type Target = [T];

    // ..
}

The fact that Target is an associated type of Deref is important, because it means that Deref can only ever be implemented once for any given (concrete) type.

This, in turns, means that when resolving methods on a type, the compiler can easily apply deref coercions. That is, as long as no method of the given name is found, it can see if the current type can be deref'ed once more and try again (yes, this can be chained).


In the current situation this means the compiler:

  • looks for a sort_by_key on &mut Vec<T>, there is none
  • looks for a sort_by_key on &mut [T], it exists

it then transforms the call from:

let mut v = vec![1, 3, 2];
v.sort_by_key(...);

into:

let mut v = vec![1, 3, 2];
(&mut *v).sort_by_key(...);

automatically.



标签: rust