Status: Decision Document Date: 2026-01-04 Author: Project Tach Development Team Rust Version: 1.88.0+ required (MSRV). Edition 2024 stabilized in 1.85.0.
Rust 2024 Edition was stabilized with Rust 1.85.0 (February 20, 2025). This document analyzes whether tach-core should migrate from Edition 2021 to Edition 2024, covering the pros, cons, breaking changes, and impact on our codebase.
Note: Project Tach requires Rust 1.88.0+ as its MSRV (see
Cargo.toml).
Recommendation: Migrate to Edition 2024 after addressing the static mut references issue. The edition brings safety improvements that align with our security-first philosophy.
Rust editions are released every three years (2015, 2018, 2021, 2024) and allow the language to evolve without breaking existing code. Key points:
- Editions are opt-in via
Cargo.toml - Different editions can interoperate (crates can depend on crates using different editions)
cargo fix --editionautomates most migrations- Editions only affect how the compiler parses code, not runtime behavior
| Change | Impact on tach-core | Severity |
|---|---|---|
| RPIT Lifetime Capture Rules | Low - We don't heavily use impl Trait returns with complex lifetimes |
Minor |
Disallow static mut references |
HIGH - We have static mut in allocator code |
Breaking |
unsafe extern blocks required |
Medium - Our FFI code needs updates | Moderate |
unsafe attributes (#[no_mangle], etc.) |
Medium - Requires #[unsafe(no_mangle)] |
Moderate |
gen keyword reserved |
None - We don't use gen as an identifier |
None |
| Match ergonomics refinements | Low - Minor pattern matching changes | Minor |
if let temporary scope changes |
Low - May affect some patterns | Minor |
| Tail expression temporary scope | Low - Affects temporary lifetimes | Minor |
| Change | Impact | Notes |
|---|---|---|
| Rustfmt Style Edition | Low | Formatting can be pinned to 2021 style |
Cargo: Reject unused default-features |
Low | May need Cargo.toml cleanup |
| Rustdoc: Combined doctests | Positive | Faster doc test execution |
| Change | Impact | Notes |
|---|---|---|
std::env::set_var is now unsafe |
None | We don't modify env vars in unsafe contexts |
| Prelude additions | None | New items in prelude |
In Edition 2024, references to static mut are denied by default. This affects our codebase in:
Current problematic pattern:
// This is now an error in Edition 2024
static mut COUNTER: u32 = 0;
unsafe {
COUNTER += 1; // Error: creating reference to mutable static
}Solution options:
- Use
std::sync::atomictypes (preferred for simple counters) - Use
std::sync::MutexorOnceLock - Use
std::ptr::addr_of_mut!for raw pointer access
Our current usage: We already follow best practices with AtomicBool, Mutex<T>, and OnceLock in most places. A grep for static mut will identify any remaining instances.
All extern blocks must now be marked unsafe:
Before (2021):
extern "C" {
fn some_ffi_function();
}After (2024):
unsafe extern "C" {
fn some_ffi_function();
}Impact: Our PyO3 FFI code may need updates.
Attributes like #[no_mangle] and #[link_section] must use #[unsafe(...)] syntax:
Before (2021):
#[no_mangle]
pub extern "C" fn my_function() {}After (2024):
#[unsafe(no_mangle)]
pub extern "C" fn my_function() {}static mutdenial: Eliminates a class of undefined behavior that we've already been avoidingunsafe externclarity: Makes FFI safety boundaries explicit- Unsafe attributes: Documents that certain attributes have safety implications
- RPIT lifetime capture: More intuitive behavior for
impl Traitreturn types - Consistent rules:
async fnand-> impl Traitnow behave consistently
genkeyword: Ready for generator syntax when stabilized- Match ergonomics: Aligns with future pattern matching improvements
- Ecosystem alignment: Libraries will start requiring 2024 edition
- Rustfmt style editions: Independent formatting evolution
- Faster doctests: Combined doctest execution
- Better error messages: Improved diagnostics
- Must address
static mutreferences - Must update
externblocks - Must update unsafe attributes
- Requires Rust 1.88.0+
- May exclude users on older toolchains
- CI must use 1.88.0+
3. Potential Hidden Issues
- Lifetime capture changes may cause subtle breaks in edge cases
- Match ergonomics changes may require pattern updates
- If using default rustfmt style, code will be reformatted
- Can mitigate with
style_edition = "2021"in rustfmt.toml
# 1. Ensure Rust 1.88.0+
rustup update stable
rustc --version # Should show 1.88.0 or later
# 2. Check for static mut usage
grep -r "static mut" src/
# 3. Check for extern blocks
grep -r 'extern "C"' src/
# 4. Check for unsafe attributes
grep -r "#\[no_mangle\]" src/
grep -r "#\[link_section\]" src/# 1. Enable 2024 compatibility lints (while still on 2021)
# Add to lib.rs or main.rs:
# #![warn(rust_2024_compatibility)]
# 2. Fix all warnings
# 3. Run cargo fix
cargo fix --edition
# 4. Update Cargo.toml
# edition = "2024"
# 5. (Optional) Pin rustfmt style
# Add to rustfmt.toml:
# style_edition = "2021"
# 6. Run tests
cargo test --all
# 7. Verify no regressions
cargo clippy --all-targetsYes, but not immediately.
Rationale:
- Safety alignment: Edition 2024's safety improvements (static mut denial, unsafe extern) align with our security-first philosophy
- Future-proofing: The ecosystem will move to 2024; early adoption prevents technical debt
- Clean codebase: We already follow most best practices; migration should be minimal
| Phase | Action | When |
|---|---|---|
| Phase 1 | Audit codebase for breaking patterns | 0.1.x |
| Phase 2 | Enable rust_2024_compatibility lint |
0.1.x |
| Phase 3 | Fix all compatibility warnings | 0.2.x |
| Phase 4 | Migrate to Edition 2024 | 0.2.0 |
Before migrating:
- Ensure all
static mutuses are converted to safe alternatives - Update all
externblocks withunsafekeyword - Update all unsafe attributes to
#[unsafe(...)]syntax - Verify all tests pass with compatibility lints enabled
- Better compiler errors reduce debugging time
- Consistent lifetime rules reduce cognitive overhead
- Alignment with Rust community best practices
- One-time migration effort (~1-2 hours for tach-core)
- Potential for subtle bugs if lifetime changes aren't understood
Neutral to slightly positive. The one-time migration cost is low, and the ongoing benefits of clearer safety boundaries and better tooling will accelerate development.
- Rust 1.85.0 Release Announcement
- Rust 2024 Edition Guide
- RFC 3498: RPIT Lifetime Capture Rules
- Static Mut References Edition Guide
- Updating a Large Codebase to Rust 2024
"Safety is not an optional feature."
Project Tach - Rust Edition Migration Analysis