|  | # Rust Rubric | 
|  |  | 
|  | [TOC] | 
|  |  | 
|  | This document lists conventions to follow when writing Rust in the Fuchsia Source Tree. These conventions are a combination of best practices, project preferences, and some choices made for the sake of consistency. | 
|  |  | 
|  | <!-- TODO add collapsible <details> sections around guideline bodies --> | 
|  | <!-- TODO inline text of upstream guidelines once fuchsia-specific guidelines settle --> | 
|  |  | 
|  | ## Guidelines | 
|  |  | 
|  | ### Naming | 
|  |  | 
|  | #### Casing conforms to Rust idioms | 
|  | See [C-CASE](https://rust-lang.github.io/api-guidelines/naming.html#c-case). | 
|  |  | 
|  | #### Ad-hoc conversions follow `as_`, `to_`, `into_` conventions | 
|  | See [C-CONV](https://rust-lang.github.io/api-guidelines/naming.html#c-conv). | 
|  |  | 
|  | #### Getter names follow Rust convention | 
|  |  | 
|  | With a few exceptions, the `get_` prefix is not used for getters in Rust code. | 
|  |  | 
|  | See [C-GETTER](https://rust-lang.github.io/api-guidelines/naming.html#c-getter). | 
|  |  | 
|  | #### Methods on collections that produce iterators follow `iter`, `iter_mut`, `into_iter` | 
|  | See [C-ITER](https://rust-lang.github.io/api-guidelines/naming.html#c-iter). | 
|  |  | 
|  | #### Iterator type names match the methods that produce them | 
|  | See [C-ITER-TY](https://rust-lang.github.io/api-guidelines/naming.html#c-iter-ty). | 
|  |  | 
|  | #### Names use a consistent word order | 
|  | See [C-WORD-ORDER](https://rust-lang.github.io/api-guidelines/naming.html#c-word-order). | 
|  |  | 
|  |  | 
|  |  | 
|  | ### Interoperability | 
|  |  | 
|  | #### Types eagerly implement common traits | 
|  | `Copy`, `Clone`, `Eq`, `PartialEq`, `Ord`, `PartialOrd`, `Hash`, `Debug`, `Display`, `Default` should all be implemented when appropriate. | 
|  |  | 
|  | See [C-COMMON-TRAITS](https://rust-lang.github.io/api-guidelines/interoperability.html#c-common-traits). | 
|  |  | 
|  | #### Conversions use the standard traits `From`, `AsRef`, `AsMut` | 
|  | See [C-CONV-TRAITS](https://rust-lang.github.io/api-guidelines/interoperability.html#c-conv-traits). | 
|  |  | 
|  | #### Collections implement `FromIterator` and `Extend` | 
|  | See [C-COLLECT](https://rust-lang.github.io/api-guidelines/interoperability.html#c-collect). | 
|  |  | 
|  | #### Data structures implement Serde's `Serialize`, `Deserialize` | 
|  | See [C-SERDE](https://rust-lang.github.io/api-guidelines/interoperability.html#c-serde). | 
|  |  | 
|  | #### Types are `Send` and `Sync` where possible | 
|  | See [C-SEND-SYNC](https://rust-lang.github.io/api-guidelines/interoperability.html#c-send-sync). | 
|  |  | 
|  | #### Error types are meaningful and well-behaved | 
|  | See [C-GOOD-ERR](https://rust-lang.github.io/api-guidelines/interoperability.html#c-good-err). | 
|  |  | 
|  | #### Binary number types provide `Hex`, `Octal`, `Binary` formatting | 
|  | See [C-NUM-FMT](https://rust-lang.github.io/api-guidelines/interoperability.html#c-num-fmt). | 
|  |  | 
|  | #### Generic reader/writer functions take `R: Read` and `W: Write` by value | 
|  | See [C-RW-VALUE](https://rust-lang.github.io/api-guidelines/interoperability.html#c-rw-value). | 
|  |  | 
|  |  | 
|  |  | 
|  | ### Macros | 
|  |  | 
|  | #### Input syntax is evocative of the output | 
|  | See [C-EVOCATIVE](https://rust-lang.github.io/api-guidelines/macros.html#c-evocative). | 
|  |  | 
|  | #### Macros compose well with attributes | 
|  | See [C-MACRO-ATTR](https://rust-lang.github.io/api-guidelines/macros.html#c-macro-attr). | 
|  |  | 
|  | #### Item macros work anywhere that items are allowed | 
|  | See [C-ANYWHERE](https://rust-lang.github.io/api-guidelines/macros.html#c-anywhere). | 
|  |  | 
|  | #### Item macros support visibility specifiers | 
|  | See [C-MACRO-VIS](https://rust-lang.github.io/api-guidelines/macros.html#c-macro-vis). | 
|  |  | 
|  | #### Type fragments are flexible | 
|  | See [C-MACRO-TY](https://rust-lang.github.io/api-guidelines/macros.html#c-macro-ty). | 
|  |  | 
|  |  | 
|  |  | 
|  | ### Documentation | 
|  |  | 
|  | #### Crate level docs are thorough and include examples | 
|  | See [C-CRATE-DOC](https://rust-lang.github.io/api-guidelines/documentation.html#c-crate-doc). | 
|  |  | 
|  | #### All items have a rustdoc example | 
|  | See [C-EXAMPLE](https://rust-lang.github.io/api-guidelines/documentation.html#c-example). | 
|  |  | 
|  | > Note: this guideline is not reasonable to enforce for targets which build on Fuchsia until | 
|  | > doctests are supported on Fuchsia targets. See | 
|  | > [#38215](https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=38215). | 
|  |  | 
|  | #### Examples use `?`, not `try!`, not `unwrap` | 
|  | See [C-QUESTION-MARK](https://rust-lang.github.io/api-guidelines/documentation.html#c-question-mark). | 
|  |  | 
|  | <!-- TODO how does this interact with avoiding ? in tests? --> | 
|  |  | 
|  | #### Function docs include error, panic, and safety considerations | 
|  | See [C-FAILURE](https://rust-lang.github.io/api-guidelines/documentation.html#c-failure). | 
|  |  | 
|  | #### Prose contains hyperlinks to relevant things | 
|  | See [C-LINK](https://rust-lang.github.io/api-guidelines/documentation.html#c-link). | 
|  |  | 
|  | #### Rustdoc does not show unhelpful implementation details | 
|  | See [C-HIDDEN](https://rust-lang.github.io/api-guidelines/documentation.html#c-hidden). | 
|  |  | 
|  | #### Every `unsafe` block has an accompanying justification | 
|  |  | 
|  | > This guideline pertains only to safety documentation when performing unsafe operations. | 
|  | > | 
|  | > See [C-FAILURE](https://rust-lang.github.io/api-guidelines/documentation.html#c-failure) for | 
|  | > guidelines on documenting function safety requirements. | 
|  |  | 
|  | Safety justifications should begin with `// SAFETY: ` and explain why the unsafe block is sound. | 
|  |  | 
|  | *DO* | 
|  |  | 
|  | ```rust | 
|  | // SAFETY: <why this unsafe operation's safety requirements are met> | 
|  | ``` | 
|  |  | 
|  | *DON'T* | 
|  |  | 
|  | ```rust | 
|  | // Safety: <...> | 
|  | // [SAFETY] <...> | 
|  | // <...> | 
|  | // SAFETY: Trust me. | 
|  | ``` | 
|  |  | 
|  | Unsafe code should explain why the unsafe block is necessary and why the code contained within the | 
|  | block is sound. If there are safe alternatives which may appear suitable but cannot be used, the | 
|  | reason why they cannot be used should be documented as well. | 
|  |  | 
|  | *DO* | 
|  |  | 
|  | ```rust | 
|  | // SAFETY: The `bytes` returned from our string builder are guaranteed to be | 
|  | // valid UTF-8. We used to call `from_utf8`, but this caused performance issues | 
|  | // with large inputs. | 
|  | let s = unsafe { String::from_utf8_unchecked(bytes) }; | 
|  | ``` | 
|  |  | 
|  | *DON'T* | 
|  |  | 
|  | ```rust | 
|  | // SAFETY: We shouldn't have to validate `bytes`, and the safe version is slow. | 
|  | let s = unsafe { String::from_utf8_unchecked(bytes) }; | 
|  | ``` | 
|  |  | 
|  | Justifications should directly address the requirements for the operation. It's okay to summarize as | 
|  | long as all of the requirements are addressed. | 
|  |  | 
|  | *DO* | 
|  |  | 
|  | ```rust | 
|  | // SAFETY: The caller has guaranteed that `ptr` is valid for reads, properly | 
|  | // aligned, and points to a properly-initialized `T`. | 
|  | unsafe { | 
|  | let x = ptr.read(); | 
|  | } | 
|  | ``` | 
|  |  | 
|  | *DO* | 
|  |  | 
|  | ```rust | 
|  | // SAFETY: The caller has guaranteed that `ptr` points to a valid `T`. | 
|  | unsafe { | 
|  | let x = ptr.read(); | 
|  | } | 
|  | ``` | 
|  |  | 
|  | *DON'T* | 
|  |  | 
|  | ```rust | 
|  | // SAFETY: `ptr` is safe to read. | 
|  | unsafe { | 
|  | let x = ptr.read(); | 
|  | } | 
|  | ``` | 
|  |  | 
|  | Safety justifications should address *why* an operation is justified, not just *that* an operation | 
|  | is justified. | 
|  |  | 
|  | *DO* | 
|  |  | 
|  | ```rust | 
|  | const BUFFER_LEN: usize = 1024; | 
|  | fn partially_init(n: usize) -> MaybeUninit<[i32; BUFFER_LEN]> { | 
|  | // These asserts ensure our safety conditions are met later on | 
|  | const _: () = assert!(BUFFER_LEN <= 1024); | 
|  | assert!(n < BUFFER_LEN); | 
|  |  | 
|  | let mut buffer = MaybeUninit::<[i32; BUFFER_LEN]>::uninit(); | 
|  | let ptr = buffer.as_mut_ptr().cast::<i32>(); | 
|  | for i in 0..n { | 
|  | // SAFETY: | 
|  | // - `ptr` points to the first `i32` of `buffer`. | 
|  | // - `buffer` has space for BUFFER_LEN elements and we asserted that | 
|  | //   `n < BUFFER_LEN`. | 
|  | // - We asserted that `BUFFER_LEN <= 1024`, so `size_of::<i32>() * i` | 
|  | //   is at most 4096 which is less than `isize::MAX` and `usize::MAX`. | 
|  | let element = unsafe { &mut *ptr.add(i) }; | 
|  | *element = i as i32; | 
|  | } | 
|  |  | 
|  | buffer | 
|  | } | 
|  | ``` | 
|  |  | 
|  | *DON'T* | 
|  |  | 
|  | ```rust | 
|  | const BUFFER_LEN: usize = 1024; | 
|  | fn partially_init(n: usize) -> MaybeUninit<[i32; BUFFER_LEN]> { | 
|  | // Why are these asserts here? | 
|  | const _: () = assert!(BUFFER_LEN <= 1024); | 
|  | assert!(n < BUFFER_LEN); | 
|  |  | 
|  | let mut buffer = MaybeUninit::<[i32; BUFFER_LEN]>::uninit(); | 
|  | let ptr = buffer.as_mut_ptr().cast::<i32>(); | 
|  | for i in 0..n { | 
|  | // SAFETY: | 
|  | // - `ptr` is in bounds or one byte past the end of an allocated object. | 
|  | // - `ptr + i` is also in bounds. | 
|  | // - The computed offset, in bytes, doesn't overflow an `isize`. | 
|  | // - The offset being in bounds does not rely on "wrapping around" the | 
|  | //   address space. | 
|  | let element = unsafe { &mut*ptr.add(i) }; | 
|  | *element = i as i32; | 
|  | } | 
|  |  | 
|  | buffer | 
|  | } | 
|  | ``` | 
|  |  | 
|  | #### Unsafe traits are documented, unsafe trait impls are justified | 
|  |  | 
|  | Unsafe traits should be documented according to the same guidelines as unsafe functions. | 
|  |  | 
|  | Unsafe trait definitions should document safety considerations (See [C-FAILURE][c-failure]), and | 
|  | unsafe trait implementations should be justified (See | 
|  | ["Every `unsafe` block has an accompanying justification"][every-unsafe-block])) | 
|  |  | 
|  | [c-failure]: https://rust-lang.github.io/api-guidelines/documentation.html#c-failure | 
|  | [every-unsafe-block]: #every-unsafe-block-has-an-accompanying-justification | 
|  |  | 
|  | *DO* | 
|  |  | 
|  | ```rust | 
|  | /// A labeler that always returns unique labels. | 
|  | /// | 
|  | /// # Safety | 
|  | /// | 
|  | /// Every time `create_unique_label()` is called on the same labeler, it must | 
|  | /// return a distinct `u32`. | 
|  | unsafe trait UniqueLabeler { | 
|  | /// Returns a new unique label. | 
|  | fn create_unique_label(&mut self) -> u32; | 
|  | } | 
|  |  | 
|  | struct SequentialLabeler { | 
|  | next: Option<u32>, | 
|  | } | 
|  |  | 
|  | // SAFETY: `create_unique_label()` will always return the next sequential label | 
|  | // or panic if all available labels are exhausted. | 
|  | unsafe impl UniqueLabeler for SequentialLabeler { | 
|  | fn create_unique_label(&mut self) -> u32 { | 
|  | if let Some(next) = self.next { | 
|  | self.next = (next < u32::MAX).then(|| next + 1); | 
|  | next | 
|  | } else { | 
|  | panic!("sequential unique labels exhausted"); | 
|  | } | 
|  | } | 
|  | } | 
|  | ``` | 
|  |  | 
|  | *DON'T* | 
|  |  | 
|  | ```rust | 
|  | /// A labeler that always returns unique labels. | 
|  | unsafe trait UniqueLabeler { | 
|  | /// Returns a new unique label. | 
|  | fn create_unique_label(&mut self) -> u32; | 
|  | } | 
|  |  | 
|  | struct SequentialLabeler { | 
|  | next: u32, | 
|  | } | 
|  |  | 
|  | unsafe impl UniqueLabeler for SequentialLabeler { | 
|  | fn create_unique_label(&mut self) -> u32 { | 
|  | // This will have correct panicking behavior in debug builds because | 
|  | // integer overflow is trapped. In a release build, this will still | 
|  | // overflow but our labeler will not panic! | 
|  | let result = self.next; | 
|  | next += 1; | 
|  | result | 
|  | } | 
|  | } | 
|  | ``` | 
|  |  | 
|  | #### Unsafe operations are always in an `unsafe` block | 
|  |  | 
|  | > This guideline depends on a change to linting behavior and cannot yet be followed | 
|  | > ([tracking issue](https://fxbug.dev/94323)). Continue to adhere to other guidelines in this | 
|  | > section. | 
|  |  | 
|  | `unsafe` functions are not considered unsafe contexts in Fuchsia. Unsafe operations must always be | 
|  | located inside an `unsafe` block, even if they are in an `unsafe` function body. | 
|  |  | 
|  | *DO* | 
|  |  | 
|  | ```rust | 
|  | unsafe fn clear_slice(ptr: *mut i32, len: usize) { | 
|  | assert!(len.checked_mul(mem::size_of::<i32>()).unwrap() < isize::MAX); | 
|  |  | 
|  | // SAFETY: | 
|  | // - The caller has guaranteed that `ptr` points to `len` consecutive, valid | 
|  | //   i32s and that the data at behind `ptr` is not simultaneously accessed | 
|  | //   through any other pointer. | 
|  | // - We asserted that the total size of the slice is less than isize::MAX. | 
|  | let slice = unsafe { slice::from_raw_parts_mut(ptr, len) }; | 
|  | for x in slice.iter_mut() { | 
|  | *x = 0; | 
|  | } | 
|  | } | 
|  | ``` | 
|  |  | 
|  | *DON'T* | 
|  |  | 
|  | ```rust | 
|  | unsafe fn clear_slice(ptr: *mut i32, len: usize) { | 
|  | // We forgot to assert that the length of the slice is less than isize::MAX! | 
|  | // If we justified our call to from_raw_parts_mut, we would have been much | 
|  | // more likely to remember. | 
|  |  | 
|  | let slice = slice::from_raw_parts_mut(ptr, len); | 
|  | for x in slice.iter_mut() { | 
|  | *x = 0; | 
|  | } | 
|  | } | 
|  | ``` | 
|  |  | 
|  |  | 
|  |  | 
|  | ### Predictability | 
|  |  | 
|  | #### Smart pointers do not add inherent methods | 
|  | See [C-SMART-PTR](https://rust-lang.github.io/api-guidelines/predictability.html#c-smart-ptr). | 
|  |  | 
|  | #### Conversions live on the most specific type involved | 
|  | See [C-CONV-SPECIFIC](https://rust-lang.github.io/api-guidelines/predictability.html#c-conv-specific) | 
|  |  | 
|  | #### Functions with a clear receiver are methods | 
|  | See [C-METHOD](https://rust-lang.github.io/api-guidelines/predictability.html#c-method). | 
|  |  | 
|  | #### Functions do not take out-parameters | 
|  | See [C-NO-OUT](https://rust-lang.github.io/api-guidelines/predictability.html#c-no-out). | 
|  |  | 
|  | #### Operator overloads are unsurprising | 
|  | See [C-OVERLOAD](https://rust-lang.github.io/api-guidelines/predictability.html#c-overload). | 
|  |  | 
|  | #### Only smart pointers implement `Deref` and `DerefMut` | 
|  | See [C-DEREF](https://rust-lang.github.io/api-guidelines/predictability.html#c-deref). | 
|  |  | 
|  | #### Constructors are static, inherent methods | 
|  | See [C-CTOR](https://rust-lang.github.io/api-guidelines/predictability.html#c-ctor). | 
|  |  | 
|  |  | 
|  |  | 
|  | ### Flexibility | 
|  |  | 
|  | #### Functions expose intermediate results to avoid duplicate work | 
|  | See [C-INTERMEDIATE](https://rust-lang.github.io/api-guidelines/flexibility.html#c-intermediate). | 
|  |  | 
|  | #### Caller decides where to copy and place data | 
|  | See [C-CALLER-CONTROL](https://rust-lang.github.io/api-guidelines/flexibility.html#c-caller-control). | 
|  |  | 
|  | #### Functions minimize assumptions about parameters by using generics | 
|  | See [C-GENERIC](https://rust-lang.github.io/api-guidelines/flexibility.html#c-generic). | 
|  |  | 
|  | #### Traits are object-safe if they may be useful as a trait object | 
|  | See [C-OBJECT](https://rust-lang.github.io/api-guidelines/flexibility.html#c-object). | 
|  |  | 
|  |  | 
|  |  | 
|  | ### Type safety | 
|  |  | 
|  | #### Newtypes provide static distinctions | 
|  | See [C-NEWTYPE](https://rust-lang.github.io/api-guidelines/type-safety.html#c-newtype). | 
|  |  | 
|  | #### Arguments convey meaning through types, not `bool` or `Option` | 
|  | See [C-CUSTOM-TYPE](https://rust-lang.github.io/api-guidelines/type-safety.html#c-custom-type). | 
|  |  | 
|  | #### Types for a set of flags are `bitflags`, not enums | 
|  | See [C-BITFLAG](https://rust-lang.github.io/api-guidelines/type-safety.html#c-bitflag). | 
|  |  | 
|  | #### Builders enable construction of complex values | 
|  | See [C-BUILDER](https://rust-lang.github.io/api-guidelines/type-safety.html#c-builder). | 
|  |  | 
|  |  | 
|  |  | 
|  | ### Dependability | 
|  |  | 
|  | #### Functions validate their arguments | 
|  | See [C-VALIDATE](https://rust-lang.github.io/api-guidelines/dependability.html#c-validate). | 
|  |  | 
|  | #### Destructors never fail | 
|  | See [C-DTOR-FAIL](https://rust-lang.github.io/api-guidelines/dependability.html#c-dtor-fail). | 
|  |  | 
|  | #### Destructors that may block have alternatives | 
|  | See [C-DTOR-BLOCK](https://rust-lang.github.io/api-guidelines/dependability.html#c-dtor-block). | 
|  |  | 
|  |  | 
|  |  | 
|  | ### Debuggability | 
|  |  | 
|  | #### All public types implement `Debug` | 
|  | See [C-DEBUG](https://rust-lang.github.io/api-guidelines/debuggability.html#c-debug). | 
|  |  | 
|  | #### `Debug` representation is never empty | 
|  | See [C-DEBUG-NONEMPTY](https://rust-lang.github.io/api-guidelines/debuggability.html#c-debug-nonempty). | 
|  |  | 
|  |  | 
|  |  | 
|  | ### Future Proofing | 
|  |  | 
|  | #### Sealed traits protect against downstream implementations | 
|  | See [C-SEALED](https://rust-lang.github.io/api-guidelines/future-proofing.html#c-sealed). | 
|  |  | 
|  | #### Structs have private fields | 
|  | See [C-STRUCT-PRIVATE](https://rust-lang.github.io/api-guidelines/future-proofing.html#c-struct-private). | 
|  |  | 
|  | #### Newtypes encapsulate implementation details | 
|  | See [C-NEWTYPE-HIDE](https://rust-lang.github.io/api-guidelines/future-proofing.html#c-newtype-hide). | 
|  |  | 
|  | #### Data structures do not duplicate derived trait bounds | 
|  | See [C-STRUCT-BOUNDS](https://rust-lang.github.io/api-guidelines/future-proofing.html#c-struct-bounds). | 
|  |  | 
|  |  | 
|  | ## Updating the guidelines | 
|  |  | 
|  | This rubric is currently maintained by the Rust on Fuchsia Working Group. To propose additions or | 
|  | modifications, open a CL and cc [`fuchsia-rust-api-rubric@google.com`][rubric-group] to ensure it | 
|  | is reviewed. | 
|  |  | 
|  | [rubric-group]: mailto:fuchsia-rust-api-rubric@google.com | 
|  |  | 
|  | ### Pending Topics | 
|  |  | 
|  | Pending topics are tracked in the [Rust>Rubric][monorail] Monorail component. | 
|  |  | 
|  | [monorail]: https://bugs.fuchsia.dev/p/fuchsia/issues/list?q=component:Rust%3ERubric | 
|  |  | 
|  | ## Relationship with upstream Rust API guidelines | 
|  |  | 
|  | This rubric contains most of the [Rust API Guidelines][rust-guidelines], however the following | 
|  | official guidelines are omitted: | 
|  |  | 
|  | * [C-FEATURE](https://rust-lang.github.io/api-guidelines/naming.html#c-feature) as Fuchsia does not | 
|  | currently support features for crates. | 
|  | * [C-METADATA](https://rust-lang.github.io/api-guidelines/documentation.html#c-metadata) as Fuchsia | 
|  | does not maintain internal `Cargo.toml` files. | 
|  | * [C-HTML-ROOT](https://rust-lang.github.io/api-guidelines/documentation.html#c-html-root) as | 
|  | Fuchsia does not currently publish most Rust code to `crates.io`. | 
|  | * [C-RELNOTES](https://rust-lang.github.io/api-guidelines/documentation.html#c-relnotes) as most | 
|  | Rust code in Fuchsia "lives at HEAD". | 
|  | * [C-STABLE](https://rust-lang.github.io/api-guidelines/necessities.html#c-stable) as Fuchsia does | 
|  | not currently publish most Rust code to `crates.io`. | 
|  | * [C-PERMISSIVE](https://rust-lang.github.io/api-guidelines/necessities.html#c-permissive) as all of | 
|  | Fuchsia's Rust code is under the Fuchsia license. | 
|  |  | 
|  | The following Fuchsia-specific guidelines are included: | 
|  |  | 
|  | * [Every `unsafe` block has an accompanying justification][safety-justification-guideline] | 
|  | * [Unsafe traits are documented, unsafe trait impls are justified][unsafe-traits-guideline] | 
|  | * [Unsafe operations are always in an `unsafe` block][unsafe-ops-in-unsafe-blocks-guideline] | 
|  |  | 
|  | [safety-justification-guideline]: #every-unsafe-block-has-an-accompanying-justification | 
|  | [unsafe-traits-guideline]: #unsafe-traits-are-documented-unsafe-trait-impls-are-justified | 
|  | [unsafe-ops-in-unsafe-blocks-guideline]: #unsafe-operations-are-always-in-an-unsafe-block | 
|  |  | 
|  | [rust-guidelines]: https://rust-lang.github.io/api-guidelines/about.html |