From aa21d439fab00b7799c3db3971a2dfd9459b6128 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 1 Feb 2022 12:26:28 -0800 Subject: [PATCH] Support functions that don't return (#1485) --- .github/workflows/test.yml | 2 ++ crates/libs/bindgen/src/functions.rs | 19 ++++++++++++++++--- crates/libs/metadata/src/tables/method_def.rs | 4 ++++ .../Win32/System/Diagnostics/Debug/mod.rs | 6 +++--- .../Windows/Win32/System/LibraryLoader/mod.rs | 2 +- .../src/Windows/Win32/System/Threading/mod.rs | 4 ++-- .../Win32/System/Diagnostics/Debug/mod.rs | 12 ++++++------ .../Windows/Win32/System/LibraryLoader/mod.rs | 4 ++-- .../src/Windows/Win32/System/Threading/mod.rs | 8 ++++---- crates/tests/does_not_return/Cargo.toml | 17 +++++++++++++++++ crates/tests/does_not_return/src/lib.rs | 1 + crates/tests/does_not_return/tests/sys.rs | 10 ++++++++++ crates/tests/does_not_return/tests/win.rs | 10 ++++++++++ 13 files changed, 78 insertions(+), 21 deletions(-) create mode 100644 crates/tests/does_not_return/Cargo.toml create mode 100644 crates/tests/does_not_return/src/lib.rs create mode 100644 crates/tests/does_not_return/tests/sys.rs create mode 100644 crates/tests/does_not_return/tests/win.rs diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a31bc74718..e9ac74b0ae 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -78,6 +78,7 @@ jobs: cargo test --target ${{ matrix.target }} -p test_core && cargo test --target ${{ matrix.target }} -p test_debug && cargo test --target ${{ matrix.target }} -p test_deprecated && + cargo test --target ${{ matrix.target }} -p test_does_not_return && cargo test --target ${{ matrix.target }} -p test_enums && cargo test --target ${{ matrix.target }} -p test_handles && cargo test --target ${{ matrix.target }} -p test_helpers && @@ -176,6 +177,7 @@ jobs: cargo clippy -p test_core && cargo clippy -p test_debug && cargo clippy -p test_deprecated && + cargo clippy -p test_does_not_return && cargo clippy -p test_enums && cargo clippy -p test_handles && cargo clippy -p test_helpers && diff --git a/crates/libs/bindgen/src/functions.rs b/crates/libs/bindgen/src/functions.rs index 8af9f609f3..a8870e21e6 100644 --- a/crates/libs/bindgen/src/functions.rs +++ b/crates/libs/bindgen/src/functions.rs @@ -53,8 +53,12 @@ fn gen_function_if(entry: &[ElementType], gen: &Gen) -> TokenStream { fn gen_sys_function(def: &MethodDef, gen: &Gen) -> TokenStream { let name = gen_ident(def.name()); let signature = def.signature(&[]); - let return_type = gen_return_sig(&signature, gen); let cfg = gen.function_cfg(def).gen_with_doc(gen); + let mut return_type = gen_return_sig(&signature, gen); + + if return_type.is_empty() { + return_type = does_not_return(def); + } let params = signature.params.iter().map(|p| { let name = gen_param_name(&p.param); @@ -214,16 +218,17 @@ fn gen_win_function(def: &MethodDef, gen: &Gen) -> TokenStream { SignatureKind::ReturnVoid => { let params = gen_win32_params(&signature.params, gen); let args = signature.params.iter().map(gen_win32_abi_arg); + let does_not_return = does_not_return(def); quote! { #cfg #[inline] - pub unsafe fn #name<#constraints>(#params) { + pub unsafe fn #name<#constraints>(#params) #does_not_return { #[cfg(windows)] { #link_attr extern "system" { - fn #name(#(#abi_params),*); + fn #name(#(#abi_params),*) #does_not_return; } #name(#(#args),*) } @@ -234,3 +239,11 @@ fn gen_win_function(def: &MethodDef, gen: &Gen) -> TokenStream { } } } + +fn does_not_return(def: &MethodDef) -> TokenStream { + if def.does_not_return() { + quote! { -> ! } + } else { + quote! {} + } +} diff --git a/crates/libs/metadata/src/tables/method_def.rs b/crates/libs/metadata/src/tables/method_def.rs index 38c8ee9959..a751892f5d 100644 --- a/crates/libs/metadata/src/tables/method_def.rs +++ b/crates/libs/metadata/src/tables/method_def.rs @@ -69,6 +69,10 @@ impl MethodDef { self.has_attribute("DeprecatedAttribute") } + pub fn does_not_return(&self) -> bool { + self.has_attribute("DoesNotReturnAttribute") + } + pub fn static_lib(&self) -> Option { self.attributes() .filter_map(|attribute| match attribute.name() { diff --git a/crates/libs/sys/src/Windows/Win32/System/Diagnostics/Debug/mod.rs b/crates/libs/sys/src/Windows/Win32/System/Diagnostics/Debug/mod.rs index ef726dafc7..200f290627 100644 --- a/crates/libs/sys/src/Windows/Win32/System/Diagnostics/Debug/mod.rs +++ b/crates/libs/sys/src/Windows/Win32/System/Diagnostics/Debug/mod.rs @@ -110,7 +110,7 @@ extern "system" { #[cfg(feature = "Win32_Foundation")] pub fn FatalAppExitW(uaction: u32, lpmessagetext: super::super::super::Foundation::PWSTR); #[doc = "*Required features: 'Win32_System_Diagnostics_Debug'*"] - pub fn FatalExit(exitcode: i32); + pub fn FatalExit(exitcode: i32) -> !; #[doc = "*Required features: 'Win32_System_Diagnostics_Debug', 'Win32_Foundation'*"] #[cfg(feature = "Win32_Foundation")] pub fn FindDebugInfoFile(filename: super::super::super::Foundation::PSTR, symbolpath: super::super::super::Foundation::PSTR, debugfilepath: super::super::super::Foundation::PSTR) -> super::super::super::Foundation::HANDLE; @@ -276,7 +276,7 @@ extern "system" { #[cfg(feature = "Win32_Foundation")] pub fn OutputDebugStringW(lpoutputstring: super::super::super::Foundation::PWSTR); #[doc = "*Required features: 'Win32_System_Diagnostics_Debug'*"] - pub fn RaiseException(dwexceptioncode: u32, dwexceptionflags: u32, nnumberofarguments: u32, lparguments: *const usize); + pub fn RaiseException(dwexceptioncode: u32, dwexceptionflags: u32, nnumberofarguments: u32, lparguments: *const usize) -> !; #[doc = "*Required features: 'Win32_System_Diagnostics_Debug', 'Win32_Foundation', 'Win32_System_Kernel'*"] #[cfg(all(feature = "Win32_Foundation", feature = "Win32_System_Kernel"))] pub fn RaiseFailFastException(pexceptionrecord: *const EXCEPTION_RECORD, pcontextrecord: *const CONTEXT, dwflags: u32); @@ -368,7 +368,7 @@ extern "system" { pub fn RtlPcToFileHeader(pcvalue: *const ::core::ffi::c_void, baseofimage: *mut *mut ::core::ffi::c_void) -> *mut ::core::ffi::c_void; #[doc = "*Required features: 'Win32_System_Diagnostics_Debug', 'Win32_Foundation'*"] #[cfg(feature = "Win32_Foundation")] - pub fn RtlRaiseException(exceptionrecord: *const EXCEPTION_RECORD); + pub fn RtlRaiseException(exceptionrecord: *const EXCEPTION_RECORD) -> !; #[doc = "*Required features: 'Win32_System_Diagnostics_Debug', 'Win32_Foundation', 'Win32_System_Kernel'*"] #[cfg(all(feature = "Win32_Foundation", feature = "Win32_System_Kernel"))] pub fn RtlRestoreContext(contextrecord: *const CONTEXT, exceptionrecord: *const EXCEPTION_RECORD); diff --git a/crates/libs/sys/src/Windows/Win32/System/LibraryLoader/mod.rs b/crates/libs/sys/src/Windows/Win32/System/LibraryLoader/mod.rs index abba3921d7..b4ac531f8d 100644 --- a/crates/libs/sys/src/Windows/Win32/System/LibraryLoader/mod.rs +++ b/crates/libs/sys/src/Windows/Win32/System/LibraryLoader/mod.rs @@ -72,7 +72,7 @@ extern "system" { pub fn FreeLibrary(hlibmodule: super::super::Foundation::HINSTANCE) -> super::super::Foundation::BOOL; #[doc = "*Required features: 'Win32_System_LibraryLoader', 'Win32_Foundation'*"] #[cfg(feature = "Win32_Foundation")] - pub fn FreeLibraryAndExitThread(hlibmodule: super::super::Foundation::HINSTANCE, dwexitcode: u32); + pub fn FreeLibraryAndExitThread(hlibmodule: super::super::Foundation::HINSTANCE, dwexitcode: u32) -> !; #[doc = "*Required features: 'Win32_System_LibraryLoader', 'Win32_Foundation'*"] #[cfg(feature = "Win32_Foundation")] pub fn FreeResource(hresdata: isize) -> super::super::Foundation::BOOL; diff --git a/crates/libs/sys/src/Windows/Win32/System/Threading/mod.rs b/crates/libs/sys/src/Windows/Win32/System/Threading/mod.rs index b56b3e2934..2c0e47fb15 100644 --- a/crates/libs/sys/src/Windows/Win32/System/Threading/mod.rs +++ b/crates/libs/sys/src/Windows/Win32/System/Threading/mod.rs @@ -247,9 +247,9 @@ extern "system" { #[cfg(feature = "Win32_Foundation")] pub fn ExecuteUmsThread(umsthread: *mut ::core::ffi::c_void) -> super::super::Foundation::BOOL; #[doc = "*Required features: 'Win32_System_Threading'*"] - pub fn ExitProcess(uexitcode: u32); + pub fn ExitProcess(uexitcode: u32) -> !; #[doc = "*Required features: 'Win32_System_Threading'*"] - pub fn ExitThread(dwexitcode: u32); + pub fn ExitThread(dwexitcode: u32) -> !; #[doc = "*Required features: 'Win32_System_Threading'*"] pub fn FlsAlloc(lpcallback: PFLS_CALLBACK_FUNCTION) -> u32; #[doc = "*Required features: 'Win32_System_Threading', 'Win32_Foundation'*"] diff --git a/crates/libs/windows/src/Windows/Win32/System/Diagnostics/Debug/mod.rs b/crates/libs/windows/src/Windows/Win32/System/Diagnostics/Debug/mod.rs index 8a76ab770d..af4b2d0cc9 100644 --- a/crates/libs/windows/src/Windows/Win32/System/Diagnostics/Debug/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/System/Diagnostics/Debug/mod.rs @@ -9147,12 +9147,12 @@ pub unsafe fn FatalAppExitW<'a, Param1: ::windows::core::IntoParam<'a, super::su } #[doc = "*Required features: 'Win32_System_Diagnostics_Debug'*"] #[inline] -pub unsafe fn FatalExit(exitcode: i32) { +pub unsafe fn FatalExit(exitcode: i32) -> ! { #[cfg(windows)] { #[link(name = "windows")] extern "system" { - fn FatalExit(exitcode: i32); + fn FatalExit(exitcode: i32) -> !; } FatalExit(::core::mem::transmute(exitcode)) } @@ -59972,12 +59972,12 @@ impl ::core::fmt::Debug for RTL_VIRTUAL_UNWIND_HANDLER_TYPE { } #[doc = "*Required features: 'Win32_System_Diagnostics_Debug'*"] #[inline] -pub unsafe fn RaiseException(dwexceptioncode: u32, dwexceptionflags: u32, nnumberofarguments: u32, lparguments: *const usize) { +pub unsafe fn RaiseException(dwexceptioncode: u32, dwexceptionflags: u32, nnumberofarguments: u32, lparguments: *const usize) -> ! { #[cfg(windows)] { #[link(name = "windows")] extern "system" { - fn RaiseException(dwexceptioncode: u32, dwexceptionflags: u32, nnumberofarguments: u32, lparguments: *const usize); + fn RaiseException(dwexceptioncode: u32, dwexceptionflags: u32, nnumberofarguments: u32, lparguments: *const usize) -> !; } RaiseException(::core::mem::transmute(dwexceptioncode), ::core::mem::transmute(dwexceptionflags), ::core::mem::transmute(nnumberofarguments), ::core::mem::transmute(lparguments)) } @@ -60463,12 +60463,12 @@ pub unsafe fn RtlPcToFileHeader(pcvalue: *const ::core::ffi::c_void, baseofimage #[doc = "*Required features: 'Win32_System_Diagnostics_Debug', 'Win32_Foundation'*"] #[cfg(feature = "Win32_Foundation")] #[inline] -pub unsafe fn RtlRaiseException(exceptionrecord: *const EXCEPTION_RECORD) { +pub unsafe fn RtlRaiseException(exceptionrecord: *const EXCEPTION_RECORD) -> ! { #[cfg(windows)] { #[link(name = "windows")] extern "system" { - fn RtlRaiseException(exceptionrecord: *const EXCEPTION_RECORD); + fn RtlRaiseException(exceptionrecord: *const EXCEPTION_RECORD) -> !; } RtlRaiseException(::core::mem::transmute(exceptionrecord)) } diff --git a/crates/libs/windows/src/Windows/Win32/System/LibraryLoader/mod.rs b/crates/libs/windows/src/Windows/Win32/System/LibraryLoader/mod.rs index 16e3f6b206..855d53f876 100644 --- a/crates/libs/windows/src/Windows/Win32/System/LibraryLoader/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/System/LibraryLoader/mod.rs @@ -405,12 +405,12 @@ pub unsafe fn FreeLibrary<'a, Param0: ::windows::core::IntoParam<'a, super::supe #[doc = "*Required features: 'Win32_System_LibraryLoader', 'Win32_Foundation'*"] #[cfg(feature = "Win32_Foundation")] #[inline] -pub unsafe fn FreeLibraryAndExitThread<'a, Param0: ::windows::core::IntoParam<'a, super::super::Foundation::HINSTANCE>>(hlibmodule: Param0, dwexitcode: u32) { +pub unsafe fn FreeLibraryAndExitThread<'a, Param0: ::windows::core::IntoParam<'a, super::super::Foundation::HINSTANCE>>(hlibmodule: Param0, dwexitcode: u32) -> ! { #[cfg(windows)] { #[link(name = "windows")] extern "system" { - fn FreeLibraryAndExitThread(hlibmodule: super::super::Foundation::HINSTANCE, dwexitcode: u32); + fn FreeLibraryAndExitThread(hlibmodule: super::super::Foundation::HINSTANCE, dwexitcode: u32) -> !; } FreeLibraryAndExitThread(hlibmodule.into_param().abi(), ::core::mem::transmute(dwexitcode)) } diff --git a/crates/libs/windows/src/Windows/Win32/System/Threading/mod.rs b/crates/libs/windows/src/Windows/Win32/System/Threading/mod.rs index ea60b42f1b..d72df44865 100644 --- a/crates/libs/windows/src/Windows/Win32/System/Threading/mod.rs +++ b/crates/libs/windows/src/Windows/Win32/System/Threading/mod.rs @@ -1540,12 +1540,12 @@ pub unsafe fn ExecuteUmsThread(umsthread: *mut ::core::ffi::c_void) -> super::su } #[doc = "*Required features: 'Win32_System_Threading'*"] #[inline] -pub unsafe fn ExitProcess(uexitcode: u32) { +pub unsafe fn ExitProcess(uexitcode: u32) -> ! { #[cfg(windows)] { #[link(name = "windows")] extern "system" { - fn ExitProcess(uexitcode: u32); + fn ExitProcess(uexitcode: u32) -> !; } ExitProcess(::core::mem::transmute(uexitcode)) } @@ -1554,12 +1554,12 @@ pub unsafe fn ExitProcess(uexitcode: u32) { } #[doc = "*Required features: 'Win32_System_Threading'*"] #[inline] -pub unsafe fn ExitThread(dwexitcode: u32) { +pub unsafe fn ExitThread(dwexitcode: u32) -> ! { #[cfg(windows)] { #[link(name = "windows")] extern "system" { - fn ExitThread(dwexitcode: u32); + fn ExitThread(dwexitcode: u32) -> !; } ExitThread(::core::mem::transmute(dwexitcode)) } diff --git a/crates/tests/does_not_return/Cargo.toml b/crates/tests/does_not_return/Cargo.toml new file mode 100644 index 0000000000..6b2dbeb2c0 --- /dev/null +++ b/crates/tests/does_not_return/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "test_does_not_return" +version = "0.0.0" +authors = ["Microsoft"] +edition = "2018" + +[dependencies.windows] +path = "../../libs/windows" +features = [ + "Win32_System_Diagnostics_Debug", +] + +[dependencies.windows-sys] +path = "../../libs/sys" +features = [ + "Win32_System_Diagnostics_Debug", +] diff --git a/crates/tests/does_not_return/src/lib.rs b/crates/tests/does_not_return/src/lib.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/crates/tests/does_not_return/src/lib.rs @@ -0,0 +1 @@ + diff --git a/crates/tests/does_not_return/tests/sys.rs b/crates/tests/does_not_return/tests/sys.rs new file mode 100644 index 0000000000..9e8d64ce8c --- /dev/null +++ b/crates/tests/does_not_return/tests/sys.rs @@ -0,0 +1,10 @@ +use windows_sys::Win32::System::Diagnostics::Debug::FatalExit; + +// Compile-only test to check that FatalExit returns `-> !` + +#[allow(dead_code)] +fn test() -> i32 { + unsafe { + FatalExit(123); + } +} diff --git a/crates/tests/does_not_return/tests/win.rs b/crates/tests/does_not_return/tests/win.rs new file mode 100644 index 0000000000..cd92d4bcf9 --- /dev/null +++ b/crates/tests/does_not_return/tests/win.rs @@ -0,0 +1,10 @@ +use windows::Win32::System::Diagnostics::Debug::FatalExit; + +// Compile-only test to check that FatalExit returns `-> !` + +#[allow(dead_code)] +fn test() -> i32 { + unsafe { + FatalExit(123); + } +}