More generally, there are various situations where garbage collection is effectively a requirement: namely, when you've got a mutable graph where anything can point to anything else, where some nodes are root nodes and others are not, and so it's possible for cycles of unreachable nodes to occur and you don't want this to result in memory leaks.
You could in theory imagine a language like Rust where garbage collection was integrated more deeply on a syntactic level, such that you might sometimes use it for convenience and not just where it's a requirement (and Rust in fact worked like this for a while pre-1.0), but the way things currently work, integrating a garbage-collection library basically always makes your code more unwieldy and you only do it if you have to.
I just feel like not having GC is sort of a deliberate, core design choice for the language. Having strict ownership rules and being forced to think about references feels like a feature not a bug you know? Adding GC feels analogous to the "++" in C++ to me.
Not that I have anything against the efforts people are putting into it though - I'm genuinely curious about what it lets me do better/faster within rust.
In terms of practical, yeah a doubly linked list (or trees with bidirectional pointers to both parent and children, etc) is especially easier to implement in a GC environment than with Rust borrow checking alone. You can do it without a GC, but a GC can be a helpful intermediary.
Not in my experience.
Of course, many GCs have indeed gotten better in their own right, but not using the GC at all remains the most potent optimization.
GCs are useful in the same way that Python is useful even though it is slow. Simplicity of use has intrinsic value but that is a tradeoff against other objectives.
You can say the same about any abstraction, such as having a generic memory allocator, using a standard library, actually about any code reuse. For example, many programs use printf, but don’t need all its features, so hand-rolling a custom version may lead to smaller, faster code (things get complicated here on systems with shared libraries)
The question always is whether lost performance (execution time, memory usage) is worth faster development.
My point is that you can start out without a GC and do a series of sane and effective optimizations that end you up with a GC. Just as you can start with a GC and optimize by moving more and more of your allocations to non-GC memory and end up without a GC. Which endpoint is faster depends on the workload.
I have also worked on projects (web apps) where GC pauses became annoying to end-users. I wouldn't say this is the fault of GC perse, but writing code without a GC, seems to prevent some performance problems for me, and can also make performance problems stand out sooner in the dev cycle.