Professional Documents
Culture Documents
Rust Language Cheat Sheet
Rust Language Cheat Sheet
Sheet
20.07.2020
Contains clickable links to The Book BK, Rust by Example EX, Std Docs STD, Nomicon NOM,
Reference REF. Other symbols used: largely deprecated 🗑, has a minimum edition '18, is work
in progress 🚧, or bad 🛑.
Data Structures
Data types and memory locations de�ned via keywords.
Example Explanation
struct S (T); De�ne "tupled" struct with numbered �eld .0 of type T .
enum E { A, B De�ne variants of enum; can be unit- A , tuple- B () and struct-
(), C {} } like C{} .
const X: T = T(); De�nes constant BK EX REF. Copied into a temporary when used.
let mut x: T; Like let , but allow for mutability BK EX and mutable borrow.2
interior mutability.
Creating and accessing data structures; and some more sigilic types.
Example Explanation
S (x) Create struct S (T) or use 'ed enum E::S () with �eld .0 set to x .
[S] Array type of unspeci�ed length, i.e., slice. STD EX REF Can't live on stack. *
s.x Named �eld access, REF might try to Deref if x not part of type S .
Example Explanation
&S Shared reference BK STD NOM REF (space for holding any &s ).
*const S Immutable raw pointer type BK STD REF w/o memory safety.
Mutable ref binding ( let x = &mut s.x ), shorthand
let S { ref mut x } =
destructuring ↓ version.
s;
Special case for Box that can also move out Box'ed content if it
s = *my_box;
isn't Copy .
&'a S Only accepts a s with an address that lives 'a or longer.
trait T<'a> {} Signals a S which impl T for S might contain address.
Example Explanation
const fn f() {} Constant fn usable at compile time, e.g., const X: u32 = f(Y) . '18
Same, but make f return an impl Future<Output=S> .
async fn f() -> S {}
return || true Closures sometimes look like logical ORs (here: return a closure).
Control Flow
Control execution within a function.
Example Explanation
loop {} Loop in�nitely REF until break . Can yield value with break x .
for x in iter
Syntactic sugar to loop over iterators. BK STD REF
{}
'label: loop {} Loop label EX REF, useful for �ow control in nested loops.
break x Same, but make x value of the loop expression (only in actual loop ).
break 'label Exit not only this loop, but the enclosing one marked with 'label .
continue Continue expression REF to the next loop iteration of this loop.
continue 'label Same, but instead of enclosing loop marked with 'label .
Only works inside async . Yield �ow until FFuuttuurree STD or Stream x ready.
x.await
REF '18
X::f(x) Same as x.f() . Unless impl Copy for X {} , f can only be called once.
T::f(&x) Same as x.f() if X impl T , i.e., x.f() �nds methods of T if in scope.
Call trait method T::f() implemented for X .
<X as T>::f()
Organizing Code
Segment projects into smaller units and minimize dependencies.
Example Explanation
Declare external dependencies and ABI (e.g., "C" ) from FFI. BK EX NOM
extern "C" {}
REF
Example Explanation
Self Type alias for implementing type REF, e.g. fn new() -> Self .
&self Same, but refers to self as borrowed, same as f(self: &Self)
&mut self Same, but mutably borrowed, same as f(self: &mut Self)
Example Explanation
$x:meta A meta item; the things that go inside #[...] and #![...] attributes.
$x:tt A single token tree, see here for more details.
$(x)<<+ In fact separators other than , are also accepted. Here: << .
Pattern Matching
Constructs found in match or let expressions, or function parameters.
Example Explanation
Initiate pattern matching BK EX REF, then use match arms, c.
match m {}
next table.
let S(x) = get(); Notably, let also destructures EX similar to the table below.
let (a, ..) = abc; Ignoring 'the rest' also works.
Example Explanation
Speci�c bindings take precedence over 'the rest', here a is 1 , b
let (.., a, b) = (1,
is 2 .
2);
if let Some(x) = get() Branch if pattern can be assigned (e.g., enum variant), syntactic
{} sugar. *
Pattern matching arms in match expressions. Left side of these arms can also be found in let
expressions.
S { x: 0, y: 1 } => Match struct with speci�c values (only accepts s with s.x of 0 and
{} s.y of 1 ).
S { x: a, y: b } =>
Match struct with any(!) values and bind s.x to a and s.y to b .
{}
(a, 0) => {} Match tuple with any value for a and 0 for second.
Slice pattern, REF 🔗 match array with any value for a and 0 for
[a, 0] => {}
second.
[1, ..] => {} Match array starting with 1 , any value for rest; subslice pattern. ?
[2, .., 5] => {} Match array starting with 1 , ending with 5 .
Same, but also bind x to slice representing middle (c. next entry).
[2, x @ .., 5] => {}
Same, but bind x if all variants have it.
E::C {x} | E::D {x}
S { x } if x > 10 => Pattern match guards, BK EX REF condition must be true as well to
{} match.
Example Explanation
A generic BK EX type with a type parameter ( T is placeholder
S<T>
name here).
T: R, P: S Independent trait bounds (here one for T and one for P ).
Same; does esp. not mean value t will 🛑 live 'static , only that
T: 'static
it could.
'b: 'a Lifetime 'b must live at least as long as (i.e., outlive) 'a bound.
Example Explanation
Raw string literal, UTF-8, but can also contain " . Number of # can
r#"..."# , ...
vary.
b"..." Byte string literal; REF constructs ASCII [u8] , not a string.
br"..." ,
Raw byte string literal, ASCII [u8] , combination of the above.
br#"..."#
' 🦀' Character literal, REF �xed 4 byte unicode 'char'. STD
Comments
No comment.
Example Explanation
# In doc tests, hide line from documentation ( ``` # use hidden; ``` ).
Miscellaneous
These sigils did not �t any other category but are good to know nonetheless.
Example Explanation
1_u8 Type speci�er for numeric literals EX REF (also i8 , u16 , ...).
Common Operators
Rust supports most operators you would expect ( + , * , % , = , == ...), including overloading. STD Since
they behave no di�erently in Rust we do not list them here.
Language Sugar
If something works that "shouldn't work now that you think about it", it might be due to one of
these.
Name Description
Deref NOM Deref x: T until *x , **x , ... compatible with some target S .
Lifetime Elision BK NOM REF Automatically annotate f(x: &T) to f<'a>(x: &'a T) .
Editorial Comment 💬 — The features above will make your life easier, but might hinder
your understanding. If you are new to Rust, you should consider reading about them in
more detail.
Standard Library
Common One-Liners
Snippets that are common, but still easy to forget. See Rust Cookbook 🔗 for more.
Intent Snippet
Parse a number "42".parse::<u32>()?
🧵 Thread Safety
Examples SSeenndd* !!SSeenndd
* An instance t where TT:: SSeenndd can be moved to another thread, a TT:: SSyynncc means &t can be moved to another thread.
1 If T is Sync .
2 If T is Send .
🚥 Iterators
Using Iterators Implementing Iterators
Basics
The Iterator
Once you have an i :
For Loops
* If it looks as if it doesn't consume c that's because type was Copy . For example, if you call
(&c).into_iter() it will invoke .into_iter() on &c (which will consume the reference and turn
it into an Iterator), but c remains untouched.
String Conversions
If you want a string of type ...
String CString OsString PathBuf Vec<u8> &str &CStr &OsStr &Path &[u8]
CString x.into_string()?
OsString x.to_str()?.into()
PathBuf x.to_str()?.into()
Vec<u8> 1 String::from_utf8(x)?
&str x.into()
&CStr x.to_str()?.into()
&OSStr x.to_str()?.into()
&Path x.to_str()?.into()
&[u8] 1 String::from_utf8_lossy(x).into()
1 You should, or must if call is unsafe , ensure raw data comes with a valid representation for the string type (e.g., UTF-8
data for a String ).
2 Only on some platforms os::<your_os>:: OsStrExt exists with helper methods to get a raw &[u8]
representation of the underlying OsStr . Use the rest of the table to go from there, e.g.:
use OsStrExt;
let bytes: &[u8] = my_os_str.as_bytes();
CString::new(bytes)?
3 The c_char must have come from a previous CString . If it comes from FFI see &CStr instead.
String Formatting
Formatting applies to print! , eprint! , write! (and their - ln siblings like println! ). Each format
argument is either empty {} , {argument} , or follows a basic syntax:
{ [argument] ':' [[fill] align] [sign] ['#'] [width [$]] ['.' precision [$]] [type] }
Element Meaning
fill The character to �ll empty spaces with (e.g., 0 ), if width is speci�ed.
Minimum width (≥ 0), padding with fill (default to space). If starts with 0 ,
width
zero-padded.
Example Explanation
{val:^2$} Center the val named argument, width speci�ed by the 3rd argument.
{val:#x} Format val argument as hex, with a leading 0x (alternate format for x ).
Tooling
Project Anatomy
Basic project layout, and common �les and folders, as used by cargo . ↓
Entry Code
📁 benches/
Benchmarks for your crate, run via ccaarrggoo bbeenncchh, requires nightly by
default. * 🚧
📁 examples/
Examples how to use your crate, they see your crate like external user
would.
Individual examples are run like ccaarrggoo rruunn ----eexxaammppllee mmyy__eexxaammppllee.
my_example.rs
Default entry point for libraries. This is where lookup for f()
lib.rs
starts.
📁 tests/
Integration tests go here, invoked via ccaarrggoo tteesstt. Unit tests often stay
in src/ �le.
.clippy.toml Special con�guration for certain clippy lints, utilized via ccaarrggoo cclliippppyy
Module tree needs to be explicitly de�ned, is not implicitly built from �le system tree. 🔗
Module tree root equals library, app, ... entry point (e.g., lib.rs ).
A mod m {} de�nes module in-�le, while mod m; will read m.rs or m/mod.rs .
Path of .rs based on nesting, e.g., mod a { mod b { mod c; }}} is either a/b/c.rs
or a/b/c/mod.rs .
Files not pathed from module tree root via some mod m; won't be touched by
compiler! 🛑
Cargo
Commands and tools that are good to know.
Command Description
cargo +{nightly, stable} Runs command with given toolchain, e.g., for 'nightly only'
... tools.
A command like cargo b uild means you can either type cargo build or just cargo b .
These are optional rustup components. Install them with rustup component add [tool] .
Tool Description
cargo clippy Additional (lints) catching common API misuses and unidiomatic code. 🔗
cargo fmt Automatic code formatter ( rustup component add rustfmt ). 🔗
Cross Compilation
🔘 Check target is supported.
🔘 Install target via .
rruussttuupp ttaarrggeett iinnssttaallll XX
[target.aarch64-linux-android]
linker = "[PATH_TO_TOOLCHAIN]/aarch64-linux-android/bin/aarch64-linux-android-clang"
or
[target.aarch64-linux-android]
linker = "C:/[PATH_TO_TOOLCHAIN]/prebuilt/windows-x86_64/bin/aarch64-linux-android21-clang.cmd"
Sometimes (depending on how compiler complains) you might also need to set an environment variable. Note t
platforms / con�guration can be extremely sensitive how paths are speci�ed (e.g., \ vs / ) and quoted:
set CC=C:\[PATH_TO_TOOLCHAIN]\prebuilt\windows-x86_64\bin\aarch64-linux-android21-clang.cmd
Coding Guides
Idiomatic Rust
If you are used to programming Java or C, consider these.
Idiom Code
Think in Expressions x = if x { a } else { b };
x = loop { break 5 };
names.iter().filter(|x| x.starts_with("A"))
Idiom Code
Handle Absence with
x = try_something()?;
??
get_option()?.run()?
Split
Generic types S<T> can have a separate impl per T .
Implementations
Rust doesn't have OO, but with separate impl you can get
specialization.
Implement Traits #[derive(Debug, Copy, ...)] and custom impl where needed.
🔥 We highly recommend you also follow the API Guidelines (Checklist) for any shared
project! 🔥
Async-Await 101
If you are familiar with async / await in C# or TypeScript, here are some things to keep in mind:
Construct Explanation
Anything declared async always returns an
async
impl Future<Output=_> . STD
Function f returns an
async fn f() {}
impl Future<Output=()> .
Closures in APIs
There is a subtrait relationship Fn : FnMut : FnOnce . That means a closure that implements Fn STD
also implements FnMut and FnOnce . Likewise a closure that implements FnMut STD
also implements
FnOnce . STD
Notice how asking for a Fn closure as a function is most restrictive for the caller; but having a Fn closure as a caller is most
compatible with any function.
|| { &s; } FnOnce , FnMut , Fn May not mutate state; but can share and reuse s .
* Rust prefers capturing by reference (resulting in the most "compatible" Fn closures from a caller perspective), but can be
forced to capture its environment by copy or move via the move || {} syntax.
Allows g() to change caller Caller may not reuse captures during g()
F: FnMut
state. .
Reading Lifetimes
Lifetimes can be overwhelming at times. Here is a simpli�ed guide on how to read and interpret
constructs containing lifetimes if you are familiar with C.
To explicitly talk about a location that can hold such a location we do &S .
&'a S A &S is a location that can hold (at least) an address, called reference.
Any address stored must be proven to exist for at least (outlive) duration
'a .
In other words, the &S part sets bounds for what any address here must
contain.
While the &'a part sets bounds for how long any such address must at
least live.
&S Sometimes 'a might be elided (or can't be speci�ed) but it still exists.
&s This will produce the actual address of location ss, called 'borrow'.
Borrowing of s stops once last &s is last used, not when &s dropped.
A &mut will allow the owner of the borrow (address) to change s content.
Construct How to read
This reiterates that not the value in s , but location of s is borrowed.
1 Compare Data Structures section above: while true for synchronous code, an async 'stack frame' might actually be placed
on to the heap by the used async runtime.
S<'a> {} Signals that S will contain at least one address (i.e., reference).
*
f<'a>(x: &'a T) Signals this function will accept an address (i.e., reference).
'a will be picked so that it satis�es input and output at call site.
So while result address with 'a is used, input address with 'a is
locked.
<'a, 'b: 'a> The lifetimes declared in S<> and f<> can also have bounds.
The <'a, 'b> part means the type will handle at least 2 addresses.
The 'b: 'a part is a lifetime bound, and means 'b must outlive 'a .
Unsafe Code
API Stability
When updating an API, these changes can break client code, compare RFC 1105. Major changes
(🔴) are de�nitely breaking, while minor changes ( ) might be breaking:
Crates
🔴 Making a crate that previously compiled for stable require nightly.
Altering use of Cargo features (e.g., adding or removing features).
Modules
🔴 Renaming / moving / removing any public items.
Adding new public items, as this might break code that does use *.
Structs
🔴 Adding private �eld when all current �elds public.
🔴 Adding public �eld when no private �eld exists.
Adding or removing private �elds when at least one already exists (before and after the
change).
Going from a tuple struct with all private �elds (with at least one �eld) to a normal struct,
or vice versa.
Enums
🔴 Adding new variants.
🔴 Adding new �elds to a variant.
Traits
🔴 Adding a non-defaulted item, breaks all existing .
impl T for S {}
🔴 Any non-trivial change to item signatures, will a�ect either consumers or implementors.
Adding a defaulted item; might cause dispatch ambiguity with other existing trait.
Traits
Adding a defaulted type parameter.
Traits
🔴 Implementing any "fundamental" trait, as not implementing a fundamental trait already
was a promise.
Inherent Implementations
Adding any inherent items; might cause clients to prefer that over trait fn and produce
compile error.
Loosening bounds.
Generalizing to generics.
Signatures in Functions
🔴 Adding / removing arguments.
Introducing a new type parameter.
Generalizing to generics.
Behavioral Changes
🔴/ Changing semantics might not cause compiler errors, but might make clients do wrong
thing.