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.
It's not that simple. Obligate refcounting has lower throughput than obligate tracing GC but offsets that with more predictable latency, which might be good for the Swift use case. Rust uses a mix of stack-based allocation, manual heap allocation and RC - and the RC only needs to manage "owners" as determined via the borrowck, as opposed to ephemeral references. So is way more efficient than something like Swift ARC, where refcounting is essentially ubiquitous and any operations via references will incur slow atomic RC updates.
That’s shared pointers recursively freeing up their reference trees. There is a great paper showing that RC tracks object death, while tracing GCs track object “liveness”, so its essentially two sides of the same coin.
As for RC, sure, at compile time many of the work can be omitted, but atomic writes needed for the counters are fundamentally slow operations on modern architectures.
GC will always be needed to solve problems dealing with general graphs containing possible cycles. Not coincidentally, this describes many of the GOFAI problems for which GC (in the context of LISP) was first developed.
Weak and unowned pointers are pretty simple to deal with, and I’ve never seen a situation where it’s really confusing whether a pointer should be strong or weak in swift. Everything mostly just works, and if you need to point back to the object that owns you, it’s usually pretty clear by the abstraction you’re building that you need a weak/unowned reference to do it.
That's not the interesting case; that is indeed easily addressed by "weak" pointers. What's interesting is the case of a spaghetti reference graph where none of the objects definitely "owns" any other, and even the choice of GC roots might be dynamic.
Modern C++ unfortunely still has too much people writing classical C with classes, to make it properly safe.
Rust, yes, affine types are great, but their usability is only justified in scenarios where having any kind of automatic memory management isn't acceptable.
With Rust and C++ (don't know about Swift), you still have to spend a lot of time thinking about memory.
You don't think about memory, you just think about how to ensure that you're always referencing live objects. And you need that kind of thinking anyway to deal with non-memory resources, where a GC won't help you at all.
There are other ways such as customozong new/delete.
Depends on your situation what you can or cannot do/afford.
Haskell needs a GC too. You can't do ergonomic functional programming without GC (it has been attempted).
In the beginning the biggest drawback seemed to be performance, so people have been hell-bent on fixing that for decades now. Completely ignoring that the "don't need to care about memory" mindset is flawed. You always need to think about memory, and if you do you might as well do it yourself. It doesn't take more time to do in the long run and you are forced to design a better system because of it.
For scripts it is a really nice have. But for a proper language writing large-scale applications? No thanks.