function: Add support for wildcards in arguments.

We don't support unnamed arguments, and we give a terrible error
("Parameter has an unsupported type.") when you use them.

They're very simple to implement so we should just do it.
This commit is contained in:
Emilio Cobos Álvarez 2020-07-25 12:24:18 +02:00
parent 8eeb0bb6ec
commit 5eae0bc07b
18 changed files with 86 additions and 35 deletions

@ -63,7 +63,7 @@ impl CDecl {
let args = f
.args
.iter()
.map(|&(ref arg_name, ref arg_ty)| (Some(arg_name.clone()), CDecl::from_type(arg_ty)))
.map(|&(ref arg_name, ref arg_ty)| (arg_name.clone(), CDecl::from_type(arg_ty)))
.collect();
self.declarators
.push(CDeclarator::Func(args, layout_vertical));

@ -28,7 +28,7 @@ pub struct Function {
/// If the function is a method, this will contain the path of the type in the impl block
pub self_type_path: Option<Path>,
pub ret: Type,
pub args: Vec<(String, Type)>,
pub args: Vec<(Option<String>, Type)>,
pub extern_decl: bool,
pub cfg: Option<Cfg>,
pub annotations: AnnotationSet,
@ -80,14 +80,14 @@ impl Function {
})
}
pub fn swift_name(&self) -> String {
pub fn swift_name(&self) -> Option<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) = 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();
return Some(self.path.to_string());
}
(format!("{}.", type_name), type_name)
}
@ -101,13 +101,13 @@ impl Function {
.trim_start_matches('_');
let item_args = {
let mut items = vec![];
let mut items = Vec::with_capacity(self.args.len());
for (arg, _) in self.args.iter() {
items.push(format!("{}:", arg.as_str()));
items.push(format!("{}:", arg.as_ref()?.as_str()));
}
items.join("")
};
format!("{}{}({})", type_prefix, item_name, item_args)
Some(format!("{}{}({})", type_prefix, item_name, item_args))
}
pub fn path(&self) -> &Path {
@ -164,16 +164,24 @@ impl Function {
];
if let Some(r) = find_first_some(&rules) {
self.args = self
.args
.iter()
.map(|x| (r.apply(&x.0, IdentifierType::FunctionArg), x.1.clone()))
let args = std::mem::replace(&mut self.args, vec![]);
self.args = args
.into_iter()
.map(|(name, ty)| {
let name = match name {
Some(n) => n,
None => return (name, ty),
};
(Some(r.apply(&name, IdentifierType::FunctionArg)), ty)
})
.collect()
}
// Escape C/C++ reserved keywords used in argument names
for args in &mut self.args {
reserved::escape(&mut args.0);
for arg in &mut self.args {
if let Some(ref mut name) = arg.0 {
reserved::escape(name);
}
}
}
}
@ -210,7 +218,9 @@ impl Source for Function {
}
if let Some(ref swift_name_macro) = config.function.swift_name_macro {
write!(out, " {}({})", swift_name_macro, func.swift_name());
if let Some(swift_name) = func.swift_name() {
write!(out, " {}({})", swift_name_macro, swift_name);
}
}
if func.never_return {
@ -257,7 +267,9 @@ impl Source for Function {
}
if let Some(ref swift_name_macro) = config.function.swift_name_macro {
write!(out, " {}({})", swift_name_macro, func.swift_name());
if let Some(swift_name) = func.swift_name() {
write!(out, " {}({})", swift_name_macro, swift_name);
}
}
if func.never_return {
@ -284,7 +296,7 @@ impl Source for Function {
}
pub trait SynFnArgHelpers {
fn as_ident_and_type(&self) -> Result<Option<(String, Type)>, String>;
fn as_ident_and_type(&self) -> Result<Option<(Option<String>, Type)>, String>;
}
fn gen_self_type(receiver: &syn::Receiver) -> Type {
@ -299,29 +311,32 @@ fn gen_self_type(receiver: &syn::Receiver) -> Type {
}
impl SynFnArgHelpers for syn::FnArg {
fn as_ident_and_type(&self) -> Result<Option<(String, Type)>, String> {
fn as_ident_and_type(&self) -> Result<Option<(Option<String>, Type)>, String> {
match *self {
syn::FnArg::Typed(syn::PatType {
ref pat, ref ty, ..
}) => match **pat {
syn::Pat::Ident(syn::PatIdent { ref ident, .. }) => {
let ty = match Type::load(ty)? {
Some(x) => {
if let Type::Array(_, _) = x {
return Err(
"Array as function arguments are not supported".to_owned()
);
}
x
}
None => return Ok(None),
};
Ok(Some((ident.to_string(), ty)))
}) => {
let name = match **pat {
syn::Pat::Wild(..) => None,
syn::Pat::Ident(syn::PatIdent { ref ident, .. }) => Some(ident.to_string()),
_ => {
return Err(format!(
"Parameter has an unsupported argument name: {:?}",
pat
))
}
};
let ty = match Type::load(ty)? {
Some(x) => x,
None => return Ok(None),
};
if let Type::Array(..) = ty {
return Err("Array as function arguments are not supported".to_owned());
}
_ => Err("Parameter has an unsupported type.".to_owned()),
},
Ok(Some((name, ty)))
}
syn::FnArg::Receiver(ref receiver) => {
Ok(Some(("self".to_string(), gen_self_type(receiver))))
Ok(Some((Some("self".to_string()), gen_self_type(receiver))))
}
}
}

@ -6,3 +6,5 @@
void pointer_test(const uint64_t *a);
void print_from_rust(void);
void unnamed(const uint64_t*);

@ -11,6 +11,8 @@ void pointer_test(const uint64_t *a);
void print_from_rust(void);
void unnamed(const uint64_t*);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

@ -53,3 +53,5 @@ void free_function_should_exist_ref_mut(SelfTypeTestStruct *test_struct) CF_SWIF
void free_function_should_not_exist_box(Box_SelfTypeTestStruct boxed) CF_SWIFT_NAME(free_function_should_not_exist_box(boxed:));
void rust_print_hello_world(void) CF_SWIFT_NAME(rust_print_hello_world());
void unnamed_argument(SelfTypeTestStruct*);

@ -58,6 +58,8 @@ void free_function_should_not_exist_box(Box_SelfTypeTestStruct boxed) CF_SWIFT_N
void rust_print_hello_world(void) CF_SWIFT_NAME(rust_print_hello_world());
void unnamed_argument(SelfTypeTestStruct*);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

@ -6,3 +6,5 @@
void pointer_test(const uint64_t *a);
void print_from_rust(void);
void unnamed(const uint64_t*);

@ -11,6 +11,8 @@ void pointer_test(const uint64_t *a);
void print_from_rust(void);
void unnamed(const uint64_t*);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

@ -9,4 +9,6 @@ void pointer_test(const uint64_t *a);
void print_from_rust();
void unnamed(const uint64_t*);
} // extern "C"

@ -53,3 +53,5 @@ void free_function_should_exist_ref_mut(SelfTypeTestStruct *test_struct) CF_SWIF
void free_function_should_not_exist_box(Box_SelfTypeTestStruct boxed) CF_SWIFT_NAME(free_function_should_not_exist_box(boxed:));
void rust_print_hello_world(void) CF_SWIFT_NAME(rust_print_hello_world());
void unnamed_argument(SelfTypeTestStruct*);

@ -58,6 +58,8 @@ void free_function_should_not_exist_box(Box_SelfTypeTestStruct boxed) CF_SWIFT_N
void rust_print_hello_world(void) CF_SWIFT_NAME(rust_print_hello_world());
void unnamed_argument(SelfTypeTestStruct*);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

@ -57,4 +57,6 @@ void free_function_should_not_exist_box(Box<SelfTypeTestStruct> boxed) CF_SWIFT_
void rust_print_hello_world() CF_SWIFT_NAME(rust_print_hello_world());
void unnamed_argument(SelfTypeTestStruct*);
} // extern "C"

@ -6,3 +6,5 @@
void pointer_test(const uint64_t *a);
void print_from_rust(void);
void unnamed(const uint64_t*);

@ -11,6 +11,8 @@ void pointer_test(const uint64_t *a);
void print_from_rust(void);
void unnamed(const uint64_t*);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

@ -53,3 +53,5 @@ void free_function_should_exist_ref_mut(struct SelfTypeTestStruct *test_struct)
void free_function_should_not_exist_box(struct Box_SelfTypeTestStruct boxed) CF_SWIFT_NAME(free_function_should_not_exist_box(boxed:));
void rust_print_hello_world(void) CF_SWIFT_NAME(rust_print_hello_world());
void unnamed_argument(struct SelfTypeTestStruct*);

@ -58,6 +58,8 @@ void free_function_should_not_exist_box(struct Box_SelfTypeTestStruct boxed) CF_
void rust_print_hello_world(void) CF_SWIFT_NAME(rust_print_hello_world());
void unnamed_argument(struct SelfTypeTestStruct*);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

@ -8,13 +8,16 @@ pub unsafe extern fn array_test(a: [u64; 3]) {
array_print(&a);
}
#[no_mangle]
pub unsafe extern fn unnamed(_: *const u64) {
}
#[no_mangle]
pub unsafe extern fn pointer_test(a: *const u64) {
let a = std::slice::from_raw_parts(a, 3);
array_print(a);
}
#[no_mangle]
pub unsafe extern fn print_from_rust() {
let a = [0, 1, 2];

@ -85,6 +85,11 @@ pub extern fn free_function_should_exist_ref_mut(test_struct: &mut SelfTypeTestS
println!("free_function_should_exist_ref_mut");
}
#[no_mangle]
pub extern fn unnamed_argument(_: &mut SelfTypeTestStruct) {
println!("unnamed_argument");
}
#[no_mangle]
#[allow(unused_variables)]
pub extern fn free_function_should_not_exist_box(boxed: Box<SelfTypeTestStruct>) {