Lifetime hell... what to do?

⚓ Rust    📅 2026-01-17    👤 surdeus    👁️ 1      

surdeus

I had been writing a toy scripting language when I learnt rust. It was quite a while when I first wrote it, and I made use of a lot of clones, so, when I came to revisit the code, I decided it would be a good idea to refactor the code to get rid of them. Doing so required a lot of refactoring and a lot of wondering why on earth I had wrote it this way before, and I must thank the compiler for helping me.

One of the things I decided to do was switch to use an arena allocator, and this required converting everything to references, which meant many, many lifetime annotations. At first it was okay, but as the more parts of the code were refactored, they quickly got out of hand.

pub struct Augment<'a, 'env, 'iter> {
    iter: slice::Iter<'iter, Content<'a>>,
    env: &'env mut Environment<'a>,
}

impl<'a, 'env, 'iter> Augment<'a, 'env, 'iter> {
    pub fn new(iter: slice::Iter<'iter, Content<'a>>, env: &'env mut Environment<'a>) -> Self {}
}

This was the lifetimes used for one of the types. If you're wondering how I managed to work through all these lifetimes... I didn't.

Despite not wanting to use AI to write code for me, I had to consult it so I can figure out the proper lifetime annotations. Though the thing was: I knew that the code was safe, but I still had to fight the borrow checker because of its strictness. Even now my brain, upon seeing the amount of lifetimes, doesn't want to work out why exactly each annotation was used.

On the other hand, I knew at the same time that there were times when the compiler caught bugs when there would've been a dangling pointer and I wasn't paying attention.

Should I have approached it a bit differently (perhaps there was a better way to write it such that I didn't need this many lifetimes) or even have used some other language with more relaxed rules?

1 post - 1 participant

Read full topic

🏷️ Rust_feed