Is unsafe Rust worse than C?

The question from the title slightly misses the point. Naively replacing C code 1:1 with unsafe Rust code is possible (and can even be automated with c2rust), but leaving it at that is a wrong way to use Rust, and it just gives you a "worse C".

Rust's requirements for unsafe code are similar to C's undefined behavior. Some requirements are more relaxed (there's no TBAA), some are stricter (mutable aliasing and immutability are stronger than in C).

But the point of Rust's unsafe is to build safe abstractions around it.

The unsafe part may be as hard or even trickier than in C, but it's clearly marked, contained, and once it's done and tested, the compiler ensures the safe API is used safely.

Rust's Vec uses unsafe, but the safe public API is as foolproof as lists in Python. You can't do that in C. In C, you can implement a good Vec and give it an API that is possible to use safely, but in C you can't give it an API that is impossible to misuse to cause UB, with zero runtime overhead.

So Rust's unsafe is just as bad or worse than C, but the huge benefit is you can write 99% less of it, which makes writing, testing and fuzzing of the unsafe parts much more tractable.

If memory safety bugs were Waldo (Wally): finding them in C programs is a "Where's Waldo?" game, and Rust's unsafe simplifies it to "Is this Waldo?"