Why does File::open move the string here?

Why doesn't it just borrow the string? If I make it &thefile, it works, but I don't understand how it can move from a non-reference argument but it can't borrow.

use std::fs::File;

fn main() {
    let thefile = String::from("the name");
    let mut handle = File::open(thefile).expect("Couldn't open it!");
    println!("{}", thefile);



   Compiling playground v0.0.1 (/playground)
warning: unused variable: `handle`
 --> src/lib.rs:5:13
5 |     let mut handle = File::open(thefile).expect("Couldn't open it!");
  |             ^^^^^^ help: if this is intentional, prefix it with an underscore: `_handle`
  = note: `#[warn(unused_variables)]` on by default

warning: variable does not need to be mutable
 --> src/lib.rs:5:9
5 |     let mut handle = File::open(thefile).expect("Couldn't open it!");
  |         ----^^^^^^
  |         |
  |         help: remove this `mut`
  = note: `#[warn(unused_mut)]` on by default

error[E0382]: borrow of moved value: `thefile`
 --> src/lib.rs:6:20
4 |     let thefile = String::from("the name");
  |         ------- move occurs because `thefile` has type `String`, which does not implement the `Copy` trait
5 |     let mut handle = File::open(thefile).expect("Couldn't open it!");
  |                                 ------- value moved here
6 |     println!("{}", thefile);
  |                    ^^^^^^^ value borrowed here after move
  = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)

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

The function is generic over any type that implements AsRef<Path>. Both String and &str implement that trait, but if you choose to pass a String, you give up ownership.

It's generic over this trait because otherwise you wouldn't be able to use &str as argument either. It would have to be a &Path only.


Rust has no implicit pass-by-reference semantics, so calling a function always moves its arguments. In this case, File::open(thefile) moves thefile into the function, and we can't use it again since String is not Copy. But if we call File::open(&thefile), we only move a &String reference into the function, so we can continue to access thefile once the function returns.


This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.