Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ on:
pull_request:

jobs:

test:
deploy-test:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
Expand All @@ -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
4 changes: 2 additions & 2 deletions anti_patterns/deny-warnings.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
11 changes: 8 additions & 3 deletions anti_patterns/deref.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion idioms/ctor.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> {
buf: RawVec<T>,
Expand Down
2 changes: 1 addition & 1 deletion idioms/default.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
9 changes: 6 additions & 3 deletions idioms/deref.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,19 @@ and borrowed views of data.

## Example

```rust
```rust,ignore
use std::ops::Deref;

struct Vec<T> {
...
data: T,
//..
}

impl<T> Deref for Vec<T> {
type Target = [T];

fn deref(&self) -> &[T] {
...
//..
}
}
```
Expand Down
2 changes: 1 addition & 1 deletion idioms/dtor-finally.md
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 4 additions & 2 deletions idioms/on-stack-dyn-dispatch.md
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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<dyn io::Read> = if arg == "-" {
Box::new(io::stdin())
Expand Down
4 changes: 4 additions & 0 deletions idioms/pass-var-to-closure.md
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion idioms/priv-extend.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ stability guarantees.

## Example

```rust
```rust,ignore
mod a {
// Public struct.
pub struct S {
Expand Down
4 changes: 2 additions & 2 deletions idioms/rustdoc-init.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Each of these methods should have examples.

For example:

```rust
```rust,ignore
struct Connection {
name: String,
stream: TcpStream,
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions idioms/temporary-mutability.md
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -26,7 +26,7 @@ let data = {

Using variable rebinding:

```rust
```rust,ignore
let mut data = get_vec();
data.sort();
let data = data;
Expand Down
27 changes: 18 additions & 9 deletions patterns/RAII.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,40 @@ 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<T> {
// We keep a reference to our data: T here.
...
//..
}

struct MutexGuard<'a, T: 'a> {
data: &'a T,
...
//..
}

// Locking the mutex is explicit.
impl<T> Mutex<T> {
fn lock(&self) -> MutexGuard<T> {
// Lock the underlying OS mutex.
...
//..

// MutexGuard keeps a reference to self
MutexGuard { data: self, ... }
MutexGuard {
data: self,
//..
}
}
}

// Destructor for unlocking the mutex.
impl<'a, T> Drop for MutexGuard<'a, T> {
fn drop(&mut self) {
// Unlock the underlying OS mutex.
...
//..
}
}

Expand All @@ -52,7 +59,7 @@ impl<'a, T> Deref for MutexGuard<'a, T> {
}
}

fn main(x: Mutex<Foo>) {
fn baz(x: Mutex<Foo>) {
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
Expand Down Expand Up @@ -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`).
Expand Down
10 changes: 6 additions & 4 deletions patterns/builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
}

Expand Down Expand Up @@ -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();
Expand Down
6 changes: 3 additions & 3 deletions patterns/compose-structs.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion patterns/fold.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
18 changes: 11 additions & 7 deletions patterns/newtype.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,31 @@ 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.
pub struct Bar(Foo);

impl Bar {
// Constructor.
pub fn new(...) -> Bar {
...
pub fn new(
//..
) -> Bar {

//..

}

...
//..
}

fn main() {
Expand Down Expand Up @@ -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<T1, T2>);
```

Expand Down
Loading