Skip to content

Commit

Permalink
More accurate signature parameter parsing (#1913)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr authored Jul 15, 2022
1 parent 623f66b commit 8ea5e6a
Show file tree
Hide file tree
Showing 224 changed files with 8,388 additions and 18,519 deletions.
47 changes: 29 additions & 18 deletions crates/libs/bindgen/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ impl<'a> Gen<'a> {
}
/// The signature params which are generic (along with their relative index)
pub fn generic_params<'b>(&'b self, params: &'b [SignatureParam]) -> impl Iterator<Item = (usize, &SignatureParam)> + 'b {
params.iter().filter(move |param| self.reader.signature_param_is_generic(param)).enumerate()
params.iter().filter(move |param| self.reader.signature_param_is_convertible(param)).enumerate()
}
/// The generic param names (i.e., `T` in `fn foo<T>()`)
pub fn constraint_generics(&self, params: &[SignatureParam]) -> TokenStream {
Expand Down Expand Up @@ -317,11 +317,10 @@ impl<'a> Gen<'a> {
name
};
for (position, param) in self.generic_params(params) {
if self.reader.signature_param_is_param(param) {
let name: TokenStream = gen_name(position);
let into = self.type_name(&param.ty);
tokens.combine(&quote! { #name: ::std::convert::Into<::windows::core::InParam<'a, #into>>, });
} else if self.reader.signature_param_is_failible_param(param) {
if !self.reader.signature_param_input_value(param) {
continue;
}
if self.reader.signature_param_is_failible_param(param) {
let name: TokenStream = gen_name(position);
let error_name: TokenStream = format!("E{}", position).into();
let into = self.type_name(&param.ty);
Expand All @@ -330,7 +329,7 @@ impl<'a> Gen<'a> {
let name: TokenStream = gen_name(position);
let into = self.type_name(&param.ty);
tokens.combine(&quote! { #name: ::std::convert::Into<::windows::core::InParam<'a, #into>>, });
} else if self.reader.signature_param_is_convertible(param) {
} else if self.reader.signature_param_is_trivially_convertible(param) {
let name: TokenStream = gen_name(position);
let into = self.type_name(&param.ty);
tokens.combine(&quote! { #name: ::std::convert::Into<#into>, });
Expand Down Expand Up @@ -941,16 +940,23 @@ impl<'a> Gen<'a> {
let name = self.param_name(params[relative].def);
quote! { #name.len() as _, }
}
_ if self.reader.signature_param_is_borrowed(param) => {
quote! { #name.into().abi(), }
}
_ if self.reader.signature_param_is_convertible(param) => {
quote! { #name.into(), }
}
_ if self.reader.signature_param_is_primitive(param) => {
quote! { #name, }
_ => {
if self.reader.signature_param_input_value(param) {
if self.reader.signature_param_is_borrowed(param) {
quote! { #name.into().abi(), }
} else if self.reader.signature_param_is_trivially_convertible(param) {
quote! { #name.into(), }
} else if self.reader.type_is_primitive(&param.ty) {
quote! { #name, }
} else if self.reader.type_is_blittable(&param.ty) {
quote! { ::core::mem::transmute(#name), }
} else {
quote! { ::core::mem::transmute_copy(#name), }
}
} else {
quote! { ::core::mem::transmute(#name), }
}
}
_ => quote! { ::core::mem::transmute(#name), },
}
}
};
Expand Down Expand Up @@ -1009,15 +1015,20 @@ impl<'a> Gen<'a> {
continue;
}

if self.reader.signature_param_is_generic(param) {
if self.reader.signature_param_is_convertible(param) {
let (position, _) = generic_params.next().unwrap();
let kind: TokenStream = format!("P{}", position).into();
tokens.combine(&quote! { #name: #kind, });
continue;
}

let kind = self.type_default_name(&param.ty);
tokens.combine(&quote! { #name: #kind, });

if self.reader.type_is_blittable(&param.ty) {
tokens.combine(&quote! { #name: #kind, });
} else {
tokens.combine(&quote! { #name: &#kind, });
}
}

tokens
Expand Down
20 changes: 6 additions & 14 deletions crates/libs/bindgen/src/winrt_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,14 @@ fn gen_winrt_params(gen: &Gen, params: &[SignatureParam]) -> TokenStream {
if gen.reader.param_flags(param.def).input() {
if param.ty.is_winrt_array() {
result.combine(&quote! { #name: &[#default_type], });
} else if gen.reader.signature_param_is_generic(param) {
} else if gen.reader.signature_param_is_convertible(param) {
let (position, _) = generic_params.next().unwrap();
let kind: TokenStream = format!("P{}", position).into();
result.combine(&quote! { #name: #kind, });
} else {
} else if gen.reader.type_is_blittable(&param.ty) {
result.combine(&quote! { #name: #kind, });
} else {
result.combine(&quote! { #name: &#kind, });
}
} else if param.ty.is_winrt_array() {
result.combine(&quote! { #name: &mut [#default_type], });
Expand All @@ -180,19 +182,9 @@ fn gen_winrt_abi_args(gen: &Gen, params: &[SignatureParam]) -> TokenStream {
if param.ty.is_winrt_array() {
quote! { #name.len() as u32, ::core::mem::transmute(#name.as_ptr()), }
} else if gen.reader.signature_param_is_failible_param(param) {
if param.ty.is_winrt_const_ref() {
quote! { &#name.try_into().map_err(|e| e.into())?.abi(), }
} else {
quote! { #name.try_into().map_err(|e| e.into())?.abi(), }
}
quote! { #name.try_into().map_err(|e| e.into())?.abi(), }
} else if gen.reader.signature_param_is_borrowed(param) {
if param.ty.is_winrt_const_ref() {
quote! { &#name.into().abi(), }
} else {
quote! { #name.into().abi(), }
}
} else if gen.reader.signature_param_is_convertible(param) {
quote! { #name.into(), }
quote! { #name.into().abi(), }
} else if gen.reader.type_is_blittable(&param.ty) {
if param.ty.is_winrt_const_ref() {
quote! { &#name, }
Expand Down
46 changes: 17 additions & 29 deletions crates/libs/metadata/src/reader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -790,16 +790,14 @@ impl<'a> Reader<'a> {
// TODO: should this just check whether the struct has > 1 fields rather than type_def_is_handle?
self.type_def_kind(row) == TypeKind::Struct && !self.type_def_is_handle(row)
}
pub fn type_def_is_in_class_hierarchy(&self, row: TypeDef) -> bool {
matches!(self.type_def_kind(row), TypeKind::Class)
}
pub fn type_def_is_borrowed(&self, row: TypeDef) -> bool {
match self.type_def_kind(row) {
TypeKind::Class => true,
TypeKind::Delegate => self.type_def_flags(row).winrt(),
_ => !self.type_def_is_blittable(row),
}
}
pub fn type_def_is_convertible(&self, row: TypeDef) -> bool {
pub fn type_def_is_trivially_convertible(&self, row: TypeDef) -> bool {
match self.type_def_kind(row) {
TypeKind::Struct => self.type_def_is_handle(row) && self.type_def_type_name(row) != TypeName::BSTR,
_ => false,
Expand Down Expand Up @@ -1147,24 +1145,18 @@ impl<'a> Reader<'a> {
signature.params.iter().for_each(|param| self.type_cfg_combine(&param.ty, cfg));
}
pub fn signature_param_is_borrowed(&self, param: &SignatureParam) -> bool {
self.signature_param_maybe_generic(param) && self.type_is_borrowed(&param.ty)
}
pub fn signature_param_is_param(&self, param: &SignatureParam) -> bool {
self.signature_param_maybe_generic(param) && self.type_is_in_class_hierarchy(&param.ty)
self.type_is_borrowed(&param.ty)
}
pub fn signature_param_is_failible_param(&self, param: &SignatureParam) -> bool {
self.signature_param_maybe_generic(param) && self.type_is_non_exclusive_winrt_interface(&param.ty)
self.type_is_non_exclusive_winrt_interface(&param.ty)
}
pub fn signature_param_is_convertible(&self, param: &SignatureParam) -> bool {
self.signature_param_maybe_generic(param) && self.type_is_convertible(&param.ty)
pub fn signature_param_is_trivially_convertible(&self, param: &SignatureParam) -> bool {
self.type_is_trivially_convertible(&param.ty)
}
pub fn signature_param_is_primitive(&self, param: &SignatureParam) -> bool {
self.signature_param_maybe_generic(param) && self.type_is_primitive(&param.ty)
}
pub fn signature_param_is_generic(&self, param: &SignatureParam) -> bool {
self.signature_param_maybe_generic(param) && (self.signature_param_is_borrowed(param) || self.signature_param_is_param(param) || self.signature_param_is_failible_param(param) || self.signature_param_is_convertible(param))
pub fn signature_param_is_convertible(&self, param: &SignatureParam) -> bool {
self.signature_param_input_value(param) && (self.type_is_borrowed(&param.ty) || self.type_is_non_exclusive_winrt_interface(&param.ty) || self.type_is_trivially_convertible(&param.ty))
}
pub fn signature_param_maybe_generic(&self, param: &SignatureParam) -> bool {
pub fn signature_param_input_value(&self, param: &SignatureParam) -> bool {
self.param_flags(param.def).input() && !param.ty.is_winrt_array() && !param.ty.is_pointer() && param.array_info == ArrayInfo::None
}
pub fn signature_param_is_retval(&self, param: &SignatureParam) -> bool {
Expand Down Expand Up @@ -1524,29 +1516,25 @@ impl<'a> Reader<'a> {
_ => false,
}
}
pub fn type_is_borrowed(&self, ty: &Type) -> bool {
fn type_is_borrowed(&self, ty: &Type) -> bool {
match ty {
Type::TypeDef((row, _)) => self.type_def_is_borrowed(*row),
Type::String | Type::IInspectable | Type::IUnknown | Type::GenericParam(_) => true,
Type::WinrtConstRef(ty) => self.type_is_borrowed(ty),
Type::IInspectable | Type::IUnknown | Type::GenericParam(_) => true,
_ => false,
}
}
pub fn type_is_non_exclusive_winrt_interface(&self, ty: &Type) -> bool {
match ty {
Type::TypeDef((row, _)) => !self.type_def_is_exclusive(*row) && self.type_def_flags(*row).winrt() && self.type_def_flags(*row).interface(),
_ => false,
}
}
pub fn type_is_in_class_hierarchy(&self, ty: &Type) -> bool {
match ty {
Type::TypeDef((row, _)) => self.type_def_is_in_class_hierarchy(*row),
Type::TypeDef((row, _)) => {
let flags = self.type_def_flags(*row);
flags.winrt() && flags.interface() && !self.type_def_is_exclusive(*row)
}
_ => false,
}
}
pub fn type_is_convertible(&self, ty: &Type) -> bool {
pub fn type_is_trivially_convertible(&self, ty: &Type) -> bool {
match ty {
Type::TypeDef((row, _)) => self.type_def_is_convertible(*row),
Type::TypeDef((row, _)) => self.type_def_is_trivially_convertible(*row),
Type::PCSTR | Type::PCWSTR => true,
_ => false,
}
Expand Down
Loading

0 comments on commit 8ea5e6a

Please sign in to comment.