rust-lang / rust-lang/rust-bindgen

Generic namespaced pointers are dropped

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

Nobody has claimed this yet.

Dominant language
Rust
Stars
5.3k
Forks
829
Avg merge
1d 1h
Merged PRs (30d)
15

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

Contributor guide

Open the contributing guide

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.

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.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.