Search code examples
filerustimmutabilityborrow-checker

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


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)


Solution

  • 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.