Generic namespaced pointers are dropped

Open
#3,479 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
62/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
cpp, rust

Research direction

Use the minimal example in src/bindgen_entry.h and run the shown bindgen command with C++ parsing enabled. Compare the namespaced pointer alias output with the unnamespaced case, then trace the handling of generic parameters and namespaced template specializations. Done means f is generated with Quux<baz_Foo> and the behavior has a regression test.

Written by the indexing model from the issue text.

Description

In my test program, generic parameters are dropped, leading to incorrect code.

with src/bindgen_entry.h:

namespace baz {
class Foo;
}

template <typename T>
using Quux=T*;

void f(Quux<baz::Foo> bar);
$ bindgen src/bindgen_entry.h -- -x c++ 
/* automatically generated by rust-bindgen 0.73.2 */

#[repr(C)]
#[derive(Debug)]
pub struct baz_Foo {
    _unused: [u8; 0],
}
pub type Quux<T> = *mut T;
unsafe extern "C" {
    #[link_name = "\u{1}__Z1fPN3baz3FooE"]
    pub fn f(bar: Quux);
}

I would expect to see pub fn f(bar: Quux<baz_Foo>).

If Quux is defined without the pointer, Quux gets ignored entirely (which is likely correct, or at least will compile):

namespace baz {
class Foo;
}

template <typename T>
using Quux=T;

void f(Quux<baz::Foo> bar);
$ bindgen src/bindgen_entry.h -- -x c++ 
/* automatically generated by rust-bindgen 0.73.2 */

#[repr(C)]
#[derive(Debug)]
pub struct baz_Foo {
    _unused: [u8; 0],
}
pub type Quux<T> = T;
unsafe extern "C" {
    #[link_name = "\u{1}__Z1fN3baz3FooE"]
    pub fn f(bar: baz_Foo);
}

Note, though, that if I drop the namespace in the C++ code, it works as expected, even with the pointer:

class Foo;

template <typename T>
using Quux=T*;

void f(Quux<Foo> bar);
$ bindgen src/bindgen_entry.h -- -x c++ 
/* automatically generated by rust-bindgen 0.73.2 */

#[repr(C)]
#[derive(Debug)]
pub struct Foo {
    _unused: [u8; 0],
}
pub type Quux<T> = *mut T;
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
    ["Size of template specialization: Quux_open0_Foo_close0"]
        [::std::mem::size_of::<Quux<Foo>>() - 8usize];
    ["Align of template specialization: Quux_open0_Foo_close0"]
        [::std::mem::align_of::<Quux<Foo>>() - 8usize];
};
unsafe extern "C" {
    #[link_name = "\u{1}__Z1fP3Foo"]
    pub fn f(bar: Quux<Foo>);
}

None of --enable-cxx-namespaces, --disable-name-namespacing, nor --conservative-inline-namespaces correct this behavior.

I believe this is related to, but not quite the same as, https://github.com/rust-lang/rust-bindgen/issues/3373

Dominant language
Rust
Stars
5.3k
Forks
846
Avg merge
2d 6h
Merged PRs (30d)
11

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from rust-lang/rust-bindgen

All issues in rust-lang/rust-bindgen

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.