diff options
author | Nick Fitzgerald <fitzgen@gmail.com> | 2017-09-29 15:36:49 -0700 |
---|---|---|
committer | Nick Fitzgerald <fitzgen@gmail.com> | 2017-10-02 11:32:06 -0700 |
commit | 2a93916e32692ecf6581138353bfa29671e342f9 (patch) | |
tree | 783354db56f3f7bf38f04f59d11a2499f9af8335 | |
parent | 0c5f4e1ffa6da921ff07525fcd1a25623c782d0e (diff) |
Introduce the `TypeId` newtype over `ItemId`
This commit also makes `BindgenContext::resolve_type` take a `TypeId`, and adds
unchecked conversions everywhere that we call it. Next, I'm going to go through
the code base, replacing these unchecked conversions with checked ones, and
tightening up types as I go.
-rw-r--r-- | src/codegen/impl_debug.rs | 2 | ||||
-rw-r--r-- | src/codegen/mod.rs | 14 | ||||
-rw-r--r-- | src/codegen/struct_layout.rs | 2 | ||||
-rw-r--r-- | src/ir/analysis/derive_debug.rs | 2 | ||||
-rw-r--r-- | src/ir/analysis/derive_hash.rs | 2 | ||||
-rw-r--r-- | src/ir/analysis/derive_partial_eq_or_partial_ord.rs | 2 | ||||
-rw-r--r-- | src/ir/analysis/has_type_param_in_array.rs | 2 | ||||
-rw-r--r-- | src/ir/analysis/template_params.rs | 4 | ||||
-rw-r--r-- | src/ir/comp.rs | 8 | ||||
-rw-r--r-- | src/ir/context.rs | 47 | ||||
-rw-r--r-- | src/ir/enum_ty.rs | 2 | ||||
-rw-r--r-- | src/ir/ty.rs | 16 | ||||
-rw-r--r-- | src/ir/var.rs | 2 |
13 files changed, 68 insertions, 37 deletions
diff --git a/src/codegen/impl_debug.rs b/src/codegen/impl_debug.rs index 7ef108da..e111ecc6 100644 --- a/src/codegen/impl_debug.rs +++ b/src/codegen/impl_debug.rs @@ -203,7 +203,7 @@ impl<'a> ImplDebug<'a> for Item { } TypeKind::Pointer(inner) => { - let inner_type = ctx.resolve_type(inner).canonical_type(ctx); + let inner_type = ctx.resolve_type(inner.as_type_id_unchecked()).canonical_type(ctx); match *inner_type.kind() { TypeKind::Function(ref sig) if !sig.can_trivially_derive_debug() => { diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 895422b0..59102296 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -689,7 +689,7 @@ impl CodeGenerator for Type { let params: Vec<_> = params.into_iter() .filter_map(|p| p.as_template_param(ctx, &())) .collect(); - if params.iter().any(|p| ctx.resolve_type(*p).is_invalid_type_param()) { + if params.iter().any(|p| ctx.resolve_type(p.as_type_id_unchecked()).is_invalid_type_param()) { warn!( "Item contained invalid template \ parameter: {:?}", @@ -1112,7 +1112,7 @@ impl Bitfield { ctor_impl: quote::Tokens, unit_field_int_ty: "e::Tokens, ) -> quote::Tokens { - let bitfield_ty = ctx.resolve_type(self.ty()); + let bitfield_ty = ctx.resolve_type(self.ty().as_type_id_unchecked()); let bitfield_ty_layout = bitfield_ty.layout(ctx).expect( "Bitfield without layout? Gah!", ); @@ -1542,7 +1542,7 @@ impl CodeGenerator for CompInfo { continue; } - let base_ty = ctx.resolve_type(base.ty); + let base_ty = ctx.resolve_type(base.ty.as_type_id_unchecked()); // NB: We won't include unsized types in our base chain because they // would contribute to our size given the dummy field we insert for // unsized types. @@ -1673,7 +1673,7 @@ impl CodeGenerator for CompInfo { let mut param_names = vec![]; for (idx, ty) in params.iter().enumerate() { - let param = ctx.resolve_type(*ty); + let param = ctx.resolve_type(ty.as_type_id_unchecked()); let name = param.name().unwrap(); let ident = ctx.rust_ident(name); param_names.push(ident.clone()); @@ -2318,7 +2318,7 @@ impl CodeGenerator for Enum { let enum_ty = item.expect_type(); let layout = enum_ty.layout(ctx); - let repr = self.repr().map(|repr| ctx.resolve_type(repr)); + let repr = self.repr().map(|repr| ctx.resolve_type(repr.as_type_id_unchecked())); let repr = match repr { Some(repr) => { match *repr.canonical_type(ctx).kind() { @@ -2932,7 +2932,7 @@ impl TryToRustTy for Type { } TypeKind::Pointer(inner) | TypeKind::Reference(inner) => { - let is_const = self.is_const() || ctx.resolve_type(inner).is_const(); + let is_const = self.is_const() || ctx.resolve_type(inner.as_type_id_unchecked()).is_const(); let inner = inner.into_resolver().through_type_refs().resolve(ctx); let inner_ty = inner.expect_type(); @@ -3641,7 +3641,7 @@ mod utils { let arg_ty = match *arg_ty.canonical_type(ctx).kind() { TypeKind::Array(t, _) => { t.to_rust_ty_or_opaque(ctx, &()) - .to_ptr(ctx.resolve_type(t).is_const()) + .to_ptr(ctx.resolve_type(t.as_type_id_unchecked()).is_const()) }, TypeKind::Pointer(inner) => { let inner = ctx.resolve_item(inner); diff --git a/src/codegen/struct_layout.rs b/src/codegen/struct_layout.rs index 06059853..9e08b13f 100644 --- a/src/codegen/struct_layout.rs +++ b/src/codegen/struct_layout.rs @@ -166,7 +166,7 @@ impl<'a> StructLayoutTracker<'a> { // // This means that the structs in the array are super-unsafe to // access, since they won't be properly aligned, but *shrug*. - if let Some(layout) = self.ctx.resolve_type(inner).layout( + if let Some(layout) = self.ctx.resolve_type(inner.as_type_id_unchecked()).layout( self.ctx, ) { diff --git a/src/ir/analysis/derive_debug.rs b/src/ir/analysis/derive_debug.rs index 7df745c9..fd9fe2cc 100644 --- a/src/ir/analysis/derive_debug.rs +++ b/src/ir/analysis/derive_debug.rs @@ -294,7 +294,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> { TypeKind::Pointer(inner) => { let inner_type = - self.ctx.resolve_type(inner).canonical_type(self.ctx); + self.ctx.resolve_type(inner.as_type_id_unchecked()).canonical_type(self.ctx); if let TypeKind::Function(ref sig) = *inner_type.kind() { if !sig.can_trivially_derive_debug() { trace!( diff --git a/src/ir/analysis/derive_hash.rs b/src/ir/analysis/derive_hash.rs index 5313cae3..f53dbfc7 100644 --- a/src/ir/analysis/derive_hash.rs +++ b/src/ir/analysis/derive_hash.rs @@ -197,7 +197,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> { TypeKind::Pointer(inner) => { let inner_type = - self.ctx.resolve_type(inner).canonical_type(self.ctx); + self.ctx.resolve_type(inner.as_type_id_unchecked()).canonical_type(self.ctx); if let TypeKind::Function(ref sig) = *inner_type.kind() { if !sig.can_trivially_derive_hash() { trace!( diff --git a/src/ir/analysis/derive_partial_eq_or_partial_ord.rs b/src/ir/analysis/derive_partial_eq_or_partial_ord.rs index f34a256a..0e01247e 100644 --- a/src/ir/analysis/derive_partial_eq_or_partial_ord.rs +++ b/src/ir/analysis/derive_partial_eq_or_partial_ord.rs @@ -209,7 +209,7 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { TypeKind::Pointer(inner) => { let inner_type = - self.ctx.resolve_type(inner).canonical_type(self.ctx); + self.ctx.resolve_type(inner.as_type_id_unchecked()).canonical_type(self.ctx); if let TypeKind::Function(ref sig) = *inner_type.kind() { if !sig.can_trivially_derive_partialeq_or_partialord() { trace!( diff --git a/src/ir/analysis/has_type_param_in_array.rs b/src/ir/analysis/has_type_param_in_array.rs index f21bae14..5b034cca 100644 --- a/src/ir/analysis/has_type_param_in_array.rs +++ b/src/ir/analysis/has_type_param_in_array.rs @@ -147,7 +147,7 @@ impl<'ctx> MonotoneFramework for HasTypeParameterInArray<'ctx> { TypeKind::Array(t, _) => { let inner_ty = - self.ctx.resolve_type(t).canonical_type(self.ctx); + self.ctx.resolve_type(t.as_type_id_unchecked()).canonical_type(self.ctx); match *inner_ty.kind() { TypeKind::TypeParam => { trace!(" Array with Named type has type parameter"); diff --git a/src/ir/analysis/template_params.rs b/src/ir/analysis/template_params.rs index 7699a0c2..ea4bd7b8 100644 --- a/src/ir/analysis/template_params.rs +++ b/src/ir/analysis/template_params.rs @@ -271,7 +271,7 @@ impl<'ctx> UsedTemplateParameters<'ctx> { ) { trace!(" template instantiation"); - let decl = self.ctx.resolve_type(instantiation.template_definition()); + let decl = self.ctx.resolve_type(instantiation.template_definition().as_type_id_unchecked()); let args = instantiation.template_arguments(); let params = decl.self_template_params(self.ctx).unwrap_or(vec![]); @@ -411,7 +411,7 @@ impl<'ctx> MonotoneFramework for UsedTemplateParameters<'ctx> { // generic template parameters are used. ctx.resolve_item(item).as_type().map(|ty| match ty.kind() { &TypeKind::TemplateInstantiation(ref inst) => { - let decl = ctx.resolve_type(inst.template_definition()); + let decl = ctx.resolve_type(inst.template_definition().as_type_id_unchecked()); let args = inst.template_arguments(); // Although template definitions should always have diff --git a/src/ir/comp.rs b/src/ir/comp.rs index e1b2a1f0..1bc53d1d 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -176,7 +176,7 @@ impl Field { layout, .. }) => Some(layout), Field::DataMember(ref data) => { - ctx.resolve_type(data.ty).layout(ctx) + ctx.resolve_type(data.ty.as_type_id_unchecked()).layout(ctx) } } } @@ -538,7 +538,7 @@ fn bitfields_to_allocation_units<E, I>( for bitfield in raw_bitfields { let bitfield_width = bitfield.bitfield().unwrap() as usize; - let bitfield_layout = ctx.resolve_type(bitfield.ty()) + let bitfield_layout = ctx.resolve_type(bitfield.ty().as_type_id_unchecked()) .layout(ctx) .expect("Bitfield without layout? Gah!"); let bitfield_size = bitfield_layout.size; @@ -913,7 +913,7 @@ impl CompInfo { pub fn is_unsized(&self, ctx: &BindgenContext, itemid: &ItemId) -> bool { !ctx.lookup_item_id_has_vtable(itemid) && self.fields().is_empty() && self.base_members.iter().all(|base| { - ctx.resolve_type(base.ty).canonical_type(ctx).is_unsized( + ctx.resolve_type(base.ty.as_type_id_unchecked()).canonical_type(ctx).is_unsized( ctx, &base.ty, ) @@ -1362,7 +1362,7 @@ impl CompInfo { // Unfortunately, given the way we implement --match-pat, and also // that you can inherit from templated types, we need to handle // other cases here too. - ctx.resolve_type(base.ty) + ctx.resolve_type(base.ty.as_type_id_unchecked()) .canonical_type(ctx) .as_comp() .map_or(false, |_| ctx.lookup_item_id_has_vtable(&base.ty)) diff --git a/src/ir/context.rs b/src/ir/context.rs index 5b6b46ef..f864ed84 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -32,15 +32,46 @@ use std::iter::IntoIterator; use std::mem; /// A single identifier for an item. -/// -/// TODO: Build stronger abstractions on top of this, like TypeId(ItemId)? #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct ItemId(usize); +/// An identifier for an `Item` whose `ItemKind` is known to be +/// `ItemKind::Type`. +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct TypeId(ItemId); + +impl From<TypeId> for ItemId { + fn from(tid: TypeId) -> ItemId { + tid.0 + } +} + +impl From<ItemId> for usize { + fn from(id: ItemId) -> usize { + id.0 + } +} + impl ItemId { /// Get a numeric representation of this id. pub fn as_usize(&self) -> usize { - self.0 + (*self).into() + } + + /// Convert this `ItemId` into a `TypeId` if its associated item is a type, + /// otherwise return `None`. + pub fn as_type_id(&self, ctx: &BindgenContext) -> Option<TypeId> { + if ctx.resolve_item(*self).kind().is_type() { + Some(self.as_type_id_unchecked()) + } else { + None + } + } + + /// Convert this `ItemId` into a `TypeId` without actually checking whether + /// this id actually points to a `Type`. + pub fn as_type_id_unchecked(&self) -> TypeId { + TypeId(*self) } } @@ -1212,16 +1243,16 @@ impl BindgenContext { /// /// Panics if there is no item for the given `ItemId` or if the resolved /// item is not a `Type`. - pub fn resolve_type(&self, type_id: ItemId) -> &Type { - self.items.get(&type_id).unwrap().kind().expect_type() + pub fn resolve_type(&self, type_id: TypeId) -> &Type { + self.items.get(&type_id.into()).unwrap().kind().expect_type() } /// Resolve the given `ItemId` as a type, or `None` if there is no item with /// the given id. /// /// Panics if the id resolves to an item that is not a type. - pub fn safe_resolve_type(&self, type_id: ItemId) -> Option<&Type> { - self.items.get(&type_id).map(|t| t.kind().expect_type()) + pub fn safe_resolve_type(&self, type_id: TypeId) -> Option<&Type> { + self.items.get(&type_id.into()).map(|t| t.kind().expect_type()) } /// Resolve the given `ItemId` into an `Item`, or `None` if no such item @@ -1371,7 +1402,7 @@ impl BindgenContext { ) -> Option<ItemId> { use clang_sys; - let num_expected_args = match self.resolve_type(template) + let num_expected_args = match self.resolve_type(template.as_type_id_unchecked()) .num_self_template_params(self) { Some(n) => n, None => { diff --git a/src/ir/enum_ty.rs b/src/ir/enum_ty.rs index dc56f64a..c02f0163 100644 --- a/src/ir/enum_ty.rs +++ b/src/ir/enum_ty.rs @@ -72,7 +72,7 @@ impl Enum { // Assume signedness since the default type by the C standard is an int. let is_signed = repr.and_then( - |r| ctx.resolve_type(r).safe_canonical_type(ctx), + |r| ctx.resolve_type(r.as_type_id_unchecked()).safe_canonical_type(ctx), ).map_or(true, |ty| match *ty.kind() { TypeKind::Int(ref int_kind) => int_kind.is_signed(), ref other => { diff --git a/src/ir/ty.rs b/src/ir/ty.rs index 8cfbde10..301f543d 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -215,7 +215,7 @@ impl Type { if len == 0 { Some(item) } else { None } } TypeKind::ResolvedTypeRef(inner) => { - ctx.resolve_type(inner).is_incomplete_array(ctx) + ctx.resolve_type(inner.as_type_id_unchecked()).is_incomplete_array(ctx) } _ => None, } @@ -238,7 +238,7 @@ impl Type { )) } TypeKind::ResolvedTypeRef(inner) => { - ctx.resolve_type(inner).layout(ctx) + ctx.resolve_type(inner.as_type_id_unchecked()).layout(ctx) } _ => None, } @@ -333,10 +333,10 @@ impl Type { TypeKind::ResolvedTypeRef(inner) | TypeKind::Alias(inner) | TypeKind::TemplateAlias(inner, _) => { - ctx.resolve_type(inner).safe_canonical_type(ctx) + ctx.resolve_type(inner.as_type_id_unchecked()).safe_canonical_type(ctx) } TypeKind::TemplateInstantiation(ref inst) => { - ctx.resolve_type(inst.template_definition()) + ctx.resolve_type(inst.template_definition().as_type_id_unchecked()) .safe_canonical_type(ctx) } @@ -546,7 +546,7 @@ impl TemplateParameters for TypeKind { ) -> Option<Vec<ItemId>> { match *self { TypeKind::ResolvedTypeRef(id) => { - ctx.resolve_type(id).self_template_params(ctx) + ctx.resolve_type(id.as_type_id_unchecked()).self_template_params(ctx) } TypeKind::Comp(ref comp) => comp.self_template_params(ctx), TypeKind::TemplateAlias(_, ref args) => Some(args.clone()), @@ -701,16 +701,16 @@ impl Type { TypeKind::Comp(ref ci) => ci.is_unsized(ctx, itemid), TypeKind::Opaque => self.layout.map_or(true, |l| l.size == 0), TypeKind::Array(inner, size) => { - size == 0 || ctx.resolve_type(inner).is_unsized(ctx, &inner) + size == 0 || ctx.resolve_type(inner.as_type_id_unchecked()).is_unsized(ctx, &inner) } TypeKind::ResolvedTypeRef(inner) | TypeKind::Alias(inner) | TypeKind::TemplateAlias(inner, _) => { - ctx.resolve_type(inner).is_unsized(ctx, &inner) + ctx.resolve_type(inner.as_type_id_unchecked()).is_unsized(ctx, &inner) } TypeKind::TemplateInstantiation(ref inst) => { let definition = inst.template_definition(); - ctx.resolve_type(definition).is_unsized(ctx, &definition) + ctx.resolve_type(definition.as_type_id_unchecked()).is_unsized(ctx, &definition) } TypeKind::TypeParam | TypeKind::Int(..) | diff --git a/src/ir/var.rs b/src/ir/var.rs index 987bfd50..5fafd72d 100644 --- a/src/ir/var.rs +++ b/src/ir/var.rs @@ -236,7 +236,7 @@ impl ClangSubItemParser for Var { // tests/headers/inner_const.hpp // // That's fine because in that case we know it's not a literal. - let canonical_ty = ctx.safe_resolve_type(ty).and_then(|t| { + let canonical_ty = ctx.safe_resolve_type(ty.as_type_id_unchecked()).and_then(|t| { t.safe_canonical_type(ctx) }); |