Skip to content

Question about "#[pymethods] cannot be used with lifetime parameters or generics" #1088

@tomplex

Description

@tomplex

Hello,

I'm a newbie to Rust in general and especially PyO3, so if there's a better place to ask this please let me know.

I'm trying to wrap / expose to Python a Rust struct which requires lifetime parameters. In #436 a comment suggests:

As far as I know there's no way to make lifetimes sound with python objects, i.e. we can't enforce that the referenced objects actually outlive our object after we moved it into a python object.

How do I reconcile this with my need to specify a lifetime for this struct?

This is an essentially equivalent example:

use std::io::{BufReader, Read};
use std::fs::File;

use pyo3::prelude::*;
use pyo3::exceptions;

// This is library code, owned by someone else 
// which I'm trying to wrap 
struct FancyReader<'a> {
    reader: &'a mut dyn Read,
}

impl <'a> FancyReader<'a> {
    pub fn open<R: 'a + Read>(reader: &'a mut R) -> Result<Self, String> {
        Ok(FancyReader { reader, })
    }
}

// My code
#[pyclass(name=Reader, unsendable)]
struct PyReader<'a> {
    reader: FancyReader<'a>,
}

#[pymethods]
impl <'a> PyReader<'a> {
    #[new]
    fn new(filepath: String) -> PyResult<Self> {
        let mut file_reader = BufReader::new(File::open(filepath)?);

        let fancy_reader = FancyReader::open(&mut file_reader);
        match fancy_reader {
            Ok(reader) => PyResult::Ok(PyReader{reader,}),
            Err(_) => {
                let error = PyErr::new::<exceptions::OSError, _>("Could not open or read file.");
                PyResult::Err(error)
            }
        }
    }
}

I get a bit further trying the'static lifetime in my pyclass, but I don't know if that is best practice. Also, I then get an error about the lifetimes not matching between the new function and FancyReader::open:

error[E0597]: `file_reader` does not live long enough
  --> src/lib.rs:30:46
   |
30 |         let fancy_reader = FancyReader::open(&mut file_reader);
   |                            ------------------^^^^^^^^^^^^^^^^-
   |                            |                 |
   |                            |                 borrowed value does not live long enough
   |                            argument requires that `file_reader` is borrowed for `'static`
...
38 |     }
   |     - `file_reader` dropped here while still borrowed

I'm not sure where to go from here. Many thanks for any help you can provide.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions