Skip to content
HN On Hacker News ↗

Rust Style Guide

▲ 394 points • 257 comments • by kaycebasques • 2w ago • HN discussion ↗

Pangram verdict · v3.3

We believe that this entire text is human-written.

0 %

AI likelihood · overall

Human
100% human-written 0% AI-generated
SEGMENTS · HUMAN 1 of 1
SEGMENTS · AI 0 of 1
WORD COUNT 1,553
PEAK AI % 0% · §1
Analyzed
Oct 21
backend: pangram/v3.3
Segments scanned
1 windows
avg 1553 words each
Distribution
100 / 0%
human / AI fraction
Verdict
Human
Pangram v3.3

Article text · 1,553 words · 1 segments analyzed

Human AI-generated
§1 Human · 0%

Google Style Guides Rust Style Guide Background Scope Goals of the style guide Follow public Rust style rules Apply API design rules in context Code organization Prefer small crates [chrome] Use flat file layout for rust_library sources [chrome] Name source files and leaf modules after the primary user-defined item Don’t implement APIs in non-leaf modules Don’t use glob imports A use statement should import items from one module Prefer locally-scoped trait imports Qualify calls to top-level functions with a module name Type names should be imported and used unqualified Use the appropriate import mechanism [chrome] Code formatting and aesthetics Use the appropriate formatting tool Opting out of automatic formatting Ownership and borrowing Avoid Rc and Arc Prefer borrows over deep copies Function inputs and outputs Accept flexible references for immutable data Iterators vs. owned collections in return types Iterators vs. slices in function parameters Accepting Into Prefer enum over bool in APIs Reporting errors Types Newtypes versus type aliases Prefer named fields over tuples and non-newtype tuple structs Traits Add trait implementations when they become necessary Implement known standard library traits instead of custom methods Use #[derive()] if possible Generics versus dyn Trait When to define a trait versus an inherent implementation Extension traits Specific guidance for important traits Pair important From impls with explicit constructor methods Options structs should implement Default Concurrency Handling poison Don’t use async / .await [chrome] Don’t start new threads through the Rust standard library [chrome] Use fuchsia_sync::Mutex [Fuchsia] Macros Naming Naming methods Naming lifetimes Naming generic parameters Naming extension traits Naming initialization functions Avoid abbreviations When and how to write documentation Other Rust features Unsafe code No unstable features Getters and setters More on accessors that accept closures Implement expected API sets together Do not access items marked #[doc(hidden)] that you don’t own Use const functions responsibly Avoid overloading for non-mathematical purposes Apply #[non_exhaustive] to publicly-exposed enums Apply #[non_exhaustive] to public structs with public fields #[must_use] on functions #[must_use] on types Do not run code before main() Implementation concerns Don’t overuse type inference Prefer pattern matching over check-then-unwrap Prefer expect over unwrap Don’t omit patterns on non_exhaustive enums when matching Use context strings to clarify assertions Don’t use iterator combinator chains when direct iteration is clearer Don’t call panic::catch_unwind Prefer format! / write! for concatenation and substitution Use the right per-codebase test framework This document is a style guide for the usage of the Rust programming language at Google. In this context, “style” refers to more than just formatting; it includes guidance on API and implementation design. Rust is used in many places, including google3, Android, ChromeOS, Fuchsia, and Chrome, and we’d like for Rust usage at Google to be consistent both within and across codebases. In addition to bringing consistency to our Rust code, style guidance also helps establish a standard of quality. Background Scope The current scope of authority of the rules outlined in this guide: In Android, Chromium, and other codebases: This style guide has been developed in consultation with other codebases, and they intend to start applying it. These codebases may have their own rules about how strictly this is expected to be applied. Expect more information here as these codebases adopt this guide. Goals of the style guide By and large, we have this document for the same reasons we have a C++ style guide. Most style rules come from one or more of the goals listed below. Style rules should prioritize readability and maintainability over writeability We expect our code to be around for long periods of time, and we consider a little bit of extra effort applied during code writing to be worth it in the long run if the style rule improves readability. Style rules should favor better automation Large-Scale Changes (LSCs) are common at Google, and consistency helps make LSCs easier to carry out. Style rules should be consistent with the wider Rust ecosystem where possible The broader Rust ecosystem already has a pretty good amount of consistency in style, and we should rely on that where possible to reduce surprise and make it less work to learn Google’s Rust style. Style rules should pull their weight Every Rust developer and reviewer at Google has to keep these style rules in mind: as such, we should be careful to include rules that have a tangible benefit. Style rules may help avoid minor style disagreements There are many cases where reasonable people may disagree about a style, and we expect that disagreement to show up often on CLs. Having a style rule helps avoid having to rehash this each time. Rules in this category that do not have other benefits should be kept to a minimum. Follow public Rust style rules Follow the official public Rust style rules to the extent they don’t conflict with this style guide. Rust Style Guide Most code formatting conventions are enforced automatically by rustfmt. Rust API Guidelines A “conflict” would be a case where this style guide suggests a pattern that is discouraged, or counter to the primary encouraged pattern in the Rust style guide. Why does the guidance in this style guide deviate from regular Rust style rules? Most style guides have three goals: consistency, readability, and encouraging good API design. Regardless of the specific choices made, it helps everyone to have these choices made beforehand to limit bikeshedding. This style guide shares those goals, but it also has an additional goal not seen as often: smoothing the way for Large-Scale Changes (LSCs). Large codebases like many of the ones at Google occasionally need to run codebase-spanning refactorings that are assisted by tooling: for this to work well, the code should be something tooling has an easy time working with. Consistency helps for this, but so does having deliberate refactor-friendly patterns. Apply API design rules in context When applying rules that relate to API design, you should distinguish two types of code: Library code Intended for use by other projects (applications or other libraries). Solves a relatively general problem. Application code Intended for use in a single application. Solves a more specific problem. For library code, style guide rules that concern API design are binding. For application code, the rules on API design are a strong recommendation. As you apply them, keep in mind that since application code is written to solve a specific problem, it should generally favor simplicity and directness over broad reusability. Avoid premature generalization and abstraction; focus on what is required to meet the immediate need. Code organization Terminology: A crate is a unit of compilation. A crate always contains a nameless Rust module, the “root module”. A Rust module is a unit of code organization within a crate. Rust modules are used to control visibility of names. Modules can be nested. They can also be used to split code across files and directories. The following sections convey that in Chromium, it is preferable to not make use of all possibilities of splitting modules across files. Prefer small crates [chrome] Prefer small crates in Chromium; ideally, but not necessarily, a single file (focusing on one abstraction). If your code can be split up into small crates, do so. A crate corresponds to a single rust_static_library (chrome) rule, which may contain one or more .rs files. Additional considerations: The root module is allowed to re-export public APIs from leaf submodules, making submodules an implementation detail of the crate (as users don’t need to know about these submodules). This rule about small crates applies equally to crates with and without submodules. First, evaluate whether the APIs need to be in the same crate, and only then consider whether submodules could help organize the APIs. If you decide to use submodules, follow the expected file structure. Larger crates are allowed when trait impl coherence rules force multiple types and traits to be included in one library, or if you’re building a large foundational library. Rationale Fine-grained library targets are recommended in Chromium due to the massive size of our codebase, non-local effects of adding dependencies in the build graph, and to improve performance of parallel compilation and build caching. Use flat file layout for rust_library sources [chrome] In Chromium .rs source files belonging to one rust_library (one Rust crate) must reside in a single directory. Don’t use subdirectories to organize files that belong to a single crate. If organizing one crate’s files into subdirectories feels necessary, this is a strong indication that the crate has grown too large and should be split. This crate layout is intentionally different from the conventional Cargo directory structure typically used in open-source repositories. Exception: Rust code in //third_party that is also built with Cargo should follow the conventional Cargo directory structure. Rationale The approach in Chromium is driven by the following factors: Based on the preference for small crates, most rust_library targets will only contain one source file. Because of the above point, creating a directory for each rust_library target would result in most directories containing only one source file. Multi-file rust_library targets should not create dedicated directories for submodules either; this ensures a consistent approach. Name source files and leaf modules after the primary user-defined item When a leaf module has a primary user-defined item (e.g., Foo), the module should be named after that item (e.g., mod foo and foo.rs). Leaf modules that are