Given Rust’s memory safety goal, IMO the proper way to solve the circular reference problem in the context of Rust would be in the language. It should have a way to express what cycles may exist, maybe also how the code will break them when needed.

Have people been thinking about that?

There haven't been any serious proposals yet, but some ideas have been floating around from time to time. For example this blog post has some ideas that might allow them https://smallcultfollowing.com/babysteps/blog/2024/03/04/bor...

The hardest problems I think is that this requires a fundamental change to the language that something might be already borrowed just by existing. It also likely needs to introduce a notion of "stable" places that will not move when you move a prefix of them, e.g. to allow moving a `Box` holding self-referential data. In other words, there's a lot of bikeshedding to do.

First, there are external crates offering safe self-referential structs.

A builtin language feature will for sure be more convenient (and also probably more performant, as most of those crates require an allocation) but it's just really hard to design. Even in very old self-referential crates soundness issues are still being discovered to this day. So it will need to a lot of time and care to design.