diff --git a/src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md b/src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md index 57cfa524..80382a25 100644 --- a/src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md +++ b/src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md @@ -22,8 +22,8 @@ fn parse_ip_addr_v4(input: &str) -> Option { ... } // Repeats information obvious from the field name. Can omit! struct BusinessAsset { - /// The customer id. - let customer_id: u64, + /// The customer id. + customer_id: u64, } // Mentions the type name first thing, don't do this! diff --git a/src/idiomatic/foundations-api-design/predictable-api/common-traits/clone.md b/src/idiomatic/foundations-api-design/predictable-api/common-traits/clone.md index c57ecf22..a0ebcc3a 100644 --- a/src/idiomatic/foundations-api-design/predictable-api/common-traits/clone.md +++ b/src/idiomatic/foundations-api-design/predictable-api/common-traits/clone.md @@ -36,17 +36,21 @@ pub struct LotsOfData { set: BTreeSet, } -let lots_of_data = LotsOfData { - string: "String".to_string(), - vec: vec![1; 255], - set: BTreeSet::from_iter([1, 2, 3, 4, 5, 6, 7, 8]), -}; +fn main() { + let lots_of_data = LotsOfData { + string: "String".to_string(), + vec: vec![1; 255], + set: BTreeSet::from_iter([1, 2, 3, 4, 5, 6, 7, 8]), + }; -let lots_of_data_cloned = lots_of_data.clone(); + // Deep copy of all of the data in `lots_of_data`. + let lots_of_data_cloned = lots_of_data.clone(); -let reference_counted = Rc::new(lots_of_data); -// Copies the reference-counted pointer, not the value. -let reference_copied = reference_counted.clone(); + let reference_counted = Rc::new(lots_of_data); + + // Copies the reference-counted pointer, not the value. + let reference_copied = reference_counted.clone(); +} ```
diff --git a/src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md b/src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md index a8ba6ba7..ec13b94b 100644 --- a/src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md +++ b/src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md @@ -22,8 +22,15 @@ When to implement: If possible, but with caveats. // Copy is just a marker trait with Clone as a supertrait. // pub trait Copy: Clone { } -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] pub struct Copyable(u8, u16, u32, u64); + +fn main() { + let copyable = Copyable(1, 2, 3, 4); + let copy = copyable; // Implicit copy operation + dbg!(copyable); + dbg!(copy); +} ```
diff --git a/src/idiomatic/foundations-api-design/predictable-api/common-traits/hash.md b/src/idiomatic/foundations-api-design/predictable-api/common-traits/hash.md index 23088679..cd022074 100644 --- a/src/idiomatic/foundations-api-design/predictable-api/common-traits/hash.md +++ b/src/idiomatic/foundations-api-design/predictable-api/common-traits/hash.md @@ -29,12 +29,18 @@ When to implement: Almost always. // where H: Hasher, // Self: Sized { ... } // } +use std::collections::HashMap; -#[derive(Hash)] +#[derive(PartialEq, Eq, Hash)] pub struct User { id: u32, name: String, - friends: Vec, +} + +fn main() { + let user = User { id: 1, name: "Alice".into() }; + let mut map = HashMap::new(); + map.insert(user, "value"); } ``` diff --git a/src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md b/src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md index e4a092c2..adc5d057 100644 --- a/src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md +++ b/src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md @@ -33,11 +33,13 @@ When to implement: Almost always. #[derive(PartialEq, Eq)] pub struct User { name: String, favorite_number: i32 } -let alice = User { name: "alice".to_string(), favorite_number: 1_000_042 }; -let bob = User { name: "bob".to_string(), favorite_number: 42 }; +fn main() { + let alice = User { name: "alice".to_string(), favorite_number: 1_000_042 }; + let bob = User { name: "bob".to_string(), favorite_number: 42 }; -dbg!(alice == alice); -dbg!(alice == bob); + dbg!(alice == alice); + dbg!(alice == bob); +} ```
diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/is.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/is.md index a9876fc1..bd199d77 100644 --- a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/is.md +++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/is.md @@ -15,16 +15,16 @@ Check a condition about a datatype. # // Copyright 2025 Google LLC # // SPDX-License-Identifier: Apache-2.0 # -impl Vec { - is_empty(&self) -> bool; +impl Vec { + fn is_empty(&self) -> bool; } impl f32 { - is_nan(self) -> bool; + fn is_nan(self) -> bool; } impl u32 { - is_power_of_two(self) -> bool; + fn is_power_of_two(self) -> bool; } ``` diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/new.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/new.md index 4cac2860..1f4ff082 100644 --- a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/new.md +++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/new.md @@ -16,12 +16,11 @@ method name. # // Copyright 2025 Google LLC # // SPDX-License-Identifier: Apache-2.0 # -impl Vec { - // Creates an empty vec. +impl Vec { fn new() -> Vec; } -impl Box { +impl Box { fn new(T) -> Box; } ``` diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md index 1ceee11b..eeebc300 100644 --- a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md +++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md @@ -16,15 +16,14 @@ Prefix to a function that takes a borrowed value and creates an owned value # // SPDX-License-Identifier: Apache-2.0 # impl str { - // &str is not consumed. - fn to_owned(&str) -> String; + fn to_owned(&self) -> String; fn to_uppercase(&self) -> String; } impl u32 { - // take an owned self because `u32` implements `Copy` - to_be(self) -> u32; + // Take an owned self because `u32` implements `Copy` + fn to_be(self) -> u32; } ``` diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/try.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/try.md index 60270fcd..fee589c4 100644 --- a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/try.md +++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/try.md @@ -17,11 +17,12 @@ Prefix for fallible methods that return a `Result`. # impl TryFrom for u32 { type Error = TryFromIntError; + fn try_from(value: i32) -> Result; } impl Receiver { - try_recv(&self) -> Result; + fn try_recv(&self) -> Result; } ``` diff --git a/src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md b/src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md index 8b17658c..97dcb48f 100644 --- a/src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md +++ b/src/idiomatic/leveraging-the-type-system/borrow-checker-invariants/single-use-values.md @@ -17,12 +17,15 @@ this is in cryptography: A "Nonce." # // SPDX-License-Identifier: Apache-2.0 # pub struct Key(/* specifics omitted */); + /// A single-use number suitable for cryptographic purposes. pub struct Nonce(u32); + /// A cryptographically sound random generator function. pub fn new_nonce() -> Nonce { Nonce(4) // chosen by a fair dice roll, https://xkcd.com/221/ } + /// Consume a nonce, but not the key or the data. pub fn encrypt(nonce: Nonce, key: &Key, data: &[u8]) {} diff --git a/src/idiomatic/leveraging-the-type-system/newtype-pattern.md b/src/idiomatic/leveraging-the-type-system/newtype-pattern.md index 91e4d998..dfd8fef0 100644 --- a/src/idiomatic/leveraging-the-type-system/newtype-pattern.md +++ b/src/idiomatic/leveraging-the-type-system/newtype-pattern.md @@ -25,12 +25,15 @@ Unlike type aliases, newtypes aren't interchangeable with the wrapped type: # // Copyright 2025 Google LLC # // SPDX-License-Identifier: Apache-2.0 # -# pub struct UserId(u64); -fn triple(n: u64) -> u64 { - n * 3 +pub struct UserId(u64); + +fn needs_user(user: UserId) { + // ... } -triple(UserId(1)); // 🛠️❌ +fn main() { + needs_user(1); // 🛠️❌ +} ``` The Rust compiler won't let you use methods or operators defined on the @@ -40,8 +43,11 @@ underlying type either: # // Copyright 2025 Google LLC # // SPDX-License-Identifier: Apache-2.0 # -# pub struct UserId(u64); -assert_ne!(UserId(1), UserId(2)); // 🛠️❌ +pub struct UserId(u64); + +fn main() { + assert_ne!(UserId(1), UserId(2)); // 🛠️❌ +} ```
diff --git a/src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md b/src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md index 18eb438e..17cae11e 100644 --- a/src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md +++ b/src/idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md @@ -17,16 +17,19 @@ unclear: # // SPDX-License-Identifier: Apache-2.0 # # struct LoginError; -pub fn login(username: &str, password: &str) -> Result<(), LoginError> { +fn login(username: &str, password: &str) -> Result<(), LoginError> { // [...] # Ok(()) } -# let password = "password"; -# let username = "username"; -// In another part of the codebase, we swap arguments by mistake. -// Bug (best case), security vulnerability (worst case) -login(password, username); +fn main() { + let password = "password"; + let username = "username"; + + // In another part of the codebase, we swap arguments by mistake. + // Bug (best case), security vulnerability (worst case) + login(password, username); +} ``` The newtype pattern can prevent this class of errors at compile time: @@ -35,18 +38,20 @@ The newtype pattern can prevent this class of errors at compile time: # // Copyright 2025 Google LLC # // SPDX-License-Identifier: Apache-2.0 # -pub struct Username(String); -pub struct Password(String); -# struct LoginError; +struct Username(String); +struct Password(String); +struct LoginError; -pub fn login(username: &Username, password: &Password) -> Result<(), LoginError> { +fn login(username: &Username, password: &Password) -> Result<(), LoginError> { // [...] # Ok(()) } -# let password = Password("password".into()); -# let username = Username("username".into()); -login(password, username); // 🛠️❌ +fn main() { + let password = Password("password".into()); + let username = Username("username".into()); + login(password, username); // 🛠️❌ +} ```