Rust spent its entire innovation budget on zero-cost memory safety! Basically, instead of you tracking lifetimes (like in C with malloc/free) or the runtime tracking lifetimes (like in a GC'd language), Rust lets the compiler do this with a 'borrowing' system.
Borrowing in Rust means objects exist in two states: owned (which get dropped when they fall out of scope, like in C++), and borrowed, which means some other scope owns the object and we only have a reference to it. The compiler verifies that a borrow cannot outlive the actual object, so it statically prevents use-after-free errors.
Rust also has a distinction between constant and mutable values, and statically checks that any mutable references are exclusive, and that immutable references are only shared with other immutable references. With this it helps prevent race conditions or other such mistakes.
Finally, Rust also actually has smart pointers in case you truly don't know when an object won't be needed anymore, although the names are a bit different than in C++; there's Rc/Arc for reference counting (like shared_ptr), Box for owning pointers (like unique_ptr?), and RefCell, that's like a runtime borrow checker.
Apart from these features that prevent use-after-free and aliasing, Rust also has a feature called 'unsafe' with which you can bypass all these and e.g. work with raw pointers. Unsafe is generally used sparingly (and if not, attracts a lot of criticism, like happened to actix-web), and the safe abstractions on top also provide more pedestrian safety features like bounds checking. You can skip bounds checking on e.g. a Vec, but doing so actually requires you to drop into unsafe yourself, since the get_unchecked function is marked unsafe in the stdlib.
Small interesting side note: I'm pretty sure Rust is actually doing very little new things, PL-design wise. It's more of a realization of theory that has been around for years if not decades.