Code Monkey home page Code Monkey logo

google / comprehensive-rust Goto Github PK

View Code? Open in Web Editor NEW
26.0K 143.0 1.5K 18.87 MB

This is the Rust course used by the Android team at Google. It provides you the material to quickly teach Rust.

Home Page: https://google.github.io/comprehensive-rust/

License: Apache License 2.0

JavaScript 14.51% AIDL 0.86% Rust 64.55% Shell 1.89% Java 0.32% C 1.31% CSS 0.55% Handlebars 7.49% Makefile 0.96% Assembly 7.56%
rust course classroom guide training-materials android google training

comprehensive-rust's Introduction

Comprehensive Rust ๐Ÿฆ€

Build workflow GitHub contributors GitHub stars

This repository has the source code for Comprehensive Rust ๐Ÿฆ€, a multi-day Rust course developed by the Android team. The course covers all aspects of Rust, from basic syntax to generics and error handling. It also includes deep dives on Android, Chromium, bare-metal, and concurrency.

Read the course at https://google.github.io/comprehensive-rust/.

Course Format and Target Audience

The course is used internally at Google when teaching Rust to experienced software engineers. They typically have a background in C++ or Java.

The course is taught in a classroom setting and we hope it will be useful for others who want to teach Rust to their team. The course will be less useful for self-study since you miss out on the discussions happening in the classroom. You don't see the questions and answers and you don't see the compiler errors we trigger when going through the code samples. We hope to improve on this via speaker notes and by publishing videos.

Press

Articles and blog posts from around the web which cover Comprehensive Rust:

Building

The course is built using a few tools:

First install Rust by following the instructions on https://rustup.rs/. Then clone this repository:

git clone https://github.com/google/comprehensive-rust/
cd comprehensive-rust

Then install these tools with:

cargo install mdbook
cargo install --locked mdbook-svgbob
cargo install --locked mdbook-i18n-helpers
cargo install --locked --path mdbook-exerciser
cargo install --locked --path mdbook-course

Run

mdbook test

to test all included Rust snippets. Run

mdbook serve

to start a web server with the course. You'll find the content on http://localhost:3000. You can use mdbook build to create a static version of the course in the book/ directory. Note that you have to separately build and zip exercises and add them to book/html. To build any of the translated versions of the course, run MDBOOK_BOOK__LANGUAGE=xx mdbook build -d book/xx where xx is the ISO 639 language code (e.g. da for the Danish translation). TRANSLATIONS.md contains further instructions.

Note On Windows, you need to enable symlinks (git config --global core.symlinks true) and Developer Mode.

Contact

For questions or comments, please contact Martin Geisler or start a discussion on GitHub. We would love to hear from you.

comprehensive-rust's People

Contributors

adetaylor avatar adrienbaudemont avatar andrewpollack avatar anforowicz avatar baltuky avatar brandonpollack23 avatar cchiw avatar dependabot[bot] avatar djmitche avatar domenukk avatar fbornhofen avatar fw-immunant avatar gendx avatar henrif75 avatar hurryabit avatar igor-petruk avatar jiyongp avatar jooyunghan avatar kantasv avatar kuanhungchen avatar mani-chand avatar mgeisler avatar nodmp avatar proski avatar qwandor avatar randompoison avatar rastringer avatar reta avatar sylxjtu avatar wnghl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

comprehensive-rust's Issues

Suggestions: Misc

I think you should show the Option and Result definitions here. They'll see the variants everywhere in Rust.


Clarify that a HashMap doesn't have to be keyed with a &str or String (unlike a JSON object, say).


Here, I was going to mention that the lifetime can be explicit in some cases... but upon reconsideration that's probably not worth getting into. However, perhaps you should mention that lifetimes with the same name must indeed be equal. This will matter a lot should they every run into some &'a mut Thing<'a> errors.

But also on that page and on this one, you say

Read &'a Point as โ€œa borrowed Point which is valid for at least the lifetime aโ€.

That can be misinterpreted as "the borrow is valid for at least 'a", as opposed to "the Point is valid for at least 'a". I.e. it might given the mistaken impression that a borrow can be lengthened.


The getters and setters here aren't very idiomatic. First of all, nothing here is public -- everything must be in the same module -- so you'd just access the fields directly. Second of all, instead of a getter an infallible setter, if the struct was public, you'd probably just make those fields public too. If the fields actually have invariants, the setters shouldn't be infallible, but instead return a Result<_, _>.

More generally, it may give the impression that using getters and setters is idiomatic (even in the same module).


Perhaps note this list of receivers is non-exhaustive. E.g. Box<Self>.


I don't know that "omitted" is the right term for mod in_another_file;. Also perhaps note that (except perhaps for test modules) separate files is the norm.

Don't silence warnings in exercises

All the exercises start with something like

// TODO: remove this when you're done with your implementation.
#![allow(unused_variables, dead_code)]

You're training people that it's normal and a good idea to ignore warnings during development. Instead, continue to emphasize what you mention in passing elsewhere -- Rust has great compiler errors!

Of course it's going to have a lot of warnings at the start since you've given them incomplete code. You can

  • Just let them deal with it
  • Or mention RUSTFLAGS=-A... cargo ... perhaps

But you shouldn't imply ignoring warnings until you're "done with your implementation" is a good idea, or IMO that ignoring warnings in your source code (as opposed to a command line flag) is a good idea.

Technical nits: Threads and Drop

This slide says that threads are all daemon threads, but this is untrue:

  • For one, you're only talking about thread::spawn created threads, as per the very next slide
  • For two, these threads are only detached if you drop the JoinHandle
  • You also mention panicking and payloads, but you can only catch unwind payloads on the current thread; for panics of another spawned thread, you call join on the join handle to see if it panicked and to get the payload
    • I.e. you can only do this if the thread isn't detached

So you should talk about JoinHandle and detaching via Drop.

On the scoped page you should talk about the different behavior:

  • ScopedJoinHandle joins and blocks upon Drop instead of detaching
  • Any dropped ScopeJoinHandle that witnesses a thread panic will cause thread::scope to panic
  • But you can manually join and check for thread panics instead, similar to JoinHandle

Aside from the ability to borrow, this difference in handle drop behavior (and thus what may panic where) is the main difference between the two tools.

Extract text more carefully in `mdbook-xgettext`

Right now, we simply split the text on \n\n+, but this leads to a number of problems:

  • We split code blocks into different messages when there are one or more blank lines in the middle of the block.
  • We extract bullet point lists as a single message.

In general, it would be awesome if we could

  • Make the extracted messages independent of the precise formatting of the Markdown text. In particular, a hard-wrapped paragraph should be extracted without the paragraph breaks.
  • Remove formatting such as # from headers and * from bullet points.
  • Extract code blocks as a single message.

So Markdown like

# This is a heading

A _little_
paragraph.

```rust,editable
fn main() {
    println!("Hello world!");
}
```

* First
* Second

should result in these messages

  • This is a heading (heading type is stripped)
  • A _little_ paragraph. (softwrapped lines are unfolded)
  • fn main() {\n println!("Hello world!");\n} (info string is stripped)
  • First (bullet point extracted individually)
  • Second

You could imagine done something nice with links too: foo [bar](https://example.net) baz could be stored as foo [bar] baz. This might be a poor idea, though: it means that the translator cannot change the destination URL.

Technical nit: Adding Context to Errors

The IoError variant of ReadUsernameError enum is not used anymore, after switching to anyhow::Result return type. Perhaps this variant should be removed from the example.

example in chapter `Ownership` seems not correct

In Ownership chapter we give one example to indicate that variable will be dropped at the end of scope.

struct Point(i32, i32);

fn main() {
    {
        let p = Point(3, 4);
        println!("x: {}", p.0);
    }
    println!("y: {}", p.1);
}

But actually the rustcโ€™s complaining is

    Blocking waiting for file lock on package cache
   Compiling exercise v0.1.0 (/home/coder/project/exercise)
error[E0425]: cannot find value `p` in this scope
 --> src/main.rs:8:23
  |
8 |     println!("y: {}", p.1);
  |                       ^ not found in this scope

For more information about this error, try `rustc --explain E0425`.
error: could not compile `exercise` due to previous error

I believe this example may cause confusion.

Bumping version numbers in cargo/running-locally.md?

This page mentions:

At the time of writing, the latest stable Rust release has these version numbers:

% rustc --version
rustc 1.61.0 (fe5b13d68 2022-05-18)
% cargo --version
cargo 1.61.0 (a028ae4 2022-04-29)

Should these numbers be bumped once in a while (together with making sure that the code snippets are still up-to-date with the latest standards - e.g. Clippy lints)?

It could also be mentioned that all the code snippets are using stable Rust, and therefore are expected to still compile in years (so readers shouldn't worry if the rustc version looks old).

Suggested content

Hi, here's some suggested content based on my experience teaching the course

  1. I think modules are not very interesting can be pushed to the last day. If we assume the audience can program in some other language, then the rest of the day 2 content (control flow and syntax) can be squeezed to the day 1 afternoon. That means the audience has to wait until the second day to see the famous borrow checker and talk about memory management but that can just be more motivation to show up :)

  2. An exercise that forces people to use pattern matching, result types, option types, and the ? operator (ideally all at once), but only using Copy types. This will let people see these important APIs and learn some pattern matching syntax before running into the borrow checker. Ideally this will force people to read the docs about methods on Options and Results since these types show up everywhere.

    • you do have to have #[derive(Copy)] and generics like Option<Foo> around but instructors can give a very brief hand-waved explanation for what those are
  3. Designing the HashMap API: There's a lot to say about it wrt generics, trait bounds, and associated types.

    • Many methods have the bounds, K: Borrow<Q> and Q: Hash + Eq + ?Sized, this is a good example of putting trait bounds on associated types
    • The entry API is somewhat unique to Rust and is pretty cool that it lets users avoid a lookup
    • This could be a good intro to generics
    • maybe talk about ?sized types too
  4. Implementing an Iterator: Here's a contrived example that will let you talk about lifetimes, the index trait, and the impl trait syntax.

/// Given some text, index all the sentences so you can access the Nth sentence in O(1) time.
struct SentenceIndex<'text> {
  text: &'text str,
  sentence_starts: Vec<usize>,
}
impl<'text> std::ops::Index<usize> for SentenceIndex<'text> {
  type Output: &'text str;
  // Note that &self has a different lifetime than &'text
  // The returned sentence str can outlive the SentenceIndex but not the underlying text.
  fn index(&self, i: usize) -> &'text str; 
}
impl<'text> SentenceIndex<'text> {
  fn iter(&self) -> impl Iterator<&'text str>;
}

Typo in Tuple Structs

https://google.github.io/comprehensive-rust/structs/tuple-structs.html

struct PoundOfForce(f64);
struct Newtons(f64);

fn compute_thruster_force() -> PoundOfForce {
    todo!("Ask a rocket scientist at NASA")
}

fn set_thruster_force(force: Newtons) {
    // ...
}

fn main() {
    let force = compute_thruster_force();
    set_thruster_force(force);
}

compile with cargo run shows:

โฏ cargo run
   Compiling exercise v0.1.0 (/Users/z/code/exercise)
error[E0308]: mismatched types
  --> src/main.rs:14:24
   |
14 |     set_thruster_force(force);
   |     ------------------ ^^^^^ expected struct `Newtons`, found struct `PoundOfForce`
   |     |
   |     arguments to this function are incorrect
   |
note: function defined here
  --> src/main.rs:8:4
   |
8  | fn set_thruster_force(force: Newtons) {
   |    ^^^^^^^^^^^^^^^^^^ --------------

For more information about this error, try `rustc --explain E0308`.
error: could not compile `exercise` due to previous error

So this maybe a typo in the code?

Publish videos

To help people use the course for self-study, we need something which will fill in all the stuff we normally talk about in class. The course is normally driven by people's questions and these are missing from the slides.

Publishing videos would be useful to help fill this gap.

Question about Multi-threaded Link Checker task

Hi. I have a difficulty understanding the following subtask:

Use threads to check the links in parallel: send the URLs to be checked to a channel and let a few threads check the URLs in parallel.

Is the suggestion here to create a channel on the main thread, which will spawn a new thread whenever it receives a URL and then run a recursive link checker for this URL on the spawned thread? So for instance, a user could simultaneously run two parallel link checkers for site A and site B.

Or is it more about parallelizing the recursive checks of the same site? So for instance, you start with the start page of site A, extract a list of URLs from that page and send them to some queue from which several other threads can pick up URLs, process them and add new extracted URLs to the queue, and so on.

could not find `unix` in `os`

Hi,I want to run this docs on win,but it can't run due to error below:

failures:

---- C:\Users\AA\AppData\Local\Temp\mdbook-tB0wit\exercises/day-3/solutions-afternoon.md - Day_3_Afternoon_Exercises::Safe_FFI_Wrapper (line 7) stdout ----
error[E0433]: failed to resolve: could not find `unix` in `os`
  --> C:\Users\AA\AppData\Local\Temp\mdbook-tB0wit\exercises/day-3/solutions-afternoon.md:51:14
   |
45 | use std::os::unix::ffi::OsStrExt;
   |              ^^^^ could not find `unix` in `os`

error[E0599]: no function or associated item named `from_bytes` found for struct `OsStr` in the current scope
  --> C:\Users\AA\AppData\Local\Temp\mdbook-tB0wit\exercises/day-3/solutions-afternoon.md:92:29
   |
86 |         let os_str = OsStr::from_bytes(d_name.to_bytes());
   |                             ^^^^^^^^^^ function or associated item not found in `OsStr`

Not support Win?

add_book method of library throws cannot borrow as mutable without declaring library as mut

Hi I was having an issue with the exercise at the end of day 1. Writing it as it is shown in the solution

   fn add_book(&mut self, book: Book) {
        self.books.push(book)
    }

will throw an error stating "cannot borrow library as mutable, as it is not declared as mutable". Adding mut to the library declaration seems to make it compile, though my impression was that we should not have to change the code in main. Or, perhaps there is something I am overlooking here? I am using rustc version 1.66.0.

Look at mdbook-keeper

We currently have a number of code blocks marked with compile_fail: this is often because they depend on third-party crates which aren't available when running mdbook test.

We should look into using https://github.com/tfpk/mdbook-keeper/ to handle testing instead. It explicitly supports using third-party crates in code snippets.

Expand the "Why Rust?" section

Actually I think we need more explanation about why we need and when to use. Rust is built with years of experience in software engineering but not every learner knows where these smart designs of Rust come from...

Originally posted by @Luosuu in #32 (comment)

Note that "Android" means "AOSP" and not "Android app"

Iโ€™d strongly suggest, in https://google.github.io/comprehensive-rust/welcome.html , to explicitely note that the Android part considers how to contribute to Android source code, using Android build system.
On first reading, the way I saw it presented on twitter, and in this page, I thought that this was aimed for the Android developers which, for some reason, wanted to write part of their app in Rust.

Iโ€™ll immediately admit that a reader could guess it is not actually for app developer, as the two sentences indicate OASP.

Building Android components in Rust.
AIDL servers and clients.

The trouble being that, if youโ€™re not used to working on Android source code, you may not know what AIDLโ€ฏis, and that itโ€™s not a Rust specific term youโ€™ll learn later.

Personally, I admit that, since AnkiDroid, an Android app, is already using Rust for its backend and Kotlin for its front-end, I was wondering whether I could learn things to improve our system. I guess it wonโ€™t be the case.

And with this, I believe itโ€™s the last PR/issue youโ€™ll get from me.
Thanks for making this public

Write chapter about async Rust

We should write a chapter about async Rust. This would be a good alternative to the Android part on Day 4. A possible agenda could look like this:

  • Introductory Example
  • Terminology
  • Futures
  • await
  • Runtimes
  • Spawning
  • IO-Compatible Cunctions

Support translations

It would be great to support translating the course into other languages. I suggest doing this with the infrastructure I wrote here: rust-lang/mdBook#1864.

We don't need to wait for this to merge upstream (infact, we can probably just pull in the code as stand-alone binaries in this repository).

With this system, we can setup something like https://pontoon.rust-lang.org/ to make it easy for people to contribute fixes to the translations.

Technical nits: the try operator

You only cover Result, but it works with other types too. At least mention Option, which is commonly used.

The desugaring example is out of date; the actual desugaring is now more complicated. (And technically it was never just From::from directly.) But I get it, you're not going to help anyone by explaining it on that level. Probably you can just rephrase this page to "the effective expansion ..." instead of "actual expansion", and "works the same as" instead of "actually becomes".

Consider adding the as-if desugaring for Option too.

Make the shell snippets easier to copy/paste (e.g. cargo/running-locally.md)?

The code blocks of mdbook provide a "Copy to clipboard" button - however pages like https://google.github.io/comprehensive-rust/cargo/running-locally.html contain shell blocks like follows:

$ cargo new exercise
     Created binary (application) `exercise` package

Clicking copies the whole block, including the dollar sign and the shell output. It would be nice to be able to only copy the command, e.g. cargo new exercise. We could achieve that by:

  1. Creating a separate block for the output.
  2. Removing the dollar sign. This would however make it less obvious that it's a shell command. Unless mdbook provides a way to display a dollar sign before the content, but exclude it from the copying?

WDYT?

Technical nits: Slices and other DSTs

I don't think you ever cover what a non-Sized type, aka dynamically sized type (DST), is.

Here you call &str and &[u8] "scalar types", and... while the reference is, I suppose... the underlying (DST) slice contains multiple values, so I found their inclusion surprising.

Then later on you refer to &[T] as a slice. This is common nomenclature, but I feel it's worth pointing out that a [T] is more properly the slice, it is dynamically sized, and this is why you typically see it behind a reference (or other pointer like in a Box). And then on this page you could say a str is basically a [u8] with invariants (valid UTF8 encoding).

Incidentally, that page says there are two Rust string types, but there are many others, such as Arc<str> or Cow<'_, str>.


Then later on you say

Recursive data types or data types with dynamic sizes need to use a Box

But that's incorrect:

  • There are no dynamic sizes here in Rust terminology; List<T> has a static size
  • If you attempt to write List without the Box, it has infinite size -- but still not dynamic
  • Slices have dynamic sizes but don't need a Box

When you get around to trait objects, you can mention that they're DSTs too, and that's why you typically see them in a Box (but may also seem them behind a reference, in an Arc, ...).

Technical nits: Misc

You make a direct comparison between Rust and C++ references, but Rust references are more similar to pointers in many ways. I see people coming from C++ and being confused by this on the forums, so making the direct comparison may be counter-productive.


The compile time guarantees are guaranteed for safe Rust with sound dependencies. Worth pointing out since you have a section on unsafe. Most of them are UB if they do get compiled.

There are no NULL references, but there are NULL pointers.

(More a suggestion:) Although foot-noted, the memory leak seemed out-of-place to me in this list. Perhaps the Mutex lock too. Both, I guess, fall under RAII.


Here you say

you need a trait object if you want to return different values implementing a trait

But what you actually mean is "if you want to return different types implementing a trait".

The rest of this is suggestion territory, but here you should point out how different the argument position (APIT) and return position (RPIT) uses are.

  • APIT is basically a generic parameter on the function, but the type becomes opaque
    • You don't need APIT to accept unnameable types in generics, e.g. to be passed a closure
    • The caller can choose any type that meets the bounds
  • RPIT is opaque, but still a single type (for a given set of parameter inputs)
    • I.e. you can't return different types in an if/else
    • The function writer chooses the (single) type that gets returned

And then when you get to returning Box<dyn Trait> you can compare and contrast with RPIT.


You say

Rust enums are packed tightly,

But they're not really packed, it's more that the variants can share storage because it's a tagged union; only one variant is "active" at a time. (And repr(packed) is something else entirely.)

Also, the layout (size optimization) is only guaranteed in very specific circumstances. Perhaps mention in general that most Rust data structures have no layout guarantees. You mention niche optimization here too; that almost meets the guaranteed case (as far as I'm aware of it existing), but not quite. So the niche optimization is not guaranteed for the example.


You say

The Iterator trait simply says that you can call next until you get None back

First, there are 74 more other methods so far, so it says a lot more than that.

But also, there's nothing that keeps you from calling next after you get a None back. And unless your iterator is fused, nothing that says you'll never get a Some(_) after you see a None.


You say

There is always exactly one variable binding which owns a value.

But Rc and Arc are often referred to as "shared owneship". Even more nit-picky, a Vec (say) can be in a single variable binding, but owns multiple values.

I don't have a good suggestion on how to word all this while getting across your original point and not being confusing though.

404 page does not work

mdbook generates a 404.html page for us and this is used by GitHub Pages when it shows a 404 error. However, the page fails to load its resources (CSS, images, ...). There is probably an easy fix for this.

Impossible to open speaker notes again after closing them

I can't find any way to open the speaker notes again after closing them once. Steps to reproduce:

  1. Go to https://google.github.io/comprehensive-rust/.
  2. Click the link to open speaker notes in a new window. The new window opens, and the link disappears from the main window.
  3. Close the speaker notes window. I would expect the link in the main window to reappear at this point, but it does not.
  4. Go to a different page in the main window. Still no link to reopen speaker notes.
  5. Refresh the main window. There is still no link to reopen speaker notes.
  6. Close the main window, and open https://google.github.io/comprehensive-rust/ again. There's still no link to reopen speaker notes again, they are gone forever.

Brazilian Portuguese translation

I've created Google Cloud Translate file to get started: pt_BR.zip.

We might have to update our publishing machinery to handle the xx_YY form of the locale, but we'll deal with this when we get there :-)

Can it be made a PWA?

I think it would be cool if it can be made a progressive web app installable on your device, so it could increase performance and not rely on the network for some time, especially when the internet network tends to fail at some particular region

`mdbook test` fails on commit 26404744

Followed the README to run mdbook test and got the following error.

2022-12-22 23:35:37 [ERROR] (mdbook::book): rustdoc returned an error:

--- stdout

running 2 tests
test /var/folders/3h/t8595zjd10l4248jh4z21h8r0000gn/T/mdbook-ozrGSf/concurrency/scoped-threads.md - Scoped_Threads (line 19) ... FAILED
test /var/folders/3h/t8595zjd10l4248jh4z21h8r0000gn/T/mdbook-ozrGSf/concurrency/scoped-threads.md - Scoped_Threads (line 5) - compile fail ... ok

failures:

---- /var/folders/3h/t8595zjd10l4248jh4z21h8r0000gn/T/mdbook-ozrGSf/concurrency/scoped-threads.md - Scoped_Threads (line 19) stdout ----
error[E0658]: use of unstable library feature 'scoped_threads'
 --> /var/folders/3h/t8595zjd10l4248jh4z21h8r0000gn/T/mdbook-ozrGSf/concurrency/scoped-threads.md:25:5
  |
7 |     thread::scope(|scope| {
  |     ^^^^^^^^^^^^^
  |
  = note: see issue #93203 <https://github.com/rust-lang/rust/issues/93203> for more information

error[E0658]: use of unstable library feature 'scoped_threads'
 --> /var/folders/3h/t8595zjd10l4248jh4z21h8r0000gn/T/mdbook-ozrGSf/concurrency/scoped-threads.md:26:15
  |
8 |         scope.spawn(|| {
  |               ^^^^^
  |
  = note: see issue #93203 <https://github.com/rust-lang/rust/issues/93203> for more information

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0658`.
Couldn't compile the test.

failures:
    /var/folders/3h/t8595zjd10l4248jh4z21h8r0000gn/T/mdbook-ozrGSf/concurrency/scoped-threads.md - Scoped_Threads (line 19)

test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.04s


--- stderr

Trait Objects memory diagram uses different order for different cells

https://google.github.io/comprehensive-rust/generics/trait-objects.html has this diagram:

```bob
Stack Heap
.- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - - - - - - - - - -.
: : : :
: xs : : :
: +-----------+-------+ : : +-----+-----+ :
: | ptr | o---+---+-----+-->| o o | o o | :
: | len | 2 | : : +-|-|-+-|-|-+ :
: | capacity | 2 | : : | | | | +----+----+----+----+----+ :
: +-----------+-------+ : : | | | '-->| H | e | l | l | o | :
: : : | | | +----+----+----+----+----+ :
`- - - - - - - - - - - - - -' : | | | :
: | | | +-------------------------+ :
: | | '---->| "<str as Display>::fmt" | :
: | | +-------------------------+ :
: | | :
: | | +-------------------------+ :
: | '-->| "<i32 as Display>::fmt" | :
: | +-------------------------+ :
: | :
: | +----+----+----+----+ :
: '---->| 7b | 00 | 00 | 00 | :
: +----+----+----+----+ :
: :
: :
'- - - - - - - - - - - - - - - - - - - - - - - -'
```

Quoting https://doc.rust-lang.org/reference/types/trait-object.html

Each instance of a pointer to a trait object includes:

  • a pointer to an instance of a type T that implements SomeTrait
  • a virtual method table, often just called a vtable, which contains, for each method of SomeTrait and its supertraits that T implements, a pointer to T's implementation (i.e. a function pointer).

It seems the diagram here draws one object as (instance, vtable) and the second as (vtable, instance). Consistency would help, and based on https://doc.rust-lang.org/reference/types/trait-object.html it seems (instance, vtable) is the safer assumption.

Translations

Thanks to our wonderful volunteers, we're able to translate the course. This bug simply tracks the various efforts:

Please create more issues if you want to help translate the course!

How to get started?

The Rust Book is already translated into a number of languages. Please try to use the same terminology for your translations.

A great way to get started is to submit an almost-empty PO file for your language. That will ensure that you have the tooling setup and it will make it easier for others to jump in and help.

Suggestion: Don't shy away from concurrent structures early on

I found it sort of odd that Arc and friends weren't mentioned until the last day, while for example you have a slide on Rc (also mentioning RefCell and Cell in passing) Why not mention Arc as well? If you use Rc, you're opting out of being able to be multi-threaded... and one of the great things about Rust is how it assumes you're going to want to be concurrent eventually. If Rc<T> meets your shared-ownership needs, usually Arc<T> does too.

Other places they come up:

[ERROR] (mdbook::utils): Error: Couldn't open SUMMARY.md in "/home/user1/cargo/src" directory

I created an empty directory called cargo in my home directory. Inside it I successfully ran:

$ cargo install mdbook
$ cargo install mdbook-svgbob

And then tried to run:

$ mdbook test
$ mdbook serve

But both commands above (test and serve) gives me the same error:

2022-12-26 13:34:39 [ERROR] (mdbook::utils): Error: Couldn't open SUMMARY.md in "/home/user1/cargo/src" directory
2022-12-26 13:34:39 [ERROR] (mdbook::utils): 	Caused By: No such file or directory (os error 2)

GitHub action to check formatting of Markdown files?

In #329, I'm adding some text which makes a line exceed the 80-column standard formatting of markdown files. I'm waiting for the workflows to be approved to see if they will catch the formatting mistake.

If not, it would be good to have a way to automatically format and check the markdown files (ala cargo fmt and cargo fmt --check).

Suggestion: Globals and state

You say:

Global state is managed with static and constant variables.

But consts can't manage a state. Statics can... but preferably only with interior mutability of some sort. Your examples have no actual managing of state.

You do say "We will look at mutating static data in the chapter on Unsafe Rust", and indeed have a page on static mut.

That slide should just be deleted. It's so nigh-on impossible to get right even for experts that there's a push for its deprecation. Definitely no introduction to Rust should convey that it might be reasonable thing to reach for.


What should take its place? A more accurate portrayal of how global state is actually done in safe idiomatic Rust.

First, it usually isn't! Pass your state around, use an Arc<Mutex<_>> or the like.

But when it is, it's done with interior mutability. static atomics, thread local RefCell, once_cell (eventually to be part of std, lazy_static.


If you must leave in static mut, at least cover Once. But really that's just a tedious and error prone way of building up things like once_cell manually. In practice people just use once_cell and similar instead of rolling their own.

Reaching for unsafe to do global state yourself is just a bad idea.

Inform about rustup.sh installation

Hello ๐Ÿ‘‹

Thanks for creating this guide! I've one discussion that I want to make:

At the start, during the setup/installation phase, it seems to currently recommend installing rust's tools using the built-in packages from apt repository

On Debian/Ubuntu, you can install Cargo and the Rust source with
```shell
$ sudo apt install cargo rust-src
```

I think this might be fine, since this is more familiar with peoples that are just getting started (I know I did this once). Though I think it might be better to also include the "standard" way of installing the tools, since it would make it easier for when latest stable/beta/nightly versions are available (via $ rustup update)

$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.