Rust Patterns
Local toolchain ground truth (verified 2026-08-26): cargo/rustc 1.97.1 installed locally; upstream stable is 1.98.0 (released 2026-08-20) — re-check both before relying on either number.
Implementation recipes, configuration examples, and production-ready patterns for new Rust projects. For always-on style and test rules, use rust.instructions.md and rust-tests.instructions.md; this skill is the deeper recipe library.
Use When
| Trigger | Output |
|---|---|
| User asks to create, review, or refactor Rust 2024 service, library, CLI, or workspace code | Edition-aware Rust implementation using this skill's runtime, error, config, and testing patterns |
| User needs Cargo workspace, toolchain, lint, or release-profile setup | Cargo.toml baselines, dependency guidance, and quality-gate commands |
User needs async, serde, gRPC, HTTP, tracing, or Azure-hosted Rust patterns |
Focused recipe selection plus version-aware implementation guidance |
Do not use this skill when:
- The task is for another language or a non-Rust build toolchain.
- The work is primarily high-level cloud architecture rather than Rust code, crates, or Cargo structure.
Operating Rules
- Treat all examples as Rust 2024-first unless the user explicitly asks for older edition compatibility.
- Verify crate APIs and versions before generating code. Prefer
context7for crate documentation andmicrosoft.learn.mcpfor Azure SDK for Rust guidance. - Do not assume fast-moving crate APIs are stable across versions. This especially applies to OpenTelemetry, tonic/prost, Azure SDK for Rust, tower, axum, hyper, and rustls.
- Prefer the standard library and native Rust capabilities before adding dependencies. Add third-party crates only when they materially reduce risk or complexity.
- Generate code that can pass formatting, linting, tests, and documentation checks. Include validation commands with substantial changes.
- Never hide risky defaults. Call out panic behavior, blocking operations, unbounded queues, secret handling, retry/idempotency assumptions, and MSRV implications.
Default New-Project Baseline
Use this baseline for greenfield projects unless the user provides stronger constraints:
- Edition:
2024. - Minimum supported Rust version: at least
1.90(conservative ecosystem floor; Rust 2024 edition requires at minimum 1.85, and Cargo itself recommends choosing an explicit MSRV policy rather than a universal number — common community practice lands around stable-minus-3 to stable-minus-6). - Toolchain: use current stable unless reproducibility requires an exact pinned release.
- Cargo resolver: for virtual workspaces, set
resolver = "3"explicitly. - Async runtime:
tokiowith minimal features, notfeatures = ["full"]by default. - Errors:
thiserrorfor libraries and domain modules;anyhowonly at binary/CLI application boundaries. - Serialization/config:
serdewith explicit defaults and redacted secrets. - Observability:
tracingfirst; add OpenTelemetry only when export is required. - Quality gates:
fmt,clippy,test, anddocare mandatory recommendations.
[package]
name = "service-name"
version = "0.1.0"
edition = "2024"
rust-version = "1.90"
license = "MIT OR Apache-2.0"
publish = false
[dependencies]
tokio = { version = "1", features = ["rt-multi-thread", "macros", "signal", "sync", "time"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
thiserror = "2"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt", "json"] }
[lints.rust]
warnings = "deny"
unsafe_code = "forbid"
[lints.clippy]
unwrap_used = "warn"
expect_used = "warn"
panic = "warn"
print_stdout = "warn"
uninlined_format_args = "warn"
missing_errors_doc = "warn"For deployable binary crates only, consider a release profile. Do not blindly apply this to reusable library crates:
[profile.release]
strip = "symbols"
lto = "thin"
codegen-units = 1
panic = "abort"Use panic = "abort" only when the application does not need unwinding, panic hooks, or recovery semantics.
Workspace Baseline
For greenfield multi-crate repositories, prefer a virtual workspace and shared workspace package metadata:
[workspace]
resolver = "3"
members = ["crates/*"]
[workspace.package]
edition = "2024"
rust-version = "1.90"
license = "MIT OR Apache-2.0"
publish = false
[workspace.dependencies]
tokio = { version = "1", features = ["rt-multi-thread", "macros", "signal", "sync", "time"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
thiserror = "2"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt", "json"] }
[workspace.lints.rust]
warnings = "deny"
unsafe_code = "forbid"
[workspace.lints.clippy]
unwrap_used = "warn"
expect_used = "warn"
panic = "warn"
print_stdout = "warn"
uninlined_format_args = "warn"
missing_errors_doc = "warn"Member crates opt in to shared metadata, dependencies, and lints:
[package]
name = "my-core"
version = "0.1.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
publish.workspace = true
[dependencies]
serde.workspace = true
thiserror.workspace = true
tracing.workspace = true
[lints]
workspace = trueRecipe Index
Load the smallest recipe file that matches the task. Recipes are composable but not all standalone: unless a recipe says otherwise, it assumes the project already defines the domain error type ServiceError and the crate-level Result<T> alias from recipes/errors.md (and AppConfig from recipes/serde-config.md where shown). Stand-in names such as UserService, Event, or Item are placeholders for your own domain types.
Typical composition order for a new service: cargo-workspace.md → errors.md → serde-config.md → tracing-opentelemetry.md → the transport recipe (http-axum.md or grpc-tonic.md) → async-runtime.md shutdown wiring.
recipes/cargo-workspace.md- new project setup, workspaces, toolchains, lint policy, release profiles.recipes/errors.md-thiserror, application-boundaryanyhow, error documentation, non-exhaustive public errors.recipes/async-runtime.md- Tokio runtime features, cancellation, graceful shutdown, bounded channels, timeouts, retries.recipes/async-traits.md- native async traits, object safety,async-trait, explicit future return types.recipes/serde-config.md- serde defaults, camelCase APIs, config loading, secret redaction.recipes/tracing-opentelemetry.md- structured tracing, JSON logs, OTLP setup, trace propagation, provider shutdown.recipes/grpc-tonic.md- current tonic/prost code generation withtonic-prost-build, server/client shape, interceptors.recipes/http-axum.md- HTTP service APIs, health/readiness, error mapping, timeouts, request tracing.recipes/testing-quality-gates.md- unit/integration tests, test helpers, CI gates, documentation checks.recipes/api-design.md- Rust API Guidelines-inspired public API patterns for libraries.recipes/security-supply-chain.md- dependency hygiene, cargo-audit/deny/vet, secrets, unsafe policy.recipes/azure-service-patterns.md- Azure-hosted Rust service shape, configuration, identity, telemetry, container readiness.
Mandatory Validation Commands
For any non-trivial code generation or refactor, recommend running:
cargo fmt --all --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace --all-features
cargo doc --workspace --all-features --no-depsWhen supply-chain tooling is present, also recommend:
cargo audit
cargo deny checkrecipes/security-supply-chain.md additionally recommends cargo tree -d and cargo outdated.
Cargo 1.97+ note: for build-cache-preserving warning enforcement you can use Cargo's native control (CARGO_BUILD_WARNINGS=deny or [build] warnings = "deny" in .cargo/config.toml) instead of RUSTFLAGS=-Dwarnings; keep the clippy -D warnings flag for lint-gating.
If the project uses a pinned toolchain, run the same commands through that toolchain.
Do / Avoid
Do:
- Keep dependencies minimal and feature-gated.
- Use bounded queues, explicit timeouts, and cancellation-aware tasks.
- Preserve caller control in library APIs.
- Use typed configuration and typed domain identifiers instead of loose strings or booleans.
- Document errors, panics, and safety invariants.
- Redact secrets from logs and
Debugoutput.
Avoid:
tokio = { features = ["full"] }unless the code needs most Tokio features.unwrap,expect,panic!,todo!, andunimplemented!in production paths.- Runtime mutation of process environment variables. In Rust 2024, some environment mutation APIs are unsafe; load configuration at startup instead.
- Unbounded channels for normal service traffic.
- Global mutable state unless there is a clear initialization and shutdown model.
- OpenTelemetry examples that do not flush/shut down providers.
Quality Gate
Do not mark work complete until:
-
cargo fmt,cargo clippy,cargo test, andcargo docpass, or exact commands are provided for the target workspace. - New production paths avoid
unwrap,expect,todo!, unbounded queues, and hidden blocking calls unless explicitly justified. - Runtime, tracing, config, and shutdown behaviour match the verified crate versions and enabled features in use.
- Secrets are redacted from logs and config examples, and no unsafe production shortcuts were introduced.
- Crate names, feature flags, macro paths, and trait methods were verified against installed metadata or official crate documentation.
Anti-Hallucination Rule
Before writing Rust code that references crate APIs, macro paths, or trait methods, verify the exact symbol name and signature against the crate's documentation or cargo doc output.
Forbidden shortcuts (restating Operating Rules 2–3 where they bite hardest):
- Do not assume
tokio::spawnorasync fnsignatures from memory; signatures vary between tokio versions. - Do not guess crate feature flag names; verify in the crate's Cargo.toml documentation.
Asymmetry traps:
std::sync::Mutexvstokio::sync::Mutex- different APIs designed for different contexts.reqwestv0.11 vs v0.12 have differentClient::requestandResponseAPIs.
Safe degraded output:
- Use
// [VERIFY] check docs.rs/<crate>/<version> for exact signaturewhen unverifiable.