diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7791551c..2129a622 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,11 +21,22 @@ jobs: toolchain: ${{ matrix.target == 'i686-pc-windows-gnu' && format('{0}-i686-pc-windows-gnu', matrix.channel) || matrix.channel }} target: ${{ matrix.target }} override: true - components: rustfmt - - uses: actions-rs/cargo@v1 + components: rustfmt, clippy + - name: Check code format + uses: actions-rs/cargo@v1 with: command: fmt args: --all -- --check + - name: Check clippy with default features + uses: actions-rs/cargo@v1 + with: + command: clippy + args: --all -- -D warnings + - name: Check clippy with all features + uses: actions-rs/cargo@v1 + with: + command: clippy + args: --all --all-features -- -D warnings - name: Run cargo deny if: ${{ contains(matrix.os, 'ubuntu') }} uses: EmbarkStudios/cargo-deny-action@v2 diff --git a/core/src/common/constants.rs b/core/src/common/constants.rs index b6d4a98a..f807c6f5 100644 --- a/core/src/common/constants.rs +++ b/core/src/common/constants.rs @@ -125,6 +125,8 @@ pub enum Syscall { SetFilePointerEx, #[cfg(windows)] WaitOnAddress, + #[cfg(windows)] + WSAPoll, } impl Syscall { diff --git a/core/src/coroutine/local.rs b/core/src/coroutine/local.rs index 8354f9ee..42ddf52a 100644 --- a/core/src/coroutine/local.rs +++ b/core/src/coroutine/local.rs @@ -16,7 +16,7 @@ impl<'c> CoroutineLocal<'c> { pub fn put(&self, key: &'c str, val: V) -> Option { let v = Box::leak(Box::new(val)); self.0 - .insert(key, std::ptr::from_mut::(v) as usize) + .insert(key, std::ptr::from_mut(v) as usize) .map(|ptr| unsafe { *Box::from_raw((ptr as *mut c_void).cast::()) }) } diff --git a/core/src/net/event_loop.rs b/core/src/net/event_loop.rs index 94c8a9b0..543bd809 100644 --- a/core/src/net/event_loop.rs +++ b/core/src/net/event_loop.rs @@ -123,7 +123,7 @@ impl<'e> EventLoop<'e> { let syscall_mask = >::into(syscall).as_ptr() as usize; let token = thread_id as usize ^ syscall_mask; if Syscall::nio() != syscall { - eprintln!("{syscall} {token}"); + eprintln!("generate token:{token} for {syscall}"); } token } @@ -255,8 +255,7 @@ impl<'e> EventLoop<'e> { continue; } // resolve completed read/write tasks - let result = cqe.result() as c_longlong; - eprintln!("io_uring finish {token} {result}"); + let result = c_longlong::from(cqe.result()); if let Some((_, pair)) = self.syscall_wait_table.remove(&token) { let (lock, cvar) = &*pair; let mut pending = lock.lock().expect("lock failed"); diff --git a/core/src/net/mod.rs b/core/src/net/mod.rs index a9283020..b512a39a 100644 --- a/core/src/net/mod.rs +++ b/core/src/net/mod.rs @@ -11,9 +11,6 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Condvar, Mutex}; use std::time::Duration; -/// 做C兼容时会用到 -pub type UserFunc = extern "C" fn(usize) -> usize; - cfg_if::cfg_if! { if #[cfg(all(target_os = "linux", feature = "io_uring"))] { use libc::{epoll_event, iovec, msghdr, off_t, size_t, sockaddr, socklen_t}; @@ -21,9 +18,16 @@ cfg_if::cfg_if! { } } +/// 做C兼容时会用到 +pub type UserFunc = extern "C" fn(usize) -> usize; + mod selector; -#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] +#[allow( + clippy::cast_possible_truncation, + clippy::cast_sign_loss, + clippy::too_many_arguments +)] #[cfg(all(target_os = "linux", feature = "io_uring"))] mod operator; diff --git a/core/src/net/operator/linux/mod.rs b/core/src/net/operator/linux/mod.rs index 94d2bfd3..e9178d1b 100644 --- a/core/src/net/operator/linux/mod.rs +++ b/core/src/net/operator/linux/mod.rs @@ -574,7 +574,6 @@ impl Operator<'_> { ) } - #[allow(clippy::too_many_arguments)] pub(crate) fn sendto( &self, user_data: usize, diff --git a/core/src/syscall/unix/connect.rs b/core/src/syscall/unix/connect.rs index 501fdb9e..788f250f 100644 --- a/core/src/syscall/unix/connect.rs +++ b/core/src/syscall/unix/connect.rs @@ -74,14 +74,14 @@ impl ConnectSyscall for NioConnectSyscall { { break; } - let mut err: c_int = 0; + let mut err = 0; unsafe { let mut len: socklen_t = std::mem::zeroed(); r = libc::getsockopt( fd, libc::SOL_SOCKET, libc::SO_ERROR, - (std::ptr::addr_of_mut!(err)).cast::(), + std::ptr::addr_of_mut!(err).cast::(), &mut len, ); } diff --git a/core/src/syscall/unix/mod.rs b/core/src/syscall/unix/mod.rs index 9db30ec4..55fd04a8 100644 --- a/core/src/syscall/unix/mod.rs +++ b/core/src/syscall/unix/mod.rs @@ -23,7 +23,8 @@ macro_rules! impl_facade { let new_state = $crate::common::constants::SyscallState::Executing; if co.syscall((), syscall, new_state).is_err() { $crate::error!("{} change to syscall {} {} failed !", - co.name(), syscall, new_state); + co.name(), syscall, new_state + ); } } let r = self.inner.$syscall(fn_ptr, $($arg, )*); @@ -32,7 +33,7 @@ macro_rules! impl_facade { $crate::error!("{} change to running state failed !", co.name()); } } - $crate::info!("exit syscall {}", syscall); + $crate::info!("exit syscall {} {:?}", syscall, r); r } } @@ -66,9 +67,7 @@ macro_rules! impl_io_uring { if co.syscall((), syscall, new_state).is_err() { $crate::error!( "{} change to syscall {} {} failed !", - co.name(), - syscall, - new_state + co.name(), syscall, new_state ); } } @@ -84,9 +83,7 @@ macro_rules! impl_io_uring { if co.syscall((), syscall, new_state).is_err() { $crate::error!( "{} change to syscall {} {} failed !", - co.name(), - syscall, - new_state + co.name(), syscall, new_state ); } } diff --git a/core/src/syscall/unix/poll.rs b/core/src/syscall/unix/poll.rs index 4e4d0fce..aa9a94ca 100644 --- a/core/src/syscall/unix/poll.rs +++ b/core/src/syscall/unix/poll.rs @@ -47,7 +47,7 @@ impl PollSyscall for NioPollSyscall { let mut t = if timeout < 0 { c_int::MAX } else { timeout }; let mut x = 1; let mut r; - // just check select every x ms + // just check poll every x ms loop { r = self.inner.poll(fn_ptr, fds, nfds, 0); if r != 0 || t == 0 { diff --git a/core/src/syscall/unix/select.rs b/core/src/syscall/unix/select.rs index 94e8ea66..d9ebc99b 100644 --- a/core/src/syscall/unix/select.rs +++ b/core/src/syscall/unix/select.rs @@ -35,8 +35,13 @@ trait SelectSyscall { } impl_facade!(SelectSyscallFacade, SelectSyscall, - select(nfds: c_int, readfds: *mut fd_set, writefds: *mut fd_set, - errorfds: *mut fd_set, timeout: *mut timeval) -> c_int + select( + nfds: c_int, + readfds: *mut fd_set, + writefds: *mut fd_set, + errorfds: *mut fd_set, + timeout: *mut timeval + ) -> c_int ); #[repr(C)] @@ -78,7 +83,7 @@ impl SelectSyscall for NioSelectSyscall { } let mut x = 1; let mut r; - // just check poll every x ms + // just check select every x ms loop { r = self .inner @@ -111,6 +116,11 @@ impl SelectSyscall for NioSelectSyscall { } impl_raw!(RawSelectSyscall, SelectSyscall, - select(nfds: c_int, readfds: *mut fd_set, writefds: *mut fd_set, - errorfds: *mut fd_set, timeout: *mut timeval) -> c_int + select( + nfds: c_int, + readfds: *mut fd_set, + writefds: *mut fd_set, + errorfds: *mut fd_set, + timeout: *mut timeval + ) -> c_int ); diff --git a/core/src/syscall/windows/WSAPoll.rs b/core/src/syscall/windows/WSAPoll.rs new file mode 100644 index 00000000..d3434c89 --- /dev/null +++ b/core/src/syscall/windows/WSAPoll.rs @@ -0,0 +1,70 @@ +use crate::net::EventLoops; +use once_cell::sync::Lazy; +use std::ffi::{c_int, c_uint}; +use std::time::Duration; +use windows_sys::Win32::Networking::WinSock::WSAPOLLFD; + +#[must_use] +pub extern "system" fn WSAPoll( + fn_ptr: Option<&extern "system" fn(*mut WSAPOLLFD, c_uint, c_int) -> c_int>, + fds: *mut WSAPOLLFD, + nfds: c_uint, + timeout: c_int, +) -> c_int { + static CHAIN: Lazy>> = + Lazy::new(Default::default); + CHAIN.WSAPoll(fn_ptr, fds, nfds, timeout) +} + +trait PollSyscall { + extern "system" fn WSAPoll( + &self, + fn_ptr: Option<&extern "system" fn(*mut WSAPOLLFD, c_uint, c_int) -> c_int>, + fds: *mut WSAPOLLFD, + nfds: c_uint, + timeout: c_int, + ) -> c_int; +} + +impl_facade!(PollSyscallFacade, PollSyscall, + WSAPoll(fds: *mut WSAPOLLFD, nfds: c_uint, timeout: c_int) -> c_int +); + +#[repr(C)] +#[derive(Debug, Default)] +struct NioPollSyscall { + inner: I, +} + +impl PollSyscall for NioPollSyscall { + extern "system" fn WSAPoll( + &self, + fn_ptr: Option<&extern "system" fn(*mut WSAPOLLFD, c_uint, c_int) -> c_int>, + fds: *mut WSAPOLLFD, + nfds: c_uint, + timeout: c_int, + ) -> c_int { + let mut t = if timeout < 0 { c_int::MAX } else { timeout }; + let mut x = 1; + let mut r; + // just check poll every x ms + loop { + r = self.inner.WSAPoll(fn_ptr, fds, nfds, 0); + if r != 0 || t == 0 { + break; + } + _ = EventLoops::wait_event(Some(Duration::from_millis(t.min(x) as u64))); + if t != c_int::MAX { + t = if t > x { t - x } else { 0 }; + } + if x < 16 { + x <<= 1; + } + } + r + } +} + +impl_raw!(RawPollSyscall, PollSyscall, windows_sys::Win32::Networking::WinSock, + WSAPoll(fds: *mut WSAPOLLFD, nfds: c_uint, timeout: c_int) -> c_int +); diff --git a/core/src/syscall/windows/connect.rs b/core/src/syscall/windows/connect.rs new file mode 100644 index 00000000..f32af718 --- /dev/null +++ b/core/src/syscall/windows/connect.rs @@ -0,0 +1,108 @@ +use crate::net::EventLoops; +use crate::syscall::common::{is_blocking, reset_errno, set_blocking, set_errno, set_non_blocking}; +use once_cell::sync::Lazy; +use std::ffi::c_int; +use std::io::Error; +use windows_sys::Win32::Networking::WinSock::{getpeername, getsockopt, SO_ERROR, SOCKADDR, SOCKET, SOL_SOCKET, WSAEALREADY, WSAEINPROGRESS, WSAEINTR, WSAETIMEDOUT}; + +#[must_use] +pub extern "system" fn connect( + fn_ptr: Option<&extern "system" fn(SOCKET, *const SOCKADDR, c_int) -> c_int>, + socket: SOCKET, + address: *const SOCKADDR, + len: c_int, +) -> c_int { + static CHAIN: Lazy>> = + Lazy::new(Default::default); + CHAIN.connect(fn_ptr, socket, address, len) +} + +trait ConnectSyscall { + extern "system" fn connect( + &self, + fn_ptr: Option<&extern "system" fn(SOCKET, *const SOCKADDR, c_int) -> c_int>, + fd: SOCKET, + address: *const SOCKADDR, + len: c_int, + ) -> c_int; +} + +impl_facade!(ConnectSyscallFacade, ConnectSyscall, + connect(fd: SOCKET, address: *const SOCKADDR, len: c_int) -> c_int +); + +#[repr(C)] +#[derive(Debug, Default)] +struct NioConnectSyscall { + inner: I, +} + +impl ConnectSyscall for NioConnectSyscall { + extern "system" fn connect( + &self, + fn_ptr: Option<&extern "system" fn(SOCKET, *const SOCKADDR, c_int) -> c_int>, + fd: SOCKET, + address: *const SOCKADDR, + len: c_int, + ) -> c_int { + let blocking = is_blocking(fd); + if blocking { + set_non_blocking(fd); + } + let mut r = self.inner.connect(fn_ptr, fd, address, len); + loop { + if r == 0 { + reset_errno(); + break; + } + let errno = Error::last_os_error().raw_os_error(); + if errno == Some(WSAEINPROGRESS) || errno == Some(WSAEALREADY) { + //阻塞,直到写事件发生 + if EventLoops::wait_write_event( + fd as _, + Some(crate::common::constants::SLICE) + ).is_err() { + break; + } + let mut err = 0; + unsafe { + let mut len: c_int = std::mem::zeroed(); + r = getsockopt( + fd, + SOL_SOCKET, + SO_ERROR, + std::ptr::addr_of_mut!(err).cast::(), + &mut len, + ); + } + if r != 0 { + r = -1; + break; + } + if err != 0 { + set_errno(err); + r = -1; + break; + }; + unsafe { + let mut address = std::mem::zeroed(); + let mut address_len = std::mem::zeroed(); + r = getpeername(fd, &mut address, &mut address_len); + } + } else if errno != Some(WSAEINTR) { + break; + } + } + if r == -1 && Error::last_os_error().raw_os_error() == Some(WSAETIMEDOUT) { + set_errno(WSAEINPROGRESS.try_into().expect("overflow")); + } + if blocking { + set_blocking(fd); + } + r + } +} + +impl_raw!(RawConnectSyscall, ConnectSyscall, windows_sys::Win32::Networking::WinSock, + connect(fd: SOCKET, address: *const SOCKADDR, len: c_int) -> c_int +); diff --git a/core/src/syscall/windows/mod.rs b/core/src/syscall/windows/mod.rs index 0738f39c..51bbc59e 100644 --- a/core/src/syscall/windows/mod.rs +++ b/core/src/syscall/windows/mod.rs @@ -36,7 +36,7 @@ macro_rules! impl_facade { $crate::error!("{} change to running state failed !", co.name()); } } - $crate::info!("exit syscall {}", syscall); + $crate::info!("exit syscall {} {:?}", syscall, r); r } } @@ -473,6 +473,7 @@ syscall_mod!( WSARecv; WSASend; WSASocketW; + WSAPoll; setsockopt; accept; ioctlsocket; @@ -481,6 +482,8 @@ syscall_mod!( send; shutdown; socket; + connect; + select; CreateFileW; SetFilePointerEx; WaitOnAddress diff --git a/core/src/syscall/windows/select.rs b/core/src/syscall/windows/select.rs new file mode 100644 index 00000000..e0648275 --- /dev/null +++ b/core/src/syscall/windows/select.rs @@ -0,0 +1,126 @@ +use crate::net::EventLoops; +use once_cell::sync::Lazy; +use std::ffi::{c_int, c_uint}; +use std::time::Duration; +use windows_sys::Win32::Networking::WinSock::{FD_SET, TIMEVAL}; + +#[must_use] +pub extern "system" fn select( + fn_ptr: Option< + &extern "system" fn(c_int, *mut FD_SET, *mut FD_SET, *mut FD_SET, *mut TIMEVAL) -> c_int, + >, + nfds: c_int, + readfds: *mut FD_SET, + writefds: *mut FD_SET, + errorfds: *mut FD_SET, + timeout: *mut TIMEVAL, +) -> c_int { + static CHAIN: Lazy>> = + Lazy::new(Default::default); + CHAIN.select(fn_ptr, nfds, readfds, writefds, errorfds, timeout) +} + +trait SelectSyscall { + extern "system" fn select( + &self, + fn_ptr: Option< + &extern "system" fn(c_int, *mut FD_SET, *mut FD_SET, *mut FD_SET, *mut TIMEVAL) -> c_int, + >, + nfds: c_int, + readfds: *mut FD_SET, + writefds: *mut FD_SET, + errorfds: *mut FD_SET, + timeout: *mut TIMEVAL, + ) -> c_int; +} + +impl_facade!(SelectSyscallFacade, SelectSyscall, + select( + nfds: c_int, + readfds: *mut FD_SET, + writefds: *mut FD_SET, + errorfds: *mut FD_SET, + timeout: *mut TIMEVAL + ) -> c_int +); + +#[repr(C)] +#[derive(Debug, Default)] +struct NioSelectSyscall { + inner: I, +} + +impl SelectSyscall for NioSelectSyscall { + extern "system" fn select( + &self, + fn_ptr: Option< + &extern "system" fn(c_int, *mut FD_SET, *mut FD_SET, *mut FD_SET, *mut TIMEVAL) -> c_int, + >, + nfds: c_int, + readfds: *mut FD_SET, + writefds: *mut FD_SET, + errorfds: *mut FD_SET, + timeout: *mut TIMEVAL, + ) -> c_int { + let mut t = if timeout.is_null() { + c_uint::MAX + } else { + unsafe { ((*timeout).tv_sec as c_uint) * 1_000_000 + (*timeout).tv_usec as c_uint } + }; + let mut o = TIMEVAL { + tv_sec: 0, + tv_usec: 0, + }; + let mut s: [FD_SET; 3] = unsafe { std::mem::zeroed() }; + if !readfds.is_null() { + s[0] = unsafe { *readfds }; + } + if !writefds.is_null() { + s[1] = unsafe { *writefds }; + } + if !errorfds.is_null() { + s[2] = unsafe { *errorfds }; + } + let mut x = 1; + let mut r; + // just check select every x ms + loop { + r = self + .inner + .select(fn_ptr, nfds, readfds, writefds, errorfds, &mut o); + if r != 0 || t == 0 { + break; + } + _ = EventLoops::wait_event(Some(Duration::from_millis(u64::from(t.min(x))))); + if t != c_uint::MAX { + t = if t > x { t - x } else { 0 }; + } + if x < 16 { + x <<= 1; + } + + if !readfds.is_null() { + unsafe { *readfds = s[0] }; + } + if !writefds.is_null() { + unsafe { *writefds = s[1] }; + } + if !errorfds.is_null() { + unsafe { *errorfds = s[2] }; + } + o.tv_sec = 0; + o.tv_usec = 0; + } + r + } +} + +impl_raw!(RawSelectSyscall, SelectSyscall, windows_sys::Win32::Networking::WinSock, + select( + nfds: c_int, + readfds: *mut FD_SET, + writefds: *mut FD_SET, + errorfds: *mut FD_SET, + timeout: *mut TIMEVAL + ) -> c_int +); diff --git a/hook/src/syscall/windows.rs b/hook/src/syscall/windows.rs index 642dbd3c..afcf3811 100644 --- a/hook/src/syscall/windows.rs +++ b/hook/src/syscall/windows.rs @@ -3,8 +3,8 @@ use std::io::{Error, ErrorKind}; use windows_sys::core::{PCSTR, PCWSTR, PSTR}; use windows_sys::Win32::Foundation::{BOOL, HANDLE, TRUE}; use windows_sys::Win32::Networking::WinSock::{ - IPPROTO, LPWSAOVERLAPPED_COMPLETION_ROUTINE, SEND_RECV_FLAGS, SOCKADDR, SOCKET, - WINSOCK_SHUTDOWN_HOW, WINSOCK_SOCKET_TYPE, WSABUF, WSAPROTOCOL_INFOW, + FD_SET, IPPROTO, LPWSAOVERLAPPED_COMPLETION_ROUTINE, SEND_RECV_FLAGS, SOCKADDR, SOCKET, + TIMEVAL, WINSOCK_SHUTDOWN_HOW, WINSOCK_SOCKET_TYPE, WSABUF, WSAPOLLFD, WSAPROTOCOL_INFOW, }; use windows_sys::Win32::Security::SECURITY_ATTRIBUTES; use windows_sys::Win32::Storage::FileSystem::{ @@ -88,7 +88,6 @@ unsafe fn attach() -> std::io::Result<()> { flags: SEND_RECV_FLAGS ) -> c_int); impl_hook!("ws2_32.dll", SHUTDOWN, shutdown(fd: SOCKET, how: WINSOCK_SHUTDOWN_HOW) -> c_int); - impl_hook!("kernel32.dll", SLEEP, Sleep(dw_milliseconds: u32) -> ()); impl_hook!("ws2_32.dll", SOCKET, socket( domain: c_int, ty: WINSOCK_SOCKET_TYPE, @@ -127,6 +126,19 @@ unsafe fn attach() -> std::io::Result<()> { g: c_uint, dw_flags: c_uint ) -> SOCKET); + impl_hook!("ws2_32.dll", SELECT, select( + nfds: c_int, + readfds: *mut FD_SET, + writefds: *mut FD_SET, + errorfds: *mut FD_SET, + timeout: *mut TIMEVAL + ) -> c_int); + impl_hook!("ws2_32.dll", WSAPOLL, WSAPoll( + fds: *mut WSAPOLLFD, + nfds: c_uint, + timeout: c_int + ) -> c_int); + impl_hook!("kernel32.dll", SLEEP, Sleep(dw_milliseconds: u32) -> ()); impl_hook!("kernel32.dll", CREATEFILEW, CreateFileW( lpfilename: PCWSTR, dwdesiredaccess: c_uint, @@ -142,13 +154,18 @@ unsafe fn attach() -> std::io::Result<()> { lpnewfilepointer : *mut c_longlong, dwmovemethod : SET_FILE_POINTER_MOVE_METHOD ) -> BOOL); - // NOTE: unhook WaitOnAddress due to stack overflow or bug + // NOTE: unhook WaitOnAddress/connect due to stack overflow or bug // impl_hook!("api-ms-win-core-synch-l1-2-0.dll", WAITONADDRESS, WaitOnAddress( // address: *const c_void, // compareaddress: *const c_void, // addresssize: usize, // dwmilliseconds: c_uint // ) -> BOOL); + // impl_hook!("ws2_32.dll", CONNECT, connect( + // fd: SOCKET, + // address: *const SOCKADDR, + // len: c_int + // ) -> c_int); // Enable the hook minhook::MinHook::enable_all_hooks() .map_err(|_| Error::new(ErrorKind::Other, "init all hooks failed !")) diff --git a/open-coroutine/src/lib.rs b/open-coroutine/src/lib.rs index 205ae160..f6d0aec2 100644 --- a/open-coroutine/src/lib.rs +++ b/open-coroutine/src/lib.rs @@ -114,14 +114,14 @@ pub fn task R>(f: F, param: P) -> JoinHa let ptr = &mut *((input as *mut c_void).cast::<(F, P)>()); let data = std::ptr::read_unaligned(ptr); let result: &'static mut R = Box::leak(Box::new((data.0)(data.1))); - std::ptr::from_mut::(result).cast::() as usize + std::ptr::from_mut(result).cast::() as usize } } let inner = Box::leak(Box::new((f, param))); unsafe { task_crate( task_main::, - std::ptr::from_mut::<(F, P)>(inner).cast::() as usize, + std::ptr::from_mut(inner).cast::() as usize, ) .into() } @@ -134,10 +134,9 @@ pub struct JoinHandle(open_coroutine_core::net::join::JoinHandle, PhantomData #[allow(missing_docs)] impl JoinHandle { - #[allow(clippy::cast_possible_truncation)] pub fn timeout_join(&self, dur: Duration) -> std::io::Result> { unsafe { - let ptr = task_timeout_join(self, dur.as_nanos() as u64); + let ptr = task_timeout_join(self, dur.as_nanos().try_into().expect("overflow")); match ptr.cmp(&0) { Ordering::Less => Err(Error::new(ErrorKind::Other, "timeout join failed")), Ordering::Equal => Ok(None), @@ -211,7 +210,7 @@ pub fn maybe_grow R>( let ptr = &mut *((input as *mut c_void).cast::()); let data = std::ptr::read_unaligned(ptr); let result: &'static mut R = Box::leak(Box::new(data())); - std::ptr::from_mut::(result).cast::() as usize + std::ptr::from_mut(result).cast::() as usize } } let inner = Box::leak(Box::new(f)); @@ -220,7 +219,7 @@ pub fn maybe_grow R>( red_zone, stack_size, execute_on_stack::, - std::ptr::from_mut::(inner).cast::() as usize, + std::ptr::from_mut(inner).cast::() as usize, ); if ptr < 0 { return Err(Error::new(ErrorKind::InvalidInput, "grow stack failed"));