2

I would like to read lines from stdin, remove whitespace and push them in a vector but I can't because line does not live long enough. Why?

use std::io::{self, BufRead};

fn main() {
    let stdin = io::stdin();
    let mut read = Vec::new();
    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let line = line.trim();
        read.push(line);
    }
}
error[E0597]: `line` does not live long enough
  --> src/main.rs:8:20
   |
8  |         let line = line.trim();
   |                    ^^^^ borrowed value does not live long enough
9  |         read.push(line);
   |         ---- borrow later used here
10 |     }
   |     - `line` dropped here while still borrowed
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
guillaume0811
  • 77
  • 1
  • 6
  • 3
    You need to copy the trimmed lines to new owned strings: `read.push(line.to_owned());` – Sven Marnach Aug 17 '20 at 07:25
  • Depending on what you want to do with the lines, you don't need to store them in a vector first. If you just want to process them once, it's best to iterate directly over file. – Sven Marnach Aug 17 '20 at 07:26
  • Using `let line = line.trim().to_string();` also works, though I'm not sure if doing that has downsides – jdaz Aug 17 '20 at 07:32

1 Answers1

2

If you look at the definition of str::trim() (lifetime annotations added):

pub fn trim<'a>(&'a self) -> &'a str

You can see that it returns a string slice that refers to part of the original string. That is, it borrows the string instead of copying it. Which makes sense, because the result of the trim is always a substring of the original one.

You may be confused by other functions, such as, str::to_uppercase(), that return a new String. Obviously this is because they do not return a substring of the original string, so they have to create a new one.

TL;DR; You have a borrowed &str but you want an owned String to store in your Vec. Just add .to_string().

About the downsides, it will allocate a new String. You could try avoiding it by doing a trim in place, but I don't think it's worth it, unless you profile and you decide that your trimming is hurting your performance.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
rodrigo
  • 94,151
  • 12
  • 143
  • 190