Skip to content

Commit cc78b6f

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 6de2d3d commit cc78b6f

14 files changed

+81
-31
lines changed

Diff for: asd.fish

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
for name in (rg -lF addr_of! tests/expectations | sd '.*/(.*).rs' '$1')
2+
set path (fd --glob "$name.*" tests/headers)
3+
if test -n "$path"
4+
5+
set flags (rg -F "// bindgen-flags" $path)
6+
if test -n "$flags"
7+
set minor (rg ".*\-\-rust\-target[ =]1.(\d+).*" $path -r '$1')
8+
if test -n "$minor"
9+
if test $minor -gt 47
10+
echo $path needs to change the version from 1.$minor to 1.47
11+
sd -s "1.$minor" "1.47" $path
12+
else
13+
echo $path uses version 1.$minor and that is fine
14+
end
15+
else
16+
echo $path does not have the `--rust-target` flag
17+
sd "// bindgen-flags: (.*)" '// bindgen-flags: --rust-target 1.47 $1' $path
18+
end
19+
else
20+
echo $path does not have the flags at all
21+
set contents (echo -e "// bindgen-flags: --rust-target 1.47\n"; cat $path)
22+
rm $path
23+
touch $path
24+
for line in $contents
25+
echo $line >> $path
26+
end
27+
end
28+
else
29+
echo $name headers not found
30+
end
31+
end

Diff for: src/codegen/mod.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -836,9 +836,34 @@ 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
846+
.kind()
847+
.expect_type()
848+
.layout(ctx)
849+
.expect("No layout?");
850+
assert_eq!(
851+
layout.size,
852+
ctx.target_pointer_size(),
853+
"Target platform requires `--no-size_t-is-usize`. The size of `{}` ({}) does not match the target pointer size ({})",
854+
spelling,
855+
layout.size,
856+
ctx.target_pointer_size(),
857+
);
858+
assert_eq!(
859+
layout.align,
860+
ctx.target_pointer_size(),
861+
"Target platform requires `--no-size_t-is-usize`. The alignment of `{}` ({}) does not match the target pointer size ({})",
862+
spelling,
863+
layout.align,
864+
ctx.target_pointer_size(),
865+
);
866+
}
842867
return;
843868
}
844869

Diff for: src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -564,8 +564,8 @@ impl Builder {
564564
output_vector.push("--no-record-matches".into());
565565
}
566566

567-
if self.options.size_t_is_usize {
568-
output_vector.push("--size_t-is-usize".into());
567+
if !self.options.size_t_is_usize {
568+
output_vector.push("--no-size_t-is-usize".into());
569569
}
570570

571571
if !self.options.rustfmt_bindings {
@@ -2253,7 +2253,7 @@ impl Default for BindgenOptions {
22532253
time_phases: false,
22542254
record_matches: true,
22552255
rustfmt_bindings: true,
2256-
size_t_is_usize: false,
2256+
size_t_is_usize: true,
22572257
rustfmt_configuration_file: None,
22582258
no_partialeq_types: Default::default(),
22592259
no_copy_types: Default::default(),

Diff for: src/options.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,12 @@ where
465465
),
466466
Arg::new("size_t-is-usize")
467467
.long("size_t-is-usize")
468-
.help("Translate size_t to usize."),
468+
.help("Ignored - this is enabled by default.")
469+
.hidden(true),
470+
Arg::with_name("no-size_t-is-usize")
471+
.long("no-size_t-is-usize")
472+
.help("Do not bind size_t as usize (useful on platforms \
473+
where those types are incompatible)."),
469474
Arg::new("no-rustfmt-bindings")
470475
.long("no-rustfmt-bindings")
471476
.help("Do not format the generated bindings with rustfmt."),
@@ -975,8 +980,8 @@ where
975980
builder = builder.record_matches(false);
976981
}
977982

978-
if matches.is_present("size_t-is-usize") {
979-
builder = builder.size_t_is_usize(true);
983+
if matches.is_present("no-size_t-is-usize") {
984+
builder = builder.size_t_is_usize(false);
980985
}
981986

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

Diff for: 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.

Diff for: tests/expectations/tests/blocks.rs

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

Diff for: 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.

Diff for: 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.

Diff for: 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.

Diff for: 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.

Diff for: 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.

Diff for: 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.

Diff for: tests/expectations/tests/nsBaseHashtable.rs

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

Diff for: 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)