<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>README — rust</title>
<link>https://readme.news/tags/rust/</link>
<atom:link href="https://readme.news/tags/rust/feed.xml" rel="self" type="application/rss+xml"/>
<description>README pieces tagged rust.</description>
<language>en-us</language>
<lastBuildDate>Thu, 01 Oct 2026 13:20:31 +0000</lastBuildDate>
<item><title>Rust's six-week metronome, seven years on</title><link>https://readme.news/rusts-six-week-metronome-seven-years-on/</link><guid isPermaLink="true">https://readme.news/rusts-six-week-metronome-seven-years-on/</guid><pubDate>Thu, 27 Aug 2026 09:00:00 +0000</pubDate><description>A release every six weeks, no exceptions, no marketing cycle. What that cadence actually produces.</description><content:encoded><![CDATA[<p>Another Rust release lands today, six weeks after the last one, as it has since</p>
<ol><li>There is no launch event, the release notes are a list, and by tomorrow</li></ol>
<p>nobody will be discussing it.</p>
<p>That is the interesting part.</p>
<h2 id="what-a-metronome-produces">what a metronome produces<a class="anchor" href="#what-a-metronome-produces" aria-label="link to this section">#</a></h2>
<p><strong>Features ship when they are ready, not when a date needs filling.</strong> A fixed train with frequent departures means nothing is ever rushed to make a release — it just goes in the next one, six weeks later. Compare with an annual release, where missing the window costs a year and the pressure to ship something half-finished is enormous.</p>
<p><strong>No release is a big deal, so no release is risky.</strong> Upgrading across six weeks of change is routine. Upgrading across a year of change is a project. The frequency is what keeps each step small enough to be boring.</p>
<p><strong>Continuous improvement is invisible and enormous.</strong> Any single Rust release looks minor. The five-year delta is a different language: async in traits, let chains, <a class="xref" href="/rust-189-and-the-long-tail-of-const-generics/" title="Rust 1.89 and the long tail of const generics">const generics</a>, a rewritten <a class="xref" href="/rust-184-and-the-quiet-rewrite-underneath/" title="Rust 1.84 and the quiet rewrite underneath">trait solver</a>, dramatically better <a class="xref" href="/error-messages-are-a-user-interface/" title="Error messages are a user interface">error messages</a>, a linker that made everyone's builds faster without anyone opting in.</p>
<p>Nobody experienced that as an upgrade. It arrived six weeks at a time.</p>
<h2 id="the-part-that-makes-it-work">the part that makes it work<a class="anchor" href="#the-part-that-makes-it-work" aria-label="link to this section">#</a></h2>
<p>The cadence alone would not be enough. What makes it safe is the stability guarantee: code that compiled on stable keeps compiling. Breaking changes go through editions — opt-in, per-crate, with automated migration, on a multi-year cycle.</p>
<p>So the six-week train carries only additions and fixes. The scary changes ride a different, much slower vehicle, and you choose when to board.</p>
<p>That separation is the actual design insight, and it is the thing most projects miss when they copy the cadence without the guarantee.</p>
<h2 id="what-to-do-on-release-day">what to do on release day<a class="anchor" href="#what-to-do-on-release-day" aria-label="link to this section">#</a></h2>
<p>The same short list, every time:</p>
<ol><li><strong>Update and run your tests.</strong> <code>rustup update stable</code>. This is almost always uneventful, which is the point.</li><li><strong>Read the release notes for stabilised APIs.</strong> This is where you find the <code>std</code> function that lets you delete a dependency or an <code>unsafe</code> block.</li><li><strong>Run <code>cargo clippy</code>.</strong> New releases teach clippy new lints, and those lints find real bugs in code that has been compiling for years.</li><li><strong>Check <code>cargo build --timings</code></strong> occasionally. Compiler performance work lands continuously and you will never notice it unless you look.</li></ol>
<h2 id="the-transferable-lesson">the transferable lesson<a class="anchor" href="#the-transferable-lesson" aria-label="link to this section">#</a></h2>
<p>If you maintain anything other people depend on, the two-track structure is worth stealing regardless of your language:</p>
<ul><li><strong>A frequent, predictable, purely-additive train</strong> that is always safe to board.</li><li><strong>A separate, rare, opt-in mechanism</strong> for the changes that break things, with tooling to migrate.</li></ul>
<p>Most projects have neither — they ship when they ship, and breaking changes arrive mixed into ordinary releases. That combination is what makes upgrades scary, and upgrades being scary is what leaves everyone three versions behind.</p>
<p>Rust's release notes are boring because the interesting decisions were made about process, once, a decade ago.</p>]]></content:encoded></item><item><title>Rust's eleventh year and the shape of a finished language</title><link>https://readme.news/rusts-eleventh-year-and-the-shape-of-a-finished-language/</link><guid isPermaLink="true">https://readme.news/rusts-eleventh-year-and-the-shape-of-a-finished-language/</guid><pubDate>Tue, 20 Jan 2026 09:00:00 +0000</pubDate><description>Six-week releases, no breakage, and a backlog that is finally shorter than it was. What&#x27;s left is the hard part.</description><content:encoded><![CDATA[<p>Another <a class="xref" href="/rusts-six-week-metronome-seven-years-on/" title="Rust&#x27;s six-week metronome, seven years on">Rust release</a>, another set of const stabilizations and library additions. The release notes have been pleasantly dull for a year, which is the best thing you can say about a language with load-bearing production deployments.</p>
<p>Rather than enumerate, it is worth asking what "finished" would look like and how close this is.</p>
<h2 id="what-got-finished">what got finished<a class="anchor" href="#what-got-finished" aria-label="link to this section">#</a></h2>
<p>The list of "this obviously should work and does not" items has genuinely shrunk. Trait upcasting, let chains, RPIT capture, anonymous pipes, const in more places, SIMD intrinsics, async closures. Each of those was a multi-year open question and each is now just how the language works.</p>
<p>That is the signature of a language moving from the growth phase into the maintenance phase, and it is a good place to be. The compiler is faster than it was. The <a class="xref" href="/error-messages-are-a-user-interface/" title="Error messages are a user interface">error messages</a> remain the best in the industry. The tooling story — cargo, clippy, rustfmt, rust-analyzer — is coherent in a way that most languages never achieve.</p>
<h2 id="what-is-left-honestly">what is left, honestly<a class="anchor" href="#what-is-left-honestly" aria-label="link to this section">#</a></h2>
<p><strong>Async.</strong> Still the sharpest edge. Async traits work. Async closures work. What does not work smoothly: cancellation semantics that do not surprise you, async drop, <code>Send</code> bound propagation through generic async code, and the absence of a standard executor <a class="xref" href="/the-interface-is-the-product/" title="The interface is the product">interface</a> which fragments the ecosystem.</p>
<p>The <code>Pin</code> API remains the piece of Rust that experienced engineers most often describe as genuinely confusing, and the ergonomic improvements have been incremental.</p>
<p>This is the area where Rust is meaningfully harder than it needs to be, and where a new user is most likely to conclude the language is too complicated. It matters because async is how you write network services, and network services are most of software.</p>
<p><strong><a class="xref" href="/rust-189-and-the-long-tail-of-const-generics/" title="Rust 1.89 and the long tail of const generics">Const generic</a> expressions.</strong> <code>[T; N * 2]</code> still needs nightly. The blocker is real — deciding when two type-level expressions are equal is undecidable in general and the team will not ship a rule they cannot explain.</p>
<p><strong>GUI.</strong> Ten-plus years, several serious projects, no consensus. Partly a Rust problem: the borrow checker's relationship with the retained-mode widget tree that every traditional GUI framework uses is genuinely awkward. Partly not a Rust problem: <a class="xref" href="/cross-platform-is-a-promise-you-make-to-your-budget/" title="Cross-platform is a promise you make to your budget">cross-platform</a> GUI is unsolved everywhere.</p>
<p><strong>Compile times.</strong> Better every year. Still slower than Go. Structurally will remain so, because monomorphization and the optimization Rust performs are not free and are the reason the output is fast.</p>
<h2 id="the-adoption-picture-unsentimentally">the adoption picture, unsentimentally<a class="anchor" href="#the-adoption-picture-unsentimentally" aria-label="link to this section">#</a></h2>
<p><strong>Won decisively:</strong> systems programming, CLI tooling, JavaScript build tooling, cryptography implementations, embedded, <a class="xref" href="/the-component-model-and-the-plugin-problem/" title="The component model and the plugin problem">WebAssembly</a> targets, kernel drivers in both Linux and Windows.</p>
<p><strong>Winning slowly:</strong> backend services, where Go's simplicity and compile speed are a real competitor and where the async ergonomics cost is felt daily.</p>
<p><strong>Not winning and probably will not:</strong> application development, data science, scripting. Different constraints, different right answers.</p>
<p>That is a good outcome. A language does not need to win everything, and the places Rust won are the places where memory safety bugs were causing the most damage.</p>
<h2 id="the-thing-to-appreciate">the thing to appreciate<a class="anchor" href="#the-thing-to-appreciate" aria-label="link to this section">#</a></h2>
<p>Eleven years of six-week releases and no broken stable program. Three editions with automated migration and no ecosystem split. A governance structure that has survived real disagreements in public.</p>
<p>For a language that has changed as much as Rust has, that stability record is the actual achievement, and it is the reason people are willing to put infrastructure on it. Features are cheap. Trust is not.</p>
<h2 id="for-someone-deciding-whether-to-learn-it-in-2026">for someone deciding whether to learn it in 2026<a class="anchor" href="#for-someone-deciding-whether-to-learn-it-in-2026" aria-label="link to this section">#</a></h2>
<p>If you write systems software, networking infrastructure, embedded code, or anything where a memory safety bug is a security incident: yes, and you probably already know that.</p>
<p>If you write web applications: the async ergonomics are the thing you will fight, and Go or a good typed scripting language will make you more productive faster. Learn Rust anyway, eventually, because understanding ownership makes you better in every language.</p>
<p>If you tried it in 2021 and bounced off the compile times or the error messages: try again. Both are substantially different now.</p>]]></content:encoded></item><item><title>Rust 1.92 closes the year</title><link>https://readme.news/rust-192-closes-the-year/</link><guid isPermaLink="true">https://readme.news/rust-192-closes-the-year/</guid><pubDate>Fri, 12 Dec 2025 09:00:00 +0000</pubDate><description>More const, more stable APIs, and a language whose release notes have become pleasantly dull.</description><content:encoded><![CDATA[<p>Rust 1.92 shipped, closing out a year that included the 2024 edition, let chains, trait upcasting, LLD by default, and a steady march of const stabilizations.</p>
<p>Rather than enumerate this release, here is the year.</p>
<h2 id="what-landed-in-2025">what landed in 2025<a class="anchor" href="#what-landed-in-2025" aria-label="link to this section">#</a></h2>
<p><strong><a class="xref" href="/rust-2024-is-the-largest-edition-since-2018/" title="Rust 2024 is the largest edition since 2018">Rust 2024</a> edition</strong> (1.85, February). RPIT lifetime capture, unsafe attributes, tail expression temporary scope, <code>gen</code> reserved. The largest edition so far and the migration was mostly mechanical.</p>
<p><strong>Trait upcasting</strong> (1.86, April). Eight years open. Deleted a category of boilerplate from every plugin system in the ecosystem.</p>
<p><strong>Anonymous pipes in std</strong> (1.87, May), on the tenth anniversary of 1.0.</p>
<p><strong>Let chains</strong> (1.88, June). The single most requested ergonomic improvement, unblocked by the edition's scope changes.</p>
<p><strong>x86 SIMD stabilizations</strong> (1.89, August). Removed a real competitive disadvantage against C++ for numerical work.</p>
<p><strong>LLD as the default linker on Linux</strong> (1.90, September). Build times improved for everyone, most of whom did not notice a release note.</p>
<p><strong>Continuous const expansion</strong> across every release, moving more computation to compile time.</p>
<h2 id="the-shape-of-the-year">the shape of the year<a class="anchor" href="#the-shape-of-the-year" aria-label="link to this section">#</a></h2>
<p>No single dramatic feature. A lot of things that had been open for years finally closing.</p>
<p>That is what a language looks like when it has passed the phase of adding capability and entered the phase of finishing what it started. The backlog of "this should work and does not" is getting shorter.</p>
<h2 id="what-is-still-open">what is still open<a class="anchor" href="#what-is-still-open" aria-label="link to this section">#</a></h2>
<p><strong>Async.</strong> Async traits work but the ergonomics around lifetimes, <code>Send</code> bounds, and cancellation remain the sharpest edges in the language. Async closures landed this year and help. The full story — async drop, better cancellation semantics, a standard executor <a class="xref" href="/the-interface-is-the-product/" title="The interface is the product">interface</a> — is still ahead.</p>
<p><strong><a class="xref" href="/rust-189-and-the-long-tail-of-const-generics/" title="Rust 1.89 and the long tail of const generics">Const generic</a> expressions.</strong> <code>[T; N * 2]</code> still requires nightly. The blocker is the type-equality question and it is genuinely hard.</p>
<p><strong>GUI.</strong> Ten years of effort, several promising projects, no consensus. This is partly a Rust problem and mostly the fact that <a class="xref" href="/cross-platform-is-a-promise-you-make-to-your-budget/" title="Cross-platform is a promise you make to your budget">cross-platform</a> GUI is unsolved everywhere.</p>
<p><strong>Compile times.</strong> Better every year, still slower than Go, probably always will be for structural reasons.</p>
<h2 id="the-adoption-picture">the adoption picture<a class="anchor" href="#the-adoption-picture" aria-label="link to this section">#</a></h2>
<p>Rust in 2025 is: the default for new systems software, a significant and growing presence in the Linux and Windows kernels, the implementation language for most new JavaScript tooling, and increasingly common in infrastructure that used to be Go or C++.</p>
<p>It is not the default for application development and shows no sign of becoming so. That is fine. It was never the goal and the systems niche is where the memory-safety bugs were.</p>
<h2 id="the-thing-worth-appreciating">the thing worth appreciating<a class="anchor" href="#the-thing-worth-appreciating" aria-label="link to this section">#</a></h2>
<p>Rust ships every six weeks and has never broken a stable program. There has been no Python 3. There has been no C++11-style decade-long adoption lag.</p>
<p>For a language that has changed as much as Rust has in ten years, that is a remarkable engineering and governance achievement, and it is the reason people are willing to build load-bearing infrastructure in it.</p>
<p>Boring release notes are the reward for getting the hard part right.</p>]]></content:encoded></item><item><title>Rust 1.91 and the slow work of shrinking unsafe</title><link>https://readme.news/rust-191-and-the-slow-work-of-shrinking-unsafe/</link><guid isPermaLink="true">https://readme.news/rust-191-and-the-slow-work-of-shrinking-unsafe/</guid><pubDate>Fri, 31 Oct 2025 09:00:00 +0000</pubDate><description>More const, more stable APIs, and an ecosystem that keeps finding ways to need less unsafe code.</description><content:encoded><![CDATA[<p>Rust 1.91 shipped this week with the usual batch of API stabilizations and const improvements. Rather than enumerate them, it is worth looking at the trend they are part of, because it is the most underrated thing about Rust's development.</p>
<h2 id="the-pattern">the pattern<a class="anchor" href="#the-pattern" aria-label="link to this section">#</a></h2>
<p>A large fraction of Rust's per-release API additions exist to let you delete an <code>unsafe</code> block.</p>
<p>Some recent examples across the last year of releases:</p>
<ul><li><code>HashMap::get_disjoint_mut</code> — previously required unsafe or a clumsy dance.</li><li><code>&lt;[T]&gt;::as_chunks</code> — previously a transmute or a manual loop with unchecked indexing.</li><li><code>Vec::extract_if</code> — previously either an allocation or unsafe in-place work.</li><li><code>std::io::pipe</code> — previously platform-specific unsafe FFI.</li><li>Const-stabilized functions across the library — previously a <code>lazy_static</code> or a build script.</li></ul>
<p>None of these are exciting individually. Cumulatively they are the mechanism by which the amount of unsafe code in the average Rust program keeps going down.</p>
<h2 id="why-this-matters-more-than-features">why this matters more than features<a class="anchor" href="#why-this-matters-more-than-features" aria-label="link to this section">#</a></h2>
<p>The value proposition of Rust is memory safety without a garbage collector. Every <code>unsafe</code> block is a hole in that guarantee — a place where the compiler stops checking and a human is asserting correctness.</p>
<p>Studies of real-world Rust code consistently find that most unsafe usage falls into a small number of patterns, and that a majority of those patterns exist because the safe standard library did not offer the operation.</p>
<p>So the library team's strategy is: find the patterns, provide safe equivalents, watch the unsafe count fall. It works, and it is measurable.</p>
<p>The remaining unsafe concentrates in the places where it belongs — FFI, hardware interaction, and hand-optimized data structures — where it is reviewed by people who know what they are doing, in crates that are audited.</p>
<h2 id="the-const-story-specifically">the const story specifically<a class="anchor" href="#the-const-story-specifically" aria-label="link to this section">#</a></h2>
<p>Const stabilization is the other steady drip. Every release moves more functions into <code>const fn</code>, meaning they can run at compile time.</p>
<p>The practical effect is that more computation moves from runtime to compile time, and more static data can be computed rather than hand-written. Lookup tables, parsed configuration, precomputed constants — all of it can now be expressed as code that runs during compilation.</p>
<div class="code"><span class="code-lang">rust</span><pre><code class="lang-rust">const TABLE: [u32; 256] = {
    let mut t = [0u32; 256];
    let mut i = 0;
    while i &lt; 256 { t[i] = crc_entry(i as u8); i += 1; }
    t
};</code></pre></div>
<p>That would have required a build script or a generated file a few years ago.</p>
<h2 id="the-honest-limitations">the honest limitations<a class="anchor" href="#the-honest-limitations" aria-label="link to this section">#</a></h2>
<p><a class="xref" href="/rust-189-and-the-long-tail-of-const-generics/" title="Rust 1.89 and the long tail of const generics">Const generics</a> still cannot do arithmetic in type position without nightly. Async in traits works but has sharp edges around lifetimes and <code>Send</code> bounds. The GUI ecosystem remains unsettled after a decade of attempts.</p>
<p>None of those are getting fixed this release, or probably next release. Rust's development model trades speed for not making mistakes it cannot undo, and the consequence is that the hard problems stay open for a long time.</p>
<p>That is a defensible trade for a language with a stability guarantee, and it is genuinely frustrating if you are blocked on one of them.</p>
<h2 id="the-meta-observation">the meta-observation<a class="anchor" href="#the-meta-observation" aria-label="link to this section">#</a></h2>
<p>If you want to evaluate a language's health, do not look at its feature announcements. Look at whether the amount of dangerous code required to do ordinary things is going up or down.</p>
<p>By that measure Rust is doing better than almost anything else, and it is doing it in increments so small that nobody writes headlines about them.</p>]]></content:encoded></item><item><title>Rust 1.90 and the linker nobody talks about</title><link>https://readme.news/rust-190-and-the-linker-nobody-talks-about/</link><guid isPermaLink="true">https://readme.news/rust-190-and-the-linker-nobody-talks-about/</guid><pubDate>Fri, 19 Sep 2025 09:00:00 +0000</pubDate><description>LLD becomes the default linker on x86-64 Linux. Link times drop and nobody notices, which is the point.</description><content:encoded><![CDATA[<p>Rust 1.90 makes LLD the default linker for <code>x86_64-unknown-linux-gnu</code>. This is a build-time performance change with no user-facing API and it is one of the more useful things to ship this year.</p>
<h2 id="why-linking-matters">why linking matters<a class="anchor" href="#why-linking-matters" aria-label="link to this section">#</a></h2>
<p>For a large Rust binary, linking is frequently the dominant cost of an incremental build. You change one line, the compiler recompiles one crate quickly, and then the linker spends several seconds stitching together a hundred megabytes of object files and debug information.</p>
<p>GNU <code>ld</code> is old, single-threaded in the parts that matter, and was designed for a different era of binary sizes. <code>lld</code> is parallel, substantially faster, and has been production-ready for years — it is the default on several other platforms already.</p>
<p>Reported improvements vary by project, with the largest gains on debug builds of large dependency trees. Two to five times faster linking is a common range. If your edit-compile-run loop is four seconds and linking was two of them, you feel this every single time.</p>
<h2 id="how-to-check">how to check<a class="anchor" href="#how-to-check" aria-label="link to this section">#</a></h2>
<div class="code"><span class="code-lang">bash</span><pre><code class="lang-bash">cargo build --timings</code></pre></div>
<p>Opens an HTML report showing where time went, including link time as a distinct phase. Most people have never looked at this and are surprised by what it says.</p>
<p>If you were already opting into <code>lld</code> or <code>mold</code> via <code>.cargo/config.toml</code>, nothing changes for you. If you were not — which is most people, because the configuration was obscure and required knowing it existed — you get the improvement for free on upgrade.</p>
<h2 id="the-general-lesson">the general lesson<a class="anchor" href="#the-general-lesson" aria-label="link to this section">#</a></h2>
<p>Defaults are the most impactful thing a toolchain ships.</p>
<p>A faster linker has been available for years. Anyone could have configured it. The instructions were in a blog post. Almost nobody did, because it required knowing the option existed, knowing it was safe, and caring enough to edit a config file.</p>
<p>Changing the default delivers the improvement to everyone at once. That is worth more than a decade of documentation.</p>
<p>This generalizes. If you maintain a tool and you find yourself writing documentation explaining how to enable a better behavior, ask whether the better behavior should be the default. The answer is usually yes, and the reason it is not is usually caution about breaking a small number of unusual setups — which is a real concern that should be handled with a flag to opt <em>out</em>, not a flag to opt in.</p>
<h2 id="the-rest-of-190">the rest of 1.90<a class="anchor" href="#the-rest-of-190" aria-label="link to this section">#</a></h2>
<ul><li><strong>Cargo workspace publishing</strong> — <code>cargo publish --workspace</code> publishes multiple interdependent crates in the correct order. Anyone maintaining a multi-crate project has written a shell script for this. Now you can delete it.</li><li><strong>Demoted target tiers</strong> for several less-used platforms.</li><li><strong><code>x86_64-apple-darwin</code> demoted to tier 2</strong> with host tools still provided, which reflects where Apple hardware has actually gone.</li><li>The usual const stabilizations and API additions.</li></ul>
<h2 id="the-trend-line">the trend line<a class="anchor" href="#the-trend-line" aria-label="link to this section">#</a></h2>
<p>Rust's reputation for slow compilation is the single most cited objection to adopting it, and it has been steadily addressed for years: incremental compilation, parallel front-end work, the new <a class="xref" href="/rust-184-and-the-quiet-rewrite-underneath/" title="Rust 1.84 and the quiet rewrite underneath">trait solver</a>, better <a class="xref" href="/caching-is-the-only-optimization-that-reliably-works/" title="Caching is the only optimization that reliably works">caching</a>, and now the linker.</p>
<p>Compile times are meaningfully better than they were three years ago and still slower than Go. That gap is partly fundamental — monomorphization and the amount of optimization Rust does are not free — and partly still addressable.</p>
<p>Anyone who tried Rust in 2021 and bounced off the build times should try again. The numbers are different now.</p>]]></content:encoded></item><item><title>Rust 1.89 and the long tail of const generics</title><link>https://readme.news/rust-189-and-the-long-tail-of-const-generics/</link><guid isPermaLink="true">https://readme.news/rust-189-and-the-long-tail-of-const-generics/</guid><pubDate>Fri, 08 Aug 2025 09:00:00 +0000</pubDate><description>Inferred array lengths in const generic position, plus x86 SIMD stabilizations that matter for anyone doing math.</description><content:encoded><![CDATA[<p>Rust 1.89 is out. The headline is explicitly inferred const generic arguments — you can now write <code>_</code> where a const generic parameter would go and let inference figure it out.</p>
<div class="code"><span class="code-lang">rust</span><pre><code class="lang-rust">fn frobnicate&lt;const N: usize&gt;(arr: [u8; N]) -&gt; [u8; N] { /* ... */ }

let data = [1, 2, 3, 4];
let out: [u8; _] = frobnicate(data);   // N inferred as 4</code></pre></div>
<p>Previously you either wrote the number, which duplicated information the compiler already had, or restructured to avoid needing it. Small change, removes a real papercut, and it composes well with the growing amount of const-generic code in the ecosystem.</p>
<h2 id="the-simd-stabilizations">the SIMD stabilizations<a class="anchor" href="#the-simd-stabilizations" aria-label="link to this section">#</a></h2>
<p>A large batch of x86 intrinsics stabilized, including AVX-512 families. This matters for a specific and growing population: people writing hand-tuned kernels in Rust for <a class="xref" href="/compression-is-underrated/" title="Compression is underrated">compression</a>, encoding, cryptography, and increasingly ML inference.</p>
<p>Before this, using these intrinsics required nightly. Which meant that a production library wanting AVX-512 paths had to either require nightly — a non-starter for most consumers — or drop to C via FFI.</p>
<p>That was a genuine competitive disadvantage against C++ for numerical work and it is now mostly gone.</p>
<p>The pattern for using them safely:</p>
<div class="code"><span class="code-lang">rust</span><pre><code class="lang-rust">if is_x86_feature_detected!("avx512f") {
    unsafe { fast_path_avx512(data) }
} else if is_x86_feature_detected!("avx2") {
    unsafe { fast_path_avx2(data) }
} else {
    scalar_path(data)
}</code></pre></div>
<p>Runtime detection, multiple implementations, scalar fallback. Tedious and correct. <code>std::simd</code> remains unstable for the portable abstraction, which is the thing most people actually want and which continues to take a long time.</p>
<h2 id="also-in-the-release">also in the release<a class="anchor" href="#also-in-the-release" aria-label="link to this section">#</a></h2>
<ul><li><strong><code>unsafe</code> attributes</strong> get more coverage, continuing the 2024 edition direction.</li><li><strong><code>Result::flatten</code></strong> stabilizes. Small and frequently wanted.</li><li><strong>Cargo</strong> now supports <code>--compile-time-deps</code> for building only what is needed for procedural macros and build scripts, which speeds up some tooling workflows meaningfully.</li><li><strong>i686 targets</strong> raise their baseline CPU requirement, which will affect approximately nobody and will affect them a lot.</li></ul>
<h2 id="the-const-generics-arc-for-context">the const generics arc, for context<a class="anchor" href="#the-const-generics-arc-for-context" aria-label="link to this section">#</a></h2>
<p>Const generics were stabilized in a minimal form in Rust 1.51, four years ago. Since then the feature has been growing capability incrementally: first only integers, then inference improvements, then better <a class="xref" href="/error-messages-are-a-user-interface/" title="Error messages are a user interface">error messages</a>, now this.</p>
<p>The full feature — const generic expressions, where you can write <code>[T; N * 2]</code> — is still unstable and has been "coming soon" for a long time. The blocker is that arbitrary const expressions in type position require deciding when two type-level expressions are equal, which is undecidable in general and requires drawing a careful line.</p>
<p>Rust's approach to this has consistently been: ship the decidable subset, leave the hard part open, do not paint yourself into a corner. It is slow and it has not produced an unsound <a class="xref" href="/type-systems-and-the-cost-of-being-right/" title="Type systems and the cost of being right">type system</a>, which is more than several languages with similar features can say.</p>]]></content:encoded></item><item><title>Rust 1.88 ships let chains, and a decade-old papercut closes</title><link>https://readme.news/rust-188-ships-let-chains-and-a-decade-old-papercut-closes/</link><guid isPermaLink="true">https://readme.news/rust-188-ships-let-chains-and-a-decade-old-papercut-closes/</guid><pubDate>Mon, 30 Jun 2025 09:00:00 +0000</pubDate><description>`if let A = a &amp;&amp; let B = b` finally compiles. Also naked functions and automatic cargo cache cleaning.</description><content:encoded><![CDATA[<p>Rust 1.88 stabilizes let chains in the 2024 edition. If you have written Rust for more than a week you have wanted this.</p>
<h2 id="the-feature">the feature<a class="anchor" href="#the-feature" aria-label="link to this section">#</a></h2>
<p>You can now chain <code>let</code> bindings with boolean conditions in <code>if</code> and <code>while</code>:</p>
<div class="code"><span class="code-lang">rust</span><pre><code class="lang-rust">if let Some(user) = session.user()
    &amp;&amp; user.is_admin()
    &amp;&amp; let Ok(perms) = load_permissions(user.id)
    &amp;&amp; perms.contains(Permission::Delete)
{
    delete_record(id)?;
}</code></pre></div>
<p>Before this you wrote the pyramid:</p>
<div class="code"><span class="code-lang">rust</span><pre><code class="lang-rust">if let Some(user) = session.user() {
    if user.is_admin() {
        if let Ok(perms) = load_permissions(user.id) {
            if perms.contains(Permission::Delete) {
                delete_record(id)?;
            }
        }
    }
}</code></pre></div>
<p>Or you restructured with early returns and helper functions, which is often better anyway but was not always applicable — particularly inside a match arm or a loop body where you cannot return.</p>
<h2 id="the-edition-caveat">the edition caveat<a class="anchor" href="#the-edition-caveat" aria-label="link to this section">#</a></h2>
<p>Let chains require the 2024 edition. This is not arbitrary: the tail-expression temporary scope changes in 2024 are what make the drop semantics of a chained <code>let</code> well-defined. In earlier editions the temporaries created in the chain would live too long and the borrow behavior would be surprising in ways that could not be fixed without a breaking change.</p>
<p>This is a nice demonstration of what editions are actually for. A feature was blocked for years on a semantic problem; the edition boundary let them fix the semantics; the feature shipped.</p>
<h2 id="the-rest-of-the-release">the rest of the release<a class="anchor" href="#the-rest-of-the-release" aria-label="link to this section">#</a></h2>
<p><strong>Naked functions.</strong> <code>#[unsafe(naked)]</code> with a <code>naked_asm!</code> body produces a function with no compiler-generated prologue or epilogue. You need this for interrupt handlers, syscall entry points, and context switching. Previously it required an external crate with fragile assumptions.</p>
<p><strong>Automatic cargo cache cleaning.</strong> Cargo now garbage-collects unused files in its global cache. If you have been running <code>cargo clean</code> on a cron job or watching <code>~/.cargo/registry</code> grow to forty gigabytes, that is handled now.</p>
<p><strong><code>cfg(true)</code> and <code>cfg(false)</code></strong> as boolean literals in configuration predicates. Small, and it removes a genuinely silly workaround people were using.</p>
<p><strong><code>Cell::update</code></strong>, several <code>const</code> stabilizations, and the usual batch of API additions.</p>
<h2 id="the-pattern-in-rusts-release-cadence">the pattern in Rust's release cadence<a class="anchor" href="#the-pattern-in-rusts-release-cadence" aria-label="link to this section">#</a></h2>
<p>Rust ships every six weeks, forever, with no marketing cycle and no "major release." What that produces is a language that improves continuously in small increments, where any given release seems minor and the five-year delta is enormous.</p>
<p>Compare Rust in 2020 — no async traits, no GATs, no let chains, no let-else, no <a class="xref" href="/rust-189-and-the-long-tail-of-const-generics/" title="Rust 1.89 and the long tail of const generics">const generics</a> worth using, a much worse compiler error story — to Rust today. The difference is large and there was never a moment where it happened.</p>
<p>That is a good way to run a language. It is also why "should I learn Rust" gets different answers from people who last tried it at different times, and why the answer today is different from the answer three years ago.</p>]]></content:encoded></item><item><title>Rust 1.87, and the standard library grows an anonymous pipe</title><link>https://readme.news/rust-187-and-the-standard-library-grows-an-anonymous-pipe/</link><guid isPermaLink="true">https://readme.news/rust-187-and-the-standard-library-grows-an-anonymous-pipe/</guid><pubDate>Thu, 15 May 2025 09:00:00 +0000</pubDate><description>`std::io::pipe`, `asm!` jumping to Rust code, and the tenth anniversary of 1.0.</description><content:encoded><![CDATA[<p>Rust 1.87 shipped today, ten years and one day after Rust 1.0. The release is a good one and the anniversary is worth a paragraph at the end.</p>
<h2 id="anonymous-pipes">anonymous pipes<a class="anchor" href="#anonymous-pipes" aria-label="link to this section">#</a></h2>
<p><code>std::io::pipe()</code> gives you a <a class="xref" href="/cross-platform-is-a-promise-you-make-to-your-budget/" title="Cross-platform is a promise you make to your budget">cross-platform</a> anonymous pipe in the standard library:</p>
<div class="code"><span class="code-lang">rust</span><pre><code class="lang-rust">use std::io::pipe;
use std::process::Command;

let (mut reader, writer) = pipe()?;
let mut child = Command::new("ls")
    .stdout(writer.try_clone()?)
    .stderr(writer)
    .spawn()?;

let mut merged = String::new();
reader.read_to_string(&amp;mut merged)?;
child.wait()?;</code></pre></div>
<p>Interleaving stdout and stderr into one stream, in order, has been a recurring annoyance requiring either a platform-specific <code>unsafe</code> block or a dependency. Now it is three lines of <code>std</code>.</p>
<h2 id="asm-can-jump-to-rust"><code>asm!</code> can jump to Rust<a class="anchor" href="#asm-can-jump-to-rust" aria-label="link to this section">#</a></h2>
<p>Inline assembly can now use labels that jump back into Rust code. This is deeply niche and matters enormously to the handful of people writing kernels, bootloaders, and hypervisors in Rust — which, at this point, is a real number of people.</p>
<h2 id="the-smaller-items">the smaller items<a class="anchor" href="#the-smaller-items" aria-label="link to this section">#</a></h2>
<ul><li><strong><code>Vec::extract_if</code> and <code>LinkedList::extract_if</code></strong> — remove and yield elements matching a predicate, in place, without collecting into a temporary.</li><li><strong><code>&lt;[T]&gt;::as_chunks</code></strong> — split a slice into fixed-size arrays, safely, with the remainder returned separately. Useful for everything from SIMD prep to parsing.</li><li><strong><code>i686-pc-windows-gnu</code> demoted</strong> to tier 2 without host tools.</li><li>Numerous <strong><code>const fn</code> stabilizations</strong>, which continue at a steady drip.</li></ul>
<h2 id="ten-years">ten years<a class="anchor" href="#ten-years" aria-label="link to this section">#</a></h2>
<p>Rust 1.0 shipped on 15 May 2015. The stability promise made then has held: code written against 1.0 still compiles, editions handled the syntax evolution without splitting the ecosystem, and there has been no Python 3 moment.</p>
<p>That is the achievement. Not the borrow checker, which is what everybody talks about. The borrow checker is a good idea that several research languages had first. What Rust did that no research language did was ship it with a package manager people liked, a stability guarantee people trusted, and an upgrade path that did not require rewriting anything.</p>
<p>Where it landed in a decade: Linux kernel drivers, Windows kernel components, Android's Bluetooth and media stacks, the core of several CDNs, most new CLI tooling in the JavaScript ecosystem, and a substantial share of new infrastructure software generally.</p>
<p>Where it did not land: application development, mostly. The GUI story is still unsettled after ten years of effort. Async Rust is still the sharpest edge in the language, and the "async traits and lifetime puzzles" complaint from 2020 is only partially resolved.</p>
<p>The honest summary: Rust won the systems niche decisively and did not win general-purpose programming, which is fine, because it was never going to and the systems niche is where the memory-safety bugs were.</p>
<p>Ten more years of the same trajectory and half the internet's infrastructure will be written in it.</p>]]></content:encoded></item><item><title>Rust 1.86 lands trait upcasting after eight years</title><link>https://readme.news/rust-186-lands-trait-upcasting-after-eight-years/</link><guid isPermaLink="true">https://readme.news/rust-186-lands-trait-upcasting-after-eight-years/</guid><pubDate>Thu, 03 Apr 2025 09:00:00 +0000</pubDate><description>You can finally coerce `dyn Sub` to `dyn Super`. Also: `HashMap::get_disjoint_mut`, and a soundness fix worth reading.</description><content:encoded><![CDATA[<p>Rust 1.86 stabilizes trait upcasting, a feature that has been open since 2017 and that everyone who has written a plugin system in Rust has stubbed their toe on.</p>
<h2 id="the-problem-it-fixes">the problem it fixes<a class="anchor" href="#the-problem-it-fixes" aria-label="link to this section">#</a></h2>
<p>Given a supertrait relationship, you could not coerce a trait object of the subtrait to a trait object of the supertrait:</p>
<div class="code"><span class="code-lang">rust</span><pre><code class="lang-rust">trait Animal { fn name(&amp;self) -&gt; String; }
trait Dog: Animal { fn bark(&amp;self); }

fn describe(a: &amp;dyn Animal) { println!("{}", a.name()); }

fn use_dog(d: &amp;dyn Dog) {
    describe(d);   // ERROR before 1.86
}</code></pre></div>
<p>The workaround was a manual <code>as_animal(&amp;self) -&gt; &amp;dyn Animal</code> method on every trait, implemented identically in every impl, existing purely to launder a pointer. Anyone building an ECS, a plugin registry, or any kind of heterogeneous object graph has written that boilerplate.</p>
<p>As of 1.86 the coercion just works. The vtable layout was changed so a subtrait's vtable embeds a pointer to the supertrait's, which is why this took eight years — it is a change to the ABI of trait objects, and getting it right without regressing size or dispatch cost required several redesigns.</p>
<h2 id="the-soundness-fix">the soundness fix<a class="anchor" href="#the-soundness-fix" aria-label="link to this section">#</a></h2>
<p>Also in this release: a long-standing hole around <code>Box&lt;T&gt;</code> in the presence of <code>Deref</code> implementations that could produce aliasing violations under certain generic code. The details are in the release notes and are worth reading if you write <code>unsafe</code>. If you do not write <code>unsafe</code>, this fixed a bug you never knew you could have had.</p>
<h2 id="the-small-ergonomics">the small ergonomics<a class="anchor" href="#the-small-ergonomics" aria-label="link to this section">#</a></h2>
<p><strong><code>HashMap::get_disjoint_mut</code></strong> — get mutable references to multiple distinct keys at once, checked at runtime for disjointness:</p>
<div class="code"><span class="code-lang">rust</span><pre><code class="lang-rust">let [a, b] = map.get_disjoint_mut(["alice", "bob"]);</code></pre></div>
<p>Previously this required either two lookups with an intermediate remove, or <code>RefCell</code>, or an <a class="xref" href="/rust-191-and-the-slow-work-of-shrinking-unsafe/" title="Rust 1.91 and the slow work of shrinking unsafe">unsafe block</a>, all to express something that is obviously fine.</p>
<p><strong><code>{float}::next_down</code> and <code>next_up</code></strong> — the adjacent representable float. Niche, and if you need it you <em>really</em> need it.</p>
<p><strong>Target tier changes</strong> — several targets moved up and down the support tiers, as always. Check if you cross-compile to anything unusual.</p>
<h2 id="the-pattern">the pattern<a class="anchor" href="#the-pattern" aria-label="link to this section">#</a></h2>
<p>Rust's stabilization pace on "obvious" features looks glacial from the outside and the reason is almost always the same: the obvious feature interacts with three other features in a way that produces unsoundness, and the team will not ship unsound.</p>
<p>Trait upcasting is a good example. The naive implementation is easy. The implementation that does not break <code>dyn</code> compatibility rules, does not bloat vtables, does not break existing <code>unsafe</code> code that assumed a layout, and composes correctly with associated types took most of a decade.</p>
<p>You can find that frustrating and still prefer it to the alternative.</p>]]></content:encoded></item><item><title>Linux 6.14 and Rust in the kernel, one driver at a time</title><link>https://readme.news/linux-614-and-rust-in-the-kernel-one-driver-at-a-time/</link><guid isPermaLink="true">https://readme.news/linux-614-and-rust-in-the-kernel-one-driver-at-a-time/</guid><pubDate>Mon, 24 Mar 2025 09:00:00 +0000</pubDate><description>Faster fuse, better hardware support, and a Rust for Linux effort that keeps advancing through genuine disagreement.</description><content:encoded><![CDATA[<p>Linux 6.14 is out. The release is modest by kernel standards — improved AMD and Intel graphics support, <code>ntsync</code> for better Wine and Proton performance, more filesystem work — but the ongoing story underneath is Rust, and this cycle had one of its sharper moments.</p>
<h2 id="where-rust-for-linux-actually-is">where Rust for Linux actually is<a class="anchor" href="#where-rust-for-linux-actually-is" aria-label="link to this section">#</a></h2>
<p>The infrastructure has been merged for several cycles. What has been slower is the <em>bindings</em>: the safe Rust abstractions over kernel C APIs that a driver author would actually use. You cannot write a Rust network driver until somebody writes a sound Rust abstraction over the network device API, and doing that correctly requires deep agreement between the Rust folks and the maintainer of the subsystem in question.</p>
<p>That is where the friction is, and it is not primarily technical.</p>
<p>The concern from some longtime maintainers is legitimate and worth stating plainly: if a Rust abstraction wraps a C API, then a change to the C API can break the Rust side, and now the C maintainer is on the hook for a language they did not sign up to learn. Multiply across dozens of subsystems and you have a real maintenance burden distributed to people who did not choose it.</p>
<p>The counter-position, also legitimate: memory safety bugs in drivers are a substantial and ongoing fraction of kernel CVEs, drivers are where most kernel code lives, and drivers are exactly the place where a language with compile-time memory safety pays off most.</p>
<p>Linus's stated position has been consistent — Rust is welcome, the experiment continues, and maintainers are not required to accept Rust in their subsystems but also are not permitted to block it purely on preference. That is a politically difficult line to hold and he has mostly held it.</p>
<h2 id="the-technical-state">the technical state<a class="anchor" href="#the-technical-state" aria-label="link to this section">#</a></h2>
<p>What exists and works today:</p>
<ul><li>Kernel allocation, error handling, and the <code>Result</code>-based error propagation.</li><li>Enough abstraction for real drivers — the Android Binder rewrite and the Asahi Linux GPU driver are both substantial Rust codebases running in production on real hardware.</li><li><code>pin-init</code>, which solves the self-referential-struct problem that makes kernel data structures awkward in safe Rust.</li></ul>
<p>What is still hard:</p>
<ul><li>The compiler version floor keeps moving, which distributions dislike.</li><li>Rust's story for <code>no_std</code> allocation failure handling required work that only exists because the kernel needed it.</li><li>Architecture coverage. Rust needs an LLVM backend for the target, which rules out several architectures the kernel still supports.</li></ul>
<h2 id="the-honest-assessment">the honest assessment<a class="anchor" href="#the-honest-assessment" aria-label="link to this section">#</a></h2>
<p>This will take longer than advocates hope and will succeed more than skeptics expect. The pattern is already visible: new drivers in Rust where a maintainer is willing, C everywhere else, indefinitely. Nobody is rewriting the VFS.</p>
<p>That is a fine outcome. The goal was never a Rust kernel. It was to stop shipping new memory-safety bugs in the parts of the kernel that get the most new code, and on that specific goal the trajectory is good.</p>]]></content:encoded></item><item><title>Rust 2024 is the largest edition since 2018</title><link>https://readme.news/rust-2024-is-the-largest-edition-since-2018/</link><guid isPermaLink="true">https://readme.news/rust-2024-is-the-largest-edition-since-2018/</guid><pubDate>Thu, 20 Feb 2025 09:00:00 +0000</pubDate><description>New match ergonomics, `gen` blocks reserved, RPIT lifetime capture changes, and unsafe attributes. Here&#x27;s what will break.</description><content:encoded><![CDATA[<p>Rust 1.85 shipped today and with it the Rust 2024 edition — the third edition since 1.0 and the most substantial one. Editions are opt-in per crate and do not split the ecosystem: a 2015 crate and a 2024 crate link together fine. But migrating your own code will surface real changes.</p>
<p>Run <code>cargo fix --edition</code> first. It handles most of it. Here is what it cannot.</p>
<h2 id="the-changes-that-will-bite">the changes that will bite<a class="anchor" href="#the-changes-that-will-bite" aria-label="link to this section">#</a></h2>
<p><strong>RPIT lifetime capture.</strong> In edition 2024, <code>-&gt; impl Trait</code> in a free function captures <em>all</em> in-scope lifetime parameters by default, matching what <code>async fn</code> already did. Previously it captured only type parameters, and you had to add a <code>+ '_</code> or a witness parameter to opt in.</p>
<p>This makes the common case work without incantations. It also means some signatures that compiled before now fail borrow checking, because the returned opaque type is now considered to borrow something it did not before. The fix is the new <code>use&lt;..&gt;</code> syntax to state precisely what is captured:</p>
<div class="code"><span class="code-lang">rust</span><pre><code class="lang-rust">fn parse&lt;'a&gt;(input: &amp;'a str) -&gt; impl Iterator&lt;Item = &amp;'a str&gt; + use&lt;'a&gt; {
    input.split(',')
}</code></pre></div>
<p><strong><code>unsafe</code> attributes.</strong> <code>#[no_mangle]</code>, <code>#[export_name]</code> and <code>#[link_section]</code> are now written <code>#[unsafe(no_mangle)]</code>. These attributes can violate soundness — <code>no_mangle</code> can collide with a symbol the linker resolves differently — and the language now says so out loud. Mechanical fix, applied by <code>cargo fix</code>.</p>
<p><strong><code>unsafe extern</code> blocks.</strong> Declaring a foreign function is an unsafe assertion about its signature. Now spelled that way.</p>
<p><strong><code>gen</code> is a reserved keyword.</strong> Generator blocks are coming; the keyword is reserved now so it can land without another edition. If you have a variable named <code>gen</code>, rename it. Yes, this affects more code than you would think.</p>
<p><strong>Tail expression temporary scope.</strong> Temporaries in the final expression of a block now drop before local variables rather than after. This fixes a class of surprising deadlocks with <code>MutexGuard</code> in a tail position, and changes drop order in ways that could matter if you have <code>Drop</code> impls with side effects.</p>
<p><strong><code>if let</code> temporary scope.</strong> Temporaries in an <code>if let</code> scrutinee now drop at the end of the <code>if let</code>, not at the end of the enclosing statement. Same category: fixes real deadlocks, changes observable drop timing.</p>
<p><strong>Never type fallback.</strong> <code>!</code> now falls back to <code>!</code> instead of <code>()</code> in more positions. Mostly this makes bad code fail to compile rather than silently doing something odd.</p>
<p><strong><code>Cargo</code> resolver v3</strong> becomes the default, which is the MSRV-aware resolver from 1.84.</p>
<h2 id="should-you-migrate">should you migrate<a class="anchor" href="#should-you-migrate" aria-label="link to this section">#</a></h2>
<p>Yes, but not urgently and not during a crunch. The migration is mostly mechanical; the RPIT changes and the drop-order changes are the two places where you need to actually think.</p>
<p>Do it on a quiet week, run your full test suite, and pay specific attention to anything with a <code>Drop</code> impl that touches shared state. That is where a silently-changed behavior can hide.</p>
<h2 id="the-meta-point-about-editions">the meta-point about editions<a class="anchor" href="#the-meta-point-about-editions" aria-label="link to this section">#</a></h2>
<p>Rust's edition mechanism remains the best answer anyone has shipped to the problem of evolving a language without breaking the world. C++ cannot do this. Python's answer took a decade and cost the community enormously. Rust gets to change syntax and semantics on a six-year cadence, per-crate, with automated migration, and old code keeps compiling forever.</p>
<p>That is a genuinely important piece of language design and it is underrated because it works.</p>]]></content:encoded></item><item><title>Rust 1.84 and the quiet rewrite underneath</title><link>https://readme.news/rust-184-and-the-quiet-rewrite-underneath/</link><guid isPermaLink="true">https://readme.news/rust-184-and-the-quiet-rewrite-underneath/</guid><pubDate>Thu, 09 Jan 2025 09:00:00 +0000</pubDate><description>The next-generation trait solver goes live for coherence checking. Most people will never notice, which is the point.</description><content:encoded><![CDATA[<p>Rust 1.84 shipped today, and the headline item is a piece of plumbing that almost nobody will consciously interact with: the next-generation trait solver is now used for coherence checking.</p>
<p>If that sentence meant nothing to you, that is fine and arguably intended. Here is why it matters anyway.</p>
<h2 id="what-a-trait-solver-does">what a trait solver does<a class="anchor" href="#what-a-trait-solver-does" aria-label="link to this section">#</a></h2>
<p>When you write <code>impl Display for MyType</code>, the compiler has to answer questions like: does this impl overlap with another one? Can this generic bound be satisfied? Is this associated type equal to that one? The component answering those questions is the trait solver, and the old one grew organically over a decade of Rust's life. It has known unsoundness holes, it has performance cliffs, and it has behaviors nobody can fully explain including the people who wrote it.</p>
<p>The new solver is a ground-up reimplementation with a proper handling of cycles, coinduction, and <a class="xref" href="/caching-is-the-only-optimization-that-reliably-works/" title="Caching is the only optimization that reliably works">caching</a>. Coherence checking — the "do these two impls conflict" question — is the first place it has been switched on by default, because coherence is a relatively contained problem where a regression shows up loudly at compile time rather than quietly at runtime.</p>
<h2 id="what-you-might-actually-see">what you might actually see<a class="anchor" href="#what-you-might-actually-see" aria-label="link to this section">#</a></h2>
<p>A very small number of crates will now get errors they did not get before, because the old solver was accepting impls it should not have. That is a fix, not a regression, but it will feel like a regression if it happens to you. The release notes flag it.</p>
<p>Also in this release:</p>
<ul><li><strong>Strict provenance APIs stabilize.</strong> <code>ptr::with_addr</code>, <code>ptr::addr</code>, <code>ptr::map_addr</code> and friends. This is the vocabulary for expressing pointer arithmetic in a way that does not launder provenance through an integer, which matters enormously for Miri, for CHERI-style hardware, and for anyone whose code is going to be checked by a tool smarter than themselves.</li><li><strong>Cargo respects the <code>rust-version</code> field when resolving dependencies.</strong> The MSRV-aware resolver will now prefer a dependency version compatible with your declared minimum Rust version instead of picking the newest and detonating. This has been requested for years and quietly fixes a real papercut for anybody supporting older toolchains.</li></ul>
<div class="code"><span class="code-lang">toml</span><pre><code class="lang-toml">[package]
rust-version = "1.75"   # cargo now actually uses this during resolution</code></pre></div>
<h2 id="the-pattern-worth-noticing">the pattern worth noticing<a class="anchor" href="#the-pattern-worth-noticing" aria-label="link to this section">#</a></h2>
<p>Rust's release train has settled into a rhythm where the exciting user-facing features arrive in editions and the intervening six-week releases carry structural work. 1.84 is almost entirely structural. The new solver has been in development for something like three years and is being landed one surface at a time, with the more invasive switch — using it everywhere, not just coherence — still ahead.</p>
<p>That is how you replace a load-bearing component in a language with a stability guarantee. Slowly, in public, with the ability to flip back. It is unglamorous and it is the reason people trust the toolchain.</p>
<p><a class="xref" href="/rust-2024-is-the-largest-edition-since-2018/" title="Rust 2024 is the largest edition since 2018">Rust 2024</a> edition lands with 1.85 next month, and that one will be noisy.</p>]]></content:encoded></item>
</channel>
</rss>
