31 May 2026
Planet Mozilla
The Servo Blog: April in Servo: new Android UI, focus, forms, security fixes, and more!
Servo 0.2.0 contains all of the changes we landed in April, which came out to yet another record 534 commits (March: 530). For security fixes, see § Security.

We've shipped several new web platform features:
- <select multiple> (@lukewarlow, @mrobinson, #43189)
- <template shadowrootslotassignment> (@simonwuelker, #44246)
- <video> playback on OpenHarmony (@rayguo17, #43208)
- 'minimum-scale' and 'maximum-scale' values in <meta name=viewport> (@shubhamg13, #40098, #43715)
- 'color-mix()' with any number of <color> values (@Loirooriol, #43890)
- '&::before' and '&::after' in '::details-content' (@Loirooriol, #43878)
- 'revert-rule' (@Loirooriol, #43878)
- 'tab-size' (@mrobinson, @SimonSapin, #44480)
- 'text-align: match-parent' (@TG199, #44073)
- new Worker() with blob URLs (@jdm, #44004)
- getContext(
"webgl") on OffscreenCanvas (@niyabits, #44159) - the detail property on PerformanceMark and PerformanceMeasure (@shubhamg13, #44289, #44272)
Plus a bunch of new DOM APIs:
- 'selectionchange' events on <input> and <textarea> (@TimvdLippe, #44461)
- StorageManager, in experimental mode (@Taym95, #43976)
- activeElement on Document and ShadowRoot (@mrobinson, #43861)
- crypto.subtle.supports() (@kkoyung, #43703) - Servo is the first major browser engine to support this!
- cellPadding, cellSpacing, and align properties on HTMLTableElement (@mrobinson, #43903) - previously supported in HTML only
- relatedTarget on 'focus' and 'blur' events (@mrobinson, #43926)
- transferFromImageBitmap() on ImageBitmapRenderingContext (@Messi002, #43984)
Servo's support for text in Chinese, Japanese, and Korean languages has improved, with correct wrapping in the layout engine (@SharanRP, #43744), and CJK fonts now enabled in servoshell's browser UI on Windows, Linux, and FreeBSD (@yezhizhen, @CynthiaOketch, @nortti0, #44055, #44138, #44514).
Navigating to a JSON file as the top-level document now renders the JSON with an interactive pretty-printer (@webbeef, @TimvdLippe, #43702).
April was a big milestone for Servo, with some automated tests failing because they had hard-coded cookie expiry dates set to April 2016 plus ten years. Surprise! We're still here. Here's to the next 100 years of Servo (@jdm, #44341).
This is another big update, so here's an outline:
Security
CryptoKey now zeroes buffers containing key material after use (@kkoyung, #44597).
With only a few exceptions, you can only access DOM APIs in another document if that document is in the same origin. But if that document is in the same site with a different port number, Servo currently allows these accesses even though it shouldn't. We've fixed some (but not all) of these incorrect accesses, specifically those that involve binding a Window or Location method in this document with a this from the other document (@yvt, @jdm, #28583).
We've fixed a bug where localStorage and sessionStorage were usable in sandboxed <iframe> and shared with every other sandboxed <iframe>, rather than throwing SecurityError (@Taym95, #44002).
We've fixed a bug where localStorage and sessionStorage were shared between all <iframe srcdoc> documents, rather than isolated using the origin of the containing document (@niyabits, #43988, #44038).
We've fixed a bug where IndexedDB was usable in sandboxed <iframe> and data: URL web workers (@Taym95, #44088).
We've fixed a bug where pages in some IP address origins can evict cookies from other IP address origins (@officialasishkumar, #44152). Only evicting cookies was possible, not reading or writing them.
We've fixed an out-of-bounds memory read in texImage3D() on WebGL2RenderingContext (@simartin, #44270), and fixed some undefined behaviour in servoshell's signal handler (@Narfinger, #43891).
Work in progress
IndexedDB is now enabled in servoshell's experimental mode (@arihant2math, #44245). As always, embedders can enable it with Preferences::dom_indexeddb_enabled (@arihant2math, #44245, #44283).
IndexedDB now uses Servo's new "client storage" system, which is based on the Storage Standard and will allow us to have a unified on-disk format and quota management for all web platform features that persistently store data (@gterzian, #44374, #43900). We've also made key range queries more efficient (@arihant2math, #39009), landed improvements to IDBDatabase, IDBObjectStore, IDBCursor, IDBKeyRange, IDBRequest, and to the handling of transactions, keys, values, and exceptions (@Taym95, #44128, #43901, #44009, #43914, #44161, #44183, #44059, #44215, #42998, #43805).
We've made more progress on the IntersectionObserver API, under --pref dom_intersection_observer_enabled (@stevennovaryo, @jdm, #42204).
We're continuing to implement document.execCommand() for rich text editing (@TimvdLippe, #44529), under --pref dom_exec_command_enabled. This release adds support for the 'bold', 'fontName', 'fontSize', 'italic', 'strikethrough', and 'underline' commands (@TimvdLippe, @jdm, @mrobinson, #44511, #43287, #44432, #44410, #44194, #44030, #44039, #44041, #44075, #44234, #44250, #44331, #44390, #44137, #44293, #44312, #44347).
All of the features above are enabled in servoshell's experimental mode.
Servo can now build a very basic accessibility tree for web contents, under --pref accessibility_enabled (@alice, @delan, @lukewarlow, #42338, #43558, #44437, #44438). This includes text runs, plus nine other non-interactive accessibility roles (@alice, @delan, #44255). We've also fixed a crash when reloading pages with accessibility enabled (@alice, #44473), and made accessibility tree updates more efficient (@alice, #44208).
We've started implementing the Sanitizer API, under --pref dom_sanitizer_enabled (@kkoyung, #44198, #44290, #44335, #44421, #44452, #44481, #44585, #44594).
We've also started implementing SharedWorker, under --pref dom_sharedworker_enabled (@Taym95, #44375, #44440).
We're working on the WakeLock API too, under --pref dom_wakelock_enabled (@TG199, @rovertrack, #43617, #44343).
servoshell
servoshell for Android now has a revamped browser UI, including a new history view (@espy, #43795), the apk is 30% smaller (@jschwe, #44278, #44182), and we've fixed the black screen bug when closing settings or switching back from another app (@yezhizhen, #44327). You can now close tabs on OpenHarmony too (@Narfinger, #42713).

As for servoshell on desktop platforms, we've fixed some focus- and IME-related bugs (@mrobinson, #43872, #43932), and on Windows, we now install a normal shortcut without the strange behaviour of an "advertised" shortcut (@yezhizhen, #44223).
For developers
When using the Inspector tab in the Firefox DevTools, the Rules panel now includes declarations in '@layer' rules (@arabson99, #43912).
When logging expressions in the Console tab, and when hovering over symbols in the Debugger tab, you can now get more information about the contents of functions, arrays, objects, and other values (@atbrakhi, @eerii, #44172, #44173, #44022, #44233, #44196, #44181, #44064, #44023, #44164, #44369, #44262).
When using the Debugger tab, you can now use the Scopes panel to inspect local and global variables (@eerii, @atbrakhi, #43792, #43791), you can now debug web worker scripts (@atbrakhi, #43981), and we've started implementing blackboxing, aka the Ignore source button (@freyacodes, #44142).
We've also landed some initial support for the Style Editor tab (@rovertrack, #44517, #44462).
We're working towards re-enabling our automated DevTools tests in CI, which should make the feature more reliable (@freyacodes, #44577), and we've landed a small build reproducibility fix too (@jschwe, #44459).
For developers of Servo itself, please note that the Cargo 'release' profile is no longer #[cfg(debug_assertions)] (@jschwe, @mrobinson, #44177). If you've been using 'release' as a "faster 'debug' with assertions" build locally, consider switching to 'checked-release' or 'medium'.
The pull request template has been updated (@mrobinson, #44135). 'Testing' and 'Fixes' should go at the bottom of the PR description, and 'Testing' is about automated tests, not how you tested the PR locally.
We've made more progress on the new dev container, which will provide an alternative to our usual procedures for setting up a Servo build environment (@jschwe, @sagudev, #44126, #44111, #44162, #44641, #44109). Keep an eye out for that in the book!
In the meantime, did you know that you can use Lix or Nix to build Servo on Linux with a lot less hassle, even if you're not using NixOS? For now at least, head to the NixOS page in the book to learn more. We've also fixed a regression that made --debug-mozjs and MOZJS_FROM_SOURCE builds take much longer to complete on Linux when not using Nix (@jschwe, #44346).
We've fixed building Servo with the 'jitspew' feature in mozjs, allowing you to set IONFLAGS to enable JIT logging (@simonwuelker, #44010). We've also fixed build issues on Windows and FreeBSD (@zhangxichang, @mrobinson, #44264, #44591).
Embedding API
With this second monthly release of the Servo library, we have some quick notes about API stability and semver compatibility:
-
The 'servo' package follows Cargo's rules for semver compatibility. 0.1.1 is compatible with version 0.1.0, but 0.2.0 is a breaking update.
-
Until we integrate semver analysis into our release process, each monthly release will have a breaking version number, while non-breaking version numbers may be used for LTS updates.
-
In general, dependencies of 'servo', like 'servo-base' and 'servo-script', do not use semver. Any release may include breaking changes.
We've fixed a build failure affecting embedders with a new or updated Cargo.lock (@jschwe, #44093), and landed several other changes to help us with the Servo library release process (@jschwe, @mukilan, #43972, #44642, #43182, #43866, #44086, #43797).
Breaking changes:
-
WebView::animatingnow takes&selfinstead ofself, so you can call it without cloning the handle (@JavaDerg, #44253) -
Servo::site_data_managernow returns&SiteDataManagerinstead ofRef<'_, SiteDataManager>(@sabbCodes, #44116) -
WebViewDelegate::play_gamepad_haptic_effectandstop_gamepad_haptic_effecthave been removed (@mrobinson, #43895), but they have not worked since February 2026 - useGamepadDelegateinstead
You can now load a URL with custom request headers by calling WebView::load_request (@Narfinger, @longvatrong111, @mrobinson, #43338).
You can now retrieve cookies asynchronously by calling SiteDataManager::cookies_for_url_async (@longvatrong111, #43794).
The synchronous version of that method, SiteDataManager::cookies_for_url, was previously not callable because CookieSource was not exposed to the public API, but we've fixed that now (@TG199, #44124).
You can now clear session cookies without clearing permanent cookies by calling SiteDataManager::clear_session_cookies (@longvatrong111, #44166).
When intercepting requests with ServoDelegate:: and WebViewDelegate::load_web_resource, we now include a destination and referrer_url in the WebResourceRequest, which can be helpful if you're implementing ad blocking (@webbeef, #44493).
You can configure Servo to write all of its storage to a unique directory for that session by enabling Opts::temporary_storage (@janvarga, #44433). Note that these unique directories currently persist after Servo exits, so it's an isolation feature, not a privacy feature.
WindowRenderingContext::new and SoftwareRenderingContext::new now return an error if the given size is less than 1x1 (@freyacodes, @mrobinson, #44011).
We've improved our API docs for WebView, WebViewBuilder, WebViewDelegate, ServoDelegate, PromptDialog, WebResourceLoad, WebXrRegistry, Preferences, and servoshell's EXPERIMENTAL_PREFS (@simonwuelker, @TG199, @sabbCodes, @jdm, @rovertrack, #43892, #43787, #44171, #43947).
We've also improved our API docs for Opts, OutputOptions, DiagnosticsLogging, PrefValue, servo::opts, and servo_config (@mukilan, #43802).
More on the web platform
Tab navigation now works across <iframe> boundaries (@mrobinson, #44397), and Ctrl+Backspace (or ⌥⌫) now deletes a whole word in input fields (@mrobinson, #43940).
Tab characters are now rendered correctly in <pre> (and other elements with 'white-space: pre'), with proper tab stops (@mrobinson, @SimonSapin, #44480). Spaces are now rendered correctly in 2D <canvas>, instead of twice as wide as they should be (@mrobinson, #43899).
<a href> now correctly resolves the URL with the page encoding (@sabbCodes, #43822).
We've improved the default appearance of <input type=file> (@sabbCodes, #44496) and <textarea placeholder> (@mrobinson, #43770).
All keyboard events, mouse events, wheel events, and pointer events, other than 'pointerenter' and 'pointerleave', now bubble out of shadow roots (@simonwuelker, @webbeef, #43799, #44094). 'error' events on Window now report the correct filename (source in onerror) and lineno (@Gae24, #43632).
console.log() and friends now support printf-style formatting directives, although for now %c is ignored (@TG199, #43897).
file: URLs are now considered secure contexts, so they can now use features like crypto.subtle and crypto.randomUUID (@simonwuelker, #43989).
Exception messages have improved in Location, StaticRange, and the HTMLElement family of types (@arihant2math, @MuhammadMouostafa, @treetmitterglad, #44282, #43260, #43882).
We've improved the conformance of fetch algorithms (@yezhizhen, #43970, #43798), focus and tab navigation (@mrobinson, #43842, #44029, #44360, #43859, #44535), form submission (@TG199, #43700), JS modules (@elomscansio, @Gae24, #43741, #44179, #44042), page navigation (@TimvdLippe, #43857), <svg viewBox> (@yezhizhen, #44420), 'attr()' (@Loirooriol, #43878), ':focus' (@mrobinson, #43873), 'font' (@RichardTjokroutomo, #44061), '@keyframes' (@simonwuelker, #43461), '@property' (@Loirooriol, #43878), 'load' events (@jdm, @arabson99, #43807, #44046), fetchLater() (@TimvdLippe, #43627), axes and buttons on Gamepad (@log101, @rovertrack, #44411, #44357), copyTexImage2D() on WebGLRenderingContext (@simartin, @mrobinson, #43608), texImage3D() on WebGL2RenderingContext (@simartin, #44367), environmentBlendMode on XRSession (@msub2, #44155), mark() and measure() on Performance (@shubhamg13, @simonwuelker, #44471, #44199, #43990, #43753), and PerformanceResourceTiming (@shubhamg13, #44228).
We've fixed bugs related to console logging (@sabbCodes, #44243), 'animation' (@mrobinson, #44299), 'box-shadow' (@yezhizhen, #44474, #44457), 'display: contents' (@Loirooriol, @mrobinson, #44551, #44299), 'display: inline-flex' (@SimonSapin, #44281), 'display: table-cell' (@Loirooriol, #44550), 'display: table-row-group' (@Veercodeprog, #43674), 'overflow-x: clip' and 'overflow-y: clip' (@Messi002, #43620), 'position: absolute' on grid items (@nicoburns, #44324), 'word-spacing: <percentage>' (@sabbCodes, #44031), removeChild() on Document (@rovertrack, #44133), and URL.revokeObjectURL() (@simonwuelker, @jdm, #43746, #43977, #44035).
Performance and stability
We've fixed some big inefficiencies in Servo. appendChild() with nested shadow roots is no longer (@yezhizhen, @webbeef, #44016), and we've halved the time it takes to load the ECMAScript spec by fixing the processing of 'id' and 'name' attributes (@simonwuelker, #44120, #44127, #44117).
Servo makes its first TLS connection in each session 30-60 ms faster (@jschwe, #44242), and we've instrumented the Servo and servoshell startup processes to find more opportunities for optimisation (@jschwe, #44443, #44456).
Like most browser engines, Servo is a multi-threaded (and sometimes multi-process) system requiring a great deal of IPC messages to keep everything connected. Two key components of this system are the constellation thread, which manages the engine as a whole, and the script threads (or web processes), which render the web pages. Sending these messages can be expensive though, so to reduce unnecessary IPC traffic, we've landed an optimisation that allows script threads to selectively receive only the relevant messages from the constellation (@webbeef, #43124).
We've reduced the memory usage of each Attr, Text, and CharacterData node in the DOM by 16 bytes (@mrobinson, @Loirooriol, #44074), and fixed a memory leak when deleting <video controls> or <audio controls> (@Messi002, #43983).
Our about:memory page is more accurate now too, with new tracking of libc memory allocations on macOS, improved tracking of libc memory allocations on Linux (@jschwe, #44037), and more accurate tracking of PathBuf and types in tokio, http, data_url, and urlpattern (@Narfinger, #43858).
Less memory usage isn't always better in browser engines though, because there are many kinds of caches and other optimisations we can do to make browsing the web faster, at the expense of increased memory usage. For example, we can greatly speed up prototype checks for DOM objects by storing a number in each object that identifies the concrete type, at the expense of making each DOM object 64 bits larger (@webbeef, #44364).
Layout can now reuse fragments in later reflows, in many cases that involve block layout or 'position: absolute' (@mrobinson, @lukewarlow, @Loirooriol, #42904, #44231). We're also working on reusing shaping results in later reflows, and making inline layout more efficient (@mrobinson, #44370, #43974, #44436).
We've landed several changes that should reduce the binary size of Servo (@rovertrack, @mrobinson, @nicoburns, @Narfinger, #44227, #44221, #44303, #44338, #44428, #44134).
We've also reduced clones, allocations, borrow checks, GC rooting steps, and other operations in many parts of Servo (@rovertrack, @Narfinger, @Loirooriol, @yezhizhen, @simonwuelker, #44008, #44544, #44271, #44279, #43826, #44052, #44139).
Several crashes have been fixed:
- in compressedTexSubImage2D() on WebGLRenderingContext (@thebabalola, #44050)
- in console.log() (@thebabalola, #43844)
- in getData() on DataTransfer (@SimonSapin, #44607)
- in remove() on Element (@SimonSapin, #44435)
- in replaceWith() on Element (@yezhizhen, #44503)
- in
--debug-mozjsbuilds (@jdm, #44386, #44573, #44581) - in flex and grid layout (@mrobinson, @nicoburns, #44424, #44203)
- in layout queries like
offsetHeight(@mrobinson, #44560) - in the devtools Debugger tab, when stepping and when inspecting nested values (@atbrakhi, @eerii, #44024, #43995)
- when removing <colgroup> from the DOM (@Loirooriol, #43846)
- when running garbage collection (@drasticactions, #43933)
- when running servoshell with a
u64--pref(@yezhizhen, #44079) - when shadow roots are deeply nested, or when calling attachShadow() removes elements from the flat tree (@yezhizhen, @mrobinson, #43888, #43930, #44259)
- when web storage features fail to write to disk or encounter SQLite errors (@arihant2math, @sabbCodes, #43918, #43949)
We fixed a crash in servoshell when pressing keys like Ctrl+2 or ⌘2 with not enough tabs open (@mrobinson, #44070).
DOM data structures (#[dom_struct]) can refer to one another, with the help of garbage collection. But when DOM objects are being destroyed, those references can become invalid for a brief moment, depending on the order the GC finalizers run in. This can be unsound if those references are accessed, which is a very easy mistake to make if the type has an impl Drop. To help prevent that class of bug, we're reworking our DOM types so that none of them have #[dom_struct] and impl Drop at the same time (@willypuzzle, #44119, #44501, #44513).
We've improved our static analysis for GC rooting (@officialasishkumar, #44489), and we've continued our long-running effort to use the Rust type system to make certain kinds of dynamic borrow failures impossible (@sagudev, @TimvdLippe, @Narfinger, @elomscansio, @Gae24, @rovertrack, @yezhizhen, @nodelpit, #43174, #43524, #43928, #43943, #43942, #43944, #43946, #43952, #43975, #44018, #44175, #44241, #44368, #44406, #44441, #44422, #44475, #44478, #44484, #44476, #44490, #44477, #44494, #44497, #44498, #44495, #44505, #44506, #44507, #44508, #44509, #44510, #44512, #44482, #44527, #44528, #44531, #44534, #44542, #44533, #44543, #44553, #44547, #44563, #44562, #44565, #44558, #44583, #44606, #44605, #44608, #44602, #44584, #44620, #44590, #44254, #44628, #44629, #44638, #44626, #44081).
Thanks to a wide range of people, we've also landed a bunch of cleanups and refactors (@delan, @alice, @Skgland, @atbrakhi, @eerii, @sabbCodes, @jdm, @thebabalola, @CynthiaOketch, @kkoyung, @TimvdLippe, @rovertrack, @webbeef, @arabson99, @yezhizhen, @simonwuelker, @mrobinson, @nicoburns, @longvatrong111, @niyabits, @treetmitterglad, @foresterre, @mukilan, @elomscansio, @freyacodes, @StaySafe020, @TG199, #43772, #44006, #43860, #44121, #44160, #43884, #44154, #44569, #43939, #44003, #44110, #44122, #43824, #44635, #44103, #43978, #44092, #44114, #44277, #44454, #44274, #44237, #44232, #44167, #44214, #43820, #43825, #43810, #43838, #43841, #43847, #43875, #43876, #43889, #43893, #43896, #43881, #43906, #43913, #43908, #43917, #43910, #43921, #43924, #43925, #43907, #43923, #43916, #43909, #43911, #43957, #43969, #43967, #43915, #43954, #43963, #43959, #43955, #44067, #44068, #44071, #44084, #44265, #44115, #44358, #43848).
Donations
Thanks again for your generous support! We are now receiving 7349 USD/month (+2.5% from March) in recurring donations. This helps us cover the cost of our speedy CI and benchmarking servers, one of our latest Outreachy interns, and funding maintainer work that helps more people contribute to Servo.
Servo is also on thanks.dev, and already 33 GitHub users (−4 from March) that depend on Servo are sponsoring us there. If you use Servo libraries like url, html5ever, selectors, or cssparser, signing up for thanks.dev could be a good way for you (or your employer) to give back to the community.
We now have sponsorship tiers that allow you or your organisation to donate to the Servo project with public acknowlegement of your support. If you're interested in this kind of sponsorship, please contact us at join@servo.org.
Use of donations is decided transparently via the Technical Steering Committee's public funding request process, and active proposals are tracked in servo/project#187. For more details, head to our Sponsorship page.
31 May 2026 12:00am GMT
30 May 2026
Planet Mozilla
Frederik Braun: The S in interoperability
This is a blog post about standards, their proliferation and the issues that may arise. My first involvement with standards was just as a reader. To better understand complicated code or unexpected behavior in a protocol. After a while, I also got involved and helped clarify certain things to ensure …
30 May 2026 10:00pm GMT
28 May 2026
Planet Mozilla
The Rust Programming Language Blog: Announcing Rust 1.96.0
The Rust team is happy to announce a new version of Rust, 1.96.0. Rust is a programming language empowering everyone to build reliable and efficient software.
If you have a previous version of Rust installed via rustup, you can get 1.96.0 with:
$ rustup update stable
If you don't have it already, you can get rustup from the appropriate page on our website, and check out the detailed release notes for 1.96.0.
If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (rustup default beta) or the nightly channel (rustup default nightly). Please report any bugs you might come across!
What's in 1.96.0 stable
New Range* types
Many users expect Range and related core::ops types to be Copy, but this is not the case: they implement Iterator directly, and it is a footgun to implement both Iterator and Copy on the same type so this has been avoided. RFC3550 proposed a set of replacement range types that implement IntoIterator rather than Iterator, meaning they can also be Copy. The standard library portion of that RFC is now stable, introducing:
core::range::Rangecore::range::RangeFromcore::range::RangeInclusive- Associated iterators
A Rust version in the near future will also add core::range::RangeFull and core::range::RangeTo as re-exports from core::ops (these do not implement Iterator and already implement Copy), and core::range::legacy::* as the new home for the current ranges. Range syntax like 0..1 still produces the legacy types for now, but will be updated to core::range types in a future edition.
With these stabilizations, it is now possible to store slice accessors in Copy types without splitting start and end:
use core::range::Range;
#[derive(Clone, Copy)]
pub struct Span(Range<usize>);
impl Span {
pub fn of(self, s: &str) -> &str {
&s[self.0]
}
}
The new RangeInclusive also makes its fields public, unlike the legacy version which avoided exposing the exhausted iterator state. This isn't a concern with the new type since it must be converted to begin iteration.
Library authors should consider making use of impl RangeBounds in public API, which accepts both legacy and new range types. If a concrete type is needed, prefer using new ranges as this will eventually become the default.
Assert matching patterns
The new macros assert_matches! and debug_assert_matches! check that a value matches a given pattern, panicking with a Debug representation of the value otherwise. These are essentially the same as assert!(matches!(..)) and debug_assert!(matches!(..)), but the printed value improves the possibility of diagnosing the failure.
These new macros have not been added to the standard prelude, because they would collide with popular third-party crates that provide macros with the same name. Instead, they should be manually imported from core or std before use.
use core::assert_matches;
/// [Random Number](https://xkcd.com/221/)
fn get_random_number() -> u32 {
// chosen by a fair dice roll.
// guaranteed to be random.
4
}
fn main() {
assert_matches!(get_random_number(), 1..=6);
}
Changes to WebAssembly targets
WebAssembly targets no longer pass --allow-undefined to the linker which means that undefined symbols when linking are now a linker error instead of being converted to WebAssembly imports from the "env" module. This change prevents modules from linking unless all linking-related symbols are defined to catch bugs earlier and prevent accidental issues with symbol naming or similar.
Undefined linking-related symbols are often indicative of build-time related bugs or misconfiguration. If, however, the old behavior is intended then it can be re-enabled with RUSTFLAGS=-Clink-arg=--allow-undefined or by editing the source code and using #[link(wasm_import_module = "env")] on the block defining the symbol.
This change was previously announced on this blog, and now takes effect in Rust 1.96.
Stabilized APIs
assert_matches!debug_assert_matches!From<T> for AssertUnwindSafe<T>From<T> for LazyCell<T, F>From<T> for LazyLock<T, F>core::range::RangeToInclusivecore::range::RangeFromcore::range::RangeFromItercore::range::Rangecore::range::RangeIter
Two Cargo advisories
Rust 1.96 contains fixes for two vulnerabilities for users of third-party registries.
-
CVE-2026-5223 is a medium severity vulnerability regarding extraction of crate tarballs with symlinks.
-
CVE-2026-5222 is a low severity vulnerability regarding authentication with normalized URLs.
Users of crates.io are not affected by either vulnerability.
Other changes
Check out everything that changed in Rust, Cargo, and Clippy.
Contributors to 1.96.0
Many people came together to create Rust 1.96.0. We couldn't have done it without all of you. Thanks!
28 May 2026 12:00am GMT