I think Rust would be fine for application code if it kept the borrow checker, but had greater allowance for dynamically-sized variables, or even garbage collection. The reason calling things through an interface is so tough in Rust is because doing so requires having a pointer to a value of unknown size, which involves either heap allocation or alloca(), neither of which are very happy in Rust. Many of the other things I complained about are also downstream of this decision. Affine types are useful both in high-level state management as well as in low-level memory management. But it's Rust's focus on static memory layout that really cements it as a low-level systems language, not its inclusion of borrowing.
Way back as an undergrad in 2011, I contributed to Plaid, a JVM language whose main feature is based on affine and linear types. I'm one of the very few people in the world who knew what borrowing is before Rust had it. So I know first-hand that borrow-checking is perfectly compatible with garbage collection.
Exactly, and that is why after Rust's break into mainstream, several garbage collected languages are trying to mix advanced type systems with their approach to garbage collection (GC, RC, a mix of both, whatever).
This is also not strange for those in the Rust community with type systems experience, hence the Roadmap 2026 proposals for a more ergonomic experience.
Thus we have Linear Haskell, Swift 6 ownership, D ownership, Koka, Hylo, Chapel, OxCaml, Scala Capabilities, Ada/SPARK proofs, Idris, F*, Dafny,....