From 6fd8bb9422b14c34624d1ef83206775b6d855db5 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 22 Mar 2026 08:02:09 -0400 Subject: [PATCH 1/6] Stable 1.94.1 release --- src/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version b/src/version index 8db4a57b3d020..df83a51c6cb9a 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.94.0 +1.94.1 From 637a138ab45d96653a1eb610c0dfeba5599624cf Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 10 Mar 2026 10:29:36 +0800 Subject: [PATCH 2/6] library: `wasm32-wasip1-threads` has functional pthreads Minimal backport-suitable fix to avoid returning `UNSUPPORTED_PLATFORM` for `wasm32-wasip1-threads` which has a working pthreads implementation via `emnapi`. The stable regression was reported in . --- library/std/src/sys/thread/unix.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/thread/unix.rs b/library/std/src/sys/thread/unix.rs index 6f23c28c04d6a..430e699e098e6 100644 --- a/library/std/src/sys/thread/unix.rs +++ b/library/std/src/sys/thread/unix.rs @@ -49,7 +49,10 @@ impl Thread { // WASI does not support threading via pthreads. While wasi-libc provides // pthread stubs, pthread_create returns EAGAIN, which causes confusing // errors. We return UNSUPPORTED_PLATFORM directly instead. - if cfg!(target_os = "wasi") { + + // NOTE: exempt `wasm32-wasip1-threads` from this check as `emnapi` has a working pthread + // implementation. See . + if cfg!(all(target_os = "wasi", not(all(target_env = "p1", target_feature = "atomics")))) { return Err(io::Error::UNSUPPORTED_PLATFORM); } From 4f1e85d8752e812ceb1e86185b10714be38659fb Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Fri, 6 Mar 2026 11:42:10 +0000 Subject: [PATCH 3/6] Move freeze_* methods to OpenOptionsExt2 --- library/std/src/os/windows/fs.rs | 35 +++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index 73f3e589e2432..7fd46b31f7d83 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -138,6 +138,8 @@ impl FileExt for fs::File { } /// Windows-specific extensions to [`fs::OpenOptions`]. +// WARNING: This trait is not sealed. DON'T add any new methods! +// Add them to OpenOptionsExt2 instead. #[stable(feature = "open_options_ext", since = "1.10.0")] pub trait OpenOptionsExt { /// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`] @@ -305,18 +307,6 @@ pub trait OpenOptionsExt { /// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-security_impersonation_level #[stable(feature = "open_options_ext", since = "1.10.0")] fn security_qos_flags(&mut self, flags: u32) -> &mut Self; - - /// If set to `true`, prevent the "last access time" of the file from being changed. - /// - /// Default to `false`. - #[unstable(feature = "windows_freeze_file_times", issue = "149715")] - fn freeze_last_access_time(&mut self, freeze: bool) -> &mut Self; - - /// If set to `true`, prevent the "last write time" of the file from being changed. - /// - /// Default to `false`. - #[unstable(feature = "windows_freeze_file_times", issue = "149715")] - fn freeze_last_write_time(&mut self, freeze: bool) -> &mut Self; } #[stable(feature = "open_options_ext", since = "1.10.0")] @@ -345,7 +335,28 @@ impl OpenOptionsExt for OpenOptions { self.as_inner_mut().security_qos_flags(flags); self } +} + +#[unstable(feature = "windows_freeze_file_times", issue = "149715")] +pub trait OpenOptionsExt2: Sealed { + /// If set to `true`, prevent the "last access time" of the file from being changed. + /// + /// Default to `false`. + #[unstable(feature = "windows_freeze_file_times", issue = "149715")] + fn freeze_last_access_time(&mut self, freeze: bool) -> &mut Self; + + /// If set to `true`, prevent the "last write time" of the file from being changed. + /// + /// Default to `false`. + #[unstable(feature = "windows_freeze_file_times", issue = "149715")] + fn freeze_last_write_time(&mut self, freeze: bool) -> &mut Self; +} + +#[unstable(feature = "sealed", issue = "none")] +impl Sealed for OpenOptions {} +#[unstable(feature = "windows_freeze_file_times", issue = "149715")] +impl OpenOptionsExt2 for OpenOptions { fn freeze_last_access_time(&mut self, freeze: bool) -> &mut Self { self.as_inner_mut().freeze_last_access_time(freeze); self From 0a29b263d05b17fc0038bcc9e73da0a7f2cdc4b5 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 22 Mar 2026 08:07:35 -0400 Subject: [PATCH 4/6] Cargo stable backports ``` $ git log --oneline 85eff7c80277b57f78b11e28d14154ab12fcf643..292f395c297d4f99171325b0842ac4ea4ff3b386 292f395c2 (HEAD) [stable 1.94] Fix symlink_and_directory when running in a long target dir name (#16777) d00475981 Fix symlink_and_directory when running in a long target dir name (#16775) ce98781f7 [stable 1.94] Update tar to 0.4.45 (#16769) fec7f9297 Update tar to 0.4.45 5e256e377 Add a test for a tar file with a symlink and directory of the same name 1ed92053d test: Remove unused docker ip_address (#16636) d7a2a0307 Increase cache_lock test timeout (#16545) 95d93fb89 Don't check the specific build-std output dfbe729f6 chore: Updated compiler errors for Rust 1.93 (#16543) cb03b21f6 Update cargo-semver-checks to 0.47.0 f7777c4f9 test(build-std): Update error message (#16658) a56abe18a Disable custom target JSON spec test 634668d49 fix: `--remap-path-scope` stabilized in 1.95-nightly (#16536) d428eaa44 fix(script): surpress `unused_features` lint for embedded (#16714) e7b27c7f9 test(git): Mark a test as non-deterministic (#16706) 38922ca44 test(replace): Mark a test as non-deterministic (#16700) ``` --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 85eff7c80277b..292f395c297d4 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 85eff7c80277b57f78b11e28d14154ab12fcf643 +Subproject commit 292f395c297d4f99171325b0842ac4ea4ff3b386 From 96a4ac8909faa762249267ba9031e1dc5b1d48ac Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 22 Mar 2026 08:13:23 -0400 Subject: [PATCH 5/6] Backport rust-lang/rust-clippy#16685 This applies the patch for that PR, fixing an ICE in match_same_arms. --- .../src/matches/match_same_arms.rs | 9 ++++++--- .../clippy_lints/src/methods/filter_map.rs | 7 +++++-- .../clippy/clippy_utils/src/hir_utils.rs | 20 +++++++++++++++---- .../clippy/tests/ui/match_same_arms.fixed | 16 +++++++++++++++ src/tools/clippy/tests/ui/match_same_arms.rs | 16 +++++++++++++++ 5 files changed, 59 insertions(+), 9 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index c20217563d62b..3976529f96120 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -12,7 +12,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::{Arm, Expr, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatExpr, PatExprKind, PatKind, RangeEnd}; use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_lint::{LateContext, LintContext}; -use rustc_middle::ty; +use rustc_middle::ty::{self, TypeckResults}; use rustc_span::{ByteSymbol, ErrorGuaranteed, Span, Symbol}; use super::MATCH_SAME_ARMS; @@ -61,7 +61,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { let check_eq_with_pat = |expr_a: &Expr<'_>, expr_b: &Expr<'_>| { let mut local_map: HirIdMap = HirIdMap::default(); - let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| { + let eq_fallback = |a_typeck_results: &TypeckResults<'tcx>, + a: &Expr<'_>, + b_typeck_results: &TypeckResults<'tcx>, + b: &Expr<'_>| { if let Some(a_id) = a.res_local_id() && let Some(b_id) = b.res_local_id() && let entry = match local_map.entry(a_id) { @@ -71,7 +74,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { } // the names technically don't have to match; this makes the lint more conservative && cx.tcx.hir_name(a_id) == cx.tcx.hir_name(b_id) - && cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b) + && a_typeck_results.expr_ty(a) == b_typeck_results.expr_ty(b) && pat_contains_local(lhs.pat, a_id) && pat_contains_local(rhs.pat, b_id) { diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs index 7b10c37de42df..d2e593fc17df8 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs @@ -9,6 +9,7 @@ use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::{Closure, Expr, ExprKind, PatKind, PathSegment, QPath, UnOp}; use rustc_lint::LateContext; +use rustc_middle::ty::TypeckResults; use rustc_middle::ty::adjustment::Adjust; use rustc_span::Span; use rustc_span::symbol::{Ident, Symbol}; @@ -136,7 +137,9 @@ impl<'tcx> OffendingFilterExpr<'tcx> { // .map(|y| y[.acceptable_method()].unwrap()) && let simple_equal = (receiver.res_local_id() == Some(filter_param_id) && map_arg_peeled.res_local_id() == Some(map_param_id)) - && let eq_fallback = (|a: &Expr<'_>, b: &Expr<'_>| { + && let eq_fallback = + (|a_typeck_results: &TypeckResults<'tcx>, a: &Expr<'_>, + b_typeck_results: &TypeckResults<'tcx>, b: &Expr<'_>| { // in `filter(|x| ..)`, replace `*x` with `x` let a_path = if !is_filter_param_ref && let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind @@ -144,7 +147,7 @@ impl<'tcx> OffendingFilterExpr<'tcx> { // let the filter closure arg and the map closure arg be equal a_path.res_local_id() == Some(filter_param_id) && b.res_local_id() == Some(map_param_id) - && cx.typeck_results().expr_ty_adjusted(a) == cx.typeck_results().expr_ty_adjusted(b) + && a_typeck_results.expr_ty_adjusted(a) == b_typeck_results.expr_ty_adjusted(b) }) && (simple_equal || SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(receiver, map_arg_peeled)) diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index c7bb3a064a093..df121d24b6aea 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -26,7 +26,8 @@ use std::slice; /// Callback that is called when two expressions are not equal in the sense of `SpanlessEq`, but /// other conditions would make them equal. -type SpanlessEqCallback<'a> = dyn FnMut(&Expr<'_>, &Expr<'_>) -> bool + 'a; +type SpanlessEqCallback<'a, 'tcx> = + dyn FnMut(&TypeckResults<'tcx>, &Expr<'_>, &TypeckResults<'tcx>, &Expr<'_>) -> bool + 'a; /// Determines how paths are hashed and compared for equality. #[derive(Copy, Clone, Debug, Default)] @@ -59,7 +60,7 @@ pub struct SpanlessEq<'a, 'tcx> { cx: &'a LateContext<'tcx>, maybe_typeck_results: Option<(&'tcx TypeckResults<'tcx>, &'tcx TypeckResults<'tcx>)>, allow_side_effects: bool, - expr_fallback: Option>>, + expr_fallback: Option>>, path_check: PathCheck, } @@ -94,7 +95,10 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { } #[must_use] - pub fn expr_fallback(self, expr_fallback: impl FnMut(&Expr<'_>, &Expr<'_>) -> bool + 'a) -> Self { + pub fn expr_fallback( + self, + expr_fallback: impl FnMut(&TypeckResults<'tcx>, &Expr<'_>, &TypeckResults<'tcx>, &Expr<'_>) -> bool + 'a, + ) -> Self { Self { expr_fallback: Some(Box::new(expr_fallback)), ..self @@ -639,7 +643,15 @@ impl HirEqInterExpr<'_, '_, '_> { ) => false, }; (is_eq && (!self.should_ignore(left) || !self.should_ignore(right))) - || self.inner.expr_fallback.as_mut().is_some_and(|f| f(left, right)) + || self + .inner + .maybe_typeck_results + .is_some_and(|(left_typeck_results, right_typeck_results)| { + self.inner + .expr_fallback + .as_mut() + .is_some_and(|f| f(left_typeck_results, left, right_typeck_results, right)) + }) } fn eq_exprs(&mut self, left: &[Expr<'_>], right: &[Expr<'_>]) -> bool { diff --git a/src/tools/clippy/tests/ui/match_same_arms.fixed b/src/tools/clippy/tests/ui/match_same_arms.fixed index 31684a5759fe9..8b16fd3193f5f 100644 --- a/src/tools/clippy/tests/ui/match_same_arms.fixed +++ b/src/tools/clippy/tests/ui/match_same_arms.fixed @@ -140,3 +140,19 @@ fn main() { _ => false, }; } + +fn issue16678() { + // ICE in Rust 1.94.0 + match true { + true => { + fn wrapper(_arg: ()) { + _arg; + } + }, + false => { + fn wrapper(_arg: ()) { + _arg; + } + }, + } +} diff --git a/src/tools/clippy/tests/ui/match_same_arms.rs b/src/tools/clippy/tests/ui/match_same_arms.rs index 39bee01bac22b..3b2d585c579d3 100644 --- a/src/tools/clippy/tests/ui/match_same_arms.rs +++ b/src/tools/clippy/tests/ui/match_same_arms.rs @@ -149,3 +149,19 @@ fn main() { _ => false, }; } + +fn issue16678() { + // ICE in Rust 1.94.0 + match true { + true => { + fn wrapper(_arg: ()) { + _arg; + } + }, + false => { + fn wrapper(_arg: ()) { + _arg; + } + }, + } +} From ff8efbd70dcd00b925c68eaf0c8d08f9c9cb806a Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 22 Mar 2026 08:24:51 -0400 Subject: [PATCH 6/6] Add release notes for 1.94.1 --- RELEASES.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index f180d740a3d17..a8ebb8343c017 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,17 @@ +Version 1.94.1 (2026-03-26) +=========================== + + + +* [Fix `std::thread::spawn` on wasm32-wasip1-threads](https://github.com/rust-lang/rust/pull/153634) +* [Remove new methods added to `std::os::windows::fs::OpenOptionsExt`](https://github.com/rust-lang/rust/pull/153491) + The new methods were unstable, but the trait itself is not sealed and so + cannot be extended with non-default methods. +* [[Clippy] Fix ICE in `match_same_arms`](https://github.com/rust-lang/rust-clippy/pull/16685) +* [[Cargo] Update tar to 0.4.45](https://github.com/rust-lang/cargo/pull/16769) + This resolves CVE-2026-33055 and CVE-2026-33056. Users of crates.io are not affected. + See [blog](https://blog.rust-lang.org/2026/03/21/cve-2026-33056/) for more details. + Version 1.94.0 (2026-03-05) ==========================