Same here!
I am now actually working in compilers, which is one thing I'm really passionate about, but not something I was doing professionaly. I managed to turn a toy project and some blog posts into an actual job at almost 40, so, thank you HN!
I work at ServiceNow, which sells an enterprise platform and a ton of products built on top of it.
Internal teams and customers can extend the platform by writing JavaScript, hence we have a JS runtime in the platform (the venerable https://github.com/mozilla/rhino/), which our team works on.
from gremllm import Gremllm
# Be sure to tell your gremllm what sort of thing it is
counter = Gremllm('counter')
counter.value = 5
counter.increment()
print(counter.value) # 6?
print(counter.to_roman_numerals()) # VI?
Of course I didn't assume to be 100% productive immediately, and I did spend a few weeks on this experiment, not just some days.
My point was more about how even modern C++ felt (to me) dated and annoying to use compared to more modern language, because of the strong (but very valid!) focus on backward compatibility that C++ has. Furthermore, the long history and baggage means that for any thing, there are _many_ different ways of doing it, which doesn't help.
And anyway, it was not a particularly serious (or, for that matter, well written or argued) discussion. As I mentioned in literally the first line, it's just a rant :-)
PS: I am unsure what you mean with "relying on LLM for configuring things says it all". In my experience, this is one area where LLMs _really_ do help a lot - it has been much faster than going through the documentation (which I also did quite a bit of, in particular for conan).
That sounds reasonable (and way better than what I have implemented).
I am not sure I am going to try it though - it probably is a bit too much code to change for something that I consider "done" and I am not working on. :)
Given that classes are managed by the arena, I know the reference will not be dangling thanks to the 'a lifetime.
Initially I had implemented this with raw pointers, without lifetimes, but then I switched to the reference because it felt more "idiomatic" and I had to put the lifetimes just about everywhere to make the compiler happy.
If there are better ways to do this, I would be really happy to learn, though!
For things like classes that aren't going to be created and destroyed quickly it likely is best to just use a Rc. Then you know it will be available and don't need to bother with lifetimes.
Of course there is a good chance that you will eventually want a VM-scoped lifetime for something else so maybe it is best to just start now.
Yeah, I think I understand why you had to write it this way, but the fact that this lifetime needs to be bubbled up so far up is really non-intuitive to me.
> If there are better ways to do this, I would be really happy to learn, though!
Me, too. :) I find myself limited by my way of thinking here, coming from C++ ("I _know_ it lives long enough, why don't you let me express this?").
Agreed, it _is_ annoying. It bubbles up everywhere and it feels like "something to silence the compiler" more than "something to express the safety of the code", as other people have pointed out.
The better way to do this is to use an indexing arena such as `slotmap` or `generational-arena`, so `ClassRef` is not actually a memory pointer to anything but can still be looked up in the context of the class collection. Or, if you never need to remove any values, you can use Vec as your arena and usize as your key.
IMHO, using an vector index as a pointer should be a last resort (as an alternative to unsafe). Although it's memory safe, you still have many of the traditional issues like stale pointers / use-after-free, plus you also have the cost of a bounds-check on every access and making sure you use your stored indexes with the correct container instance. If you can solve your problem by using safe code with lifetimes, that should be preferred.
What is presented here is a self-referential type, and Rust does not allow you to declare self-referential types, and an indexed arena is a solution to that. You are correct that you still have all the issues you described - that doesn't mean it should be a 'last resort' to stop using an incorrect system of lifetimes, because there is no 'safe code with lifetimes' that encodes a self-referential type. The type safety issue is solved by using slotmap or typed-generational-arena, which use unique key types.
Same way to write self referential structs - use index types into the whatever arena you are using. Indexes are usually 32 bit so they are a bit faster than pointers.
If you are building one off trees such as for parsing and ast transforms, bumpalo is your friend.
In your case, you can look into generational arenas and slabs which are useful for graphs.