All compilers do anyways is translate from one language specification to another. There's nothing magical about Rust or any specific architecture target. The compiler of a "memory safe" language like Rust could easily output assembly with severe issues in the presence of a compiler bug. There's no difference between compiling to assembly vs. C in that regard.
For one, signed integer overflow is allowed and well-defined in Rust (the result simply wraps around in release builds), while it's Undefined Behavior in C. This means that the LLVM IR emitted by the Rust compiler for signed integer arithmetic can't be directly translated into the analogous C code, because that would change the semantics of the program. There are ways around this and other issues, but they aren't necessarily simple, efficient, and portable all at once.
You guys seem to be assuming transpiling to C means it must produce C that DTRT on any random C compiler invoked any which way on the other side, where UB is some huge possibility space.
There's nothing preventing it from being some specific invocation of a narrow set of compilers like gcc-only of some specific version range with a set of flags configuring the UB to match what's required. UB doesn't mean non-deterministic, it's simply undefined by the standard and generally defined by the implementation (and often something you can influence w/cli flags).
> You guys seem to be assuming transpiling to C means it must produce C that DTRT on any random C compiler invoked any which way on the other side, where UB is some huge possibility space.
Yes, that's exactly what "translating to C" means – as opposed to "translating to the very specific C-dialect spoken by gcc 10.9.3 with patches X, Y, and Z, running on an AMD Zen 4 under Debian 12.1 with glibc 2.38, invoked with flags -O0 -g1 -no-X -with-Y -foo -blah -blub...", and may the gods have mercy if you change any of this!
The gigantic difference is that assembly language has extremely simple semantics, while C has very complex semantics. Similarly, assembler output is quite predictable, while C compilers are anything but. So the level of match between the Rust code and the machine code you'll get from a Rust-to-assembly compiler will be much, much easier to understand than the match you'll get between the Rust code and the machine code produced by a C compiler compiling C code output by a Rust-to-C transpiler.