diff options
-rw-r--r-- | src/codegen/mod.rs | 6 | ||||
-rw-r--r-- | src/ir/context.rs | 82 |
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 { |