Skip to content

Rust Syntax

Now that you can run Rust, let’s slow down and look at what each part of a program actually means. We’ll use the smallest possible example and take it apart piece by piece.

fn main() {
println!("Hello, World!");
}

Output:

Hello, World!
▶ Try it Yourself
fn main() {
// your code runs here
}

Every Rust program starts at a function called main. When you run your program, Rust looks for main and runs the code inside it.

  • fn is the keyword for defining a function (a named block of code).
  • main is the function’s name — this specific name is special; it’s the entry point.
  • () holds the function’s inputs (empty here — main takes none).
  • { } curly braces wrap the body — the code that belongs to the function.

Inside the body, each instruction is usually a statement, and statements end with a semicolon ;:

fn main() {
let x = 5;
let y = 10;
println!("{}", x + y);
}

Output:

15
▶ Try it Yourself

Leaving off a semicolon where one is expected is one of the most common beginner errors — and the compiler will point right at it.

Rust code is made of two kinds of pieces, and the difference matters more in Rust than in most languages:

  • A statement does something but gives back no value. let x = 5; is a statement.
  • An expression produces a value. 5, x + 1 and x * 2 are all expressions.

Here’s the part that surprises people: a block of code in curly braces { } is an expression too. Its value is the last line, written without a semicolon:

fn main() {
let x = 5;
let y = {
let doubled = x * 2; // a statement inside the block
doubled + 1 // no semicolon: this is the block's value
};
println!("y is {y}");
}

Output:

y is 11
▶ Try it Yourself

The block runs its statements, then hands back doubled + 1, which is 11, and that becomes y. Notice the semicolon after the closing }: the whole let y = ...; line is still a statement.

If you add a semicolon after doubled + 1, it stops being the block’s value. The block then gives back “nothing” (Rust writes that as ()), and println! can’t print it, so the code won’t compile. This “no semicolon on the last line” rule is exactly how functions return values. You’ll see it again on the Functions page and with if as an expression.

Look closely at println! — that exclamation mark isn’t a typo. The ! means it’s a macro, not a regular function.

You don’t need to fully understand macros yet. Just know this: when you see !, it’s a macro. For now the only one you’ll use is println! for printing text.

fn main() {
println!("This is a macro call");
}

Inside println!, curly braces {} are placeholders that get filled in with values you pass after the text:

fn main() {
let name = "Ferris";
let age = 10;
println!("{} is {} years old", name, age);
}

Output:

Ferris is 10 years old
▶ Try it Yourself

You can also put the variable name directly inside the braces, which is often cleaner:

println!("{name} is {age} years old");

Rust doesn’t care about indentation the way Python does — it uses the curly braces { } to know where blocks begin and end. Indentation is just for humans to read the code more easily.

That said, the community has a standard style, and Rust ships a tool to enforce it automatically:

Terminal window
cargo fmt

Running cargo fmt reformats your code to the official style. Get in the habit of using it.

You can leave notes in your code that Rust ignores. These are comments, and they start with //:

fn main() {
// This is a comment — Rust skips it
println!("Hello!"); // comments can go at the end of a line too
}

We cover comments in more detail on the next page.

Create two variables, a = 7 and b = 3, and print 7 + 3 = 10. Let Rust do the adding. Hint: a println! can have several {} placeholders, filled in order by the values after the text.

Show solution
fn main() {
let a = 7;
let b = 3;
println!("{} + {} = {}", a, b, a + b);
}

Output:

7 + 3 = 10
▶ Try it Yourself

A shop sells 3 items at a price of 4 each, plus 2 for shipping. Compute total with a { } block: inside it, make a subtotal, then give back subtotal + 2. Print Total: 14. Hint: the last line of the block must have no semicolon.

Show solution
fn main() {
let price = 4;
let quantity = 3;
let total = {
let subtotal = price * quantity;
subtotal + 2 // shipping
};
println!("Total: {total}");
}

Output:

Total: 14
▶ Try it Yourself
  • Every program starts in the main function.
  • Code lives inside curly braces { }; most statements end with ;.
  • Statements do something; expressions produce a value. A block’s last line without ; is its value.
  • A ! (like in println!) means it’s a macro.
  • {} inside println! are placeholders filled by the values you pass.
  • Indentation is for readability — run cargo fmt to auto-format.

Quick check

1. What is special about the main function in a Rust program?

2. What does the ! after println mean?

3. What is the value of y after let y = { let a = 2; a + 1 };?

Score: 0 / 3