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

Status

borrow-core is young and still changing, but you can write real programs in it today. This page says what works, what you are likely to trip over, and what is coming. It is the one place the book lists what isn’t built yet.

What works today

  • Ownership and borrows: imm and mut borrows, &x and &mut x, borrow blocks, let mut (Ownership and borrows)
  • Functions and closures, reusable and one-shot (Functions as values)
  • Numbers: i32, i64, u8, f32, f64; integer division by zero raises an error you can handle (Numbers, Division)
  • Records and variants with match (Records and variants)
  • Recursive data: lists and trees, folds, and types that hold a Vec, an array or a map of themselves (Data and generics)
  • Recursion, with deep recursion on the heap (Recursion)
  • Arrays, views and slices: split, swap, sort (Arrays)
  • Vectors, buffers and UTF-8 strings (Buffers and strings)
  • Generics: generic functions and types (Generic functions)
  • poly families: operators, equality, hashing and order at your own types (poly families)
  • Hash maps and sets (Maps and sets)
  • Loops: counted for with break, continue and else; while and loop; bounded runs with div_fuel (Iteration)
  • Generators and |> pipelines (Generators)
  • Effects and handlers, with effects inferred (Effects and handlers)
  • Errors as raise and handlers, no ? needed (Errors)
  • I/O: standard input, output and error, the clock and the command-line arguments (Input and output)
  • Async tasks: spawn, resume, cancel, logged and scoped tasks, and a task that borrows its own data across await (Async tasks)
  • Two targets: WebAssembly (bcc run) and native code through LLVM (bcc run --native), with the same I/O on both (Getting started)
  • Safety proved in Lean: a program that compiles can’t use memory after freeing it, free it twice or leak it (Safety guarantees)

Things you’ll run into

Types and syntax

  • The unit type is spelled 1, not () (#148).
  • No unary minus, +=, or bitwise and shift operators: write 0 - x, x = x + 1, host[and32](a, b), host[shl64](n, 3) (#583).
  • No indexing sugar such as v[i] (#143).
  • total, leaf, node and swap are reserved, so they can’t be names of variables or functions.
  • == doesn’t compare two bools; use if or match.
  • An if or borrow block can’t be a call’s argument: bind it with let first.

Borrows

  • &mut r.field doesn’t parse: take the record apart, borrow the field, and build it again.
  • &x and &mut x must be the whole call of a let or statement: write let n = len(&v); f(n), not f(len(&v)) (#510).
  • A heap cell can’t be lent with &c to a function that does I/O or performs an answering (fn) operation; lend it with a block instead, borrow imm c { r -> show(r) }. A function that may raise takes &c like any other.
  • A borrow can’t be lent on with &mut m; pass it and hand it back instead (Borrow blocks).
  • Two borrow blocks can’t be nested over two different owners; inside a block, lend the second owner to a call with &d instead.
  • A for over a view of a buffer or string must be in a function that takes the view, not directly inside the borrow block (a view of an array works either way).

Data

  • A text view can be used only once, so a word can’t be looked up in a map and then inserted as a key.
  • Folds (fold_imm, fold_own, fold_reuse) don’t walk a type that holds a Vec of itself; write the recursion, as in Collections of recursive data.

Loops, generators and effects

  • The body of a while or loop can’t perform an operation that a handler in the program serves: no raise, no division by a variable, and no operation of your own effects. The platform’s I/O works. Use a counted for, or do it after the loop (#522).
  • A generator can’t use a capability, such as standard output, across a yield. The body of a for over a library adapter (map, filter, take, …), or over a generator that calls another generator directly, can’t do I/O: collect the values in the loop and print after it.
  • A callback stored with its effects, rather than called, isn’t supported yet (#161).
  • An effect can’t mix answering (fn) and control (ctl) operations, and an operation can’t answer with a borrow into its handler’s state.
  • An error can’t carry an owned value yet (#215).
  • A reusable closure that keeps state between calls (Rust’s FnMut) has no surface syntax yet; a handler with state does the same job (Effects and handlers).

I/O and async

  • A program can’t set its exit status.
  • Async is cooperative and single-threaded, with no event loop over real I/O, platform timers or wakers yet (#52).
  • A task can hold a mut borrow of its own cell across await, and a task of spawn_in a borrow lent from outside its scheduler. Other borrows held across an await or a yield are not implemented yet (Async tasks). Two tasks can’t share one output stream.

Performance

  • Some programs are still slower than their Rust versions (#213).

On the roadmap

  • Modules and packages (#63)
  • Traits, or bounds on type parameters, and derived cases (#489)
  • Operator sugar: unary minus, compound assignment, bitwise and shifts (#583)
  • Files, environment variables and randomness; networking (#597)
  • Threads and parallelism (#212)
  • Interior mutability (#119)
  • Unsafe code and a C FFI (#79)
  • Panics and backtraces (#192)
  • Libraries: JSON (#65), regular expressions (#225)
  • Sized types (#72)