Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Types

Structs

Unit Structs

No fields:

struct Unit
pvt struct PvtUnit

Newtype / Tuple Structs

Positional fields in parentheses:

struct Newtype(i64)
struct Pair(i64, i64)

Fields can have visibility:

struct TupleVis(pvt i64, String)

Record Structs

Named fields in braces:

struct Point {
  x: i64,
  y: i64,
}

Field visibility:

struct RecordVis {
  pvt name: String,
  age: i64,
}

Generics

Type parameters with optional bounds:

struct Container<T> {
  value: T,
}

struct Bounded<T: Clone + Debug> {
  value: T,
}

struct Multi<T: Clone, U: Display> {
  first: T,
  second: U,
}

Where Clauses

Complex bounds can use where:

struct WithWhere<T, U> where T: Clone + Debug, U: Display {
  first: T,
  second: U,
}

struct BoundedTuple<T>(T) where T: Clone

Attributes

#[derive(Debug, Clone)]
struct Annotated {
  field: i64,
}

#[derive(Debug)]
#[repr(C)]
struct CRepr {
  x: i32,
  y: i32,
}

Multiple attributes can be stacked.

Everything Combined

#[derive(Debug, Clone, PartialEq)]
pvt struct FullBellsAndWhistles<T, U: Default> where T: Clone + Debug {
  pvt id: i64,
  name: String,
  data: T,
  extra: U,
}

Recursive Structs

Use Box for indirection:

struct List<T> {
  head: T,
  tail: Option<Box<List<T>>>,
}

Struct Literals

Creating struct values:

Point { x: 1, y: 2 }

Shorthand when variable names match fields:

let x = 1
let y = 2
Point { x, y }         // same as Point { x: x, y: y }

Spread to copy remaining fields:

let p = Point { x: 1, y: 2 }
Point { x: 10, ..p }   // y comes from p

Path-qualified:

std::geo::Point { x: 1, y: 2 }

Nested:

Line { start: Point { x: 0, y: 0 }, end: Point { x: 1, y: 1 } }

Enums

Unit Variants

C-style enumerations:

enum Color { Red, Green, Blue }
pvt enum Internal { A, B }

Tuple Variants

Variants carrying unnamed data:

enum Option<T> {
  Some(T),
  None,
}

enum Result<T, E> {
  Ok(T),
  Err(E),
}

Record Variants

Variants with named fields:

enum Shape {
  Circle { radius: f64 },
  Rectangle { width: f64, height: f64 },
}

Mixed Variants

An enum can mix unit, tuple, and record variants:

enum Message {
  Quit,
  Move { x: i64, y: i64 },
  Write(String),
  ChangeColor(i64, i64, i64),
}

Generics, Bounds, and Where Clauses

enum Wrapper<T: Clone> {
  Item(T),
  Empty,
}

enum Constrained<T, U> where T: Clone, U: Debug {
  Both(T, U),
  First(T),
}

Recursive Enums

enum Tree<T> {
  Leaf(T),
  Node(Box<Tree<T>>, Box<Tree<T>>),
}

GADTs

Variants can specialize their return type with ->:

enum Expr<T> {
  LitInt(i64) -> Expr<i64>,
  LitBool(bool) -> Expr<bool>,
  Add(Expr<i64>, Expr<i64>) -> Expr<i64>,
  If(Expr<bool>, Expr<T>, Expr<T>) -> Expr<T>,
  Eq(Expr<i64>, Expr<i64>) -> Expr<bool>,
}

This enables type-safe expression trees where the type parameter tracks the result type of each node.

Type Aliases

type Byte = i8
type Result<T> = std::result::Result<T, MyError>
type Pair<A, B> = Tuple2<A, B>
type CloneVec<T: Clone> = Vec<T>
type Mapped<T, U> = Map<T, U> where T: Clone, U: From<T>
pvt type Internal = InternalImpl

Tuples

Ordered, fixed-size groups of values:

(1, 2)
(42, "hello", true)
(1, (2, 3))          // nested

Arrays

Fixed-size, homogeneous collections:

[1, 2, 3]
[]                    // empty
["hello", "world"]
[[1, 2], [3, 4]]     // nested

Array types are written [T; n]:

fn make_array() -> [i64; 3]:
  [1, 2, 3]