Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplified parameter bindings and type projection #2775

Merged
merged 10 commits into from
Jan 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
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