You've already forked comprehensive-rust
mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-06-22 16:57:41 +02:00
Minor fixes for Day 3 Morning (#532)
* don't explain default trait methods early * talk about Iterator before IntoIterator * Defer discussion of trait objects to that chapter * be more specific about turbofish, in speaker notes
This commit is contained in:
committed by
GitHub
parent
8c56c949ef
commit
780368b4f7
@ -16,7 +16,6 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
* `impl Trait` cannot be used with the `::<>` turbo fish syntax.
|
||||
* `impl Trait` allows you to work with types which you cannot name.
|
||||
|
||||
<details>
|
||||
@ -24,15 +23,22 @@ fn main() {
|
||||
The meaning of `impl Trait` is a bit different in the different positions.
|
||||
|
||||
* For a parameter, `impl Trait` is like an anonymous generic parameter with a trait bound.
|
||||
|
||||
* For a return type, it means that the return type is some concrete type that implements the trait,
|
||||
without naming the type. This can be useful when you don't want to expose the concrete type in a
|
||||
public API.
|
||||
|
||||
Inference is hard in return position. A function returning `impl Foo` picks
|
||||
the concrete type it returns, without writing it out in the source. A function
|
||||
returning a generic type like `collect<B>() -> B` can return any type
|
||||
satisfying `B`, and the caller may need to choose one, such as with `let x:
|
||||
Vec<_> = foo.collect()` or with the turbofish, `foo.collect::<Vec<_>>()`.
|
||||
|
||||
This example is great, because it uses `impl Display` twice. It helps to explain that
|
||||
nothing here enforces that it is _the same_ `impl Display` type. If we used a single
|
||||
`T: Display`, it would enforce the constraint that input `T` and return `T` type are the same type.
|
||||
It would not work for this particular function, as the type we expect as input is likely not
|
||||
what `format!` returns. If we wanted to do the same via `: Display` syntax, we'd need two
|
||||
independent generic parameters.
|
||||
|
||||
|
||||
</details>
|
||||
|
@ -19,7 +19,7 @@ However, how can we store a collection of mixed types which implement `Display`?
|
||||
|
||||
```rust,editable,compile_fail
|
||||
fn main() {
|
||||
let xs = vec![123, "Hello"];
|
||||
let displayables = vec![123, "Hello"];
|
||||
}
|
||||
```
|
||||
|
||||
@ -29,20 +29,20 @@ For this, we need _trait objects_:
|
||||
use std::fmt::Display;
|
||||
|
||||
fn main() {
|
||||
let xs: Vec<Box<dyn Display>> = vec![Box::new(123), Box::new("Hello")];
|
||||
for x in xs {
|
||||
let displayables: Vec<Box<dyn Display>> = vec![Box::new(123), Box::new("Hello")];
|
||||
for x in displayables {
|
||||
println!("x: {x}");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Memory layout after allocating `xs`:
|
||||
Memory layout after allocating `displayables`:
|
||||
|
||||
```bob
|
||||
Stack Heap
|
||||
.- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - - -.
|
||||
: : : :
|
||||
: xs : : :
|
||||
: displayables : : :
|
||||
: +-----------+-------+ : : +-----+-----+ :
|
||||
: | ptr | o---+---+-----+-->| o o | o o | :
|
||||
: | len | 2 | : : +-|-|-+-|-|-+ :
|
||||
@ -84,3 +84,19 @@ fn main() {
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
<details>
|
||||
|
||||
* Types that implement a given trait may be of different sizes. This makes it impossible to have things like `Vec<Display>` in the example above.
|
||||
* `dyn Display` is a way to tell the compiler about a dynamically sized type that implements `Display`.
|
||||
* In the example, `displayables` holds *fat pointers* to objects that implement `Display`. The fat pointer consists of two components, a pointer to the actual object and a pointer to the virtual method table for the `Display` implementation of that particular object.
|
||||
* Compare these outputs in the above example:
|
||||
```rust,ignore
|
||||
use std::fmt::Display;
|
||||
println!("{}", std::mem::size_of::<u32>());
|
||||
println!("{}", std::mem::size_of::<&u32>());
|
||||
println!("{}", std::mem::size_of::<&dyn Display>());
|
||||
println!("{}", std::mem::size_of::<Box<dyn Display>>());
|
||||
```
|
||||
|
||||
</details>
|
||||
|
Reference in New Issue
Block a user