Struct lifecycle question

Hi there,

I am new to Rust and I am running into a lifecycle issue. I am not sure I fully understand it, but more so how to actually solve it.

This is the minimum code showing my problem.

use std::io::BufRead;
use unicode_segmentation::UnicodeSegmentation;

pub struct TestStream<'a> {
  vec: Vec<&'a str>,
  reader: Box<dyn BufRead + 'a>,
  buffer: String,
}

impl<'a> TestStream<'a> {

  fn doIt(&mut self) {
    self.buffer.clear();
    self.reader.read_line(&mut self.buffer);
    self.vec = self.buffer.graphemes(true).collect();
  }
}

The self.buffer.graphemes is from:

[dependencies]
unicode-segmentation = "1.6.0"

The compiler complains:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --> src/testme.rs:33:28
   |
33 |     self.vec = self.buffer.graphemes(true).collect();
   |                            ^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 30:3...
  --> src/testme.rs:30:3
   |
30 | /   fn doIt(&mut self) {
31 | |     self.buffer.clear();
32 | |     self.reader.read_line(&mut self.buffer);
33 | |     self.vec = self.buffer.graphemes(true).collect();
34 | |   }
   | |___^
note: ...so that reference does not outlive borrowed content
  --> src/testme.rs:33:16
   |
33 |     self.vec = self.buffer.graphemes(true).collect();
   |                ^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 28:6...
  --> src/testme.rs:28:6
   |
28 | impl<'a> TestStream<'a> {
   |      ^^
note: ...so that the expression is assignable
  --> src/testme.rs:33:16
   |
33 |     self.vec = self.buffer.graphemes(true).collect();
   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: expected  `std::vec::Vec<&'a str>`
              found  `std::vec::Vec<&str>`

error: aborting due to previous error

The lifetime of the vector of the struct vs the one that's collected differ, but how can I fix this? Or am I just doing something fundamentally wrong here?

Essentially I need the vector later on to read from it in different functions (left-out here to keep the code short).

I hope someone can shine some light on this. Thanks a lot for your time!

Martijn

self.buffer.graphemes() returns &str, the question is - who owns those &strs?

At the moment, is seems like the current function is trying to return/save a reference for a temporary type. Consider making the returned type owned:

pub struct TestStream<'a> {
  vec: Vec<String>,
  reader: Box<dyn BufRead + 'a>,
  buffer: String,
}
self.vec = self.buffer.graphemes(true).map(|v| v.to_owned()).collect();
1 Like

If I understand correctly, you are trying to build a self-referential struct - vec borrows from buffer. That's fairly hard to do in Rust, and impossible using only safe code.

Thank you both for your reply. The owned solution works fine, thanks!

Unsafe code is probably not the best idea for me right now as I am only starting and it's hard enough right now. :slight_smile:

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.