1

This works:

let paths: Vec<String> = args.collect();
let paths = paths.iter().map(|f| std::path::Path::new(&f));

This doesn't work:

let paths = ::std::env::args().map(|f| std::path::Path::new(&f));
error[E0597]: `f` does not live long enough
 --> src/main.rs:2:66
  |
2 |     let paths = ::std::env::args().map(|f| std::path::Path::new(&f));
  |                                                                  ^-- borrowed value needs to live until here
  |                                                                  ||
  |                                                                  |`f` dropped here while still borrowed
  |                                                                  borrowed value does not live long enough

Why do I need to collect the args iterator into a vector just to produce another iterator? Why can't I produce one iterator directly from another?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
user1685095
  • 5,787
  • 9
  • 51
  • 100

1 Answers1

4

The Args iterator returns values of type String. When you map over an iterator, the closure is given ownership of each value.

The code that doesn't work attempts to take a reference to the String, but that string will go out of scope at the end of the closure. This is disallowed as discussed in Return local String as a slice (&str).

The code that does work is not iterating over Strings but &Strings; see What is the difference between iter and into_iter?. Thus there's nothing to go out of scope in the closure and returning a reference from the closure is fine.

The correct solution is to transfer ownership of the String's data to a new type. PathBuf is the appropriate choice. PathBuf is to &Path as String is to &str:

let paths = ::std::env::args().map(std::path::PathBuf::from);

PathBuf is mutable. I don't need mutability here. Why do you think I need PathBuf?

You are confused about how mutability works in Rust. Go back and re-read The Rust Programming Language, especially the chapter on Variables and Mutability.

Types in Rust are not mutable or immutable by themselves. Mutability is a property of the variable binding:

let buf = std::path::PathBuf::new();
buf.push("home");
error[E0596]: cannot borrow immutable local variable `buf` as mutable
 --> src/main.rs:3:5
  |
2 |     let buf = std::path::PathBuf::new();
  |         --- consider changing this to `mut buf`
3 |     buf.push("home");
  |     ^^^ cannot borrow mutably
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366