Initial commit
This commit is contained in:
414
commands/rust-async-traits.md
Normal file
414
commands/rust-async-traits.md
Normal file
@@ -0,0 +1,414 @@
|
||||
---
|
||||
description: Modernize async trait usage to native async fn in traits
|
||||
---
|
||||
|
||||
You are helping modernize async trait definitions to use native async fn in traits instead of the async-trait crate.
|
||||
|
||||
## Your Task
|
||||
|
||||
Convert traits using the `async-trait` crate to native async fn in traits, which has been supported since Rust 1.75.
|
||||
|
||||
## Background
|
||||
|
||||
**Since Rust 1.75 (December 2023):** Async functions in traits are natively supported without requiring the `async-trait` crate.
|
||||
|
||||
**When to use async-trait:**
|
||||
- Supporting Rust versions < 1.75
|
||||
- Need for `dyn Trait` (dynamic dispatch/object safety)
|
||||
- Specific edge cases with complex bounds
|
||||
|
||||
**When to use native async fn:**
|
||||
- Rust 1.75 or later ✅
|
||||
- Static dispatch (generics)
|
||||
- Modern codebases
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Check Current Usage**
|
||||
|
||||
Scan for async-trait usage:
|
||||
```rust
|
||||
use async_trait::async_trait;
|
||||
|
||||
#[async_trait]
|
||||
trait MyTrait {
|
||||
async fn method(&self) -> Result<T, E>;
|
||||
}
|
||||
```
|
||||
|
||||
2. **Verify Rust Version**
|
||||
|
||||
Check Cargo.toml:
|
||||
```toml
|
||||
[package]
|
||||
rust-version = "1.75" # Or higher
|
||||
```
|
||||
|
||||
If rust-version < 1.75, ask user if they can upgrade.
|
||||
|
||||
3. **Identify Use Cases**
|
||||
|
||||
Categorize each async trait:
|
||||
|
||||
**Can Remove async-trait (most common):**
|
||||
- Trait used with generics/static dispatch
|
||||
- No `Box<dyn Trait>` usage
|
||||
- Rust 1.75+
|
||||
|
||||
**Must Keep async-trait:**
|
||||
- Using `dyn Trait` for dynamic dispatch
|
||||
- Supporting older Rust versions
|
||||
- Object safety required
|
||||
|
||||
4. **Convert to Native Async Fn**
|
||||
|
||||
**Before:**
|
||||
```rust
|
||||
use async_trait::async_trait;
|
||||
|
||||
#[async_trait]
|
||||
pub trait UserRepository: Send + Sync {
|
||||
async fn find_user(&self, id: &str) -> Result<User, Error>;
|
||||
async fn save_user(&self, user: &User) -> Result<(), Error>;
|
||||
async fn delete_user(&self, id: &str) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl UserRepository for PostgresRepository {
|
||||
async fn find_user(&self, id: &str) -> Result<User, Error> {
|
||||
sqlx::query_as!(User, "SELECT * FROM users WHERE id = $1", id)
|
||||
.fetch_one(&self.pool)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn save_user(&self, user: &User) -> Result<(), Error> {
|
||||
sqlx::query!(
|
||||
"INSERT INTO users (id, email) VALUES ($1, $2)",
|
||||
user.id,
|
||||
user.email
|
||||
)
|
||||
.execute(&self.pool)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn delete_user(&self, id: &str) -> Result<(), Error> {
|
||||
sqlx::query!("DELETE FROM users WHERE id = $1", id)
|
||||
.execute(&self.pool)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```rust
|
||||
// No async_trait import needed!
|
||||
|
||||
pub trait UserRepository: Send + Sync {
|
||||
async fn find_user(&self, id: &str) -> Result<User, Error>;
|
||||
async fn save_user(&self, user: &User) -> Result<(), Error>;
|
||||
async fn delete_user(&self, id: &str) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
impl UserRepository for PostgresRepository {
|
||||
async fn find_user(&self, id: &str) -> Result<User, Error> {
|
||||
sqlx::query_as!(User, "SELECT * FROM users WHERE id = $1", id)
|
||||
.fetch_one(&self.pool)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn save_user(&self, user: &User) -> Result<(), Error> {
|
||||
sqlx::query!(
|
||||
"INSERT INTO users (id, email) VALUES ($1, $2)",
|
||||
user.id,
|
||||
user.email
|
||||
)
|
||||
.execute(&self.pool)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn delete_user(&self, id: &str) -> Result<(), Error> {
|
||||
sqlx::query!("DELETE FROM users WHERE id = $1", id)
|
||||
.execute(&self.pool)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
5. **Handle Dynamic Dispatch Cases**
|
||||
|
||||
If you need `dyn Trait`, keep async-trait:
|
||||
|
||||
```rust
|
||||
// When you need this:
|
||||
let repo: Box<dyn UserRepository> = Box::new(PostgresRepository::new(pool));
|
||||
|
||||
// You MUST use async-trait for object safety:
|
||||
use async_trait::async_trait;
|
||||
|
||||
#[async_trait]
|
||||
pub trait UserRepository: Send + Sync {
|
||||
async fn find_user(&self, id: &str) -> Result<User, Error>;
|
||||
}
|
||||
```
|
||||
|
||||
Or redesign to avoid dynamic dispatch:
|
||||
|
||||
```rust
|
||||
// Alternative: Use generics instead
|
||||
pub async fn process_users<R: UserRepository>(repo: R) {
|
||||
// Works with any UserRepository implementation
|
||||
let user = repo.find_user("123").await.unwrap();
|
||||
}
|
||||
```
|
||||
|
||||
6. **Remove async-trait Dependency**
|
||||
|
||||
Update Cargo.toml:
|
||||
|
||||
**Before:**
|
||||
```toml
|
||||
[dependencies]
|
||||
async-trait = "0.1"
|
||||
```
|
||||
|
||||
**After:**
|
||||
```toml
|
||||
[dependencies]
|
||||
# async-trait removed - using native async fn in traits
|
||||
```
|
||||
|
||||
If still needed for some traits:
|
||||
```toml
|
||||
[dependencies]
|
||||
# Only needed for dyn Trait support
|
||||
async-trait = "0.1" # Optional, only for object-safe traits
|
||||
```
|
||||
|
||||
7. **Update Imports**
|
||||
|
||||
Remove unused async-trait imports:
|
||||
|
||||
```rust
|
||||
// Remove this if no longer needed
|
||||
use async_trait::async_trait;
|
||||
```
|
||||
|
||||
8. **Run Tests**
|
||||
|
||||
Verify everything compiles and works:
|
||||
|
||||
```bash
|
||||
cargo check
|
||||
cargo test
|
||||
cargo clippy
|
||||
```
|
||||
|
||||
9. **Provide Summary**
|
||||
|
||||
```
|
||||
✅ Modernized async trait usage!
|
||||
|
||||
## Changes Made:
|
||||
|
||||
### Converted to Native Async Fn (3 traits):
|
||||
- UserRepository (src/domain/user.rs)
|
||||
- OrderRepository (src/domain/order.rs)
|
||||
- PaymentGateway (src/ports/payment.rs)
|
||||
|
||||
### Kept async-trait (1 trait):
|
||||
- DynamicHandler (src/handlers/mod.rs)
|
||||
Reason: Uses Box<dyn Trait> for plugin system
|
||||
|
||||
## Dependency Updates:
|
||||
- Removed async-trait from main dependencies
|
||||
- Added as optional for dynamic dispatch cases
|
||||
|
||||
## Benefits:
|
||||
- ✅ Zero-cost abstraction (no boxing overhead)
|
||||
- ✅ Simpler code (no macro needed)
|
||||
- ✅ Better error messages
|
||||
- ✅ Native language feature
|
||||
|
||||
## Before/After Example:
|
||||
|
||||
Before:
|
||||
```rust
|
||||
use async_trait::async_trait;
|
||||
|
||||
#[async_trait]
|
||||
trait Repository {
|
||||
async fn find(&self, id: &str) -> Result<Item, Error>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Repository for MyRepo {
|
||||
async fn find(&self, id: &str) -> Result<Item, Error> {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
```rust
|
||||
// No import needed!
|
||||
|
||||
trait Repository {
|
||||
async fn find(&self, id: &str) -> Result<Item, Error>;
|
||||
}
|
||||
|
||||
impl Repository for MyRepo {
|
||||
async fn find(&self, id: &str) -> Result<Item, Error> {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Next Steps:
|
||||
1. All tests passing ✅
|
||||
2. Consider removing async-trait entirely if unused
|
||||
3. Update documentation
|
||||
```
|
||||
|
||||
## Key Differences
|
||||
|
||||
### Native Async Fn (Rust 1.75+)
|
||||
|
||||
**Pros:**
|
||||
- No external dependency
|
||||
- Zero-cost abstraction
|
||||
- Better compiler errors
|
||||
- Simpler syntax
|
||||
- Native language feature
|
||||
|
||||
**Cons:**
|
||||
- Cannot use with `dyn Trait` directly
|
||||
- Requires Rust 1.75+
|
||||
|
||||
**Usage:**
|
||||
```rust
|
||||
trait MyTrait {
|
||||
async fn method(&self) -> Result<T, E>;
|
||||
}
|
||||
|
||||
// Use with generics
|
||||
fn process<T: MyTrait>(t: T) { }
|
||||
```
|
||||
|
||||
### Async-Trait Crate
|
||||
|
||||
**Pros:**
|
||||
- Works with older Rust
|
||||
- Supports `dyn Trait`
|
||||
- Object-safe traits
|
||||
|
||||
**Cons:**
|
||||
- External dependency
|
||||
- Macro overhead
|
||||
- Slight performance cost (boxing)
|
||||
|
||||
**Usage:**
|
||||
```rust
|
||||
use async_trait::async_trait;
|
||||
|
||||
#[async_trait]
|
||||
trait MyTrait {
|
||||
async fn method(&self) -> Result<T, E>;
|
||||
}
|
||||
|
||||
// Can use with dyn
|
||||
let t: Box<dyn MyTrait> = Box::new(impl);
|
||||
```
|
||||
|
||||
## Migration Patterns
|
||||
|
||||
### Pattern 1: Simple Repository
|
||||
|
||||
```rust
|
||||
// Before
|
||||
#[async_trait]
|
||||
trait Repository {
|
||||
async fn get(&self, id: i32) -> Option<Item>;
|
||||
}
|
||||
|
||||
// After
|
||||
trait Repository {
|
||||
async fn get(&self, id: i32) -> Option<Item>;
|
||||
}
|
||||
```
|
||||
|
||||
### Pattern 2: Generic Service
|
||||
|
||||
```rust
|
||||
// Before
|
||||
#[async_trait]
|
||||
trait Service<T> {
|
||||
async fn process(&self, item: T) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
// After
|
||||
trait Service<T> {
|
||||
async fn process(&self, item: T) -> Result<(), Error>;
|
||||
}
|
||||
```
|
||||
|
||||
### Pattern 3: Multiple Async Methods
|
||||
|
||||
```rust
|
||||
// Before
|
||||
#[async_trait]
|
||||
trait Complex {
|
||||
async fn fetch(&self) -> Result<Data, Error>;
|
||||
async fn save(&self, data: Data) -> Result<(), Error>;
|
||||
async fn delete(&self, id: i32) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
// After - just remove the macro!
|
||||
trait Complex {
|
||||
async fn fetch(&self) -> Result<Data, Error>;
|
||||
async fn save(&self, data: Data) -> Result<(), Error>;
|
||||
async fn delete(&self, id: i32) -> Result<(), Error>;
|
||||
}
|
||||
```
|
||||
|
||||
### Pattern 4: Keep for Dynamic Dispatch
|
||||
|
||||
```rust
|
||||
// When you need this:
|
||||
struct PluginSystem {
|
||||
plugins: Vec<Box<dyn Plugin>>,
|
||||
}
|
||||
|
||||
// Keep async-trait:
|
||||
#[async_trait]
|
||||
trait Plugin: Send + Sync {
|
||||
async fn execute(&self) -> Result<(), Error>;
|
||||
}
|
||||
```
|
||||
|
||||
## Important Notes
|
||||
|
||||
- Native async fn in traits requires **Rust 1.75+**
|
||||
- Check MSRV before removing async-trait
|
||||
- `dyn Trait` requires async-trait (or alternatives)
|
||||
- Static dispatch (generics) works with native async fn
|
||||
- Performance is better with native async fn (no boxing)
|
||||
|
||||
## Version Requirements
|
||||
|
||||
| Feature | Rust Version | Notes |
|
||||
|---------|-------------|-------|
|
||||
| Async fn in traits | 1.75.0+ | Native support |
|
||||
| async-trait crate | Any | Fallback for older versions |
|
||||
| Return-position impl Trait | 1.75.0+ | Enables async fn |
|
||||
|
||||
## After Completion
|
||||
|
||||
Ask the user:
|
||||
1. Did all tests pass?
|
||||
2. Can we remove async-trait entirely?
|
||||
3. Are there any dyn Trait use cases remaining?
|
||||
4. Should we update documentation?
|
||||
346
commands/rust-modernize.md
Normal file
346
commands/rust-modernize.md
Normal file
@@ -0,0 +1,346 @@
|
||||
---
|
||||
description: Analyze and modernize Rust code to use latest features and patterns
|
||||
---
|
||||
|
||||
You are helping modernize Rust code to use the latest features from Rust 2024 Edition.
|
||||
|
||||
## Your Task
|
||||
|
||||
Analyze Rust code and refactor it to use modern patterns including let chains, async closures, improved match ergonomics, and other Rust 2024 features.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Scan for Modernization Opportunities**
|
||||
|
||||
Look for these patterns that can be modernized:
|
||||
- Nested if-let statements → let chains
|
||||
- Manual async closures → native async closures
|
||||
- Old match patterns → improved match ergonomics
|
||||
- Regular functions → const functions where possible
|
||||
- Manual iterators → gen blocks
|
||||
- Complex error propagation → cleaner patterns
|
||||
|
||||
2. **Categorize Findings**
|
||||
|
||||
Group by modernization type:
|
||||
```
|
||||
Modernization Opportunities Found:
|
||||
|
||||
Let Chains (5):
|
||||
- src/user.rs:42 - Nested if-let (3 levels deep)
|
||||
- src/api.rs:15 - Multiple Option checks
|
||||
...
|
||||
|
||||
Async Closures (3):
|
||||
- src/tasks.rs:28 - Manual async wrapper
|
||||
...
|
||||
|
||||
Const Opportunities (2):
|
||||
- src/config.rs:10 - Function could be const
|
||||
...
|
||||
```
|
||||
|
||||
3. **Ask User for Scope**
|
||||
|
||||
Ask which modernizations to apply:
|
||||
- All recommended changes?
|
||||
- Specific category (let chains, async, etc.)?
|
||||
- Specific file or function?
|
||||
|
||||
4. **Refactor Pattern: Nested If-Let → Let Chains**
|
||||
|
||||
**Before:**
|
||||
```rust
|
||||
if let Some(user) = get_user(id) {
|
||||
if let Some(profile) = user.profile {
|
||||
if profile.is_active {
|
||||
if let Some(email) = profile.email {
|
||||
send_email(&email);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```rust
|
||||
if let Some(user) = get_user(id)
|
||||
&& let Some(profile) = user.profile
|
||||
&& profile.is_active
|
||||
&& let Some(email) = profile.email
|
||||
{
|
||||
send_email(&email);
|
||||
}
|
||||
```
|
||||
|
||||
5. **Refactor Pattern: Manual Async → Async Closures**
|
||||
|
||||
**Before:**
|
||||
```rust
|
||||
let futures: Vec<_> = items
|
||||
.iter()
|
||||
.map(|item| {
|
||||
let item = item.clone();
|
||||
async move {
|
||||
process_item(item).await
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
```
|
||||
|
||||
**After:**
|
||||
```rust
|
||||
let futures: Vec<_> = items
|
||||
.iter()
|
||||
.map(async |item| {
|
||||
process_item(item).await
|
||||
})
|
||||
.collect();
|
||||
```
|
||||
|
||||
6. **Refactor Pattern: Functions → Const Functions**
|
||||
|
||||
**Before:**
|
||||
```rust
|
||||
fn calculate_buffer_size(items: usize) -> usize {
|
||||
items * std::mem::size_of::<Item>()
|
||||
}
|
||||
|
||||
static BUFFER: [u8; calculate_buffer_size(100)]; // Error!
|
||||
```
|
||||
|
||||
**After:**
|
||||
```rust
|
||||
const fn calculate_buffer_size(items: usize) -> usize {
|
||||
items * std::mem::size_of::<Item>()
|
||||
}
|
||||
|
||||
const BUFFER_SIZE: usize = calculate_buffer_size(100);
|
||||
static BUFFER: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
|
||||
```
|
||||
|
||||
7. **Refactor Pattern: Manual Iterator → Gen Block**
|
||||
|
||||
**Before:**
|
||||
```rust
|
||||
struct FibIterator {
|
||||
a: u64,
|
||||
b: u64,
|
||||
}
|
||||
|
||||
impl Iterator for FibIterator {
|
||||
type Item = u64;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let current = self.a;
|
||||
self.a = self.b;
|
||||
self.b = current + self.b;
|
||||
Some(current)
|
||||
}
|
||||
}
|
||||
|
||||
fn fibonacci() -> FibIterator {
|
||||
FibIterator { a: 0, b: 1 }
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```rust
|
||||
fn fibonacci() -> impl Iterator<Item = u64> {
|
||||
gen {
|
||||
let (mut a, mut b) = (0, 1);
|
||||
loop {
|
||||
yield a;
|
||||
(a, b) = (b, a + b);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
8. **Refactor Pattern: Match Ergonomics**
|
||||
|
||||
**Before (Rust 2021):**
|
||||
```rust
|
||||
match &option {
|
||||
Some(x) => {
|
||||
// x is &T, need to clone or handle reference
|
||||
process(x.clone());
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
```
|
||||
|
||||
**After (Rust 2024):**
|
||||
```rust
|
||||
match &option {
|
||||
Some(mut x) => {
|
||||
// x is &mut T (not moved), can modify in place
|
||||
x.update();
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
```
|
||||
|
||||
9. **Check Edition and Version**
|
||||
|
||||
Ensure project supports modern features:
|
||||
|
||||
```toml
|
||||
[package]
|
||||
edition = "2024"
|
||||
rust-version = "1.85" # For full 2024 support
|
||||
```
|
||||
|
||||
If edition needs updating:
|
||||
- Ask user if they want to upgrade
|
||||
- Run `cargo fix --edition` after updating
|
||||
- Check for breaking changes
|
||||
|
||||
10. **Provide Modernization Summary**
|
||||
|
||||
```
|
||||
✅ Code modernized successfully!
|
||||
|
||||
## Changes Made:
|
||||
|
||||
### Let Chains (5 locations):
|
||||
- src/user.rs:42 - Flattened 3-level nesting
|
||||
- src/api.rs:15 - Combined Option checks
|
||||
- src/validate.rs:88 - Simplified Result handling
|
||||
|
||||
### Async Closures (3 locations):
|
||||
- src/tasks.rs:28 - Replaced manual async wrapper
|
||||
- src/jobs.rs:45 - Simplified async map
|
||||
- src/handlers.rs:102 - Cleaner async callback
|
||||
|
||||
### Const Functions (2 locations):
|
||||
- src/config.rs:10 - Made calculate_size const
|
||||
- src/utils.rs:25 - Made hash_string const
|
||||
|
||||
### Gen Blocks (1 location):
|
||||
- src/iter.rs:15 - Simplified iterator with gen block
|
||||
|
||||
## Edition Status:
|
||||
- Current: edition = "2024" ✅
|
||||
- MSRV: rust-version = "1.85" ✅
|
||||
|
||||
## Before/After Example:
|
||||
|
||||
Before:
|
||||
```rust
|
||||
if let Some(user) = get_user() {
|
||||
if let Some(email) = user.email {
|
||||
if email.contains('@') {
|
||||
send_email(&email);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
```rust
|
||||
if let Some(user) = get_user()
|
||||
&& let Some(email) = user.email
|
||||
&& email.contains('@')
|
||||
{
|
||||
send_email(&email);
|
||||
}
|
||||
```
|
||||
|
||||
## Next Steps:
|
||||
1. Run tests: `cargo test`
|
||||
2. Check for warnings: `cargo check`
|
||||
3. Review changes for correctness
|
||||
4. Consider enabling more lints for modern patterns
|
||||
|
||||
## Suggested Lints:
|
||||
Add to Cargo.toml or lib.rs:
|
||||
```rust
|
||||
#![warn(rust_2024_compatibility)]
|
||||
#![warn(let_underscore_drop)]
|
||||
```
|
||||
```
|
||||
|
||||
## Modernization Patterns
|
||||
|
||||
### Let Chains
|
||||
|
||||
Look for:
|
||||
- Multiple nested if-let
|
||||
- if-let followed by if condition
|
||||
- while-let with additional conditions
|
||||
|
||||
Convert to:
|
||||
```rust
|
||||
if let Pattern1 = expr1
|
||||
&& let Pattern2 = expr2
|
||||
&& boolean_condition
|
||||
{
|
||||
// body
|
||||
}
|
||||
```
|
||||
|
||||
### Async Closures
|
||||
|
||||
Look for:
|
||||
- `.map(|x| { let x = x.clone(); async move { ... } })`
|
||||
- Manual future wrapping
|
||||
- Complex async callback patterns
|
||||
|
||||
Convert to:
|
||||
```rust
|
||||
.map(async |x| { ... })
|
||||
```
|
||||
|
||||
### Const Functions
|
||||
|
||||
Look for:
|
||||
- Functions with only const-safe operations
|
||||
- Compile-time computations
|
||||
- Functions used in const contexts
|
||||
|
||||
Convert to:
|
||||
```rust
|
||||
const fn function_name(...) -> ReturnType {
|
||||
// const-safe operations only
|
||||
}
|
||||
```
|
||||
|
||||
### Gen Blocks
|
||||
|
||||
Look for:
|
||||
- Manual Iterator implementations
|
||||
- State machines for iteration
|
||||
- Complex iteration logic
|
||||
|
||||
Convert to:
|
||||
```rust
|
||||
gen {
|
||||
// yield values
|
||||
}
|
||||
```
|
||||
|
||||
## Important Notes
|
||||
|
||||
- Only apply changes if edition = "2024" or offer to upgrade
|
||||
- Test thoroughly after modernization
|
||||
- Some patterns require minimum Rust versions
|
||||
- Preserve behavior - modernization should not change logic
|
||||
- Document breaking changes if any
|
||||
|
||||
## Version Requirements
|
||||
|
||||
| Feature | Min Rust Version | Edition |
|
||||
|---------|-----------------|---------|
|
||||
| Let chains | 1.88.0 | 2024 |
|
||||
| Async closures | 1.85.0 | 2024 |
|
||||
| Gen blocks | 1.85.0 | 2024 |
|
||||
| Match ergonomics | 1.85.0 | 2024 |
|
||||
|
||||
## After Completion
|
||||
|
||||
Ask the user:
|
||||
1. Did all tests pass?
|
||||
2. Are there more files to modernize?
|
||||
3. Should we enable additional lints?
|
||||
4. Do you want to update documentation?
|
||||
417
commands/rust-pattern-check.md
Normal file
417
commands/rust-pattern-check.md
Normal file
@@ -0,0 +1,417 @@
|
||||
---
|
||||
description: Check code for opportunities to use modern Rust patterns
|
||||
---
|
||||
|
||||
You are analyzing Rust code to identify opportunities for using modern patterns from Rust 2024 Edition.
|
||||
|
||||
## Your Task
|
||||
|
||||
Scan the codebase for patterns that could be modernized and provide a detailed report with recommendations.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Check Edition and Version**
|
||||
|
||||
First, verify the project setup:
|
||||
|
||||
Read Cargo.toml:
|
||||
```
|
||||
Current Configuration:
|
||||
- Edition: [edition]
|
||||
- Rust version: [rust-version if set]
|
||||
- Toolchain: [rustc --version]
|
||||
```
|
||||
|
||||
If not on 2024:
|
||||
```
|
||||
ℹ️ Project is using edition [current]. Consider upgrading to 2024 Edition
|
||||
to use latest features. Use `/rust-upgrade-edition` to upgrade.
|
||||
```
|
||||
|
||||
2. **Scan for Nested If-Let Patterns**
|
||||
|
||||
Search for nested if-let that could use let chains:
|
||||
|
||||
Pattern to find:
|
||||
```rust
|
||||
if let Pattern1 = expr1 {
|
||||
if let Pattern2 = expr2 {
|
||||
// Could be flattened with let chains
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Use Grep to search for:
|
||||
- `if let` followed by another `if let` in same scope
|
||||
- Multiple levels of nesting
|
||||
|
||||
Report:
|
||||
```
|
||||
## Let Chain Opportunities (5):
|
||||
|
||||
### High Priority (deep nesting):
|
||||
- src/user.rs:42 - 4 levels of nested if-let
|
||||
Current: if let -> if let -> if let -> if let
|
||||
Suggestion: Use let chains to flatten
|
||||
|
||||
- src/api.rs:88 - 3 levels of nested if-let
|
||||
Current: Multiple Option unwrapping
|
||||
Suggestion: Combine with && in single if
|
||||
|
||||
### Medium Priority:
|
||||
- src/validate.rs:15 - 2 levels with boolean check
|
||||
- src/handler.rs:102 - if let with additional condition
|
||||
```
|
||||
|
||||
3. **Scan for Manual Async Closures**
|
||||
|
||||
Look for patterns like:
|
||||
```rust
|
||||
.map(|x| {
|
||||
let x = x.clone();
|
||||
async move { ... }
|
||||
})
|
||||
```
|
||||
|
||||
Report:
|
||||
```
|
||||
## Async Closure Opportunities (3):
|
||||
|
||||
- src/tasks.rs:28
|
||||
Current: Manual async move wrapper
|
||||
Suggestion: Use async |x| { ... } syntax
|
||||
|
||||
- src/jobs.rs:45
|
||||
Current: Clone before async move
|
||||
Suggestion: Async closure can borrow directly
|
||||
```
|
||||
|
||||
4. **Scan for Const Function Opportunities**
|
||||
|
||||
Look for functions that:
|
||||
- Contain only const-safe operations
|
||||
- Are used in const contexts
|
||||
- Could be evaluated at compile time
|
||||
|
||||
Patterns to check:
|
||||
- Pure computation functions
|
||||
- Functions with no I/O or allocations
|
||||
- Hash functions, calculations
|
||||
|
||||
Report:
|
||||
```
|
||||
## Const Function Opportunities (4):
|
||||
|
||||
- src/config.rs:10 - calculate_buffer_size
|
||||
Current: fn calculate_buffer_size(n: usize) -> usize
|
||||
Suggestion: Add const keyword for compile-time eval
|
||||
Impact: Can be used in const/static initialization
|
||||
|
||||
- src/hash.rs:25 - hash_string
|
||||
Current: Regular function
|
||||
Suggestion: Make const fn for compile-time hashing
|
||||
```
|
||||
|
||||
5. **Scan for Manual Iterator Implementations**
|
||||
|
||||
Look for:
|
||||
- struct implementing Iterator trait
|
||||
- Complex next() implementations
|
||||
- State machine patterns
|
||||
|
||||
Report:
|
||||
```
|
||||
## Gen Block Opportunities (2):
|
||||
|
||||
- src/iter.rs:15 - FibonacciIterator
|
||||
Current: 25 lines of Iterator impl
|
||||
Suggestion: Replace with 8-line gen block
|
||||
Benefit: Simpler, more maintainable
|
||||
|
||||
- src/tree.rs:48 - TreeTraversal
|
||||
Current: Complex state machine
|
||||
Suggestion: Recursive gen block
|
||||
```
|
||||
|
||||
6. **Scan for Match Pattern Improvements**
|
||||
|
||||
Look for:
|
||||
- Match on references with moves
|
||||
- Unclear binding modes
|
||||
- Patterns that would benefit from 2024 ergonomics
|
||||
|
||||
Report:
|
||||
```
|
||||
## Match Ergonomics Opportunities (3):
|
||||
|
||||
- src/process.rs:65
|
||||
Current: Match with clone to avoid move
|
||||
Suggestion: Use 2024 ergonomics for in-place modify
|
||||
|
||||
- src/validate.rs:42
|
||||
Current: Explicit ref patterns
|
||||
Suggestion: Can be simplified with 2024 ergonomics
|
||||
```
|
||||
|
||||
7. **Scan for While-Let Chains**
|
||||
|
||||
Look for while-let with additional conditions:
|
||||
|
||||
Pattern:
|
||||
```rust
|
||||
while let Some(item) = iterator.next() {
|
||||
if condition {
|
||||
// Could use while let with &&
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Report:
|
||||
```
|
||||
## While-Let Chain Opportunities (2):
|
||||
|
||||
- src/parser.rs:35
|
||||
Current: while let with nested if
|
||||
Suggestion: Combine with && condition
|
||||
```
|
||||
|
||||
8. **Scan for Never Type Opportunities**
|
||||
|
||||
Look for functions that never return:
|
||||
- Functions ending with process::exit
|
||||
- Functions that always panic
|
||||
- Infinite loops without return
|
||||
|
||||
Report:
|
||||
```
|
||||
## Never Type (!) Opportunities (3):
|
||||
|
||||
- src/error.rs:25 - fatal_error
|
||||
Current: fn fatal_error(msg: &str)
|
||||
Suggestion: Change to fn fatal_error(msg: &str) -> !
|
||||
Benefit: Compiler knows function doesn't return
|
||||
```
|
||||
|
||||
9. **Check for Outdated Idioms**
|
||||
|
||||
Look for patterns that are outdated:
|
||||
- try! macro instead of ?
|
||||
- match instead of if let
|
||||
- Unnecessary type annotations
|
||||
- Old-style error handling
|
||||
|
||||
Report:
|
||||
```
|
||||
## Outdated Idioms (2):
|
||||
|
||||
- src/legacy.rs:15
|
||||
Current: try!(expression)
|
||||
Suggestion: Use ? operator
|
||||
|
||||
- src/utils.rs:88
|
||||
Current: match on Result with Ok/Err
|
||||
Suggestion: Use if let Ok(...) for simpler case
|
||||
```
|
||||
|
||||
10. **Generate Comprehensive Report**
|
||||
|
||||
```
|
||||
✅ Pattern Check Complete
|
||||
|
||||
## Summary:
|
||||
|
||||
📊 Total Opportunities: 19
|
||||
|
||||
### By Category:
|
||||
- Let Chains: 5 opportunities (15 nested levels total)
|
||||
- Async Closures: 3 opportunities
|
||||
- Const Functions: 4 opportunities
|
||||
- Gen Blocks: 2 opportunities
|
||||
- Match Ergonomics: 3 opportunities
|
||||
- While-Let Chains: 2 opportunities
|
||||
|
||||
### Priority:
|
||||
- High: 7 (deep nesting, clarity improvements)
|
||||
- Medium: 8 (performance, modern idioms)
|
||||
- Low: 4 (minor improvements)
|
||||
|
||||
## Detailed Findings:
|
||||
|
||||
### 1. Let Chains (High Priority)
|
||||
|
||||
**src/user.rs:42** (4 levels nested)
|
||||
```rust
|
||||
// Current
|
||||
if let Some(user) = get_user(id) {
|
||||
if let Some(profile) = user.profile {
|
||||
if profile.is_active {
|
||||
if let Some(email) = profile.email {
|
||||
send_email(&email);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Suggested
|
||||
if let Some(user) = get_user(id)
|
||||
&& let Some(profile) = user.profile
|
||||
&& profile.is_active
|
||||
&& let Some(email) = profile.email
|
||||
{
|
||||
send_email(&email);
|
||||
}
|
||||
```
|
||||
|
||||
**Impact:** Much clearer, reduces nesting from 4 to 1 level
|
||||
|
||||
### 2. Const Functions (Medium Priority)
|
||||
|
||||
**src/config.rs:10**
|
||||
```rust
|
||||
// Current
|
||||
fn calculate_buffer_size(items: usize) -> usize {
|
||||
items * std::mem::size_of::<Item>()
|
||||
}
|
||||
|
||||
// Suggested
|
||||
const fn calculate_buffer_size(items: usize) -> usize {
|
||||
items * std::mem::size_of::<Item>()
|
||||
}
|
||||
|
||||
// Enables
|
||||
const BUFFER_SIZE: usize = calculate_buffer_size(1000);
|
||||
static BUFFER: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
|
||||
```
|
||||
|
||||
**Impact:** Compile-time computation, better performance
|
||||
|
||||
### 3. Gen Blocks (Medium Priority)
|
||||
|
||||
**src/iter.rs:15**
|
||||
```rust
|
||||
// Current: 25 lines
|
||||
struct FibIterator { a: u64, b: u64 }
|
||||
impl Iterator for FibIterator {
|
||||
type Item = u64;
|
||||
fn next(&mut self) -> Option<u64> {
|
||||
let current = self.a;
|
||||
self.a = self.b;
|
||||
self.b = current + self.b;
|
||||
Some(current)
|
||||
}
|
||||
}
|
||||
|
||||
// Suggested: 8 lines
|
||||
fn fibonacci() -> impl Iterator<Item = u64> {
|
||||
gen {
|
||||
let (mut a, mut b) = (0, 1);
|
||||
loop {
|
||||
yield a;
|
||||
(a, b) = (b, a + b);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Impact:** 60% less code, more maintainable
|
||||
|
||||
## Edition Status:
|
||||
|
||||
Current: edition = "2021"
|
||||
⚠️ To use these features, upgrade to edition = "2024"
|
||||
|
||||
Use: `/rust-upgrade-edition`
|
||||
|
||||
## Recommendations:
|
||||
|
||||
1. **Immediate:** Upgrade to Rust 2024 Edition
|
||||
2. **High Priority:** Apply let chain modernizations (5 locations)
|
||||
3. **Medium Priority:** Convert to const functions (4 locations)
|
||||
4. **Medium Priority:** Simplify with gen blocks (2 locations)
|
||||
5. **Consider:** Async closure updates when appropriate
|
||||
|
||||
## Estimated Impact:
|
||||
|
||||
- **Readability:** +40% (reduced nesting)
|
||||
- **Code reduction:** -15% (simpler patterns)
|
||||
- **Performance:** +5% (compile-time computation)
|
||||
- **Maintainability:** +30% (modern idioms)
|
||||
|
||||
## Next Steps:
|
||||
|
||||
```bash
|
||||
# 1. Upgrade edition
|
||||
/rust-upgrade-edition
|
||||
|
||||
# 2. Apply modernizations
|
||||
/rust-modernize
|
||||
|
||||
# 3. Run tests
|
||||
cargo test
|
||||
```
|
||||
|
||||
## Need Help?
|
||||
|
||||
- Ask `rust-modern-expert` for detailed guidance
|
||||
- Use `/rust-modernize` to apply changes automatically
|
||||
- See examples in CONTEXT.md
|
||||
```
|
||||
|
||||
## Search Patterns
|
||||
|
||||
Use Grep to find these patterns:
|
||||
|
||||
### Nested If-Let
|
||||
```
|
||||
Pattern: if let.*\{[^}]*if let
|
||||
```
|
||||
|
||||
### Manual Async Closures
|
||||
```
|
||||
Pattern: async move
|
||||
```
|
||||
|
||||
### Non-const Functions
|
||||
```
|
||||
Pattern: fn .+\(.*\) -> (usize|i32|u32|bool)
|
||||
Filter out those already const
|
||||
```
|
||||
|
||||
### Manual Iterators
|
||||
```
|
||||
Pattern: impl Iterator for
|
||||
```
|
||||
|
||||
## Scoring System
|
||||
|
||||
Assign priority based on:
|
||||
|
||||
**High Priority:**
|
||||
- 3+ levels of nesting
|
||||
- Functions in hot paths
|
||||
- Widely used patterns
|
||||
|
||||
**Medium Priority:**
|
||||
- 2 levels of nesting
|
||||
- Const-eligible functions
|
||||
- Iterator simplifications
|
||||
|
||||
**Low Priority:**
|
||||
- Style improvements
|
||||
- Minor simplifications
|
||||
|
||||
## Important Notes
|
||||
|
||||
- Only suggest changes compatible with current edition
|
||||
- Note if edition upgrade is required
|
||||
- Estimate impact (readability, performance, maintainability)
|
||||
- Prioritize changes by value
|
||||
- Provide before/after examples
|
||||
|
||||
## After Completion
|
||||
|
||||
Ask the user:
|
||||
1. Do you want to apply these modernizations?
|
||||
2. Should we start with high priority items?
|
||||
3. Do you want to upgrade the edition first?
|
||||
4. Would you like detailed explanations for any items?
|
||||
332
commands/rust-quality-check.md
Normal file
332
commands/rust-quality-check.md
Normal file
@@ -0,0 +1,332 @@
|
||||
---
|
||||
description: Run comprehensive quality checks using modern Rust tooling (fmt, clippy, nextest, audit, deny)
|
||||
---
|
||||
|
||||
Run a comprehensive quality check suite on the current Rust project using modern tooling best practices.
|
||||
|
||||
## What This Command Does
|
||||
|
||||
This command runs a complete quality assurance suite including:
|
||||
|
||||
1. **Code Formatting** - Verify code follows standard formatting
|
||||
2. **Linting** - Run clippy with strict settings
|
||||
3. **Testing** - Execute tests with cargo-nextest
|
||||
4. **Security Audit** - Check for known vulnerabilities
|
||||
5. **Dependency Checks** - Validate licenses and sources (if configured)
|
||||
6. **SemVer Check** - Verify API compatibility (for libraries)
|
||||
|
||||
## Process
|
||||
|
||||
### 1. Check Project Structure
|
||||
|
||||
First, verify this is a Rust project:
|
||||
- Look for `Cargo.toml` in current directory
|
||||
- Determine if this is a library or binary (affects checks)
|
||||
- Check for existing configurations (deny.toml, clippy.toml, etc.)
|
||||
|
||||
### 2. Run Quality Checks
|
||||
|
||||
Execute checks in this order:
|
||||
|
||||
#### Format Check
|
||||
```bash
|
||||
cargo fmt --all -- --check
|
||||
```
|
||||
- Verifies code follows rustfmt standards
|
||||
- **Fails if**: Code is not formatted
|
||||
- **Fix**: Run `cargo fmt --all`
|
||||
|
||||
#### Clippy Linting
|
||||
```bash
|
||||
cargo clippy --all-targets --all-features -- -D warnings
|
||||
```
|
||||
- Runs comprehensive linting
|
||||
- **Fails if**: Any clippy warnings exist
|
||||
- **Fix**: Address warnings or use `#[allow(...)]` with justification
|
||||
|
||||
#### Test Suite
|
||||
```bash
|
||||
# Check if nextest is available
|
||||
if command -v cargo-nextest &> /dev/null; then
|
||||
cargo nextest run --all-features
|
||||
cargo test --doc # nextest doesn't run doctests
|
||||
else
|
||||
cargo test --all-features
|
||||
fi
|
||||
```
|
||||
- Runs all tests
|
||||
- **Fails if**: Any test fails
|
||||
- **Fix**: Debug and fix failing tests
|
||||
|
||||
#### Security Audit
|
||||
```bash
|
||||
# Check if cargo-audit is available
|
||||
if command -v cargo-audit &> /dev/null; then
|
||||
cargo audit
|
||||
else
|
||||
echo "⚠️ cargo-audit not installed. Run: cargo install cargo-audit"
|
||||
fi
|
||||
```
|
||||
- Checks dependencies against RustSec database
|
||||
- **Fails if**: Known vulnerabilities found
|
||||
- **Fix**: Update dependencies or review advisories
|
||||
|
||||
#### Dependency Validation (Optional)
|
||||
```bash
|
||||
# Only if deny.toml exists
|
||||
if [ -f "deny.toml" ]; then
|
||||
if command -v cargo-deny &> /dev/null; then
|
||||
cargo deny check
|
||||
else
|
||||
echo "⚠️ deny.toml found but cargo-deny not installed"
|
||||
echo " Run: cargo install cargo-deny"
|
||||
fi
|
||||
fi
|
||||
```
|
||||
- Checks licenses, sources, bans, and advisories
|
||||
- **Fails if**: Policy violations found
|
||||
- **Fix**: Update dependencies or adjust policy
|
||||
|
||||
#### SemVer Check (Libraries Only)
|
||||
```bash
|
||||
# Check if this is a library and cargo-semver-checks is available
|
||||
if grep -q "\\[lib\\]" Cargo.toml; then
|
||||
if command -v cargo-semver-checks &> /dev/null; then
|
||||
cargo semver-checks check-release
|
||||
else
|
||||
echo "📚 Library detected. Consider installing cargo-semver-checks"
|
||||
echo " Run: cargo install cargo-semver-checks"
|
||||
fi
|
||||
fi
|
||||
```
|
||||
- Verifies API changes follow semantic versioning
|
||||
- **Fails if**: Breaking changes in non-major version
|
||||
- **Fix**: Bump version appropriately or fix API
|
||||
|
||||
### 3. Report Results
|
||||
|
||||
Provide a summary of all checks:
|
||||
|
||||
```
|
||||
✅ Rust Quality Check Results
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ Format Check - Passed
|
||||
✅ Clippy Linting - Passed
|
||||
✅ Test Suite - Passed (42 tests)
|
||||
✅ Security Audit - Passed (no vulnerabilities)
|
||||
✅ Dependency Check - Passed
|
||||
✅ SemVer Check - Passed
|
||||
|
||||
All checks passed! 🎉
|
||||
```
|
||||
|
||||
Or if issues found:
|
||||
|
||||
```
|
||||
❌ Rust Quality Check Results
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
❌ Format Check - FAILED
|
||||
Run: cargo fmt --all
|
||||
|
||||
✅ Clippy Linting - Passed
|
||||
❌ Test Suite - FAILED (2 tests failed)
|
||||
⚠️ Security Audit - WARNINGS (1 vulnerability)
|
||||
Update: tokio 1.25 -> 1.26 (RUSTSEC-2023-0001)
|
||||
|
||||
✅ Dependency Check - Passed
|
||||
|
||||
Fix these issues before committing.
|
||||
```
|
||||
|
||||
## Tool Installation Guide
|
||||
|
||||
If tools are missing, provide installation instructions:
|
||||
|
||||
```bash
|
||||
# Essential tools for quality checks
|
||||
cargo install cargo-nextest # Faster test runner
|
||||
cargo install cargo-audit # Security scanning
|
||||
cargo install cargo-deny # Dependency validation
|
||||
cargo install cargo-semver-checks # API compatibility
|
||||
|
||||
# Optional but recommended
|
||||
cargo install bacon # Continuous feedback
|
||||
cargo install flamegraph # Performance profiling
|
||||
```
|
||||
|
||||
## Configuration Recommendations
|
||||
|
||||
### Create clippy.toml
|
||||
|
||||
If `clippy.toml` doesn't exist, suggest creating one:
|
||||
|
||||
```toml
|
||||
# clippy.toml - Clippy configuration
|
||||
cognitive-complexity-threshold = 30
|
||||
single-char-binding-names-threshold = 5
|
||||
too-many-arguments-threshold = 7
|
||||
```
|
||||
|
||||
### Create deny.toml
|
||||
|
||||
If `deny.toml` doesn't exist for a project with dependencies, suggest:
|
||||
|
||||
```bash
|
||||
cargo deny init
|
||||
```
|
||||
|
||||
Then review and adjust the generated configuration.
|
||||
|
||||
### Update Cargo.toml
|
||||
|
||||
Suggest adding these to project Cargo.toml:
|
||||
|
||||
```toml
|
||||
[package]
|
||||
edition = "2024" # Use latest edition
|
||||
rust-version = "1.85" # Set MSRV
|
||||
|
||||
[profile.release]
|
||||
debug = true # For profiling
|
||||
|
||||
[profile.dev]
|
||||
# Enable some optimizations for faster dev builds
|
||||
opt-level = 1
|
||||
```
|
||||
|
||||
## CI/CD Integration
|
||||
|
||||
Provide a GitHub Actions workflow snippet:
|
||||
|
||||
```yaml
|
||||
name: Quality Checks
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
quality:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: Install tools
|
||||
run: |
|
||||
cargo install cargo-nextest
|
||||
cargo install cargo-audit
|
||||
cargo install cargo-deny
|
||||
|
||||
- name: Format check
|
||||
run: cargo fmt --all -- --check
|
||||
|
||||
- name: Clippy
|
||||
run: cargo clippy --all-targets --all-features -- -D warnings
|
||||
|
||||
- name: Tests
|
||||
run: |
|
||||
cargo nextest run --all-features
|
||||
cargo test --doc
|
||||
|
||||
- name: Security audit
|
||||
run: cargo audit
|
||||
|
||||
- name: Dependency check
|
||||
run: cargo deny check
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
When running quality checks:
|
||||
|
||||
1. **Run locally before pushing** - Catch issues early
|
||||
2. **Fix formatting first** - Easiest to resolve
|
||||
3. **Address clippy warnings** - They often catch real bugs
|
||||
4. **Don't skip tests** - Even if they're slow
|
||||
5. **Review security advisories** - Don't just update blindly
|
||||
6. **Keep tools updated** - `cargo install --force <tool>`
|
||||
7. **Configure in CI** - Enforce quality automatically
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "cargo-nextest not found"
|
||||
```bash
|
||||
cargo install cargo-nextest
|
||||
```
|
||||
|
||||
### "cargo-audit not found"
|
||||
```bash
|
||||
cargo install cargo-audit
|
||||
```
|
||||
|
||||
### Clippy warnings overwhelming
|
||||
```bash
|
||||
# Fix incrementally
|
||||
cargo clippy --fix --allow-dirty --allow-staged
|
||||
```
|
||||
|
||||
### Tests fail on CI but pass locally
|
||||
- Check for race conditions
|
||||
- Ensure deterministic behavior
|
||||
- Use cargo-nextest's flaky test detection
|
||||
|
||||
### Security vulnerabilities can't be fixed
|
||||
- Check if patched versions exist
|
||||
- Review the advisory details
|
||||
- Consider alternatives if no fix available
|
||||
- Document accepted risks
|
||||
|
||||
## Output Format
|
||||
|
||||
Provide structured output:
|
||||
|
||||
```
|
||||
🔍 Running Rust Quality Checks...
|
||||
|
||||
[1/6] Format Check...
|
||||
✅ Code is properly formatted
|
||||
|
||||
[2/6] Clippy Linting...
|
||||
✅ No warnings found
|
||||
|
||||
[3/6] Test Suite...
|
||||
Running 42 tests...
|
||||
✅ All tests passed (42/42)
|
||||
|
||||
[4/6] Security Audit...
|
||||
Scanning 187 dependencies...
|
||||
✅ No vulnerabilities found
|
||||
|
||||
[5/6] Dependency Check...
|
||||
✅ All licenses approved
|
||||
✅ All sources verified
|
||||
|
||||
[6/6] SemVer Check...
|
||||
✅ No breaking changes detected
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
✅ All Quality Checks Passed
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Ready to commit! 🚀
|
||||
```
|
||||
|
||||
## Your Task
|
||||
|
||||
Execute the comprehensive quality check suite:
|
||||
|
||||
1. Verify project structure
|
||||
2. Check for required tools
|
||||
3. Run all available checks
|
||||
4. Provide clear summary
|
||||
5. Suggest fixes for failures
|
||||
6. Recommend tool installations if needed
|
||||
7. Offer configuration improvements
|
||||
|
||||
Make the output clear, actionable, and encouraging!
|
||||
597
commands/rust-setup-tooling.md
Normal file
597
commands/rust-setup-tooling.md
Normal file
@@ -0,0 +1,597 @@
|
||||
---
|
||||
description: Set up modern Rust development tooling (bacon, nextest, audit, deny, clippy config)
|
||||
---
|
||||
|
||||
Set up a modern Rust development environment with best-in-class tooling for 2025.
|
||||
|
||||
## What This Command Does
|
||||
|
||||
This command configures your Rust project with:
|
||||
|
||||
1. **Essential Development Tools** - Install bacon, cargo-nextest, etc.
|
||||
2. **Quality Assurance Tools** - Set up clippy, rustfmt, cargo-audit
|
||||
3. **Security Tools** - Configure cargo-audit and cargo-deny
|
||||
4. **Configuration Files** - Create clippy.toml, deny.toml, rustfmt.toml
|
||||
5. **CI/CD Template** - Provide GitHub Actions workflow
|
||||
6. **Documentation** - Add tool usage guide to project
|
||||
|
||||
## Process
|
||||
|
||||
### 1. Assess Current Setup
|
||||
|
||||
Check what's already installed:
|
||||
|
||||
```bash
|
||||
# Check Rust version
|
||||
rustc --version
|
||||
rustup --version
|
||||
|
||||
# Check for existing tools
|
||||
cargo-nextest --version 2>/dev/null
|
||||
cargo-audit --version 2>/dev/null
|
||||
cargo-deny --version 2>/dev/null
|
||||
bacon --version 2>/dev/null
|
||||
flamegraph --version 2>/dev/null
|
||||
cargo-semver-checks --version 2>/dev/null
|
||||
```
|
||||
|
||||
### 2. Install Essential Tools
|
||||
|
||||
Install missing tools with user confirmation:
|
||||
|
||||
```bash
|
||||
echo "Installing modern Rust tooling..."
|
||||
echo ""
|
||||
echo "Essential tools:"
|
||||
echo " • bacon - Background compiler"
|
||||
echo " • cargo-nextest - Fast test runner"
|
||||
echo " • cargo-audit - Security scanner"
|
||||
echo " • cargo-deny - Dependency validator"
|
||||
echo ""
|
||||
echo "Optional tools:"
|
||||
echo " • flamegraph - Performance profiler"
|
||||
echo " • cargo-semver-checks - API compatibility"
|
||||
echo " • cargo-machete - Unused dependency finder"
|
||||
echo ""
|
||||
|
||||
# Install essentials
|
||||
cargo install bacon
|
||||
cargo install cargo-nextest
|
||||
cargo install cargo-audit
|
||||
cargo install cargo-deny
|
||||
|
||||
# Optionally install others
|
||||
# cargo install flamegraph
|
||||
# cargo install cargo-semver-checks
|
||||
# cargo install cargo-machete
|
||||
```
|
||||
|
||||
### 3. Create Configuration Files
|
||||
|
||||
#### clippy.toml
|
||||
|
||||
Create `clippy.toml` with sensible defaults:
|
||||
|
||||
```toml
|
||||
# clippy.toml - Clippy linter configuration
|
||||
# See: https://doc.rust-lang.org/clippy/
|
||||
|
||||
# Complexity thresholds
|
||||
cognitive-complexity-threshold = 30
|
||||
too-many-arguments-threshold = 7
|
||||
too-many-lines-threshold = 150
|
||||
large-error-threshold = 128
|
||||
|
||||
# Naming conventions
|
||||
single-char-binding-names-threshold = 5
|
||||
|
||||
# Documentation
|
||||
missing-docs-in-private-items = false
|
||||
|
||||
# Allow some pedantic lints that are too noisy
|
||||
# Uncomment to allow:
|
||||
# doc-markdown = "allow"
|
||||
# module-name-repetitions = "allow"
|
||||
# missing-errors-doc = "allow"
|
||||
```
|
||||
|
||||
#### rustfmt.toml
|
||||
|
||||
Create `rustfmt.toml` for consistent formatting:
|
||||
|
||||
```toml
|
||||
# rustfmt.toml - Rustfmt configuration
|
||||
# See: https://rust-lang.github.io/rustfmt/
|
||||
|
||||
edition = "2024"
|
||||
|
||||
# Line length
|
||||
max_width = 100
|
||||
hard_tabs = false
|
||||
tab_spaces = 4
|
||||
|
||||
# Imports
|
||||
imports_granularity = "Crate"
|
||||
group_imports = "StdExternalCrate"
|
||||
reorder_imports = true
|
||||
|
||||
# Comments and docs
|
||||
wrap_comments = true
|
||||
format_code_in_doc_comments = true
|
||||
normalize_comments = true
|
||||
|
||||
# Misc
|
||||
use_field_init_shorthand = true
|
||||
use_try_shorthand = true
|
||||
```
|
||||
|
||||
#### deny.toml
|
||||
|
||||
Initialize cargo-deny configuration:
|
||||
|
||||
```bash
|
||||
cargo deny init
|
||||
```
|
||||
|
||||
Then customize the generated `deny.toml`:
|
||||
|
||||
```toml
|
||||
# deny.toml - Cargo-deny configuration
|
||||
|
||||
[advisories]
|
||||
vulnerability = "deny"
|
||||
unmaintained = "warn"
|
||||
unsound = "warn"
|
||||
yanked = "warn"
|
||||
notice = "warn"
|
||||
|
||||
[licenses]
|
||||
unlicensed = "deny"
|
||||
# Adjust allowed licenses for your needs
|
||||
allow = [
|
||||
"MIT",
|
||||
"Apache-2.0",
|
||||
"BSD-3-Clause",
|
||||
"BSD-2-Clause",
|
||||
"ISC",
|
||||
]
|
||||
confidence-threshold = 0.8
|
||||
|
||||
[bans]
|
||||
multiple-versions = "warn"
|
||||
wildcards = "warn"
|
||||
highlight = "all"
|
||||
|
||||
# Ban known problematic crates (customize as needed)
|
||||
deny = [
|
||||
# Example: { name = "openssl", use-instead = "rustls" },
|
||||
]
|
||||
|
||||
[sources]
|
||||
unknown-registry = "deny"
|
||||
unknown-git = "warn"
|
||||
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
|
||||
```
|
||||
|
||||
#### .cargo/config.toml
|
||||
|
||||
Create `.cargo/config.toml` for local development settings:
|
||||
|
||||
```toml
|
||||
# .cargo/config.toml - Cargo configuration
|
||||
|
||||
[alias]
|
||||
# Convenient aliases
|
||||
check-all = "check --all-targets --all-features"
|
||||
test-all = "nextest run --all-features"
|
||||
lint = "clippy --all-targets --all-features -- -D warnings"
|
||||
quality = "run --bin rust-quality-check"
|
||||
|
||||
[build]
|
||||
# Increase parallel compilation
|
||||
jobs = 8 # Adjust based on CPU cores
|
||||
|
||||
[term]
|
||||
# Better progress bars
|
||||
progress.when = "auto"
|
||||
progress.width = 80
|
||||
```
|
||||
|
||||
### 4. Update Cargo.toml
|
||||
|
||||
Suggest updates to the project's `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[package]
|
||||
name = "my-project"
|
||||
version = "0.1.0"
|
||||
edition = "2024" # Use latest edition
|
||||
rust-version = "1.85" # Set minimum Rust version (MSRV)
|
||||
|
||||
# Add lints
|
||||
[lints.rust]
|
||||
unsafe_code = "forbid" # Adjust as needed
|
||||
missing_docs = "warn"
|
||||
|
||||
[lints.clippy]
|
||||
all = "warn"
|
||||
pedantic = "warn"
|
||||
nursery = "warn"
|
||||
cargo = "warn"
|
||||
|
||||
# Allow some pedantic lints that are too noisy
|
||||
module_name_repetitions = "allow"
|
||||
missing_errors_doc = "allow"
|
||||
|
||||
[profile.dev]
|
||||
# Faster iterative compilation
|
||||
opt-level = 1
|
||||
|
||||
[profile.release]
|
||||
# Enable debug symbols for profiling
|
||||
debug = true
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
```
|
||||
|
||||
### 5. Create Development Scripts
|
||||
|
||||
#### scripts/quality.sh
|
||||
|
||||
Create a pre-commit script:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# scripts/quality.sh - Run quality checks
|
||||
|
||||
set -e
|
||||
|
||||
echo "🔍 Running quality checks..."
|
||||
echo ""
|
||||
|
||||
echo "📝 Formatting..."
|
||||
cargo fmt --all -- --check
|
||||
|
||||
echo "✨ Linting..."
|
||||
cargo clippy --all-targets --all-features -- -D warnings
|
||||
|
||||
echo "🧪 Testing..."
|
||||
if command -v cargo-nextest &> /dev/null; then
|
||||
cargo nextest run --all-features
|
||||
cargo test --doc
|
||||
else
|
||||
cargo test --all-features
|
||||
fi
|
||||
|
||||
echo "🔒 Security audit..."
|
||||
cargo audit
|
||||
|
||||
echo "📦 Dependency check..."
|
||||
if [ -f "deny.toml" ]; then
|
||||
cargo deny check
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "✅ All checks passed!"
|
||||
```
|
||||
|
||||
Make it executable:
|
||||
```bash
|
||||
chmod +x scripts/quality.sh
|
||||
```
|
||||
|
||||
#### scripts/dev.sh
|
||||
|
||||
Create a development startup script:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# scripts/dev.sh - Start development environment
|
||||
|
||||
echo "🚀 Starting Rust development environment..."
|
||||
echo ""
|
||||
|
||||
# Start bacon in background
|
||||
echo "Starting bacon clippy..."
|
||||
bacon clippy &
|
||||
BACON_PID=$!
|
||||
|
||||
# Trap Ctrl+C to clean up
|
||||
trap "echo ''; echo 'Shutting down...'; kill $BACON_PID 2>/dev/null; exit" INT TERM
|
||||
|
||||
echo ""
|
||||
echo "✅ Development environment ready!"
|
||||
echo ""
|
||||
echo " 📝 Bacon is running clippy in the background"
|
||||
echo " 🔧 Make changes and see feedback automatically"
|
||||
echo ""
|
||||
echo "Press Ctrl+C to stop"
|
||||
echo ""
|
||||
|
||||
# Keep script running
|
||||
wait $BACON_PID
|
||||
```
|
||||
|
||||
Make it executable:
|
||||
```bash
|
||||
chmod +x scripts/dev.sh
|
||||
```
|
||||
|
||||
### 6. Create CI/CD Workflow
|
||||
|
||||
Create `.github/workflows/ci.yml`:
|
||||
|
||||
```yaml
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop]
|
||||
pull_request:
|
||||
branches: [main, develop]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
RUSTFLAGS: -D warnings
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: Check formatting
|
||||
run: cargo fmt --all -- --check
|
||||
|
||||
- name: Run clippy
|
||||
run: cargo clippy --all-targets --all-features -- -D warnings
|
||||
|
||||
- name: Check cargo.toml
|
||||
run: cargo check --all-features
|
||||
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: Install nextest
|
||||
uses: taiki-e/install-action@nextest
|
||||
|
||||
- name: Run tests
|
||||
run: cargo nextest run --all-features
|
||||
|
||||
- name: Run doctests
|
||||
run: cargo test --doc
|
||||
|
||||
security:
|
||||
name: Security Audit
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: Install cargo-audit
|
||||
run: cargo install cargo-audit
|
||||
|
||||
- name: Run security audit
|
||||
run: cargo audit
|
||||
|
||||
- name: Install cargo-deny
|
||||
run: cargo install cargo-deny
|
||||
|
||||
- name: Check dependencies
|
||||
run: cargo deny check
|
||||
|
||||
coverage:
|
||||
name: Code Coverage
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Install tarpaulin
|
||||
run: cargo install cargo-tarpaulin
|
||||
|
||||
- name: Generate coverage
|
||||
run: cargo tarpaulin --out xml --all-features
|
||||
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
files: ./cobertura.xml
|
||||
```
|
||||
|
||||
### 7. Create Documentation
|
||||
|
||||
Create `DEVELOPMENT.md`:
|
||||
|
||||
```markdown
|
||||
# Development Guide
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Rust 1.85 or later
|
||||
- Modern Rust tooling (see setup below)
|
||||
|
||||
### Setup
|
||||
|
||||
Install development tools:
|
||||
|
||||
\`\`\`bash
|
||||
./scripts/setup-tooling.sh # Or manually install tools
|
||||
\`\`\`
|
||||
|
||||
### Development Workflow
|
||||
|
||||
Start the development environment:
|
||||
|
||||
\`\`\`bash
|
||||
./scripts/dev.sh
|
||||
\`\`\`
|
||||
|
||||
This starts bacon for continuous feedback. Make changes and see linting results automatically.
|
||||
|
||||
### Before Committing
|
||||
|
||||
Run quality checks:
|
||||
|
||||
\`\`\`bash
|
||||
./scripts/quality.sh
|
||||
# Or use the alias:
|
||||
cargo quality
|
||||
\`\`\`
|
||||
|
||||
This runs:
|
||||
- Code formatting check
|
||||
- Clippy linting
|
||||
- All tests
|
||||
- Security audit
|
||||
- Dependency validation
|
||||
|
||||
## Tools
|
||||
|
||||
### bacon
|
||||
Continuous background compilation and linting.
|
||||
|
||||
\`\`\`bash
|
||||
bacon clippy # Run clippy continuously
|
||||
bacon test # Run tests continuously
|
||||
\`\`\`
|
||||
|
||||
### cargo-nextest
|
||||
Faster test runner with better output.
|
||||
|
||||
\`\`\`bash
|
||||
cargo nextest run # Run all tests
|
||||
cargo nextest run test_name # Run specific test
|
||||
\`\`\`
|
||||
|
||||
### cargo-audit
|
||||
Security vulnerability scanner.
|
||||
|
||||
\`\`\`bash
|
||||
cargo audit # Check for vulnerabilities
|
||||
cargo audit fix # Update dependencies
|
||||
\`\`\`
|
||||
|
||||
### cargo-deny
|
||||
Dependency validator for licenses, sources, and security.
|
||||
|
||||
\`\`\`bash
|
||||
cargo deny check # Check all policies
|
||||
cargo deny check licenses # Check licenses only
|
||||
\`\`\`
|
||||
|
||||
### flamegraph
|
||||
Performance profiler.
|
||||
|
||||
\`\`\`bash
|
||||
cargo flamegraph --bin myapp
|
||||
\`\`\`
|
||||
|
||||
## Configuration
|
||||
|
||||
- `clippy.toml` - Clippy linting rules
|
||||
- `rustfmt.toml` - Code formatting rules
|
||||
- `deny.toml` - Dependency policies
|
||||
- `.cargo/config.toml` - Cargo aliases and settings
|
||||
|
||||
## CI/CD
|
||||
|
||||
All checks run automatically in CI:
|
||||
- Format checking
|
||||
- Clippy linting
|
||||
- Test suite
|
||||
- Security audit
|
||||
- Dependency validation
|
||||
|
||||
See `.github/workflows/ci.yml` for details.
|
||||
\`\`\`
|
||||
|
||||
### 8. Provide Setup Summary
|
||||
|
||||
After completion, show summary:
|
||||
|
||||
```
|
||||
✅ Rust Development Tooling Setup Complete!
|
||||
|
||||
Installed Tools:
|
||||
✅ bacon - Background compiler
|
||||
✅ cargo-nextest - Fast test runner
|
||||
✅ cargo-audit - Security scanner
|
||||
✅ cargo-deny - Dependency validator
|
||||
|
||||
Created Configurations:
|
||||
✅ clippy.toml - Linting rules
|
||||
✅ rustfmt.toml - Formatting rules
|
||||
✅ deny.toml - Dependency policies
|
||||
✅ .cargo/config.toml - Cargo settings
|
||||
|
||||
Created Scripts:
|
||||
✅ scripts/quality.sh - Pre-commit checks
|
||||
✅ scripts/dev.sh - Development environment
|
||||
|
||||
Created Workflows:
|
||||
✅ .github/workflows/ci.yml - CI pipeline
|
||||
|
||||
Created Documentation:
|
||||
✅ DEVELOPMENT.md - Developer guide
|
||||
|
||||
Next Steps:
|
||||
1. Review and adjust configurations to your needs
|
||||
2. Run: ./scripts/dev.sh
|
||||
3. Make changes and see instant feedback
|
||||
4. Before committing: ./scripts/quality.sh
|
||||
|
||||
Happy coding! 🦀✨
|
||||
```
|
||||
|
||||
## Tool Descriptions
|
||||
|
||||
Explain each tool's purpose:
|
||||
|
||||
- **bacon**: Watches files and runs cargo commands, showing minimal, actionable output
|
||||
- **cargo-nextest**: Runs tests in parallel with better reporting, 60% faster than cargo test
|
||||
- **cargo-audit**: Scans dependencies for security vulnerabilities from RustSec database
|
||||
- **cargo-deny**: Validates licenses, sources, and checks for banned/duplicated dependencies
|
||||
- **cargo-semver-checks**: Ensures API changes follow semantic versioning (for libraries)
|
||||
- **flamegraph**: Generates flamegraphs for performance profiling
|
||||
|
||||
## Your Task
|
||||
|
||||
Set up modern Rust development tooling:
|
||||
|
||||
1. Check current tool installation
|
||||
2. Install missing essential tools
|
||||
3. Create configuration files
|
||||
4. Set up development scripts
|
||||
5. Create CI/CD workflow
|
||||
6. Generate documentation
|
||||
7. Provide clear next steps
|
||||
|
||||
Make the setup smooth and explain what each tool does!
|
||||
347
commands/rust-upgrade-edition.md
Normal file
347
commands/rust-upgrade-edition.md
Normal file
@@ -0,0 +1,347 @@
|
||||
---
|
||||
description: Upgrade Rust project to Rust 2024 Edition
|
||||
---
|
||||
|
||||
You are helping upgrade a Rust project to Rust 2024 Edition.
|
||||
|
||||
## Your Task
|
||||
|
||||
Guide the user through upgrading their project from an older edition (2015, 2018, or 2021) to Rust 2024 Edition, handling breaking changes and migration steps.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Check Current Status**
|
||||
|
||||
Read Cargo.toml to determine:
|
||||
- Current edition
|
||||
- Current rust-version (MSRV) if set
|
||||
- Project structure (workspace or single crate)
|
||||
|
||||
```rust
|
||||
Current Status:
|
||||
- Edition: 2021
|
||||
- MSRV: Not set
|
||||
- Type: Single crate
|
||||
```
|
||||
|
||||
2. **Verify Rust Version**
|
||||
|
||||
Check that Rust toolchain is recent enough:
|
||||
|
||||
```bash
|
||||
rustc --version
|
||||
```
|
||||
|
||||
Required: Rust 1.85.0 or later for full Rust 2024 support.
|
||||
|
||||
If version is too old:
|
||||
```
|
||||
⚠️ Rust version is too old. Rust 2024 Edition requires 1.85.0 or later.
|
||||
|
||||
Please update:
|
||||
```bash
|
||||
rustup update stable
|
||||
```
|
||||
```
|
||||
|
||||
3. **Create Backup**
|
||||
|
||||
Suggest creating a git commit or backup:
|
||||
```
|
||||
💡 Recommendation: Commit current changes before upgrading
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Pre-2024 edition upgrade snapshot"
|
||||
```
|
||||
```
|
||||
|
||||
4. **Update Cargo.toml**
|
||||
|
||||
For single crate:
|
||||
```toml
|
||||
[package]
|
||||
name = "my-project"
|
||||
version = "0.1.0"
|
||||
edition = "2024" # Updated from 2021
|
||||
rust-version = "1.85" # Add MSRV
|
||||
```
|
||||
|
||||
For workspace:
|
||||
```toml
|
||||
[workspace]
|
||||
members = ["crate1", "crate2"]
|
||||
|
||||
[workspace.package]
|
||||
edition = "2024"
|
||||
rust-version = "1.85"
|
||||
|
||||
# Then each crate can inherit:
|
||||
[package]
|
||||
name = "crate1"
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
```
|
||||
|
||||
5. **Run cargo fix**
|
||||
|
||||
Automatically fix edition-related issues:
|
||||
|
||||
```bash
|
||||
cargo fix --edition
|
||||
```
|
||||
|
||||
This will:
|
||||
- Fix deprecated patterns
|
||||
- Update syntax where needed
|
||||
- Add compatibility shims
|
||||
|
||||
6. **Check for Warnings**
|
||||
|
||||
Review compiler warnings:
|
||||
|
||||
```bash
|
||||
cargo check --all-targets
|
||||
```
|
||||
|
||||
Common warnings:
|
||||
- Match ergonomics changes
|
||||
- Binding mode changes
|
||||
- Reserved syntax warnings
|
||||
|
||||
7. **Update Match Patterns (Rust 2024)**
|
||||
|
||||
**Breaking Change:** mut binding behavior changed
|
||||
|
||||
Before (2021):
|
||||
```rust
|
||||
match &option {
|
||||
Some(mut x) => {
|
||||
// x is T (moved)
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
```
|
||||
|
||||
After (2024):
|
||||
```rust
|
||||
match &option {
|
||||
Some(mut x) => {
|
||||
// x is &mut T (not moved)
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
```
|
||||
|
||||
If you need the old behavior:
|
||||
```rust
|
||||
match option { // Match on value, not reference
|
||||
Some(mut x) => {
|
||||
// x is T (moved)
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
```
|
||||
|
||||
8. **Update Reserved Patterns**
|
||||
|
||||
Rust 2024 reserves some pattern combinations for future use:
|
||||
|
||||
```rust
|
||||
// ❌ Not allowed in 2024 (mixed ergonomics)
|
||||
match value {
|
||||
Some(ref x) => {} // Error if not fully explicit
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// ✅ Allowed (fully explicit)
|
||||
match value {
|
||||
&Some(ref x) => {}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// ✅ Or use ergonomics fully
|
||||
match &value {
|
||||
Some(x) => {} // x is &T
|
||||
_ => {}
|
||||
}
|
||||
```
|
||||
|
||||
9. **Run Tests**
|
||||
|
||||
Verify everything still works:
|
||||
|
||||
```bash
|
||||
cargo test --all-targets
|
||||
```
|
||||
|
||||
If tests fail:
|
||||
- Check for match pattern changes
|
||||
- Look for binding mode issues
|
||||
- Review compiler errors carefully
|
||||
|
||||
10. **Update Dependencies**
|
||||
|
||||
Check if dependencies support Rust 2024:
|
||||
|
||||
```bash
|
||||
cargo update
|
||||
cargo check
|
||||
```
|
||||
|
||||
The MSRV-aware resolver (Rust 1.84+) will automatically select compatible versions based on your rust-version.
|
||||
|
||||
11. **Enable Modern Features**
|
||||
|
||||
Now you can use Rust 2024 features:
|
||||
|
||||
```rust
|
||||
// Let chains
|
||||
if let Some(x) = opt1
|
||||
&& let Some(y) = opt2
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
// Async closures
|
||||
items.iter().map(async |item| {
|
||||
process(item).await
|
||||
})
|
||||
|
||||
// Gen blocks
|
||||
let iter = gen {
|
||||
yield 1;
|
||||
yield 2;
|
||||
};
|
||||
```
|
||||
|
||||
12. **Update Lints**
|
||||
|
||||
Add modern lints to catch issues:
|
||||
|
||||
```rust
|
||||
// In lib.rs or main.rs
|
||||
#![warn(rust_2024_compatibility)]
|
||||
#![warn(let_underscore_drop)]
|
||||
#![warn(unused_qualifications)]
|
||||
```
|
||||
|
||||
13. **Provide Upgrade Summary**
|
||||
|
||||
```
|
||||
✅ Successfully upgraded to Rust 2024 Edition!
|
||||
|
||||
## Changes Made:
|
||||
|
||||
### Cargo.toml Updates:
|
||||
- Edition: 2021 → 2024
|
||||
- Added rust-version = "1.85"
|
||||
|
||||
### Code Changes:
|
||||
- Applied automatic fixes via cargo fix
|
||||
- Updated 3 match patterns for new ergonomics
|
||||
- Fixed 2 reserved pattern warnings
|
||||
|
||||
### Tests:
|
||||
- All tests passing ✅
|
||||
|
||||
## New Features Available:
|
||||
|
||||
1. **Let Chains** - Flatten nested if-let
|
||||
2. **Async Closures** - Native async || {} syntax
|
||||
3. **Gen Blocks** - Simplified iterators
|
||||
4. **Improved Match Ergonomics** - Clearer semantics
|
||||
5. **MSRV-Aware Resolver** - Automatic compatible versions
|
||||
|
||||
## Next Steps:
|
||||
|
||||
1. Use `/rust-modernize` to apply modern patterns
|
||||
2. Review new edition guide: https://doc.rust-lang.org/edition-guide/rust-2024/
|
||||
3. Update CI/CD to use Rust 1.85+
|
||||
4. Consider modernizing code patterns
|
||||
|
||||
## Migration Guide:
|
||||
See the [Rust 2024 Edition Guide](https://doc.rust-lang.org/edition-guide/rust-2024/) for details.
|
||||
```
|
||||
|
||||
## Breaking Changes Checklist
|
||||
|
||||
When upgrading to Rust 2024, be aware of:
|
||||
|
||||
- [ ] **Match ergonomics** - mut bindings work differently
|
||||
- [ ] **Reserved patterns** - Some patterns reserved for future
|
||||
- [ ] **Temporary scopes in let chains** - Different drop order
|
||||
- [ ] **Impl trait captures** - More lifetime capture rules
|
||||
|
||||
## Workspace Upgrade
|
||||
|
||||
For workspaces with multiple crates:
|
||||
|
||||
1. **Update workspace root**:
|
||||
```toml
|
||||
[workspace.package]
|
||||
edition = "2024"
|
||||
rust-version = "1.85"
|
||||
```
|
||||
|
||||
2. **Update each crate**:
|
||||
```toml
|
||||
[package]
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
```
|
||||
|
||||
3. **Run cargo fix for each crate**:
|
||||
```bash
|
||||
cargo fix --edition --workspace
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### cargo fix fails
|
||||
|
||||
If `cargo fix --edition` fails:
|
||||
1. Fix compilation errors first: `cargo check`
|
||||
2. Resolve dependency issues
|
||||
3. Try fixing one crate at a time
|
||||
4. Check for proc-macro compatibility
|
||||
|
||||
### Tests fail after upgrade
|
||||
|
||||
Common issues:
|
||||
1. **Match pattern changes** - Check mut bindings
|
||||
2. **Drop order changes** - Let chains have different scoping
|
||||
3. **Lifetime changes** - Impl trait captures more lifetimes
|
||||
|
||||
### Dependencies incompatible
|
||||
|
||||
If dependencies don't support Rust 2024:
|
||||
1. Check for updates: `cargo update`
|
||||
2. MSRV resolver should pick compatible versions
|
||||
3. File issues with dependency maintainers
|
||||
4. Consider alternatives if critical
|
||||
|
||||
## Version Requirements
|
||||
|
||||
- **Minimum Rust:** 1.85.0 for full Rust 2024 Edition
|
||||
- **Let chains:** 1.88.0
|
||||
- **MSRV resolver:** 1.84.0 (recommended before upgrade)
|
||||
|
||||
## Edition Comparison
|
||||
|
||||
| Feature | 2021 | 2024 |
|
||||
|---------|------|------|
|
||||
| Let chains | ❌ | ✅ |
|
||||
| Async closures | ❌ | ✅ |
|
||||
| Gen blocks | ❌ | ✅ |
|
||||
| Match ergonomics | Old | Improved |
|
||||
| MSRV resolver | ❌ | ✅ |
|
||||
|
||||
## After Completion
|
||||
|
||||
Ask the user:
|
||||
1. Did the upgrade complete successfully?
|
||||
2. Are all tests passing?
|
||||
3. Should we modernize the code to use new features?
|
||||
4. Do you want to update CI/CD configuration?
|
||||
Reference in New Issue
Block a user