Rust from the ground up

Your first Rust program

What Rust is, what the compiler does for you, and the smallest complete program — one function, one line of output, and a run.

Part 1 of 12

Beginner12 min readBack to Courses

What Rust is for

Rust is a language for code that has to be fast and has to keep working: command-line tools, servers, engines, anything close to the machine. It gives you the speed of C without the two things that ruin C programs — manual memory management and data races between threads.

The way it does that is the compiler. Rust checks your program before it runs, and most of what goes wrong in other languages — using memory after it is gone, two threads writing the same value, forgetting to handle an error — is caught at that point, with a message that names the line. That strictness is the whole trade: a little more work while writing, far less while debugging.

The shape of every program

A Rust program starts at main. That is the function the system calls, and everything your program does happens because main asked for it. This site runs a single file, so every example here is one main.rs with a main in it.

On your own machine you would write the same file inside a project made by cargo, Rust's build tool and package manager: cargo new hello makes a folder, cargo run builds and runs it. Cargo is also what fetches other people's crates, Rust's word for packages — the course comes back to it once your programs have more than one file.

Printing

println! prints a line. The ! matters: it is a macro, not an ordinary function — a piece of the language that writes code for you, which is how Rust can read the text inside the string and check that the values you pass match the blanks you left. {} is a blank for a value, and the values come after the string, in order.

Statements end in a semicolon. The last line of a function without one is the value it hands back — a rule the next chapter leans on, and one of the places Rust reads more like arithmetic than like a script.

One program, end to end

fn main() {
    let language = "Rust";
    let year = 2015;

    // {} fills from the values in order.
    println!("Hello from {}!", language);
    println!("The first stable release was in {}.", year);
}

Run it, then make it yours

Press Run to see the program compile and print. Then change the name and the year, add one more println! line of your own, and run again.

Output
Click "Run" to execute your code

Change a value and press Run again. The run goes to a real compiler on the server, so the first one may take a second — after that the round trip is quick.

When the compiler complains

The compiler is a colleague with no patience and a good memory. When something is wrong it prints an error code such as E0425, the line and column, a caret under the exact character, and often a help: line with the fix. Read the first error first: one missing semicolon can produce a page of follow-on messages, and they usually disappear together.

Warnings are different. They mean the program builds and runs, but something is suspicious — a variable that is never used, a name that is not snake case. Treat a warning as a question: either fix it, or rename the variable with a leading underscore to say you meant to keep it. Either way, do not scroll past it.

Formatting is checked, not guessed

println! is checked before the program runs. The macro reads the string and counts the blanks, so println!("{} {}", 1) is a compile error rather than a line that prints half a sentence. That is why the ! matters: an ordinary function could not see the text inside its argument while the code is compiled.

Format details sit between the braces. A width pads a value — {:>6} right-aligns it in six columns — {:.2} keeps two decimal places, and {:?} prints the debug shape. To print a literal brace, double it: {{ and }}, because a single brace opens a blank.

Three mistakes explain most first runs. A missing semicolon makes the parser read the next line as a continuation, so the error points after the real mistake; println without the ! is an unknown function; and a blank in the string with no value after it is an argument-count error. Read the caret before you read the page.

Try these next

  • Print a three-column receipt with {:>8} on the prices, and check that the decimal points line up.
  • Print a literal pair of braces with {{ }}, then print a real value inside braces on the next line.
  • Delete a semicolon on purpose, run it, and match the caret to the character the compiler stopped at.

A name badge, aligned

Run it to see the columns, then change the width from 20 to 24 and make the border match. Add a second person and print their badge below the first.

Output
Click "Run" to execute your code

Check what you learned

One question at a time. A wrong answer explains itself — take another go.

Part 1 of 5

Where does a Rust program begin?