Recently I came across Bjarne Stroustrup's often-cited list of design criteria for C++ again, and I thought it'd be interesting to compare it with my take on the design of Rust. Since Rust is meant to be used in many of the same scenarios as C++ is today, the design goals overlap, but Rust has a different focus that led to different choices. Note that this is my take only and not an official decree as to the design of the language by any means.
C++ is designed to be a statically typed, general-purpose language that is as efficient and portable as C.
Rust is designed to be a statically-typed, general-purpose language that is designed to be as efficient and portable as idiomatic C++, without sacrificing safety.
It's impossible to be "as fast as C" in all cases while remaining safe. As Dave Herman put it, "competing with C++ when you're safe is fighting with one arm tied behind your back". C++ allows all sorts of low-level tricks, mostly involving circumventing the type system, that offer practically unlimited avenues for optimization. In practice, though, C++ programmers restrict themselves to a few tools for the vast majority of the code they write, including stack-allocated variables owned by one function and passed by alias, uniquely owned objects (often used with auto_ptr or the C++0x unique_ptr), and reference counting via shared_ptr or COM. One of the goals of Rust's type system is to support these patterns exactly as C++ does, but to enforce their safe usage. In this way, the goal is to be competitive with the vast majority of idiomatic C++ in performance, while remaining memory-safe.
C++ is designed to directly and comprehensively support multiple programming styles (procedural programming, data abstraction, object-oriented programming, and generic programming).
C++ is designed to give the programmer choice, even if this makes it possible for the programmer to choose incorrectly.
Rust is designed to give the programmer choice, but to guide the programmer to the best choice. You can use a mutable data structure in Rust, but you have to specify that in the type declaration, and you lose the ability to send such data over channels. You can use dynamic assertions throughout your code, but you cut down on check calls by performing the assertions as early as possible and propagating the constraints down with predicates. You can use unsafe code, but you have to mark the functions using it as unsafe and mark the associated modules as unsafe in the .rc file. Rust isn't intended to be a "bondage-and-discipline" language, because writing code in the recommended style is designed to be as straightforward and friendly as possible, but it is designed to make the programmer aware of aspects of the program that could have a negative impact on safety, performance, or correctness.
C++ is designed to be as compatible with C as possible, therefore providing a smooth transition from C.
Rust is designed to be as compatible with external C code as possible, therefore providing a smooth transition from C. The runtime features a separate C stack that's very quick (8 instructions) to switch to, and destructors allow C resources to be managed like Rust resources. The source language is obviously incompatible with C, but every language needs a good foreign function interface (FFI) to survive. We're already making heavy use of the FFI in the production compiler to interface to LLVM.
C++ avoids features that are platform specific or not general purpose.
Rust attempts to be as portable as possible, but we aren't particularly conservative regarding the standard library. Instead, the goal is to adopt a "batteries included" model à la Python. We diverge significantly from C++ here; we don't want different programs and libraries inventing things like vectors and hash maps.
C++ does not incur overhead for features that are not used (the "zero-overhead principle").
Rust incurs minimal overhead for features that aren't used. "Zero overhead" is too restrictive in practice, as, taken literally, it forbids features like garbage collection. Rather than aiming for zero overhead, I hope to achieve two goals: first, to make the runtime system simple enough that programmers aren't surprised by its behavior; and second, to make the system conservative enough that most software projects use most of the features anyway. Most commonly in large C++ projects, the "zero-overhead principle" is important with respect to two features: exceptions and runtime type information (RTTI). In Rust, exceptions don't exist (we need stack unwinding, but it's simpler than that of C++), and runtime type information does in fact conform to the zero-overhead principle (although runtime type information will be frequently used in practice due to the standard library's implementation of collections).
C++ is designed to function without a sophisticated programming environment.
Rust is also designed to function without a sophisticated programming environment. Rust crates are self-contained modules in the operating system's native format. There are no runtimes for end users to download beyond a small rustrt.dll runtime and the standard library.
Ultimately, Rust and C++ have more in common than not, but the few different design decisions buy us radically different safety, concurrency, and (we hope!) usability properties.