diff --git a/src/bindgen/ir/function.rs b/src/bindgen/ir/function.rs index a54c34d..59bfc05 100644 --- a/src/bindgen/ir/function.rs +++ b/src/bindgen/ir/function.rs @@ -11,7 +11,8 @@ use crate::bindgen::config::{Config, Language, Layout}; use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver; use crate::bindgen::dependencies::Dependencies; use crate::bindgen::ir::{ - AnnotationSet, Cfg, ConditionWrite, Documentation, Path, PrimitiveType, ToCondition, Type, + AnnotationSet, Cfg, ConditionWrite, Documentation, GenericPath, Path, PrimitiveType, + ToCondition, Type, }; use crate::bindgen::library::Library; use crate::bindgen::monomorph::Monomorphs; @@ -43,21 +44,22 @@ impl Function { attrs: &[syn::Attribute], mod_cfg: Option<&Cfg>, ) -> Result { - let args = sig - .inputs - .iter() - .try_skip_map(|x| x.as_ident_and_type(self_type_path.as_ref()))?; - let ret = match sig.output { + let mut args = sig.inputs.iter().try_skip_map(|x| x.as_ident_and_type())?; + + let mut ret = match sig.output { syn::ReturnType::Default => Type::Primitive(PrimitiveType::Void), syn::ReturnType::Type(_, ref ty) => { - if let Some(x) = Type::load(ty)? { - x - } else { - Type::Primitive(PrimitiveType::Void) - } + Type::load(ty)?.unwrap_or_else(|| Type::Primitive(PrimitiveType::Void)) } }; + if let Some(ref self_path) = self_type_path { + for (_, ref mut ty) in &mut args { + ty.replace_self_with(self_path); + } + ret.replace_self_with(self_path); + } + Ok(Function { path, self_type_path, @@ -73,14 +75,15 @@ impl Function { pub fn swift_name(&self) -> String { // If the symbol name starts with the type name, separate the two components with '.' // so that Swift recognises the association between the method and the type - let (ref type_prefix, ref type_name) = if let Some(type_name) = &self.self_type_path { - let type_name = type_name.to_string(); - if !self.path.name().starts_with(&type_name) { - return self.path.to_string(); + let (ref type_prefix, ref type_name) = match self.self_type_path { + Some(ref type_name) => { + let type_name = type_name.to_string(); + if !self.path.name().starts_with(&type_name) { + return self.path.to_string(); + } + (format!("{}.", type_name), type_name) } - (format!("{}.", type_name), type_name) - } else { - ("".to_string(), "".to_string()) + None => ("".to_string(), "".to_string()), }; let item_name = self @@ -268,66 +271,37 @@ impl Source for Function { } pub trait SynFnArgHelpers { - fn as_ident_and_type( - &self, - self_type_path: Option<&Path>, - ) -> Result, String>; + fn as_ident_and_type(&self) -> Result, String>; } -fn gen_self_type(self_type_path: &Path, receiver: &syn::Receiver) -> Result, String> { - fn _gen_self_type( - self_type_path: &Path, - receiver: &syn::Receiver, - ) -> Result { - Ok(match receiver.reference { - Some(_) => syn::Type::Reference(match receiver.mutability { - Some(_) => syn::parse_str(&format!("&mut {}", self_type_path))?, - None => syn::parse_str(&format!("&{}", self_type_path))?, - }), - None => syn::Type::Path(syn::parse_str(self_type_path.name())?), - }) +fn gen_self_type(receiver: &syn::Receiver) -> Type { + let self_ty = Type::Path(GenericPath::self_path()); + match receiver.reference { + Some(_) => match receiver.mutability { + Some(_) => Type::Ptr(Box::new(self_ty)), + None => Type::ConstPtr(Box::new(self_ty)), + }, + None => self_ty, } - - Type::load(&Box::new( - _gen_self_type(self_type_path, receiver) - .map_err(|e| format!("Failed to generate self type: {}", e))?, - )) } impl SynFnArgHelpers for syn::FnArg { - fn as_ident_and_type( - &self, - self_type_path: Option<&Path>, - ) -> Result, String> { - match self { - &syn::FnArg::Typed(syn::PatType { + fn as_ident_and_type(&self) -> Result, String> { + match *self { + syn::FnArg::Typed(syn::PatType { ref pat, ref ty, .. }) => match **pat { syn::Pat::Ident(syn::PatIdent { ref ident, .. }) => { - if let Some(mut x) = Type::load(ty)? { - if let Some(self_type_path) = self_type_path { - x.replace_self_with(self_type_path) - } - Ok(Some((ident.to_string(), x))) - } else { - Ok(None) - } + let ty = match Type::load(ty)? { + Some(x) => x, + None => return Ok(None), + }; + Ok(Some((ident.to_string(), ty))) } _ => Err("Parameter has an unsupported type.".to_owned()), }, - &syn::FnArg::Receiver(ref receiver) => { - if let Some(self_type_path) = self_type_path { - if let Some(x) = gen_self_type(self_type_path, receiver)? { - Ok(Some(("self".to_string(), x))) - } else { - Ok(None) - } - } else { - Err( - "Parameter has an unsupported type (Self type found in free function)" - .to_owned(), - ) - } + syn::FnArg::Receiver(ref receiver) => { + Ok(Some(("self".to_string(), gen_self_type(receiver)))) } } } diff --git a/src/bindgen/ir/generic_path.rs b/src/bindgen/ir/generic_path.rs index 871544f..9a89d04 100644 --- a/src/bindgen/ir/generic_path.rs +++ b/src/bindgen/ir/generic_path.rs @@ -72,6 +72,10 @@ impl GenericPath { } } + pub fn self_path() -> Self { + Self::new(Path::new("Self"), vec![]) + } + pub fn replace_self_with(&mut self, self_ty: &Path) { if self.path.replace_self_with(self_ty) { self.export_name = self_ty.name().to_owned(); diff --git a/tests/expectations/both/swift_name.c b/tests/expectations/both/swift_name.c index 4a23851..935167b 100644 --- a/tests/expectations/both/swift_name.c +++ b/tests/expectations/both/swift_name.c @@ -40,6 +40,8 @@ void SelfTypeTestStruct_should_exist_unannotated(SelfTypeTestStruct self) CF_SWI void SelfTypeTestStruct_should_not_exist_box(Box_SelfTypeTestStruct self) CF_SWIFT_NAME(SelfTypeTestStruct.should_not_exist_box(self:)); +Box_SelfTypeTestStruct SelfTypeTestStruct_should_not_exist_return_box(void) CF_SWIFT_NAME(SelfTypeTestStruct.should_not_exist_return_box()); + void free_function_should_exist_annotated_by_name(SelfTypeTestStruct test_struct) CF_SWIFT_NAME(free_function_should_exist_annotated_by_name(test_struct:)); void free_function_should_exist_annotated_mut_by_name(SelfTypeTestStruct test_struct) CF_SWIFT_NAME(free_function_should_exist_annotated_mut_by_name(test_struct:)); diff --git a/tests/expectations/both/swift_name.compat.c b/tests/expectations/both/swift_name.compat.c index d5927ba..4d185f9 100644 --- a/tests/expectations/both/swift_name.compat.c +++ b/tests/expectations/both/swift_name.compat.c @@ -44,6 +44,8 @@ void SelfTypeTestStruct_should_exist_unannotated(SelfTypeTestStruct self) CF_SWI void SelfTypeTestStruct_should_not_exist_box(Box_SelfTypeTestStruct self) CF_SWIFT_NAME(SelfTypeTestStruct.should_not_exist_box(self:)); +Box_SelfTypeTestStruct SelfTypeTestStruct_should_not_exist_return_box(void) CF_SWIFT_NAME(SelfTypeTestStruct.should_not_exist_return_box()); + void free_function_should_exist_annotated_by_name(SelfTypeTestStruct test_struct) CF_SWIFT_NAME(free_function_should_exist_annotated_by_name(test_struct:)); void free_function_should_exist_annotated_mut_by_name(SelfTypeTestStruct test_struct) CF_SWIFT_NAME(free_function_should_exist_annotated_mut_by_name(test_struct:)); diff --git a/tests/expectations/swift_name.c b/tests/expectations/swift_name.c index 4f66ce7..9aafdf7 100644 --- a/tests/expectations/swift_name.c +++ b/tests/expectations/swift_name.c @@ -40,6 +40,8 @@ void SelfTypeTestStruct_should_exist_unannotated(SelfTypeTestStruct self) CF_SWI void SelfTypeTestStruct_should_not_exist_box(Box_SelfTypeTestStruct self) CF_SWIFT_NAME(SelfTypeTestStruct.should_not_exist_box(self:)); +Box_SelfTypeTestStruct SelfTypeTestStruct_should_not_exist_return_box(void) CF_SWIFT_NAME(SelfTypeTestStruct.should_not_exist_return_box()); + void free_function_should_exist_annotated_by_name(SelfTypeTestStruct test_struct) CF_SWIFT_NAME(free_function_should_exist_annotated_by_name(test_struct:)); void free_function_should_exist_annotated_mut_by_name(SelfTypeTestStruct test_struct) CF_SWIFT_NAME(free_function_should_exist_annotated_mut_by_name(test_struct:)); diff --git a/tests/expectations/swift_name.compat.c b/tests/expectations/swift_name.compat.c index 55bcc7b..4d8d244 100644 --- a/tests/expectations/swift_name.compat.c +++ b/tests/expectations/swift_name.compat.c @@ -44,6 +44,8 @@ void SelfTypeTestStruct_should_exist_unannotated(SelfTypeTestStruct self) CF_SWI void SelfTypeTestStruct_should_not_exist_box(Box_SelfTypeTestStruct self) CF_SWIFT_NAME(SelfTypeTestStruct.should_not_exist_box(self:)); +Box_SelfTypeTestStruct SelfTypeTestStruct_should_not_exist_return_box(void) CF_SWIFT_NAME(SelfTypeTestStruct.should_not_exist_return_box()); + void free_function_should_exist_annotated_by_name(SelfTypeTestStruct test_struct) CF_SWIFT_NAME(free_function_should_exist_annotated_by_name(test_struct:)); void free_function_should_exist_annotated_mut_by_name(SelfTypeTestStruct test_struct) CF_SWIFT_NAME(free_function_should_exist_annotated_mut_by_name(test_struct:)); diff --git a/tests/expectations/swift_name.cpp b/tests/expectations/swift_name.cpp index ba2d9eb..4509382 100644 --- a/tests/expectations/swift_name.cpp +++ b/tests/expectations/swift_name.cpp @@ -43,6 +43,8 @@ void SelfTypeTestStruct_should_exist_unannotated(SelfTypeTestStruct self) CF_SWI void SelfTypeTestStruct_should_not_exist_box(Box self) CF_SWIFT_NAME(SelfTypeTestStruct.should_not_exist_box(self:)); +Box SelfTypeTestStruct_should_not_exist_return_box() CF_SWIFT_NAME(SelfTypeTestStruct.should_not_exist_return_box()); + void free_function_should_exist_annotated_by_name(SelfTypeTestStruct test_struct) CF_SWIFT_NAME(free_function_should_exist_annotated_by_name(test_struct:)); void free_function_should_exist_annotated_mut_by_name(SelfTypeTestStruct test_struct) CF_SWIFT_NAME(free_function_should_exist_annotated_mut_by_name(test_struct:)); diff --git a/tests/expectations/tag/swift_name.c b/tests/expectations/tag/swift_name.c index 927d05b..6d56837 100644 --- a/tests/expectations/tag/swift_name.c +++ b/tests/expectations/tag/swift_name.c @@ -40,6 +40,8 @@ void SelfTypeTestStruct_should_exist_unannotated(struct SelfTypeTestStruct self) void SelfTypeTestStruct_should_not_exist_box(struct Box_SelfTypeTestStruct self) CF_SWIFT_NAME(SelfTypeTestStruct.should_not_exist_box(self:)); +struct Box_SelfTypeTestStruct SelfTypeTestStruct_should_not_exist_return_box(void) CF_SWIFT_NAME(SelfTypeTestStruct.should_not_exist_return_box()); + void free_function_should_exist_annotated_by_name(struct SelfTypeTestStruct test_struct) CF_SWIFT_NAME(free_function_should_exist_annotated_by_name(test_struct:)); void free_function_should_exist_annotated_mut_by_name(struct SelfTypeTestStruct test_struct) CF_SWIFT_NAME(free_function_should_exist_annotated_mut_by_name(test_struct:)); diff --git a/tests/expectations/tag/swift_name.compat.c b/tests/expectations/tag/swift_name.compat.c index a4cfcd1..8d8ce85 100644 --- a/tests/expectations/tag/swift_name.compat.c +++ b/tests/expectations/tag/swift_name.compat.c @@ -44,6 +44,8 @@ void SelfTypeTestStruct_should_exist_unannotated(struct SelfTypeTestStruct self) void SelfTypeTestStruct_should_not_exist_box(struct Box_SelfTypeTestStruct self) CF_SWIFT_NAME(SelfTypeTestStruct.should_not_exist_box(self:)); +struct Box_SelfTypeTestStruct SelfTypeTestStruct_should_not_exist_return_box(void) CF_SWIFT_NAME(SelfTypeTestStruct.should_not_exist_return_box()); + void free_function_should_exist_annotated_by_name(struct SelfTypeTestStruct test_struct) CF_SWIFT_NAME(free_function_should_exist_annotated_by_name(test_struct:)); void free_function_should_exist_annotated_mut_by_name(struct SelfTypeTestStruct test_struct) CF_SWIFT_NAME(free_function_should_exist_annotated_mut_by_name(test_struct:)); diff --git a/tests/rust/swift_name.rs b/tests/rust/swift_name.rs index b1af1cc..b110982 100644 --- a/tests/rust/swift_name.rs +++ b/tests/rust/swift_name.rs @@ -27,6 +27,12 @@ impl SelfTypeTestStruct { println!("should_not_exist_box"); } + #[export_name="SelfTypeTestStruct_should_not_exist_return_box"] + #[no_mangle] + pub extern fn should_not_exist_box() -> Box { + println!("should_not_exist_box"); + } + #[export_name="SelfTypeTestStruct_should_exist_annotated_self"] #[no_mangle] pub extern fn should_exist_annotated_self(self: Self) { @@ -120,4 +126,4 @@ impl PointerToOpaque { } } } -} \ No newline at end of file +} diff --git a/tests/rust/swift_name.toml b/tests/rust/swift_name.toml index 2aec3e2..b04dc63 100644 --- a/tests/rust/swift_name.toml +++ b/tests/rust/swift_name.toml @@ -1,4 +1,4 @@ header = "#define CF_SWIFT_NAME(_name) __attribute__((swift_name(#_name)))" [fn] -swift_name_macro = "CF_SWIFT_NAME" \ No newline at end of file +swift_name_macro = "CF_SWIFT_NAME"