Lab Journal: Stable vs. Nightly, the Next-Gen Trait Solver, and a Full Git/GitHub Loop

Rustup gives you stable and nightly side by side — here's what the next-gen trait solver rewrite actually means, and a full rehearsal of the cargo-to-GitHub workflow, gh CLI install included, on Debian.

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

  1. Default to stable. Only reach for nightly when testing something explicitly experimental, or when a crate requires it.
  2. Start a project: cargo new my_project — generates Cargo.toml and a src/main.rs with a working “Hello, world!”
  3. Write code, add dependencies with cargo add crate_name.
  4. Build and run: cargo run compiles and executes in one step; cargo build alone just compiles.
  5. Nightly variant: prefix any command with +nightly — e.g. cargo +nightly run.
  6. Iterate: cargo check is 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 cargogitgh loop, done once deliberately end to end, is a much better way to internalize the workflow than reading about each piece in isolation.
  • Cargo.lock handling is a small but real convention worth knowing before it becomes a habit done wrong.

Repo for reference: github.com/ny2honolulu/rust_test