> I can't say I've ever seen someone manually implement Arc in C
In C++, shared_ptr in the standard. But this was common even before the c++11 standard introduced that. I've rolled my own before, more than once. Microsoft ATL had CComPtr.
It wasn't surprising to me either that rust came from Mozilla, which made heavy use of COM, an object model that is very heavily based on reference counting.
Anyway, what do you prefer to lifetimes? They go back to at least the 60s with lisps and algol and possibly earlier. I wouldn't be surprised to find that idea predates electromechanical computers entirely.
To your second question, writing C I like to let the scope dominate the lifetime by doing a free as soon as an object goes out of scope. To make something borrow, you assign it to something with a different scope, then assign your local copy to NULL, exploiting the fact that free(NULL) is a well behaved no-op. In c++ you do the same but you can use destructors to make it more automatic.
I agree with them that in any well-written program (in any language really, not just C and C++) the ownership and lifetime constraints are not necessarily enforced by the compiler - that is, they are not expressed through types or even necessarily through code at all - but they are definitely existent in the design and behaviour of the system. If the programmer cannot explain who holds what and for how long, and therefore when it's safe to read or write particular resources, then that isn't well-written code IMO.
> I can't say I've ever seen someone manually implement Arc in C
...an Arc is literally just a shared pointer. It's in the name, Atomically Reference Counted. Reference counted resources that use atomic operations to adjust the count are a dime a dozen in C projects in my experience.
Rust did not invent the concept of a multiple-reader/single-writer lock either, e.g. the Linux kernel has the `rw_semaphore` type. I don't understand treating types like this as something arcane simply because they're given an explicit tag in Rust.