I write C and C++ for a living, and the reason I prefer Rust to them is definitely not memory safety, that's just a nice plus.

I think that lots of C/C++ developers have never thought for long about how you end up having to care about the same things in C and C++ too.
In C++, you have to think about exception safety, lifetimes and move semantics when you write your code; you have to know if a variable is moveable, if it is worth it to do so, when and by whom it will be destroyed, etc. If you start writing modern and sane C++, you just realise that lots of the patterns you find yourself using are all things Rust already does automatically enforces for you at the language level.

Meanwhile, often people forget that while C just does not care about what you do with memory, you still _must_ remember that objects still have lifetimes, memory still has ownership; the main difference is that the compiler neither enforces nor checks what you're doing with it. Just like in Rust and C++ you must know if a certain resource is yours or not, and you need to be actively aware of it and manage it properly by clearly documenting how it should be managed and where you expect it to change ownership.

I cannot count how many times I saw C libraries forcing you to use reference-counted objects on the heap just to get out of the messy they used pointers. That is, lots of people find that some of their code references random objects in unsound places without any regard about ownership, and then they get need to find a way around it; refcounting is often the easiest solution. And don't get me started about people managing objects like this:

struct obj;

struct obj* obj_new();
void obj_delete(struct obj*);

that is, simply forcing you to use heap allocation using malloc() (rarely, the objects might come from a pool, but it's not that frequent) without considering that you're forcing people to allocate memory (and fragmenting the heap) for short-lived objects that could have well resided on the stack; it also makes a library unusable for those people who might want to use your library on a system that has no heap or has an heterogeneous memory model where not all memory is the same.

I have seen a handful C libraries actually care about allocators, but they are definitely not the norm. This is also the reason why I started using C++ on embedded systems such as the ESP32, where flash is relatively abundant (it gets up to 16 MB in some configurations) but internal, on chip ram is still scarce for lots of advanced use cases (~512K) and you need to rely on SPI-connected RAM to actually get work done. C++ libraries that use allocators can be used on such systems without any issue, by simply writing your own allocator; Rust still has not such a nice allocator system in place, but at least it allows you to use the stack and return almost everything by value.

In the end, my point of view is that switching from C or C++ to Rust should not feel like you're radically changing the way you code regarding ownership and memory management, because it's orthogonal to the language; it's something you that always needs to be a crucial point in the code you design. In my experience I learnt that 99% of the time when you feel that Rust is hindering your design it's because your design is either unsound or depends on trusting safety assumptions that are enforced outside of your program (i.e. the OS is guaranteeing this, or this is not physically possible).

Rust will always guarantee safety as long as the postulates it lies on hold, but you should not expect it to make a potentially unsafe C library 100% sound because the language can only go as far ahead as ensuring the code you wrote in it is doing exactly what you've said it should do, and nothing more.

Lots of C libraries are often based on an assumption of trust. They just assume that some things will always happen in a certain way, or that certain events are not likely o serious enough to justify wasting time on writing code to check them. This is, I think, the reason some things can't be directly model on top of Rust, because Rust has been made explicitly to force you to eliminate the occurrence of certain errors, so you either have to implement yourself boilerplate code to guarantee your library behaves like Rust wants it to behave, or you accept the need of writing unsafe code.