# Rust Design Principles
nikomatsakis
---
Rust has always had *slogans*...
----

----

----

----

----
Each slogan captured some aspect of our design
---
We've also had our share of fearsome debates...
----

---

**482 comments!**
---
How can we capture the tradeoffs we've developed?
----
Rust Design Principles is an attempt to do that.
----
Grew out of the [design tenets](https://rust-lang.github.io/wg-async-foundations/vision/tenets.html) from the [async vision doc](https://rust-lang.github.io/wg-async-foundations/)
---
### Six principles
* Safety first
* You *can* have nice things
* Transparent and predictable
* Orthogonal, composable, and extensible
* Expose all system capabilities
* Hard to misuse
---
### Safety first
Safe Rust code is memory safe, data-race free, and free of other kinds of [undefined behavior](https://en.wikipedia.org/wiki/Undefined_behavior). Unsafe Rust code is meant to be well-encapsulated and exposed via a safe interface.
----
### Example: Ownership and borrowing
----
### Where we compromise on this
We don't. We'll even break stability.
---
### You *can* have nice things
The high-level features in Rust are scalable, performant, and full-featured. We don't expect our users to "drop down" to low-level code, except in extreme cases.
----
### Example: Iterators
```rust
values.iter().map(|x| x * 2).sum()
```
* In Rust (or C++), as fast as a for loop
* Or faster! No bounds checks.
* In many other languages:
* Costs performance
----
### More examples
* Iterators, async fn, etc
* Closures that desugar to struct fields
* Autoderef and `.` syntax
* Operator overloading
----
### Where do we give up on "nice things"?
* Bounds checks:
* Using `vec[i]` in C is faster, but we value safety more.
* Unsafe code to skip indexing checks ensures we still "expose all capabilities"
---
### Transparent and predictable
Rust avoids hidden control flow, silent memory allocation, or complex built-in operations. You don't need a lot of context to figure out what some Rust code will do when it runs or what machine code it will generate.
----
### Example: No garbage collector
----
### Example: Copy vs Clone
```rust
some_function(y);
```
* In Rust, always does a memcpy
* In C++, could invoke a copy constructor
* Arguably, not entirely true to the spirit of principle
----
### More examples
* Unwind, `?` operator
* Exceptions make it harder to reason about control flow
* No implicit allocation
* Leads to unexpected performance cliffs
* The "Predictability" rules of the API guidelines
* e.g., Smart pointers do not add inherent methods
----
### Where do we give up on transparency?
* To be used, must be "nice enough".
* Optimizations often unpredictable:
* e.g., reordering struct fields and enums to enable composition
---
### Orthogonal, composable, extensible
Rust encourages components that can be reused in many ways and in many environments. Rust programs work across mainstream architectures and operating systems by default. We encourage exploration, but we also recognize that exploration sometimes requires standardization.
----
### Example: cargo, crates.io
----
### Example: Coherence
* Coherence exists to ensure that any two crates can be combined
----
### Example: Portability
----
### More examples
* Minimal standard library
* Global allocator, which permits convenient interop
* Language constructs like `usize` meant to ensure code builds on both 32- and 64-bit architectures
----
### Where we compromise on this
* No garbage collector
* Auto traits and auto trait leakage:
* prefer "nice things" over stronger semver
---
### Expose all system capabilities
Whatever it is you want to do, you should be able to do it in Rust, though it may require jumping through some hoops.
----
### `"C"` vs `"C-unwind"`
----
### SIMD intrinsics
----
### More examples
* Inline assembly
* `OsString`
* `#[repr(C)]`, `extern "C"`, `extern "C-unwind"`
----
### Where we compromise on this
* For "nice things":
* support longjmp, but only in limited cases
* For composition:
* Portable abstractions
* std library exists
---
### Hard to misuse
We take every opportunity to help users detect bugs and errors in their programs.
----
### Example: Exhaustive pattern matching
```rust
match foo {
Some(x) => ...,
}
```
* In Rust, requires a `_` case
* In other languages, would generate an exception
* Hard to know if something was elided on purpose
----
### Example: dead code lints
* Helps catch bugs and half-finished refactorings
* Kind of annoying when you're writing code, though
----
### Other examples
* Overflow checks on math operations
* `assert!` on by default
* `Path::display`
----
### Where we compromise on this
* Overflow checks disabled in release
* Because "nice things" take priority
---
### What now
* Evolving, still a WIP
* Planning to try applying these principles to ongoing design questions
* Would like to hear from other teams on how well they fit (or don't)
* Would like to derive other rules from these
----
### Questions for you
* Something not covered by these principles?
* Not sure about the ordering?
* Have a counterexample?
----
### The principles (again)
* Safety first
* You *can* have nice things
* Transparent and predictable
* Orthogonal, composable, and extensible
* Expose all system capabilities
* Hard to misuse
{"metaMigratedAt":"2023-06-16T02:42:54.015Z","metaMigratedFrom":"YAML","title":"3: Rust design principles","breaks":true,"contributors":"[{\"id\":\"27d8f2ac-a5dc-4ebe-8c31-cc45bcd8447e\",\"add\":10932,\"del\":5069}]"}