Alex Balgavy

Just some stuff about me.

Here's my dotfiles repository.

Check out my blog.

My keys: PGP, SSH

My crypto wallets (BTC, XMR)

Table of contents:

Jon Gjengset: Rust for Rustaceans

Rules/guidelines

Writing functions

Generic traits

Writing types

Writing errors

Documentation

Logging

tracing crate

Dependency management

Macros vs generics

If your code changes based on type, use generics. Otherwise, use macros.

Compiling and testing

Other notes

Concurrency/multithreading

Standardized polling:

Why not threads: hard to keep track, threads add up fast and complexity to keep track does too, switching between many threads is costly (each switch is round-trip to OS scheduler), introduce parallelism

Concurrency: execution of tasks is interleaved

Parallelism: multiple tasks executing at the same time

Macros

Declarative macros:

Traits

Orphan rule: you can implement a trait for a type only if the trait or the type is local to your crate. You can’t implement Debug for bool.

Generics

Functions

Static dispatch (fn x(a: impl Pattern), fn x<T: Pattern>(a: T)): need different copy of x for each impl Pattern type – need to know address of instance functions to call them. For each of the types, create a copy of the method with right addresses.

Dynamic dispatch (fn x(a: &dyn Pattern)): the caller must give address of pattern and address of any methods called on it, via vtable.

Traits

Rust traits can be generic: with type parameters (trait Foo<T>) or with associated types (trait Foo { type Bar;}). Use associated type if you only expect one implementation of the trait for a given type, use generic type parameter otherwise. Just use associated types whenever you can.

Trait object: type that implements a trait, and its vtable. So, dyn Trait is a trait object.

Type system guidance

Testing:

Not all compiler warnings are enabled by default. Those disabled by default are usually still being refined, or are more about style than content. A good example of this is the “idiomatic Rust 2018 edition” lint, which you can enable with #![warn(rust_2018_idioms)]. When this lint is enabled, the compiler will tell you if you’re failing to take advantage of changes brought by the Rust 2018 edition. Some other lints that you may want to get into the habit of enabling when you start a new project are missing_docs and missing_debug_implementations, which warn you if you’ve forgotten to document any public items in your crate or add Debug implementations for any public types, respectively.

With std::hint::black_box(x), you can tell compiler to assume that x is used in arbitrary ways that can’t be optimized out.