I'm having trouble with lifetime annotations. I hope this hasn't been covered a million times, but I couldn't really find anything helpful.
I have the following code:
use pdfium_render::prelude::{PdfDocument, Pdfium};
struct X<'a> {
docs: Vec<PdfDocument<'a>>,
pdfium: Pdfium
}
impl<'a> X<'a> {
fn new() -> Self {
let pdfium = Pdfium::new(Pdfium::bind_to_system_library().unwrap());
Self {
docs: vec![],
pdfium
}
}
fn test(&'a mut self) {
let doc = self.pdfium.load_pdf_from_file("test.pdf", None).unwrap();
self.docs.push(doc);
}
}
struct Y<'a> {
docs: Vec<&'a i32>,
pdfium: i32,
}
impl<'a> Y<'a> {
fn new() -> Self {
let pdfium = Pdfium::new(Pdfium::bind_to_system_library().unwrap());
Self {
docs: vec![],
pdfium: 123
}
}
fn test(&'a mut self) {
let doc = &self.pdfium;
self.docs.push(doc);
}
}
struct Z<'a> {
docs: Vec<PdfDocument<'a>>,
pdfium: &'a Pdfium
}
impl<'a> Z<'a> {
fn new(pdfium: &'a Pdfium) -> Self {
Self {
docs: vec![],
pdfium
}
}
fn test(&mut self) {
let doc = self.pdfium.load_pdf_from_file("test.pdf", None).unwrap();
self.docs.push(doc);
}
}
fn main() {
let mut x = X::new();
x.test(); // Error
let mut y = Y::new();
y.test();
y.test(); // Error (works with a single y.test() call)
let pdfium = Pdfium::new(Pdfium::bind_to_system_library().unwrap());
let mut z = Z::new(&pdfium);
z.test();
z.test(); // Works
}
I get the following compilation error:
error[E0597]: `x` does not live long enough
--> src/main.rs:62:5
|
62 | x.test(); // Error
| ^^^^^^^^ borrowed value does not live long enough
...
72 | }
| -
| |
| `x` dropped here while still borrowed
| borrow might be used here, when `x` is dropped and runs the destructor for type `X<'_>`
error[E0499]: cannot borrow `y` as mutable more than once at a time
--> src/main.rs:66:5
|
65 | y.test();
| -------- first mutable borrow occurs here
66 | y.test(); // Error
| ^^^^^^^^
| |
| second mutable borrow occurs here
| first borrow later used here
For completeness, here is the relevant code from PDFium:
pub fn load_pdf_from_file<'a>(
&'a self,
path: &(impl AsRef<Path> + ?Sized),
password: Option<&'a str>,
) -> Result<PdfDocument, PdfiumError> {
self.load_pdf_from_reader(File::open(path).map_err(PdfiumError::IoError)?, password)
}
pub fn load_pdf_from_reader<'a, R: Read + Seek + 'a>(
&'a self,
reader: R,
password: Option<&'a str>,
) -> Result<PdfDocument<'a>, PdfiumError> {
...
As far as I can tell, the issue is that I can only do a single &'a mut
borrow, so for X
the second borrow occurs in the destructor, whereas for Y
, I can do a single y.test()
call because the destructor doesn't use anything with lifetime 'a
(note that PdfDocument<'a>
has a nontrivial destructor)?
My Z
implementation works, but it seems inelegant to have the Pdfium
object outside. Is there a way to implement this without having to pass Pdfium
as a reference to Z
?