summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Fitzgerald <fitzgen@gmail.com>2017-04-17 13:23:22 -0700
committerNick Fitzgerald <fitzgen@gmail.com>2017-04-17 16:01:57 -0700
commit8fc90585593c011c5a5be03278d6b785db5f16b8 (patch)
tree30afb8765865b1888add5a2c730c5e8dfa848d52
parentc6a1e003d792c7067d5f3ec792196d449a9b3bbf (diff)
Make a builder for item resolution options
We have a couple knobs to turn for item resolution, such as whether we keep going through type references and type aliases. It makes sense to have a single, easy place to configure these knobs.
-rw-r--r--src/codegen/mod.rs6
-rw-r--r--src/ir/context.rs82
2 files changed, 71 insertions, 17 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 20151fe3..950de02a 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -2647,8 +2647,10 @@ impl TryToRustTy for TemplateInstantiation {
// This can happen if we generated an opaque type for a partial
// template specialization, and we've hit an instantiation of
// that partial specialization.
- extra_assert!(ctx.resolve_type_through_type_refs(decl)
- .is_opaque());
+ extra_assert!(decl.into_resolver()
+ .through_type_refs()
+ .resolve(ctx)
+ .is_opaque(ctx));
return Err(error::Error::InstantiationOfOpaqueType);
}
};
diff --git a/src/ir/context.rs b/src/ir/context.rs
index d00e4899..01416c9e 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -712,21 +712,6 @@ impl<'ctx> BindgenContext<'ctx> {
}
}
- /// Resolve the given `ItemId` into a `Type`, and keep doing so while we see
- /// `ResolvedTypeRef`s to other items until we get to the final `Type`.
- pub fn resolve_type_through_type_refs(&self, item_id: ItemId) -> &Type {
- assert!(self.collected_typerefs());
-
- let mut id = item_id;
- loop {
- let ty = self.resolve_type(id);
- match *ty.kind() {
- TypeKind::ResolvedTypeRef(next_id) => id = next_id,
- _ => return ty,
- }
- }
- }
-
/// Get the current module.
pub fn current_module(&self) -> ItemId {
self.current_module
@@ -1420,6 +1405,73 @@ impl<'ctx> BindgenContext<'ctx> {
}
}
+/// A builder struct for configuring item resolution options.
+#[derive(Debug, Copy, Clone)]
+pub struct ItemResolver {
+ id: ItemId,
+ through_type_refs: bool,
+ through_type_aliases: bool,
+}
+
+impl ItemId {
+ /// Create an `ItemResolver` from this item id.
+ pub fn into_resolver(self) -> ItemResolver {
+ self.into()
+ }
+}
+
+impl From<ItemId> for ItemResolver {
+ fn from(id: ItemId) -> ItemResolver {
+ ItemResolver::new(id)
+ }
+}
+
+impl ItemResolver {
+ /// Construct a new `ItemResolver` from the given id.
+ pub fn new(id: ItemId) -> ItemResolver {
+ ItemResolver {
+ id: id,
+ through_type_refs: false,
+ through_type_aliases: false,
+ }
+ }
+
+ /// Keep resolving through `Type::TypeRef` items.
+ pub fn through_type_refs(mut self) -> ItemResolver {
+ self.through_type_refs = true;
+ self
+ }
+
+ /// Keep resolving through `Type::Alias` items.
+ pub fn through_type_aliases(mut self) -> ItemResolver {
+ self.through_type_aliases = true;
+ self
+ }
+
+ /// Finish configuring and perform the actual item resolution.
+ pub fn resolve<'a, 'b>(self, ctx: &'a BindgenContext<'b>) -> &'a Item {
+ assert!(ctx.collected_typerefs());
+
+ let mut id = self.id;
+ loop {
+ let item = ctx.resolve_item(id);
+ let ty_kind = item.as_type().map(|t| t.kind());
+ match ty_kind {
+ Some(&TypeKind::ResolvedTypeRef(next_id)) if self.through_type_refs => {
+ id = next_id;
+ }
+ // We intentionally ignore template aliases here, as they are
+ // more complicated, and don't represent a simple renaming of
+ // some type.
+ Some(&TypeKind::Alias(next_id)) if self.through_type_aliases => {
+ id = next_id;
+ }
+ _ => return item,
+ }
+ }
+ }
+}
+
/// A type that we are in the middle of parsing.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct PartialType {