Learn / Rust Practical Systems
Rust Language and Cargo Foundations
A consolidated foundations lesson preserving 3 focused PTesting lessons without duplicating an unrelated authored PTLearn topic.
Course: Rust Practical Systems. Level: Intermediate. Topic: Systems reliability.
Stage: basic - Foundation - Language and runtime foundations. Connect rust language and cargo foundations to the professional workflow for Rust Systems.
Outcomes
- Describe Rust's goals: safety, performance, concurrency, and maintainability
- Recognize compile-time guarantees that replace runtime checks or garbage collection
- Read compiler diagnostics as design feedback rather than as mere errors
- Create binary and library packages with Cargo
- Use Cargo commands for building, checking, testing, formatting, linting, and documentation
- Understand Cargo.toml, Cargo.lock, crates.io, features, and profiles at a practical level
- Use let bindings, mutability, scalar types, compound types, functions, and expressions
- Write if, match, loop, while, for, and iterator-based transformations
- Recognize when semicolons turn expressions into statements
Concepts
- Rust Orientation
- The Rust value proposition
- Compiler feedback as a workflow
- Rust for Reliable Systems and Services foundations
- Guided practice
- Cargo and Tooling
- Project structure
- Dependencies, lockfiles, and features
- Syntax and Control Flow
- Expressions and bindings
- Loops and iterators
Concept flow
Show how language and runtime foundations moves from trigger to implementation outcome in Rust Systems.
- Language model
- Runtime behavior
- Engineering decision
- Verification evidence
Session flow
- Model Rust Orientation (concept, 64 min) — Name the decisions behind Rust Orientation before writing code.
- Describe Rust's goals: safety, performance, concurrency, and maintainability
- Explain where Rust Orientation belongs in job orchestration service.
- Build the vertical slice (walkthrough, 115 min) — Implement the smallest useful slice in legacy/rust-systems/rust-language-and-cargo-foundations.txt.
- Recognize compile-time guarantees that replace runtime checks or garbage collection
- Connect The Rust value proposition to a working example.
- Verify and harden (exercise, 76 min) — Reference solution: memory safety: ownership and borrowing prevent dangling references and many use-after-free bugs at compile time.
zero-cost abstractions: iterators, generics, and traits are designed to optimize away like hand-written code.
fearless concurrency: Send, Sync, and ownership rules prevent many data races in safe Rust.
- Read compiler diagnostics as design feedback rather than as mere errors
- Record one risk or follow-up before moving on.
- Why Rust and How to Think in Rust: The Rust value proposition (concept, 38 min) — Rust is a compiled systems language with strong static types, deterministic destruction, and memory safety without a garbage collector. It is especially useful when code must be fast, predictable, embeddable, or concurrent while still being maintainable by teams.
- Rust gives one owner to each value and checks references at compile time.
- The compiler rejects data races in safe Rust by combining ownership with Send and Sync.
- Zero-cost abstractions mean high-level code often compiles to code comparable to manual implementations.
- Rust's learning curve is front-loaded because the compiler asks you to prove ownership decisions early.
- Safe Rust means code that does not use unsafe blocks; it can still panic, leak memory, or contain logic bugs.
- Retained source example: A tiny Rust program
fn main() {
let language = "Rust";
println!("Hello, {language}!");
}
Expected output: Hello, Rust!
The main function is the program entry point. The println! macro expands at compile time and supports captured formatting variables.
- Why Rust and How to Think in Rust: Compiler feedback as a workflow (walkthrough, 38 min) — Rust developers often write a small slice, compile, read diagnostics, and refine ownership or types. Error messages commonly include the offending span, the reason, and a suggested fix. Treat diagnostics as a conversation about program design.
- Retained source example: The compiler protects moved values
fn main() {
let name = String::from("Ferris");
let owner = name;
// println!("{name}"); // error: name was moved into owner
println!("{owner}");
}
Expected output: Ferris
String owns heap memory, so assigning it to owner moves ownership. The original binding cannot be used afterward.
- Why Rust and How to Think in Rust: practices and mistakes (review, 5 min) — Retained guidance from the legacy PTesting lesson.
- Practice: Compile frequently while learning so diagnostics stay small and useful.
- Practice: Prefer simple ownership first; introduce references, lifetimes, or smart pointers only when needed.
- Practice: Read examples from the standard library and official book alongside your own experiments.
- Avoid: Assuming Rust is just C++ with a stricter compiler.
- Avoid: Trying to silence diagnostics before understanding the ownership model they reveal.
- Avoid: Using clone as a reflex instead of deciding where ownership should live.
- Why Rust and How to Think in Rust: references (review, 2 min) — Original references retained from the legacy library.
- The Rust Programming Language: https://doc.rust-lang.org/book/
- Rust by Example: https://doc.rust-lang.org/rust-by-example/
- Rust standard library: https://doc.rust-lang.org/std/
- The Cargo Workflow: Project structure (concept, 45 min) — Cargo is Rust's package manager, build tool, test runner, and dependency resolver. A typical package has a Cargo.toml manifest, a src directory, and optionally examples, tests, benches, and workspace members.
- Retained source example: Minimal Cargo.toml
[package]
name = "inventory-api"
version = "0.1.0"
edition = "2021"
[dependencies]
serde = { version = "1", features = ["derive"] }
The package table identifies the crate. Dependencies can enable feature flags, such as serde's derive macros.
- Retained source example: Common commands
cargo new hello-rust
cargo check
cargo fmt
cargo clippy -- -D warnings
cargo test
cargo doc --open
cargo check is usually the fastest feedback loop because it skips final code generation.
- The Cargo Workflow: Dependencies, lockfiles, and features (walkthrough, 45 min) — Libraries usually commit Cargo.toml and may omit Cargo.lock, while applications commonly commit both to keep builds reproducible. Features are additive flags that let crates expose optional code such as TLS backends, derive macros, or runtime integrations.
- Use cargo tree to inspect dependency graphs before adding large crates.
- Run cargo update intentionally; it can change resolved transitive versions.
- Retained source example: Feature-gated dependency
[dependencies]
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
Choosing rustls-tls avoids depending on the platform OpenSSL installation.
- The Cargo Workflow: practices and mistakes (review, 5 min) — Retained guidance from the legacy PTesting lesson.
- Practice: Use cargo check during development and cargo test before pushing changes.
- Practice: Run cargo fmt and cargo clippy in continuous integration.
- Practice: Review dependency features and default features when adding production dependencies.
- Avoid: Adding dependencies before checking whether the standard library is enough.
- Avoid: Ignoring feature flags and accidentally pulling in unnecessary TLS, runtime, or native dependencies.
- Avoid: Treating cargo build success as a substitute for tests and lints.
- The Cargo Workflow: references (review, 2 min) — Original references retained from the legacy library.
- Cargo book: https://doc.rust-lang.org/cargo/
- Clippy: https://doc.rust-lang.org/clippy/
- crates.io: https://crates.io/
- Syntax Foundations: Expressions and bindings (concept, 45 min) — Rust is expression-oriented: blocks, if expressions, match arms, and loop breaks can produce values. Bindings are immutable by default, and shadowing lets you transform a value while keeping names focused.
- Retained source example: Blocks return values
fn main() {
let raw = "42";
let answer: i32 = {
let parsed = raw.parse::<i32>().expect("valid number");
parsed + 1
};
println!("{answer}");
}
Expected output: 43
The final expression in a block has no semicolon and becomes the block's value.
- Syntax Foundations: Loops and iterators (walkthrough, 45 min) — for loops work over anything that implements IntoIterator. Iterator adapters such as map, filter, and collect are idiomatic for transformations, while explicit loops are clear for stateful logic.
- Retained source example: Iterator pipeline
fn main() {
let scores = [10, 20, 30, 40];
let doubled: Vec<i32> = scores
.iter()
.filter(|score| **score >= 20)
.map(|score| score * 2)
.collect();
println!("{doubled:?}");
}
Expected output: [40, 60, 80]
iter borrows each item, filter keeps matching references, and map produces values collected into Vec.
- Syntax Foundations: practices and mistakes (review, 5 min) — Retained guidance from the legacy PTesting lesson.
- Practice: Use explicit type annotations where they clarify intent or resolve inference ambiguity.
- Practice: Prefer iterator chains for simple transformations and loops for multi-step stateful logic.
- Practice: Keep match arms small; move complex behavior into named functions.
- Avoid: Adding a semicolon to the intended return expression.
- Avoid: Using unwrap in examples and forgetting to replace it in production paths.
- Avoid: Fighting the type checker instead of adding one clear annotation.
- Syntax Foundations: references (review, 2 min) — Original references retained from the legacy library.
- Rust book: common programming concepts: https://doc.rust-lang.org/book/ch03-00-common-programming-concepts.html
- Iterator trait: https://doc.rust-lang.org/std/iter/trait.Iterator.html
Code example
rust in legacy/rust-systems/rust-language-and-cargo-foundations.txt.
fn main() {}
Walkthrough examples
- Rust Language and Cargo Foundations in a job orchestration service — A team is extending an Axum service with a companion CLI and needs this lesson's pattern to be clear enough for review, testing, and future maintenance.
- File: legacy/rust-systems/rust-language-and-cargo-foundations.txt
- File: tests/rust-language-and-cargo-foundations.spec
- File: docs/rust-systems/rust-language-and-cargo-foundations.md
- Start from the provided rust snippet and make the intent visible in names and boundaries.
- Apply the checklist item "Explain the language or runtime rule in your own words" before adding extra behavior.
- Write down how the implementation changes when The Rust value proposition fails or becomes slow.
- A tiny Rust program — The main function is the program entry point. The println! macro expands at compile time and supports captured formatting variables.
- Retained source code:
fn main() {
let language = "Rust";
println!("Hello, {language}!");
}
- Expected output: Hello, Rust!
- Compare the example with the canonical PTLearn implementation.
- The compiler protects moved values — String owns heap memory, so assigning it to owner moves ownership. The original binding cannot be used afterward.
- Retained source code:
fn main() {
let name = String::from("Ferris");
let owner = name;
// println!("{name}"); // error: name was moved into owner
println!("{owner}");
}
- Expected output: Ferris
- Compare the example with the canonical PTLearn implementation.
- Immutable by default — Bindings are immutable unless marked mut, which makes mutation visible at the declaration.
- Retained source code:
fn main() {
let attempts = 3;
let mut remaining = attempts;
remaining -= 1;
println!("{remaining} attempts remain");
}
- Expected output: 2 attempts remain
- Compare the example with the canonical PTLearn implementation.
- Minimal Cargo.toml — The package table identifies the crate. Dependencies can enable feature flags, such as serde's derive macros.
- Retained source code:
[package]
name = "inventory-api"
version = "0.1.0"
edition = "2021"
[dependencies]
serde = { version = "1", features = ["derive"] }
- Explain the expected behavior.
- Compare the example with the canonical PTLearn implementation.
- Common commands — cargo check is usually the fastest feedback loop because it skips final code generation.
- Retained source code:
cargo new hello-rust
cargo check
cargo fmt
cargo clippy -- -D warnings
cargo test
cargo doc --open
- Explain the expected behavior.
- Compare the example with the canonical PTLearn implementation.
- Feature-gated dependency — Choosing rustls-tls avoids depending on the platform OpenSSL installation.
- Retained source code:
[dependencies]
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
- Explain the expected behavior.
- Compare the example with the canonical PTLearn implementation.
- Library plus binary shape — A package can expose a library crate and one or more binary targets.
- Retained source code:
// src/lib.rs
pub fn greeting(name: &str) -> String {
format!("Hello, {name}")
}
// src/main.rs
fn main() {
println!("{}", inventory_api::greeting("Rust"));
}
- Expected output: Hello, Rust
- Compare the example with the canonical PTLearn implementation.
- Blocks return values — The final expression in a block has no semicolon and becomes the block's value.
- Retained source code:
fn main() {
let raw = "42";
let answer: i32 = {
let parsed = raw.parse::<i32>().expect("valid number");
parsed + 1
};
println!("{answer}");
}
- Expected output: 43
- Compare the example with the canonical PTLearn implementation.
- Iterator pipeline — iter borrows each item, filter keeps matching references, and map produces values collected into Vec.
- Retained source code:
fn main() {
let scores = [10, 20, 30, 40];
let doubled: Vec<i32> = scores
.iter()
.filter(|score| **score >= 20)
.map(|score| score * 2)
.collect();
println!("{doubled:?}");
}
- Expected output: [40, 60, 80]
- Compare the example with the canonical PTLearn implementation.
- match is exhaustive — Rust requires every possible input to be handled or covered by a wildcard pattern.
- Retained source code:
fn describe(status: u16) -> &'static str {
match status {
200..=299 => "success",
400..=499 => "client error",
500..=599 => "server error",
_ => "other",
}
}
- Explain the expected behavior.
- Compare the example with the canonical PTLearn implementation.
Practice
- Match Rust's core promises: Write three short bullets describing what Rust means by memory safety, zero-cost abstractions, and fearless concurrency. The guided runner checks that the required terms are present; it does not compile or execute user code.
- Starter code: memory safety:
zero-cost abstractions:
fearless concurrency:
- Hint: Mention compile-time checks for memory safety.
- Hint: Mention abstractions that should not require extra runtime overhead.
- Hint: Mention data race prevention for concurrency.
- Reference solution: memory safety: ownership and borrowing prevent dangling references and many use-after-free bugs at compile time.
zero-cost abstractions: iterators, generics, and traits are designed to optimize away like hand-written code.
fearless concurrency: Send, Sync, and ownership rules prevent many data races in safe Rust.
- Accepted answers: memory safety | zero-cost | concurrency
- Choose the right Cargo command: For each task, write the Cargo command: fast type checking, formatting, linting, running tests, and generating docs. The guided runner checks command names only.
- Starter code: check:
format:
lint:
test:
docs:
- Hint: Use cargo fmt for formatting.
- Hint: Clippy is the standard lint tool.
- Hint: Documentation is generated by cargo doc.
- Reference solution: check: cargo check
format: cargo fmt
lint: cargo clippy
test: cargo test
docs: cargo doc
- Accepted answers: cargo check | cargo fmt | cargo clippy | cargo test | cargo doc
- Predict iterator output: Given values [1, 2, 3, 4], map each value to value * value and keep only even results. Write the final vector. The guided runner checks a deterministic text answer.
- Starter code: final vector:
- Expected output: [4, 16]
- Hint: Squares are 1, 4, 9, and 16.
- Hint: Only 4 and 16 are even.
- Reference solution: final vector: [4, 16]
- Accepted answers: [4, 16]
Checklist
- Explain the language or runtime rule in your own words
- Run one focused example and record its output
- Name one failure mode or tradeoff
- Keep the verification evidence with the lesson
Quiz prompts
- A teammate wants to hide Rust Orientation inside a convenient helper. What should you check first? — Place Rust Orientation at the boundary that keeps job orchestration service behavior explicit, testable, and reviewable.
- Which artifact best proves this Rust Systems lesson is ready for review? — Production-ready learning needs evidence: a test, trace, command, screenshot, or log that catches the risk again.
- What does Rust usually do instead of relying on a garbage collector? — Rust tracks ownership statically and drops values deterministically when their owners go out of scope.
- Why do applications usually commit Cargo.lock? — Cargo.lock records exact resolved versions so application builds are repeatable.
- What does a semicolon do to the final expression of a Rust block? — A trailing semicolon suppresses the expression value and yields ().
Flashcards
- In Rust Systems, what should you remember about Rust Orientation? Rust Orientation matters here because it supports "Describe Rust's goals: safety, performance, concurrency, and maintainability".
- In Rust Systems, what should you remember about The Rust value proposition? The Rust value proposition matters here because it supports "Recognize compile-time guarantees that replace runtime checks or garbage collection".
- In Rust Systems, what should you remember about Compiler feedback as a workflow? Compiler feedback as a workflow matters here because it supports "Read compiler diagnostics as design feedback rather than as mere errors".
- In Rust Systems, what should you remember about Rust for Reliable Systems and Services foundations? Rust for Reliable Systems and Services foundations matters here because it supports "Create binary and library packages with Cargo".
Labs
- Ship a rust language and cargo foundations slice — Extend an Axum service with a companion CLI with a small but reviewable feature that proves the lesson's architecture in code.
- Match Rust's core promises: Write three short bullets describing what Rust means by memory safety, zero-cost abstractions, and fearless concurrency. The guided runner checks that the required terms are present; it does not compile or execute user code.
- Starter code: memory safety:
zero-cost abstractions:
fearless concurrency:
- Hint: Mention compile-time checks for memory safety.
- Hint: Mention abstractions that should not require extra runtime overhead.
- Hint: Mention data race prevention for concurrency.
- Reference solution: memory safety: ownership and borrowing prevent dangling references and many use-after-free bugs at compile time.
zero-cost abstractions: iterators, generics, and traits are designed to optimize away like hand-written code.
fearless concurrency: Send, Sync, and ownership rules prevent many data races in safe Rust.
- The implementation demonstrates Rust Orientation without hidden global state.
- At least one test or verification step covers the main success path.
- The review notes explain the tradeoff behind The Rust value proposition.
Challenge
- Review-ready rust language and cargo foundations (Core) — Turn the lesson work into a pull-request-sized change for job orchestration service. Include the code, verification notes, one explicit tradeoff, and an updated concept diagram that names the riskiest handoff.
- All checklist items are either implemented or documented with a reason.
- The change can be understood from legacy/rust-systems/rust-language-and-cargo-foundations.txt plus one short note.
- The concept diagram names ownership, failure handling, and verification points.
- A teammate could run the verification steps without asking for hidden context.
Canonical lesson URL