-
Notifications
You must be signed in to change notification settings - Fork 702
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
Signedness mismatch #1594
Comments
See https://en.cppreference.com/w/cpp/language/integer_literal Specifically the section: "The type of the literal" Bindgen should not attempt to detect signedness. It should rely on the |
Well, in practice most people don't really use the u / U suffix, so we try to pick an appropriate size. In any case you can override this: https://docs.rs/bindgen/0.50.0/bindgen/callbacks/trait.ParseCallbacks.html#method.int_macro |
There are two issues here: size and signedness. Size detection is fine. Signedness is not. Trying to detect sign is wrong. Half the time you will get it wrong and people will have to fix it up in the rust code. The C specification is very clear what sign is assigned to literals. The only difference is that Rust doesn't have implicit conversion but C does. Put simply, you're trying to work around a bug in the source file. This is absolutely a bad default. The default should be to follow the C specification. Anything else is unpredictable. |
That is fair. I'm not opposed to changing behavior here in theory. The macro evaluator (https://github.com/jethrogb/rust-cexpr) doesn't provide any information other than the final |
@emilio I've been doing some thinking about this problem. Obviously, What if instead of making C macro definitions into Rust constants we turned them into Rust macros? We obviously trade some syntactic nicety for ergonomics. Code that uses the macros would get integer literals and Rust would automatically promote the type at the site of use. Thoughts? |
It may be ok to do that, but I'm not 100% sure ergonomics are better... Specially since macros in pre-2018 edition (I think?) are subject to module ordering, so if you have: mod bindings;
mod other; // <- this uses the macros in `bindings` It'd work, while: mod other; // <- this uses the macros in `bindings`
mod bindings; wouldn't. |
@emilio The ergonomics of pre-2018 Rust are really a low priority to me. So much has happened since 2018 in the language that if you're worried about ergonomics you just update to The bigger concern that I see is that bindgen would break its current API. But it solves this problem: #define CONSTANT 1234
void foo(uint64_t value);
void bar(int value); Currently, bindgen doesn't work without casts in either of the above function calls. You end up with the following output: pub const CONSTANT: u32 = 1234;
extern "C" {
pub fn foo(value: u64);
}
extern "C" {
pub fn bar(value: ::std::os::raw::c_int);
} The problem is, of course, that My proposal is to make bindgen emit this instead: #[macro_export]
macro_rules! CONSTANT {
() => { 1234 }
}
extern "C" {
pub fn foo(value: u64);
}
extern "C" {
pub fn bar(value: ::std::os::raw::c_int);
} In this case, both of these calls works as expected: foo(CONSTANT!());
bar(CONSTANT!()); |
I like the idea in general, but I think it's worthwhile keeping the existing behavior around for libraries with a sane API. Maybe we can make this configurable using the ParseCallbacks? |
@jethrogb Configurable seems sane to me. |
Slightly related, size detection also fails: #923 |
The macro idea is discussed at #1594, perhaps the discussion around that should be moved there.
Please see my reply at #2120 (comment) -- the discussion is very similar. |
Input C/C++ Header
Bindgen Invocation
Actual Results
Expected Results
Summary
Bindgen outputs a
u32
instead ofc_int
for defines. This makes them difficult to work with due to signedness mismatch.The text was updated successfully, but these errors were encountered: