Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
ahayzen-kdab committed May 29, 2023
1 parent 542f78b commit 6ee764b
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 9 deletions.
3 changes: 3 additions & 0 deletions crates/cxx-qt-gen/src/generator/cpp/inherit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ pub fn generate(

for method in inherited_methods {
let return_type = if let ReturnType::Type(_, ty) = &method.method.sig.output {
// TODO: this could be a Result<T> from C++ -> Rust as this is an extern "C++" block
//
// https://cxx.rs/binding/result.html#returning-result-from-c-to-rust
CppType::from(ty, &None, cxx_mappings)?
.as_cxx_ty()
.to_owned()
Expand Down
12 changes: 10 additions & 2 deletions crates/cxx-qt-gen/src/generator/rust/invokable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
generator::{
naming::{invokable::QInvokableName, qobject::QObjectName},
rust::{fragment::RustFragmentPair, qobject::GeneratedRustQObjectBlocks},
utils::rust::syn_type_is_cxx_bridge_unsafe,
utils::rust::{syn_return_type_for_cxx_bridge, syn_type_is_cxx_bridge_unsafe},
},
parser::invokable::ParsedQInvokable,
};
Expand Down Expand Up @@ -54,7 +54,15 @@ pub fn generate_rust_invokables(
.collect::<Vec<TokenStream>>();
quote! { self: #rust_struct, cpp: #cpp_struct, #(#parameters),* }
};

// TODO: this could be a Result<T> from Rust -> C++ as this is an extern "Rust" block
//
// TODO: when this goes into the CXX block we need to convert it to not have the extra return type
//
// https://cxx.rs/binding/result.html#returning-result-from-rust-to-c
let return_type = &invokable.method.sig.output;
// Build the CXX bridge return type as we need to remove the E from a Result<T, E>
let cxx_bridge_return_type = syn_return_type_for_cxx_bridge(return_type)?;
let has_return = if matches!(invokable.method.sig.output, ReturnType::Default) {
quote! {}
} else {
Expand Down Expand Up @@ -85,7 +93,7 @@ pub fn generate_rust_invokables(
cxx_bridge: vec![quote! {
extern "Rust" {
#[cxx_name = #wrapper_ident_cpp]
#has_unsafe fn #wrapper_ident_rust(#parameter_signatures) #return_type;
#has_unsafe fn #wrapper_ident_rust(#parameter_signatures) #cxx_bridge_return_type;
}
}],
implementation: vec![
Expand Down
29 changes: 23 additions & 6 deletions crates/cxx-qt-gen/src/generator/utils/cpp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,21 @@ 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
let args = if ident == "Pin" {
ident = path_argument_to_string(&segment.arguments, cxx_mapping)?
.map_or_else(|| "".to_owned(), |values| values.join(", "));
let args = match ident.as_str() {
"Pin" => {
ident = path_argument_to_string(&segment.arguments, cxx_mapping)?
.map_or_else(|| "".to_owned(), |values| values.join(", "));

None
} else {
path_argument_to_string(&segment.arguments, cxx_mapping)?.map(|values| values.join(", "))
None
}
"Result" => {
return Err(Error::new(segment.span(), "Result is not supported"));
}
"Option" => {
return Err(Error::new(segment.span(), "Option is not supported"));
}
_others => path_argument_to_string(&segment.arguments, cxx_mapping)?
.map(|values| values.join(", ")),
};

// If there are template args check that we aren't a recognised A of A<B>
Expand Down Expand Up @@ -554,4 +562,13 @@ mod tests {
"::rust::Fn<void, ()>"
);
}

#[test]
fn test_syn_type_to_cxx_type_result() {
let ty = parse_quote! { Result<(), std::io::Error> };
assert_eq!(
syn_type_to_cxx_type(&ty, &ParsedCxxMappings::default()).unwrap(),
""
);
}
}
12 changes: 11 additions & 1 deletion crates/cxx-qt-gen/src/generator/utils/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,17 @@
//
// SPDX-License-Identifier: MIT OR Apache-2.0

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

/// When a [syn::ReturnType] is used in a CXX bridge we need to ensure that
/// there is only one generic
pub(crate) fn syn_return_type_for_cxx_bridge(ty: &ReturnType) -> Result<ReturnType> {
// TODO: if Result<T, E> change to Result<T>

// FIXME: problem is that we can't detect anyhow::Result<T>

Ok(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

0 comments on commit 6ee764b

Please sign in to comment.