diff options
author | zzhu <zzhu@mozilla.com> | 2017-07-26 18:25:32 -0700 |
---|---|---|
committer | zzhu <zzhu@mozilla.com> | 2017-07-27 16:46:38 -0700 |
commit | 0231a21a98f49064d6bb58734366fdd660ba69c7 (patch) | |
tree | 122f54bab45374c08e0cb74b617dae2c60ff53d6 /src | |
parent | 0fab51e501f45727169516f605de31e7e1d19a62 (diff) |
can derive default analysis
Diffstat (limited to 'src')
-rw-r--r-- | src/codegen/mod.rs | 2 | ||||
-rw-r--r-- | src/ir/analysis/derive_default.rs | 360 | ||||
-rw-r--r-- | src/ir/analysis/mod.rs | 2 | ||||
-rw-r--r-- | src/ir/comp.rs | 69 | ||||
-rw-r--r-- | src/ir/context.rs | 36 | ||||
-rw-r--r-- | src/ir/derive.rs | 20 | ||||
-rw-r--r-- | src/ir/item.rs | 20 | ||||
-rw-r--r-- | src/ir/layout.rs | 8 | ||||
-rw-r--r-- | src/ir/ty.rs | 42 |
9 files changed, 416 insertions, 143 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 4ae0bfeb..637e3a65 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1418,7 +1418,7 @@ impl CodeGenerator for CompInfo { derives.push("Debug"); } - if item.can_derive_default(ctx, ()) { + if item.can_derive_default(ctx) { derives.push("Default"); } else { needs_default_impl = ctx.options().derive_default; diff --git a/src/ir/analysis/derive_default.rs b/src/ir/analysis/derive_default.rs new file mode 100644 index 00000000..de74177d --- /dev/null +++ b/src/ir/analysis/derive_default.rs @@ -0,0 +1,360 @@ +//! Determining which types for which we can emit `#[derive(Default)]`. + +use super::{ConstrainResult, MonotoneFramework, HasVtable}; +use std::collections::HashSet; +use std::collections::HashMap; +use ir::context::{BindgenContext, ItemId}; +use ir::item::IsOpaque; +use ir::traversal::EdgeKind; +use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT; +use ir::ty::TypeKind; +use ir::comp::Field; +use ir::comp::FieldMethods; +use ir::derive::CanTriviallyDeriveDefault; +use ir::comp::CompKind; +use ir::traversal::Trace; +use ir::item::ItemSet; + +/// An analysis that finds for each IR item whether default cannot be derived. +/// +/// We use the monotone constraint function `cannot_derive_default`, defined as +/// follows: +/// +/// * If T is Opaque and layout of the type is known, get this layout as opaque +/// type and check whether it can be derived using trivial checks. +/// * If T is Array type, default cannot be derived if the length of the array is +/// larger than the limit or the type of data the array contains cannot derive +/// default. +/// * If T is a type alias, a templated alias or an indirection to another type, +/// default cannot be derived if the type T refers to cannot be derived default. +/// * If T is a compound type, default cannot be derived if any of its base member +/// or field cannot be derived default. +#[derive(Debug, Clone)] +pub struct CannotDeriveDefault<'ctx, 'gen> + where 'gen: 'ctx +{ + ctx: &'ctx BindgenContext<'gen>, + + // The incremental result of this analysis's computation. Everything in this + // set cannot derive debug. + cannot_derive_default: HashSet<ItemId>, + + // Dependencies saying that if a key ItemId has been inserted into the + // `cannot_derive_default` 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 + // can derive debug or not. + dependencies: HashMap<ItemId, Vec<ItemId>>, +} + +impl<'ctx, 'gen> CannotDeriveDefault<'ctx, 'gen> { + fn consider_edge(kind: EdgeKind) -> bool { + match kind { + // These are the only edges that can affect whether a type can derive + // debug or not. + EdgeKind::BaseMember | + EdgeKind::Field | + EdgeKind::TypeReference | + EdgeKind::VarType | + EdgeKind::TemplateArgument | + EdgeKind::TemplateDeclaration | + EdgeKind::TemplateParameterDefinition => true, + + EdgeKind::Constructor | + EdgeKind::Destructor | + EdgeKind::FunctionReturn | + EdgeKind::FunctionParameter | + EdgeKind::InnerType | + EdgeKind::InnerVar | + EdgeKind::Method => false, + EdgeKind::Generic => false, + } + } + + fn insert(&mut self, id: ItemId) -> ConstrainResult { + trace!("inserting {:?} into the cannot_derive_default set", id); + + let was_not_already_in_set = self.cannot_derive_default.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 CannotDeriveDefault<'ctx, 'gen> { + type Node = ItemId; + type Extra = &'ctx BindgenContext<'gen>; + type Output = HashSet<ItemId>; + + fn new(ctx: &'ctx BindgenContext<'gen>) -> CannotDeriveDefault<'ctx, 'gen> { + let mut dependencies = HashMap::new(); + let cannot_derive_default = HashSet::new(); + + let whitelisted_items: HashSet<_> = ctx.whitelisted_items() + .iter() + .cloned() + .collect(); + + let whitelisted_and_blacklisted_items: ItemSet = whitelisted_items.iter() + .cloned() + .flat_map(|i| { + let mut reachable = vec![i]; + i.trace(ctx, &mut |s, _| { + reachable.push(s); + }, &()); + reachable + }) + .collect(); + + for item in whitelisted_and_blacklisted_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); + } + }, &()); + } + } + + CannotDeriveDefault { + ctx, + cannot_derive_default, + dependencies, + } + } + + fn initial_worklist(&self) -> Vec<ItemId> { + self.ctx.whitelisted_items().iter().cloned().collect() + } + + fn constrain(&mut self, id: ItemId) -> ConstrainResult { + trace!("constrain: {:?}", id); + + if self.cannot_derive_default.contains(&id) { + trace!(" already know it cannot derive Default"); + return ConstrainResult::Same; + } + + let item = self.ctx.resolve_item(id); + let ty = match item.as_type() { + Some(ty) => ty, + None => { + trace!(" not a type; ignoring"); + return ConstrainResult::Same; + } + }; + + if ty.is_opaque(self.ctx, item) { + let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| { + l.opaque().can_trivially_derive_default() + }); + return if layout_can_derive { + trace!(" we can trivially derive Default for the layout"); + ConstrainResult::Same + } else { + trace!(" we cannot derive Default for the layout"); + self.insert(id) + }; + } + + if ty.layout(self.ctx).map_or(false, |l| l.align > RUST_DERIVE_IN_ARRAY_LIMIT) { + // We have to be conservative: the struct *could* have enough + // padding that we emit an array that is longer than + // `RUST_DERIVE_IN_ARRAY_LIMIT`. If we moved padding calculations + // into the IR and computed them before this analysis, then we could + // be precise rather than conservative here. + return self.insert(id); + } + + match *ty.kind() { + // Handle the simple cases. These can derive debug without further + // information. + TypeKind::Function(..) | + TypeKind::Int(..) | + TypeKind::Float(..) | + TypeKind::Complex(..) => { + trace!(" simple type that can always derive Default"); + ConstrainResult::Same + } + + TypeKind::Void | + TypeKind::Named | + TypeKind::Reference(..) | + TypeKind::NullPtr | + TypeKind::Pointer(..) | + TypeKind::BlockPointer | + TypeKind::ObjCId | + TypeKind::ObjCSel | + TypeKind::ObjCInterface(..) | + TypeKind::Enum(..) => { + trace!(" types that always cannot derive Default"); + self.insert(id) + } + + TypeKind::Array(t, len) => { + if self.cannot_derive_default.contains(&t) { + trace!(" arrays of T for which we cannot derive Default \ + also cannot derive Default"); + return self.insert(id); + } + + if len <= RUST_DERIVE_IN_ARRAY_LIMIT { + trace!(" array is small enough to derive Default"); + ConstrainResult::Same + } else { + trace!(" array is too large to derive Default"); + self.insert(id) + } + } + + TypeKind::ResolvedTypeRef(t) | + TypeKind::TemplateAlias(t, _) | + TypeKind::Alias(t) => { + if self.cannot_derive_default.contains(&t) { + trace!(" aliases and type refs to T which cannot derive \ + Default also cannot derive Default"); + self.insert(id) + } else { + trace!(" aliases and type refs to T which can derive \ + Default can also derive Default"); + ConstrainResult::Same + } + } + + TypeKind::Comp(ref info) => { + assert!( + !info.has_non_type_template_params(), + "The early ty.is_opaque check should have handled this case" + ); + + if info.kind() == CompKind::Union { + if self.ctx.options().unstable_rust { + trace!(" cannot derive Default for Rust unions"); + return self.insert(id); + } + + if ty.layout(self.ctx) + .map_or(true, + |l| l.opaque().can_trivially_derive_default()) { + trace!(" union layout can trivially derive Default"); + return ConstrainResult::Same; + } else { + trace!(" union layout cannot derive Default"); + return self.insert(id); + } + } + + if item.has_vtable(self.ctx) { + trace!(" comp with vtable cannot derive Default"); + return self.insert(id); + } + + let bases_cannot_derive = info.base_members() + .iter() + .any(|base| self.cannot_derive_default.contains(&base.ty)); + if bases_cannot_derive { + trace!(" base members cannot derive Default, so we can't \ + either"); + return self.insert(id); + } + + let fields_cannot_derive = info.fields() + .iter() + .any(|f| { + match *f { + Field::DataMember(ref data) => { + self.cannot_derive_default.contains(&data.ty()) + } + Field::Bitfields(ref bfu) => { + bfu.bitfields() + .iter().any(|b| { + self.cannot_derive_default.contains(&b.ty()) + }) + } + } + }); + if fields_cannot_derive { + trace!(" fields cannot derive Default, so we can't either"); + return self.insert(id); + } + + trace!(" comp can derive Default"); + ConstrainResult::Same + } + + TypeKind::TemplateInstantiation(ref template) => { + if self.ctx.whitelisted_items().contains(&template.template_definition()) { + let args_cannot_derive = template.template_arguments() + .iter() + .any(|arg| self.cannot_derive_default.contains(&arg)); + if args_cannot_derive { + trace!(" template args cannot derive Default, so \ + insantiation can't either"); + return self.insert(id); + } + + assert!( + !template.template_definition().is_opaque(self.ctx, &()), + "The early ty.is_opaque check should have handled this case" + ); + let def_cannot_derive = self.cannot_derive_default + .contains(&template.template_definition()); + if def_cannot_derive { + trace!(" template definition cannot derive Default, so \ + insantiation can't either"); + return self.insert(id); + } + + trace!(" template instantiation can derive Default"); + ConstrainResult::Same + } else { + trace!(" blacklisted template instantiation cannot derive default"); + return self.insert(id); + } + } + + TypeKind::Opaque => { + unreachable!( + "The early ty.is_opaque check should have handled this case" + ) + } + + TypeKind::UnresolvedTypeRef(..) => { + unreachable!( + "Type with unresolved type ref can't reach derive default" + ) + } + } + } + + 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<CannotDeriveDefault<'ctx, 'gen>> for HashSet<ItemId> { + fn from(analysis: CannotDeriveDefault<'ctx, 'gen>) -> Self { + analysis.cannot_derive_default + } +} diff --git a/src/ir/analysis/mod.rs b/src/ir/analysis/mod.rs index 8a00ecce..ec150ec4 100644 --- a/src/ir/analysis/mod.rs +++ b/src/ir/analysis/mod.rs @@ -45,6 +45,8 @@ pub use self::derive_debug::CannotDeriveDebug; mod has_vtable; pub use self::has_vtable::HasVtableAnalysis; pub use self::has_vtable::HasVtable; +mod derive_default; +pub use self::derive_default::CannotDeriveDefault; use ir::context::{BindgenContext, ItemId}; use ir::traversal::{EdgeKind, Trace}; diff --git a/src/ir/comp.rs b/src/ir/comp.rs index c2e9bd8f..b3cb3ca5 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -2,12 +2,12 @@ use super::annotations::Annotations; use super::context::{BindgenContext, ItemId}; -use super::derive::{CanDeriveCopy, CanDeriveDefault}; +use super::derive::CanDeriveCopy; use super::dot::DotAttributes; use super::item::{IsOpaque, Item}; use super::layout::Layout; use super::traversal::{EdgeKind, Trace, Tracer}; -use super::ty::RUST_DERIVE_IN_ARRAY_LIMIT; +// use super::ty::RUST_DERIVE_IN_ARRAY_LIMIT; use super::template::TemplateParameters; use clang; use codegen::struct_layout::{align_to, bytes_from_bits_pow2}; @@ -702,19 +702,6 @@ impl FieldMethods for FieldData { } } -impl<'a> CanDeriveDefault<'a> for Field { - type Extra = (); - - fn can_derive_default(&self, ctx: &BindgenContext, _: ()) -> bool { - match *self { - Field::DataMember(ref data) => data.ty.can_derive_default(ctx, ()), - Field::Bitfields(BitfieldUnit { ref bitfields, .. }) => bitfields.iter().all(|b| { - b.ty().can_derive_default(ctx, ()) - }), - } - } -} - impl<'a> CanDeriveCopy<'a> for Field { type Extra = (); @@ -845,10 +832,6 @@ pub struct CompInfo { /// and pray, or behave as an opaque type. found_unknown_attr: bool, - /// Used to detect if we've run in a can_derive_default cycle while cycling - /// around the template arguments. - detect_derive_default_cycle: Cell<bool>, - /// Used to detect if we've run in a has_destructor cycle while cycling /// around the template arguments. detect_has_destructor_cycle: Cell<bool>, @@ -877,7 +860,6 @@ impl CompInfo { has_non_type_template_params: false, packed: false, found_unknown_attr: false, - detect_derive_default_cycle: Cell::new(false), detect_has_destructor_cycle: Cell::new(false), is_forward_declaration: false, } @@ -1422,53 +1404,6 @@ impl TemplateParameters for CompInfo { } } -impl<'a> CanDeriveDefault<'a> for CompInfo { - type Extra = (&'a Item, Option<Layout>); - - fn can_derive_default(&self, - ctx: &BindgenContext, - (item, layout): (&Item, Option<Layout>)) - -> bool { - // We can reach here recursively via template parameters of a member, - // for example. - if self.detect_derive_default_cycle.get() { - warn!("Derive default cycle detected!"); - return true; - } - - if layout.map_or(false, |l| l.align > RUST_DERIVE_IN_ARRAY_LIMIT) { - return false; - } - - if self.kind == CompKind::Union { - if ctx.options().unstable_rust { - return false; - } - - return layout.map_or(true, |l| l.opaque().can_derive_default(ctx, ())); - } - - if self.has_non_type_template_params { - return layout.map_or(true, |l| l.opaque().can_derive_default(ctx, ())); - } - - self.detect_derive_default_cycle.set(true); - - 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, ())) && - self.fields() - .iter() - .all(|f| f.can_derive_default(ctx, ())); - - self.detect_derive_default_cycle.set(false); - - can_derive_default - } -} - impl<'a> CanDeriveCopy<'a> for CompInfo { type Extra = (&'a Item, Option<Layout>); diff --git a/src/ir/context.rs b/src/ir/context.rs index 6c38e8e7..d9281a23 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -5,7 +5,8 @@ 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, HasVtableAnalysis}; +use super::analysis::{analyze, UsedTemplateParameters, CannotDeriveDebug, HasVtableAnalysis, + CannotDeriveDefault}; use super::template::{TemplateInstantiation, TemplateParameters}; use super::traversal::{self, Edge, ItemTraversal}; use super::ty::{FloatKind, Type, TypeKind}; @@ -45,11 +46,9 @@ impl CanDeriveDebug for ItemId { } } -impl<'a> CanDeriveDefault<'a> for ItemId { - type Extra = (); - - fn can_derive_default(&self, ctx: &BindgenContext, _: ()) -> bool { - ctx.resolve_item(*self).can_derive_default(ctx, ()) +impl CanDeriveDefault for ItemId { + fn can_derive_default(&self, ctx: &BindgenContext) -> bool { + ctx.options().derive_default && ctx.lookup_item_id_can_derive_default(*self) } } @@ -183,6 +182,12 @@ pub struct BindgenContext<'ctx> { /// and is always `None` before that and `Some` after. cant_derive_debug: Option<HashSet<ItemId>>, + /// The set of (`ItemId`s of) types that can't derive default. + /// + /// This is populated when we enter codegen by `compute_can_derive_default` + /// and is always `None` before that and `Some` after. + cannot_derive_default: Option<HashSet<ItemId>>, + /// The set of (`ItemId's of`) types that has vtable. /// /// Populated when we enter codegen by `compute_has_vtable`; always `None` @@ -314,6 +319,7 @@ impl<'ctx> BindgenContext<'ctx> { need_bitfield_allocation: Default::default(), needs_mangling_hack: needs_mangling_hack, cant_derive_debug: None, + cannot_derive_default: None, have_vtable: None, }; @@ -788,6 +794,7 @@ impl<'ctx> BindgenContext<'ctx> { self.compute_has_vtable(); self.find_used_template_parameters(); self.compute_cant_derive_debug(); + self.compute_cannot_derive_default(); let ret = cb(self); self.gen_ctx = None; @@ -1770,6 +1777,23 @@ impl<'ctx> BindgenContext<'ctx> { // derive debug or not. !self.cant_derive_debug.as_ref().unwrap().contains(&id) } + + /// Compute whether we can derive default. + fn compute_cannot_derive_default(&mut self) { + assert!(self.cannot_derive_default.is_none()); + self.cannot_derive_default = Some(analyze::<CannotDeriveDefault>(self)); + } + + /// Look up whether the item with `id` can + /// derive default or not. + pub fn lookup_item_id_can_derive_default(&self, id: ItemId) -> bool { + assert!(self.in_codegen_phase(), + "We only compute can_derive_default when we enter codegen"); + + // Look up the computed value for whether the item with `id` can + // derive default or not. + !self.cannot_derive_default.as_ref().unwrap().contains(&id) + } } /// A builder struct for configuring item resolution options. diff --git a/src/ir/derive.rs b/src/ir/derive.rs index 3334618c..5bc9cfdd 100644 --- a/src/ir/derive.rs +++ b/src/ir/derive.rs @@ -82,16 +82,22 @@ 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<'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. - type Extra; +pub trait CanDeriveDefault { /// Return `true` if `Default` can be derived for this thing, `false` /// otherwise. fn can_derive_default(&self, - ctx: &BindgenContext, - extra: Self::Extra) + ctx: &BindgenContext) -> bool; } + +/// A trait that encapsulates the logic for whether or not we can derive `Default`. +/// The difference between this trait and the CanDeriveDefault is that the type +/// implementing this trait cannot use recursion or lookup result from fix point +/// analysis. It's a helper trait for fix point analysis. +pub trait CanTriviallyDeriveDefault { + + /// Return `true` if `Default` can be derived for this thing, `false` + /// otherwise. + fn can_trivially_derive_default(&self) -> bool; +} diff --git a/src/ir/item.rs b/src/ir/item.rs index 92954a8f..8a210e38 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -276,23 +276,9 @@ impl CanDeriveDebug for Item { } } -impl<'a> CanDeriveDefault<'a> for Item { - type Extra = (); - - fn can_derive_default(&self, ctx: &BindgenContext, _: ()) -> bool { - ctx.options().derive_default && - match self.kind { - ItemKind::Type(ref ty) => { - if self.is_opaque(ctx, &()) { - ty.layout(ctx) - .map_or(false, - |l| l.opaque().can_derive_default(ctx, ())) - } else { - ty.can_derive_default(ctx, self) - } - } - _ => false, - } +impl CanDeriveDefault for Item { + fn can_derive_default(&self, ctx: &BindgenContext) -> bool { + ctx.options().derive_default && ctx.lookup_item_id_can_derive_default(self.id()) } } diff --git a/src/ir/layout.rs b/src/ir/layout.rs index 03496ad0..b0ec171a 100644 --- a/src/ir/layout.rs +++ b/src/ir/layout.rs @@ -1,7 +1,8 @@ //! Intermediate representation for the physical layout of some type. use super::context::BindgenContext; -use super::derive::{CanDeriveCopy, CanTriviallyDeriveDebug, CanDeriveDefault}; +use super::derive::{CanDeriveCopy, CanTriviallyDeriveDebug, + CanTriviallyDeriveDefault}; use super::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, Type, TypeKind}; use clang; use std::{cmp, mem}; @@ -111,10 +112,9 @@ impl CanTriviallyDeriveDebug for Opaque { } } -impl<'a> CanDeriveDefault<'a> for Opaque { - type Extra = (); +impl CanTriviallyDeriveDefault for Opaque { - fn can_derive_default(&self, _: &BindgenContext, _: ()) -> bool { + fn can_trivially_derive_default(&self) -> bool { self.array_size() .map_or(false, |size| size <= RUST_DERIVE_IN_ARRAY_LIMIT) } diff --git a/src/ir/ty.rs b/src/ir/ty.rs index 1c213569..b3de1f03 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -2,7 +2,7 @@ use super::comp::CompInfo; use super::context::{BindgenContext, ItemId}; -use super::derive::{CanDeriveCopy, CanDeriveDefault}; +use super::derive::CanDeriveCopy; use super::dot::DotAttributes; use super::enum_ty::Enum; use super::function::FunctionSig; @@ -526,46 +526,6 @@ impl TemplateParameters for TypeKind { } } -impl<'a> CanDeriveDefault<'a> for Type { - type Extra = &'a Item; - - fn can_derive_default(&self, ctx: &BindgenContext, item: &Item) -> bool { - match self.kind { - TypeKind::Array(t, len) => { - len <= RUST_DERIVE_IN_ARRAY_LIMIT && - t.can_derive_default(ctx, ()) - } - TypeKind::ResolvedTypeRef(t) | - TypeKind::TemplateAlias(t, _) | - TypeKind::Alias(t) => t.can_derive_default(ctx, ()), - TypeKind::Comp(ref info) => { - info.can_derive_default(ctx, (&item, self.layout(ctx))) - } - TypeKind::Opaque => { - self.layout - .map_or(true, |l| l.opaque().can_derive_default(ctx, ())) - } - TypeKind::Void | - TypeKind::Named | - TypeKind::TemplateInstantiation(..) | - TypeKind::Reference(..) | - TypeKind::NullPtr | - TypeKind::Pointer(..) | - TypeKind::BlockPointer | - TypeKind::ObjCId | - TypeKind::ObjCSel | - TypeKind::ObjCInterface(..) | - TypeKind::Enum(..) => false, - - TypeKind::Function(..) | - TypeKind::Int(..) | - TypeKind::Float(..) | - TypeKind::Complex(..) => true, - TypeKind::UnresolvedTypeRef(..) => unreachable!(), - } - } -} - impl<'a> CanDeriveCopy<'a> for Type { type Extra = &'a Item; |