From 5aeecbd761f41890119b126b2b587340ef839429 Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Sun, 16 Aug 2026 11:17:26 +0200 Subject: [PATCH 1/8] windows: stabilise inherit_handles --- library/std/src/os/windows/process.rs | 5 ++++- tests/ui/process/win-inherit-handles.rs | 2 -- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index 41dcb70c59c9f..7c6e709261012 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs @@ -372,7 +372,10 @@ pub impl(self) trait CommandExt { /// see the [Remarks][1] section of the `CreateProcessW` documentation. /// /// [1]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw#remarks - #[unstable(feature = "windows_process_extensions_inherit_handles", issue = "146407")] + #[stable( + feature = "windows_process_extensions_inherit_handles", + since = "CURRENT_RUSTC_VERSION" + )] fn inherit_handles(&mut self, inherit_handles: bool) -> &mut process::Command; } diff --git a/tests/ui/process/win-inherit-handles.rs b/tests/ui/process/win-inherit-handles.rs index 5750a4b40f055..9ec7310466aa5 100644 --- a/tests/ui/process/win-inherit-handles.rs +++ b/tests/ui/process/win-inherit-handles.rs @@ -6,8 +6,6 @@ //@ needs-subprocess //@ edition: 2024 -#![feature(windows_process_extensions_inherit_handles)] - use std::os::windows::io::AsRawHandle; use std::os::windows::process::CommandExt; use std::process::{Command, Stdio}; From 90700c96facbab07cc0dd235260c73893b425fcd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 30 Sep 2026 16:10:00 +0200 Subject: [PATCH 2/8] DirEntry: warn about use potential races when fetching metadata or file_type --- library/std/src/fs.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index b4561457adb1e..7bebd4a81f7fe 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2853,7 +2853,9 @@ impl DirEntry { /// /// On Windows this function is cheap to call (no extra system calls /// needed), but on Unix platforms this function is the equivalent of - /// calling `symlink_metadata` on the path. + /// calling `symlink_metadata` on the path. In that case, if the file has been renamed or + /// replaced since the `DirEntry` was created, this can fail or return the metadata of a + /// different file! /// /// # Examples /// @@ -2886,9 +2888,11 @@ impl DirEntry { /// /// # Platform-specific behavior /// - /// On Windows and most Unix platforms this function is free (no extra - /// system calls needed), but some Unix platforms may require the equivalent - /// call to `symlink_metadata` to learn about the target file type. + /// On Windows and most Unix platforms and file systems this function is free (no extra + /// system calls needed), but some Unix platforms or file systems may require the equivalent of + /// calling `symlink_metadata` to learn about the target file type. In that case, if the file + /// has been renamed or replaced since the `DirEntry` was created, this can fail or return the + /// file type of a different file! /// /// # Examples /// From bede68c565be7189666caa1d748c86253d6f4464 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 4 Oct 2026 14:13:15 +0100 Subject: [PATCH 3/8] xous: tcpstream fix timeout rounding with small and wrap large values connect_timeout also now reject Duration::ZERO --- .../src/sys/net/connection/xous/tcpstream.rs | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/library/std/src/sys/net/connection/xous/tcpstream.rs b/library/std/src/sys/net/connection/xous/tcpstream.rs index 45fe0418a27fa..56c0b3bfa3ee3 100644 --- a/library/std/src/sys/net/connection/xous/tcpstream.rs +++ b/library/std/src/sys/net/connection/xous/tcpstream.rs @@ -39,12 +39,13 @@ pub struct TcpStream { nonblocking: Arc>, } -fn sockaddr_to_buf(duration: Duration, addr: &SocketAddr, buf: &mut [u8]) { +fn sockaddr_to_buf(duration: Option, addr: &SocketAddr, buf: &mut [u8]) { // Construct the request. let port_bytes = addr.port().to_le_bytes(); buf[0] = port_bytes[0]; buf[1] = port_bytes[1]; - for (dest, src) in buf[2..].iter_mut().zip((duration.as_millis() as u64).to_le_bytes()) { + let millis = duration.map_or(0, |d| u64::try_from(d.as_millis()).unwrap_or(u64::MAX).max(1)); + for (dest, src) in buf[2..].iter_mut().zip(millis.to_le_bytes()) { *dest = src; } match addr.ip() { @@ -82,15 +83,11 @@ impl TcpStream { } } - pub fn connect(addr: A) -> io::Result { - each_addr(addr, |addr| Self::connect_timeout(addr, Duration::ZERO)) - } - - pub fn connect_timeout(addr: &SocketAddr, duration: Duration) -> io::Result { + fn connect_inner(addr: &SocketAddr, timeout: Option) -> io::Result { let mut connect_request = ConnectRequest { raw: [0u8; 4096] }; // Construct the request. - sockaddr_to_buf(duration, &addr, &mut connect_request.raw); + sockaddr_to_buf(timeout, &addr, &mut connect_request.raw); let Ok((_, valid)) = crate::os::xous::ffi::lend_mut( services::net_server(), @@ -138,6 +135,17 @@ impl TcpStream { }) } + pub fn connect(addr: A) -> io::Result { + each_addr(addr, |addr| Self::connect_inner(addr, None)) + } + + pub fn connect_timeout(addr: &SocketAddr, duration: Duration) -> io::Result { + if duration.is_zero() { + return Err(io::Error::ZERO_TIMEOUT); + } + Self::connect_inner(addr, Some(duration)) + } + pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { if let Some(to) = timeout { if to.is_zero() { @@ -145,7 +153,7 @@ impl TcpStream { } } self.read_timeout.store( - timeout.map(|t| t.as_millis().min(u32::MAX as u128) as u32).unwrap_or_default(), + timeout.map_or(0, |t| u32::try_from(t.as_millis()).unwrap_or(u32::MAX).max(1)), Ordering::Relaxed, ); Ok(()) @@ -158,7 +166,7 @@ impl TcpStream { } } self.write_timeout.store( - timeout.map(|t| t.as_millis().min(u32::MAX as u128) as u32).unwrap_or_default(), + timeout.map_or(0, |t| u32::try_from(t.as_millis()).unwrap_or(u32::MAX).max(1)), Ordering::Relaxed, ); Ok(()) From 2c0fdb904221443574f654a560493acd0a79aeb3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Oct 2026 18:42:59 +0200 Subject: [PATCH 4/8] enable fchmodat_works test under android --- library/std/src/fs/tests.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 14547227744e4..17ebdd2410c64 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1736,7 +1736,6 @@ fn fchmod_works() { check!(file.set_permissions(p)); } -#[cfg(not(target_os = "android"))] #[test] fn fchmodat_works() { let tmpdir = tmpdir(); From aa39324897ad45e0ff9480fd7328577cf456580b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Oct 2026 18:26:06 +0200 Subject: [PATCH 5/8] make remove_dir_all behavior around symlinks on Unix more clear --- library/std/src/fs.rs | 4 +++- library/std/src/fs/tests.rs | 13 +++++++------ library/std/src/sys/fs/unix.rs | 9 ++++++++- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 139275ed2e1c2..9c4ec06fae47b 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -3496,7 +3496,9 @@ pub fn remove_dir>(path: P) -> io::Result<()> { /// carefully! /// /// This function does **not** follow symbolic links and it will simply remove the -/// symbolic link itself. +/// symbolic link itself. If `path` itself is a symbolic link to a directory, it will get +/// removed. If it is a symbolic link to a file, behavior is platform-specific: +/// currently, it will get removed on Unix-like systems but not on Windows. /// /// # Platform-specific behavior /// diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 54a6cf3904202..ce3bd17a52bc2 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1315,7 +1315,7 @@ fn recursive_rmdir() { } #[test] -fn recursive_rmdir_of_symlink() { +fn recursive_rmdir_of_dir_symlink() { // test we do not recursively delete a symlink but only dirs. let tmpdir = tmpdir(); let link = tmpdir.join("d1"); @@ -1342,8 +1342,6 @@ fn recursive_rmdir_of_file_fails() { } #[test] -// only Windows makes a distinction between file and directory symlinks. -#[cfg(windows)] fn recursive_rmdir_of_file_symlink() { let tmpdir = tmpdir(); if !got_symlink_permission(&tmpdir) { @@ -1354,9 +1352,12 @@ fn recursive_rmdir_of_file_symlink() { let f2 = tmpdir.join("f2"); check!(check!(File::create(&f1)).write(b"foo")); check!(symlink_file(&f1, &f2)); - match fs::remove_dir_all(&f2) { - Ok(..) => panic!("wanted a failure"), - Err(..) => {} + let res = fs::remove_dir_all(&f2); + // Windows and Unix behavior differs here. + if cfg!(windows) { + let _err = res.unwrap_err(); + } else { + let _ok = res.unwrap(); } } diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 0adc0b9136f63..79e16cd4b6e23 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -2492,6 +2492,9 @@ mod remove_dir_impl { } } + /// `parent_fd` being `None` indicates that this is the root where we start. + /// In that case, `path` will only be deleted if it is a directory. + /// When it is `Some`, this will delete anything. fn remove_dir_all_recursive(parent_fd: Option, path: &CStr) -> io::Result<()> { // try opening as directory let fd = match openat_nofollow_dironly(parent_fd, path) { @@ -2503,7 +2506,8 @@ mod remove_dir_impl { Some(parent_fd) => { cvt(unsafe { unlinkat(parent_fd, path.as_ptr(), 0) }).map(drop) } - // ...unless this was supposed to be the deletion root directory + // ...unless this was supposed to be the deletion root directory. We don't want + // to delete a file at the root, so we just forward the error. None => Err(err), }; } @@ -2562,6 +2566,9 @@ mod remove_dir_impl { // into symlinks. let attr = lstat(p)?; if attr.file_type().is_symlink() { + // This would error in `remove_dir_all_recursive` as it is not a directory. + // We promise to delete directory symlinks, so use `unlink` to do that. On Unix, we + // inadvertently also delete symlinks to files. super::unlink(p) } else { remove_dir_all_recursive(None, p) From 02a48893382d6e8e1d3aa17a9ab03d43fe815df8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 10 Sep 2026 14:49:54 -0700 Subject: [PATCH 6/8] Add a `wasm32-none-component` target definition This commit adds a new tier 3 target to the compiler named `wasm32-none-component`. This was previously approved some time ago in rust-lang/compiler-team/948. The main purpose of this target is to provide some means of producing a WebAssembly component which does not, by default, import any APIs at all. Users get to have fine-grained control over what exactly is imported and what exactly is exported. There's no immediate plan at this time to seek out tier 2, so for now this is intended to just be a target that rustc knows about that's useful for experimenting with but otherwise shouldn't cause too much overhead otherwise. --- compiler/rustc_target/src/spec/mod.rs | 1 + .../src/spec/targets/wasm32_none_component.rs | 31 +++++++++++ src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 1 + .../platform-support/wasm32-none-component.md | 54 +++++++++++++++++++ tests/assembly-llvm/targets/targets-elf.rs | 3 ++ 6 files changed, 91 insertions(+) create mode 100644 compiler/rustc_target/src/spec/targets/wasm32_none_component.rs create mode 100644 src/doc/rustc/src/platform-support/wasm32-none-component.md diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 6c7f5a7772323..ae17e37e29f86 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1511,6 +1511,7 @@ supported_targets! { ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc), ("thumbv7a-uwp-windows-msvc", thumbv7a_uwp_windows_msvc), + ("wasm32-none-component", wasm32_none_component), ("wasm32-unknown-emscripten", wasm32_unknown_emscripten), ("wasm32-unknown-unknown", wasm32_unknown_unknown), ("wasm32v1-none", wasm32v1_none), diff --git a/compiler/rustc_target/src/spec/targets/wasm32_none_component.rs b/compiler/rustc_target/src/spec/targets/wasm32_none_component.rs new file mode 100644 index 0000000000000..6bedf1e4fc0f5 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/wasm32_none_component.rs @@ -0,0 +1,31 @@ +use crate::spec::{Arch, Cc, LinkerFlavor, Os, Target, TargetMetadata, base}; + +pub(crate) fn target() -> Target { + let mut options = base::wasm::options(); + + options.os = Os::None; + options.linker = Some("wasm-component-ld".into()); + + options.add_pre_link_args( + LinkerFlavor::WasmLld(Cc::No), + &[ + // For now this target just never has an entry symbol no matter the output + // type, so unconditionally pass this. + "--no-entry", + ], + ); + + Target { + llvm_target: "wasm32-none-component".into(), + metadata: TargetMetadata { + description: Some("WebAssembly".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 32, + data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20".into(), + arch: Arch::Wasm32, + options, + } +} diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 953789648485b..7588b749a9bce 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -145,6 +145,7 @@ - [\*-pc-windows-msvc](platform-support/windows-msvc.md) - [\*-uwp-windows-msvc](platform-support/uwp-windows-msvc.md) - [\*-wrs-vxworks](platform-support/vxworks.md) + - [wasm32-none-component](platform-support/wasm32-none-component.md) - [wasm32-wasip1](platform-support/wasm32-wasip1.md) - [wasm32-wasip1-threads](platform-support/wasm32-wasip1-threads.md) - [wasm32-wasip2](platform-support/wasm32-wasip2.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 2321dec16b8eb..e890c83dbe9c7 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -448,6 +448,7 @@ target | std | host | notes [`thumbv8m.base-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv8M Baseline with NuttX [`thumbv8m.main-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv8M Mainline with NuttX [`thumbv8m.main-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv8M Mainline with NuttX, hardfloat +[`wasm32-none-component`](platform-support/wasm32-none-component.md) | * | | WebAssembly bare components [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly [`wasm32-wali-linux-musl`](platform-support/wasm32-wali-linux.md) | ? | | WebAssembly with [WALI](https://github.com/arjunr2/WALI) [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ✓ | | x86 64-bit tvOS diff --git a/src/doc/rustc/src/platform-support/wasm32-none-component.md b/src/doc/rustc/src/platform-support/wasm32-none-component.md new file mode 100644 index 0000000000000..be6aab6338f51 --- /dev/null +++ b/src/doc/rustc/src/platform-support/wasm32-none-component.md @@ -0,0 +1,54 @@ +# `wasm32-none-component` + +**Tier: 3** + +The `wasm32-none-component` target is a `no_std` WebAssembly compilation target. This +target produces a WebAssembly Component as the output and otherwise makes no +assumptions about the environment that it is compiled within. As a `no_std` +compilation target you're required to bring your own `#[global_allocator]` and +`#[panic_handler]`. + +The purpose of this target is to represent a compilation target that produces a +WebAssembly component which otherwise does not bring in any APIs by default. +This is suitable for testing out new component targets, for example, or for +building possibly leaner components than one might acquire with the +`wasm32-wasip{2,3}` targets, for example. + +Components produced for this target are not assumed to have any particular host +that they're going to run within, so ecosystem crates are expected to fall back +to `no_std` paths or wasm paths otherwise. + +One example usage of this target is to build a custom SDK based on the +`wit-bindgen` crate on crates.io. This provides users the ability to import +functions into a component, but this is an opt-in feature per build and +otherwise won't happen by default. This can additionally be used to define +exports as well. + +## Target maintainers + +[@alexcrichton](https://github.com/alexcrichton) + +## Requirements + +This target is cross-compiled and has no requirements beyond the base LLVM +toolchain. The target uses `wasm-component-ld` to link which requires LLD to be +built from the Rust source tree, and this ships by default with compiler builds. + +## Conditionally compiling code + +It's recommended to conditionally compile code for this target with: + +```text +#[cfg(all(target_family = "wasm", target_os = "none"))] +``` + +It's worth noting though that this does not specifically select this target +uniquely as this also matches the `wasm32v1-none` target, for example. Detecting +this target and this target alone currently requires a `build.rs` to look at the +`TARGET` being compiled for to look for the `wasm32-none-component` target name. + +## Enabled WebAssembly features + +The default set of WebAssembly features enabled for compilation is currently the +same as [`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md). See the +documentation there for more information. diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index 075863c673045..2908c659f9f02 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -661,6 +661,9 @@ //@ revisions: wasm32_unknown_unknown //@ [wasm32_unknown_unknown] compile-flags: --target wasm32-unknown-unknown //@ [wasm32_unknown_unknown] needs-llvm-components: webassembly +//@ revisions: wasm32_none_component +//@ [wasm32_none_component] compile-flags: --target wasm32-none-component +//@ [wasm32_none_component] needs-llvm-components: webassembly //@ revisions: wasm32v1_none //@ [wasm32v1_none] compile-flags: --target wasm32v1-none //@ [wasm32v1_none] needs-llvm-components: webassembly From 0df0dfa7f8ed37620da702ae4ac17768d2d0c1ac Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 19 Oct 2026 19:01:27 +0200 Subject: [PATCH 7/8] Update books --- src/doc/nomicon | 2 +- src/doc/reference | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/nomicon b/src/doc/nomicon index 46fc44214afcd..b0bb569883a3e 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 46fc44214afcd159be175c8ee62887cad04f615d +Subproject commit b0bb569883a3e65ab19d4f1adf1b8dbc1629d0a6 diff --git a/src/doc/reference b/src/doc/reference index a286e1ecb8ce1..2dafab96d919d 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit a286e1ecb8ce193d50056e4bb042eea9b23876ef +Subproject commit 2dafab96d919d6ab2884488e970bf95610ff83eb From efecf9b2f36b4d56c6704bd8e8c892d714f88c59 Mon Sep 17 00:00:00 2001 From: THARUN Date: Tue, 20 Oct 2026 01:27:50 +0000 Subject: [PATCH 8/8] Avoid ICE when closure expected signature contains non-lifetime bound variables * typeck: avoid ICE with non-lifetime closure binders * test: add non-lifetime closure binder regression tests and FIXMEs --- compiler/rustc_hir_typeck/src/closure.rs | 18 ++++- tests/crashes/108814.rs | 9 --- tests/crashes/110627.rs | 8 -- tests/crashes/125841.rs | 14 ---- .../closure-expected-sig-bound-type-154537.rs | 41 ++++++++++ ...sure-expected-sig-bound-type-154537.stderr | 76 +++++++++++++++++++ 6 files changed, 133 insertions(+), 33 deletions(-) delete mode 100644 tests/crashes/108814.rs delete mode 100644 tests/crashes/110627.rs delete mode 100644 tests/crashes/125841.rs create mode 100644 tests/ui/traits/non_lifetime_binders/closure-expected-sig-bound-type-154537.rs create mode 100644 tests/ui/traits/non_lifetime_binders/closure-expected-sig-bound-type-154537.stderr diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 79b4eff9153b0..7423d7d94d7f0 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -481,8 +481,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { cause_span: Option, projection: ty::PolyProjectionClause<'tcx>, ) -> Option> { + // FIXME(non_lifetime_binders): provide better diagnostics. Should non-lifetime binders + // in opaques with fn traits bound be rejected? + if projection.has_non_region_bound_vars() { + return None; + } let projection = self.deeply_resolve_ignoring_regions(projection); - let arg_param_ty = projection.skip_binder().projection_term.args.type_at(1); debug!(?arg_param_ty); @@ -526,6 +530,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { cause_span: Option, projection: ty::PolyProjectionClause<'tcx>, ) -> Option> { + // FIXME(non_lifetime_binders): provide better diagnostics. Should non-lifetime binders + // in opaques with fn traits bound be rejected? + if projection.has_non_region_bound_vars() { + return None; + } let projection = self.deeply_resolve_ignoring_regions(projection); let arg_param_ty = projection.skip_binder().projection_term.args.type_at(1); @@ -665,7 +674,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Watch out for some surprises and just ignore the // expectation if things don't see to match up with what we // expect. - if expected_sig.sig.c_variadic() != decl.c_variadic() { + + // FIXME(non_lifetime_binders): provide better diagnostics. Should non-lifetime binders + // in opaques with fn traits bound be rejected? + if expected_sig.sig.c_variadic() != decl.c_variadic() + || expected_sig.sig.has_non_region_bound_vars() + { return self.sig_of_closure_no_expectation(expr_def_id, decl, closure_kind); } else if expected_sig.sig.skip_binder().inputs_and_output.len() != decl.inputs.len() + 1 { return self.sig_of_closure_with_mismatched_number_of_arguments( diff --git a/tests/crashes/108814.rs b/tests/crashes/108814.rs deleted file mode 100644 index c8db848f2e188..0000000000000 --- a/tests/crashes/108814.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #108814 - -#![feature(non_lifetime_binders)] - -fn take(_: impl for FnOnce(T) -> T) {} - -fn main() { - take(|x| x) -} diff --git a/tests/crashes/110627.rs b/tests/crashes/110627.rs deleted file mode 100644 index 752682fa6059e..0000000000000 --- a/tests/crashes/110627.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ known-bug: #110627 -#![feature(non_lifetime_binders)] - -fn take(id: impl for Fn(T) -> T) {} - -fn main() { - take(|x| x) -} diff --git a/tests/crashes/125841.rs b/tests/crashes/125841.rs deleted file mode 100644 index e2e61071f1df9..0000000000000 --- a/tests/crashes/125841.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ known-bug: rust-lang/rust#125841 -#![feature(non_lifetime_binders)] -fn take(id: impl for Fn(T) -> T) { - id(0); - id(""); -} - -fn take2() -> impl for Fn(T) -> T { - |x| x -} - -fn main() { - take(|x| take2) -} diff --git a/tests/ui/traits/non_lifetime_binders/closure-expected-sig-bound-type-154537.rs b/tests/ui/traits/non_lifetime_binders/closure-expected-sig-bound-type-154537.rs new file mode 100644 index 0000000000000..1f186718acb60 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/closure-expected-sig-bound-type-154537.rs @@ -0,0 +1,41 @@ +//@ check-fail +//! Regression test for issues: +//! - +//! - +//! - +//! - +//! +//! FIXME(non_lifetime_binders): provide better diagnostics. Should non-lifetime binders +//! in opaques with fn traits bound be rejected? + +#![feature(non_lifetime_binders)] + +// Variant 1: #154537 +fn test_return_fn() -> impl for Fn() -> T { + //~^ ERROR type mismatch + || 3 +} + +// Variant 2: #108814 +fn take_fnonce(_: impl for FnOnce(T) -> T) {} + +// Variant 3: #110627 +fn take_fn(_id: impl for Fn(T) -> T) {} + +// Variant 4: #125841 +fn take_nested_fn(_id: impl for Fn(T) -> T) {} +fn take2() -> impl for Fn(T) -> T { + //~^ ERROR type mismatch in closure arguments + |x| x +} + +fn main() { + take_fnonce(|x| x); + //~^ ERROR type mismatch in closure arguments + + take_fn(|x| x); + //~^ ERROR type mismatch in closure arguments + + take_nested_fn(|x| take2); + //~^ ERROR type mismatch in closure arguments +} diff --git a/tests/ui/traits/non_lifetime_binders/closure-expected-sig-bound-type-154537.stderr b/tests/ui/traits/non_lifetime_binders/closure-expected-sig-bound-type-154537.stderr new file mode 100644 index 0000000000000..89ff8667c4875 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/closure-expected-sig-bound-type-154537.stderr @@ -0,0 +1,76 @@ +error[E0271]: type mismatch resolving `<{closure@closure-expected-sig-bound-type-154537.rs:16:5} as FnOnce<()>>::Output == T` + --> $DIR/closure-expected-sig-bound-type-154537.rs:14:24 + | +LL | fn test_return_fn() -> impl for Fn() -> T { + | ^^^^^^^^^^^^^^^^^^^^^ expected integer, found placeholder type + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-expected-sig-bound-type-154537.rs:27:15 + | +LL | fn take2() -> impl for Fn(T) -> T { + | ^^^^^^^^^^^^^^^^^^^^^^ expected due to this +LL | +LL | |x| x + | ----- + | | + | found signature defined here + | return type was inferred to be `{closure@$DIR/closure-expected-sig-bound-type-154537.rs:29:5: 29:8}` here + | + = note: expected closure signature `fn(T) -> _` + found closure signature `fn(_) -> _` + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-expected-sig-bound-type-154537.rs:33:5 + | +LL | take_fnonce(|x| x); + | ^^^^^^^^^^^^---^^^ + | | | + | | found signature defined here + | expected due to this + | + = note: expected closure signature `fn(T) -> _` + found closure signature `fn(_) -> _` +note: required by a bound in `take_fnonce` + --> $DIR/closure-expected-sig-bound-type-154537.rs:20:24 + | +LL | fn take_fnonce(_: impl for FnOnce(T) -> T) {} + | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `take_fnonce` + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-expected-sig-bound-type-154537.rs:36:5 + | +LL | take_fn(|x| x); + | ^^^^^^^^---^^^ + | | | + | | found signature defined here + | expected due to this + | + = note: expected closure signature `fn(T) -> _` + found closure signature `fn(_) -> _` +note: required by a bound in `take_fn` + --> $DIR/closure-expected-sig-bound-type-154537.rs:23:22 + | +LL | fn take_fn(_id: impl for Fn(T) -> T) {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `take_fn` + +error[E0631]: type mismatch in closure arguments + --> $DIR/closure-expected-sig-bound-type-154537.rs:39:5 + | +LL | take_nested_fn(|x| take2); + | ^^^^^^^^^^^^^^^---^^^^^^^ + | | | + | | found signature defined here + | expected due to this + | + = note: expected closure signature `fn(T) -> _` + found closure signature `fn(_) -> _` +note: required by a bound in `take_nested_fn` + --> $DIR/closure-expected-sig-bound-type-154537.rs:26:29 + | +LL | fn take_nested_fn(_id: impl for Fn(T) -> T) {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `take_nested_fn` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0271, E0631. +For more information about an error, try `rustc --explain E0271`.