[bindings] Avoid guessing whether resolved type is a ref in blocks
authorMatt Corallo <git@bluematt.me>
Thu, 1 Oct 2020 22:42:33 +0000 (18:42 -0400)
committerMatt Corallo <git@bluematt.me>
Wed, 21 Oct 2020 18:50:22 +0000 (14:50 -0400)
In some cases, things which are a Rust Reference (ie slices), we
may still want to map them as a non-reference and need to put a
"mut " in front of the variable name in a function decl. This
worked fine by just checking for the slice case, except that we
are about to add support for type aliases, which no longer match
the naive case.

Instead, we can just have the types module print out the C type and
check if it begins with a '&' to figure out if it is a reference.

c-bindings-gen/src/blocks.rs

index 9e255a1521e928a3500b31f13c9283b13be0a5d7..076f9373116985d638bcae7411b637b99be11f1c 100644 (file)
@@ -113,20 +113,15 @@ pub fn write_method_params<W: std::io::Write>(w: &mut W, sig: &syn::Signature, a
                        syn::FnArg::Typed(arg) => {
                                if types.skip_arg(&*arg.ty, generics) { continue; }
                                if !arg.attrs.is_empty() { unimplemented!(); }
-                               let mut is_ref = if let syn::Type::Reference(_) = *arg.ty { true } else { false };
-                               if let syn::Type::Reference(syn::TypeReference { ref elem, .. }) = *arg.ty {
-                                       if let syn::Type::Slice(_) = &**elem {
-                                               // Slices are mapped to non-ref Vec types, so we want them to be mut
-                                               // letting us drain(..) the underlying Vec.
-                                               is_ref = false;
-                                       }
-                               }
+                               // First get the c type so that we can check if it ends up being a reference:
+                               let mut c_type = Vec::new();
+                               types.write_c_type(&mut c_type, &*arg.ty, generics, false);
                                match &*arg.pat {
                                        syn::Pat::Ident(ident) => {
                                                if !ident.attrs.is_empty() || ident.subpat.is_some() {
                                                        unimplemented!();
                                                }
-                                               write!(w, "{}{}{}: ", if first_arg { "" } else { ", " }, if is_ref || !fn_decl { "" } else { "mut " }, ident.ident).unwrap();
+                                               write!(w, "{}{}{}: ", if first_arg { "" } else { ", " }, if !fn_decl || c_type[0] == '&' as u8 || c_type[0] == '*' as u8 { "" } else { "mut " }, ident.ident).unwrap();
                                                first_arg = false;
                                        },
                                        syn::Pat::Wild(wild) => {
@@ -136,7 +131,7 @@ pub fn write_method_params<W: std::io::Write>(w: &mut W, sig: &syn::Signature, a
                                        },
                                        _ => unimplemented!(),
                                }
-                               types.write_c_type(w, &*arg.ty, generics, false);
+                               w.write(&c_type).unwrap();
                        }
                }
        }