How is an interpreter expressed in Rust- what parts can be safe and what must be unsafe? For example the GC conceptually has access to every object at every allocation point, how does that work with the borrow checker?
Depends on the details. If you are just doing a classic AST interpreter, no particular focus on speed, there's no need for unsafe code at all, especially if you do what Python does and just use refcounting, though I have not implemented a cycle detector personally...