Skip to content

Commit

Permalink
WIP: cxx-qt-gen: expand Result and Pin correct in Rust wrapper genera…
Browse files Browse the repository at this point in the history
…tion

Related to KDAB#404
  • Loading branch information
ahayzen-kdab committed Jun 22, 2023
1 parent db0226d commit e018a3e
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 3 deletions.
4 changes: 3 additions & 1 deletion crates/cxx-qt-gen/src/generator/rust/invokable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ pub fn generate_rust_invokables(
};

let return_type = &invokable.method.sig.output;
// TODO: If we are a Result<T> then change it to a Result<T, _> and use inference
let wrapper_return_type = return_type;
let has_return = if matches!(invokable.method.sig.output, ReturnType::Default) {
quote! {}
} else {
Expand All @@ -77,7 +79,7 @@ pub fn generate_rust_invokables(
// TODO: is an unsafe block valid?
extern "Rust" {
#[cxx_name = #wrapper_ident_cpp]
#unsafe_call fn #wrapper_ident_rust(#parameter_signatures) #return_type;
#unsafe_call fn #wrapper_ident_rust(#parameter_signatures) #wrapper_return_type;
}
}],
implementation: vec![
Expand Down
3 changes: 3 additions & 0 deletions crates/cxx-qt-gen/src/generator/utils/cpp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ fn path_segment_to_string(
let mut ident = segment.ident.to_string();

// If we are a Pin<T> then for C++ it becomes just T
//
// TODO: this could become confused if Pin is not the first arg
// we should likely have a separate way of checking the first segment in the future?
let args = match ident.as_str() {
"Pin" => {
ident = path_argument_to_string(&segment.arguments, cxx_mapping)?
Expand Down
69 changes: 67 additions & 2 deletions crates/cxx-qt-gen/src/generator/utils/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,58 @@
//
// SPDX-License-Identifier: MIT OR Apache-2.0

use syn::{GenericArgument, PathArguments, Type, TypeReference};
use syn::{parse_quote, GenericArgument, PathArguments, ReturnType, Type, TypeReference};

// TODO: Result<T> -> Result<T, _>
//
// TODO: is this where we do Pin -> core::pin::Pin as well and have a normal method as well?
pub(crate) fn syn_cxx_bridge_return_type_as_normal_type(ty: &ReturnType) -> ReturnType {
if let ReturnType::Type(default, ty) = ty {
// If there is a Result<T> then convert to a Result<T, _>
if let Type::Path(ty_path) = &**ty {
if let Some(segment) = ty_path.path.segments.first() {
if segment.ident == "Result" {
if let PathArguments::AngleBracketed(angled) = &segment.arguments {
if angled.args.len() == 1 {
let arg = &angled.args[0];

return ReturnType::Type(
default.clone(),
parse_quote! { Result<#arg, _> },
);
}
}
}
}
}

return ReturnType::Type(
default.clone(),
Box::new(syn_cxx_bridge_type_as_normal_type(ty)),
);
}

ty.clone()
}

pub(crate) fn syn_cxx_bridge_type_as_normal_type(ty: &Type) -> Type {
match ty {
Type::Path(ty_path) => {
if let Some(seg) = ty_path.path.segments.first() {
// Ensure Pin is core::pin::Pin
if seg.ident == "Pin" {
let mut ty_path = ty_path.clone();
ty_path.path.segments.insert(0, parse_quote! { pin });
ty_path.path.segments.insert(0, parse_quote! { core });
return Type::Path(ty_path);
}
}
}
_others => {}
}

ty.clone()
}

/// Return if the type is unsafe for CXX bridges
pub(crate) fn syn_type_is_cxx_bridge_unsafe(ty: &syn::Type) -> bool {
Expand Down Expand Up @@ -33,7 +84,21 @@ pub(crate) fn syn_type_is_cxx_bridge_unsafe(ty: &syn::Type) -> bool {
mod tests {
use super::*;

use syn::parse_quote;
#[test]
fn test_syn_cxx_bridge_return_type_as_normal_type_pin() {
assert_eq!(
syn_cxx_bridge_return_type_as_normal_type(&parse_quote! { Result<T> }),
parse_quote! { Result<T, _> }
);
}

#[test]
fn test_syn_cxx_bridge_type_as_normal_type_pin() {
assert_eq!(
syn_cxx_bridge_type_as_normal_type(&parse_quote! { Pin<T> }),
parse_quote! { core::pin::Pin<T> }
);
}

#[test]
fn test_syn_type_is_cxx_bridge_unsafe_path() {
Expand Down

0 comments on commit e018a3e

Please sign in to comment.