Compile-time deadlock prevention very, very quickly begins butting up against Rice's theorem, unless you do something silly like having channels be the only way for threads to communicate. Even then, deadlock conditions are still perfectly possible and very common.
You mean channels like Erlang-style message passing? Where the send is async, and the receiver can pick things out of the queue out-of-order? That is indeed hard to deadlock. It's easy to get other pathological behavior out of them (endlessly-backing-up messages being the one I hit with some frequency) but deadlocks are hard. I think they're doable, but it takes work.
Deadlocking Go-style synchronous channels isn't hard. In practice they're practical to use because they're not particularly hard to not deadlock, either, but I can certainly deadlock them in code if I tried. But I'd be using patterns I'd normally be suspicious of.
(By contrast, conventional mutexes are hard to use without deadlocking, because as soon as you have more than one you have troubles. I use mutexes a lot in Go, but my rule is never take more than one at a time. As soon as you are tempted, do something else. IMHO, the conclusion from the 1990s and early 2000s is wrong... it is not that multithreading in general is impossibly hard, it is that multithreading with multiple mutexes is impossibly hard. If you stay away from that, rather than "impossibly hard" it is merely a challenge, but one humans can rise to meet. I think there's an unjustified residual fear of multithreading to this day that stems from this misunderstanding. And I mean "threads" just as multiple independent simultaneous execution, without regard to any particular technology used to implement them.)
So does “Compile time memory safety”. The way Rust does it is by restricting the valid program to a much narrower set than valid C programs (at least in safe Rust). We may as well find a way to make a programming language that will guarantee zero deadlocks at compile time without being too restrictive, in the same fashion the “aliasing XOR mutable” solved the memory safety challenge. Maybe not, but nobody knows.
That language will need to be built around this limited set of programs though, and is really unlikely to be retrofitted in Rust, like C++ can't realistically add a borrow checker at this point.