Rust has two toolchains living side by side on my machine now — stable and nightly — and I wanted to actually understand what that means in practice rather than just typing rustup toolchain install nightly and hoping for the best. That curiosity led down two paths: what’s actually changing under the hood in the compiler right now (the trait solver rewrite), and a full practical rehearsal of the everyday Rust workflow, from cargo new all the way through pushing a real commit history to GitHub.
What the next-gen trait solver actually is
The trait solver is the part of the compiler responsible for figuring out which trait implementation applies when you call a trait method — proving where-clauses, normalizing associated types, resolving generic bounds. It’s been under a ground-up rewrite for nearly four years, and it’s now enabled by default on nightly so the Rust team can surface any remaining issues before stabilizing it in the next few months. It’s being described as the largest single change to the compiler since its initial release.
Practically speaking, this is mostly an invisible internal swap for day-to-day use. It unblocks future language features (Type Alias Impl Trait, Return Type Notation) and lets the team fix known soundness bugs in the old solver. Unless you’re hitting a specific edge case, the main thing you’d notice is compile error wording changing slightly. If you want to try it directly once you’re confirmed on nightly:
bash
cargo build -Zunstable-options
RUSTFLAGS="-Znext-solver" cargo build
Confirming which toolchain is active
A few reliable checks, in order of how much detail they give you:
bash
rustc --version # ends in "-nightly" if nightly is active
rustup show # lists installed toolchains, marks the active default
rustup show active-toolchain # accounts for any rust-toolchain.toml override in the current dir
Installing nightly with rustup toolchain install nightly doesn’t touch your shell config, .bashrc, or any existing aliases — it just adds the toolchain as an option. Your default stays whatever it was unless you explicitly run rustup default nightly. To use nightly for a single command without changing anything globally:
bash
rustc +nightly --version
cargo +nightly run
The general workflow, stable or nightly
- Default to stable. Only reach for nightly when testing something explicitly experimental, or when a crate requires it.
- Start a project:
cargo new my_project— generatesCargo.tomland asrc/main.rswith a working “Hello, world!” - Write code, add dependencies with
cargo add crate_name. - Build and run:
cargo runcompiles and executes in one step;cargo buildalone just compiles. - Nightly variant: prefix any command with
+nightly— e.g.cargo +nightly run. - Iterate:
cargo checkis a fast compile-only sanity check while you’re actively editing.
Putting it into practice: a full test loop
To actually rehearse this rather than just read about it, I ran the whole loop end to end:
bash
cargo new rust_test
cd rust_test
cargo run # → Hello, world!
git init # (cargo new already runs this)
git add -A && git commit -m "initial commit"
Clean build, clean run, first commit in place. From there the goal was to get it onto GitHub as a real, browsable repo — which meant installing the GitHub CLI (gh) from scratch on Debian, since it isn’t in the default apt repos:
bash
sudo mkdir -p -m 755 /etc/apt/keyrings && \
wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null && \
sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg && \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \
sudo apt-get update && \
sudo apt-get install -y gh
Authentication (gh auth login) needed to run in a real interactive terminal rather than piped through an agent, since it walks through a menu (GitHub.com → HTTPS → browser login) and a one-time device code you paste into github.com/login/device. Once authenticated as ny2honolulu, the rest was one command away: create the repo, add it as a remote, and push — landing at github.com/ny2honolulu/rust_test.
From there I rounded the repo out properly: a README, an MIT LICENSE, and a .gitignore check (cargo new already ignores /target by default, so nothing needed there). I also ran into a good real-world lesson about Cargo.lock: for binary crates (applications, as opposed to libraries), the Rust convention is to commit Cargo.lock, not ignore it — it pins the exact dependency versions that were tested, which matters for reproducible builds. I tried ignoring it, learned the convention, and reverted — untracking it and then re-tracking it, each step committed and pushed, so the repo’s history honestly reflects the back-and-forth rather than hiding it.
Takeaways
- Stable and nightly coexist cleanly via
rustup— nothing about installing nightly puts your everyday stable workflow at risk. - The trait solver rewrite is a good example of compiler work that’s enormous in scope but nearly invisible in daily use — worth knowing about, not worth worrying about.
- The full
cargo→git→ghloop, done once deliberately end to end, is a much better way to internalize the workflow than reading about each piece in isolation. Cargo.lockhandling is a small but real convention worth knowing before it becomes a habit done wrong.
Repo for reference: github.com/ny2honolulu/rust_test