Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bindgen generates conflicting definitions when template dependent parameters are used #3160

Open
adetaylor opened this issue Feb 26, 2025 · 0 comments

Comments

@adetaylor
Copy link
Contributor

Reproduction:

Input C++:

namespace a {
typedef int b;
//inline namespace c {}
template <typename> class aa;
inline namespace c {
template <typename d, typename = d, typename = aa<d>> class e;
}
typedef e<char> f;
template <typename g, typename, template <typename> typename> struct h {
    using i = g;
};
template <typename g, template <typename> class k> using j = h<g, void, k>;
template <typename g, template <typename> class k>
using m = typename j<g, k>::i;
template <typename> struct l { typedef b ab; };
template <typename p> class aa {
public:
    typedef p n;
};
struct r {
    template <typename p> using o = typename p::c;
};
template <typename ad> struct u : r {
    typedef typename ad::n n;
    using ae = m<n, o>;
    template <typename af, typename> struct v { using i = typename l<f>::ab; };
    using ab = typename v<ad, ae>::i;
};
} // namespace a
namespace q {
template <typename ad> struct w : a::u<ad> {};
} // namespace q
namespace a {
inline namespace c {
template <typename, typename, typename ad> class e {
    typedef q::w<ad> s;
public:
    typedef typename s::ab ab;
};
} // namespace c
} // namespace a
namespace ag {
namespace ah {
typedef a::f::ab t;
class ai {
public:
    t aj;
};
class al;
namespace am {
class an {
public:
    void ao(ai);
};
} // namespace am
class ap {
public:
    al aq();
};
class ar {
public:
    am::an as;
};
class al {
public:
    ar at;
};
struct au {
    ap av;
};
} // namespace ah
} // namespace ag
namespace operations_research {
class aw {
public:
    ag::ah::au ax;
};
class Solver {
public:
    aw ay;
};
} // namespace operations_research

Command line:
cargo run -- test.hpp --no-layout-tests --enable-cxx-namespaces --allowlist-type operations_research::Solver -- -std=c++14

Resulting Rust:

/* automatically generated by rust-bindgen 0.71.1 */

#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
pub mod root {
    #[allow(unused_imports)]
    use self::super::root;
    pub mod a {
        #[allow(unused_imports)]
        use self::super::super::root;
        pub type b = ::std::os::raw::c_int;
    }
    pub mod ag {
        #[allow(unused_imports)]
        use self::super::super::root;
        pub mod ah {
            #[allow(unused_imports)]
            use self::super::super::super::root;
            pub type t = root::ab;
            #[repr(C)]
            #[derive(Debug, Copy, Clone)]
            pub struct ai {
                pub aj: root::ag::ah::t,
            }
            pub mod am {
                #[allow(unused_imports)]
                use self::super::super::super::super::root;
                #[repr(C)]
                #[derive(Debug, Copy, Clone)]
                pub struct an {
                    pub _address: u8,
                }
                unsafe extern "C" {
                    #[link_name = "\u{1}__ZN2ag2ah2am2an2aoENS0_2aiE"]
                    pub fn an_ao(
                        this: *mut root::ag::ah::am::an,
                        arg1: root::ag::ah::ai,
                    );
                }
                impl an {
                    #[inline]
                    pub unsafe fn ao(&mut self, arg1: root::ag::ah::ai) {
                        an_ao(self, arg1)
                    }
                }
            }
            #[repr(C)]
            #[derive(Debug, Copy, Clone)]
            pub struct ap {
                pub _address: u8,
            }
            unsafe extern "C" {
                #[link_name = "\u{1}__ZN2ag2ah2ap2aqEv"]
                pub fn ap_aq(this: *mut root::ag::ah::ap) -> root::ag::ah::al;
            }
            impl ap {
                #[inline]
                pub unsafe fn aq(&mut self) -> root::ag::ah::al {
                    ap_aq(self)
                }
            }
            #[repr(C)]
            #[derive(Debug, Copy, Clone)]
            pub struct ar {
                pub as_: root::ag::ah::am::an,
            }
            #[repr(C)]
            #[derive(Debug, Copy, Clone)]
            pub struct al {
                pub at: root::ag::ah::ar,
            }
            #[repr(C)]
            #[derive(Debug, Copy, Clone)]
            pub struct au {
                pub av: root::ag::ah::ap,
            }
        }
    }
    pub mod operations_research {
        #[allow(unused_imports)]
        use self::super::super::root;
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct aw {
            pub ax: root::ag::ah::au,
        }
        #[repr(C)]
        #[derive(Debug, Copy, Clone)]
        pub struct Solver {
            pub ay: root::operations_research::aw,
        }
    }
    pub type ab = root::a::b;
    pub type ab = root::ab;
    pub type ab = root::i;
    pub type i = root::ab;
}

Note that near the end there are three defintions of ab, so the resulting Rust doesn't build.

Bindgen version 20aa65a (today's HEAD).

As you can see this code was already minimized a while ago for google/autocxx#264, though that was a separate issue so it's quite possible it can be reduced more to get a more minimal test case for bindgen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant