Skip to content

Commit

Permalink
Reduce references to niche optimization
Browse files Browse the repository at this point in the history
Niche optimization is currently mentioned in three places:
 - Enums (User-Defined Types, Day 1 Afternoon)
 - Option (Standard Library Types, Day 2 Afternoon)
 - Box (Smart Pointers, Day 3 Morning)

This is a tricky thing to get right, and it was just in the speaker
notes in each place. google#1820 will introduce a fuller explanation.
  • Loading branch information
djmitche committed Sep 30, 2024
1 parent 29dcb0c commit 06e7632
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 34 deletions.
36 changes: 4 additions & 32 deletions src/smart-pointers/box.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fn main() {
from `T` directly on a `Box<T>`](https://doc.rust-lang.org/std/ops/trait.Deref.html#more-on-deref-coercion).

Recursive data types or data types with dynamic sizes cannot be stored inline
without a pointer indirection, which can be worked around using `Box`:
without a pointer indirection. `Box` accomplishes that indirection:

```rust,editable
#[derive(Debug)]
Expand Down Expand Up @@ -86,36 +86,8 @@ fn main() {
have to use indirection, a `Box` or reference of some kind, instead of storing
the value directly.

# More to Explore

## Niche Optimization

Though `Box` looks like `std::unique_ptr` in C++, it cannot be empty/null. This
makes `Box` one of the types that allow the compiler to optimize storage of some
enums.

For example, `Option<Box<T>>` has the same size, as just `Box<T>`, because
compiler uses NULL-value to discriminate variants instead of using explicit tag
(["Null Pointer Optimization"](https://doc.rust-lang.org/std/option/#representation)):

```rust,editable
use std::mem::size_of_val;
struct Item(String);
fn main() {
let just_box: Box<Item> = Box::new(Item("Just box".into()));
let optional_box: Option<Box<Item>> =
Some(Box::new(Item("Optional box".into())));
let none: Option<Box<Item>> = None;
assert_eq!(size_of_val(&just_box), size_of_val(&optional_box));
assert_eq!(size_of_val(&just_box), size_of_val(&none));
println!("Size of just_box: {}", size_of_val(&just_box));
println!("Size of optional_box: {}", size_of_val(&optional_box));
println!("Size of none: {}", size_of_val(&none));
}
```
- Though `Box` looks like `std::unique_ptr` in C++, it cannot be empty/null.
This makes `Box` one of the types that allow the compiler to optimize storage
of some enums (the "niche optimization").

</details>
8 changes: 6 additions & 2 deletions src/std-types/option.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ fn main() {
None.
- It's common to `unwrap`/`expect` all over the place when hacking something
together, but production code typically handles `None` in a nicer fashion.
- The niche optimization means that `Option<T>` often has the same size in
memory as `T`.

- The "niche optimization" means that `Option<T>` often has the same size in
memory as `T`, if there is some representation that is not a valid value of T.
For example, a reference cannot be NULL, so `Option<&T>` automatically uses
NULL to represent the `None` variant, and thus can be stored in the same
memory as `&T`.

</details>

0 comments on commit 06e7632

Please sign in to comment.