> But with with Swift, Rust and modern C++ the argument can be made that GC doesn't bring anything to the table.
Well, it would be a bad argument :D
A reference counter is arguably the slowest option, so Swift is out of the picture (besides it leaks circular dependencies). Rust is a good idea, but it is a tradeoff. Quite a lot of programs can’t be expressed with strictly tree-like lifecycles, and then you are either left with the yet again slower (A)RC, or unsafe. C++ is in pretty similar shoes. They are good for the niche they were made, systems/low-level programming.
Let me quote from the Garbage collector handbook: “above all, memory management is a software engineering issue. Well-designed programs are built from components [..] that are highly cohesive and loosely coupled. [..] modules should not have to know the rules of the memory management game played by other modules. [..] GC uncouples the problem of memory management from interfaces.”
It says nothing about not thinking about memory, you are free to optimize it where you need it.
EDIT: Oh and dynamic allocation is much faster with a modern GC than with malloc and friends, plus a moving GC can defragment heap.