It's a problem in practice. Of the three times I've ever had to use a debugger on Rust code, two came from code someone had written to do their own index allocation. They'd created a race condition that Rust would ordinary prevent.
But I agree, it does give up some of the benefits of using native references.
I had one bug in a renderer where I'd see object shadows moving across a 3D scene, but not the object casting the shadow. Didn't crash. That was hard to find. A dead index was still in use, and it pointed to something valid enough to be drawn.
You can just wrap your pointers, and then say the underlying collection they point to must outlive the pointers returned. Granted, that doesn't work so well if the collection allows removal. But if your collection is append only you've hit the sweet spot for this pattern, because with the lifetime constrained pointers and no deletions literally nothing can go wrong.
He says he's only seen it in Zig. I guess that means he hasn't done much Rust, because the Rust nudges you in that direction. Wrapped pointers are common in the language and it's libraries. They aren't used to save space. They are used to get around lifetime restrictions.
When I've done it in Rust, it has been to save space. A u32 index occupies 1/4 of the space of an Rc on 64 bit. If you're handling millions of them, it's hard to ignore. Ditto using u16 offsets to describe slices into strings I know won't be more than 64k. Again, it's a 4 fold saving on 64 bit.