Bindgen sometimes drops the type parameter of a struct for fields with multiple type parameters
Header File
Here is an example header, though there are a lot of others which exhibit similar behavior (briefly mentioned in the discussion).
template <typename T, typename K = bool> struct Inner {
T foo;
K bar;
};
template <typename T> struct Outer {
Inner<T> inner;
};
Expected Result
Something along the lines of:
/* automatically generated by rust-bindgen 0.71.1 */
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Inner<T, K = bool> {
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell<K>>,
pub foo: T,
pub bar: K,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Outer<T> {
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
pub inner: Inner<T>,
}
Actual Translation
When running bindgen lib.hpp -o bindings.rs (with lib.hpp containing the cpp code above), bindgen writes the following to bindings.rs:
/* automatically generated by rust-bindgen 0.71.1 */
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Inner<T, K> {
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
pub _phantom_1: ::std::marker::PhantomData<::std::cell::UnsafeCell<K>>,
pub foo: T,
pub bar: K,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Outer {
pub inner: Inner<T, K>,
}
The log is attached here.
Discussion
The problem seems to be in the translating Outer's field. Removing the default type of K (the = bool) and instead instantiating it in the field as Inner<T, bool> inner exhibits the same problem.
Interestingly, changing the field to be Inner<T, T> inner lets the Rust generate fine, creating
// Definition of Inner omitted for brevity
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Outer<T> {
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
pub inner: Inner<T, T>,
}
This leads me to believe the problem isn't to do with the default type parameter, but instead some more general problem when dealing with templates with multiple type parameters.
I've realized I don't think there is currently support for default template arguments. I spent a little trying to implement it and didn't see an easy way to do this. libclang really doesn't exposes much template information.
I didn't see a way to get default template arguments from template declarations, which makes it hard to directly translate default template argument to a default trait parameter.
In the canonical type of the template instantiation, the type of the default template arguments is substituted in, which can be directly put into the trait parameter. This works in simple cases, but breaks on nested template instantiations (I think bindgen it only tries to parses the outer template instantiation?). And I don't see an easy way to fix this.