API design question: I need a lifetime that is tied to an object's... lifetime, but not borrows of it

⚓ Rust    📅 2025-07-20    👤 surdeus    👁️ 3      

surdeus

Hello,

I need to make an API that has a 'lifetime that is tied an object's existence (its time alive) but not tied to a specific borrow of the object. To illustrate:

struct Database;
struct Permission<'perm> (std::marker::PhantomData<&'perm ()>);

impl Database {
    /// Acquires a permission object, doing a runtime check to ensure that's ok
    fn get_perm<'perm>(&'perm self) -> Option<Permission<'perm>> {
        Some(Permission(std::marker::PhantomData))
    }
}

impl<'perm> Permission<'perm> {
    /// Allows a borrow of the underlying data, which will be valid until the permission is dropped
    fn access_data(&self) -> &'perm u64 {
        &42
    }
    /// Does an operation that modifies the `Permission` in an inconsequential way, and does
    /// not invalidate any data references
    fn frob(&mut self) { }
}

fn main() {
    let db = Database;
    let mut perm = db.get_perm().unwrap();
    let data = perm.access_data();
    assert_eq!(*data, 42);
    
    //Validate `data` is still valid after frobbing
    perm.frob();
    assert_eq!(*data, 42);
    
    drop(perm);
    assert_eq!(*data, 42); //Accessing `data` after perm is dropped will be UB!
}

It seems like this use case should be a straightforward thing to express with the Rust type system... But I can't seem to figure out a way to do it. I'm probably being dense... Thanks for any ideas in advance.

5 posts - 3 participants

Read full topic

🏷️ rust_feed