diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd33f2f1..0ce1edc3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,8 +6,7 @@ on: pull_request: jobs: - - test: + deploy-test: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 @@ -24,3 +23,21 @@ jobs: mdbook-version: '${{ steps.mdbook-version.outputs.MDBOOK_VERSION }}' - run: mdbook build + + doc-test: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + + - name: Read .env + id: mdbook-version + run: | + . ./.env + echo "::set-output name=MDBOOK_VERSION::${MDBOOK_VERSION}" + + - name: Setup mdBook + uses: peaceiris/actions-mdbook@v1 + with: + mdbook-version: '${{ steps.mdbook-version.outputs.MDBOOK_VERSION }}' + + - run: mdbook test diff --git a/anti_patterns/deny-warnings.md b/anti_patterns/deny-warnings.md index e019c765..b19a68d2 100644 --- a/anti_patterns/deny-warnings.md +++ b/anti_patterns/deny-warnings.md @@ -55,7 +55,7 @@ without requiring a change to the code. Alternatively, we can specify the lints that we want to `deny` in the code. Here is a list of warning lints that is (hopefully) safe to deny: -```rust +```rust,ignore #[deny(bad-style, const-err, dead-code, @@ -84,7 +84,7 @@ Here is a list of warning lints that is (hopefully) safe to deny: In addition, the following `allow`ed lints may be a good idea to `deny`: -```rust +```rust,ignore #[deny(missing-debug-implementations, missing-docs, trivial-casts, diff --git a/anti_patterns/deref.md b/anti_patterns/deref.md index a5a69849..f037c749 100644 --- a/anti_patterns/deref.md +++ b/anti_patterns/deref.md @@ -26,11 +26,16 @@ public static void main(String[] args) { We can use the deref polymorphism anti-pattern to do so: -```rust +```rust,ignore +use std::ops::Deref; + struct Foo {} impl Foo { - fn m(&self) { ... } + fn m(&self) { + //.. + } + } struct Bar { @@ -68,7 +73,7 @@ well as `Bar`. You save a little boilerplate, e.g., -```rust +```rust,ignore impl Bar { fn m(&self) { self.f.m() diff --git a/idioms/ctor.md b/idioms/ctor.md index 7ff38bcf..17684b76 100644 --- a/idioms/ctor.md +++ b/idioms/ctor.md @@ -8,7 +8,7 @@ is to use a static `new` method to create an object. ## Example -```rust +```rust,ignore // A Rust vector, see liballoc/vec.rs pub struct Vec { buf: RawVec, diff --git a/idioms/default.md b/idioms/default.md index 5abcc2a7..45a9b7ec 100644 --- a/idioms/default.md +++ b/idioms/default.md @@ -19,7 +19,7 @@ different names, but there can only be one `Default` implementation per type. ## Example -```rust +```rust,ignore // note that we can simply auto-derive Default here. #[derive(Default)] struct MyConfiguration { diff --git a/idioms/deref.md b/idioms/deref.md index 86d67d1b..999e1c41 100644 --- a/idioms/deref.md +++ b/idioms/deref.md @@ -8,16 +8,19 @@ and borrowed views of data. ## Example -```rust +```rust,ignore +use std::ops::Deref; + struct Vec { - ... + data: T, + //.. } impl Deref for Vec { type Target = [T]; fn deref(&self) -> &[T] { - ... + //.. } } ``` diff --git a/idioms/dtor-finally.md b/idioms/dtor-finally.md index b7edf52f..3e2d2873 100644 --- a/idioms/dtor-finally.md +++ b/idioms/dtor-finally.md @@ -9,7 +9,7 @@ be used to run code that must be run before exit. ## Example -```rust +```rust,ignore fn bar() -> Result<(), ()> { // These don't need to be defined inside the function. struct Foo; diff --git a/idioms/on-stack-dyn-dispatch.md b/idioms/on-stack-dyn-dispatch.md index e4dc011d..e0c29a27 100644 --- a/idioms/on-stack-dyn-dispatch.md +++ b/idioms/on-stack-dyn-dispatch.md @@ -9,7 +9,9 @@ below: ## Example -```rust +```rust,ignore +std::io::File; + // These must live longer than `readable`, and thus are declared first: let (mut stdin_read, mut file_read); @@ -46,7 +48,7 @@ whole code that follows to work with both `File` or `Stdin`, with all the The code needs more moving parts than the `Box`-based version: -```rust +```rust,ignore // We still need to ascribe the type for dynamic dispatch. let readable: Box = if arg == "-" { Box::new(io::stdin()) diff --git a/idioms/pass-var-to-closure.md b/idioms/pass-var-to-closure.md index 2df610d0..4d82767d 100644 --- a/idioms/pass-var-to-closure.md +++ b/idioms/pass-var-to-closure.md @@ -14,6 +14,8 @@ Use variable rebinding in separate scope for that. Use ```rust +use std::rc::Rc; + let num1 = Rc::new(1); let num2 = Rc::new(2); let num3 = Rc::new(3); @@ -30,6 +32,8 @@ let closure = { instead of ```rust +use std::rc::Rc; + let num1 = Rc::new(1); let num2 = Rc::new(2); let num3 = Rc::new(3); diff --git a/idioms/priv-extend.md b/idioms/priv-extend.md index 492bec1e..b8d05ace 100644 --- a/idioms/priv-extend.md +++ b/idioms/priv-extend.md @@ -8,7 +8,7 @@ stability guarantees. ## Example -```rust +```rust,ignore mod a { // Public struct. pub struct S { diff --git a/idioms/rustdoc-init.md b/idioms/rustdoc-init.md index 60d6c9b4..6c693757 100644 --- a/idioms/rustdoc-init.md +++ b/idioms/rustdoc-init.md @@ -11,7 +11,7 @@ Each of these methods should have examples. For example: -```rust +```rust,ignore struct Connection { name: String, stream: TcpStream, @@ -43,7 +43,7 @@ impl Connection { ## Example Instead of typing all of this boiler plate to create an `Connection` and `Request` it is easier to just create a wrapping dummy function which takes them as arguments: -```rust +```rust,ignore struct Connection { name: String, stream: TcpStream, diff --git a/idioms/temporary-mutability.md b/idioms/temporary-mutability.md index fff21d05..2b7bb21d 100644 --- a/idioms/temporary-mutability.md +++ b/idioms/temporary-mutability.md @@ -14,7 +14,7 @@ Say, vector must be sorted before usage. Using nested block: -```rust +```rust,ignore let data = { let mut data = get_vec(); data.sort(); @@ -26,7 +26,7 @@ let data = { Using variable rebinding: -```rust +```rust,ignore let mut data = get_vec(); data.sort(); let data = data; diff --git a/patterns/RAII.md b/patterns/RAII.md index 9da6a0d6..61875cc5 100644 --- a/patterns/RAII.md +++ b/patterns/RAII.md @@ -13,25 +13,32 @@ on the type system to ensure that access is always mediated by the guard object. Mutex guards are the classic example of this pattern from the std library (this is a simplified version of the real implementation): -```rust +```rust,ignore +use std::ops::Deref; + +struct Foo {} + struct Mutex { // We keep a reference to our data: T here. - ... + //.. } struct MutexGuard<'a, T: 'a> { data: &'a T, - ... + //.. } // Locking the mutex is explicit. impl Mutex { fn lock(&self) -> MutexGuard { // Lock the underlying OS mutex. - ... + //.. // MutexGuard keeps a reference to self - MutexGuard { data: self, ... } + MutexGuard { + data: self, + //.. + } } } @@ -39,7 +46,7 @@ impl Mutex { impl<'a, T> Drop for MutexGuard<'a, T> { fn drop(&mut self) { // Unlock the underlying OS mutex. - ... + //.. } } @@ -52,7 +59,7 @@ impl<'a, T> Deref for MutexGuard<'a, T> { } } -fn main(x: Mutex) { +fn baz(x: Mutex) { let xx = x.lock(); xx.foo(); // foo is a method on Foo. // The borrow checker ensures we can't store a reference to the underlying @@ -90,8 +97,10 @@ and that references to the resource mediated by the guard cannot outlive the guard. To see how this works it is helpful to examine the signature of `deref` without lifetime elision: -```rust -fn deref<'a>(&'a self) -> &'a T { ... } +```rust,ignore +fn deref<'a>(&'a self) -> &'a T { + //.. +} ``` The returned reference to the resource has the same lifetime as `self` (`'a`). diff --git a/patterns/builder.md b/patterns/builder.md index 4b6ce12d..f9366c93 100644 --- a/patterns/builder.md +++ b/patterns/builder.md @@ -7,18 +7,20 @@ Construct an object with calls to a builder helper. ## Example -```rust +```rust,ignore struct Foo { // Lots of complicated fields. } struct FooBuilder { // Probably lots of optional fields. - ... + //.. } impl FooBuilder { - fn new(...) -> FooBuilder { + fn new( + //.. + ) -> FooBuilder { // Set the minimally required fields of Foo. } @@ -85,7 +87,7 @@ The example takes and returns the builder by value. It is often more ergonomic borrow checker makes this work naturally. This approach has the advantage that one can write code like -``` +```rust,ignore let mut fb = FooBuilder::new(); fb.a(); fb.b(); diff --git a/patterns/compose-structs.md b/patterns/compose-structs.md index 449fdc3e..d9b9f72e 100644 --- a/patterns/compose-structs.md +++ b/patterns/compose-structs.md @@ -20,7 +20,7 @@ pattern often reveals smaller units of functionality. Here is a contrived example of where the borrow checker foils us in our plan to use a struct: -```rust +```rust,ignore struct A { f1: u32, f2: u32, @@ -30,7 +30,7 @@ struct A { fn foo(a: &mut A) -> &u32 { &a.f2 } fn bar(a: &mut A) -> u32 { a.f1 + a.f3 } -fn main(a: &mut A) { +fn baz(a: &mut A) { // x causes a to be borrowed for the rest of the function. let x = foo(a); // Borrow check error @@ -59,7 +59,7 @@ struct C { fn foo(b: &mut B) -> &u32 { &b.f2 } fn bar(c: &mut C) -> u32 { c.f1 + c.f3 } -fn main(a: &mut A) { +fn baz(a: &mut A) { let x = foo(&mut a.b); // Now it's OK! let y = bar(&mut a.c); diff --git a/patterns/fold.md b/patterns/fold.md index 4d70d4f9..6b649b82 100644 --- a/patterns/fold.md +++ b/patterns/fold.md @@ -11,7 +11,7 @@ fold in the usual sense. See the discussion below for more details. ## Example -```rust +```rust,ignore // The data we will fold, a simple AST. mod ast { pub enum Stmt { diff --git a/patterns/newtype.md b/patterns/newtype.md index eb1f1b7b..0eeaeb54 100644 --- a/patterns/newtype.md +++ b/patterns/newtype.md @@ -7,15 +7,15 @@ This creates a new type, rather than an alias to a type (`type` items). ## Example -```rust +```rust,ignore // Some type, not necessarily in the same module or even crate. struct Foo { - ... + //.. } impl Foo { // These functions are not present on Bar. - ... + //.. } // The newtype. @@ -23,11 +23,15 @@ pub struct Bar(Foo); impl Bar { // Constructor. - pub fn new(...) -> Bar { - ... + pub fn new( + //.. + ) -> Bar { + + //.. + } - ... + //.. } fn main() { @@ -80,7 +84,7 @@ most common uses, but they can be used for other reasons: * making a type with copy semantics have move semantics, * abstraction by providing a more concrete type and thus hiding internal types, e.g., -```rust +```rust,ignore pub struct Foo(Bar); ``` diff --git a/patterns/visitor.md b/patterns/visitor.md index 604d211e..855a3e08 100644 --- a/patterns/visitor.md +++ b/patterns/visitor.md @@ -13,7 +13,7 @@ a collection of objects from the operations performed on each object. ## Example -```rust +```rust,ignore // The data we will visit mod ast { pub enum Stmt { @@ -87,7 +87,7 @@ it between algorithms (and also to provide noop default methods). In Rust, the common way to do this is to provide `walk_*` functions for each datum. For example, -```rust +```rust,ignore pub fn walk_expr(visitor: &mut Visitor, e: &Expr) { match *e { Expr::IntLit(_) => {},