summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Fitzgerald <fitzgen@gmail.com>2017-07-25 16:47:35 -0700
committerGitHub <noreply@github.com>2017-07-25 16:47:35 -0700
commit69075f48c9b7c1ebf52ff4bec098dd15be162a78 (patch)
treee30acbf472320e713e5c5da224a46a09afebeff3
parent23dbe487b8d2a142fb03d9aefc3b4dd29aa78009 (diff)
parent0969a8d6a226590fc293c3e4d79aafb3da05a34b (diff)
Merge pull request #850 from photoszzt/has_vtable
has vtable analysis
-rw-r--r--src/codegen/mod.rs10
-rw-r--r--src/ir/analysis/has_vtable.rs186
-rw-r--r--src/ir/analysis/mod.rs3
-rw-r--r--src/ir/comp.rs45
-rw-r--r--src/ir/context.rs28
-rw-r--r--src/ir/derive.rs2
-rw-r--r--src/ir/item.rs21
-rw-r--r--src/ir/layout.rs2
-rw-r--r--src/ir/template.rs5
-rw-r--r--src/ir/ty.rs32
10 files changed, 272 insertions, 62 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 78d73cd0..1c87d14f 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -1473,7 +1473,7 @@ impl CodeGenerator for CompInfo {
// the parent too.
let mut fields = vec![];
let mut struct_layout = StructLayoutTracker::new(ctx, self, &canonical_name);
- if self.needs_explicit_vtable(ctx) {
+ if self.needs_explicit_vtable(ctx, item) {
let vtable =
Vtable::new(item.id(), self.methods(), self.base_members());
vtable.codegen(ctx, result, item);
@@ -1504,7 +1504,7 @@ impl CodeGenerator for CompInfo {
// 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.
- if base_ty.is_unsized(ctx) {
+ if base_ty.is_unsized(ctx, &base.ty) {
continue;
}
@@ -1583,7 +1583,7 @@ impl CodeGenerator for CompInfo {
warn!("Opaque type without layout! Expect dragons!");
}
}
- } else if !is_union && !self.is_unsized(ctx) {
+ } else if !is_union && !self.is_unsized(ctx, &item.id()) {
if let Some(padding_field) =
layout.and_then(|layout| {
struct_layout.pad_struct(layout)
@@ -1607,7 +1607,7 @@ impl CodeGenerator for CompInfo {
//
// NOTE: This check is conveniently here to avoid the dummy fields we
// may add for unused template parameters.
- if self.is_unsized(ctx) {
+ if self.is_unsized(ctx, &item.id()) {
let has_address = if is_opaque {
// Generate the address field if it's an opaque type and
// couldn't determine the layout of the blob.
@@ -1707,7 +1707,7 @@ impl CodeGenerator for CompInfo {
let too_many_base_vtables = self.base_members()
.iter()
.filter(|base| {
- ctx.resolve_type(base.ty).has_vtable(ctx)
+ ctx.lookup_item_id_has_vtable(&base.ty)
})
.count() > 1;
diff --git a/src/ir/analysis/has_vtable.rs b/src/ir/analysis/has_vtable.rs
new file mode 100644
index 00000000..d6287742
--- /dev/null
+++ b/src/ir/analysis/has_vtable.rs
@@ -0,0 +1,186 @@
+//! Determining which types has vtable
+use super::{ConstrainResult, MonotoneFramework};
+use std::collections::HashSet;
+use std::collections::HashMap;
+use ir::context::{BindgenContext, ItemId};
+use ir::traversal::EdgeKind;
+use ir::ty::TypeKind;
+use ir::traversal::Trace;
+
+/// An analysis that finds for each IR item whether it has vtable or not
+///
+/// We use the monotone function `has vtable`, defined as follows:
+///
+/// * If T is a type alias, a templated alias, an indirection to another type,
+/// or a reference of a type, T has vtable if the type T refers to has vtable.
+/// * If T is a compound type, T has vtable if we saw a virtual function when
+/// parsing it or any of its base member has vtable.
+/// * If T is an instantiation of an abstract template definition, T has
+/// vtable if template definition has vtable
+#[derive(Debug, Clone)]
+pub struct HasVtableAnalysis<'ctx, 'gen>
+ where 'gen: 'ctx
+{
+ ctx: &'ctx BindgenContext<'gen>,
+
+ // The incremental result of this analysis's computation. Everything in this
+ // set definitely has a vtable.
+ have_vtable: HashSet<ItemId>,
+
+ // Dependencies saying that if a key ItemId has been inserted into the
+ // `have_vtable` set, then each of the ids in Vec<ItemId> need to be
+ // considered again.
+ //
+ // This is a subset of the natural IR graph with reversed edges, where we
+ // only include the edges from the IR graph that can affect whether a type
+ // has a vtable or not.
+ dependencies: HashMap<ItemId, Vec<ItemId>>,
+}
+
+impl<'ctx, 'gen> HasVtableAnalysis<'ctx, 'gen> {
+ fn consider_edge(kind: EdgeKind) -> bool {
+ match kind {
+ // These are the only edges that can affect whether a type has a
+ // vtable or not.
+ EdgeKind::TypeReference |
+ EdgeKind::BaseMember |
+ EdgeKind::TemplateDeclaration => true,
+ _ => false,
+ }
+ }
+
+ fn insert(&mut self, id: ItemId) -> ConstrainResult {
+ let was_not_already_in_set = self.have_vtable.insert(id);
+ assert!(
+ was_not_already_in_set,
+ "We shouldn't try and insert {:?} twice because if it was \
+ already in the set, `constrain` should have exited early.",
+ id
+ );
+ ConstrainResult::Changed
+ }
+}
+
+impl<'ctx, 'gen> MonotoneFramework for HasVtableAnalysis<'ctx, 'gen> {
+ type Node = ItemId;
+ type Extra = &'ctx BindgenContext<'gen>;
+ type Output = HashSet<ItemId>;
+
+ fn new(ctx: &'ctx BindgenContext<'gen>) -> HasVtableAnalysis<'ctx, 'gen> {
+ let have_vtable = HashSet::new();
+ let mut dependencies = HashMap::new();
+
+ for &item in ctx.whitelisted_items() {
+ dependencies.entry(item).or_insert(vec![]);
+
+ {
+ // We reverse our natural IR graph edges to find dependencies
+ // between nodes.
+ item.trace(ctx, &mut |sub_item: ItemId, edge_kind| {
+ if ctx.whitelisted_items().contains(&sub_item) &&
+ Self::consider_edge(edge_kind) {
+ dependencies.entry(sub_item)
+ .or_insert(vec![])
+ .push(item);
+ }
+ }, &());
+ }
+ }
+
+ HasVtableAnalysis {
+ ctx,
+ have_vtable,
+ dependencies,
+ }
+ }
+
+ fn initial_worklist(&self) -> Vec<ItemId> {
+ self.ctx.whitelisted_items().iter().cloned().collect()
+ }
+
+ fn constrain(&mut self, id: ItemId) -> ConstrainResult {
+ if self.have_vtable.contains(&id) {
+ // We've already computed that this type has a vtable and that can't
+ // change.
+ return ConstrainResult::Same;
+ }
+
+ let item = self.ctx.resolve_item(id);
+ let ty = match item.as_type() {
+ None => return ConstrainResult::Same,
+ Some(ty) => ty
+ };
+
+ // TODO #851: figure out a way to handle deriving from template type parameters.
+ match *ty.kind() {
+ TypeKind::TemplateAlias(t, _) |
+ TypeKind::Alias(t) |
+ TypeKind::ResolvedTypeRef(t) |
+ TypeKind::Reference(t) => {
+ if self.have_vtable.contains(&t) {
+ self.insert(id)
+ } else {
+ ConstrainResult::Same
+ }
+ },
+
+ TypeKind::Comp(ref info) => {
+ if info.has_own_virtual_method() {
+ return self.insert(id);
+ }
+ let bases_has_vtable = info.base_members().iter().any(|base| {
+ self.have_vtable.contains(&base.ty)
+ });
+ if bases_has_vtable {
+ self.insert(id)
+ } else {
+ ConstrainResult::Same
+ }
+ },
+
+ TypeKind::TemplateInstantiation(ref inst) => {
+ if self.have_vtable.contains(&inst.template_definition()) {
+ self.insert(id)
+ } else {
+ ConstrainResult::Same
+ }
+ },
+
+ _ => ConstrainResult::Same,
+ }
+ }
+
+ fn each_depending_on<F>(&self, id: ItemId, mut f: F)
+ where F: FnMut(ItemId),
+ {
+ if let Some(edges) = self.dependencies.get(&id) {
+ for item in edges {
+ trace!("enqueue {:?} into worklist", item);
+ f(*item);
+ }
+ }
+ }
+}
+
+impl<'ctx, 'gen> From<HasVtableAnalysis<'ctx, 'gen>> for HashSet<ItemId> {
+ fn from(analysis: HasVtableAnalysis<'ctx, 'gen>) -> Self {
+ analysis.have_vtable
+ }
+}
+
+/// A convenience trait for the things for which we might wonder if they have a
+/// vtable during codegen.
+///
+/// This is not for _computing_ whether the thing has a vtable, it is for
+/// looking up the results of the HasVtableAnalysis's computations for a
+/// specific thing.
+pub trait HasVtable {
+
+ /// Implementations can define this type to get access to any extra
+ /// information required to determine whether they have vtable. If
+ /// extra information is unneeded, then this should simply be the unit type.
+ type Extra;
+
+ /// Return `true` if this thing has vtable, `false` otherwise.
+ fn has_vtable(&self, ctx: &BindgenContext, extra: &Self::Extra) -> bool;
+}
diff --git a/src/ir/analysis/mod.rs b/src/ir/analysis/mod.rs
index 5fe6785b..11467438 100644
--- a/src/ir/analysis/mod.rs
+++ b/src/ir/analysis/mod.rs
@@ -42,6 +42,9 @@ mod template_params;
pub use self::template_params::UsedTemplateParameters;
mod derive_debug;
pub use self::derive_debug::CannotDeriveDebug;
+mod has_vtable;
+pub use self::has_vtable::HasVtableAnalysis;
+pub use self::has_vtable::HasVtable;
use std::fmt;
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
index 0960ee11..327711fe 100644
--- a/src/ir/comp.rs
+++ b/src/ir/comp.rs
@@ -701,7 +701,7 @@ impl FieldMethods for FieldData {
}
}
-impl CanDeriveDefault for Field {
+impl<'a> CanDeriveDefault<'a> for Field {
type Extra = ();
fn can_derive_default(&self, ctx: &BindgenContext, _: ()) -> bool {
@@ -819,7 +819,7 @@ pub struct CompInfo {
/// Whether this type should generate an vtable (TODO: Should be able to
/// look at the virtual methods and ditch this field).
- has_vtable: bool,
+ has_own_virtual_method: bool,
/// Whether this type has destructor.
has_destructor: bool,
@@ -870,7 +870,7 @@ impl CompInfo {
base_members: vec![],
inner_types: vec![],
inner_vars: vec![],
- has_vtable: false,
+ has_own_virtual_method: false,
has_destructor: false,
has_nonempty_base: false,
has_non_type_template_params: false,
@@ -883,10 +883,10 @@ impl CompInfo {
}
/// Is this compound type unsized?
- pub fn is_unsized(&self, ctx: &BindgenContext) -> bool {
- !self.has_vtable(ctx) && self.fields().is_empty() &&
+ 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)
+ ctx.resolve_type(base.ty).canonical_type(ctx).is_unsized(ctx, &base.ty)
})
}
@@ -964,13 +964,10 @@ impl CompInfo {
self.has_non_type_template_params
}
- /// Does this type have a virtual table?
- pub fn has_vtable(&self, ctx: &BindgenContext) -> bool {
- self.has_vtable ||
- self.base_members().iter().any(|base| {
- ctx.resolve_type(base.ty)
- .has_vtable(ctx)
- })
+ /// Do we see a virtual function during parsing?
+ /// Get the has_own_virtual_method boolean.
+ pub fn has_own_virtual_method(&self) -> bool {
+ return self.has_own_virtual_method;
}
/// Get this type's set of methods.
@@ -1169,7 +1166,7 @@ impl CompInfo {
}
CXCursor_CXXBaseSpecifier => {
let is_virtual_base = cur.is_virtual_base();
- ci.has_vtable |= is_virtual_base;
+ ci.has_own_virtual_method |= is_virtual_base;
let kind = if is_virtual_base {
BaseKind::Virtual
@@ -1192,7 +1189,7 @@ impl CompInfo {
debug_assert!(!(is_static && is_virtual), "How?");
ci.has_destructor |= cur.kind() == CXCursor_Destructor;
- ci.has_vtable |= is_virtual;
+ ci.has_own_virtual_method |= is_virtual;
// This used to not be here, but then I tried generating
// stylo bindings with this (without path filters), and
@@ -1335,8 +1332,8 @@ impl CompInfo {
/// Returns whether this type needs an explicit vtable because it has
/// virtual methods and none of its base classes has already a vtable.
- pub fn needs_explicit_vtable(&self, ctx: &BindgenContext) -> bool {
- self.has_vtable(ctx) &&
+ pub fn needs_explicit_vtable(&self, ctx: &BindgenContext, item: &Item) -> bool {
+ ctx.lookup_item_id_has_vtable(&item.id()) &&
!self.base_members.iter().any(|base| {
// NB: Ideally, we could rely in all these types being `comp`, and
// life would be beautiful.
@@ -1347,7 +1344,7 @@ impl CompInfo {
ctx.resolve_type(base.ty)
.canonical_type(ctx)
.as_comp()
- .map_or(false, |ci| ci.has_vtable(ctx))
+ .map_or(false, |_| ctx.lookup_item_id_has_vtable(&base.ty))
})
}
@@ -1368,7 +1365,7 @@ impl DotAttributes for CompInfo {
{
writeln!(out, "<tr><td>CompKind</td><td>{:?}</td></tr>", self.kind)?;
- if self.has_vtable {
+ if self.has_own_virtual_method {
writeln!(out, "<tr><td>has_vtable</td><td>true</td></tr>")?;
}
@@ -1424,12 +1421,12 @@ impl TemplateParameters for CompInfo {
}
}
-impl CanDeriveDefault for CompInfo {
- type Extra = Option<Layout>;
+impl<'a> CanDeriveDefault<'a> for CompInfo {
+ type Extra = (&'a Item, Option<Layout>);
fn can_derive_default(&self,
ctx: &BindgenContext,
- layout: Option<Layout>)
+ (item, layout): (&Item, Option<Layout>))
-> bool {
// We can reach here recursively via template parameters of a member,
// for example.
@@ -1452,8 +1449,8 @@ impl CanDeriveDefault for CompInfo {
self.detect_derive_default_cycle.set(true);
- let can_derive_default = !self.has_vtable(ctx) &&
- !self.needs_explicit_vtable(ctx) &&
+ let can_derive_default = !ctx.lookup_item_id_has_vtable(&item.id()) &&
+ !self.needs_explicit_vtable(ctx, item) &&
self.base_members
.iter()
.all(|base| base.ty.can_derive_default(ctx, ())) &&
diff --git a/src/ir/context.rs b/src/ir/context.rs
index 1f6580f0..3232e8e6 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -5,7 +5,7 @@ use super::int::IntKind;
use super::item::{IsOpaque, Item, ItemAncestors, ItemCanonicalPath, ItemSet};
use super::item_kind::ItemKind;
use super::module::{Module, ModuleKind};
-use super::analysis::{analyze, UsedTemplateParameters, CannotDeriveDebug};
+use super::analysis::{analyze, UsedTemplateParameters, CannotDeriveDebug, HasVtableAnalysis};
use super::template::{TemplateInstantiation, TemplateParameters};
use super::traversal::{self, Edge, ItemTraversal};
use super::ty::{FloatKind, Type, TypeKind};
@@ -47,7 +47,7 @@ impl CanDeriveDebug for ItemId {
}
}
-impl CanDeriveDefault for ItemId {
+impl<'a> CanDeriveDefault<'a> for ItemId {
type Extra = ();
fn can_derive_default(&self, ctx: &BindgenContext, _: ()) -> bool {
@@ -184,6 +184,12 @@ pub struct BindgenContext<'ctx> {
/// This is populated when we enter codegen by `compute_can_derive_debug`
/// and is always `None` before that and `Some` after.
cant_derive_debug: Option<HashSet<ItemId>>,
+
+ /// The set of (`ItemId's of`) types that has vtable.
+ ///
+ /// Populated when we enter codegen by `compute_has_vtable`; always `None`
+ /// before that and `Some` after.
+ have_vtable: Option<HashSet<ItemId>>,
}
/// A traversal of whitelisted items.
@@ -310,6 +316,7 @@ impl<'ctx> BindgenContext<'ctx> {
need_bitfield_allocation: Default::default(),
needs_mangling_hack: needs_mangling_hack,
cant_derive_debug: None,
+ have_vtable: None,
};
me.add_item(root_module, None, None);
@@ -780,6 +787,7 @@ impl<'ctx> BindgenContext<'ctx> {
// messes with them correctly.
self.assert_every_item_in_a_module();
+ self.compute_has_vtable();
self.find_used_template_parameters();
self.compute_cant_derive_debug();
@@ -847,6 +855,22 @@ impl<'ctx> BindgenContext<'ctx> {
}
}
+ /// Compute whether the type has vtable.
+ fn compute_has_vtable(&mut self) {
+ assert!(self.have_vtable.is_none());
+ self.have_vtable = Some(analyze::<HasVtableAnalysis>(self));
+ }
+
+ /// Look up whether the item with `id` has vtable or not.
+ pub fn lookup_item_id_has_vtable(&self, id: &ItemId) -> bool {
+ assert!(self.in_codegen_phase(),
+ "We only compute vtables when we enter codegen");
+
+ // Look up the computed value for whether the item with `id` has a
+ // vtable or not.
+ self.have_vtable.as_ref().unwrap().contains(id)
+ }
+
fn find_used_template_parameters(&mut self) {
if self.options.whitelist_recursively {
let used_params = analyze::<UsedTemplateParameters>(self);
diff --git a/src/ir/derive.rs b/src/ir/derive.rs
index 59548163..446d2435 100644
--- a/src/ir/derive.rs
+++ b/src/ir/derive.rs
@@ -90,7 +90,7 @@ pub trait CanDeriveCopy<'a> {
/// to be a recursive method that checks whether all the proper members can
/// derive default or not, because of the limit rust has on 32 items as max in the
/// array.
-pub trait CanDeriveDefault {
+pub trait CanDeriveDefault<'a> {
/// Implementations can define this type to get access to any extra
/// information required to determine whether they can derive `Default`. If
/// extra information is unneeded, then this should simply be the unit type.
diff --git a/src/ir/item.rs b/src/ir/item.rs
index 7f3afefb..b3a26bb7 100644
--- a/src/ir/item.rs
+++ b/src/ir/item.rs
@@ -14,6 +14,7 @@ use super::module::Module;
use super::template::{AsTemplateParam, TemplateParameters};
use super::traversal::{EdgeKind, Trace, Tracer};
use super::ty::{Type, TypeKind};
+use super::analysis::HasVtable;
use clang;
use clang_sys;
use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
@@ -277,7 +278,7 @@ impl CanDeriveDebug for Item {
}
}
-impl CanDeriveDefault for Item {
+impl<'a> CanDeriveDefault<'a> for Item {
type Extra = ();
fn can_derive_default(&self, ctx: &BindgenContext, _: ()) -> bool {
@@ -289,7 +290,7 @@ impl CanDeriveDefault for Item {
.map_or(false,
|l| l.opaque().can_derive_default(ctx, ()))
} else {
- ty.can_derive_default(ctx, ())
+ ty.can_derive_default(ctx, self)
}
}
_ => false,
@@ -947,6 +948,22 @@ impl IsOpaque for Item {
}
}
+impl HasVtable for ItemId {
+ type Extra = ();
+
+ fn has_vtable(&self, ctx: &BindgenContext, _: &()) -> bool {
+ ctx.lookup_item_id_has_vtable(self)
+ }
+}
+
+impl HasVtable for Item {
+ type Extra = ();
+
+ fn has_vtable(&self, ctx: &BindgenContext, _: &()) -> bool {
+ ctx.lookup_item_id_has_vtable(&self.id())
+ }
+}
+
/// A set of items.
pub type ItemSet = BTreeSet<ItemId>;
diff --git a/src/ir/layout.rs b/src/ir/layout.rs
index 91dd9d6c..03496ad0 100644
--- a/src/ir/layout.rs
+++ b/src/ir/layout.rs
@@ -111,7 +111,7 @@ impl CanTriviallyDeriveDebug for Opaque {
}
}
-impl CanDeriveDefault for Opaque {
+impl<'a> CanDeriveDefault<'a> for Opaque {
type Extra = ();
fn can_derive_default(&self, _: &BindgenContext, _: ()) -> bool {
diff --git a/src/ir/template.rs b/src/ir/template.rs
index 25d1d438..6147365e 100644
--- a/src/ir/template.rs
+++ b/src/ir/template.rs
@@ -292,11 +292,6 @@ impl TemplateInstantiation {
Some(TemplateInstantiation::new(template_definition, template_args))
}
- /// Does this instantiation have a vtable?
- pub fn has_vtable(&self, ctx: &BindgenContext) -> bool {
- ctx.resolve_type(self.definition).has_vtable(ctx)
- }
-
/// Does this instantiation have a destructor?
pub fn has_destructor(&self, ctx: &BindgenContext) -> bool {
ctx.resolve_type(self.definition).has_destructor(ctx) ||
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index 5cbc4cf6..b189ceac 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -237,19 +237,6 @@ impl Type {
})
}
- /// Whether this type has a vtable.
- pub fn has_vtable(&self, ctx: &BindgenContext) -> bool {
- // FIXME: Can we do something about template parameters? Huh...
- match self.kind {
- TypeKind::TemplateAlias(t, _) |
- TypeKind::Alias(t) |
- TypeKind::ResolvedTypeRef(t) => ctx.resolve_type(t).has_vtable(ctx),
- TypeKind::Comp(ref info) => info.has_vtable(ctx),
- TypeKind::TemplateInstantiation(ref inst) => inst.has_vtable(ctx),
- _ => false,
- }
- }
-
/// Returns whether this type has a destructor.
pub fn has_destructor(&self, ctx: &BindgenContext) -> bool {
match self.kind {
@@ -547,10 +534,10 @@ impl CanDeriveDebug for Type {
}
}
-impl CanDeriveDefault for Type {
- type Extra = ();
+impl<'a> CanDeriveDefault<'a> for Type {
+ type Extra = &'a Item;
- fn can_derive_default(&self, ctx: &BindgenContext, _: ()) -> bool {
+ fn can_derive_default(&self, ctx: &BindgenContext, item: &Item) -> bool {
match self.kind {
TypeKind::Array(t, len) => {
len <= RUST_DERIVE_IN_ARRAY_LIMIT &&
@@ -560,7 +547,7 @@ impl CanDeriveDefault for Type {
TypeKind::TemplateAlias(t, _) |
TypeKind::Alias(t) => t.can_derive_default(ctx, ()),
TypeKind::Comp(ref info) => {
- info.can_derive_default(ctx, self.layout(ctx))
+ info.can_derive_default(ctx, (&item, self.layout(ctx)))
}
TypeKind::Opaque => {
self.layout
@@ -745,23 +732,24 @@ impl Type {
/// derive whether we should generate a dummy `_address` field for structs,
/// to comply to the C and C++ layouts, that specify that every type needs
/// to be addressable.
- pub fn is_unsized(&self, ctx: &BindgenContext) -> bool {
+ pub fn is_unsized(&self, ctx: &BindgenContext, itemid: &ItemId) -> bool {
debug_assert!(ctx.in_codegen_phase(), "Not yet");
match self.kind {
TypeKind::Void => true,
- TypeKind::Comp(ref ci) => ci.is_unsized(ctx),
+ 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)
+ size == 0 || ctx.resolve_type(inner).is_unsized(ctx, &inner)
}
TypeKind::ResolvedTypeRef(inner) |
TypeKind::Alias(inner) |
TypeKind::TemplateAlias(inner, _) => {
- ctx.resolve_type(inner).is_unsized(ctx)
+ ctx.resolve_type(inner).is_unsized(ctx, &inner)
}
TypeKind::TemplateInstantiation(ref inst) => {
- ctx.resolve_type(inst.template_definition()).is_unsized(ctx)
+ let definition = inst.template_definition();
+ ctx.resolve_type(definition).is_unsized(ctx, &definition)
}
TypeKind::Named |
TypeKind::Int(..) |