Why can I call File.take() on a reference?

2019-02-24 04:51发布

When I look at File's docs, I see that the take method takes a self, not a &self. But I'm still able to call the method on a borrowed reference:

fn foo(file: &File) {
    let _ = file.take(1); // why does this work?
    println!("can still use the file: {:?}", file);
}

I thought a self passes ownership but I'm even able to use file after calling take so ownership clearly stays inside foo.

If I do it myself on a custom struct with a method, it doesn't work:

struct Foo;

impl Foo {
    fn foo(self: Foo) { }
}

fn main() {
    let foo = &Foo;
    foo.foo(); // error: cannot move out of borrowed content
}

which is fully expected.

Likewise according to the docs, File does not implement any special traits as far as I can tell. What did get my attention is that Read has a by_ref() method but I don't call it yet everything still works.

What's going on here? (using rustc 1.3.0-dev)

标签: rust
1条回答
三岁会撩人
2楼-- · 2019-02-24 05:32

The take method comes from the Read trait. That trait is implemented on File, so there is a method File::take(self, u64) -> Take<Self>, but the trait is also implemented on &File (the impl is even listed on the very page you link to). For that impl, the Self type is &File, so its take method takes a reference.

查看更多
登录 后发表回答