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

Precise generic type code generation #1492

Merged
merged 9 commits into from Feb 2, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/libs/bindgen/src/delegates.rs
Expand Up @@ -30,7 +30,7 @@ fn gen_win_delegate(def: &TypeDef, gen: &Gen) -> TokenStream {
let features = cfg.gen(gen);
let vtbl_signature = gen_vtbl_signature(def, &method, gen);
let invoke = gen_winrt_method(def, InterfaceKind::Default, &method, &mut MethodNames::new(), &mut MethodNames::new(), gen);
let invoke_upcall = gen_winrt_upcall(&signature, quote! { ((*this).invoke) }, gen);
let invoke_upcall = gen_winrt_upcall(&signature, quote! { ((*this).invoke) });

let mut tokens = quote! {
#doc
Expand Down
45 changes: 27 additions & 18 deletions crates/libs/bindgen/src/helpers.rs
Expand Up @@ -361,8 +361,8 @@ pub fn gen_win32_upcall(sig: &MethodSignature, inner: TokenStream) -> TokenStrea
}
}

pub fn gen_winrt_upcall(sig: &MethodSignature, inner: TokenStream, gen: &Gen) -> TokenStream {
let invoke_args = sig.params.iter().map(|param| gen_winrt_invoke_arg(param, gen));
pub fn gen_winrt_upcall(sig: &MethodSignature, inner: TokenStream) -> TokenStream {
let invoke_args = sig.params.iter().map(gen_winrt_invoke_arg);

match &sig.return_sig {
Some(return_sig) if return_sig.is_array => {
Expand Down Expand Up @@ -406,9 +406,8 @@ fn gen_win32_invoke_arg(param: &MethodParam) -> TokenStream {
}
}

fn gen_winrt_invoke_arg(param: &MethodParam, gen: &Gen) -> TokenStream {
fn gen_winrt_invoke_arg(param: &MethodParam) -> TokenStream {
let name = gen_param_name(&param.param);
let kind = gen_element_name(&param.signature.kind, gen);

if param.signature.is_array {
let abi_size_name: TokenStream = format!("{}_array_size", param.param.name()).into();
Expand All @@ -424,9 +423,9 @@ fn gen_winrt_invoke_arg(param: &MethodParam, gen: &Gen) -> TokenStream {
if param.signature.kind.is_primitive() {
quote! { #name }
} else if param.signature.is_const {
quote! { &*(#name as *const <#kind as ::windows::core::Abi>::Abi as *const <#kind as ::windows::core::DefaultType>::DefaultType) }
quote! { ::core::mem::transmute_copy(&#name) }
} else {
quote! { &*(&#name as *const <#kind as ::windows::core::Abi>::Abi as *const <#kind as ::windows::core::DefaultType>::DefaultType) }
quote! { ::core::mem::transmute(&#name) }
}
} else {
quote! { ::core::mem::transmute_copy(&#name) }
Expand Down Expand Up @@ -502,30 +501,40 @@ fn gen_win32_produce_type(param: &MethodParam, gen: &Gen) -> TokenStream {
}

fn gen_winrt_produce_type(param: &MethodParam, include_param_names: bool, gen: &Gen) -> TokenStream {
let tokens = gen_element_name(&param.signature.kind, gen);
let kind = gen_element_name(&param.signature.kind, gen);

let sig = if param.signature.is_array {
if param.param.is_input() {
quote! { &[<#tokens as ::windows::core::DefaultType>::DefaultType] }
} else if param.signature.by_ref {
quote! { &mut ::windows::core::Array<#tokens> }
if param.signature.by_ref {
quote! { &mut ::windows::core::Array<#kind> }
} else {
quote! { &mut [<#tokens as ::windows::core::DefaultType>::DefaultType] }
let kind = if let ElementType::GenericParam(_) = param.signature.kind {
quote! { <#kind as ::windows::core::DefaultType>::DefaultType }
} else if param.signature.kind.is_nullable() {
quote! { ::core::option::Option<#kind> }
} else {
kind
};

if param.param.is_input() {
quote! { &[#kind] }
} else {
quote! { &mut [#kind] }
}
}
} else if param.param.is_input() {
if let ElementType::GenericParam(_) = param.signature.kind {
quote! { &<#tokens as ::windows::core::DefaultType>::DefaultType }
quote! { &<#kind as ::windows::core::DefaultType>::DefaultType }
} else if param.signature.kind.is_primitive() {
quote! { #tokens }
quote! { #kind }
} else if param.signature.kind.is_nullable() {
quote! { &::core::option::Option<#tokens> }
quote! { &::core::option::Option<#kind> }
} else {
quote! { &#tokens }
quote! { &#kind }
}
} else if param.signature.kind.is_nullable() {
quote! { &mut ::core::option::Option<#tokens> }
quote! { &mut ::core::option::Option<#kind> }
} else {
quote! { &mut #tokens }
quote! { &mut #kind }
};

if include_param_names {
Expand Down
2 changes: 1 addition & 1 deletion crates/libs/bindgen/src/implements.rs
Expand Up @@ -73,7 +73,7 @@ pub fn gen(def: &TypeDef, gen: &Gen) -> TokenStream {
let signature = method.signature(&def.generics);
let vtbl_signature = gen_vtbl_signature(def, &method, gen);

let invoke_upcall = if def.is_winrt() { gen_winrt_upcall(&signature, quote! { (*this).#name }, gen) } else { gen_win32_upcall(&signature, quote! { (*this).#name }) };
let invoke_upcall = if def.is_winrt() { gen_winrt_upcall(&signature, quote! { (*this).#name }) } else { gen_win32_upcall(&signature, quote! { (*this).#name }) };

quote! {
unsafe extern "system" fn #name<#(#constraints)* Identity: ::windows::core::IUnknownImpl, Impl: #impl_ident<#(#generics)*>, const OFFSET: isize> #vtbl_signature {
Expand Down
18 changes: 14 additions & 4 deletions crates/libs/bindgen/src/methods.rs
Expand Up @@ -263,12 +263,22 @@ pub fn gen_winrt_params(params: &[MethodParam], gen: &Gen) -> TokenStream {
let kind = gen_element_name(&param.signature.kind, gen);

if param.signature.is_array {
if param.param.is_input() {
result.combine(&quote! { #name: &[<#kind as ::windows::core::DefaultType>::DefaultType], });
} else if param.signature.by_ref {
if param.signature.by_ref {
result.combine(&quote! { #name: &mut ::windows::core::Array<#kind>, });
} else {
result.combine(&quote! { #name: &mut [<#kind as ::windows::core::DefaultType>::DefaultType], });
let kind = if let ElementType::GenericParam(_) = param.signature.kind {
quote! { <#kind as ::windows::core::DefaultType>::DefaultType }
} else if param.signature.kind.is_nullable() {
quote! { ::core::option::Option<#kind> }
} else {
kind
};

if param.param.is_input() {
result.combine(&quote! { #name: &[#kind], });
} else {
result.combine(&quote! { #name: &mut [#kind], });
}
}
} else if param.param.is_input() {
if param.is_convertible() {
Expand Down