With something like the slotmap, you store a generation counter, so you can't accidentally use something that has been freed and recreated.
It also checks that the slot you are trying to get is occupied, and if it's not it won't let you access it. It actually is forced to check that the slot is occupied because the slot is an enum with vacant and occupied variants, and the vacant variant doesn't have a value to get in the first place. In rust you can't read a data out of an enum without checking the variant first.
With these two restrictions, you can't use stale keys, you can't UAF, and you can't read junk data at all, it's enforced by the type system and the runtime checks.
You can still have keys that are invalid, but the slotmap's "get" method returns an option type, and invalid keys cause it to return "None".
So in practice, you will end up panicking if your keys become invalid (the index operator panics when the return value is "None"), or you will explicitly handle the "None" case and do whatever you want to do.
All of this only applies to this specific data structure though, and the checks do have some performance cost.