diff --git a/src/SUMMARY.md b/src/SUMMARY.md
index dd6f25139ead..51e5c3c2a932 100644
--- a/src/SUMMARY.md
+++ b/src/SUMMARY.md
@@ -436,6 +436,48 @@
# Idiomatic Rust
- [Welcome](idiomatic/welcome.md)
+- [Foundations of API Design](idiomatic/foundations-api-design.md)
+ - [Meaningful Doc Comments](idiomatic/foundations-api-design/meaningful-doc-comments.md)
+ - [Who Are You Writing For?](idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md)
+ - [Library vs Application docs](idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md)
+ - [Anatomy of a Doc Comment](idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md)
+ - [Name Drop and Signpost](idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md)
+ - [Avoid Redundancy](idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md)
+ - [Name and Signature are Not Enough](idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md)
+ - [What and Why, not How and Where](idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md)
+ - [Exercise](idiomatic/foundations-api-design/meaningful-doc-comments/exercise.md)
+ - [Predictable API](idiomatic/foundations-api-design/predictable-api.md)
+ - [Naming conventions](idiomatic/foundations-api-design/predictable-api/naming-conventions.md)
+ - [New](idiomatic/foundations-api-design/predictable-api/naming-conventions/new.md)
+ - [Get](idiomatic/foundations-api-design/predictable-api/naming-conventions/get.md)
+ - [Push](idiomatic/foundations-api-design/predictable-api/naming-conventions/push.md)
+ - [Is](idiomatic/foundations-api-design/predictable-api/naming-conventions/is.md)
+ - [Mut](idiomatic/foundations-api-design/predictable-api/naming-conventions/mut.md)
+ - [With: Constructor](idiomatic/foundations-api-design/predictable-api/naming-conventions/with-constructor.md)
+ - [With: Copy-and-change](idiomatic/foundations-api-design/predictable-api/naming-conventions/with-copy-setter.md)
+ - [With: Closures](idiomatic/foundations-api-design/predictable-api/naming-conventions/with-closure.md)
+ - [With in normal use](idiomatic/foundations-api-design/predictable-api/naming-conventions/with-word.md)
+ - [Try](idiomatic/foundations-api-design/predictable-api/naming-conventions/try.md)
+ - [From](idiomatic/foundations-api-design/predictable-api/naming-conventions/from.md)
+ - [Into](idiomatic/foundations-api-design/predictable-api/naming-conventions/into.md)
+ - [Into inner](idiomatic/foundations-api-design/predictable-api/naming-conventions/into_inner.md)
+ - [By](idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md)
+ - [Unchecked](idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md)
+ - [To](idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md)
+ - [As and Ref](idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md)
+ - [Raw parts](idiomatic/foundations-api-design/predictable-api/naming-conventions/raw_parts.md)
+ - [Exercise](idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md)
+ - [Implementing Common Traits](idiomatic/foundations-api-design/predictable-api/common-traits.md)
+ - [Debug](idiomatic/foundations-api-design/predictable-api/common-traits/debug.md)
+ - [PartialEq and Eq](idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md)
+ - [PartialOrd and Ord](idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md)
+ - [Hash](idiomatic/foundations-api-design/predictable-api/common-traits/hash.md)
+ - [Clone](idiomatic/foundations-api-design/predictable-api/common-traits/clone.md)
+ - [Copy](idiomatic/foundations-api-design/predictable-api/common-traits/copy.md)
+ - [Serialize and Deserialize](idiomatic/foundations-api-design/predictable-api/common-traits/serde.md)
+ - [From and Into](idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md)
+ - [TryFrom and TryInto](idiomatic/foundations-api-design/predictable-api/common-traits/try-from-into.md)
+ - [Display](idiomatic/foundations-api-design/predictable-api/common-traits/display.md)
- [Leveraging the Type System](idiomatic/leveraging-the-type-system.md)
- [Newtype Pattern](idiomatic/leveraging-the-type-system/newtype-pattern.md)
- [Semantic Confusion](idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md)
@@ -479,6 +521,35 @@
- [Branded pt 2: `PhantomData` and Lifetime Subtyping](idiomatic/leveraging-the-type-system/token-types/branded-02-phantomdata.md)
- [Branded pt 3: Implementation](idiomatic/leveraging-the-type-system/token-types/branded-03-impl.md)
- [Branded pt 4: Branded types in action.](idiomatic/leveraging-the-type-system/token-types/branded-04-in-action.md)
+- [Polymorphism](idiomatic/polymorphism.md)
+ - [Refresher](idiomatic/polymorphism/refresher.md)
+ - [Traits](idiomatic/polymorphism/refresher/traits.md)
+ - [Trait Bounds](idiomatic/polymorphism/refresher/trait-bounds.md)
+ - [Deriving Traits](idiomatic/polymorphism/refresher/deriving-traits.md)
+ - [Default Implementations](idiomatic/polymorphism/refresher/default-impls.md)
+ - [Supertraits](idiomatic/polymorphism/refresher/supertraits.md)
+ - [Blanket Implementations](idiomatic/polymorphism/refresher/blanket-impls.md)
+ - [Conditional Methods](idiomatic/polymorphism/refresher/conditional-methods.md)
+ - [Orphan Rule](idiomatic/polymorphism/refresher/orphan-rule.md)
+ - [Statically Sized and Dynamically Sized types](idiomatic/polymorphism/refresher/sized.md)
+ - [Monomorphization and Binary Size](idiomatic/polymorphism/refresher/monomorphization.md)
+ - [From OOP to Rust](idiomatic/polymorphism/from-oop-to-rust.md)
+ - [Inheritance](idiomatic/polymorphism/from-oop-to-rust/inheritance.md)
+ - [Why no Inheritance in Rust?](idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md)
+ - [Inheritance from Rust's Perspective](idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md)
+ - ["Inheritance" in rust and Supertraits](idiomatic/polymorphism/from-oop-to-rust/supertraits.md)
+ - [Composition over Inheritance](idiomatic/polymorphism/from-oop-to-rust/composition.md)
+ - [Trait Objects and Dynamic Dispatch](idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-trait.md)
+ - [Dyn Compatibility](idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md)
+ - [Generics vs Trait Objects](idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-vs-generics.md)
+ - [Limits of Trait Objects](idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/limits.md)
+ - [Heterogeneous Collections](idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/heterogeneous.md)
+ - [The `Any` Trait](idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/any-trait.md)
+ - [Pitfall: Reaching too quickly for `dyn Trait`](idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/pitfalls.md)
+ - [Sealed Traits](idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md)
+ - [Sealing with Enums](idiomatic/polymorphism/from-oop-to-rust/sealing-with-enums.md)
+ - [Traits for Polymorphism users can extend](idiomatic/polymorphism/from-oop-to-rust/sticking-with-traits.md)
+ - [Problem solving: Break Down the Problem](idiomatic/polymorphism/from-oop-to-rust/problem-solving.md)
---
diff --git a/src/idiomatic/foundations-api-design.md b/src/idiomatic/foundations-api-design.md
new file mode 100644
index 000000000000..c31a52ef740f
--- /dev/null
+++ b/src/idiomatic/foundations-api-design.md
@@ -0,0 +1,7 @@
+---
+minutes: 2
+---
+
+# Foundations of API Design
+
+{{%segment outline}}
diff --git a/src/idiomatic/foundations-api-design/meaningful-doc-comments.md b/src/idiomatic/foundations-api-design/meaningful-doc-comments.md
new file mode 100644
index 000000000000..2da5ff7c867d
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/meaningful-doc-comments.md
@@ -0,0 +1,25 @@
+---
+minutes: 5
+---
+
+# Meaningful Doc Comments
+
+```rust,compile_fail
+/// API for the client // ❌ Lacks detail
+pub mod client {}
+
+/// Function from A to B // ❌ Redundant
+fn a_to_b(a: A) -> B {...}
+
+/// Connects to the database. // ❌ Lacks detail
+fn connect() -> Result<(), Error> {...}
+```
+
+
+
+- Doc comments are the most common form of documentation developers engage with.
+
+- Good doc comments provide information that the code, names, and types cannot,
+ without restating the obvious information.
+
+
diff --git a/src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md b/src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md
new file mode 100644
index 000000000000..9c845c0445be
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/meaningful-doc-comments/anatomy-of-a-doc-comment.md
@@ -0,0 +1,84 @@
+---
+minutes: 5
+---
+
+# The Anatomy of a Doc Comment
+
+1. A brief, one-sentence summary.
+2. A more detailed explanation.
+3. Special sections: code examples, panics, errors, safety preconditions.
+
+````rust,compile_fail
+/// Parses a key-value pair from a string.
+///
+/// The input string must be in the format `key=value`. Everything before the
+/// first '=' is treated as the key, and everything after is the value.
+///
+/// # Examples
+///
+/// ```
+/// use my_crate::parse_key_value;
+/// let (key, value) = parse_key_value("lang=rust").unwrap();
+/// assert_eq!(key, "lang");
+/// assert_eq!(value, "rust");
+/// ```
+///
+/// # Panics
+///
+/// Panics if the input is empty.
+///
+/// # Errors
+///
+/// Returns a `ParseError::Malformed` if the string does not contain `=`.
+///
+/// # Safety
+///
+/// Triggers undefined behavior if...
+unsafe fn parse_key_value(s: &str) -> Result<(String, String), ParseError>
+
+enum ParseError {
+ Empty,
+ Malformed,
+}
+````
+
+
+
+- Idiomatic Rust doc comments follow a conventional structure that makes them
+ easier for developers to read.
+
+- The first line of a doc comment is a single-sentence summary of the function.
+ Keep it concise. `rustdoc` and other tools have a strong expectation about
+ that: it is used as a short summary in module-level documentation and search
+ results.
+
+- Next, you can provide a long, multi-paragraph description of the "why" and
+ "what" of the function. Use Markdown.
+
+- Finally, you can use top-level section headers to organize your content. Doc
+ comments commonly use `# Examples`, `# Panics`, `# Errors`, and `# Safety` as
+ section titles. The Rust community expects to see relevant aspects of your API
+ documented in these sections.
+
+- Rust heavily focuses on safety and correctness. Documenting behavior of your
+ code in case of errors is critical for writing reliable software.
+
+- `# Panics`: If your function may panic, you must document the specific
+ conditions when that might happen. Callers need to know what to avoid.
+
+- `# Errors`: For functions returning a `Result`, this section explains what
+ kind of errors can occur and under what circumstances. Callers need this
+ information to write robust error handling logic.
+
+- **Question:** Ask the class why documenting panics is so important in a
+ language that prefers returning `Result`.
+
+ - **Answer:** Panics are for unrecoverable, programming errors. A library
+ should not panic unless a contract is violated by the caller. Documenting
+ these contracts is essential.
+
+- `# Safety` comments document safety preconditions on unsafe functions that
+ must be satisfied, or else undefined behavior might result. They are discussed
+ in detail in the Unsafe Rust deep dive.
+
+
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
new file mode 100644
index 000000000000..2aefebaf5558
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/meaningful-doc-comments/avoid-redundancy.md
@@ -0,0 +1,102 @@
+---
+minutes: 15
+---
+
+# Avoiding Redundancy
+
+Names and type signatures communicate a lot of information, don't repeat it in
+comments!
+
+```rust,compile_fail
+// Repeats name/type information. Can omit!
+/// Parses an ipv4 from a str. Returns an option for failure modes.
+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,
+}
+
+// Mentions the type name first thing, don't do this!
+/// `ServerSynchronizer` is an orchestrator that sends local edits [...]
+struct ServerSynchronizer { ... }
+
+// Better! Focuses on purpose.
+/// Sends local edits [...]
+struct ServerSynchronizer { ... }
+
+// Mentions the function name first thing, don't do this!
+/// `sync_to_server` sends local edits [...]
+fn sync_to_server(...)
+
+// Better! Focuses on function.
+/// Sends local edits [...]
+fn sync_to_server(...)
+```
+
+
+
+- Motivation: Documentation that merely repeats name/signature information
+ provides nothing new to the API user.
+
+Additionally, signature information may change over time without the
+documentation being updated accordingly!
+
+- This is an understandable pattern to fall into!
+
+ Naive approach to "always document your code," follows this advice literally
+ but does not follow the intent.
+
+ Some tools might enforce documentation coverage, this kind of documentation is
+ an easy fix.
+
+- Be aware of the purpose of different modes of documentation:
+
+ - Library code will need to be documented in ways that understand the scope of
+ what it is used for and the breadth of people who are trying to use it.
+
+ - Application code has a more narrow purpose, it can afford to be more simple
+ and direct.
+
+- The name of an item is part of the documentation of that item.
+
+ Similarly, the signature of a function is part of the documentation of that
+ function.
+
+ Therefore: Some aspects of the item are already covered when you start writing
+ doc comments!
+
+ Do not repeat information for the sake of an itemized list.
+
+- Many areas of the standard library have minimal documentation because the name
+ and types do give enough information.
+
+ Rule of Thumb: What information is missing from a user's perspective? Other
+ than name, signature, and irrelevant details of the implementation.
+
+- Don't explain the basics of Rust or the standard library. Assume the reader of
+ doc comments has an intermediate understanding of the language itself. Focus
+ on documenting your API.
+
+ For example, if your function returns `Result`, you don't need to explain how
+ `Result` or the question mark operators work.
+
+- If there is a complex topic involved with the functions and types you're
+ documenting, signpost to a "source of truth" if one exists such as an internal
+ document, a paper, a blog post etc.
+
+- Collaborate with Students: Go through the methods in the slide and discuss
+ what might be relevant to an API user.
+
+## More to Explore
+
+- The `#![warn(missing_docs)]` lint can be helpful for enforcing the existence
+ of doc comments, but puts a large burden on developers that could lead to
+ leaning onto these patterns of writing low-quality comments.
+
+ This kind of lint should only be enabled if the people maintaining a project
+ can afford to keep up with its demands, and usually only for library-style
+ crates rather than application code.
+
+
diff --git a/src/idiomatic/foundations-api-design/meaningful-doc-comments/exercise.md b/src/idiomatic/foundations-api-design/meaningful-doc-comments/exercise.md
new file mode 100644
index 000000000000..1d34a702b12b
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/meaningful-doc-comments/exercise.md
@@ -0,0 +1,50 @@
+---
+minutes: 10
+---
+
+# Exercise: Dialog on Details
+
+Unnecessary details can sometimes be indicative of something that does need
+documentation.
+
+```rust,compile_fail
+/// Sorts a slice. Implemented using recursive quicksort.
+fn sort_quickly(to_sort: &mut [T]) { ... }
+```
+
+
+
+- Consider the example here, we discussed in
+ [what and why, not how and where](what-why-not-how-where.md) that internal
+ details are unlikely relevant to someone reading documentation.
+
+ Here we're discussing a counterexample.
+
+- Ask the class: Is this comment necessary for this function?
+
+- Narrative: Playing the part of an intermediary between the class and the
+ author, such as a PM, manager, etc. tell the class that the author of this
+ function is pushing back.
+
+- Ask the class: Why would an author of this kind of comment push back?
+
+ If the class asks why the author is pushing back, do not give details yet.
+
+- Ask the class: Why would the caller need to know the sorting algorithm in use?
+
+- Narrative: "Come back" from a meeting with the original author, explain to the
+ class that this function is application code that is called on untrusted data
+ that
+ [could be crafted maliciously to cause quadratic behavior during sorting](https://www.cs.dartmouth.edu/~doug/mdmspe.pdf).
+
+- Ask the class: Now we have more detail, how should we comment this function?
+
+ The point being implementation detail vs not depends a lot on what the public
+ contract is (e.g., can you supply untrusted data or not), and this requires
+ careful judgement.
+
+ Consider if a comment is explaining that a for-loop is used (unnecessary
+ detail) or if it is explaining that the algorithms used internally have known
+ exploits (documentation draws attention to the wrong thing).
+
+
diff --git a/src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md b/src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md
new file mode 100644
index 000000000000..854ee96d40c8
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/meaningful-doc-comments/library-vs-application-docs.md
@@ -0,0 +1,43 @@
+---
+minutes: 10
+---
+
+# Library vs application docs
+
+You might see elaborate documentation for fundamental APIs that repeats the
+names and type signatures. Stable and highly reusable code can afford this with
+a positive RoI.
+
+- Library code:
+ - has a high number of users,
+ - solves a whole range of related problems,
+ - often has stable APIs.
+
+- Application code is the opposite:
+ - few users,
+ - solves a specific problem,
+ - changes often.
+
+
+
+- You might have seen elaborate documentation that repeats code, looks at the
+ same API multiple times with many examples and case studies. Context is key:
+ who wrote it, for whom, and what material it is covering, and what resources
+ did they have.
+
+- Fundamental library code often has Elaborate documentation, for example, the
+ standard library, highly reusable frameworks like serde and tokio. Teams
+ responsible for this code often have appropriate resources to write and
+ maintain elaborate documentation.
+
+- Library code is often stable, so the community is going to extract a
+ significant benefit from elaborate documentation before it needs to be
+ reworked.
+
+- Application code has the opposite traits: it has few users, solves a specific
+ problem, and changes often. For application code elaborate documentation
+ quickly becomes outdated and misleading. It is also difficult to extract a
+ positive RoI from boilerplate docs even while they are up to date, because
+ there are only a few users.
+
+
diff --git a/src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md b/src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md
new file mode 100644
index 000000000000..9a262abb7d58
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/meaningful-doc-comments/name-drop-signpost.md
@@ -0,0 +1,83 @@
+---
+minutes: 15
+---
+
+# Name-dropping keywords and signposting topics
+
+```rust
+/// A parsed representation of a MARC 21 record
+/// [leader](//www.loc.gov/marc/bibliographic/bdleader.html).
+/// A MARC leader contains metadata that dictates how to interpret the rest
+/// of the record.
+pub struct Leader {
+ /// Determines the schema and the set of valid subsequent data fields.
+ ///
+ /// Encoded in byte 6 of the leader.
+ pub type_of_record: char,
+
+ /// Indicates whether to parse relationship fields, such as a "773 Host
+ /// Item Entry" for an article within a larger work.
+ ///
+ /// Encoded in byte 7 of the leader.
+ pub bibliographic_level: char,
+ // ... other fields
+}
+
+/// Parses the [leader of a MARC 21 record](https://www.loc.gov/marc/bibliographic/bdleader.html).
+///
+/// The leader is encoded as a fixed-length 24-byte field, containing metadata
+/// that determines the semantic interpretation of the rest of the record.
+pub fn parse_leader(leader_bytes: &[u8; 24]) -> Result {
+ todo!()
+}
+
+#[derive(Debug)]
+pub enum MarcError {}
+```
+
+
+
+- Motivation: Readers of documentation will not be closely reading most of your
+ doc comments like they would dialogue in a novel they love.
+
+Users will most likely be skimming and scan-reading to find the part of the
+documentation that is relevant to whatever problem they're trying to solve in
+the moment.
+
+Once a user has found a keyword or potential signpost that's relevant to them
+they will begin to search for context surrounding what is being documented.
+
+- Ask the class: What do you look for in documentation? Focus on the
+ moment-to-moment searching for information here, not general values in
+ documentation.
+
+- Name-drop keywords close to the beginning of a paragraph.
+
+ This aids skimming and scanning, as the first few words of a paragraph stand
+ out the most.
+
+ Skimming and scanning lets users quickly navigate a text, keeping keywords as
+ close to the beginning of a paragraph as possible lets a user determine if
+ they've found relevant information faster.
+
+- Signpost, but don't over-explain.
+
+ Users will not necessarily have the same domain expertise as an API designer.
+
+ If a tangential, specialist term or acronym is mentioned try to bring in
+ enough context such that a novice could quickly do more research.
+
+- Signposting often happens organically, consider a networking library that
+ mentions various protocols. But when it doesn't happen organically, it can be
+ difficult to choose what to mention.
+
+ Rule of thumb: API developers should be asking themselves "if a novice ran
+ into what they are documenting, what sources would they look up and are there
+ any red herrings they might end up following"?
+
+ Users should be given enough information to look up subjects on their own.
+
+- What we've already covered, predictability of an API including the naming
+ conventions, is a form of signposting.
+
+
diff --git a/src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md b/src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md
new file mode 100644
index 000000000000..69aa5381918f
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/meaningful-doc-comments/what-isnt-docs.md
@@ -0,0 +1,58 @@
+---
+minutes: 5
+---
+
+# Names and Signatures are not full documentation
+
+```rust,compile_fail
+// bad
+/// Returns a future that resolves when operation completes.
+fn sync_to_server() -> Future;
+
+// good
+/// Sends local edits to the server, overwriting concurrent edits
+/// if any happened.
+fn sync_to_server() -> Future;
+// bad
+/// Returns an error if sending the email fails.
+fn send(&self, email: Email) -> Result<(), Error>;
+
+// good
+/// Queues the email for background delivery and returns immediately.
+/// Returns an error immediately if the email is malformed.
+fn send(&self, email: Email) -> Result<(), Error>;
+```
+
+
+
+- Motivation: API designers can over-commit to the idea that a function name and
+ signature is enough documentation.
+
+It's better than nothing, but it's worse than good documentation.
+
+- Again, names and types are _part_ of the documentation. They are not always
+ the full story!
+
+- Consider the behavior of functions that are not covered by the name, parameter
+ names, or signature of that function.
+
+ In the example on the slide it is not obvious that `sync_to_server()` could
+ overwrite something (leading to a data loss), so document that.
+
+ In the email example, it is not obvious that the function can return success
+ and still fail to deliver the email.
+
+- Use comments to disambiguate. Nuanced behaviors, behaviors that users of an
+ API could trip up on, should be documented.
+
+ For example, consider a remove() method on a business entity: There are many
+ ways to remove an entity!
+
+ Is it removing the entity from the database? From the parent collection in
+ memory (unlink vs erase)?
+
+ If it is removing the data in the database, is the data actually being
+ deleted, or merely marked as deleted, but still recoverable (soft vs hard
+ delete)?
+
+
diff --git a/src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md b/src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md
new file mode 100644
index 000000000000..4340813b4ea7
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/meaningful-doc-comments/what-why-not-how-where.md
@@ -0,0 +1,77 @@
+---
+minutes: 10
+---
+
+# Why and What, not How and Where
+
+Avoid documenting irrelevant details that may frequently change.
+
+```rust,compile_fail
+/// Sorts a slice. Implemented using recursive quicksort.
+
+fn sort_quickly(to_sort: &mut [T]) { /* ... */
+}
+
+// bad
+/// Saves a `User` record to the Postgres database.
+///
+/// This function opens a new connection and begins a transaction. It checks
+/// if a user with the given ID exists with a `SELECT` query. If a user is
+/// not found, performs an `INSERT`.
+///
+/// # Errors
+///
+/// Returns an error if any database operation fails.
+pub fn save_user(user: &User) -> Result<(), db::Error> {
+ // ...
+}
+
+// good
+/// Atomically saves a user record.
+///
+/// # Errors
+///
+/// Returns a `db::Error::DuplicateUsername` error if the user (keyed by
+/// `user.username` field) already exists.
+pub fn save_user(user: &User) -> Result<(), db::Error> {
+ // ...
+}
+```
+
+
+
+- Motivation: Users want to know the contract of the API (what is guaranteed
+ about this function), rather than implementation details.
+
+- Motivation: Doc comments that explain implementation details become outdated
+ faster than comments that explain the contract.
+
+ Internal information is likely irrelevant to a user. Imagine explaining in a
+ doc comment for a function that you're using for loops to solve a problem,
+ what is the point of this information?
+
+- Consider the `sort_quickly` function above. Its documentation calls out that
+ it uses quicksort, but is this necessary?
+
+ It could be that another sorting function is used in the future, if that were
+ the case then this comment would need to be updated too. This is a point of
+ failure in documentation.
+
+- It could be that the implementation is necessary to explain, but this is
+ likely due to whatever effects or invariants the user of that API needs to be
+ aware of instead.
+
+ Focus on those effects and invariants instead of instead of the implementation
+ details themselves.
+
+ Reiterate: Implementation details can and will change, so do not explain these
+ details.
+
+- Don't talk about where something is used for the sake of it.
+
+ This is another instance where this information can become stale quickly.
+
+- Focus on what the function does (not how it is implemented) for a user trying
+ to reach this practical information as quickly as possible.
+
+
diff --git a/src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md b/src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md
new file mode 100644
index 000000000000..d62e0567d7a1
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/meaningful-doc-comments/who-are-you-writing-for.md
@@ -0,0 +1,67 @@
+---
+minutes: 10
+---
+
+# Who are you writing for?
+
+Colleagues, collaborators, largely-silent API users, or just yourself?
+
+```rust,compile_fail
+// expert writes for experts
+/// Canonicalizes the MIR for the borrow checker.
+///
+/// This pass ensures that all borrows conform to the NLL-Polonius constraints
+/// before we proceed to MIR-to-LLVM-IR translation.
+pub fn canonicalize_mir(mir: &mut Mir) {
+ // ...
+}
+
+// expert writes for newcomers
+/// Prepares the Mid-level IR (MIR) for borrow checking.
+///
+/// The borrow checker operates on a simplified, "canonical" form of the MIR.
+/// This function performs that transformation. It is a prerequisite for the
+/// final stages of code generation.
+///
+/// For more about Rust's intermediate representations, see the
+/// [rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/mir/index.html).
+pub fn canonicalize_mir(mir: &mut Mir) {
+ // ...
+}
+```
+
+
+
+- Background: The
+ [curse of knowledge](https://en.wikipedia.org/wiki/Curse_of_knowledge) is a
+ cognitive bias where experts assume that others have the same level of
+ expertise and perspective.
+
+- Motivation: Your reader does not have the same level of expertise and the same
+ perspective as you. Don't write for people like yourself, write for others.
+
+- Unintentionally writing for yourself can lead to people not understanding a
+ point you're trying to make or the concept you're trying to articulate.
+
+- Imagine a version of you, or others you've known, struggling to find practical
+ information while going through documentation.
+
+ Keep this idea of a person in mind when thinking about what areas of a
+ codebase need attention for doc comments.
+
+- Who are you writing for?
+
+- Also imagine a version of you, or others you've known, who is struggling to
+ find the important details in winding, extensive doc comments. Don't give too
+ much information.
+
+- Always ask: Is this documentation making it difficult for the API user? Are
+ they able to quickly grasp what they need or find out where they could need
+ it?
+
+- Always consider: Experts also read API level documentation. Doc comments might
+ not be the right place to educate your audience about the basics of your
+ domain. In that case, signpost and name-drop. Divert people to long-form
+ documentation.
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api.md b/src/idiomatic/foundations-api-design/predictable-api.md
new file mode 100644
index 000000000000..4f78df0a7cfd
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api.md
@@ -0,0 +1,32 @@
+---
+minutes: 2
+---
+
+# Predictable API
+
+Keep your APIs predictable through naming conventions and implementing common
+traits.
+
+```rust,compile_fail
+/* What traits should this implement? */
+pub struct ApiToken(String);
+
+impl ApiToken {
+ // What should this method be called?
+ pub unsafe fn ____(String) -> ApiToken;
+}
+```
+
+
+
+- A predictable API is one where a user's can make assumptions about a part of
+ the API based on surface-level details like names, types, and signatures.
+
+- We'll be looking at common naming conventions in Rust, which allow users to
+ search for methods that fit their needs quickly and be able to understand
+ existing code quickly.
+
+- We will also be looking at common traits that types implement, and when to
+ implement them for types you define.
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/common-traits.md b/src/idiomatic/foundations-api-design/predictable-api/common-traits.md
new file mode 100644
index 000000000000..9c25c382f465
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/common-traits.md
@@ -0,0 +1,30 @@
+---
+minutes: 5
+---
+
+# Common Traits to Implement
+
+```rust
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone /* ... */)]
+pub struct MyData {
+ pub name: String,
+ pub number: usize,
+ pub data: [u8; 64],
+}
+```
+
+
+- Traits are one of the most potent tools in the Rust language. The language and ecosystem expects you to use them, and so a big part of _predictability_ is what traits are implemented for a type!
+
+- Traits should be liberally implemented on types you author, but there are
+ caveats!
+
+- Remember, many traits have the ability to be _derived_: to have a compiler
+ plugin (macro) write the implementation for you!
+
+- Authors of ecosystem traits (like De/Serialize) have made derive
+ implementations for traits available to users, leading to very little
+ commitment needed on the developer side for implementing these kinds of
+ traits!
+
+
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
new file mode 100644
index 000000000000..c8a80c92540f
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/common-traits/clone.md
@@ -0,0 +1,52 @@
+---
+minutes: 5
+---
+
+# Clone
+
+Deep-copy a type or duplicate a smart, shareable pointer.
+
+Derivable: ✅
+
+When to implement: If duplicating doesn't break invariants.
+
+```rust
+// pub trait Clone: Sized {
+// // Required method
+// fn clone(&self) -> Self;
+//
+// // Provided methods omitted
+// }
+
+use std::collections::BTreeSet;
+use std::rc::Rc;
+
+#[derive(Clone)]
+pub struct LotsOfData {
+ string: String,
+ vec: Vec,
+ 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]),
+};
+
+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();
+```
+
+
+
+- "Deep copy" a value, or in the case of reference counting pointers like
+ `Rc`/`Arc` create a new instance of that pointer.
+
+- When to not implement/derive: For types that, to maintain an invariant, the
+ value should not be duplicated. We'll touch on this later in Idiomatic Rust.
+
+
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
new file mode 100644
index 000000000000..09331affe680
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/common-traits/copy.md
@@ -0,0 +1,49 @@
+---
+minutes: 10
+---
+
+# Copy
+
+Like `Clone`, but indicates the type is can be bitwise copied.
+
+Derivable: ✅
+
+When to implement: If possible, but with caveats.
+
+```rust
+// Copy is just a marker trait with Clone as a supertrait.
+// pub trait Copy: Clone { }
+
+#[derive(Clone, Copy)]
+pub struct Copyable(u8, u16, u32, u64);
+```
+
+
+- Clone represents a deep clone, and so does copy, but copy suggests to the compiler that a value can be copied bitwise.
+
+- When not to implement/derive: If you do not want to implicitly create copies
+ when dereferencing values of a type, do not implement this trait.
+
+ Copy enables implicit duplication, so be careful about what types you're
+ implementing this on.
+
+- Ask the class: Can a type with heap data (`Vec`, `BTreeMap`, `Rc`, etc.) be
+ copy? Should it be?
+
+ It both cannot and should not, this is a misuse of this trait.
+
+ Bitwise copying on these types would mean types with heap data would no longer
+ have exclusive ownership of a pointer, breaking the invariants usually upheld
+ by Rust and its ecosystem.
+
+ Multiple `Vec`s would point to the same data in memory. Adding and removing
+ data would only update individual `Vec`s length and capacity values. The same
+ for `BTreeMap`.
+
+ Bitwise copying of `Rc`s would not update the reference counting value within
+ the pointers, meaning there could be two instances of a `Rc` value that
+ believe themselves to be the only `Rc` for that pointer. Once one of them is
+ destroyed, the reference count will become 0 on one of them and the inner
+ value dropped despite there being another `Rc` still alive.
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md b/src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md
new file mode 100644
index 000000000000..3c7924114dac
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/common-traits/debug.md
@@ -0,0 +1,76 @@
+---
+minutes: 5
+---
+
+# Debug
+
+"Write to string" trait, for debug purposes.
+
+Derivable: ✅
+
+When to implement: Almost always
+
+```rust
+// pub trait Debug {
+// fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>;
+// }
+
+#[derive(Debug)]
+pub struct Date {
+ day: u8,
+ month: u8,
+ year: i64,
+}
+
+#[derive(Debug)]
+pub struct User {
+ name: String,
+ date_of_birth: Date,
+}
+
+pub struct PlainTextPassword {
+ password: String,
+ hint: String,
+}
+
+impl std::fmt::Debug for PlainTextPassword {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("PlainTextPassword")
+ .field("hint", &self.hint)
+ .field("password", &"[omitted]")
+ .finish()
+ }
+}
+
+fn main() {
+ let user = User {
+ name: "Alice".to_string(),
+ date_of_birth: Date { day: 31, month: 10, year: 2002 },
+ };
+
+ println!("{user:?}");
+ println!(
+ "{:?}",
+ PlainTextPassword {
+ password: "Password123".to_string(),
+ hint: "Used it for years".to_string()
+ }
+ );
+}
+```
+
+
+- Provides trivial "write to string" functionality.
+
+- Formatting for _debug information_ for programmers during , not appearance or
+ serialization.
+
+- Allows for use of `{:?}` and `{#?}` interpolation in string formatting macros.
+
+- When to not derive/implement: If a struct holds sensitive data, investigate if
+ you should implement Debug for it.
+
+ If Debug is needed, consider manually implementing Debug rather than deriving
+ it. Omit the sensitive data from the implementation.
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/common-traits/display.md b/src/idiomatic/foundations-api-design/predictable-api/common-traits/display.md
new file mode 100644
index 000000000000..926cede7a87d
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/common-traits/display.md
@@ -0,0 +1,49 @@
+---
+minutes: 5
+---
+
+# Display
+
+"Write to string" trait, prioritizing readability for an end user.
+
+Derivable: ❌, without crates like `derive_more`.
+
+When to implement: As-needed, for errors and other types that an end-user will
+see.
+
+```rust
+#[derive(Debug)]
+pub enum NetworkError {
+ HttpCode(u16),
+ WhaleBitTheUnderseaCable,
+}
+
+impl std::fmt::Display for NetworkError {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ NetworkError::HttpCode(code) => write!(f, "HTTP Error code {code}"),
+ NetworkError::WhaleBitTheUnderseaCable => {
+ write!(f, "Whale attack detected – call Ishmael")
+ }
+ }
+ }
+}
+
+impl std::error::Error for NetworkError {}
+```
+
+
+- A trait similar to `Debug`, but with a focus on end-user readability.
+
+- Prerequisite for the `Error` trait.
+
+ If implementing for an error type, focus on providing a descriptive error for
+ users and programmers other than you.
+
+- Same security considerations as Debug, consider the ways that sensitive data
+ could be exposed in UI or logs.
+
+- Types that implement `Display` automatically have `ToString` implemented for
+ them.
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md b/src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md
new file mode 100644
index 000000000000..ea1b19d669cf
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/common-traits/from-into.md
@@ -0,0 +1,59 @@
+---
+minutes: 5
+---
+
+# From & Into
+
+Conversion from one type to another.
+
+Derivable: ❌, without crates like `derive_more`.
+
+When to implement: As-needed and convenient.
+
+```rust
+pub struct ObviousImplementation(String);
+
+impl From for ObviousImplementation {
+ fn from(value: String) -> Self {
+ ObviousImplementation(value)
+ }
+}
+
+impl From<&str> for ObviousImplementation {
+ fn from(value: &str) -> Self {
+ ObviousImplementation(value.to_owned())
+ }
+}
+
+fn main() {
+ // From String
+ let obvious1 = ObviousImplementation::from("Hello, obvious!".to_string());
+ // From &str
+ let obvious2 = ObviousImplementation::from("Hello, obvious!");
+ // A From implementation implies an Into implementation, &str.into() ->
+ // ObviousImplementation
+ let obvious3: ObviousImplementation = "Hello, implementation!".into();
+}
+```
+
+
+- Provides conversion functionality to types.
+
+- The two traits exist to express different areas you'll find conversion in
+ codebases.
+
+- `From` provides a constructor-style function, whereas into provides a method
+ on an existing value.
+
+- Prefer writing `From` implementations for a type you're authoring instead
+ of `Into`.
+
+ The `Into` trait is implemented for any type that implements `From`
+ automatically.
+
+ `Into` is preferred as a trait bound for arguments to functions for clarity of
+ intent for what the function can take.
+
+ `T: Into` has clearer intent than `String: From`.
+
+
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
new file mode 100644
index 000000000000..a87ebc881586
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/common-traits/hash.md
@@ -0,0 +1,38 @@
+---
+minutes: 2
+---
+
+# Hash
+
+Performing a hash on a type.
+
+Derivable: ✅
+
+When to implement: Almost always.
+
+```rust
+// pub trait Hash {
+// // Required method
+// fn hash(&self, state: &mut H)
+// where H: Hasher;
+//
+// // Provided method
+// fn hash_slice(data: &[Self], state: &mut H)
+// where H: Hasher,
+// Self: Sized { ... }
+// }
+
+#[derive(Hash)]
+pub struct User {
+ id: u32,
+ name: String,
+ friends: Vec,
+}
+```
+
+
+- Allows a type to be used in hash algorithms.
+
+- Most commonly used with data structures like `HashMap`.
+
+
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
new file mode 100644
index 000000000000..92cb2b4e5329
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/common-traits/partialeq-eq.md
@@ -0,0 +1,55 @@
+---
+minutes: 10
+---
+
+PartialEq and Eq
+
+Partial equality & Total equality.
+
+Derivable: ✅
+
+When to implement: Almost always.
+
+```rust
+// pub trait PartialEq
+//{
+// // Required method
+// fn eq(&self, other: &Rhs) -> bool;
+//
+// // Provided method
+// fn ne(&self, other: &Rhs) -> bool { ... }
+// }
+//
+// pub trait Eq: PartialEq { }
+
+#[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 };
+
+dbg!(alice == alice);
+dbg!(alice == bob);
+```
+
+
+- Equality-related methods. If a type implements `PartialEq`/`Eq` then you can use the `==` operator with that type.
+
+- A type can't implement `Eq` without implementing `PartialEq`.
+
+- Reminder: Partial means "there are invalid members of this set for this
+ function."
+
+ This doesn't mean that equality will panic, or that it returns a result, just
+ that there may be values that may not behave as you expect equality to behave.
+
+ For example, with floating point values `NaN` is an outlier: `NaN == NaN` is
+ false, despite bitwise equality.
+
+ `PartialEq` exists to separate types like f32/f64 from types with Total
+ Equality.
+
+- You can implement `PartialEq` between different types, but this is mostly
+ useful for reference/smart pointer types.
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md b/src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md
new file mode 100644
index 000000000000..c3ff7271d8d9
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/common-traits/partialord-ord.md
@@ -0,0 +1,66 @@
+---
+minutes: 10
+---
+
+# PartialOrd and Ord
+
+Partial ordering & Total ordering.
+
+Derivable: ✅
+
+When to implement: Almost always.
+
+```rust
+// pub trait PartialOrd: PartialEq
+// {
+// // Required method
+// fn partial_cmp(&self, other: &Rhs) -> Option;
+//
+// /* Provided methods omitted */
+// }
+// pub trait Ord: Eq + PartialOrd {
+// // Required method
+// fn cmp(&self, other: &Self) -> Ordering;
+//
+// /* Provided methods omitted */
+// }
+
+#[derive(PartialEq, PartialOrd)]
+pub struct Partially(f32);
+
+#[derive(PartialEq, Eq, PartialOrd, Ord)]
+pub struct Totally {
+ id: u32,
+ name: String,
+}
+```
+
+
+- Comparison-related methods. If a type implements `PartialOrd`/`Ord` then you can use comparison operators (`<`, `<=`, `>`, `>=`) with that type.
+
+`Ord` gives access to `min`, `max`, and `clamp` methods.
+
+- When derived, compares things in the order they are defined.
+
+ For enums this means each variant is considered "greater than" the last as
+ they are written.
+
+ For structs this means fields are compared as they are written, so `id` fields
+ are compared before `name` fields in `Totally`.
+
+- Prerequisites: `PartialEq` for `PartialOrd`, `Eq` for `Ord`.
+
+ To implement `Ord`, a type must also implement `PartialEq`, `Eq`, and
+ `PartialOrd`.
+
+- Like with `PartialEq` and `Eq`, a type cannot implement `Ord` without
+ implementing `PartialOrd`.
+
+ Like those equality traits, `PartialOrd` exists to separate types with
+ non-total ordering (particularly floating-point numbers) from types with total
+ ordering.
+
+- Used for sorting/searching algorithms and maintaining the ordering of
+ `BTreeMap`/`BTreeSet` style data types.
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/common-traits/serde.md b/src/idiomatic/foundations-api-design/predictable-api/common-traits/serde.md
new file mode 100644
index 000000000000..c37ca609e9e1
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/common-traits/serde.md
@@ -0,0 +1,38 @@
+---
+minutes: 5
+---
+
+Serialize/Deserialize style traits
+
+Crates like `serde` can implement serialization automatically.
+
+Derivable: ✅
+
+When to implement: Almost always.
+
+```rust,compile_fail
+#[derive(Serialize, Deserialize)]
+struct ExtraData {
+ fav_color: String,
+ name_of_dog: String,
+}
+
+#[derive(Serialize, Deserialize)]
+struct Data {
+ name: String,
+ age: usize,
+ extra_data: ExtraData,
+}
+```
+
+
+- Provides serialization and deserialization functionality for a type.
+
+- When not to implement: If a type contains sensitive data that should not be
+ erroneously saved to disk or sent over a network, consider not implementing
+ Serialize/Deserialize for that type.
+
+ Shares security concerns with `Debug`, but given serialization is often used
+ in networking there can be higher stakes.
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/common-traits/try-from-into.md b/src/idiomatic/foundations-api-design/predictable-api/common-traits/try-from-into.md
new file mode 100644
index 000000000000..ed41c4f080bd
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/common-traits/try-from-into.md
@@ -0,0 +1,47 @@
+---
+minutes: 5
+---
+
+# TryFrom/TryInto
+
+Fallible conversion from one type to another.
+
+Derivable: ❌
+
+When to implement: As-needed.
+
+```rust
+#[derive(Debug)]
+pub struct InvalidNumber;
+
+#[derive(Debug)]
+pub struct DivisibleByTwo(usize);
+
+impl TryFrom for DivisibleByTwo {
+ type Error = InvalidNumber;
+ fn try_from(value: usize) -> Result {
+ if value.rem_euclid(2) == 0 {
+ Ok(DivisibleByTwo(value))
+ } else {
+ Err(InvalidNumber)
+ }
+ }
+}
+
+fn main() {
+ let success: Result = 4.try_into();
+ dbg!(success);
+ let fail: Result = 5.try_into();
+ dbg!(fail);
+}
+```
+
+
+- Provides conversion that can fail, returning a result type.
+
+- Like `From`/`Into`, prefer implementing `TryFrom` for types rather than
+ `TryInto`.
+
+- Implementations can specify what the error type of the `Result`.
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions.md
new file mode 100644
index 000000000000..91e306686e3b
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions.md
@@ -0,0 +1,20 @@
+---
+minutes: 2
+---
+
+# Naming Conventions
+
+
+- One core component of readability and predictability is the way function names are composed.
+
+A formal and consistently-applied naming convention lets developers treat names
+like a domain-specific language and quickly understand the functionality and use
+cases of a method.
+
+Rust's community developed naming conventions early, making them mostly
+consistent in places like the standard library.
+
+- Here we'll learn common components of rust method names, giving examples from
+ the standard library and some context to go with them.
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md
new file mode 100644
index 000000000000..e316c8306572
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/as-and-ref.md
@@ -0,0 +1,78 @@
+---
+minutes: 5
+---
+
+# `as_` and `_ref`: reference conversions
+
+`as` is a prefix for methods that convert references. `ref` is a suffix (but
+prefer `as`.)
+
+`as` methods borrow out the primary piece of data contained in `&self`.
+
+Most commonly return references, but can also return a custom borrowing type or
+an unsafe pointer.
+
+```rust,compile_fail
+impl Rc {
+ fn as_ptr(&self) -> *const T;
+
+ // Very common on container types, see how it's also on Option.
+ fn as_ref(&self) -> &T;
+}
+
+impl Option {
+ fn as_ref(&self) -> Option<&T>;
+ // Slices can be empty! So this is 0 or 1 elements.
+ fn as_slice(&self) -> &[T];
+}
+
+impl OwnedFd {
+ // Covered later.
+ fn as_fd(&'a self) -> BorrowedFd<'a>;
+}
+```
+
+
+
+- Method that returns a borrow of the primary piece of contained data.
+
+- The borrowing relationship is most often straightforward: the return value is
+ a reference that borrows `self`.
+
+- Borrowing can also be subtle, and merely implied.
+
+ - The returned value could be a custom borrowing type, fore example,
+ `BorrowedFd` borrows `OwnedFd` through an explicit lifetime.
+
+ - We cover custom borrowing types later in this deep dive,
+ [PhantomData: OwnedFd & BorrowedFd](../../../leveraging-the-type-system/borrow-checker-invariants/phantomdata-04-borrowedfd.md).
+
+ - The returned value could borrow `self` only logically, for example,
+ `as_ptr()` methods return an unsafe pointer. The borrow checker does not
+ track borrowing for pointers.
+
+- The type implementing an "as" method should contain one primary piece of data
+ that is being borrowed out.
+
+ - The "as" naming convention does not work if the data type is an aggregate of
+ many fields without an obvious primary one. Think about the call site:
+
+ ```rust,compile_fail
+ my_vec.as_ptr() // OK
+ my_person.as_first_name() // does not read right, don't use "as_"
+ my_person.first_name() // OK
+ ```
+
+ - If you want to have two getters that you need to distinguish, one that
+ returns first name by value, and another one that returns it by reference,
+ use `_ref` suffix:
+
+ ```rust,compile_fail
+ impl Person {
+ fn first_name(&self) -> String
+ fn first_name_ref() -> &str
+ fn first_name_mut() -> &mut String
+ }
+ ```
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md
new file mode 100644
index 000000000000..7a980900c650
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/by.md
@@ -0,0 +1,61 @@
+---
+minutes: 2
+---
+
+# `by`: custom comparator or projection
+
+Component for methods that take a custom projection or comparison function.
+
+```rust,compile_fail
+impl [T] {
+ // Simplified
+ fn sort_by(&mut self, compare: impl FnMut(&T, &T) -> Ordering);
+
+ // Uses a predicate to determine what items end up in non-overlapping chunks.
+ fn chunk_by_mut bool>(
+ &mut self,
+ pred: F,
+ ) -> ChunkByMut<'_, T, F>;
+}
+
+trait Iterator {
+ // Provided method of Iterator. Simplified.
+ fn min_by(
+ self,
+ compare: impl FnMut(&Self::Item, &Self::Item) -> Ordering,
+ ) -> Option;
+}
+```
+
+
+- Method will take a comparison or projection function.
+
+A projection function here being a function that, given a reference to a value
+that exists in the data structure, will compute a value to perform the principle
+computation with.
+
+Methods like `sort_by_key` allow us to sort by _the hash function I've passed to
+the method_ or sort by _this specific field of the data in the slice_.
+
+For example, if you have a slice of values of some data structure you might want
+to sort them by a field of that data structure, or even a hash value of that
+data.
+
+`sort_by` takes a comparator function directly.
+
+- Most often seen in methods that sort or otherwise manipulate a slice with a
+ custom sort or comparison function rather than by the `Ord` implementation of
+ the type itself.
+
+- Sometimes the "by" preposition is simply a preposition.
+
+ "by", like some other name components, may end up in a method name for normal
+ linguistic reasons rather than holding specific naming convention semantic
+ weight.
+
+ - [`Read::by_ref()`](https://doc.rust-lang.org/std/io/trait.Read.html#method.by_ref)
+
+ - [`Iterator::advance_by()`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.advance_by)
+ iterator method (nightly feature)
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md
new file mode 100644
index 000000000000..b48ff6224055
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/exercise.md
@@ -0,0 +1,53 @@
+---
+minutes: 10
+---
+
+# Exercise
+
+1. What do these names imply they do?
+2. What should we name these signatures?
+
+```rust,compile_fail
+// What are the types of these methods?
+Option::is_some // ?
+slice::get // ?
+slice::get_unchecked_mut // ?
+Option::as_ref // ?
+str::from_utf8_unchecked_mut // ?
+Rc::get_mut // ?
+Vec::dedup_by_key // ?
+
+// What should we name methods with these types?
+fn ____(String) -> Self;
+fn ____(&self) -> Option<&InnerType>; // details for InnerType do not matter.
+fn ____(self, String) -> Self;
+fn ____(&mut self) -> Option<&mut InnerType>;
+```
+
+
+
+- Go through the methods in the example with the class and discuss what the
+ types of the functions should be.
+
+- Go through the unnamed methods and brainstorm what names those methods should
+ have.
+
+ Answers for missing types:
+ - `Option::is_some(&self) -> bool`
+ - `slice::get(&self /* &[T] */, usize) -> Option<&T>`
+ - `slice::get_unchecked_mut(&self /* &[T] */, usize) -> &T` (unsafe and
+ simplified)
+ - `Option::as_ref(&self /* &Option */) -> Option<&T>`
+ - `str::from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str` (unsafe)
+ - `Rc::get_mut(&mut self /* &mut Rc */) -> Option<&mut T>` (simplified)
+ - `Vec::dedup_by_key(&mut self /* &mut Vec */, key: impl FnMut(&mut T) -> K)`
+ (simplified)
+
+ Answers for missing names:
+ - `fn from_string(String) -> Self`
+ - `fn inner(&self) -> Option<&InnerType>` or `as_ref`, depending on context
+ - `fn with_string(self, String) -> Self`
+ - `fn inner_mut(&mut self) -> Option<&mut InnerType>` or `as_ref_mut`,
+ depending on context
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/from.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/from.md
new file mode 100644
index 000000000000..cd9dc2501286
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/from.md
@@ -0,0 +1,59 @@
+---
+minutes: 2
+---
+
+# `from`
+
+A constructor function, strongly implying "type conversion".
+
+```rust,compile_fail
+impl CStr {
+ unsafe fn from_ptr<'a>(ptr: *const i8) -> &'a CStr;
+}
+
+impl Duration {
+ fn from_days(days: u64) -> Duration;
+}
+
+impl Vec {
+ fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Vec;
+}
+
+impl i32 {
+ fn from_ascii(src: &[u8]) -> Result;
+}
+
+impl u32 {
+ fn from_le_bytes(bytes: [u8; 4]) -> u32;
+}
+```
+
+
+- Prefix for constructor-style, `From`-trait-style functions.
+
+- These functions can take multiple arguments, but usually imply the user is
+ doing more of the work than a usual constructor would.
+
+ `new` is still preferred for most constructor-style functions, the implication
+ for `from` is transformation of one data type to another.
+
+- Ask: Without looking at the standard library documentation, what would the
+ argument type of `u32::from_be` be?
+
+ Answer guidance: we already see `u32::from_le_bytes` on the slide, it takes a
+ slice of bytes. So from_le must be simpler, taking not bytes. Think about the
+ contrast between `u32` and `be`. The argument must be a big-endian `u32`!
+
+ Follow-up question: How about `str::from_utf8`?
+
+ Answer guidance: `str` vs `utf8`. The argument can't be a `str` because every
+ `str` is valid UTF-8. So what is the simplest way to provide UTF-8 data? A
+ slice of bytes.
+
+ Follow-up: Why not `str::from_utf8_bytes`?
+
+ Answer: It could be in theory. However, the "omit needless words" principle
+ applies, the word "bytes" would merely repeat the obvious - could a UTF-8
+ sequence ever be non-bytes?
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/get.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/get.md
new file mode 100644
index 000000000000..2e4bdc1cd890
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/get.md
@@ -0,0 +1,31 @@
+---
+minutes: 2
+---
+
+# `get`: Borrow an Element
+
+Getting an element from a collection or container.
+
+```rust,compile_fail
+impl Vec {
+ fn get(&self, index: usize) -> Option<&T> {...}
+}
+
+impl OnceCell {
+ fn get(&self) -> Option<&T> {...}
+}
+```
+
+
+- Gets are trivial, they get a value!
+
+Immutable by default, for the most part.
+
+Should not panic. May return an option or result, depending on the framework.
+
+- Not for fields!
+
+ For private fields you don't want users to have direct, assign a method with a
+ more descriptive name (or the same name as the field) is preferred.
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into.md
new file mode 100644
index 000000000000..c60d37a4ac13
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into.md
@@ -0,0 +1,35 @@
+---
+minutes: 2
+---
+
+# `into`
+
+- Prefix for methods that convert `self` into another type.
+
+Consumes `self`, returns an owned value.
+
+```rust,compile_fail
+impl Vec {
+ fn into_parts(self) -> (NonNull, usize, usize);
+}
+
+impl Cell {
+ fn into_inner(self) -> T;
+}
+```
+
+
+- Prefix for a function that consumes an owned value and transforms it into a value of another type.
+
+Not reinterpret cast! The data can be rearranged, reallocated, changed in any
+way, including losing information.
+
+- corollary to `From`
+
+- `into_iter` consumes a collection (like a vec, or a btreeset, or a hashmap)
+ and produces an iterator over owned values, unlike `iter` and `iter_mut` which
+ produce iterators over reference values.
+
+- Ask the class: what will `Vec::into_raw_parts` do?
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into_inner.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into_inner.md
new file mode 100644
index 000000000000..3d5511b7898d
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/into_inner.md
@@ -0,0 +1,46 @@
+---
+minutes: 2
+---
+
+# Aside: `into_inner`
+
+Special case of `into`: for exclusive pointer types or newtypes, extract the
+internal value.
+
+```rust,compile_fail
+pub struct Wrapper(T);
+
+impl Wrapper {
+ fn into_inner(self) -> T;
+}
+
+pub struct NonZeroU32(u32);
+
+impl NonZeroU32 {
+ fn into_inner(self) -> u32;
+}
+
+impl Cell {
+ fn into_inner(self) -> T;
+}
+```
+
+
+
+- `into_inner` is a method usually found on newtypes: types whose main purpose
+ is to wrap around an existing type and be semantically distinct from other
+ uses of that inner type.
+
+This kind of method is also found on types like `Cell`, which exclusively own
+the internal data.
+
+The purpose of this kind of method is to consume the "wrapper" type and return
+the "contained" value.
+
+- When defining a type with exactly one field, consider if it makes sense to
+ implement an `into_inner` method that consumes `self` and returns the field as
+ an owned value.
+
+ Don't write a method like this if more fields will be added in the future.
+
+
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
new file mode 100644
index 000000000000..3164359fb4b5
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/is.md
@@ -0,0 +1,31 @@
+---
+minutes: 2
+---
+
+# `is_[condition]`: Boolean Check
+
+Check a condition about a datatype.
+
+```rust,compile_fail
+impl Vec {
+ is_empty(&self) -> bool;
+}
+
+impl f32 {
+ is_nan(self) -> bool;
+}
+
+impl u32 {
+ is_power_of_two(self) -> bool;
+}
+```
+
+
+- A boolean condition on a value.
+
+- `is` prefix is preferred over methods with `not` in the name.
+
+ There are no instances of `is_not_` in standard library methods, just use
+ `!value.is_[condition]`.
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/mut.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/mut.md
new file mode 100644
index 000000000000..38a96b55062c
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/mut.md
@@ -0,0 +1,32 @@
+---
+minutes: 2
+---
+
+# `[method]_mut`: Mutable reference access
+
+Suffix for access-style methods.
+
+```rust,compile_fail
+impl Vec {
+ // Simplified
+ fn get_mut(&mut self, usize) -> Option<&T>;
+}
+
+impl [T] {
+ // Simplified
+ fn iter_mut(&mut self) -> impl Iterator- ;
+}
+
+impl str {
+ fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error>;
+}
+```
+
+
+- Mut for Mutability
+
+- Suffix that signifies the method gives access to a mutable reference.
+
+ Requires mutable access to the value you're calling this method on.
+
+
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
new file mode 100644
index 000000000000..014d4b6eee1e
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/new.md
@@ -0,0 +1,31 @@
+---
+minutes: 1
+---
+
+# `new`: Constructor functions
+
+Rust does not have a `new` keyword, instead `new` is a common prefix or whole
+method name.
+
+```rust,compile_fail
+impl Vec {
+ // Creates an empty vec.
+ fn new() -> Vec;
+}
+
+impl Box {
+ fn new(T) -> Box;
+}
+```
+
+
+
+- There's no `new` keyword for rust to initialize a new value, only functions
+ you call or values you directly populate.
+
+ `new` is conventional for the "default" constructor function for a type. It
+ holds no special syntactic meaning.
+
+ This is sometimes a prefix, it sometimes takes arguments.
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/push.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/push.md
new file mode 100644
index 000000000000..33ec8336f733
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/push.md
@@ -0,0 +1,23 @@
+---
+minutes: 2
+---
+
+# `push`
+
+Common on array-like structures.
+
+```rust,compile_fail
+impl Vec {
+ fn push(&mut self, value: T);
+}
+
+impl VecDeque {
+ fn push_back(&mut self, value: T);
+ fn push_front(&mut self, value: T);
+}
+```
+
+
+- Modifies a sequential collection by adding an element.
+
+- Takes `self` by mutable reference.
diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/raw_parts.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/raw_parts.md
new file mode 100644
index 000000000000..0118ba8f5409
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/raw_parts.md
@@ -0,0 +1,32 @@
+---
+minutes: 2
+---
+
+# `raw_parts`
+
+Peeling back safe abstractions on heap data.
+
+```rust,compile_fail
+impl Vec {
+ // Note how this is an unsafe function
+ unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Vec;
+
+ fn into_raw_parts(self) -> (*mut T, usize, usize);
+}
+```
+
+
+
+- `raw_parts` denotes methods that construct items from or decompose items into
+ underlying pointer data and its relevant layout information (capacity, etc.).
+
+- These kinds of methods can be marked as `unsafe` if constructing new values as
+ trust is placed on the user to avoid conditions that might lead to undefined
+ behavior.
+
+ Such a case might be passing a pointer of `sizeof T * 10` to
+ `Vec::from_raw_parts` but also passing `20` as the capacity argument, which
+ would lead to writing or accessing values 10 through 19 in the vector being
+ undefined behavior.
+
+
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
new file mode 100644
index 000000000000..2a019eca44bd
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/to.md
@@ -0,0 +1,60 @@
+---
+minutes: 2
+---
+
+# `to`: Non-consuming Conversion
+
+Prefix to a function that takes a borrowed value and creates an owned value
+
+```rust,compile_fail
+impl str {
+ // &str is not consumed.
+ fn to_owned(&str) -> String;
+
+ fn to_uppercase(&self) -> String;
+}
+
+impl u32 {
+ // take an owned self because `u32` implements `Copy`
+ to_be(self) -> u32;
+}
+```
+
+
+- Methods that create a new owned value without consuming `self`, and imply a type conversion, are named starting with `to`.
+
+- This is not a borrow checker escape hatch, or an instance of unsafe code. A
+ new value is created, the original data is left alone.
+
+- Methods that start with "to" return a different type, and strongly imply a
+ non-trivial type conversion, or even a data transformation. For example,
+ `str::to_uppercase`.
+
+- "to" methods most commonly take `&self`. However they can take `self` by value
+ if the type implements `Copy`: this also ensures that the conversion method
+ call does not consume `self`.
+
+- If you simply want to define a method that takes `&self` and returns an owned
+ value of the same type, implement the `Clone` trait.
+
+Example: to_uppercase creates a version of a string with all uppercase letters.
+
+- If you want to define a method that consumes the source value, use the "into"
+ naming pattern.
+
+- Also seen in functions that convert the endianness of primitives, or copy and
+ expose the value of a newtype.
+
+## More to Explore
+
+- Ask the class: What's the difference between `to_owned` and `into_owned`?
+
+ Answer: `to_owned` appears on reference values like `&str`, whereas
+ `into_owned` appears on owned values that hold reference types, like `Cow`
+ (copy-on-write).
+
+ Types like `Cow` can be owned while containing references that are borrowed,
+ so the owned value of `Cow` is consumed to create an owned value of the
+ reference type it was holding onto.
+
+
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
new file mode 100644
index 000000000000..5f8e45fce32a
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/try.md
@@ -0,0 +1,33 @@
+---
+minutes: 2
+---
+
+# `try_[method]`: Fallible methods with Specific Errors
+
+Prefix for fallible methods that return a `Result`.
+
+```rust,compile_fail
+impl TryFrom for u32 {
+ type Error = TryFromIntError;
+ fn try_from(value: i32) -> Result;
+}
+
+impl Receiver {
+ try_recv(&self) -> Result;
+}
+```
+
+
+- Prefix for methods that can fail, returning a `Result`.
+
+- `TryFrom` is a `From`-like trait for types whose single-value constructors
+ might fail in some way.
+
+- Ask: Why aren't `Vec::get` and other similar methods called `try_get`?
+
+ Methods are named `get` if they return a reference to an existing value and
+ return an `Option` instead of `Result` because there is only one failure mode.
+ For example, only "index out of bounds" for `Vec::get`, and "key does not
+ exist" for `HashMap::get`.
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md
new file mode 100644
index 000000000000..b6637b8d8227
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/unchecked.md
@@ -0,0 +1,58 @@
+---
+minutes: 5
+---
+
+# `unchecked`: Unsafe
+
+`unchecked` distinguishes the unsafe function in a safe/unsafe pair.
+
+Don't add "unchecked" to the name of every unsafe function.
+
+```rust,compile_fail
+impl NonNull {
+ // A checked version of the constructor, `None` on null.
+ fn new(ptr: *mut T) -> Option>
+
+ // Unchecked constructor, you can violate the non-null invariant!
+ unsafe fn new_unchecked(ptr: *mut T) -> NonNull
+}
+
+impl Vec {
+ // Panics on OOB, old API design.
+ fn split_at(&self, mid: usize) -> (&[T], &[T])
+
+ // Newer method, returns `None` if mid > len
+ fn split_at_checked(&self, mid: usize) -> Option<(&[T], &[T])>
+
+ // Unchecked split function, splitting out of bounds is undefined behavior!
+ unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T])
+}
+```
+
+
+- Sometimes we need to define a pair of functions that have very similar behavior, but one is safe, and the other one is unsafe.
+
+- Please take the Unsafe Rust deep dive if you want to learn more about unsafe
+ code. Briefly, unsafe functions transfer the responsibility for memory safety
+ from the compiler to the programmer. If misused, they can trigger undefined
+ behavior.
+
+- Rust does not overload functions on safety, so we use different names for the
+ functions in the pair. To make the names predictable for users, we use a
+ naming convention.
+
+- The safe function gets the short name. We add "unchecked" to the name of the
+ unsafe function.
+
+- We don't add "unchecked" to the name of every unsafe function.
+
+ - In Rust we don't need a naming convention to highlight the danger of unsafe
+ code at the callsite: Rust already requires the caller to write an
+ `unsafe {}` block. This is different from other languages that don't have
+ unsafe blocks, for example, Swift naming convention is to add the word
+ "unsafe" to the type and function names.
+
+ - We only use this naming convention when we want to provide a function pair,
+ and therefore must use different names.
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-closure.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-closure.md
new file mode 100644
index 000000000000..b93dfa8853d6
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-closure.md
@@ -0,0 +1,29 @@
+---
+minutes: 2
+---
+
+# `with`: Working with Closures
+
+`with` as in "do X, but with this specific way of computing things."
+
+```rust,compile_fail
+impl Vec {
+ // Simplified. If the resize is larger than the current vec size, use the
+ // closure to populate elements.
+ pub fn resize_with(&mut self, new_len: usize, f: impl FnMut() -> T);
+}
+
+mod iter {
+ // Create an infinite, lazy iterator using a closure.
+ pub fn repeat_with A>(repeater: F) -> RepeatWith;
+}
+```
+
+
+
+- `with` can appear as a suffix to communicate there is a specific function or
+ closure that can be used instead of a "sensible default" for a computation.
+
+ Similar to [`by`](./by.md).
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-constructor.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-constructor.md
new file mode 100644
index 000000000000..3e92fdfe86f1
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-constructor.md
@@ -0,0 +1,33 @@
+---
+minutes: 2
+---
+
+# `with` as constructor
+
+`with` as a constructor sets one value among a type while using default values
+for the rest.
+
+`with` as in "`` with specific setting."
+
+```rust,compile_fail
+impl Vec {
+ // Initializes memory for at least N elements, len is still 0.
+ fn with_capacity(capacity: usize) -> Vec;
+}
+```
+
+
+
+- `with` can appear as a constructor prefix, most commonly when initializing
+ heap memory for container types.
+
+ In this case, it's distinct from `new` constructors because it specifies the
+ value for something that is not usually cared about by API users.
+
+- Ask the class: Why not `from_capacity`?
+
+ Answer: `Vec::with_capacity` as a method call scans well as creating a "Vec
+ with capacity". Consider how `Vec::new_capacity` or `Vec::from_capacity` scan
+ when written down, they do not communicate what's going on well.
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-copy-setter.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-copy-setter.md
new file mode 100644
index 000000000000..dedd2cd35a89
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-copy-setter.md
@@ -0,0 +1,29 @@
+---
+minutes: 2
+---
+
+# `with` as copy-and-set
+
+`with` appears when a value is being copied, but also changed in a specific way.
+
+`with` as in "like ``, but with something different."
+
+```rust,compile_fail
+impl Path {
+ // Simplified. "/home/me/mortgage.pdf".with_extension("mov") =>
+ // "/home/me/mortgage.mov"
+ fn with_extension(&self, ext: &OsStr) -> PathBuf;
+}
+```
+
+
+
+- `with` can be used for methods that copy a value, but then change a specific
+ part of that value.
+
+ In the example here, `with_extension` copies the data of a `&Path` into a new
+ `PathBuf`, but changes the extension to something else.
+
+ The original `Path` is unchanged.
+
+
diff --git a/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-word.md b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-word.md
new file mode 100644
index 000000000000..98c9bcc4bac2
--- /dev/null
+++ b/src/idiomatic/foundations-api-design/predictable-api/naming-conventions/with-word.md
@@ -0,0 +1,37 @@
+---
+minutes: 2
+---
+
+# `with` in normal use
+
+Sometimes a `with` is just a `with`.
+
+`with` when used in common English contexts.
+
+```rust,compile_fail
+// impl block for slices
+impl [T] {
+ // A condition, but doesn't start with `is`, and uses `with` as a normal word.
+ fn starts_with(&self, &[T]) -> bool;
+}
+```
+
+
+
+- Name fragments are not hard rules, they are guidance. Sometimes a method's
+ name will include words that break its pattern.
+
+- In this example with have `starts_with`, which is a boolean condition that
+ does not start with "is" and is suffixed by "with".
+
+ If naming conventions were to be treated as hard rules, this would fail as a
+ case.
+
+ This is a good name for understanding what is going on at the callsite. We end
+ up writing `.starts_with()` which scans well for authors
+ and readers of code.
+
+- Remember: the point of naming conventions is predictability, and how
+ predictability is in service of callsite clarity and readability.
+
+
diff --git a/src/idiomatic/polymorphism.md b/src/idiomatic/polymorphism.md
new file mode 100644
index 000000000000..f94cbae78c3f
--- /dev/null
+++ b/src/idiomatic/polymorphism.md
@@ -0,0 +1,30 @@
+---
+minutes: 2
+---
+
+# Polymorphism
+
+```rust
+pub trait Trait {}
+
+pub struct HasGeneric(T);
+
+pub enum Either {
+ Left(A),
+ Right(B),
+}
+
+fn takes_generic(value: &T) {}
+
+fn takes_dyn(value: &dyn Trait) {}
+```
+
+
+
+- Rust has plenty of mechanisms for writing and using polymorphic code, but
+ they're somewhat different from other popular languages!
+
+- This chapter will cover the details of Rust's polymorphism and how it's
+ similar, or different to, other languages.
+
+
diff --git a/src/idiomatic/polymorphism/from-oop-to-rust.md b/src/idiomatic/polymorphism/from-oop-to-rust.md
new file mode 100644
index 000000000000..c172bee1870e
--- /dev/null
+++ b/src/idiomatic/polymorphism/from-oop-to-rust.md
@@ -0,0 +1,27 @@
+---
+minutes: 2
+---
+
+# From OOP to Rust: Composition, Not Inheritance
+
+- Inheritance is key to OOP's success as a paradigm. Decades of successful
+ software engineering has been done with Inheritance as a core part of business
+ logic.
+
+- So why did rust avoid inheritance?
+
+- How do we move from inheritance-based problem solving to rust's approach?
+
+- How do you represent heterogeneous collections in rust?
+
+
+
+- In this section we'll be looking at how to move from thinking about
+ polymorphic problem solving with types in OOP languages like java, C++ etc. to
+ Rust's trait-based approach to Polymorphism.
+
+- There will be differences, but there are also plenty of areas in common
+ – especially with modern standards of OOP development. Remember to keep an
+ open mind.
+
+
diff --git a/src/idiomatic/polymorphism/from-oop-to-rust/composition.md b/src/idiomatic/polymorphism/from-oop-to-rust/composition.md
new file mode 100644
index 000000000000..3324813d1974
--- /dev/null
+++ b/src/idiomatic/polymorphism/from-oop-to-rust/composition.md
@@ -0,0 +1,36 @@
+---
+minutes: 5
+---
+
+# Composition over Inheritance
+
+```rust
+pub struct Uuid([u8; 16]);
+
+pub struct Address {
+ street: String,
+ city_or_province: String,
+ code: String,
+ country: String,
+}
+
+pub struct User {
+ id: Uuid,
+ address: Address,
+}
+```
+
+
+
+- Rather than mixins or inheritance, we compose types by creating fields of
+ different types.
+
+ This has downsides, largely in ergonomics of field access, but gives
+ developers a lot of control and clarity over what a type does and it has
+ access to.
+
+- When deriving traits, make sure all the field types of a struct or variant
+ types of an enum implement that trait. Derive macros often assume all types
+ that compose a new type implement that trait already.
+
+
diff --git a/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/any-trait.md b/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/any-trait.md
new file mode 100644
index 000000000000..bfcaafbd400c
--- /dev/null
+++ b/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/any-trait.md
@@ -0,0 +1,49 @@
+---
+minutes: 10
+---
+
+# Any Trait and Downcasting
+
+```rust
+use std::any::Any;
+
+#[derive(Debug)]
+pub struct ThisImplementsAny;
+
+fn take_any(t: &T) {}
+
+fn main() {
+ let is_an_any = ThisImplementsAny;
+ take_any(&is_an_any);
+
+ let dyn_any: &dyn Any = &is_an_any;
+ dbg!(dyn_any.type_id());
+ dbg!(dyn_any.is::());
+ let is_downcast: Option<&ThisImplementsAny> = dyn_any.downcast_ref();
+ dbg!(is_downcast);
+}
+```
+
+
+
+- The `Any` trait allows us to downcast values back from dyn values into
+ concrete values.
+
+- This is an auto trait: like Send/Sync/Sized, it is automatically implemented
+ for any type that meets specific criteria.
+
+- The criteria for Any is that a type is `'static`. That is, the type does not
+ contain any non-`'static` lifetimes within it.
+
+- Any offers two related behaviors: downcasting, and runtime checking of types
+ being the same.
+
+ In the example above, we see the ability to downcast from `Any` into
+ `ThisImplementsAny` automatically.
+
+ We also see `Any::is` being used to check to see what type the value is.
+
+- `Any` does not implement reflection for a type, this is all you can do with
+ `Any`.
+
+
diff --git a/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md b/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md
new file mode 100644
index 000000000000..f81f3d34e0a2
--- /dev/null
+++ b/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-compatible.md
@@ -0,0 +1,54 @@
+---
+minutes: 10
+---
+
+# Dyn-compatible traits
+
+```rust
+pub trait Trait {
+ // dyn compatible
+ fn takes_self(&self);
+
+ // dyn compatible, but you can't use this method when it's dyn
+ fn takes_self_and_param(&self, input: &T);
+
+ // no longer dyn compatible
+ const ASSOC_CONST: i32;
+
+ // no longer dyn compatible
+ fn clone(&self) -> Self;
+}
+```
+
+
+
+- Not all traits are able to be invoked as trait objects. A trait that can be
+ invoked is referred to as a _dyn compatible_ trait.
+
+- This was previously called _object safe traits_ or _object safety_.
+
+- Dynamic dispatch offloads a lot of compile-time type information into runtime
+ vtable information.
+
+ If a concept is incompatible with what we can meaningfully store in a vtable,
+ either the trait stops being dyn compatible or those methods are excluded from
+ being able to be used in a dyn context.
+
+- A trait is dyn-compatible when all its supertraits are dyn-compatible and when
+ it has no associated constants/types, and no methods that depend on generics.
+
+- You'll most frequently run into dyn incompatible traits when they have
+ associated types/constants or return values of `Self` (i.e. the Clone trait is
+ not dyn compatible.)
+
+ This is because the associated data would have to be stored in vtables, taking
+ up extra memory.
+
+ For methods like `clone`, this disqualifies dyn compatibility because the
+ output type depends on the concrete type of `self`.
+
+ref:
+
+- https://doc.rust-lang.org/1.91.1/reference/items/traits.html#r-items.traits.dyn-compatible
+
+
diff --git a/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-trait.md b/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-trait.md
new file mode 100644
index 000000000000..bd5120ab79e0
--- /dev/null
+++ b/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-trait.md
@@ -0,0 +1,39 @@
+---
+minutes: 5
+---
+
+# `dyn Trait` for Dynamic Dispatch in Rust
+
+```rust
+pub trait Trait {}
+
+impl Trait for i32 {}
+impl Trait for String {}
+
+fn main() {
+ let int: &dyn Trait = &42i32;
+ let string: &dyn Trait = &("Hello dyn!".to_owned());
+}
+```
+
+
+
+- Dynamic Dispatch is a tool in Object Oriented Programming that is often used
+ in places where one needs to care more about the behavior of a type than what
+ the type is.
+
+ In OOP languages, dynamic dispatch is often an _implicit_ process and not
+ something you can opt out of.
+
+ In rust, we use `dyn Trait`: an opt-in form of dynamic dispatch.
+
+- For any trait that is _dyn compatible_ we can coerce a reference to a value of
+ that trait into a `dyn Trait` value.
+
+- We call these _trait objects_. Their type is not known at compile time, but
+ their behavior is: what is implemented by the trait itself.
+
+- When you _need_ OOP-style heterogeneous data structures, you can reach for
+ `Box`, but try to keep it homogeneous and generic-based first!
+
+
diff --git a/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-vs-generics.md b/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-vs-generics.md
new file mode 100644
index 000000000000..e99606dfd3d8
--- /dev/null
+++ b/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/dyn-vs-generics.md
@@ -0,0 +1,43 @@
+---
+minutes: 5
+---
+
+# Generic Function Parameters vs dyn Trait
+
+We have two means of writing polymorphic functions, how do they compare?
+
+```rust
+fn print_display(t: &T) {
+ println!("{}", t);
+}
+
+fn print_display_dyn(t: &dyn std::fmt::Display) {
+ println!("{}", t);
+}
+
+fn main() {
+ let int = 42i32;
+ // Monomorphized to a unique function for i32 inputs.
+ print_display(&int);
+ // One per
+ print_display_dyn(&int);
+}
+```
+
+
+
+- We can write polymorphic functions over generics or over trait objects.
+
+- When writing functions with generic parameters, for each unique type that
+ substitutes a parameter a new version of that function is generated.
+
+ We went over this in monomorphization: in exchange for binary size, we gain a
+ greater capacity for optimization.
+
+- When writing functions that take a trait object, only one version of that
+ function will exist in the final binary (not counting inlining.)
+
+- Generic parameters are zero-cost other than binary size. Types must be
+ homogenous (all instances of T can only be the same type).
+
+
diff --git a/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/heterogeneous.md b/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/heterogeneous.md
new file mode 100644
index 000000000000..be6da4bc81d2
--- /dev/null
+++ b/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/heterogeneous.md
@@ -0,0 +1,43 @@
+---
+minutes: 2
+---
+
+# Heterogeneous data with `dyn trait`
+
+```rust
+pub struct Lambda;
+
+impl std::fmt::Display for Lambda {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "λ")
+ }
+}
+
+pub struct Heterogeneous {
+ pub collection: Vec>,
+}
+
+fn main() {
+ let heterogeneous = Heterogeneous {
+ collection: vec![
+ Box::new(42u32),
+ Box::new("Woah".to_string()),
+ Box::new(Lambda),
+ ],
+ };
+ for item in heterogeneous.collection {
+ // We know "item" implements Display, but we know nothing else!
+ println!("Display output: {}", item);
+ }
+}
+```
+
+
+
+- `dyn Trait`, being a dynamic dispatch tool, lets us store heterogeneous data
+ in collections.
+
+- In this example, we're storing types that all implement `std::fmt::Display`
+ and printing all items in that collection to screen.
+
+
diff --git a/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/limits.md b/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/limits.md
new file mode 100644
index 000000000000..46624fd63b18
--- /dev/null
+++ b/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/limits.md
@@ -0,0 +1,41 @@
+---
+minutes: 5
+---
+
+# Limits of Trait Objects
+
+```rust
+use std::any::Any;
+
+pub trait Trait: Any {}
+
+impl Trait for i32 {}
+
+fn main() {
+ dbg!(size_of::()); // 4 bytes, owned value
+ dbg!(size_of::<&i32>()); // 8 bytes, reference
+ dbg!(size_of::<&dyn Trait>()); // 16 bytes, wide pointer
+}
+```
+
+
+
+- Trait objects are a limited way of solving problems.
+
+- If you want to downcast to a concrete type from a trait object, you will need
+ to specify that the trait in question has Any as a supertrait or that the
+ trait object is over the main trait and `Any`.
+
+ Even then, you will still need to cast a `dyn MyTrait` to `dyn Any`
+
+- Trait objects have overhead in memory, they are "wide pointers" that need to
+ hold not just the pointer to the data itself but another pointer for the
+ vtable.
+
+- Trait objects, being dynamically sized types, can only be used practically via
+ reference or pointer types.
+
+ There is a baseline overhead of dereferencing the value and relevant trait
+ methods when using trait objects.
+
+
diff --git a/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/pitfalls.md b/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/pitfalls.md
new file mode 100644
index 000000000000..eb83e51fa0fc
--- /dev/null
+++ b/src/idiomatic/polymorphism/from-oop-to-rust/dynamic-dispatch/pitfalls.md
@@ -0,0 +1,68 @@
+---
+minutes: 10
+---
+
+# Pitfall: Reaching too quickly for `dyn Trait`
+
+```rust
+use std::any::Any;
+
+pub trait AddDyn: Any {
+ fn add_dyn(&self, rhs: &dyn AddDyn) -> Box;
+}
+
+impl AddDyn for i32 {
+ fn add_dyn(&self, rhs: &dyn AddDyn) -> Box {
+ if let Some(downcast) = (rhs as &dyn Any).downcast_ref::() {
+ Box::new(self + downcast)
+ } else {
+ Box::new(*self)
+ }
+ }
+}
+
+fn main() {
+ let i: &dyn AddDyn = &42;
+ let j: &dyn AddDyn = &64;
+ let k: Box = i.add_dyn(j);
+ dbg!((k.as_ref() as &dyn Any).is::());
+ dbg!((k.as_ref() as &dyn Any).downcast_ref::());
+}
+```
+
+
+
+- Coming from an OOP background, it's understandable to reach for this dynamic
+ dispatch tool as early as possible.
+
+- This is not the preferred way of doing things, trait objects put us in a
+ situation where we're exchanging knowledge of a type that both the developer
+ and compiler has for flexibility.
+
+- The above example takes things to the absurd: If adding numbers were tied up
+ in the dynamic dispatch process, it would be difficult to do anything at all.
+
+ But dynamic dispatch is often hidden in a lot of programming languages: here's
+ it is more explicit.
+
+ In the `i32` implementation of `AddDyn`, first we need to attempt to downcast
+ the `rhs` argument to the same type as `i32`, silently failing if this isn't
+ the case.
+
+ Then we need to allocate the new value on the heap, because if we're keeping
+ this in the world of dynamic dispatch then we need to do this.
+
+ Once we've added two values together, if we want to view them we must downcast
+ them again into a "real" type we can print out given the trait bounds tied up
+ in the operation so far.
+
+- Ask the class: Why can't we just add Display bounds in `main` to be able to
+ print things as-is?
+
+ Answer: Because add_dyn returns only a `dyn AddDyn`, we lose information about
+ what the type implements between the argument type and return type. Even if
+ the inputs implement `Display`, the return type does not.
+
+- This leads to less performant code which is harder to understand
+
+
diff --git a/src/idiomatic/polymorphism/from-oop-to-rust/inheritance.md b/src/idiomatic/polymorphism/from-oop-to-rust/inheritance.md
new file mode 100644
index 000000000000..815052b2cb8c
--- /dev/null
+++ b/src/idiomatic/polymorphism/from-oop-to-rust/inheritance.md
@@ -0,0 +1,45 @@
+---
+minutes: 5
+---
+
+# Inheritance in OOP languages
+
+```cpp
+#include
+using namespace std;
+
+// Base class
+class Vehicle {
+public:
+ void accelerate() { }
+ void brake() { }
+};
+
+// Inheriting class
+class Car : public Vehicle {
+public:
+ void honk() { }
+};
+
+int main() {
+ Car myCar; // Create a Car object
+ myCar.accelerate(); // Inherited method
+ myCar.honk(); // Car's own method
+ myCar.brake(); // Inherited method
+ return 0;
+}
+```
+
+
+
+- This should be a short reminder for students about what inheritance is in
+ other languages.
+
+- Inheritance is a mechanism where a "child" type gains the fields and methods
+ of the "parent" types it is inheriting from.
+
+- Methods are able to be overridden as-needed by the inheriting type.
+
+- Can call methods of inherited-from classes with `super`.
+
+
diff --git a/src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md b/src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md
new file mode 100644
index 000000000000..44dff3be8367
--- /dev/null
+++ b/src/idiomatic/polymorphism/from-oop-to-rust/problem-solving.md
@@ -0,0 +1,81 @@
+---
+minutes: 15
+---
+
+# Problem solving: Break Down the Problem
+
+```rust
+// Problem: implementing a GUI API
+
+// Question: What's the minimum useful behavior for a drawing API?
+pub trait DrawApi {
+ fn arc(&self, center: [f32; 2], radius: f32, start_angle: f32, end_angle: f32);
+ fn line(&self, start: [f32; 2], end: [f32; 2]);
+}
+
+pub struct TextDraw;
+
+impl DrawApi for TextDraw {
+ fn arc(&self, center: [f32; 2], radius: f32, start_angle: f32, end_angle: f32) {
+ println!("arc of radius ")
+ }
+
+ fn line(&self, start: [f32; 2], end: [f32; 2]) { /* ... */
+ }
+}
+
+// Question: What's a good API for users?
+
+pub trait Draw {
+ fn draw(&self, surface: &mut T);
+}
+
+pub struct Rect {
+ start: [f32; 2],
+ end: [f32; 2],
+}
+
+impl Draw for Rect {
+ fn draw(&self, surface: &mut T) {
+ surface.line([self.start[0], self.start[1]], [self.end[0], self.start[1]]);
+ surface.line([self.end[0], self.start[1]], [self.end[0], self.end[1]]);
+ surface.line([self.end[0], self.end[1]], [self.start[0], self.end[1]]);
+ surface.line([self.start[0], self.end[1]], [self.start[0], self.start[1]]);
+ }
+}
+```
+
+
+
+- You're already adept at breaking down problems, but you're likely used to
+ reaching for OOP-style methods.
+
+This isn't a drastic change, it just requires re-ordering the way you approach
+things.
+
+- Try to solve the problem with either Generics & Traits or Enums first.
+
+ Does the problem require a specific set of types? An enum may be the cleanest
+ way of solving this problem.
+
+ Does the problem really care about the specifics of the types involved, or can
+ behavior be focused on?
+
+- Organize your problem solving around finding a minimum viable amount of
+ knowledge to implement something.
+
+ Does a trait already exist for this use case? If so, use it!
+
+- If you really do need heterogeneous collections, use them! They exist in rust
+ as a tool for a reason.
+
+ Be aware of the XY problem: a problem may seem most easily addressable by one
+ solution, but it might not tackle the root cause and could lead to new
+ difficult problems popping up in the future.
+
+ That is, be certain that dynamic dispatch with trait objects is what you need
+ before you commit to using them.
+
+ Be certain that traits are what you need before you commit to using them.
+
+
diff --git a/src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md b/src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md
new file mode 100644
index 000000000000..741ca22ed05b
--- /dev/null
+++ b/src/idiomatic/polymorphism/from-oop-to-rust/sealed-traits.md
@@ -0,0 +1,53 @@
+---
+minutes: 5
+---
+
+# Sealed traits for Polymorphism users cannot extend
+
+```rust
+// crate can access the "sealed" module and its trait, but projects that
+// depend on it cannot.
+mod sealed {
+ pub trait Sealed {}
+ impl Sealed for String {}
+ impl Sealed for Vec {}
+ //...
+}
+
+pub trait APITrait: sealed::Sealed {
+ /* methods */
+}
+impl APITrait for String {}
+impl APITrait for Vec {}
+```
+
+
+
+- Motivation: We want trait-driven code in a crate, but we don't want projects
+ that depend on this crate to be able to implement a trait.
+
+Why?
+
+The trait could be considered unstable for downstream-implementations at this
+point in time.
+
+Alternatively: Domain is high-risk for naive implementations of a trait (such as
+cryptography).
+
+- The mechanism we use to do this is restricting access to a supertrait,
+ preventing downstream users from being able to implement that trait for their
+ types.
+
+- Why not just use enums?
+
+ - Enums expose implementation details – "this works for these types".
+
+ - Users need to use variant constructors of an enum to use the API.
+
+ - Users can use the enum as a type in their own code, and when the enum
+ changes users need to update their code to match those changes.
+
+ - Enums require branching on variants, whereas sealed traits lets the compile
+ specify monomorphized functions for each type.
+
+
diff --git a/src/idiomatic/polymorphism/from-oop-to-rust/sealing-with-enums.md b/src/idiomatic/polymorphism/from-oop-to-rust/sealing-with-enums.md
new file mode 100644
index 000000000000..0257d8ab1d48
--- /dev/null
+++ b/src/idiomatic/polymorphism/from-oop-to-rust/sealing-with-enums.md
@@ -0,0 +1,48 @@
+---
+minutes: 5
+---
+
+# Sealing with Enums
+
+```rust
+use std::collections::BTreeMap;
+pub enum GetSource {
+ WebUrl(String),
+ BytesMap(BTreeMap>),
+}
+
+impl GetSource {
+ fn get(&self, url: &str) -> Option<&Vec> {
+ match self {
+ Self::WebUrl(source) => unimplemented!(),
+ Self::BytesMap(map) => map.get(url),
+ }
+ }
+}
+```
+
+
+
+- Motivation: API is designed around a specific list of types that are valid for
+ it, users of the API are not expected to extend it.
+
+- Enums in Rust are _algebraic data types_, we can define different structures
+ for each variant.
+
+ For some domains, this might be enough polymorphism for the problem.
+ Experiment and see what works, what solutions seem to make more sense.
+
+- By having the user-facing part of the API refer to an enum, users know what
+ types are valid inputs and can construct those types using the available
+ methods to do so.
+
+ - If the types that make up the enum have invariants that the API internally
+ upholds, and the only way users can construct those types is through
+ constructors that build and maintain those invariants, then you can be sure
+ that inputs to a generic method uphold their invariants.
+
+ - If the types that make up the enum instead are types the user can freely
+ construct, then sanitisation and interpretation may need to be taken into
+ consideration.
+
+
diff --git a/src/idiomatic/polymorphism/from-oop-to-rust/sticking-with-traits.md b/src/idiomatic/polymorphism/from-oop-to-rust/sticking-with-traits.md
new file mode 100644
index 000000000000..f517ae7669ae
--- /dev/null
+++ b/src/idiomatic/polymorphism/from-oop-to-rust/sticking-with-traits.md
@@ -0,0 +1,39 @@
+---
+minutes: 2
+---
+
+# Traits for Polymorphism users can extend
+
+```rust
+// Crate A
+
+pub trait Trait {
+ fn use_trait(&self) {}
+}
+
+// Crate B, depends on A
+
+pub struct Data(u8);
+
+impl Trait for Data {}
+
+fn main() {
+ let data = Data(7u8);
+ data.use_trait();
+}
+```
+
+
+
+- We've already covered normal traits at length, but compared to enums and
+ sealed traits they allow users to extend an API by implementing the behavior
+ that API asks of them.
+
+This ability for users to extend is powerful for a number of domains, from
+serialization to abstract representations of hardware and type safe linear
+algebra.
+
+- If a trait is exposed publicly in a crate, a user depending on that crate can
+ implement that trait for types they define.
+
+
diff --git a/src/idiomatic/polymorphism/from-oop-to-rust/supertraits.md b/src/idiomatic/polymorphism/from-oop-to-rust/supertraits.md
new file mode 100644
index 000000000000..af66868568c7
--- /dev/null
+++ b/src/idiomatic/polymorphism/from-oop-to-rust/supertraits.md
@@ -0,0 +1,36 @@
+---
+minutes: 5
+---
+
+# "Inheritance" in Rust: Supertraits
+
+```rust
+pub trait SuperTrait {}
+
+pub trait Trait: SuperTrait {}
+```
+
+
+
+- In Rust, traits can depend on other traits. We're already familiar with Traits
+ being able to have Supertraits.
+
+- This looks superficially similar to inheritance.
+
+- This is a mechanism like inheritance, but separates the data from the
+ behavior.
+
+- Keeps behavior in a state where it's easy to reason about.
+
+- Makes what we aim to achieve with "multiple inheritance" easier too:
+
+ We only care about what behavior a type is capable of at the point where we
+ clarify we want that behavior (when bounding a generic by traits).
+
+ By specifying multiple traits on a generic, we know that the type has the
+ methods of all those traits.
+
+- Does not involve inheritance of fields. A trait doesn't expose fields, only
+ methods and associated types / constants.
+
+
diff --git a/src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md b/src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md
new file mode 100644
index 000000000000..49627b322a66
--- /dev/null
+++ b/src/idiomatic/polymorphism/from-oop-to-rust/switch-perspective.md
@@ -0,0 +1,57 @@
+---
+minutes: 5
+---
+
+# Inheritance from Rust's Perspective
+
+```rust
+// Data
+pub struct Data {
+ id: usize,
+ name: String,
+}
+
+// Concrete behavior
+impl Data {
+ fn new(id: usize, name: impl Into) -> Self {
+ Self { id, name: name.into() }
+ }
+}
+
+// Abstract behavior
+trait Named {
+ fn name(&self) -> &str;
+}
+
+// Instanced behavior
+impl Named for Data {
+ fn name(&self) -> &str {
+ &self.name
+ }
+}
+```
+
+
+
+- From Rust's perspective, one where Inheritance was never there, introducing
+ inheritance would look like muddying the water between types and traits.
+
+- A type is a concrete piece of data and its associated behavior.
+
+ A trait is abstract behavior that must be implemented by a type.
+
+ A class is a combination of data, behavior, and overrides to that behavior.
+
+- Coming from rust, an inheritable class looks like a type that is also a trait.
+
+- This is not an upside, as we can no longer reason about concrete types.
+
+- Without being able to separate the two, it becomes difficult to reason about
+ generic behavior vs concrete specifics, because in OOP these two concepts are
+ tied up in each other.
+
+- The convenience of flat field access and DRY in type definitions is not worth
+ the loss in specificity between writing code that delineates between behavior
+ and data.
+
+
diff --git a/src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md b/src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md
new file mode 100644
index 000000000000..134db3e636c4
--- /dev/null
+++ b/src/idiomatic/polymorphism/from-oop-to-rust/why-no-inheritance.md
@@ -0,0 +1,73 @@
+---
+minutes: 10
+---
+
+# Why no Inheritance in Rust?
+
+```rust,compile_fail
+pub struct Id {
+ pub id: u32
+}
+
+impl Id {
+ // methods
+}
+
+// 🔨❌, rust does not have inheritance!
+pub struct Data: Id {
+ // Inherited "id" field
+ pub name: String,
+}
+
+impl Data {
+ // methods, but also includes Id's methods, or maybe overrides to
+ // those methods.
+}
+
+// ✅
+pub struct Data {
+ pub id: Id,
+ pub name: String,
+}
+
+impl Data {
+ // All of data's methods that aren't from traits.
+}
+
+impl SomeTrait for Data {
+ // Implementations for traits in separate impl blocks.
+}
+```
+
+
+
+- Inheritance comes with a number of downsides.
+
+- Heterogeneous by default:
+
+ Class inheritance implicitly allows types of different classes to be used
+ interchangeably, without being able to specify a concrete type or if a type is
+ identical to another.
+
+ For operations like equality, comparison this allows for comparison and
+ equality that throws and error or otherwise panics.
+
+- Multiple sources of truth for what makes up a data structure and how it
+ behaves:
+
+ A type's fields are obscured by the inheritance hierarchy.
+
+ A type's methods could be overriding a parent type or be overridden by a child
+ type, it's hard to tell what the behavior of a type is in complex codebases
+ maintained by multiple parties.
+
+- Dynamic dispatch as default adds overhead from vtable lookups:
+
+ For dynamic dispatch to work, there needs to be somewhere to store information
+ on what methods to call and other pieces of runtime-known pieces of
+ information on the type.
+
+ This store is the `vtable` for a value. Method calls will require more
+ dereferences than calling a method for a type that is known at compile time.
+
+
diff --git a/src/idiomatic/polymorphism/refresher.md b/src/idiomatic/polymorphism/refresher.md
new file mode 100644
index 000000000000..518d053c4edf
--- /dev/null
+++ b/src/idiomatic/polymorphism/refresher.md
@@ -0,0 +1,22 @@
+---
+minutes: 2
+---
+
+# Refresher
+
+Basic features of Rust's generics and polymorphism.
+
+```rust,compile_fail
+pub struct HasGenerics(...);
+
+pub fn uses_traits(input: T) {...}
+
+pub trait TraitBounds: Clone {...}
+```
+
+
+
+- In this section we'll be going through the core concepts of Rust's approach to
+ polymorphism, the things you'll run into the most in day-to-day usage.
+
+
diff --git a/src/idiomatic/polymorphism/refresher/blanket-impls.md b/src/idiomatic/polymorphism/refresher/blanket-impls.md
new file mode 100644
index 000000000000..286e23ac98a6
--- /dev/null
+++ b/src/idiomatic/polymorphism/refresher/blanket-impls.md
@@ -0,0 +1,59 @@
+---
+minutes: 10
+---
+
+# Blanket Trait Implementations
+
+When a trait is local, we can implement it for as many types as we like. How far
+can we take this?
+
+```rust
+pub trait PrettyPrint {
+ fn pretty_print(&self);
+}
+
+// A blanket implementation! If something implements Display, it implements
+// PrettyPrint.
+impl PrettyPrint for T
+where
+ T: std::fmt::Display,
+{
+ fn pretty_print(&self) {
+ println!("{self}")
+ }
+}
+```
+
+
+
+- The subject of a trait implementation at the definition site of a trait can be
+ anything, including `T` with no bounds.
+
+ We can't do anything with a `T` we don't know nothing about, so this is
+ uncommon.
+
+- Conditional blanket implementations are much more useful and you are more
+ likely to see and author them.
+
+ These implementations will have a bound on the trait, like
+ `impl ToString for T {...}`
+
+ In the example above we have a blanket implementation for all types that
+ implement Display, the implementation has one piece of information available
+ to it from the trait bounds: it implements `Display::fmt`.
+
+ This is enough to write an implementation for pretty printing to console.
+
+- Do be careful with these kinds of implementations, as it may end up preventing
+ users downstream from implementing a more meaningful.
+
+ The above isn't written for `Debug` as that would mean almost all types end up
+ implementing `PrettyPrint`, and `Debug` is not semantically similar to
+ `Display`: It's meant for debug output instead of something more
+ human-readable.
+
+ref:
+
+- https://doc.rust-lang.org/reference/glossary.html#blanket-implementation
+
+
diff --git a/src/idiomatic/polymorphism/refresher/conditional-methods.md b/src/idiomatic/polymorphism/refresher/conditional-methods.md
new file mode 100644
index 000000000000..e97e8e9d0d23
--- /dev/null
+++ b/src/idiomatic/polymorphism/refresher/conditional-methods.md
@@ -0,0 +1,47 @@
+---
+minutes: 5
+---
+
+# Conditional Method Implementations
+
+```rust
+// No trait bounds on the type definition.
+pub struct Value(T);
+
+// Instead bounds are put on the implementations for the type.
+impl Value {
+ fn log(&self) {
+ println!("{}", self.0);
+ }
+}
+
+// alternatively
+impl Value {
+ // Specifies the trait bound in a where expression
+ fn log_error(&self)
+ where
+ T: std::error::Error,
+ {
+ eprintln!("{}", self.0);
+ }
+}
+```
+
+
+
+- When authoring a type with generic parameters, we can write implementations
+ for that type that depend on what the parameters are or what traits they
+ implement.
+
+- These methods are only available when the type meets those conditions.
+
+- For things like ordered sets, where you'd want the inner type to always be
+ `Ord`, this is the preferred way of putting a trait bound on a parameter of a
+ type.
+
+ We don't put the definition on the type itself as this would cause downstream
+ issues for everywhere the type is mentioned with a generic parameter.
+
+ We can maintain invariants just fine with conditional method implementations.
+
+
diff --git a/src/idiomatic/polymorphism/refresher/default-impls.md b/src/idiomatic/polymorphism/refresher/default-impls.md
new file mode 100644
index 000000000000..06e74b712c81
--- /dev/null
+++ b/src/idiomatic/polymorphism/refresher/default-impls.md
@@ -0,0 +1,44 @@
+---
+minutes: 5
+---
+
+# Default Method Implementations
+
+```rust
+pub trait CollectLeaves {
+ type Leaf;
+
+ // Required Method
+ fn collect_leaves_buffered(&self, buf: &mut Vec);
+
+ // Default implementation
+ fn collect_leaves(&self) -> Vec {
+ let mut buf = vec![];
+ self.collect_leaves_buffered(&mut buf);
+ buf
+ }
+}
+```
+
+
+
+- Traits often have methods that are implemented for you already, once you
+ implement the required methods.
+
+- A trait method has a default implementation if the function body is present.
+ This implementation can be written in terms of other methods available, such
+ as other methods in the trait or methods of a supertrait.
+
+- Often you'll see methods that provide the broad functionality that is
+ necessary to implement (like `Ord`'s `compare`) with default implementations
+ for functions that can be implemented in terms of those methods (like `Ord`'s
+ `max`/`min`/`clamp`).
+
+- Default methods can be overridden by derive macros, as derive macros produce
+ arbitrary ASTs in the implementation.
+
+ref:
+
+- https://doc.rust-lang.org/reference/items/traits.html#r-items.traits.associated-item-decls
+
+
diff --git a/src/idiomatic/polymorphism/refresher/deriving-traits.md b/src/idiomatic/polymorphism/refresher/deriving-traits.md
new file mode 100644
index 000000000000..621c7d4a0979
--- /dev/null
+++ b/src/idiomatic/polymorphism/refresher/deriving-traits.md
@@ -0,0 +1,49 @@
+---
+minutes: 10
+---
+
+# Deriving Traits
+
+```rust
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
+struct BufferId([u8; 16]);
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
+struct DrawingBuffer {
+ target: [u8; 16],
+ commands: Vec,
+}
+```
+
+
+
+- Many traits, protocols, interfaces, have trivial implementations that would be
+ easy to mechanically write.
+
+- Definitions of types (their syntax trees) can be fed to procedural macros
+ (compiler plugins) to automatically generate implementations of traits.
+
+ These macros have to be authored by someone, the compiler cannot figure out
+ everything by itself.
+
+- Many traits have a naive, obvious implementation. Mostly implementations that
+ depend on all fields or variants already implementing the trait.
+
+ `PartialEq`/`Eq` can be derived on types whose fields / variants all implement
+ those traits fairly easily: line up the fields / variants, if any of them
+ don't match then the equality check returns false.
+
+- Derives let us avoid boilerplate mechanically and predictably, the authors of
+ a derive implementation likely authored the trait the derive was implemented
+ with the proper semantics of a trait in mind.
+
+- Ask the class: Have the students had to deal with a codebase where most of the
+ code was trivial boilerplate?
+
+- This is similar to Haskell's `deriving` system.
+
+references:
+
+- https://doc.rust-lang.org/reference/attributes/derive.html#r-attributes.derive
+
+
diff --git a/src/idiomatic/polymorphism/refresher/monomorphization.md b/src/idiomatic/polymorphism/refresher/monomorphization.md
new file mode 100644
index 000000000000..5550da6eb3e6
--- /dev/null
+++ b/src/idiomatic/polymorphism/refresher/monomorphization.md
@@ -0,0 +1,45 @@
+---
+minutes: 10
+---
+
+# Monomorphization and Binary Size
+
+```rust
+fn print_vec(debug_vec: &Vec) {
+ for item in debug_vec {
+ println!("{:?}", item);
+ }
+}
+
+fn main() {
+ let ints = vec![1u32, 2, 3];
+ let floats = vec![1.1f32, 2.2, 3.3];
+
+ // instance one, &Vec -> ()
+ print_vec(&ints);
+ // instance two, &Vec -> ()
+ print_vec(&floats);
+}
+```
+
+
+
+- Each instance of a function or type with generics gets transformed into a
+ unique, concrete version of that function at compile time. Generics do not
+ exist at runtime, only specific types.
+
+- This comes with a strong baseline performance and capacity for optimization,
+ but at a cost of binary size and compile time.
+
+- There are plenty of ways to trim binary size and compilation times, but we're
+ not covering them here.
+
+- Pay for what you use: Binary size increase of monomorphization is only
+ incurred for instances of a type or functions on a type used in the final
+ program or dynamic library.
+
+- When to care: Monomorphization impacts compile times and binary size. In
+ circumstances like WebAssembly in-browser or embedded systems development, you
+ may want to be mindful about designing with generics in mind.
+
+
diff --git a/src/idiomatic/polymorphism/refresher/orphan-rule.md b/src/idiomatic/polymorphism/refresher/orphan-rule.md
new file mode 100644
index 000000000000..c28bfae7dfd3
--- /dev/null
+++ b/src/idiomatic/polymorphism/refresher/orphan-rule.md
@@ -0,0 +1,69 @@
+---
+minutes: 10
+---
+
+# Orphan Rule
+
+What prevents users from writing arbitrary trait implementations for any type?
+
+```rust,compile_fail
+// Crate `postgresql-bindings`
+
+pub struct PostgresqlConn(/* details */);
+
+// Crate `database-traits`, depends on `postgresql-bindings`
+
+pub trait DbConnection {
+ /* methods */
+}
+
+impl DbConnection for PostgresqlConn {} // ✅, `DbConnection` is local.
+
+// Crate `mycoolnewdb` depends on `database-traits`
+
+pub struct MyCoolNewDbConn(/* details */);
+
+impl DbConnection for MyCoolNewDbConn {} // ✅, `MyCoolNewDbConn` is local.
+
+// Neither `PostgresqlConn` or `DbConnection` are local to `mycoolnewdb`.
+// This would lead to two implementations of `DbConnection` for PostgresqlConn!
+impl DbConnection for PostgresqlConn {} // ❌🔨
+```
+
+
+
+- Rust traits should never be able to be implemented twice in its ecosystem. Two
+ implementations of the same trait for the same type is a conflict with no
+ solution.
+
+- We can prevent this within a crate by detecting if there are multiple
+ definitions and disallowing it, but what about between crates in the entire
+ rust ecosystem?
+
+- Types are either _local_ to a crate, they are defined there, or they're not.
+
+ In the example's "crates", `PostgresqlConn` is local to `postgresql-bindings`,
+ `MyCoolNewDbConn` is local to `mycoolnewdb`.
+
+- Traits are also either _local_ to a crate, they are defined there, or they're
+ not.
+
+ Again in the example, the `DbConnection` trait is local to `database-traits`.
+
+- If something is local, you can write trait implementations for it.
+
+ If the trait is local, you can write implementations of that trait for any
+ type.
+
+ If the type is local, you can write any trait implementations for that type.
+
+- Outside of these boundaries, trait implementations cannot be written.
+
+ This keeps implementations "coherent": Only one implementation of a trait for
+ a type can exist across crates.
+
+ref:
+
+- https://doc.rust-lang.org/stable/reference/items/implementations.html#r-items.impl.trait.orphan-rule
+
+
diff --git a/src/idiomatic/polymorphism/refresher/sized.md b/src/idiomatic/polymorphism/refresher/sized.md
new file mode 100644
index 000000000000..9bec328a873f
--- /dev/null
+++ b/src/idiomatic/polymorphism/refresher/sized.md
@@ -0,0 +1,39 @@
+---
+minutes: 2
+---
+
+# Statically Sized and Dynamically Sized Types
+
+```rust
+use std::fmt::Debug;
+
+pub struct AlwaysSized(T);
+
+pub struct OptionallySized(T);
+
+type Dyn1 = OptionallySized;
+```
+
+
+
+- Motivation: Being able to specify between types whose size are known and
+ compile time and types whose size are known at runtime is useful for
+
+- The Sized trait is automatically implemented by types with a known size at
+ compile-time.
+
+ This trait is also automatically added to any type parameter that doesn't
+ opt-out of being sized.
+
+- Most types implement `Sized`: they have a compile-time known size.
+
+ Types like `[T]`, `str` and `dyn Trait` are all dynamically sized types. Their
+ size is stored as part of the reference to the value of that type.
+
+- Type parameters automatically implement `Sized` unless specified.
+
+ref:
+
+- https://doc.rust-lang.org/stable/reference/dynamically-sized-types.html#r-dynamic-sized
+
+
diff --git a/src/idiomatic/polymorphism/refresher/supertraits.md b/src/idiomatic/polymorphism/refresher/supertraits.md
new file mode 100644
index 000000000000..8a7ed769ecd6
--- /dev/null
+++ b/src/idiomatic/polymorphism/refresher/supertraits.md
@@ -0,0 +1,49 @@
+---
+minutes: 5
+---
+
+# Supertraits / Trait Dependencies
+
+Traits can be extended by new traits.
+
+```rust
+pub trait DeviceId {
+ /* trait for device ID types */
+}
+
+pub trait GraphicsDevice: DeviceId {
+ /* Graphics device specifics */
+}
+
+// From stdlib
+
+pub trait Ord: PartialOrd {
+ /* methods for Ord */
+}
+```
+
+
+
+- When authoring a trait, you can specify traits that a type must also. These
+ are called _Supertraits_.
+
+ For the example above, any type that implements `GraphicsDevice` must also
+ implement `DeviceId`.
+
+- These hierarchies of traits let us design systems around the behavior of
+ complex real-world taxonomies (like machine hardware, operating system
+ specifics).
+
+- This is distinct from object inheritance! But it looks similar.
+
+ - Object inheritance allows for overrides and brings in the behavior of the
+ inherited types by default.
+
+ - A trait having a supertrait doesn't mean that trait can override method
+ implementations as default implementations.
+
+ref:
+
+- https://doc.rust-lang.org/reference/items/traits.html?highlight=supertrait#r-items.traits.supertraits
+
+
diff --git a/src/idiomatic/polymorphism/refresher/trait-bounds.md b/src/idiomatic/polymorphism/refresher/trait-bounds.md
new file mode 100644
index 000000000000..bb6db4fe529d
--- /dev/null
+++ b/src/idiomatic/polymorphism/refresher/trait-bounds.md
@@ -0,0 +1,39 @@
+---
+minutes: 5
+---
+
+# Trait Bounds on Generics
+
+```rust
+use std::fmt::Display;
+
+fn print_with_length(item: T) {
+ println!("Item: {}", item);
+ println!("Length: {}", item.to_string().len());
+}
+
+fn main() {
+ let number = 42;
+ let text = "Hello, Rust!";
+
+ print_with_length(number); // Works with integers
+ print_with_length(text); // Works with strings
+}
+```
+
+
+
+- Traits are most commonly used as bounds on generic type parameters for a
+ function or method.
+
+ Without a trait bound on a generic type parameter, we don't have access to any
+ behavior to write functions and methods with.
+
+ Trait bounds allow us to specify the minimum viable behavior of a type for it
+ to work in generic code.
+
+ref:
+
+- https://doc.rust-lang.org/reference/trait-bounds.html
+
+
diff --git a/src/idiomatic/polymorphism/refresher/traits.md b/src/idiomatic/polymorphism/refresher/traits.md
new file mode 100644
index 000000000000..e0f23d93b3a9
--- /dev/null
+++ b/src/idiomatic/polymorphism/refresher/traits.md
@@ -0,0 +1,63 @@
+---
+minutes: 10
+---
+
+# Traits, Protocols, Interfaces
+
+```rust
+trait Receiver {
+ fn send(&self, message: &str);
+}
+
+struct Email {
+ email: String,
+}
+
+impl Receiver for Email {
+ fn send(&self, message: &str) {
+ println!("Email to {}: {}", self.email, message);
+ }
+}
+
+struct ChatId {
+ uuid: [u8; 16],
+}
+
+impl Receiver for ChatId {
+ fn send(&self, message: &str) {
+ println!("Chat message sent to {:?}: {}", self.uuid, message);
+ }
+}
+```
+
+
+
+- Rust's concept of polymorphism and generics is heavily built around traits.
+
+- Traits are requirements on a type in a generic context.
+
+- Requirements function much like a compile-time checked duck typing.
+
+ Duck typing is a concept from the practice of dynamic, untyped languages like
+ Python, "if it walks like a duck and quacks like a duck, it's a duck."
+
+ That is, types with the methods and fields expected by a function are all
+ valid inputs for that function. If a type implements methods, it is that type
+ in a duck-typing context.
+
+ Traits behave like a static duck typing mechanism, in that we specify behavior
+ rather than type. But we get the compile-time checks on if that behavior does
+ really exist.
+
+- Alternatively: Traits are like collections of propositions, and implementing a
+ trait for a type is a proof that the type can be used wherever the trait is
+ asked for.
+
+ Traits have required methods, implementing those methods is the proof that a
+ type has the required behavior.
+
+reference:
+
+- https://doc.rust-lang.org/reference/items/traits.html
+
+