2

This Rust program collects words/lines from the user, and adds each to the variable line_set. I'd like to change the code to trim each word before adding it to line_set.

use std::collections::HashSet;
use std::io;

fn main() {
  let mut line_set = HashSet::new();

  for i in 1..4 {
    let mut line = String::new();
    io::stdin()
      .read_line(&mut line)
      .expect("Failed to read line");
    //let line = line.trim();
    line_set.insert(line.clone());
    if i == 3 {
      for l in &line_set {
        println!("{}", l);
      }
    }
  }
}

When I try to add a call to String::trim, applied to the current word, the program no longer compiles:

error[E0597]: `line` does not live long enough
  --> src/main.rs:12:20
   |
12 |         let line = line.trim();
   |                    ^^^^ borrowed value does not live long enough
13 |         line_set.insert(line.clone());
   |         -------- borrow later used here
...
19 |     }
   |     - `line` dropped here while still borrowed

I used rustc's --explain switch, and it relates that "This error occurs because a value was dropped while it was still borrowed". I had hoped using the clone method would avoid that problem. How do I get past the error?

user2023370
  • 10,488
  • 6
  • 50
  • 83

1 Answers1

4

str::trim just produces a slice, not another String, so when you call clone on it, you're calling &str's implementation of Clone, which just copies the &str (a cheap pointer copy). Instead, you should use one of the methods to turn the &str into a String, such as to_string, to_owned or more verbosely, String::from.

use std::collections::HashSet;
use std::io;

fn main() {
    let mut line_set = HashSet::new();

    for i in 1..4 {
        let mut line = String::new();
        io::stdin()
            .read_line(&mut line)
            .expect("Failed to read line");
        line_set.insert(line.trim().to_owned());
        if i == 3 {
            for l in &line_set {
                println!("{}", l);
            }
        }
    }
}

(playground)

SCappella
  • 9,534
  • 1
  • 26
  • 35
  • Thanks. So the `&str` implementation of `clone` returns a `&str`. Is there a purpose to such a call - perhaps it's useful to have it there for generic code? – user2023370 Apr 08 '20 at 11:32