Borrowed value doesn't live long enough in if ... else arms

I'm iterating over the lines of a .txt file. Every 3rd line I'm doing some calculation, every 1st or 2nd line, I save a reference to the line.

// Signature of fn used below
fn common_char(l1: &str, l2: &str, l3: &str) -> char

fn main() {
      let args: Vec<String> = env::args().collect();
      if args.len() != 2 {
          panic!("{} expects a pathname", args[0])
      }
  
      let mut cum = 0u64;
      let mut n = 0;
  
      if let Ok(lines) = read_lines(&args[1]) {
          let mut l1: &str = "";
          let mut l2: &str = "";
          for line in lines {
              if let Ok(l) = line {
                  n += 1;
                  let rest = n % 3;
                  if rest == 0 {
                      let common = common_char(l1, l2, l.trim());
                      cum += item_to_score(common);
                  } else if rest == 1 {
                      l1 = l.trim();
                  } else {
                      l2 = l.trim();
                  }
              }
          }
      }
  
      println!("The score is {}.", cum)
  }

The compiler complains that

error[E0597]: `l` does not live long enough
  --> src/main.rs:48:26
   |
45 |                     let common = common_char(l1, l2, l.trim());
   |                                              -- borrow later used here
...
48 |                     l1 = l.trim();
   |                          ^^^^^^^^ borrowed value does not live long enough
...
52 |             }
   |             - `l` dropped here while still borrowed

I don't really get what's happening here, the branches can't run during the same iteration of the loop and every loop iteration gets a new line.

You haven't given us the signature of your read_lines() function, but I presume it is returning an iterator of Strings.

Each time the loop iterates, the String in the variable l owns its characters, and l1 and l2 only borrow them, but l is dropped when the loop loops or ends, so l1 and l2 can't borrow l which no longer exists. You will need to change the l1 and l2 variables to store Strings so that somebody owns the characters that you want to keep around for the next iteration of the loop.

1 Like

Consider making an iterator adapter that wraps lines and has an Item of (String, String, String), since you only do something once you've collected three lines.