Generic function parameters take ownership when they are used within another function

Hi!
I have a small application in which I am passing around the reference to a file in a lot of places.
Now I want to try memmap, and instead of changing all function signatures to accept that, I tried to go the generic route.
At first everything looked good, and I was able to pass a reference to that multiple times in main().
But as soon as I try to do that from another function, which also borrowed this parameter, the called procedure takes ownership if I pass the parameter directly.
Passing a reference instead also does not work because "the trait bound &impl Read + Seek: Seek is not satisfied" then.
There should a way to make this work, right?
Thanks!

This has no function, but it demonstrates my issue:

use std::{
    fs::File,
    io::{BufRead, BufReader, Read, Seek, SeekFrom},
};

fn read_data(r: (impl Read + Seek)) {
    let mut reader = BufReader::with_capacity(10, r);
    reader.seek(SeekFrom::Start(0 as u64)).unwrap();
    reader.fill_buf().unwrap();
}

fn read_data_2(r: (impl Read + Seek)) {
    read_data(r);
    read_data(r);
}

fn main() {
    let file = File::open("test.bin").unwrap();
    read_data(&file);
    read_data(&file);
    read_data_2(&file);
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0382]: use of moved value: `r`
  --> src/lib.rs:14:15
   |
12 | fn read_data_2(r: (impl Read + Seek)) {
   |                - move occurs because `r` has type `impl Read + Seek`, which does not implement the `Copy` trait
13 |     read_data(r);
   |               - value moved here
14 |     read_data(r);
   |               ^ value used here after move
   |
note: consider changing this parameter type in function `read_data` to borrow instead if owning the value isn't necessary
  --> src/lib.rs:6:18
   |
6  | fn read_data(r: (impl Read + Seek)) {
   |    ---------     ^^^^^^^^^^^^^^^^ this parameter takes ownership of the value
   |    |
   |    in this function
help: consider further restricting this bound
   |
12 | fn read_data_2(r: (impl Read + Seek + Copy)) {
   |                                     ++++++

For more information about this error, try `rustc --explain E0382`.
error: could not compile `playground` (lib) due to previous error

Pass mutable references.

2 Likes

Ok, that's less complicated that I thought.
Thanks!

Relevant docs.

2 Likes