Skip to content

Commit 5691cab

Browse files
committed
Use BindgenContext::whitelisted_items in code generation
This replaces the manual gathering and traversal of the transitive closure of whitelisted items with the new canonical method.
1 parent fcc7b57 commit 5691cab

File tree

2 files changed

+34
-94
lines changed

2 files changed

+34
-94
lines changed

src/codegen/mod.rs

+33-93
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use ir::item_kind::ItemKind;
1414
use ir::layout::Layout;
1515
use ir::module::Module;
1616
use ir::ty::{Type, TypeKind};
17-
use ir::type_collector::{ItemSet, TypeCollector};
17+
use ir::type_collector::ItemSet;
1818
use ir::var::Var;
1919
use self::helpers::{BlobTyBuilder, attributes};
2020

@@ -1692,108 +1692,48 @@ impl CodeGenerator for Function {
16921692
}
16931693
}
16941694

1695+
// Return true if any of the ancestors of `id` are in the whitelisted items set,
1696+
// false otherwise.
1697+
fn ancestor_is_whitelisted(ctx: &BindgenContext,
1698+
whitelisted_items: &ItemSet,
1699+
id: ItemId)
1700+
-> bool {
1701+
let item = ctx.resolve_item(id);
1702+
let mut last = id;
1703+
let mut current = item.parent_id();
1704+
1705+
while last != current {
1706+
if whitelisted_items.contains(&current) {
1707+
return true;
1708+
}
1709+
last = current;
1710+
current = ctx.resolve_item(current).parent_id();
1711+
}
1712+
1713+
false
1714+
}
1715+
16951716
pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> {
16961717
context.gen(|context| {
16971718
let mut result = CodegenResult::new();
16981719

16991720
debug!("codegen: {:?}", context.options());
17001721

1701-
// If the whitelisted types and functions sets are empty, just generate
1702-
// everything.
1703-
if context.options().whitelisted_types.is_empty() &&
1704-
context.options().whitelisted_functions.is_empty() &&
1705-
context.options().whitelisted_vars.is_empty() {
1706-
for (_item_id, item) in context.items() {
1707-
// Non-toplevel item parents are the responsible one for
1708-
// generating them.
1709-
if item.is_toplevel(context) {
1710-
item.codegen(context, &mut result, &());
1711-
}
1712-
}
1713-
} else {
1714-
// Recursively collect all the types dependent on the whitelisted
1715-
// types, then generate them.
1716-
//
1717-
// FIXME(emilio): This pass is probably slow, but it can't be faster
1718-
// than docopt anyway :)
1719-
let mut items = ItemSet::new();
1720-
for (_item_id, item) in context.items() {
1721-
// FIXME(emilio): This probably should look only at whether the
1722-
// parent is a module.
1723-
if !item.is_toplevel(context) {
1724-
continue;
1725-
}
1726-
1727-
let name = item.canonical_name(context);
1728-
match *item.kind() {
1729-
ItemKind::Type(ref ty) => {
1730-
if context.options().whitelisted_types.matches(&name) {
1731-
item.collect_types(context, &mut items, &());
1732-
}
1733-
// Unnamed top-level enums are special and we whitelist
1734-
// them via the whitelisted_vars filter, since they're
1735-
// effectively top-level constants, and there's no way
1736-
// for them to be referenced consistently.
1737-
if let TypeKind::Enum(ref enum_) = *ty.kind() {
1738-
if ty.name().is_none() {
1739-
if enum_.variants().iter().any(|variant| {
1740-
context.options()
1741-
.whitelisted_vars
1742-
.matches(&variant.name())
1743-
}) {
1744-
item.collect_types(context,
1745-
&mut items,
1746-
&());
1747-
}
1748-
}
1749-
}
1750-
}
1751-
ItemKind::Function(ref fun) => {
1752-
if context.options()
1753-
.whitelisted_functions
1754-
.matches(&name) {
1755-
items.insert(item.id());
1756-
fun.signature()
1757-
.collect_types(context, &mut items, &());
1758-
}
1759-
}
1760-
ItemKind::Var(ref var) => {
1761-
if context.options().whitelisted_vars.matches(&name) {
1762-
items.insert(item.id());
1763-
var.ty().collect_types(context, &mut items, &());
1764-
}
1765-
}
1766-
ItemKind::Module(..) => {}
1767-
}
1768-
}
1769-
1770-
fn contains_parent(ctx: &BindgenContext,
1771-
types: &ItemSet,
1772-
id: ItemId)
1773-
-> bool {
1774-
let item = ctx.resolve_item(id);
1775-
let mut last = id;
1776-
let mut current = item.parent_id();
1777-
1778-
while last != current {
1779-
if types.contains(&current) {
1780-
return true;
1781-
}
1782-
last = current;
1783-
current = ctx.resolve_item(current).parent_id();
1784-
}
1722+
let whitelisted_items: ItemSet = context.whitelisted_items().collect();
17851723

1786-
false
1787-
}
1724+
for &id in whitelisted_items.iter() {
1725+
let item = context.resolve_item(id);
17881726

1789-
for item_id in items.iter() {
1790-
let item = context.resolve_item(*item_id);
1791-
if item.is_toplevel(context) ||
1792-
!contains_parent(context, &items, *item_id) {
1793-
item.codegen(context, &mut result, &());
1794-
}
1727+
// Non-toplevel items' parents are responsible one for generating
1728+
// their children. However, if we find an orphaned reference to a
1729+
// non-toplevel item whose parent is not in our whitelisted set, we
1730+
// need to take responsibility for generating it.
1731+
if item.is_toplevel(context) ||
1732+
!ancestor_is_whitelisted(context, &whitelisted_items, id) {
1733+
item.codegen(context, &mut result, &());
17951734
}
17961735
}
1736+
17971737
let saw_union = result.saw_union;
17981738
let mut result = result.items;
17991739
if saw_union && !context.options().unstable_rust {

tests/expectations/type_alias_empty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
#![allow(non_snake_case)]
55

66

7-
7+
pub type bool_constant = ();

0 commit comments

Comments
 (0)