From 58853efcc3634c03c436c89d3e6b4e7e5182c49f Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 5 Jun 2024 09:31:43 -0500 Subject: [PATCH 01/10] callsite --- crates/libs/bindgen/src/metadata.rs | 6 + crates/libs/bindgen/src/rust/winrt_methods.rs | 77 ++- crates/tests/noexcept/Cargo.toml | 11 + crates/tests/noexcept/build.rs | 37 ++ crates/tests/noexcept/src/bindings.rs | 587 ++++++++++++++++++ crates/tests/noexcept/src/lib.rs | 1 + crates/tests/noexcept/src/test.idl | 19 + crates/tests/noexcept/tests/test.rs | 124 ++++ 8 files changed, 844 insertions(+), 18 deletions(-) create mode 100644 crates/tests/noexcept/Cargo.toml create mode 100644 crates/tests/noexcept/build.rs create mode 100644 crates/tests/noexcept/src/bindings.rs create mode 100644 crates/tests/noexcept/src/lib.rs create mode 100644 crates/tests/noexcept/src/test.idl create mode 100644 crates/tests/noexcept/tests/test.rs diff --git a/crates/libs/bindgen/src/metadata.rs b/crates/libs/bindgen/src/metadata.rs index a345d30ad3..11c9e7a5e1 100644 --- a/crates/libs/bindgen/src/metadata.rs +++ b/crates/libs/bindgen/src/metadata.rs @@ -475,6 +475,12 @@ fn method_def_last_error(row: MethodDef) -> bool { } } +pub fn method_def_is_noexcept(method: MethodDef) -> bool { + method.has_attribute("NoExceptionAttribute") + || (method.flags().contains(MethodAttributes::SpecialName) + && method.name().starts_with("remove")) +} + pub fn type_is_borrowed(ty: &Type) -> bool { match ty { Type::TypeDef(row, _) => !type_def_is_blittable(*row), diff --git a/crates/libs/bindgen/src/rust/winrt_methods.rs b/crates/libs/bindgen/src/rust/winrt_methods.rs index 0ac752d43b..4f371a76da 100644 --- a/crates/libs/bindgen/src/rust/winrt_methods.rs +++ b/crates/libs/bindgen/src/rust/winrt_methods.rs @@ -22,6 +22,7 @@ pub fn writer( let features = writer.cfg_features(&cfg); let args = gen_winrt_abi_args(writer, params); let params = gen_winrt_params(writer, params); + let noexcept = metadata::method_def_is_noexcept(method); let return_type_tokens = match &signature.return_type { metadata::Type::Void => quote! { () }, @@ -35,6 +36,18 @@ pub fn writer( } }; + let return_type_tokens = if noexcept { + if metadata::type_is_nullable(&signature.return_type) { + quote! { -> Option<#return_type_tokens> } + } else if signature.return_type == metadata::Type::Void { + quote! {} + } else { + quote! { -> #return_type_tokens } + } + } else { + quote! { -> windows_core::Result<#return_type_tokens> } + }; + let return_arg = match &signature.return_type { metadata::Type::Void => quote! {}, _ => { @@ -47,30 +60,58 @@ pub fn writer( } }; + let vcall = quote! { (windows_core::Interface::vtable(this).#vname)(windows_core::Interface::as_raw(this), #args #return_arg) }; + let vcall = match &signature.return_type { metadata::Type::Void => { - quote! { - (windows_core::Interface::vtable(this).#vname)(windows_core::Interface::as_raw(this), #args).ok() + if noexcept { + quote! { + _ = #vcall; + } + } else { + quote! { + #vcall.ok() + } } } _ if signature.return_type.is_winrt_array() => { - quote! { - let mut result__ = core::mem::MaybeUninit::zeroed(); - (windows_core::Interface::vtable(this).#vname)(windows_core::Interface::as_raw(this), #args #return_arg) - .map(|| result__.assume_init()) + if noexcept { + quote! { + let mut result__ = core::mem::MaybeUninit::zeroed(); + _ = #vcall; + result__.assume_init() + } + } else { + quote! { + let mut result__ = core::mem::MaybeUninit::zeroed(); + #vcall + .map(|| result__.assume_init()) + } } } _ => { - let map = if metadata::type_is_blittable(&signature.return_type) { - quote! { map(||result__) } + if noexcept { + if metadata::type_is_blittable(&signature.return_type) { + quote! { + let mut result__ = core::mem::zeroed(); + _ = #vcall; + result__ } + } else { + quote! { + let mut result__ = core::mem::zeroed(); + _ = #vcall; + core::mem::transmute(result__) } + } } else { - quote! { and_then(|| windows_core::Type::from_abi(result__)) } - }; - - quote! { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).#vname)(windows_core::Interface::as_raw(this), #args #return_arg) - .#map + if metadata::type_is_blittable(&signature.return_type) { + quote! { + let mut result__ = core::mem::zeroed(); + #vcall + .map(||result__) } + } else { + quote! { let mut result__ = core::mem::zeroed(); + #vcall.and_then(|| windows_core::Type::from_abi(result__)) } + } } } }; @@ -78,7 +119,7 @@ pub fn writer( match kind { metadata::InterfaceKind::Default => quote! { #features - pub fn #name<#generics>(&self, #params) -> windows_core::Result<#return_type_tokens> #where_clause { + pub fn #name<#generics>(&self, #params) #return_type_tokens #where_clause { let this = self; unsafe { #vcall @@ -90,7 +131,7 @@ pub fn writer( | metadata::InterfaceKind::Overridable => { quote! { #features - pub fn #name<#generics>(&self, #params) -> windows_core::Result<#return_type_tokens> #where_clause { + pub fn #name<#generics>(&self, #params) #return_type_tokens #where_clause { let this = &windows_core::Interface::cast::<#interface_name>(self)?; unsafe { #vcall @@ -101,7 +142,7 @@ pub fn writer( metadata::InterfaceKind::Static => { quote! { #features - pub fn #name<#generics>(#params) -> windows_core::Result<#return_type_tokens> #where_clause { + pub fn #name<#generics>(#params) #return_type_tokens #where_clause { Self::#interface_name(|this| unsafe { #vcall }) } } diff --git a/crates/tests/noexcept/Cargo.toml b/crates/tests/noexcept/Cargo.toml new file mode 100644 index 0000000000..f1caaf2c3a --- /dev/null +++ b/crates/tests/noexcept/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "test_noexcept" +version = "0.0.0" +edition = "2021" +publish = false + +[dependencies.windows-core] +path = "../../libs/core" + +[build-dependencies.windows-bindgen] +path = "../../libs/bindgen" diff --git a/crates/tests/noexcept/build.rs b/crates/tests/noexcept/build.rs new file mode 100644 index 0000000000..217d224bd6 --- /dev/null +++ b/crates/tests/noexcept/build.rs @@ -0,0 +1,37 @@ +fn main() { + println!("cargo:rerun-if-changed=src/test.idl"); + let metadata_dir = format!("{}\\System32\\WinMetadata", env!("windir")); + let mut command = std::process::Command::new("midlrt.exe"); + + command.args([ + "/winrt", + "/nomidl", + "/h", + "nul", + "/metadata_dir", + &metadata_dir, + "/reference", + &format!("{metadata_dir}\\Windows.Foundation.winmd"), + "/winmd", + "test.winmd", + "src/test.idl", + ]); + + if !command.status().unwrap().success() { + panic!("Failed to run midlrt"); + } + + if let Err(error) = windows_bindgen::bindgen([ + "--in", + "test.winmd", + &metadata_dir, + "--out", + "src/bindings.rs", + "--filter", + "Test", + "--config", + "implement", + ]) { + panic!("{error}"); + } +} diff --git a/crates/tests/noexcept/src/bindings.rs b/crates/tests/noexcept/src/bindings.rs new file mode 100644 index 0000000000..2067e279d6 --- /dev/null +++ b/crates/tests/noexcept/src/bindings.rs @@ -0,0 +1,587 @@ +// Bindings generated by `windows-bindgen` 0.56.0 + +#![allow( + non_snake_case, + non_upper_case_globals, + non_camel_case_types, + dead_code, + clippy::all +)] +windows_core::imp::define_interface!(ITest, ITest_Vtbl, 0x37b05fc1_6ee1_5798_b48d_602875fb73a2); +impl core::ops::Deref for ITest { + type Target = windows_core::IInspectable; + fn deref(&self) -> &Self::Target { + unsafe { core::mem::transmute(self) } + } +} +windows_core::imp::interface_hierarchy!(ITest, windows_core::IUnknown, windows_core::IInspectable); +impl ITest { + pub fn MethodString(&self, test: &windows_core::HSTRING) -> windows_core::Result<()> { + let this = self; + unsafe { + (windows_core::Interface::vtable(this).MethodString)( + windows_core::Interface::as_raw(this), + core::mem::transmute_copy(test), + ) + .ok() + } + } + pub fn MethodInt32(&self, test: i32) -> windows_core::Result<()> { + let this = self; + unsafe { + (windows_core::Interface::vtable(this).MethodInt32)( + windows_core::Interface::as_raw(this), + test, + ) + .ok() + } + } + pub fn MethodTest(&self, test: P0) -> windows_core::Result<()> + where + P0: windows_core::Param, + { + let this = self; + unsafe { + (windows_core::Interface::vtable(this).MethodTest)( + windows_core::Interface::as_raw(this), + test.param().abi(), + ) + .ok() + } + } + pub fn String(&self) -> windows_core::Result { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).String)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) + } + } + pub fn SetString(&self, value: &windows_core::HSTRING) -> windows_core::Result<()> { + let this = self; + unsafe { + (windows_core::Interface::vtable(this).SetString)( + windows_core::Interface::as_raw(this), + core::mem::transmute_copy(value), + ) + .ok() + } + } + pub fn Int32(&self) -> windows_core::Result { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).Int32)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) + } + } + pub fn SetInt32(&self, value: i32) -> windows_core::Result<()> { + let this = self; + unsafe { + (windows_core::Interface::vtable(this).SetInt32)( + windows_core::Interface::as_raw(this), + value, + ) + .ok() + } + } + pub fn Test(&self) -> windows_core::Result { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).Test)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) + } + } + pub fn SetTest(&self, value: P0) -> windows_core::Result<()> + where + P0: windows_core::Param, + { + let this = self; + unsafe { + (windows_core::Interface::vtable(this).SetTest)( + windows_core::Interface::as_raw(this), + value.param().abi(), + ) + .ok() + } + } + pub fn MethodStringN(&self, test: &windows_core::HSTRING) { + let this = self; + unsafe { + _ = (windows_core::Interface::vtable(this).MethodStringN)( + windows_core::Interface::as_raw(this), + core::mem::transmute_copy(test), + ); + } + } + pub fn MethodInt32N(&self, test: i32) { + let this = self; + unsafe { + _ = (windows_core::Interface::vtable(this).MethodInt32N)( + windows_core::Interface::as_raw(this), + test, + ); + } + } + pub fn MethodTestN(&self, test: P0) + where + P0: windows_core::Param, + { + let this = self; + unsafe { + _ = (windows_core::Interface::vtable(this).MethodTestN)( + windows_core::Interface::as_raw(this), + test.param().abi(), + ); + } + } + pub fn StringN(&self) -> windows_core::HSTRING { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + _ = (windows_core::Interface::vtable(this).StringN)( + windows_core::Interface::as_raw(this), + &mut result__, + ); + core::mem::transmute(result__) + } + } + pub fn SetStringN(&self, value: &windows_core::HSTRING) { + let this = self; + unsafe { + _ = (windows_core::Interface::vtable(this).SetStringN)( + windows_core::Interface::as_raw(this), + core::mem::transmute_copy(value), + ); + } + } + pub fn Int32N(&self) -> i32 { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + _ = (windows_core::Interface::vtable(this).Int32N)( + windows_core::Interface::as_raw(this), + &mut result__, + ); + result__ + } + } + pub fn SetInt32N(&self, value: i32) { + let this = self; + unsafe { + _ = (windows_core::Interface::vtable(this).SetInt32N)( + windows_core::Interface::as_raw(this), + value, + ); + } + } + pub fn TestN(&self) -> Option { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + _ = (windows_core::Interface::vtable(this).TestN)( + windows_core::Interface::as_raw(this), + &mut result__, + ); + core::mem::transmute(result__) + } + } + pub fn SetTestN(&self, value: P0) + where + P0: windows_core::Param, + { + let this = self; + unsafe { + _ = (windows_core::Interface::vtable(this).SetTestN)( + windows_core::Interface::as_raw(this), + value.param().abi(), + ); + } + } +} +impl windows_core::RuntimeType for ITest { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); +} +#[repr(C)] +pub struct ITest_Vtbl { + pub base__: windows_core::IInspectable_Vtbl, + pub MethodString: unsafe extern "system" fn( + *mut core::ffi::c_void, + core::mem::MaybeUninit, + ) -> windows_core::HRESULT, + pub MethodInt32: + unsafe extern "system" fn(*mut core::ffi::c_void, i32) -> windows_core::HRESULT, + pub MethodTest: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub String: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::mem::MaybeUninit, + ) -> windows_core::HRESULT, + pub SetString: unsafe extern "system" fn( + *mut core::ffi::c_void, + core::mem::MaybeUninit, + ) -> windows_core::HRESULT, + pub Int32: unsafe extern "system" fn(*mut core::ffi::c_void, *mut i32) -> windows_core::HRESULT, + pub SetInt32: unsafe extern "system" fn(*mut core::ffi::c_void, i32) -> windows_core::HRESULT, + pub Test: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub SetTest: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub MethodStringN: unsafe extern "system" fn( + *mut core::ffi::c_void, + core::mem::MaybeUninit, + ) -> windows_core::HRESULT, + pub MethodInt32N: + unsafe extern "system" fn(*mut core::ffi::c_void, i32) -> windows_core::HRESULT, + pub MethodTestN: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub StringN: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::mem::MaybeUninit, + ) -> windows_core::HRESULT, + pub SetStringN: unsafe extern "system" fn( + *mut core::ffi::c_void, + core::mem::MaybeUninit, + ) -> windows_core::HRESULT, + pub Int32N: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut i32) -> windows_core::HRESULT, + pub SetInt32N: unsafe extern "system" fn(*mut core::ffi::c_void, i32) -> windows_core::HRESULT, + pub TestN: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub SetTestN: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + ) -> windows_core::HRESULT, +} +pub trait ITest_Impl: Sized { + fn MethodString(&self, test: &windows_core::HSTRING) -> windows_core::Result<()>; + fn MethodInt32(&self, test: i32) -> windows_core::Result<()>; + fn MethodTest(&self, test: Option<&ITest>) -> windows_core::Result<()>; + fn String(&self) -> windows_core::Result; + fn SetString(&self, value: &windows_core::HSTRING) -> windows_core::Result<()>; + fn Int32(&self) -> windows_core::Result; + fn SetInt32(&self, value: i32) -> windows_core::Result<()>; + fn Test(&self) -> windows_core::Result; + fn SetTest(&self, value: Option<&ITest>) -> windows_core::Result<()>; + fn MethodStringN(&self, test: &windows_core::HSTRING) -> windows_core::Result<()>; + fn MethodInt32N(&self, test: i32) -> windows_core::Result<()>; + fn MethodTestN(&self, test: Option<&ITest>) -> windows_core::Result<()>; + fn StringN(&self) -> windows_core::Result; + fn SetStringN(&self, value: &windows_core::HSTRING) -> windows_core::Result<()>; + fn Int32N(&self) -> windows_core::Result; + fn SetInt32N(&self, value: i32) -> windows_core::Result<()>; + fn TestN(&self) -> windows_core::Result; + fn SetTestN(&self, value: Option<&ITest>) -> windows_core::Result<()>; +} +impl windows_core::RuntimeName for ITest { + const NAME: &'static str = "Test.ITest"; +} +impl ITest_Vtbl { + pub const fn new< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >() -> ITest_Vtbl { + unsafe extern "system" fn MethodString< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + test: core::mem::MaybeUninit, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + ITest_Impl::MethodString(this, core::mem::transmute(&test)).into() + } + unsafe extern "system" fn MethodInt32< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + test: i32, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + ITest_Impl::MethodInt32(this, test).into() + } + unsafe extern "system" fn MethodTest< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + test: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + ITest_Impl::MethodTest(this, windows_core::from_raw_borrowed(&test)).into() + } + unsafe extern "system" fn String< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + result__: *mut core::mem::MaybeUninit, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + match ITest_Impl::String(this) { + Ok(ok__) => { + core::ptr::write(result__, core::mem::transmute_copy(&ok__)); + core::mem::forget(ok__); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + unsafe extern "system" fn SetString< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + value: core::mem::MaybeUninit, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + ITest_Impl::SetString(this, core::mem::transmute(&value)).into() + } + unsafe extern "system" fn Int32< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + result__: *mut i32, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + match ITest_Impl::Int32(this) { + Ok(ok__) => { + core::ptr::write(result__, core::mem::transmute_copy(&ok__)); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + unsafe extern "system" fn SetInt32< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + value: i32, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + ITest_Impl::SetInt32(this, value).into() + } + unsafe extern "system" fn Test< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + result__: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + match ITest_Impl::Test(this) { + Ok(ok__) => { + core::ptr::write(result__, core::mem::transmute_copy(&ok__)); + core::mem::forget(ok__); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + unsafe extern "system" fn SetTest< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + value: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + ITest_Impl::SetTest(this, windows_core::from_raw_borrowed(&value)).into() + } + unsafe extern "system" fn MethodStringN< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + test: core::mem::MaybeUninit, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + ITest_Impl::MethodStringN(this, core::mem::transmute(&test)).into() + } + unsafe extern "system" fn MethodInt32N< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + test: i32, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + ITest_Impl::MethodInt32N(this, test).into() + } + unsafe extern "system" fn MethodTestN< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + test: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + ITest_Impl::MethodTestN(this, windows_core::from_raw_borrowed(&test)).into() + } + unsafe extern "system" fn StringN< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + result__: *mut core::mem::MaybeUninit, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + match ITest_Impl::StringN(this) { + Ok(ok__) => { + core::ptr::write(result__, core::mem::transmute_copy(&ok__)); + core::mem::forget(ok__); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + unsafe extern "system" fn SetStringN< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + value: core::mem::MaybeUninit, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + ITest_Impl::SetStringN(this, core::mem::transmute(&value)).into() + } + unsafe extern "system" fn Int32N< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + result__: *mut i32, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + match ITest_Impl::Int32N(this) { + Ok(ok__) => { + core::ptr::write(result__, core::mem::transmute_copy(&ok__)); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + unsafe extern "system" fn SetInt32N< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + value: i32, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + ITest_Impl::SetInt32N(this, value).into() + } + unsafe extern "system" fn TestN< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + result__: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + match ITest_Impl::TestN(this) { + Ok(ok__) => { + core::ptr::write(result__, core::mem::transmute_copy(&ok__)); + core::mem::forget(ok__); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + unsafe extern "system" fn SetTestN< + Identity: windows_core::IUnknownImpl, + Impl: ITest_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + value: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + ITest_Impl::SetTestN(this, windows_core::from_raw_borrowed(&value)).into() + } + Self { + base__: windows_core::IInspectable_Vtbl::new::(), + MethodString: MethodString::, + MethodInt32: MethodInt32::, + MethodTest: MethodTest::, + String: String::, + SetString: SetString::, + Int32: Int32::, + SetInt32: SetInt32::, + Test: Test::, + SetTest: SetTest::, + MethodStringN: MethodStringN::, + MethodInt32N: MethodInt32N::, + MethodTestN: MethodTestN::, + StringN: StringN::, + SetStringN: SetStringN::, + Int32N: Int32N::, + SetInt32N: SetInt32N::, + TestN: TestN::, + SetTestN: SetTestN::, + } + } + pub fn matches(iid: &windows_core::GUID) -> bool { + iid == &::IID + } +} diff --git a/crates/tests/noexcept/src/lib.rs b/crates/tests/noexcept/src/lib.rs new file mode 100644 index 0000000000..90c70dcc2c --- /dev/null +++ b/crates/tests/noexcept/src/lib.rs @@ -0,0 +1 @@ +pub mod bindings; diff --git a/crates/tests/noexcept/src/test.idl b/crates/tests/noexcept/src/test.idl new file mode 100644 index 0000000000..721162acd2 --- /dev/null +++ b/crates/tests/noexcept/src/test.idl @@ -0,0 +1,19 @@ +namespace Test +{ + interface ITest + { + void MethodString(String test); + void MethodInt32(Int32 test); + void MethodTest(ITest test); + String String; + Int32 Int32; + ITest Test; + + [noexcept] void MethodStringN(String test); + [noexcept] void MethodInt32N(Int32 test); + [noexcept] void MethodTestN(ITest test); + [noexcept] String StringN; + [noexcept] Int32 Int32N; + [noexcept] ITest TestN; + } +} diff --git a/crates/tests/noexcept/tests/test.rs b/crates/tests/noexcept/tests/test.rs new file mode 100644 index 0000000000..b5b6b7e83e --- /dev/null +++ b/crates/tests/noexcept/tests/test.rs @@ -0,0 +1,124 @@ +use test_noexcept::bindings::*; +use windows_core::*; + +#[implement(ITest)] +#[derive(Default)] +struct Test(std::sync::RwLock<(HSTRING, i32, Option)>); + +impl ITest_Impl for Test { + fn MethodString(&self, test: &HSTRING) -> Result<()> { + let mut this = self.0.write().unwrap(); + this.0 = test.clone(); + Ok(()) + } + fn MethodInt32(&self, test: i32) -> Result<()> { + let mut this = self.0.write().unwrap(); + this.1 = test; + Ok(()) + } + fn MethodTest(&self, test: Option<&ITest>) -> Result<()> { + let mut this = self.0.write().unwrap(); + this.2 = test.cloned(); + Ok(()) + } + fn String(&self) -> Result { + let this = self.0.read().unwrap(); + Ok(this.0.clone()) + } + fn SetString(&self, value: &HSTRING) -> Result<()> { + let mut this = self.0.write().unwrap(); + this.0 = value.clone(); + Ok(()) + } + fn Int32(&self) -> Result { + let this = self.0.read().unwrap(); + Ok(this.1) + } + fn SetInt32(&self, value: i32) -> Result<()> { + let mut this = self.0.write().unwrap(); + this.1 = value; + Ok(()) + } + fn Test(&self) -> Result { + let this = self.0.read().unwrap(); + this.2.clone().ok_or_else(|| Error::empty()) + } + fn SetTest(&self, value: Option<&ITest>) -> Result<()> { + let mut this = self.0.write().unwrap(); + this.2 = value.cloned(); + Ok(()) + } + + fn MethodStringN(&self, test: &HSTRING) -> Result<()> { + let mut this = self.0.write().unwrap(); + this.0 = test.clone(); + Ok(()) + } + fn MethodInt32N(&self, test: i32) -> Result<()> { + let mut this = self.0.write().unwrap(); + this.1 = test; + Ok(()) + } + fn MethodTestN(&self, test: Option<&ITest>) -> Result<()> { + let mut this = self.0.write().unwrap(); + this.2 = test.cloned(); + Ok(()) + } + fn StringN(&self) -> Result { + let this = self.0.read().unwrap(); + Ok(this.0.clone()) + } + fn SetStringN(&self, value: &HSTRING) -> Result<()> { + let mut this = self.0.write().unwrap(); + this.0 = value.clone(); + Ok(()) + } + fn Int32N(&self) -> Result { + let this = self.0.read().unwrap(); + Ok(this.1) + } + fn SetInt32N(&self, value: i32) -> Result<()> { + let mut this = self.0.write().unwrap(); + this.1 = value; + Ok(()) + } + fn TestN(&self) -> Result { + let this = self.0.read().unwrap(); + this.2.clone().ok_or_else(|| Error::empty()) + } + fn SetTestN(&self, value: Option<&ITest>) -> Result<()> { + let mut this = self.0.write().unwrap(); + this.2 = value.cloned(); + Ok(()) + } +} + +#[test] +fn test_except() -> Result<()> { + let test: ITest = Test::default().into(); + + test.MethodString(h!("abc"))?; + assert_eq!(test.String()?, "abc"); + + test.MethodInt32(123)?; + assert_eq!(test.Int32()?, 123); + + test.MethodTest(&test)?; + assert_eq!(&test.Test()?, &test); + + Ok(()) +} + +#[test] +fn test_noexcept() { + let test: ITest = Test::default().into(); + + test.MethodStringN(h!("abc")); + assert_eq!(test.StringN(), "abc"); + + test.MethodInt32N(123); + assert_eq!(test.Int32N(), 123); + + test.MethodTestN(&test); + assert_eq!(test.TestN().as_ref(), Some(&test)); +} From 86a8f2b932cbc512e4a8f2cc6c10a9d06409d77f Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 5 Jun 2024 09:55:11 -0500 Subject: [PATCH 02/10] upcalls --- crates/libs/bindgen/src/rust/winrt_methods.rs | 76 +++++++++++++------ crates/libs/bindgen/src/rust/writer.rs | 18 ++++- crates/tests/noexcept/src/bindings.rs | 70 ++++++++--------- crates/tests/noexcept/tests/test.rs | 32 ++++---- 4 files changed, 114 insertions(+), 82 deletions(-) diff --git a/crates/libs/bindgen/src/rust/winrt_methods.rs b/crates/libs/bindgen/src/rust/winrt_methods.rs index 4f371a76da..20da9b770e 100644 --- a/crates/libs/bindgen/src/rust/winrt_methods.rs +++ b/crates/libs/bindgen/src/rust/winrt_methods.rs @@ -102,8 +102,7 @@ pub fn writer( _ = #vcall; core::mem::transmute(result__) } } - } else { - if metadata::type_is_blittable(&signature.return_type) { + } else if metadata::type_is_blittable(&signature.return_type) { quote! { let mut result__ = core::mem::zeroed(); #vcall @@ -112,7 +111,6 @@ pub fn writer( quote! { let mut result__ = core::mem::zeroed(); #vcall.and_then(|| windows_core::Type::from_abi(result__)) } } - } } }; @@ -230,10 +228,13 @@ pub fn gen_upcall( inner: TokenStream, this: bool, ) -> TokenStream { + let noexcept = metadata::method_def_is_noexcept(sig.def); + let invoke_args = sig .params .iter() .map(|param| gen_winrt_invoke_arg(writer, param)); + let this = if this { quote! { this, } } else { @@ -241,20 +242,39 @@ pub fn gen_upcall( }; match &sig.return_type { - metadata::Type::Void => quote! { - #inner(#this #(#invoke_args,)*).into() - }, + metadata::Type::Void => { + if noexcept { + quote! { + #inner(#this #(#invoke_args,)*); + windows_core::HRESULT(0) + } + } else { + quote! { + #inner(#this #(#invoke_args,)*).into() + } + } + } _ if sig.return_type.is_winrt_array() => { - quote! { - match #inner(#this #(#invoke_args,)*) { - Ok(ok__) => { - let (ok_data__, ok_data_len__) = ok__.into_abi(); - // use `core::ptr::write` since `result` could be uninitialized - core::ptr::write(result__, ok_data__); - core::ptr::write(result_size__, ok_data_len__); - windows_core::HRESULT(0) + if noexcept { + quote! { + let ok__ = #inner(#this #(#invoke_args,)*); + let (ok_data__, ok_data_len__) = ok__.into_abi(); + core::ptr::write(result__, ok_data__); + core::ptr::write(result_size__, ok_data_len__); + windows_core::HRESULT(0) + } + } else { + quote! { + match #inner(#this #(#invoke_args,)*) { + Ok(ok__) => { + let (ok_data__, ok_data_len__) = ok__.into_abi(); + // use `core::ptr::write` since `result` could be uninitialized + core::ptr::write(result__, ok_data__); + core::ptr::write(result_size__, ok_data_len__); + windows_core::HRESULT(0) + } + Err(err) => err.into() } - Err(err) => err.into() } } } @@ -265,15 +285,25 @@ pub fn gen_upcall( quote! { core::mem::forget(ok__); } }; - quote! { - match #inner(#this #(#invoke_args,)*) { - Ok(ok__) => { - // use `core::ptr::write` since `result` could be uninitialized - core::ptr::write(result__, core::mem::transmute_copy(&ok__)); - #forget - windows_core::HRESULT(0) + if noexcept { + quote! { + let ok__ = #inner(#this #(#invoke_args,)*); + // use `core::ptr::write` since `result` could be uninitialized + core::ptr::write(result__, core::mem::transmute_copy(&ok__)); + #forget + windows_core::HRESULT(0) + } + } else { + quote! { + match #inner(#this #(#invoke_args,)*) { + Ok(ok__) => { + // use `core::ptr::write` since `result` could be uninitialized + core::ptr::write(result__, core::mem::transmute_copy(&ok__)); + #forget + windows_core::HRESULT(0) + } + Err(err) => err.into() } - Err(err) => err.into() } } } diff --git a/crates/libs/bindgen/src/rust/writer.rs b/crates/libs/bindgen/src/rust/writer.rs index e6e6189eee..26cddf50e2 100644 --- a/crates/libs/bindgen/src/rust/writer.rs +++ b/crates/libs/bindgen/src/rust/writer.rs @@ -1284,12 +1284,14 @@ impl Writer { .contains(metadata::TypeAttributes::WindowsRuntime) { let is_delegate = def.kind() == metadata::TypeKind::Delegate; + let noexcept = metadata::method_def_is_noexcept(signature.def); + let params = signature .params .iter() .map(|p| self.winrt_produce_type(p, !is_delegate)); - let return_type = match &signature.return_type { + let return_type_tokens = match &signature.return_type { metadata::Type::Void => quote! { () }, _ => { let tokens = self.type_name(&signature.return_type); @@ -1302,13 +1304,25 @@ impl Writer { } }; + let return_type_tokens = if noexcept { + if metadata::type_is_nullable(&signature.return_type) { + quote! { -> Option<#return_type_tokens> } + } else if signature.return_type == metadata::Type::Void { + quote! {} + } else { + quote! { -> #return_type_tokens } + } + } else { + quote! { -> windows_core::Result<#return_type_tokens> } + }; + let this = if is_delegate { quote! {} } else { quote! { &self, } }; - quote! { (#this #(#params),*) -> windows_core::Result<#return_type> } + quote! { (#this #(#params),*) #return_type_tokens } } else { let signature_kind = signature.kind(); let mut params = quote! {}; diff --git a/crates/tests/noexcept/src/bindings.rs b/crates/tests/noexcept/src/bindings.rs index 2067e279d6..5ca843dd7a 100644 --- a/crates/tests/noexcept/src/bindings.rs +++ b/crates/tests/noexcept/src/bindings.rs @@ -284,15 +284,15 @@ pub trait ITest_Impl: Sized { fn SetInt32(&self, value: i32) -> windows_core::Result<()>; fn Test(&self) -> windows_core::Result; fn SetTest(&self, value: Option<&ITest>) -> windows_core::Result<()>; - fn MethodStringN(&self, test: &windows_core::HSTRING) -> windows_core::Result<()>; - fn MethodInt32N(&self, test: i32) -> windows_core::Result<()>; - fn MethodTestN(&self, test: Option<&ITest>) -> windows_core::Result<()>; - fn StringN(&self) -> windows_core::Result; - fn SetStringN(&self, value: &windows_core::HSTRING) -> windows_core::Result<()>; - fn Int32N(&self) -> windows_core::Result; - fn SetInt32N(&self, value: i32) -> windows_core::Result<()>; - fn TestN(&self) -> windows_core::Result; - fn SetTestN(&self, value: Option<&ITest>) -> windows_core::Result<()>; + fn MethodStringN(&self, test: &windows_core::HSTRING); + fn MethodInt32N(&self, test: i32); + fn MethodTestN(&self, test: Option<&ITest>); + fn StringN(&self) -> windows_core::HSTRING; + fn SetStringN(&self, value: &windows_core::HSTRING); + fn Int32N(&self) -> i32; + fn SetInt32N(&self, value: i32); + fn TestN(&self) -> Option; + fn SetTestN(&self, value: Option<&ITest>); } impl windows_core::RuntimeName for ITest { const NAME: &'static str = "Test.ITest"; @@ -441,7 +441,8 @@ impl ITest_Vtbl { ) -> windows_core::HRESULT { let this = (this as *const *const ()).offset(OFFSET) as *const Identity; let this = (*this).get_impl(); - ITest_Impl::MethodStringN(this, core::mem::transmute(&test)).into() + ITest_Impl::MethodStringN(this, core::mem::transmute(&test)); + windows_core::HRESULT(0) } unsafe extern "system" fn MethodInt32N< Identity: windows_core::IUnknownImpl, @@ -453,7 +454,8 @@ impl ITest_Vtbl { ) -> windows_core::HRESULT { let this = (this as *const *const ()).offset(OFFSET) as *const Identity; let this = (*this).get_impl(); - ITest_Impl::MethodInt32N(this, test).into() + ITest_Impl::MethodInt32N(this, test); + windows_core::HRESULT(0) } unsafe extern "system" fn MethodTestN< Identity: windows_core::IUnknownImpl, @@ -465,7 +467,8 @@ impl ITest_Vtbl { ) -> windows_core::HRESULT { let this = (this as *const *const ()).offset(OFFSET) as *const Identity; let this = (*this).get_impl(); - ITest_Impl::MethodTestN(this, windows_core::from_raw_borrowed(&test)).into() + ITest_Impl::MethodTestN(this, windows_core::from_raw_borrowed(&test)); + windows_core::HRESULT(0) } unsafe extern "system" fn StringN< Identity: windows_core::IUnknownImpl, @@ -477,14 +480,10 @@ impl ITest_Vtbl { ) -> windows_core::HRESULT { let this = (this as *const *const ()).offset(OFFSET) as *const Identity; let this = (*this).get_impl(); - match ITest_Impl::StringN(this) { - Ok(ok__) => { - core::ptr::write(result__, core::mem::transmute_copy(&ok__)); - core::mem::forget(ok__); - windows_core::HRESULT(0) - } - Err(err) => err.into(), - } + let ok__ = ITest_Impl::StringN(this); + core::ptr::write(result__, core::mem::transmute_copy(&ok__)); + core::mem::forget(ok__); + windows_core::HRESULT(0) } unsafe extern "system" fn SetStringN< Identity: windows_core::IUnknownImpl, @@ -496,7 +495,8 @@ impl ITest_Vtbl { ) -> windows_core::HRESULT { let this = (this as *const *const ()).offset(OFFSET) as *const Identity; let this = (*this).get_impl(); - ITest_Impl::SetStringN(this, core::mem::transmute(&value)).into() + ITest_Impl::SetStringN(this, core::mem::transmute(&value)); + windows_core::HRESULT(0) } unsafe extern "system" fn Int32N< Identity: windows_core::IUnknownImpl, @@ -508,13 +508,9 @@ impl ITest_Vtbl { ) -> windows_core::HRESULT { let this = (this as *const *const ()).offset(OFFSET) as *const Identity; let this = (*this).get_impl(); - match ITest_Impl::Int32N(this) { - Ok(ok__) => { - core::ptr::write(result__, core::mem::transmute_copy(&ok__)); - windows_core::HRESULT(0) - } - Err(err) => err.into(), - } + let ok__ = ITest_Impl::Int32N(this); + core::ptr::write(result__, core::mem::transmute_copy(&ok__)); + windows_core::HRESULT(0) } unsafe extern "system" fn SetInt32N< Identity: windows_core::IUnknownImpl, @@ -526,7 +522,8 @@ impl ITest_Vtbl { ) -> windows_core::HRESULT { let this = (this as *const *const ()).offset(OFFSET) as *const Identity; let this = (*this).get_impl(); - ITest_Impl::SetInt32N(this, value).into() + ITest_Impl::SetInt32N(this, value); + windows_core::HRESULT(0) } unsafe extern "system" fn TestN< Identity: windows_core::IUnknownImpl, @@ -538,14 +535,10 @@ impl ITest_Vtbl { ) -> windows_core::HRESULT { let this = (this as *const *const ()).offset(OFFSET) as *const Identity; let this = (*this).get_impl(); - match ITest_Impl::TestN(this) { - Ok(ok__) => { - core::ptr::write(result__, core::mem::transmute_copy(&ok__)); - core::mem::forget(ok__); - windows_core::HRESULT(0) - } - Err(err) => err.into(), - } + let ok__ = ITest_Impl::TestN(this); + core::ptr::write(result__, core::mem::transmute_copy(&ok__)); + core::mem::forget(ok__); + windows_core::HRESULT(0) } unsafe extern "system" fn SetTestN< Identity: windows_core::IUnknownImpl, @@ -557,7 +550,8 @@ impl ITest_Vtbl { ) -> windows_core::HRESULT { let this = (this as *const *const ()).offset(OFFSET) as *const Identity; let this = (*this).get_impl(); - ITest_Impl::SetTestN(this, windows_core::from_raw_borrowed(&value)).into() + ITest_Impl::SetTestN(this, windows_core::from_raw_borrowed(&value)); + windows_core::HRESULT(0) } Self { base__: windows_core::IInspectable_Vtbl::new::(), diff --git a/crates/tests/noexcept/tests/test.rs b/crates/tests/noexcept/tests/test.rs index b5b6b7e83e..48f289a563 100644 --- a/crates/tests/noexcept/tests/test.rs +++ b/crates/tests/noexcept/tests/test.rs @@ -41,7 +41,7 @@ impl ITest_Impl for Test { } fn Test(&self) -> Result { let this = self.0.read().unwrap(); - this.2.clone().ok_or_else(|| Error::empty()) + this.2.clone().ok_or_else(Error::empty) } fn SetTest(&self, value: Option<&ITest>) -> Result<()> { let mut this = self.0.write().unwrap(); @@ -49,47 +49,41 @@ impl ITest_Impl for Test { Ok(()) } - fn MethodStringN(&self, test: &HSTRING) -> Result<()> { + fn MethodStringN(&self, test: &HSTRING) { let mut this = self.0.write().unwrap(); this.0 = test.clone(); - Ok(()) } - fn MethodInt32N(&self, test: i32) -> Result<()> { + fn MethodInt32N(&self, test: i32) { let mut this = self.0.write().unwrap(); this.1 = test; - Ok(()) } - fn MethodTestN(&self, test: Option<&ITest>) -> Result<()> { + fn MethodTestN(&self, test: Option<&ITest>) { let mut this = self.0.write().unwrap(); this.2 = test.cloned(); - Ok(()) } - fn StringN(&self) -> Result { + fn StringN(&self) -> HSTRING { let this = self.0.read().unwrap(); - Ok(this.0.clone()) + this.0.clone() } - fn SetStringN(&self, value: &HSTRING) -> Result<()> { + fn SetStringN(&self, value: &HSTRING) { let mut this = self.0.write().unwrap(); this.0 = value.clone(); - Ok(()) } - fn Int32N(&self) -> Result { + fn Int32N(&self) -> i32 { let this = self.0.read().unwrap(); - Ok(this.1) + this.1 } - fn SetInt32N(&self, value: i32) -> Result<()> { + fn SetInt32N(&self, value: i32) { let mut this = self.0.write().unwrap(); this.1 = value; - Ok(()) } - fn TestN(&self) -> Result { + fn TestN(&self) -> Option { let this = self.0.read().unwrap(); - this.2.clone().ok_or_else(|| Error::empty()) + this.2.clone() } - fn SetTestN(&self, value: Option<&ITest>) -> Result<()> { + fn SetTestN(&self, value: Option<&ITest>) { let mut this = self.0.write().unwrap(); this.2 = value.cloned(); - Ok(()) } } From 0f401c6d9ec0eeaccc0ee0b88c3732651025edb6 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 5 Jun 2024 09:59:20 -0500 Subject: [PATCH 03/10] noexcept system APIs --- .../windows/src/Windows/UI/UIAutomation/Core/impl.rs | 12 ++++-------- .../windows/src/Windows/UI/UIAutomation/Core/mod.rs | 5 +++-- .../libs/windows/src/Windows/UI/UIAutomation/mod.rs | 10 ++++++---- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/crates/libs/windows/src/Windows/UI/UIAutomation/Core/impl.rs b/crates/libs/windows/src/Windows/UI/UIAutomation/Core/impl.rs index 08dfd59472..ca97630d6f 100644 --- a/crates/libs/windows/src/Windows/UI/UIAutomation/Core/impl.rs +++ b/crates/libs/windows/src/Windows/UI/UIAutomation/Core/impl.rs @@ -1,5 +1,5 @@ pub trait ICoreAutomationConnectionBoundObjectProvider_Impl: Sized { - fn IsComThreadingRequired(&self) -> windows_core::Result; + fn IsComThreadingRequired(&self) -> bool; } impl windows_core::RuntimeName for ICoreAutomationConnectionBoundObjectProvider { const NAME: &'static str = "Windows.UI.UIAutomation.Core.ICoreAutomationConnectionBoundObjectProvider"; @@ -9,13 +9,9 @@ impl ICoreAutomationConnectionBoundObjectProvider_Vtbl { unsafe extern "system" fn IsComThreadingRequired, Impl: ICoreAutomationConnectionBoundObjectProvider_Impl, const OFFSET: isize>(this: *mut core::ffi::c_void, result__: *mut bool) -> windows_core::HRESULT { let this = (this as *const *const ()).offset(OFFSET) as *const Identity; let this = (*this).get_impl(); - match ICoreAutomationConnectionBoundObjectProvider_Impl::IsComThreadingRequired(this) { - Ok(ok__) => { - core::ptr::write(result__, core::mem::transmute_copy(&ok__)); - windows_core::HRESULT(0) - } - Err(err) => err.into(), - } + let ok__ = ICoreAutomationConnectionBoundObjectProvider_Impl::IsComThreadingRequired(this); + core::ptr::write(result__, core::mem::transmute_copy(&ok__)); + windows_core::HRESULT(0) } Self { base__: windows_core::IInspectable_Vtbl::new::(), diff --git a/crates/libs/windows/src/Windows/UI/UIAutomation/Core/mod.rs b/crates/libs/windows/src/Windows/UI/UIAutomation/Core/mod.rs index b7db3c05b0..cf0adfb90a 100644 --- a/crates/libs/windows/src/Windows/UI/UIAutomation/Core/mod.rs +++ b/crates/libs/windows/src/Windows/UI/UIAutomation/Core/mod.rs @@ -20,11 +20,12 @@ impl core::ops::Deref for ICoreAutomationConnectionBoundObjectProvider { } windows_core::imp::interface_hierarchy!(ICoreAutomationConnectionBoundObjectProvider, windows_core::IUnknown, windows_core::IInspectable); impl ICoreAutomationConnectionBoundObjectProvider { - pub fn IsComThreadingRequired(&self) -> windows_core::Result { + pub fn IsComThreadingRequired(&self) -> bool { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).IsComThreadingRequired)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + _ = (windows_core::Interface::vtable(this).IsComThreadingRequired)(windows_core::Interface::as_raw(this), &mut result__); + result__ } } } diff --git a/crates/libs/windows/src/Windows/UI/UIAutomation/mod.rs b/crates/libs/windows/src/Windows/UI/UIAutomation/mod.rs index c2f3cef80f..cac740db5a 100644 --- a/crates/libs/windows/src/Windows/UI/UIAutomation/mod.rs +++ b/crates/libs/windows/src/Windows/UI/UIAutomation/mod.rs @@ -44,11 +44,12 @@ pub struct IAutomationTextRange_Vtbl { pub struct AutomationConnection(windows_core::IUnknown); windows_core::imp::interface_hierarchy!(AutomationConnection, windows_core::IUnknown, windows_core::IInspectable); impl AutomationConnection { - pub fn IsRemoteSystem(&self) -> windows_core::Result { + pub fn IsRemoteSystem(&self) -> bool { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).IsRemoteSystem)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + _ = (windows_core::Interface::vtable(this).IsRemoteSystem)(windows_core::Interface::as_raw(this), &mut result__); + result__ } } pub fn AppUserModelId(&self) -> windows_core::Result { @@ -108,11 +109,12 @@ unsafe impl Sync for AutomationConnectionBoundObject {} pub struct AutomationElement(windows_core::IUnknown); windows_core::imp::interface_hierarchy!(AutomationElement, windows_core::IUnknown, windows_core::IInspectable); impl AutomationElement { - pub fn IsRemoteSystem(&self) -> windows_core::Result { + pub fn IsRemoteSystem(&self) -> bool { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).IsRemoteSystem)(windows_core::Interface::as_raw(this), &mut result__).map(|| result__) + _ = (windows_core::Interface::vtable(this).IsRemoteSystem)(windows_core::Interface::as_raw(this), &mut result__); + result__ } } pub fn AppUserModelId(&self) -> windows_core::Result { From 6021da6411dc114cb4b1cc9409d5acf313e5a1eb Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 5 Jun 2024 10:09:11 -0500 Subject: [PATCH 04/10] remove --- crates/libs/bindgen/src/metadata.rs | 2 -- crates/libs/bindgen/src/rust/winrt_methods.rs | 16 ++++++++-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/crates/libs/bindgen/src/metadata.rs b/crates/libs/bindgen/src/metadata.rs index 11c9e7a5e1..af2c387dde 100644 --- a/crates/libs/bindgen/src/metadata.rs +++ b/crates/libs/bindgen/src/metadata.rs @@ -477,8 +477,6 @@ fn method_def_last_error(row: MethodDef) -> bool { pub fn method_def_is_noexcept(method: MethodDef) -> bool { method.has_attribute("NoExceptionAttribute") - || (method.flags().contains(MethodAttributes::SpecialName) - && method.name().starts_with("remove")) } pub fn type_is_borrowed(ty: &Type) -> bool { diff --git a/crates/libs/bindgen/src/rust/winrt_methods.rs b/crates/libs/bindgen/src/rust/winrt_methods.rs index 20da9b770e..1f98cf7999 100644 --- a/crates/libs/bindgen/src/rust/winrt_methods.rs +++ b/crates/libs/bindgen/src/rust/winrt_methods.rs @@ -103,14 +103,14 @@ pub fn writer( core::mem::transmute(result__) } } } else if metadata::type_is_blittable(&signature.return_type) { - quote! { - let mut result__ = core::mem::zeroed(); - #vcall - .map(||result__) } - } else { - quote! { let mut result__ = core::mem::zeroed(); - #vcall.and_then(|| windows_core::Type::from_abi(result__)) } - } + quote! { + let mut result__ = core::mem::zeroed(); + #vcall + .map(||result__) } + } else { + quote! { let mut result__ = core::mem::zeroed(); + #vcall.and_then(|| windows_core::Type::from_abi(result__)) } + } } }; From b135edbbb664ea349ec6618c2c1e4a1c198a9ee5 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 5 Jun 2024 10:18:21 -0500 Subject: [PATCH 05/10] yml --- .github/workflows/clippy.yml | 2 ++ .github/workflows/test.yml | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 5936bbb2aa..8ee1f01732 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -208,6 +208,8 @@ jobs: run: cargo clippy -p test_msrv - name: Clippy test_no_use run: cargo clippy -p test_no_use + - name: Clippy test_noexcept + run: cargo clippy -p test_noexcept - name: Clippy test_not_dll run: cargo clippy -p test_not_dll - name: Clippy test_query_signature diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e24c3ec7f6..337bf8ca18 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -234,6 +234,8 @@ jobs: run: cargo test -p test_msrv --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_no_use run: cargo test -p test_no_use --target ${{ matrix.target }} ${{ matrix.etc }} + - name: Test test_noexcept + run: cargo test -p test_noexcept --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_not_dll run: cargo test -p test_not_dll --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_query_signature @@ -256,10 +258,10 @@ jobs: run: cargo test -p test_riddle --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_standalone run: cargo test -p test_standalone --target ${{ matrix.target }} ${{ matrix.etc }} - - name: Test test_string_param - run: cargo test -p test_string_param --target ${{ matrix.target }} ${{ matrix.etc }} - name: Clean run: cargo clean + - name: Test test_string_param + run: cargo test -p test_string_param --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_structs run: cargo test -p test_structs --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_sys From 6253f0ff34cbbc786add4e6b2b79144382772819 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 6 Jun 2024 07:45:27 -0500 Subject: [PATCH 06/10] debug_assert --- crates/libs/bindgen/src/rust/winrt_methods.rs | 12 ++++++--- crates/tests/noexcept/src/bindings.rs | 27 ++++++++++++------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/crates/libs/bindgen/src/rust/winrt_methods.rs b/crates/libs/bindgen/src/rust/winrt_methods.rs index 1f98cf7999..345cb01e75 100644 --- a/crates/libs/bindgen/src/rust/winrt_methods.rs +++ b/crates/libs/bindgen/src/rust/winrt_methods.rs @@ -66,7 +66,8 @@ pub fn writer( metadata::Type::Void => { if noexcept { quote! { - _ = #vcall; + let hresult__ = #vcall; + debug_assert!(hresult__.0 == 0); } } else { quote! { @@ -78,7 +79,8 @@ pub fn writer( if noexcept { quote! { let mut result__ = core::mem::MaybeUninit::zeroed(); - _ = #vcall; + let hresult__ = #vcall; + debug_assert!(hresult__.0 == 0); result__.assume_init() } } else { @@ -94,12 +96,14 @@ pub fn writer( if metadata::type_is_blittable(&signature.return_type) { quote! { let mut result__ = core::mem::zeroed(); - _ = #vcall; + let hresult__ = #vcall; + debug_assert!(hresult__.0 == 0); result__ } } else { quote! { let mut result__ = core::mem::zeroed(); - _ = #vcall; + let hresult__ = #vcall; + debug_assert!(hresult__.0 == 0); core::mem::transmute(result__) } } } else if metadata::type_is_blittable(&signature.return_type) { diff --git a/crates/tests/noexcept/src/bindings.rs b/crates/tests/noexcept/src/bindings.rs index 5ca843dd7a..1f4a837e1a 100644 --- a/crates/tests/noexcept/src/bindings.rs +++ b/crates/tests/noexcept/src/bindings.rs @@ -118,19 +118,21 @@ impl ITest { pub fn MethodStringN(&self, test: &windows_core::HSTRING) { let this = self; unsafe { - _ = (windows_core::Interface::vtable(this).MethodStringN)( + let hresult__ = (windows_core::Interface::vtable(this).MethodStringN)( windows_core::Interface::as_raw(this), core::mem::transmute_copy(test), ); + debug_assert!(hresult__.0 == 0); } } pub fn MethodInt32N(&self, test: i32) { let this = self; unsafe { - _ = (windows_core::Interface::vtable(this).MethodInt32N)( + let hresult__ = (windows_core::Interface::vtable(this).MethodInt32N)( windows_core::Interface::as_raw(this), test, ); + debug_assert!(hresult__.0 == 0); } } pub fn MethodTestN(&self, test: P0) @@ -139,60 +141,66 @@ impl ITest { { let this = self; unsafe { - _ = (windows_core::Interface::vtable(this).MethodTestN)( + let hresult__ = (windows_core::Interface::vtable(this).MethodTestN)( windows_core::Interface::as_raw(this), test.param().abi(), ); + debug_assert!(hresult__.0 == 0); } } pub fn StringN(&self) -> windows_core::HSTRING { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - _ = (windows_core::Interface::vtable(this).StringN)( + let hresult__ = (windows_core::Interface::vtable(this).StringN)( windows_core::Interface::as_raw(this), &mut result__, ); + debug_assert!(hresult__.0 == 0); core::mem::transmute(result__) } } pub fn SetStringN(&self, value: &windows_core::HSTRING) { let this = self; unsafe { - _ = (windows_core::Interface::vtable(this).SetStringN)( + let hresult__ = (windows_core::Interface::vtable(this).SetStringN)( windows_core::Interface::as_raw(this), core::mem::transmute_copy(value), ); + debug_assert!(hresult__.0 == 0); } } pub fn Int32N(&self) -> i32 { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - _ = (windows_core::Interface::vtable(this).Int32N)( + let hresult__ = (windows_core::Interface::vtable(this).Int32N)( windows_core::Interface::as_raw(this), &mut result__, ); + debug_assert!(hresult__.0 == 0); result__ } } pub fn SetInt32N(&self, value: i32) { let this = self; unsafe { - _ = (windows_core::Interface::vtable(this).SetInt32N)( + let hresult__ = (windows_core::Interface::vtable(this).SetInt32N)( windows_core::Interface::as_raw(this), value, ); + debug_assert!(hresult__.0 == 0); } } pub fn TestN(&self) -> Option { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - _ = (windows_core::Interface::vtable(this).TestN)( + let hresult__ = (windows_core::Interface::vtable(this).TestN)( windows_core::Interface::as_raw(this), &mut result__, ); + debug_assert!(hresult__.0 == 0); core::mem::transmute(result__) } } @@ -202,10 +210,11 @@ impl ITest { { let this = self; unsafe { - _ = (windows_core::Interface::vtable(this).SetTestN)( + let hresult__ = (windows_core::Interface::vtable(this).SetTestN)( windows_core::Interface::as_raw(this), value.param().abi(), ); + debug_assert!(hresult__.0 == 0); } } } From 097277520c4f9f2fd18d4272fdce2debed644231 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 6 Jun 2024 07:48:08 -0500 Subject: [PATCH 07/10] debug_assert system APIs --- crates/libs/windows/src/Windows/UI/UIAutomation/Core/mod.rs | 3 ++- crates/libs/windows/src/Windows/UI/UIAutomation/mod.rs | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/libs/windows/src/Windows/UI/UIAutomation/Core/mod.rs b/crates/libs/windows/src/Windows/UI/UIAutomation/Core/mod.rs index cf0adfb90a..39b1d59570 100644 --- a/crates/libs/windows/src/Windows/UI/UIAutomation/Core/mod.rs +++ b/crates/libs/windows/src/Windows/UI/UIAutomation/Core/mod.rs @@ -24,7 +24,8 @@ impl ICoreAutomationConnectionBoundObjectProvider { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - _ = (windows_core::Interface::vtable(this).IsComThreadingRequired)(windows_core::Interface::as_raw(this), &mut result__); + let hresult__ = (windows_core::Interface::vtable(this).IsComThreadingRequired)(windows_core::Interface::as_raw(this), &mut result__); + debug_assert!(hresult__.0 == 0); result__ } } diff --git a/crates/libs/windows/src/Windows/UI/UIAutomation/mod.rs b/crates/libs/windows/src/Windows/UI/UIAutomation/mod.rs index cac740db5a..6a980ffaaf 100644 --- a/crates/libs/windows/src/Windows/UI/UIAutomation/mod.rs +++ b/crates/libs/windows/src/Windows/UI/UIAutomation/mod.rs @@ -48,7 +48,8 @@ impl AutomationConnection { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - _ = (windows_core::Interface::vtable(this).IsRemoteSystem)(windows_core::Interface::as_raw(this), &mut result__); + let hresult__ = (windows_core::Interface::vtable(this).IsRemoteSystem)(windows_core::Interface::as_raw(this), &mut result__); + debug_assert!(hresult__.0 == 0); result__ } } @@ -113,7 +114,8 @@ impl AutomationElement { let this = self; unsafe { let mut result__ = core::mem::zeroed(); - _ = (windows_core::Interface::vtable(this).IsRemoteSystem)(windows_core::Interface::as_raw(this), &mut result__); + let hresult__ = (windows_core::Interface::vtable(this).IsRemoteSystem)(windows_core::Interface::as_raw(this), &mut result__); + debug_assert!(hresult__.0 == 0); result__ } } From 7dfe20bae4210df4577e82df731d48d92a41741f Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 6 Jun 2024 14:38:53 -0500 Subject: [PATCH 08/10] cppwinrt test --- crates/tests/noexcept/Cargo.toml | 6 ++ crates/tests/noexcept/build.rs | 18 ++++ crates/tests/noexcept/src/interop.cpp | 140 ++++++++++++++++++++++++++ crates/tests/noexcept/src/lib.rs | 24 ++++- crates/tests/noexcept/tests/test.rs | 38 ++++--- 5 files changed, 211 insertions(+), 15 deletions(-) create mode 100644 crates/tests/noexcept/src/interop.cpp diff --git a/crates/tests/noexcept/Cargo.toml b/crates/tests/noexcept/Cargo.toml index f1caaf2c3a..881ecabdda 100644 --- a/crates/tests/noexcept/Cargo.toml +++ b/crates/tests/noexcept/Cargo.toml @@ -9,3 +9,9 @@ path = "../../libs/core" [build-dependencies.windows-bindgen] path = "../../libs/bindgen" + +[build-dependencies] +cc = "1.0" + +[build-dependencies.cppwinrt] +path = "../../libs/cppwinrt" diff --git a/crates/tests/noexcept/build.rs b/crates/tests/noexcept/build.rs index 217d224bd6..fb516b21f1 100644 --- a/crates/tests/noexcept/build.rs +++ b/crates/tests/noexcept/build.rs @@ -2,6 +2,8 @@ fn main() { println!("cargo:rerun-if-changed=src/test.idl"); let metadata_dir = format!("{}\\System32\\WinMetadata", env!("windir")); let mut command = std::process::Command::new("midlrt.exe"); + println!("cargo:rerun-if-changed=src/interop.cpp"); + println!("cargo:rustc-link-lib=windows.0.52.0"); command.args([ "/winrt", @@ -34,4 +36,20 @@ fn main() { ]) { panic!("{error}"); } + + cppwinrt::cppwinrt([ + "-in", + "test.winmd", + &format!("{}\\System32\\WinMetadata", env!("windir")), + "-out", + "src", + ]) + .unwrap(); + + cc::Build::new() + .cpp(true) + .std("c++20") + .flag("/EHsc") + .file("src/interop.cpp") + .compile("interop"); } diff --git a/crates/tests/noexcept/src/interop.cpp b/crates/tests/noexcept/src/interop.cpp new file mode 100644 index 0000000000..595ad741dd --- /dev/null +++ b/crates/tests/noexcept/src/interop.cpp @@ -0,0 +1,140 @@ +#include +#include "winrt/Test.h" + +using namespace winrt; +using namespace winrt::Test; + +void test_except(ITest const &test) +{ + test.MethodString(L"abc"); + assert(test.String() == L"abc"); + + test.MethodInt32(123); + assert(test.Int32() == 123); + + test.MethodTest(test); + assert(test.Test() == test); +} + +void test_noexcept(ITest const &test) +{ + test.MethodStringN(L"abc"); + assert(test.StringN() == L"abc"); + + test.MethodInt32N(123); + assert(test.Int32N() == 123); + + test.MethodTestN(test); + assert(test.TestN() == test); +} + +struct Implementation : implements +{ + hstring m_string; + int32_t m_int32; + ITest m_test; + + void MethodString(hstring const &value) + { + m_string = value; + } + void MethodInt32(int32_t value) + { + m_int32 = value; + } + void MethodTest(ITest const &value) + { + m_test = value; + } + hstring String() const + { + return m_string; + } + void String(hstring const &value) + { + m_string = value; + } + int32_t Int32() const + { + return m_int32; + } + void Int32(int32_t value) + { + m_int32 = value; + } + ITest Test() const + { + return m_test; + } + void Test(ITest const &value) + { + m_test = value; + } + + void MethodStringN(hstring const &value) noexcept + { + m_string = value; + } + void MethodInt32N(int32_t value) noexcept + { + m_int32 = value; + } + void MethodTestN(ITest const &value) noexcept + { + m_test = value; + } + hstring StringN() const noexcept + { + return m_string; + } + void StringN(hstring const &value) noexcept + { + m_string = value; + } + int32_t Int32N() const noexcept + { + return m_int32; + } + void Int32N(int32_t value) noexcept + { + m_int32 = value; + } + ITest TestN() const noexcept + { + return m_test; + } + void TestN(ITest const &value) noexcept + { + m_test = value; + } +}; + +extern "C" +{ + HRESULT __stdcall consume(void *abi) noexcept + try + { + ITest const &test = *reinterpret_cast(&abi); + + test_noexcept(test); + test_except(test); + + return S_OK; + } + catch (...) + { + return to_hresult(); + } + + HRESULT __stdcall produce(void **abi) noexcept + try + { + *abi = detach_abi(make()); + + return S_OK; + } + catch (...) + { + return to_hresult(); + } +} diff --git a/crates/tests/noexcept/src/lib.rs b/crates/tests/noexcept/src/lib.rs index 90c70dcc2c..79a79039e3 100644 --- a/crates/tests/noexcept/src/lib.rs +++ b/crates/tests/noexcept/src/lib.rs @@ -1 +1,23 @@ -pub mod bindings; +mod bindings; +pub use bindings::*; +pub use windows_core::*; + +pub fn consume(test: &ITest) -> Result<()> { + extern "system" { + fn consume(test: Ref) -> HRESULT; + } + + unsafe { consume(std::mem::transmute_copy(test)).ok() } +} + +pub fn produce() -> Result { + extern "system" { + fn produce(test: *mut *mut std::ffi::c_void) -> HRESULT; + } + + unsafe { + let mut test = None; + produce(&mut test as *mut _ as *mut _).ok()?; + Type::from_default(&test) + } +} diff --git a/crates/tests/noexcept/tests/test.rs b/crates/tests/noexcept/tests/test.rs index 48f289a563..63af99dd4e 100644 --- a/crates/tests/noexcept/tests/test.rs +++ b/crates/tests/noexcept/tests/test.rs @@ -1,5 +1,4 @@ -use test_noexcept::bindings::*; -use windows_core::*; +use test_noexcept::*; #[implement(ITest)] #[derive(Default)] @@ -87,32 +86,43 @@ impl ITest_Impl for Test { } } -#[test] -fn test_except() -> Result<()> { - let test: ITest = Test::default().into(); - +fn test_except(test: &ITest) -> Result<()> { test.MethodString(h!("abc"))?; assert_eq!(test.String()?, "abc"); test.MethodInt32(123)?; assert_eq!(test.Int32()?, 123); - test.MethodTest(&test)?; - assert_eq!(&test.Test()?, &test); + test.MethodTest(test)?; + assert_eq!(&test.Test()?, test); Ok(()) } -#[test] -fn test_noexcept() { - let test: ITest = Test::default().into(); - +fn test_noexcept(test: &ITest) { test.MethodStringN(h!("abc")); assert_eq!(test.StringN(), "abc"); test.MethodInt32N(123); assert_eq!(test.Int32N(), 123); - test.MethodTestN(&test); - assert_eq!(test.TestN().as_ref(), Some(&test)); + test.MethodTestN(test); + assert_eq!(test.TestN().as_ref(), Some(test)); +} + +#[test] +fn test_rust() -> Result<()> { + let test: ITest = Test::default().into(); + test_noexcept(&test); + test_except(&test) +} + +#[test] +fn test_cpp() -> Result<()> { + let test: ITest = Test::default().into(); + consume(&test)?; + + let test: ITest = produce()?; + test_noexcept(&test); + test_except(&test) } From 0139d5d590519728778276df5b48d7e0ad3b8099 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 6 Jun 2024 14:45:57 -0500 Subject: [PATCH 09/10] gnu is a mess --- crates/tests/noexcept/build.rs | 4 ++++ crates/tests/noexcept/src/lib.rs | 2 ++ crates/tests/noexcept/tests/test.rs | 2 ++ 3 files changed, 8 insertions(+) diff --git a/crates/tests/noexcept/build.rs b/crates/tests/noexcept/build.rs index fb516b21f1..3cf9fbfe49 100644 --- a/crates/tests/noexcept/build.rs +++ b/crates/tests/noexcept/build.rs @@ -1,4 +1,8 @@ fn main() { + if !cfg!(target_env = "msvc") { + return; + } + println!("cargo:rerun-if-changed=src/test.idl"); let metadata_dir = format!("{}\\System32\\WinMetadata", env!("windir")); let mut command = std::process::Command::new("midlrt.exe"); diff --git a/crates/tests/noexcept/src/lib.rs b/crates/tests/noexcept/src/lib.rs index 79a79039e3..6bff33433c 100644 --- a/crates/tests/noexcept/src/lib.rs +++ b/crates/tests/noexcept/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg(target_env = "msvc")] + mod bindings; pub use bindings::*; pub use windows_core::*; diff --git a/crates/tests/noexcept/tests/test.rs b/crates/tests/noexcept/tests/test.rs index 63af99dd4e..0ab220686a 100644 --- a/crates/tests/noexcept/tests/test.rs +++ b/crates/tests/noexcept/tests/test.rs @@ -1,3 +1,5 @@ +#![cfg(target_env = "msvc")] + use test_noexcept::*; #[implement(ITest)] From b33162247b4ecd3e0f4e467e1f6410f5a6ad7328 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 6 Jun 2024 14:54:06 -0500 Subject: [PATCH 10/10] simpler --- crates/libs/bindgen/src/rust/writer.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/crates/libs/bindgen/src/rust/writer.rs b/crates/libs/bindgen/src/rust/writer.rs index 26cddf50e2..c37778cd97 100644 --- a/crates/libs/bindgen/src/rust/writer.rs +++ b/crates/libs/bindgen/src/rust/writer.rs @@ -1291,16 +1291,15 @@ impl Writer { .iter() .map(|p| self.winrt_produce_type(p, !is_delegate)); - let return_type_tokens = match &signature.return_type { - metadata::Type::Void => quote! { () }, - _ => { - let tokens = self.type_name(&signature.return_type); + let return_type_tokens = if signature.return_type == metadata::Type::Void { + quote! { () } + } else { + let tokens = self.type_name(&signature.return_type); - if signature.return_type.is_winrt_array() { - quote! { windows_core::Array<#tokens> } - } else { - tokens - } + if signature.return_type.is_winrt_array() { + quote! { windows_core::Array<#tokens> } + } else { + tokens } };