Course outline

Rust / Basic / Lesson 1

Cargo, editions, and program structure

Build a reproducible Rust package, separate compiler and package-manager responsibilities, and read program output independently from build diagnostics.

About 4 min readContent reviewed
On this page

Lesson goals

  • Identify a package, crate, manifest, and executable entry point.
  • Select edition 2024 explicitly and explain its toolchain requirement.
  • Compile complete examples without external dependencies.

An edition is not a compiler release

This course assumes stable Rust 1.85 or newer and edition 2024. Edition 2024 first became available in Rust 1.85; later compiler releases can still compile older editions. An edition selects language compatibility rules, while the compiler version determines available features and standard-library APIs. State both in a real project rather than assuming a date in a folder selects them. The examples use only the standard library and features available at this baseline. A package using newer APIs must raise and verify its minimum supported Rust version separately.

Cargo connects files to build targets

Cargo manages packages, dependencies, and build commands. A package has a Cargo.toml manifest and can contain library and binary crates. A crate is a compilation unit; src/main.rs conventionally defines a default binary and src/lib.rs a library. The manifest records package metadata, edition, and dependencies. cargo check checks code without producing the final executable, while cargo build builds it and cargo run builds then runs a selected binary. Keep build failure separate from the output of a previous executable so stale artifacts cannot masquerade as a successful repair.

A complete entry point

A binary normally starts at fn main. println! is a macro, indicated by the exclamation mark, that formats a message and adds a newline. Braces delimit the function body, and semicolons end statements. Save each complete example separately because both define main. The first program has no user input, file access, network operations, or crate dependencies. Its output is one line on standard output; compiler warnings, if any, use another diagnostic channel. Predicting that line before execution separates understanding the source from merely observing a terminal.

rust One line from a complete binary
fn main() {
    println!("Rust ready");
}
Expected output
Rust ready

The macro writes the text and a newline. No build-command text is part of this output.

Read values across a small function

Functions declare parameter and return types explicitly. The final expression in a block can supply its value without a semicolon. In the second example, total receives two u32 values and returns their sum. The selected small operands avoid overflow. main formats the returned value using a placeholder. For a standalone file, rustc --edition=2024 main.rs compiles it with explicit edition rules. In a package, put edition = "2024" and an appropriate rust-version in the package section of Cargo.toml rather than relying on a historical default.

rust A typed function result
fn total(left: u32, right: u32) -> u32 { left + right }
fn main() {
    println!("total={}", total(6, 9));
}
Expected output
total=15

The block returns fifteen because its last expression has no semicolon. Formatting labels the result.

Preserve commands and evidence

For an offline standard-library-only lab, cargo build --offline and cargo test --offline avoid dependency fetching; they still require an installed toolchain. Existing dependency packages must already be cached for offline builds. Cargo.lock records resolved dependency versions, while a toolchain configuration can pin compiler selection. Formatting and linting help review but do not prove business correctness. Read the first relevant diagnostic, fix its cause, rebuild, and compare behavior against a written expectation. Do not install arbitrary crates to solve a problem that a small standard-library example can isolate.

Common errors and fixes

An edition 2024 package is rejected.

Why it happens
The selected compiler predates Rust 1.85.
How to fix it
Select a compatible installed toolchain and check its version.
Prevent it next time
Record edition and minimum compiler version independently.

cargo check succeeds but no binary appears.

Why it happens
Checking did not request a final executable.
How to fix it
Use cargo build or cargo run for the intended target.
Prevent it next time
Distinguish checking, building, and running in instructions.

A function returns unit unexpectedly.

Why it happens
A semicolon discarded its final expression value.
How to fix it
Remove that semicolon or use an explicit return.
Prevent it next time
Compare the block value with the declared return type.

Check your understanding

1. Change total to add twelve and eighteen. State the full output and explain whether println! computes the arithmetic itself.

Show worked solution

Call total(12, 18). The line is total=30 followed by a newline. The function computes a u32 sum before formatting receives the result. The label is presentation, not part of the arithmetic. Compile the edited source again so the launched binary reflects the new call.

2. A standard-library-only package works online but offline compilation fails before checking source. List the two environmental facts to investigate first.

Show worked solution

Confirm the requested toolchain is installed and inspect whether the package truly has no external dependencies, including development or build dependencies. Offline mode does not install a missing compiler and cannot fetch uncached crates. Preserve the complete command and diagnostic before changing source, because this failure may be environmental rather than a Rust type error.

Key takeaways

  • Choose an explicit edition and compatible toolchain.
  • Keep package structure and observable program output separate.
  • Use reproducible standard-library labs before adding dependencies.

Official references