Swift could have been a big player but equally I can’t see a particularly good reason why you'd choose it. I like it a lot as a language but unless I was really wedded to the idea of reusing code between server and native app client I wouldn’t be pushing it. For one it’s way too easy to create memory leaks compared to garbage collected languages.
Once you've worked with refcounting GC systems for a while avoiding leaks becomes pretty much second nature.
It is absolutely a pain when you first come to it from a mark and sweep GC'ed language but once figuring out the right spot to use a weak reference becomes automatic creating leaks largely ceases to feel 'too easy' though occasionally throwing a cycle checker at your code is recommended nonetheless.
For sure. But the question still remains: when you’re running on a high performance server that’s more than capable of speedy garbage collection, why bother?
My last comment was only addressing your 'too easy to' part (which, per sibling comment, may not be as universal an appearance as I thought).
However, fair question.
My answer here is that I am also really rather fond of timely destruction - in the same way as a Rust value's Drop happens as soon as the value is no longer required, a refcounting GC can fire destructors/finalizers immediately.
That means that e.g. if code that's using an "external" resource (think file descriptor) throws an exception, the resource will automatically be released during the stack unwind rather than having to wait for the next GC pass.
It also means that you can (and I, in fact, do) have a transaction object that can emit a warning at a useful point if you let it go out of scope without calling commit or rollback on it.
You can absolutely get (close) equivalents to this with a mark and sweep GC language, go's 'defer' strikes me as something I could implement at the very least 90% of these patterns with, but it's still something you have to consciously implement.
What's trickier is e.g. if you have N objects in flight sharing a resource but want the resource to go away when all of those are done - in a non-refcounting language you either have to track the count yourself (i.e. effectively implementing a mini-refcounter) or again rely on GC to sweep it up soon enough not to be a problem.
So it's a trade-off between having to think about resource releases and having to think about breaking cycles, and I'm not at all arguing refcounting is -better- but I personally mostly find it just -different- and I'm definitely not convinced that getting used to it is (much) harder than getting used to the relevant dances to not temporarily leak file descriptors and similar.
Possibly it just fits my brain unusually well; possibly those environments have more footguns than the ones I've used refcounting in.
I do think something Recycler-enabled is preferable, but I'm still very fond of deterministic destruction and personally willing to make the trade-off.