Everything you ever wanted to know about Rust...

...but didn't know where to ask. Rust is designed to be a flexible language, one that will let you do just about anything. This is a good thing. But it also means that learning to use Rust means developing a sense for which features and patterns to use where. This book is designed to help you "shortcircuit" that process by collecting expert answers and advice to common questions that come up when building Rust software.

Want to help improve this guide?

This book is community maintained and we need your help to make it better!

  • If you have questions you'd like to see answered, open an issue on the github repo.
  • If you'd like to answer a new question, or improve an answer, open a pull request.

When to use Rust?

Like most general programming languages, Rust can be used for virtually any kind of project. This can make it difficult to know when to use it! Here are a few criteria.

Rust is designed for programs and projects where

  • performance and/or memory usage;
  • reliability; and
  • long-term maintaince

are top considerations. If your program fits these criteria, then Rust would probably be a good choice.

What are great domains for Rust?

Domains where Rust can be a particularly good fit:

  • Systems programing, low-level development, or embedded systems;
  • Network systems, where Rust offers "predictably low" tail latency, low memory usage, and high reliability;
  • Developer tools and CLI applications, where Rust's can snappy response time and getting the right answer is super important.

When not to use Rust?

When there's a better option, of course! Here are some reasons you might prefer not to use Rust

  • you want to make use of a library or framework in another language;
  • you're targeting an environment or community where the other language is the default choice (e.g., Swift for iOS);
  • rapid iteration is more important than getting the details right;
  • you want to learn something else or you just really like the other language. That's cool too.

When to use references (&T)

References are Rust's superpower -- but if they are used too much, they can also be a super pain in the neck.

How many lifetime parameters?

When not to borrow

Vector and indices

The "vector and index" pattern is a very simple way to model virtually any kind of data structure, particularly those with cycles or other shapes that don't fit Rust's .

Short description

  • For each node, create two types
    • A struct Node(usize) representing references to a node via a vector index
    • A struct NodeData { ..., link: Node } representing the data in a node
  • Store your graph struct Graph { nodes: Vec<NodeData> } with
    • accessors for node data
      • fn edge(&self, node: Node) -> &NodeData { &self.nodes[node.0] }
      • fn edge_mut(&mut self, node: Node) -> &mut NodeData { &mut self.nodes[node.0] }

When it works well

  • When you mainly add things to your graph, not remove them
  • When you want to share your graph in a read-only fashion across threads, but be able to mutate it when not shared

When it works less well

  • You have a long-lived graph where you will be adding and removing nodes over time
    • Because

Alternatives and ways to make it safer

References

Crates

Real-world examples of this pattern in use

Blog posts

Ref-counting

When to use enums?

Usually. :)

Designing traits

Generics vs associated types

Handling errors

When to use async I/O vs sync I/O?

Choosing and configuring your executor

Work stealing

Thread per core

Choosing and configuring your executor

Work stealing

Thread per core

Intrusive linked list

TBD