Skip to content

Commit

Permalink
Support functions that don't return (#1485)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr committed Feb 1, 2022
1 parent 9a27020 commit aa21d43
Show file tree
Hide file tree
Showing 13 changed files with 78 additions and 21 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Expand Up @@ -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 &&
Expand Down Expand Up @@ -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 &&
Expand Down
19 changes: 16 additions & 3 deletions crates/libs/bindgen/src/functions.rs
Expand Up @@ -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);
Expand Down Expand Up @@ -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),*)
}
Expand All @@ -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! {}
}
}
4 changes: 4 additions & 0 deletions crates/libs/metadata/src/tables/method_def.rs
Expand Up @@ -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<String> {
self.attributes()
.filter_map(|attribute| match attribute.name() {
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions crates/libs/sys/src/Windows/Win32/System/Threading/mod.rs
Expand Up @@ -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'*"]
Expand Down
Expand Up @@ -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))
}
Expand Down Expand Up @@ -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))
}
Expand Down Expand Up @@ -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))
}
Expand Down
Expand Up @@ -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))
}
Expand Down
8 changes: 4 additions & 4 deletions crates/libs/windows/src/Windows/Win32/System/Threading/mod.rs
Expand Up @@ -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))
}
Expand All @@ -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))
}
Expand Down
17 changes: 17 additions & 0 deletions 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",
]
1 change: 1 addition & 0 deletions crates/tests/does_not_return/src/lib.rs
@@ -0,0 +1 @@

10 changes: 10 additions & 0 deletions 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);
}
}
10 changes: 10 additions & 0 deletions 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);
}
}

0 comments on commit aa21d43

Please sign in to comment.