summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Fitzgerald <fitzgen@gmail.com>2017-09-29 15:36:49 -0700
committerNick Fitzgerald <fitzgen@gmail.com>2017-10-02 11:32:06 -0700
commit2a93916e32692ecf6581138353bfa29671e342f9 (patch)
tree783354db56f3f7bf38f04f59d11a2499f9af8335
parent0c5f4e1ffa6da921ff07525fcd1a25623c782d0e (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.rs2
-rw-r--r--src/codegen/mod.rs14
-rw-r--r--src/codegen/struct_layout.rs2
-rw-r--r--src/ir/analysis/derive_debug.rs2
-rw-r--r--src/ir/analysis/derive_hash.rs2
-rw-r--r--src/ir/analysis/derive_partial_eq_or_partial_ord.rs2
-rw-r--r--src/ir/analysis/has_type_param_in_array.rs2
-rw-r--r--src/ir/analysis/template_params.rs4
-rw-r--r--src/ir/comp.rs8
-rw-r--r--src/ir/context.rs47
-rw-r--r--src/ir/enum_ty.rs2
-rw-r--r--src/ir/ty.rs16
-rw-r--r--src/ir/var.rs2
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: &quote::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)
});