Skip to content

Commit

Permalink
Simplified parameter bindings and type projection (#2775)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr authored Jan 7, 2024
1 parent 7219668 commit a4a2241
Show file tree
Hide file tree
Showing 827 changed files with 61,684 additions and 171,659 deletions.
27 changes: 2 additions & 25 deletions crates/libs/bindgen/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ pub enum SignatureParamKind {
ArrayRelativeLen(usize),
ArrayRelativeByteLen(usize),
ArrayRelativePtr(usize),
TryInto,
IntoParam,
OptionalPointer,
ValueType,
Expand Down Expand Up @@ -115,7 +114,7 @@ impl SignatureParamKind {

impl SignatureParam {
pub fn is_convertible(&self) -> bool {
!self.def.flags().contains(ParamAttributes::Out) && !self.ty.is_winrt_array() && !self.ty.is_pointer() && !self.kind.is_array() && (type_is_borrowed(&self.ty) || type_is_non_exclusive_winrt_interface(&self.ty) || type_is_trivially_convertible(&self.ty))
!self.def.flags().contains(ParamAttributes::Out) && !self.ty.is_winrt_array() && !self.ty.is_pointer() && !self.kind.is_array() && (type_is_borrowed(&self.ty) || type_is_trivially_convertible(&self.ty))
}

fn is_retval(&self) -> bool {
Expand Down Expand Up @@ -292,11 +291,7 @@ pub fn method_def_signature(namespace: &str, row: MethodDef, generics: &[Type])
for param in &mut params {
if param.kind == SignatureParamKind::Other {
if param.is_convertible() {
if type_is_non_exclusive_winrt_interface(&param.ty) {
param.kind = SignatureParamKind::TryInto;
} else {
param.kind = SignatureParamKind::IntoParam;
}
param.kind = SignatureParamKind::IntoParam;
} else {
let flags = param.def.flags();
if param.ty.is_pointer() && (flags.contains(ParamAttributes::Optional) || param.def.has_attribute("ReservedAttribute")) {
Expand Down Expand Up @@ -376,24 +371,6 @@ pub fn type_is_borrowed(ty: &Type) -> bool {
}
}

pub fn type_is_non_exclusive_winrt_interface(ty: &Type) -> bool {
match ty {
Type::TypeDef(row, _) => {
let flags = row.flags();
if !flags.contains(TypeAttributes::WindowsRuntime) {
false
} else {
match row.kind() {
TypeKind::Interface => !type_def_is_exclusive(*row),
TypeKind::Class => row.has_attribute("ComposableAttribute"),
_ => false,
}
}
}
_ => false,
}
}

fn type_is_trivially_convertible(ty: &Type) -> bool {
match ty {
Type::TypeDef(row, _) => match row.kind() {
Expand Down
38 changes: 23 additions & 15 deletions crates/libs/bindgen/src/rust/classes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,20 +89,24 @@ fn gen_class(writer: &Writer, def: metadata::TypeDef) -> TokenStream {
#[repr(transparent)]
#[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::fmt::Debug, ::core::clone::Clone)]
pub struct #name(::windows_core::IUnknown);
};

tokens.combine(&gen_conversions(writer, def, &name, &interfaces, &cfg));

tokens.combine(&quote! {
#features
impl #name {
#new
#methods
#(#factories)*
}
};
});

tokens.combine(&writer.interface_winrt_trait(def, &[], &name, &TokenStream::new(), &TokenStream::new(), &features));
tokens.combine(&writer.interface_trait(def, &[], &name, &TokenStream::new(), &features, true));
tokens.combine(&writer.runtime_name_trait(def, &[], &name, &TokenStream::new(), &features));
tokens.combine(&writer.async_get(def, &[], &name, &TokenStream::new(), &TokenStream::new(), &features));
tokens.combine(&iterators::writer(writer, def, &[], &name, &TokenStream::new(), &TokenStream::new(), &cfg));
tokens.combine(&gen_conversions(writer, def, &name, &interfaces, &cfg));
tokens.combine(&writer.agile(def, &name, &TokenStream::new(), &features));
tokens
} else {
Expand All @@ -122,13 +126,17 @@ fn gen_class(writer: &Writer, def: metadata::TypeDef) -> TokenStream {
}
}

fn gen_conversions(writer: &Writer, def: metadata::TypeDef, name: &TokenStream, interfaces: &[metadata::Interface], cfg: &cfg::Cfg) -> TokenStream {
fn gen_conversions(writer: &Writer, def: metadata::TypeDef, ident: &TokenStream, interfaces: &[metadata::Interface], cfg: &cfg::Cfg) -> TokenStream {
let features = writer.cfg_features(cfg);
let mut tokens = quote! {
#features
::windows_core::imp::interface_hierarchy!(#name, ::windows_core::IUnknown, ::windows_core::IInspectable);
::windows_core::imp::interface_hierarchy!(#ident, ::windows_core::IUnknown, ::windows_core::IInspectable);
};

let mut hierarchy = format!("::windows_core::imp::required_hierarchy!({ident}");
let mut hierarchy_cfg = cfg.clone();
let mut hierarchy_added = false;

for interface in interfaces {
if type_is_exclusive(&interface.ty) {
continue;
Expand All @@ -139,22 +147,22 @@ fn gen_conversions(writer: &Writer, def: metadata::TypeDef, name: &TokenStream,
}

let into = writer.type_name(&interface.ty);
let features = writer.cfg_features(&cfg.union(&cfg::type_cfg(&interface.ty)));

tokens.combine(&quote! {
#features
impl ::windows_core::CanTryInto<#into> for #name {}
});
write!(&mut hierarchy, ", {into}").unwrap();
hierarchy_cfg = hierarchy_cfg.union(&cfg::type_cfg(&interface.ty));
hierarchy_added = true;
}

for def in metadata::type_def_bases(def) {
let into = writer.type_def_name(def, &[]);
let features = writer.cfg_features(&cfg.union(&cfg::type_def_cfg(def, &[])));
write!(&mut hierarchy, ", {into}").unwrap();
hierarchy_cfg = hierarchy_cfg.union(&cfg::type_def_cfg(def, &[]));
hierarchy_added = true;
}

tokens.combine(&quote! {
#features
impl ::windows_core::CanTryInto<#into> for #name {}
});
if hierarchy_added {
hierarchy.push_str(");");
tokens.combine(&writer.cfg_features(&hierarchy_cfg));
tokens.push_str(&hierarchy);
}

tokens
Expand Down
4 changes: 2 additions & 2 deletions crates/libs/bindgen/src/rust/com_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef, kind: metadata::Interface
let args = writer.win32_args(&signature.params, kind);
let params = writer.win32_params(&signature.params, kind);
let generics = expand_generics(generics, quote!(T));
let where_clause = expand_where_clause(where_clause, quote!(T: ::windows_core::ComInterface));
let where_clause = expand_where_clause(where_clause, quote!(T: ::windows_core::Interface));

quote! {
#doc
Expand All @@ -43,7 +43,7 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef, kind: metadata::Interface
let args = writer.win32_args(&signature.params, kind);
let params = writer.win32_params(&signature.params, kind);
let generics = expand_generics(generics, quote!(T));
let where_clause = expand_where_clause(where_clause, quote!(T: ::windows_core::ComInterface));
let where_clause = expand_where_clause(where_clause, quote!(T: ::windows_core::Interface));

quote! {
#doc
Expand Down
31 changes: 21 additions & 10 deletions crates/libs/bindgen/src/rust/delegates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,23 @@ fn gen_win_delegate(writer: &Writer, def: metadata::TypeDef) -> TokenStream {
let invoke = winrt_methods::writer(writer, def, generics, metadata::InterfaceKind::Default, method, &mut MethodNames::new(), &mut MethodNames::new());
let invoke_upcall = winrt_methods::gen_upcall(writer, &signature, quote! { ((*this).invoke) });

let mut tokens = quote! {
#doc
#features
#[repr(transparent)]
#[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::fmt::Debug, ::core::clone::Clone)]
pub struct #ident(pub ::windows_core::IUnknown, #phantoms) where #constraints;
let mut tokens = if generics.is_empty() {
let iid = writer.guid_literal(metadata::type_def_guid(def));
quote! {
#features
::windows_core::imp::com_interface!(#doc #ident, #vtbl, #iid);
}
} else {
quote! {
#doc
#features
#[repr(transparent)]
#[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::fmt::Debug, ::core::clone::Clone)]
pub struct #ident(::windows_core::IUnknown, #phantoms) where #constraints;
}
};

tokens.combine(&quote! {
#features
impl<#constraints> #ident {
pub fn new<#fn_constraint>(invoke: F) -> Self {
Expand Down Expand Up @@ -109,9 +120,9 @@ fn gen_win_delegate(writer: &Writer, def: metadata::TypeDef) -> TokenStream {
return ::windows_core::HRESULT(-2147467261); // E_POINTER
}

*interface = if *iid == <#ident as ::windows_core::ComInterface>::IID ||
*iid == <::windows_core::IUnknown as ::windows_core::ComInterface>::IID ||
*iid == <::windows_core::imp::IAgileObject as ::windows_core::ComInterface>::IID {
*interface = if *iid == <#ident as ::windows_core::Interface>::IID ||
*iid == <::windows_core::IUnknown as ::windows_core::Interface>::IID ||
*iid == <::windows_core::imp::IAgileObject as ::windows_core::Interface>::IID {
&mut (*this).vtable as *mut _ as _
} else {
::core::ptr::null_mut()
Expand Down Expand Up @@ -145,7 +156,7 @@ fn gen_win_delegate(writer: &Writer, def: metadata::TypeDef) -> TokenStream {
#invoke_upcall
}
}
};
});

tokens.combine(&writer.interface_trait(def, generics, &ident, &constraints, &features, true));
tokens.combine(&writer.interface_winrt_trait(def, generics, &ident, &constraints, &phantoms, &features));
Expand Down
4 changes: 2 additions & 2 deletions crates/libs/bindgen/src/rust/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ fn gen_win_function(writer: &Writer, namespace: &str, def: metadata::MethodDef)
let args = writer.win32_args(&signature.params, kind);
let params = writer.win32_params(&signature.params, kind);
let generics = expand_generics(generics, quote!(T));
let where_clause = expand_where_clause(where_clause, quote!(T: ::windows_core::ComInterface));
let where_clause = expand_where_clause(where_clause, quote!(T: ::windows_core::Interface));

quote! {
#doc
Expand All @@ -63,7 +63,7 @@ fn gen_win_function(writer: &Writer, namespace: &str, def: metadata::MethodDef)
let args = writer.win32_args(&signature.params, kind);
let params = writer.win32_params(&signature.params, kind);
let generics = expand_generics(generics, quote!(T));
let where_clause = expand_where_clause(where_clause, quote!(T: ::windows_core::ComInterface));
let where_clause = expand_where_clause(where_clause, quote!(T: ::windows_core::Interface));

quote! {
#doc
Expand Down
4 changes: 2 additions & 2 deletions crates/libs/bindgen/src/rust/implements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream {
}
}

let mut matches = quote! { iid == &<#type_ident as ::windows_core::ComInterface>::IID };
let mut matches = quote! { iid == &<#type_ident as ::windows_core::Interface>::IID };

if let Some(metadata::Type::TypeDef(def, _)) = vtables.last() {
requires.combine(&gen_required_trait(writer, *def, &[]))
Expand All @@ -40,7 +40,7 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef) -> TokenStream {
let name = writer.type_def_name(*def, generics);

matches.combine(&quote! {
|| iid == &<#name as ::windows_core::ComInterface>::IID
|| iid == &<#name as ::windows_core::Interface>::IID
})
}
}
Expand Down
79 changes: 50 additions & 29 deletions crates/libs/bindgen/src/rust/interfaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ fn gen_sys_interface(def: metadata::TypeDef) -> TokenStream {
fn gen_win_interface(writer: &Writer, def: metadata::TypeDef) -> TokenStream {
let generics = &metadata::type_def_generics(def);
let ident = writer.type_def_name(def, generics);
let vtbl_ident = writer.type_def_vtbl_name(def, generics);
let is_exclusive = metadata::type_def_is_exclusive(def);
let phantoms = writer.generic_phantoms(generics);
let constraints = writer.generic_constraints(generics);
Expand All @@ -34,25 +35,29 @@ fn gen_win_interface(writer: &Writer, def: metadata::TypeDef) -> TokenStream {
let vtables = metadata::type_def_vtables(def);
let has_unknown_base = matches!(vtables.first(), Some(metadata::Type::IUnknown));

let mut tokens = if is_exclusive {
quote! { #[doc(hidden)] }
} else {
quote! { #doc }
};
let mut tokens = quote! {};

if has_unknown_base {
tokens.combine(&quote! {
#features
#[repr(transparent)]
#[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::fmt::Debug, ::core::clone::Clone)]
pub struct #ident(::windows_core::IUnknown, #phantoms) where #constraints;
});
if generics.is_empty() {
let iid = writer.guid_literal(metadata::type_def_guid(def));
tokens.combine(&quote! {
#features
::windows_core::imp::com_interface!(#doc #ident, #vtbl_ident, #iid);
});
} else {
tokens.combine(&quote! {
#doc
#features
#[repr(transparent)]
#[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::fmt::Debug, ::core::clone::Clone)]
pub struct #ident(::windows_core::IUnknown, #phantoms) where #constraints;
});
}
} else {
tokens.combine(&quote! {
#doc
#features
#[repr(transparent)]
#[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::fmt::Debug, ::core::clone::Clone)]
pub struct #ident(::std::ptr::NonNull<::std::ffi::c_void>);
::windows_core::imp::interface!(#ident, #vtbl_ident);
});
}

Expand Down Expand Up @@ -95,13 +100,6 @@ fn gen_win_interface(writer: &Writer, def: metadata::TypeDef) -> TokenStream {
}
}

tokens.combine(&quote! {
#features
impl<#constraints> #ident {
#methods
}
});

if !vtables.is_empty() && generics.is_empty() {
let mut hierarchy = format!("::windows_core::imp::interface_hierarchy!({ident}");
let mut hierarchy_cfg = cfg.clone();
Expand All @@ -127,17 +125,40 @@ fn gen_win_interface(writer: &Writer, def: metadata::TypeDef) -> TokenStream {
}
}

if def.flags().contains(metadata::TypeAttributes::WindowsRuntime) {
for interface in &interfaces {
let into = writer.type_name(&interface.ty);
let cfg = writer.cfg_features(&cfg.union(&cfg::type_cfg(&interface.ty)));
tokens.combine(&quote! {
#cfg
impl<#constraints> ::windows_core::CanTryInto<#into> for #ident {}
});
if def.flags().contains(metadata::TypeAttributes::WindowsRuntime) && !interfaces.is_empty() {
if generics.is_empty() {
let mut hierarchy = format!("::windows_core::imp::required_hierarchy!({ident}");
let mut hierarchy_cfg = cfg.clone();

for interface in &interfaces {
let into = writer.type_name(&interface.ty);

write!(&mut hierarchy, ", {into}").unwrap();
hierarchy_cfg = hierarchy_cfg.union(&cfg::type_cfg(&interface.ty));
}

hierarchy.push_str(");");
tokens.combine(&writer.cfg_features(&hierarchy_cfg));
tokens.push_str(&hierarchy);
} else {
for interface in &interfaces {
let into = writer.type_name(&interface.ty);
let cfg = writer.cfg_features(&cfg.union(&cfg::type_cfg(&interface.ty)));
tokens.combine(&quote! {
#cfg
impl<#constraints> ::windows_core::CanInto<#into> for #ident { const QUERY: bool = true; }
});
}
}
}

tokens.combine(&quote! {
#features
impl<#constraints> #ident {
#methods
}
});

tokens.combine(&writer.interface_winrt_trait(def, generics, &ident, &constraints, &phantoms, &features));
tokens.combine(&writer.async_get(def, generics, &ident, &constraints, &phantoms, &features));
tokens.combine(&iterators::writer(writer, def, generics, &ident, &constraints, &phantoms, &cfg));
Expand Down
4 changes: 2 additions & 2 deletions crates/libs/bindgen/src/rust/iterators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef, generics: &[metadata::Typ
type IntoIter = #wfc VectorViewIterator<Self::Item>;

fn into_iter(self) -> Self::IntoIter {
#wfc VectorViewIterator::new(::windows_core::ComInterface::cast(self).ok())
#wfc VectorViewIterator::new(::windows_core::Interface::cast(self).ok())
}
}
};
Expand All @@ -199,7 +199,7 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef, generics: &[metadata::Typ
type IntoIter = #wfc VectorIterator<Self::Item>;

fn into_iter(self) -> Self::IntoIter {
#wfc VectorIterator::new(::windows_core::ComInterface::cast(self).ok())
#wfc VectorIterator::new(::windows_core::Interface::cast(self).ok())
}
}
};
Expand Down
4 changes: 1 addition & 3 deletions crates/libs/bindgen/src/rust/winrt_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pub fn writer(writer: &Writer, def: metadata::TypeDef, generic_types: &[metadata
#doc
#features
pub fn #name<#generics>(&self, #params) -> ::windows_core::Result<#return_type_tokens> #where_clause {
let this = &::windows_core::ComInterface::cast::<#interface_name>(self)?;
let this = &::windows_core::Interface::cast::<#interface_name>(self)?;
unsafe {
#vcall
}
Expand Down Expand Up @@ -142,8 +142,6 @@ fn gen_winrt_abi_args(writer: &Writer, params: &[metadata::SignatureParam]) -> T
} else {
quote! { #name.len().try_into().unwrap(), ::core::mem::transmute(#name.as_ptr()), }
}
} else if metadata::type_is_non_exclusive_winrt_interface(&param.ty) {
quote! { #name.try_into_param()?.abi(), }
} else if metadata::type_is_borrowed(&param.ty) {
quote! { #name.into_param().abi(), }
} else if metadata::type_is_blittable(&param.ty) {
Expand Down
Loading

0 comments on commit a4a2241

Please sign in to comment.