Skip to content

Commit 28364c1

Browse files
geofftpvdrz
authored andcommitted
Map size_t to usize by default and check compatibility (fixes #1901, #1903)
This addresses the underlying issue identified in #1671, that size_t (integer that can hold any object size) isn't guaranteed to match usize, which is defined more like uintptr_t (integer that can hold any pointer). However, on almost all platforms, this is true, and in fact Rust already uses usize extensively in contexts where size_t would be more appropriate, such as slice indexing. So, it's better for ergonomics when interfacing with C code to map the C size_t type to usize. (See also discussion in rust-lang/rust#65473 about how usize really should be defined as size_t, not uintptr_t.) The previous fix for #1671 removed the special case for size_t and defaulted to binding it as a normal typedef. This change effectively reverts that and goes back to mapping size_t to usize (and ssize_t to isize), but also ensures that if size_t is emitted, the typedef'd type of size_t in fact is compatible with usize (defined by checking that the size and alignment match the target pointer width). For (hypothetical) platforms where this is not true, or for compatibility with the default behavior of bindgen between 0.53 and this commit, onwards, you can disable this mapping with --no-size_t-is-usize.
1 parent 0d805d7 commit 28364c1

13 files changed

+32
-31
lines changed

src/codegen/mod.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -836,9 +836,16 @@ impl CodeGenerator for Type {
836836
}
837837

838838
// If this is a known named type, disallow generating anything
839-
// for it too.
839+
// for it too. If size_t -> usize conversions are enabled, we
840+
// need to check that these conversions are permissible, but
841+
// nothing needs to be generated, still.
840842
let spelling = self.name().expect("Unnamed alias?");
841843
if utils::type_from_named(ctx, spelling).is_some() {
844+
if let "size_t" | "ssize_t" = spelling {
845+
let layout = inner_item.kind().expect_type().layout(ctx).expect("No layout?");
846+
assert!(layout.size == ctx.target_pointer_size() && layout.align == ctx.target_pointer_size(),
847+
"Target platform requires --no-size_t-is-usize");
848+
}
842849
return;
843850
}
844851

src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -550,8 +550,8 @@ impl Builder {
550550
output_vector.push("--no-record-matches".into());
551551
}
552552

553-
if self.options.size_t_is_usize {
554-
output_vector.push("--size_t-is-usize".into());
553+
if !self.options.size_t_is_usize {
554+
output_vector.push("--no-size_t-is-usize".into());
555555
}
556556

557557
if !self.options.rustfmt_bindings {
@@ -2183,7 +2183,7 @@ impl Default for BindgenOptions {
21832183
time_phases: false,
21842184
record_matches: true,
21852185
rustfmt_bindings: true,
2186-
size_t_is_usize: false,
2186+
size_t_is_usize: true,
21872187
rustfmt_configuration_file: None,
21882188
no_partialeq_types: Default::default(),
21892189
no_copy_types: Default::default(),

src/options.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,12 @@ where
429429
),
430430
Arg::new("size_t-is-usize")
431431
.long("size_t-is-usize")
432-
.help("Translate size_t to usize."),
432+
.help("Ignored - this is enabled by default.")
433+
.hidden(true),
434+
Arg::with_name("no-size_t-is-usize")
435+
.long("no-size_t-is-usize")
436+
.help("Do not bind size_t as usize (useful on platforms \
437+
where those types are incompatible)."),
433438
Arg::new("no-rustfmt-bindings")
434439
.long("no-rustfmt-bindings")
435440
.help("Do not format the generated bindings with rustfmt."),
@@ -915,8 +920,8 @@ where
915920
builder = builder.record_matches(false);
916921
}
917922

918-
if matches.is_present("size_t-is-usize") {
919-
builder = builder.size_t_is_usize(true);
923+
if matches.is_present("no-size_t-is-usize") {
924+
builder = builder.size_t_is_usize(false);
920925
}
921926

922927
let no_rustfmt_bindings = matches.is_present("no-rustfmt-bindings");

tests/expectations/tests/blocks-signature.rs

+3-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/expectations/tests/blocks.rs

-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/expectations/tests/issue-1498.rs

+1-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/expectations/tests/jsval_layout_opaque.rs

+1-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/expectations/tests/jsval_layout_opaque_1_0.rs

+1-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/expectations/tests/layout_array.rs

+1-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/expectations/tests/msvc-no-usr.rs

+1-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/expectations/tests/size_t_is_usize.rs renamed to tests/expectations/tests/no_size_t_is_usize.rs

+4-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/expectations/tests/nsBaseHashtable.rs

-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/headers/size_t_is_usize.h renamed to tests/headers/no_size_t_is_usize.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --size_t-is-usize
1+
// bindgen-flags: --no-size_t-is-usize
22

33
typedef unsigned long size_t;
44
typedef long ssize_t;

0 commit comments

Comments
 (0)