1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-06-26 10:41:01 +02:00

Format all Markdown files with dprint (#1157)

This is the result of running `dprint fmt` after removing `src/` from
the list of excluded directories.

This also reformats the Rust code: we might want to tweak this a bit in
the future since some of the changes removes the hand-formatting. Of
course, this formatting can be seen as a mis-feature, so maybe this is
good overall.

Thanks to mdbook-i18n-helpers 0.2, the POT file is nearly unchanged
after this, meaning that all existing translations remain valid! A few
messages were changed because of stray whitespace characters:

     msgid ""
     "Slices always borrow from another object. In this example, `a` has to remain "
    -"'alive' (in scope) for at least as long as our slice. "
    +"'alive' (in scope) for at least as long as our slice."
     msgstr ""

The formatting is enforced in CI and we will have to see how annoying
this is in practice for the many contributors. If it becomes annoying,
we should look into fixing dprint/check#11 so that `dprint` can annotate
the lines that need fixing directly, then I think we can consider more
strict formatting checks.

I added more customization to `rustfmt.toml`. This is to better emulate
the dense style used in the course:

- `max_width = 85` allows lines to take up the full width available in
our code blocks (when taking margins and the line numbers into account).
- `wrap_comments = true` ensures that we don't show very long comments
in the code examples. I edited some comments to shorten them and avoid
unnecessary line breaks — please trim other unnecessarily long comments
when you see them! Remember we're writing code for slides 😄
- `use_small_heuristics = "Max"` allows for things like struct literals
and if-statements to take up the full line width configured above.

The formatting settings apply to all our Rust code right now — I think
we could improve this with https://github.com/dprint/dprint/issues/711
which lets us add per-directory `dprint` configuration files. However,
the `inherit: true` setting is not yet implemented (as far as I can
tell), so a nested configuration file will have to copy most or all of
the top-level file.
This commit is contained in:
Martin Geisler
2023-12-31 00:15:07 +01:00
committed by GitHub
parent f43e72e0ad
commit c9f66fd425
302 changed files with 3067 additions and 2622 deletions

View File

@ -7,4 +7,3 @@ publish = false
[[bin]]
name = "generics"
path = "exercise.rs"

View File

@ -48,18 +48,9 @@ fn min<T: LessThan>(l: T, r: T) -> T {
// ANCHOR: main
fn main() {
let cit1 = Citation {
author: "Shapiro",
year: 2011,
};
let cit2 = Citation {
author: "Baumann",
year: 2010,
};
let cit3 = Citation {
author: "Baumann",
year: 2019,
};
let cit1 = Citation { author: "Shapiro", year: 2011 };
let cit2 = Citation { author: "Baumann", year: 2010 };
let cit3 = Citation { author: "Baumann", year: 2019 };
debug_assert_eq!(min(cit1, cit2), cit2);
debug_assert_eq!(min(cit2, cit3), cit2);
debug_assert_eq!(min(cit1, cit3), cit3);

View File

@ -31,13 +31,17 @@ fn main() {
<details>
* *Q:* Why `T` is specified twice in `impl<T> Point<T> {}`? Isn't that redundant?
* This is because it is a generic implementation section for generic type. They are independently generic.
* It means these methods are defined for any `T`.
* It is possible to write `impl Point<u32> { .. }`.
* `Point` is still generic and you can use `Point<f64>`, but methods in this block will only be available for `Point<u32>`.
- _Q:_ Why `T` is specified twice in `impl<T> Point<T> {}`? Isn't that
redundant?
- This is because it is a generic implementation section for generic type.
They are independently generic.
- It means these methods are defined for any `T`.
- It is possible to write `impl Point<u32> { .. }`.
- `Point` is still generic and you can use `Point<f64>`, but methods in this
block will only be available for `Point<u32>`.
* Try declaring a new variable `let p = Point { x: 5, y: 10.0 };`.
Update the code to allow points that have elements of different types, by using two type variables, e.g., `T` and `U`.
- Try declaring a new variable `let p = Point { x: 5, y: 10.0 };`. Update the
code to allow points that have elements of different types, by using two type
variables, e.g., `T` and `U`.
</details>

View File

@ -5,8 +5,7 @@ minutes: 5
# Generic Functions
Rust supports generics, which lets you abstract algorithms or data structures
(such as sorting or a binary tree)
over the types used or stored.
(such as sorting or a binary tree) over the types used or stored.
```rust,editable
/// Pick `even` or `odd` depending on the value of `n`.
@ -26,16 +25,16 @@ fn main() {
<details>
* Rust infers a type for T based on the types of the arguments and return value.
- Rust infers a type for T based on the types of the arguments and return value.
* This is similar to C++ templates, but Rust partially compiles the generic
- This is similar to C++ templates, but Rust partially compiles the generic
function immediately, so that function must be valid for all types matching
the constraints. For example, try modifying `pick` to return `even + odd` if
`n == 0`. Even if only the `pick` instantiation with integers is used, Rust
still considers it invalid. C++ would let you do this.
* Generic code is turned into non-generic code based on the call sites.
This is a zero-cost abstraction: you get exactly the same result as if you had
- Generic code is turned into non-generic code based on the call sites. This is
a zero-cost abstraction: you get exactly the same result as if you had
hand-coded the data structures without the abstraction.
</details>

View File

@ -30,20 +30,22 @@ fn main() {
<details>
`impl Trait` allows you to work with types which you cannot name.
The meaning of `impl Trait` is a bit different in the different positions.
`impl Trait` allows you to work with types which you cannot name. 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 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.
- 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<_>>()`.
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<_>>()`.
What is the type of `debuggable`? Try `let debuggable: () = ..` to see what the
error message shows.

View File

@ -25,11 +25,11 @@ fn main() {
<details>
* Try making a `NonClonable` and passing it to `duplicate`.
- Try making a `NonClonable` and passing it to `duplicate`.
* When multiple traits are necessary, use `+` to join them.
- When multiple traits are necessary, use `+` to join them.
* Show a `where` clause, students will encounter it when reading code.
- Show a `where` clause, students will encounter it when reading code.
```rust,ignore
fn duplicate<T>(a: T) -> (T, T)
@ -38,13 +38,14 @@ fn main() {
{
(a.clone(), a.clone())
}
```
```
* It declutters the function signature if you have many parameters.
* It has additional features making it more powerful.
* If someone asks, the extra feature is that the type on the left of ":" can be arbitrary, like `Option<T>`.
- It declutters the function signature if you have many parameters.
- It has additional features making it more powerful.
- If someone asks, the extra feature is that the type on the left of ":" can
be arbitrary, like `Option<T>`.
* Note that Rust does not (yet) support specialization. For example, given the
- Note that Rust does not (yet) support specialization. For example, given the
original `duplicate`, it is invalid to add a specialized `duplicate(a: u32)`.
</details>