Skip to content

Commit 9b227c8

Browse files
author
bors-servo
authored
Auto merge of #110 - heycam:stable-gen-names, r=emilio
Give vtables and anonymous items more stable generated names (fixes #60) r? @emilio This works pretty well. There are two remaining things in stylo's structs files that have identifiers that look like they won't be that stable: the anonymous enum for the NODE_* flags at the top level, and the `typedef union { ... } nsStyleUnion`. There are various anonymous enums and other things at the top level in system headers that cause these identifiers to have generated IDs in them higher than 1 and 2. Probably for anonymous enums we could just avoid generating a rust enum altogether, since having the static consts should be sufficient. I tried to mess with the codegen to automatically treat `typedef union { ... } nsStyleUnion` like `union nsStyleUnion { ... }` but it seems the way clang exposes the typedef and union are as two adjacent cursors rather than a parent-child relationship, so it's not so easy.
2 parents f499192 + 55e7d05 commit 9b227c8

35 files changed

+282
-288
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ quasi_codegen = "0.20"
2323

2424
[dependencies]
2525
clang-sys = "0.8.0"
26+
lazy_static = "0.1.*"
2627
libc = "0.2"
2728
log = "0.3"
2829
env_logger = "0.3"

src/codegen/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,8 +445,8 @@ impl<'a> CodeGenerator for Vtable<'a> {
445445
}
446446

447447
impl<'a> ItemCanonicalName for Vtable<'a> {
448-
fn canonical_name(&self, _ctx: &BindgenContext) -> String {
449-
format!("bindgen_vtable_{}", self.item_id)
448+
fn canonical_name(&self, ctx: &BindgenContext) -> String {
449+
format!("{}__bindgen_vtable", self.item_id.canonical_name(ctx))
450450
}
451451
}
452452

src/ir/item.rs

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
use regex::Regex;
12
use super::context::BindgenContext;
23
use super::item_kind::ItemKind;
34
use super::ty::{Type, TypeKind};
45
use super::function::Function;
56
use super::module::Module;
67
use super::annotations::Annotations;
7-
use std::fmt;
8+
use std::cell::Cell;
89
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
910
use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
1011
use clang;
@@ -46,13 +47,6 @@ pub trait ItemCanonicalPath {
4647
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
4748
pub struct ItemId(usize);
4849

49-
impl fmt::Display for ItemId {
50-
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
51-
try!(write!(fmt, "_bindgen_id_"));
52-
self.0.fmt(fmt)
53-
}
54-
}
55-
5650
pub static NEXT_ITEM_ID: AtomicUsize = ATOMIC_USIZE_INIT;
5751

5852
impl ItemId {
@@ -96,6 +90,11 @@ impl ItemCanonicalPath for ItemId {
9690
pub struct Item {
9791
/// This item's id.
9892
id: ItemId,
93+
/// The item's local id, unique only amongst its siblings. Only used
94+
/// for anonymous items. Lazily initialized in local_id().
95+
local_id: Cell<Option<usize>>,
96+
/// The next local id to use for a child.
97+
next_child_local_id: Cell<usize>,
9998
/// A doc comment over the item, if any.
10099
comment: Option<String>,
101100
/// Annotations extracted from the doc comment, or the default ones
@@ -120,6 +119,8 @@ impl Item {
120119
debug_assert!(id != parent_id || kind.is_module());
121120
Item {
122121
id: id,
122+
local_id: Cell::new(None),
123+
next_child_local_id: Cell::new(1),
123124
parent_id: parent_id,
124125
comment: comment,
125126
annotations: annotations.unwrap_or_default(),
@@ -147,6 +148,16 @@ impl Item {
147148
&mut self.kind
148149
}
149150

151+
pub fn local_id(&self, ctx: &BindgenContext) -> usize {
152+
if self.local_id.get().is_none() {
153+
let parent = ctx.resolve_item(self.parent_id);
154+
let local_id = parent.next_child_local_id.get();
155+
parent.next_child_local_id.set(local_id + 1);
156+
self.local_id.set(Some(local_id));
157+
}
158+
self.local_id.get().unwrap()
159+
}
160+
150161
/// Returns whether this item is a top-level item, from the point of view of
151162
/// bindgen.
152163
///
@@ -435,7 +446,6 @@ impl Item {
435446
ty.name()
436447
}
437448
}.map(ToOwned::to_owned)
438-
.unwrap_or_else(|| format!("_bindgen_ty{}", self.id()))
439449
}
440450
ItemKind::Function(ref fun) => {
441451
let mut base = fun.name().to_owned();
@@ -464,30 +474,68 @@ impl Item {
464474
}
465475
}
466476
}
467-
base
477+
Some(base)
468478
}
469479
ItemKind::Var(ref var) => {
470-
var.name().to_owned()
480+
Some(var.name().to_owned())
471481
}
472482
ItemKind::Module(ref module) => {
473483
module.name().map(ToOwned::to_owned)
474-
.unwrap_or_else(|| format!("_bindgen_mod{}", self.id()))
475484
}
476485
};
477486

478487
let parent = ctx.resolve_item(self.parent_id());
479488
let parent_is_namespace = parent.is_module();
489+
480490
if self.is_toplevel(ctx) || (parent_is_namespace && count_namespaces) {
491+
let base_name = self.make_exposed_name(None, base_name, ctx);
481492
return ctx.rust_mangle(&base_name).into_owned();
482493
}
483494

484495
// TODO: allow modification of the mangling functions, maybe even per
485496
// item type?
486-
let parent = parent.canonical_name(ctx);
487-
if parent.is_empty() {
488-
base_name.to_owned()
489-
} else {
490-
format!("{}_{}", parent, base_name)
497+
let parent_name = parent.canonical_name(ctx);
498+
self.make_exposed_name(Some(parent_name), base_name, ctx)
499+
}
500+
501+
fn exposed_id(&self, ctx: &BindgenContext) -> String {
502+
// Only use local ids for enums, classes, structs and union types. All
503+
// other items use their global id.
504+
let ty_kind = self.kind().as_type().map(|t| t.kind());
505+
if let Some(ty_kind) = ty_kind {
506+
match *ty_kind {
507+
TypeKind::Comp(..) |
508+
TypeKind::Enum(..) => return self.local_id(ctx).to_string(),
509+
_ => {}
510+
}
511+
}
512+
format!("id_{}", self.id().0)
513+
}
514+
515+
fn make_exposed_name(&self,
516+
parent_name: Option<String>,
517+
base_name: Option<String>,
518+
ctx: &BindgenContext) -> String {
519+
lazy_static! {
520+
static ref RE_ENDS_WITH_BINDGEN_TY: Regex = Regex::new(r"_bindgen_ty(_\d+)+$").unwrap();
521+
static ref RE_ENDS_WITH_BINDGEN_MOD: Regex = Regex::new(r"_bindgen_mod(_\d+)+$").unwrap();
522+
}
523+
let (re, kind) = match *self.kind() {
524+
ItemKind::Module(..) => (&*RE_ENDS_WITH_BINDGEN_MOD, "mod"),
525+
_ => (&*RE_ENDS_WITH_BINDGEN_TY, "ty"),
526+
};
527+
let parent_name = parent_name.and_then(|n| if n.is_empty() { None } else { Some(n) });
528+
match (parent_name, base_name) {
529+
(Some(parent), Some(base)) => format!("{}_{}", parent, base),
530+
(Some(parent), None) => {
531+
if re.is_match(parent.as_str()) {
532+
format!("{}_{}", parent, self.exposed_id(ctx))
533+
} else {
534+
format!("{}__bindgen_{}_{}", parent, kind, self.exposed_id(ctx))
535+
}
536+
}
537+
(None, Some(base)) => base,
538+
(None, None) => format!("_bindgen_{}_{}", kind, self.exposed_id(ctx)),
491539
}
492540
}
493541

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ extern crate libc;
1616
extern crate regex;
1717
#[macro_use]
1818
extern crate log;
19+
#[macro_use]
20+
extern crate lazy_static;
1921

2022
mod clangll;
2123
mod clang;

tests/expectations/anon_enum.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ pub struct Test {
1010
pub foo: ::std::os::raw::c_int,
1111
pub bar: f32,
1212
}
13-
pub const Test_T_NONE: Test__bindgen_ty_bindgen_id_6 =
14-
Test__bindgen_ty_bindgen_id_6::T_NONE;
13+
pub const Test_T_NONE: Test__bindgen_ty_1 = Test__bindgen_ty_1::T_NONE;
1514
#[repr(u32)]
1615
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
17-
pub enum Test__bindgen_ty_bindgen_id_6 { T_NONE = 0, }
16+
pub enum Test__bindgen_ty_1 { T_NONE = 0, }
1817
#[test]
1918
fn bindgen_test_layout_Test() {
2019
assert_eq!(::std::mem::size_of::<Test>() , 8usize);

tests/expectations/anon_enum_whitelist.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
#![allow(non_snake_case)]
55

66

7-
pub const NODE_FLAG_FOO: _bindgen_ty_bindgen_id_1 =
8-
_bindgen_ty_bindgen_id_1::NODE_FLAG_FOO;
9-
pub const NODE_FLAG_BAR: _bindgen_ty_bindgen_id_1 =
10-
_bindgen_ty_bindgen_id_1::NODE_FLAG_BAR;
7+
pub const NODE_FLAG_FOO: _bindgen_ty_1 = _bindgen_ty_1::NODE_FLAG_FOO;
8+
pub const NODE_FLAG_BAR: _bindgen_ty_1 = _bindgen_ty_1::NODE_FLAG_BAR;
119
#[repr(u32)]
1210
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
13-
pub enum _bindgen_ty_bindgen_id_1 { NODE_FLAG_FOO = 0, NODE_FLAG_BAR = 1, }
11+
pub enum _bindgen_ty_1 { NODE_FLAG_FOO = 0, NODE_FLAG_BAR = 1, }

tests/expectations/anon_union.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
2828
#[derive(Debug, Copy, Clone)]
2929
pub struct TErrorResult<T> {
3030
pub mResult: ::std::os::raw::c_int,
31-
pub __bindgen_anon_1: TErrorResult__bindgen_ty_bindgen_id_10<T>,
31+
pub __bindgen_anon_1: TErrorResult__bindgen_ty_1<T>,
3232
pub mMightHaveUnreported: bool,
3333
pub mUnionState: TErrorResult_UnionState,
3434
pub _phantom_0: ::std::marker::PhantomData<T>,
@@ -52,7 +52,7 @@ pub struct TErrorResult_DOMExceptionInfo<T> {
5252
}
5353
#[repr(C)]
5454
#[derive(Debug, Copy, Clone)]
55-
pub struct TErrorResult__bindgen_ty_bindgen_id_10<T> {
55+
pub struct TErrorResult__bindgen_ty_1<T> {
5656
pub mMessage: __BindgenUnionField<*mut TErrorResult_Message<T>>,
5757
pub mDOMExceptionInfo: __BindgenUnionField<*mut TErrorResult_DOMExceptionInfo<T>>,
5858
pub bindgen_union_field: u64,

tests/expectations/class_with_inner_struct.rs

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ impl <T> ::std::marker::Copy for __BindgenUnionField<T> { }
2828
#[derive(Debug, Copy)]
2929
pub struct A {
3030
pub c: ::std::os::raw::c_uint,
31-
pub named_union: A__bindgen_ty_bindgen_id_9,
32-
pub __bindgen_anon_1: A__bindgen_ty_bindgen_id_14,
31+
pub named_union: A__bindgen_ty_1,
32+
pub __bindgen_anon_1: A__bindgen_ty_2,
3333
}
3434
#[repr(C)]
3535
#[derive(Debug, Copy)]
@@ -47,31 +47,30 @@ impl Clone for A_Segment {
4747
}
4848
#[repr(C)]
4949
#[derive(Debug, Copy)]
50-
pub struct A__bindgen_ty_bindgen_id_9 {
50+
pub struct A__bindgen_ty_1 {
5151
pub f: __BindgenUnionField<::std::os::raw::c_int>,
5252
pub bindgen_union_field: u32,
5353
}
5454
#[test]
55-
fn bindgen_test_layout_A__bindgen_ty_bindgen_id_9() {
56-
assert_eq!(::std::mem::size_of::<A__bindgen_ty_bindgen_id_9>() , 4usize);
57-
assert_eq!(::std::mem::align_of::<A__bindgen_ty_bindgen_id_9>() , 4usize);
55+
fn bindgen_test_layout_A__bindgen_ty_1() {
56+
assert_eq!(::std::mem::size_of::<A__bindgen_ty_1>() , 4usize);
57+
assert_eq!(::std::mem::align_of::<A__bindgen_ty_1>() , 4usize);
5858
}
59-
impl Clone for A__bindgen_ty_bindgen_id_9 {
59+
impl Clone for A__bindgen_ty_1 {
6060
fn clone(&self) -> Self { *self }
6161
}
6262
#[repr(C)]
6363
#[derive(Debug, Copy)]
64-
pub struct A__bindgen_ty_bindgen_id_14 {
64+
pub struct A__bindgen_ty_2 {
6565
pub d: __BindgenUnionField<::std::os::raw::c_int>,
6666
pub bindgen_union_field: u32,
6767
}
6868
#[test]
69-
fn bindgen_test_layout_A__bindgen_ty_bindgen_id_14() {
70-
assert_eq!(::std::mem::size_of::<A__bindgen_ty_bindgen_id_14>() , 4usize);
71-
assert_eq!(::std::mem::align_of::<A__bindgen_ty_bindgen_id_14>() ,
72-
4usize);
69+
fn bindgen_test_layout_A__bindgen_ty_2() {
70+
assert_eq!(::std::mem::size_of::<A__bindgen_ty_2>() , 4usize);
71+
assert_eq!(::std::mem::align_of::<A__bindgen_ty_2>() , 4usize);
7372
}
74-
impl Clone for A__bindgen_ty_bindgen_id_14 {
73+
impl Clone for A__bindgen_ty_2 {
7574
fn clone(&self) -> Self { *self }
7675
}
7776
#[test]
@@ -121,57 +120,51 @@ pub enum StepSyntax {
121120
#[derive(Debug, Copy)]
122121
pub struct C {
123122
pub d: ::std::os::raw::c_uint,
124-
pub __bindgen_anon_1: C__bindgen_ty_bindgen_id_31,
123+
pub __bindgen_anon_1: C__bindgen_ty_1,
125124
}
126125
#[repr(C)]
127126
#[derive(Debug, Copy)]
128-
pub struct C__bindgen_ty_bindgen_id_31 {
129-
pub mFunc: __BindgenUnionField<C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_32>,
130-
pub __bindgen_anon_1: __BindgenUnionField<C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_43>,
127+
pub struct C__bindgen_ty_1 {
128+
pub mFunc: __BindgenUnionField<C__bindgen_ty_1_1>,
129+
pub __bindgen_anon_1: __BindgenUnionField<C__bindgen_ty_1_2>,
131130
pub bindgen_union_field: [u32; 4usize],
132131
}
133132
#[repr(C)]
134133
#[derive(Debug, Copy)]
135-
pub struct C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_32 {
134+
pub struct C__bindgen_ty_1_1 {
136135
pub mX1: f32,
137136
pub mY1: f32,
138137
pub mX2: f32,
139138
pub mY2: f32,
140139
}
141140
#[test]
142-
fn bindgen_test_layout_C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_32() {
143-
assert_eq!(::std::mem::size_of::<C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_32>()
144-
, 16usize);
145-
assert_eq!(::std::mem::align_of::<C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_32>()
146-
, 4usize);
141+
fn bindgen_test_layout_C__bindgen_ty_1_1() {
142+
assert_eq!(::std::mem::size_of::<C__bindgen_ty_1_1>() , 16usize);
143+
assert_eq!(::std::mem::align_of::<C__bindgen_ty_1_1>() , 4usize);
147144
}
148-
impl Clone for C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_32 {
145+
impl Clone for C__bindgen_ty_1_1 {
149146
fn clone(&self) -> Self { *self }
150147
}
151148
#[repr(C)]
152149
#[derive(Debug, Copy)]
153-
pub struct C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_43 {
150+
pub struct C__bindgen_ty_1_2 {
154151
pub mStepSyntax: StepSyntax,
155152
pub mSteps: ::std::os::raw::c_uint,
156153
}
157154
#[test]
158-
fn bindgen_test_layout_C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_43() {
159-
assert_eq!(::std::mem::size_of::<C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_43>()
160-
, 8usize);
161-
assert_eq!(::std::mem::align_of::<C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_43>()
162-
, 4usize);
155+
fn bindgen_test_layout_C__bindgen_ty_1_2() {
156+
assert_eq!(::std::mem::size_of::<C__bindgen_ty_1_2>() , 8usize);
157+
assert_eq!(::std::mem::align_of::<C__bindgen_ty_1_2>() , 4usize);
163158
}
164-
impl Clone for C__bindgen_ty_bindgen_id_31__bindgen_ty_bindgen_id_43 {
159+
impl Clone for C__bindgen_ty_1_2 {
165160
fn clone(&self) -> Self { *self }
166161
}
167162
#[test]
168-
fn bindgen_test_layout_C__bindgen_ty_bindgen_id_31() {
169-
assert_eq!(::std::mem::size_of::<C__bindgen_ty_bindgen_id_31>() ,
170-
16usize);
171-
assert_eq!(::std::mem::align_of::<C__bindgen_ty_bindgen_id_31>() ,
172-
4usize);
163+
fn bindgen_test_layout_C__bindgen_ty_1() {
164+
assert_eq!(::std::mem::size_of::<C__bindgen_ty_1>() , 16usize);
165+
assert_eq!(::std::mem::align_of::<C__bindgen_ty_1>() , 4usize);
173166
}
174-
impl Clone for C__bindgen_ty_bindgen_id_31 {
167+
impl Clone for C__bindgen_ty_1 {
175168
fn clone(&self) -> Self { *self }
176169
}
177170
#[repr(C)]

tests/expectations/const_enum_unnamed.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,20 @@
44
#![allow(non_snake_case)]
55

66

7-
pub const FOO_BAR: _bindgen_ty_bindgen_id_1 =
8-
_bindgen_ty_bindgen_id_1::FOO_BAR;
9-
pub const FOO_BAZ: _bindgen_ty_bindgen_id_1 =
10-
_bindgen_ty_bindgen_id_1::FOO_BAZ;
7+
pub const FOO_BAR: _bindgen_ty_1 = _bindgen_ty_1::FOO_BAR;
8+
pub const FOO_BAZ: _bindgen_ty_1 = _bindgen_ty_1::FOO_BAZ;
119
#[repr(u32)]
1210
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
13-
pub enum _bindgen_ty_bindgen_id_1 { FOO_BAR = 0, FOO_BAZ = 1, }
11+
pub enum _bindgen_ty_1 { FOO_BAR = 0, FOO_BAZ = 1, }
1412
#[repr(C)]
1513
#[derive(Debug, Copy)]
1614
pub struct Foo {
1715
pub _address: u8,
1816
}
19-
pub const Foo_FOO_BAR: Foo__bindgen_ty_bindgen_id_5 =
20-
Foo__bindgen_ty_bindgen_id_5::FOO_BAR;
17+
pub const Foo_FOO_BAR: Foo__bindgen_ty_1 = Foo__bindgen_ty_1::FOO_BAR;
2118
#[repr(u32)]
2219
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
23-
pub enum Foo__bindgen_ty_bindgen_id_5 { FOO_BAR = 10, }
20+
pub enum Foo__bindgen_ty_1 { FOO_BAR = 10, }
2421
#[test]
2522
fn bindgen_test_layout_Foo() {
2623
assert_eq!(::std::mem::size_of::<Foo>() , 1usize);

0 commit comments

Comments
 (0)