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

error[E0428]: the name sentry is defined multiple times #1048

Closed
ctaggart opened this issue Sep 29, 2017 · 3 comments
Closed

error[E0428]: the name sentry is defined multiple times #1048

ctaggart opened this issue Sep 29, 2017 · 3 comments

Comments

@ctaggart
Copy link

For Octave bindings, I need to interop with C++ std::string ctaggart/octh#28. Any recommendations of how to do this are appreciated. This is the first issue I'm up against that I'm not sure how to solve. ctaggart/octh#29

Input C/C++ Header

namespace a {
template <typename, typename> class b;
template <typename, typename = int> class c;
class B {
  typedef b<int, int> d;
};
class e {
  B g;
};
template <typename, typename> class c : e { class sentry; };
template <typename f, typename h> class c<f, h>::sentry {};
template <typename, typename> class b { class sentry; };
template <typename f, typename h> class b<f, h>::sentry {};
}
class octave_diary_stream : a::c<char> {};

Bindgen Invocation

#!/usr/bin/env bash
set -eu
clang-3.9 --std=c++11 -c __bindgen.ii

~/rust-bindgen/target/release/bindgen \
    --output __bindgen.rs \
    --enable-cxx-namespaces \
    --whitelist-type octave.* \
    --whitelist-function octave.* \
    --use-core \
    --raw-line "extern crate core;" \
    __bindgen.ii \
    -- -v -x c++ -std=c++11 \
    2>/dev/null

rustc __bindgen.rs \
    2>&1 \
    | grep 'error\[E0428\]: the name `sentry` is defined multiple times'

# time creduce ./bindgen-bug.sh __bindgen.ii

Actual Results

error[E0428]: the name `sentry` is defined multiple times

Expected Results

It compiles.

@fitzgen
Copy link
Member

fitzgen commented Sep 29, 2017

Thanks for the bug report @ctaggart !

Here is a slightly cleaned up / annotated test case:

// bindgen-flags: --enable-cxx-namespaces -- -std=c++11

// First::sentry and Second::sentry should be emitted as `First_sentry` and
// `Second_sentry`, but instead are both being named just `sentry` which leads
// to compilation errors.
//
// Note: if there is no namespace, then we don't run into problems. Similarly,
// making the `sentry` definitions inline in `First` and `Second`, rather than
// declared inline with out of line definitions, makes the problem go away as
// well.

namespace whatever {
    template <typename, typename>
    class First {
        // Declaration of First::sentry
        class sentry;
    };

    // Definition of First::sentry
    template <typename f, typename h>
    class First<f, h>::sentry {};

    template <typename, typename>
    class Second {
        // Declaration of Second::sentry
        class sentry;
    };

    // Definition of Second::sentry
    template <typename f, typename h>
    class Second<f, h>::sentry {};
}

And here are the bindings that get generated:

/* automatically generated by rust-bindgen */


#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]


#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
pub mod root {
    #[allow(unused_imports)]
    use self::super::root;
    pub mod whatever {
        #[allow(unused_imports)]
        use self::super::super::root;
        #[repr(C)]
        #[derive(Debug, Default, Copy, Clone)]
        pub struct First {
            pub _address: u8,
        }
        #[repr(C)]
        #[derive(Debug, Default, Copy)]
        pub struct sentry {
            pub _address: u8,
        }
        impl Clone for sentry {
            fn clone(&self) -> Self {
                *self
            }
        }
        #[repr(C)]
        #[derive(Debug, Default, Copy, Clone)]
        pub struct Second {
            pub _address: u8,
        }
        #[repr(C)]
        #[derive(Debug, Default, Copy)]
        pub struct sentry {
            pub _address: u8,
        }
        impl Clone for sentry {
            fn clone(&self) -> Self {
                *self
            }
        }
    }
}

It seems like we're parsing the inner sentry classes incorrectly, and they don't end up with First or Second as their parents.

Here's the IR:

ir

fitzgen added a commit to fitzgen/rust-bindgen that referenced this issue Sep 29, 2017
When choosing a parent ID for a type that we are parsing, prefer known semantic
parents over the provided parent ID. It seems like we shouldn't even be passing
explicit parent IDs around (they're often buggy), and instead should expand the
`known_semantic_parent` infrastructure, but I'll leave that to some future work.

Fixes rust-lang#1048
@fitzgen
Copy link
Member

fitzgen commented Sep 29, 2017

I have a fix over in #1049

@ctaggart
Copy link
Author

ctaggart commented Oct 1, 2017

I tried the fix out and it worked for ctaggart/octh#29.

bors-servo pushed a commit that referenced this issue Oct 1, 2017
…rations, r=emilio

ir: Prefer using known semantic parents

When choosing a parent ID for a type that we are parsing, prefer known semantic parents over the provided parent ID. It seems like we shouldn't even be passing explicit parent IDs around (they're often buggy), and instead should expand the `known_semantic_parent` infrastructure, but I'll leave that to some future work.

Fixes #1048

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

No branches or pull requests

2 participants