diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/codegen/impl_debug.rs (renamed from src/codegen/derive_debug.rs) | 0 | ||||
-rw-r--r-- | src/codegen/mod.rs | 39 | ||||
-rw-r--r-- | src/ir/analysis/derive_partial_eq_or_partial_ord.rs | 89 | ||||
-rw-r--r-- | src/ir/comp.rs | 32 | ||||
-rw-r--r-- | src/ir/context.rs | 25 | ||||
-rw-r--r-- | src/ir/derive.rs | 121 | ||||
-rw-r--r-- | src/ir/function.rs | 54 | ||||
-rw-r--r-- | src/ir/layout.rs | 29 | ||||
-rw-r--r-- | src/ir/objc.rs | 14 | ||||
-rw-r--r-- | src/lib.rs | 22 |
10 files changed, 211 insertions, 214 deletions
diff --git a/src/codegen/derive_debug.rs b/src/codegen/impl_debug.rs index 7ef108da..7ef108da 100644 --- a/src/codegen/derive_debug.rs +++ b/src/codegen/impl_debug.rs diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 49187125..895422b0 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1,4 +1,4 @@ -mod derive_debug; +mod impl_debug; mod error; mod helpers; pub mod struct_layout; @@ -865,24 +865,6 @@ impl CodeGenerator for TemplateInstantiation { } } -/// Generates an infinite number of anonymous field names. -struct AnonFieldNames(usize); - -impl Default for AnonFieldNames { - fn default() -> AnonFieldNames { - AnonFieldNames(0) - } -} - -impl Iterator for AnonFieldNames { - type Item = String; - - fn next(&mut self) -> Option<String> { - self.0 += 1; - Some(format!("__bindgen_anon_{}", self.0)) - } -} - /// Trait for implementing the code generation of a struct or union field. trait FieldCodegen<'a> { type Extra; @@ -894,7 +876,6 @@ trait FieldCodegen<'a> { codegen_depth: usize, accessor_kind: FieldAccessorKind, parent: &CompInfo, - anon_field_names: &mut AnonFieldNames, result: &mut CodegenResult, struct_layout: &mut StructLayoutTracker, fields: &mut F, @@ -915,7 +896,6 @@ impl<'a> FieldCodegen<'a> for Field { codegen_depth: usize, accessor_kind: FieldAccessorKind, parent: &CompInfo, - anon_field_names: &mut AnonFieldNames, result: &mut CodegenResult, struct_layout: &mut StructLayoutTracker, fields: &mut F, @@ -933,7 +913,6 @@ impl<'a> FieldCodegen<'a> for Field { codegen_depth, accessor_kind, parent, - anon_field_names, result, struct_layout, fields, @@ -948,7 +927,6 @@ impl<'a> FieldCodegen<'a> for Field { codegen_depth, accessor_kind, parent, - anon_field_names, result, struct_layout, fields, @@ -970,7 +948,6 @@ impl<'a> FieldCodegen<'a> for FieldData { codegen_depth: usize, accessor_kind: FieldAccessorKind, parent: &CompInfo, - anon_field_names: &mut AnonFieldNames, result: &mut CodegenResult, struct_layout: &mut StructLayoutTracker, fields: &mut F, @@ -1030,7 +1007,7 @@ impl<'a> FieldCodegen<'a> for FieldData { let field_name = self.name() .map(|name| ctx.rust_mangle(name).into_owned()) - .unwrap_or_else(|| anon_field_names.next().unwrap()); + .expect("Each field should have a name in codegen!"); let field_ident = ctx.rust_ident_raw(field_name.as_str()); if !parent.is_union() { @@ -1164,7 +1141,6 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { codegen_depth: usize, accessor_kind: FieldAccessorKind, parent: &CompInfo, - anon_field_names: &mut AnonFieldNames, result: &mut CodegenResult, struct_layout: &mut StructLayoutTracker, fields: &mut F, @@ -1213,7 +1189,6 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { codegen_depth, accessor_kind, parent, - anon_field_names, result, struct_layout, fields, @@ -1321,7 +1296,6 @@ impl<'a> FieldCodegen<'a> for Bitfield { _codegen_depth: usize, _accessor_kind: FieldAccessorKind, parent: &CompInfo, - _anon_field_names: &mut AnonFieldNames, _result: &mut CodegenResult, _struct_layout: &mut StructLayoutTracker, _fields: &mut F, @@ -1595,7 +1569,6 @@ impl CodeGenerator for CompInfo { let mut methods = vec![]; if !is_opaque { - let mut anon_field_names = AnonFieldNames::default(); let codegen_depth = item.codegen_depth(ctx); let fields_should_be_private = item.annotations().private_fields().unwrap_or(false); @@ -1609,7 +1582,6 @@ impl CodeGenerator for CompInfo { codegen_depth, struct_accessor_kind, self, - &mut anon_field_names, result, &mut struct_layout, &mut fields, @@ -1910,7 +1882,7 @@ impl CodeGenerator for CompInfo { } if needs_debug_impl { - let impl_ = derive_debug::gen_debug_impl( + let impl_ = impl_debug::gen_debug_impl( ctx, self.fields(), item, @@ -2454,7 +2426,10 @@ impl CodeGenerator for Enum { let repr = self.repr() .and_then(|repr| repr.try_to_rust_ty_or_opaque(ctx, &()).ok()) - .unwrap_or_else(|| helpers::ast_ty::raw_type(ctx, repr_name)); + .unwrap_or_else(|| { + let repr_name = ctx.rust_ident_raw(repr_name); + quote! { #repr_name } + }); let mut builder = EnumBuilder::new( &name, 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 1c3ab059..f34a256a 100644 --- a/src/ir/analysis/derive_partial_eq_or_partial_ord.rs +++ b/src/ir/analysis/derive_partial_eq_or_partial_ord.rs @@ -1,4 +1,5 @@ -//! Determining which types for which we can emit `#[derive(PartialEq)]`. +//! Determining which types for which we cannot emit `#[derive(PartialEq, +//! PartialOrd)]`. use super::{ConstrainResult, MonotoneFramework, generate_dependencies}; use ir::comp::CompKind; @@ -13,31 +14,39 @@ use ir::ty::TypeKind; use std::collections::HashMap; use std::collections::HashSet; -/// An analysis that finds for each IR item whether partialeq or partialord cannot be derived. +/// An analysis that finds for each IR item whether `PartialEq`/`PartialOrd` +/// cannot be derived. /// -/// We use the monotone constraint function `cannot_derive_partialeq_or_partialord`, defined as -/// follows: +/// We use the monotone constraint function +/// `cannot_derive_partialeq_or_partialord`, 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, partialeq or partialord cannot be derived if the length of -/// the array is larger than the limit or the type of data the array contains cannot derive -/// partialeq or partialord. +/// +/// * If T is Array type, `PartialEq` or partialord cannot be derived if the +/// length of the array is larger than the limit or the type of data the array +/// contains cannot derive `PartialEq`/`PartialOrd`. +/// /// * If T is a type alias, a templated alias or an indirection to another type, -/// partialeq or partialord cannot be derived if the type T refers to cannot be derived partialeq or partialord. -/// * If T is a compound type, partialeq or partialord cannot be derived if any of its base member -/// or field cannot be derived partialeq or partialord. -/// * If T is a pointer, T cannot be derived partialeq or partialord if T is a function pointer -/// and the function signature cannot be derived partialeq or partialord. +/// `PartialEq`/`PartialOrd` cannot be derived if the type T refers to cannot be +/// derived `PartialEq`/`PartialOrd`. +/// +/// * If T is a compound type, `PartialEq`/`PartialOrd` cannot be derived if any +/// of its base member or field cannot be derived `PartialEq`/`PartialOrd`. +/// +/// * If T is a pointer, T cannot be derived `PartialEq`/`PartialOrd` if T is a +/// function pointer and the function signature cannot be derived +/// `PartialEq`/`PartialOrd`. +/// /// * If T is an instantiation of an abstract template definition, T cannot be -/// derived partialeq or partialord if any of the template arguments or template definition -/// cannot derive partialeq or partialord. +/// derived `PartialEq`/`PartialOrd` if any of the template arguments or +/// template definition cannot derive `PartialEq`/`PartialOrd`. #[derive(Debug, Clone)] pub struct CannotDerivePartialEqOrPartialOrd<'ctx> { ctx: &'ctx BindgenContext, // The incremental result of this analysis's computation. Everything in this - // set cannot derive partialeq or partialord. + // set cannot derive `PartialEq`/`PartialOrd`. cannot_derive_partialeq_or_partialord: HashSet<ItemId>, // Dependencies saying that if a key ItemId has been inserted into the @@ -46,7 +55,7 @@ pub struct CannotDerivePartialEqOrPartialOrd<'ctx> { // // 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 partialeq or partialord. + // can derive `PartialEq`/`PartialOrd`. dependencies: HashMap<ItemId, Vec<ItemId>>, } @@ -54,7 +63,7 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> { fn consider_edge(kind: EdgeKind) -> bool { match kind { // These are the only edges that can affect whether a type can derive - // partialeq or partialord. + // `PartialEq`/`PartialOrd`. EdgeKind::BaseMember | EdgeKind::Field | EdgeKind::TypeReference | @@ -115,7 +124,7 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { trace!("constrain: {:?}", id); if self.cannot_derive_partialeq_or_partialord.contains(&id) { - trace!(" already know it cannot derive PartialEq or PartialOrd"); + trace!(" already know it cannot derive `PartialEq`/`PartialOrd`"); return ConstrainResult::Same; } @@ -140,10 +149,10 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { return if layout_can_derive && !(ty.is_union() && self.ctx.options().rust_features().untagged_union()) { - trace!(" we can trivially derive PartialEq or PartialOrd for the layout"); + trace!(" we can trivially derive `PartialEq`/`PartialOrd` for the layout"); ConstrainResult::Same } else { - trace!(" we cannot derive PartialEq or PartialOrd for the layout"); + trace!(" we cannot derive `PartialEq`/`PartialOrd` for the layout"); self.insert(id) }; } @@ -176,24 +185,24 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { TypeKind::ObjCInterface(..) | TypeKind::ObjCId | TypeKind::ObjCSel => { - trace!(" simple type that can always derive PartialEq or PartialOrd"); + trace!(" simple type that can always derive `PartialEq`/`PartialOrd`"); ConstrainResult::Same } TypeKind::Array(t, len) => { if self.cannot_derive_partialeq_or_partialord.contains(&t) { trace!( - " arrays of T for which we cannot derive PartialEq or PartialOrd \ - also cannot derive PartialEq or PartialOrd" + " arrays of T for which we cannot derive `PartialEq`/`PartialOrd` \ + also cannot derive `PartialEq`/`PartialOrd`" ); return self.insert(id); } if len <= RUST_DERIVE_IN_ARRAY_LIMIT { - trace!(" array is small enough to derive PartialEq or PartialOrd"); + trace!(" array is small enough to derive `PartialEq`/`PartialOrd`"); ConstrainResult::Same } else { - trace!(" array is too large to derive PartialEq or PartialOrd"); + trace!(" array is too large to derive `PartialEq`/`PartialOrd`"); self.insert(id) } } @@ -204,7 +213,7 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { if let TypeKind::Function(ref sig) = *inner_type.kind() { if !sig.can_trivially_derive_partialeq_or_partialord() { trace!( - " function pointer that can't trivially derive PartialEq or PartialOrd" + " function pointer that can't trivially derive `PartialEq`/`PartialOrd`" ); return self.insert(id); } @@ -216,11 +225,11 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { TypeKind::Function(ref sig) => { if !sig.can_trivially_derive_partialeq_or_partialord() { trace!( - " function that can't trivially derive PartialEq or PartialOrd" + " function that can't trivially derive `PartialEq`/`PartialOrd`" ); return self.insert(id); } - trace!(" function can derive PartialEq or PartialOrd"); + trace!(" function can derive `PartialEq`/`PartialOrd`"); ConstrainResult::Same } @@ -230,13 +239,13 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { if self.cannot_derive_partialeq_or_partialord.contains(&t) { trace!( " aliases and type refs to T which cannot derive \ - PartialEq or PartialOrd also cannot derive PartialEq or PartialOrd" + `PartialEq`/`PartialOrd` also cannot derive `PartialEq`/`PartialOrd`" ); self.insert(id) } else { trace!( " aliases and type refs to T which can derive \ - PartialEq or PartialOrd can also derive PartialEq or PartialOrd" + `PartialEq`/`PartialOrd` can also derive `PartialEq`/`PartialOrd`" ); ConstrainResult::Same } @@ -250,7 +259,7 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { if info.kind() == CompKind::Union { if self.ctx.options().rust_features().untagged_union() { - trace!(" cannot derive PartialEq or PartialOrd for Rust unions"); + trace!(" cannot derive `PartialEq`/`PartialOrd` for Rust unions"); return self.insert(id); } @@ -259,11 +268,11 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { }) { trace!( - " union layout can trivially derive PartialEq or PartialOrd" + " union layout can trivially derive `PartialEq`/`PartialOrd`" ); return ConstrainResult::Same; } else { - trace!(" union layout cannot derive PartialEq or PartialOrd"); + trace!(" union layout cannot derive `PartialEq`/`PartialOrd`"); return self.insert(id); } } @@ -275,7 +284,7 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { }); if bases_cannot_derive { trace!( - " base members cannot derive PartialEq or PartialOrd, so we can't \ + " base members cannot derive `PartialEq`/`PartialOrd`, so we can't \ either" ); return self.insert(id); @@ -312,7 +321,7 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { }); if fields_cannot_derive { trace!( - " fields cannot derive PartialEq or PartialOrd, so we can't either" + " fields cannot derive `PartialEq`/`PartialOrd`, so we can't either" ); return self.insert(id); } @@ -328,8 +337,8 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { }); if args_cannot_derive { trace!( - " template args cannot derive PartialEq or PartialOrd, so \ - insantiation can't either" + " template args cannot derive `PartialEq`/`PartialOrd`, so \ + insantiation can't either" ); return self.insert(id); } @@ -343,13 +352,13 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { ); if def_cannot_derive { trace!( - " template definition cannot derive PartialEq or PartialOrd, so \ - insantiation can't either" + " template definition cannot derive `PartialEq`/`PartialOrd`, so \ + insantiation can't either" ); return self.insert(id); } - trace!(" template instantiation can derive PartialEq or PartialOrd"); + trace!(" template instantiation can derive `PartialEq`/`PartialOrd`"); ConstrainResult::Same } diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 4c57a86b..fc17ab8f 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -666,6 +666,33 @@ impl CompFields { CompFields::AfterComputingBitfieldUnits(fields_and_units), ); } + + fn deanonymize_fields(&mut self) { + let fields = match *self { + CompFields::AfterComputingBitfieldUnits(ref mut fields) => { + fields + } + CompFields::BeforeComputingBitfieldUnits(_) => { + panic!("Not yet computed bitfield units."); + } + }; + + let mut anon_field_counter = 0; + for field in fields.iter_mut() { + let field_data = match *field { + Field::DataMember(ref mut fd) => fd, + Field::Bitfields(_) => continue, + }; + + if let Some(_) = field_data.name { + continue; + } + + anon_field_counter += 1; + let name = format!("__bindgen_anon_{}", anon_field_counter); + field_data.name = Some(name); + } + } } impl Trace for CompFields { @@ -1351,6 +1378,11 @@ impl CompInfo { self.fields.compute_bitfield_units(ctx); } + /// Assign for each anonymous field a generated name. + pub fn deanonymize_fields(&mut self) { + self.fields.deanonymize_fields(); + } + /// Returns whether the current union can be represented as a Rust `union` /// /// Requirements: diff --git a/src/ir/context.rs b/src/ir/context.rs index b2c53aac..b540d152 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -239,8 +239,9 @@ pub struct BindgenContext { /// The set of (`ItemId`s of) types that can't derive hash. /// - /// This is populated when we enter codegen by `compute_can_derive_partialeq` - /// and is always `None` before that and `Some` after. + /// This is populated when we enter codegen by + /// `compute_cannot_derive_partialord_partialeq_or_eq` and is always `None` + /// before that and `Some` after. cannot_derive_partialeq_or_partialord: Option<HashSet<ItemId>>, /// The set of (`ItemId's of`) types that has vtable. @@ -799,6 +800,18 @@ impl BindgenContext { } } + /// Assign a new generated name for each anonymous field. + fn deanonymize_fields(&mut self) { + let _t = self.timer("deanonymize_fields"); + let comp_types = self.items + .values_mut() + .filter_map(|item| item.kind_mut().as_type_mut()) + .filter_map(Type::as_comp_mut); + for comp_info in comp_types { + comp_info.deanonymize_fields(); + } + } + /// Iterate over all items and replace any item that has been named in a /// `replaces="SomeType"` annotation with the replacement type. fn process_replacements(&mut self) { @@ -940,6 +953,8 @@ impl BindgenContext { self.compute_bitfield_units(); self.process_replacements(); } + + self.deanonymize_fields(); // And assert once again, because resolving type refs and processing // replacements both mutate the IR graph. @@ -2149,8 +2164,7 @@ impl BindgenContext { } } - /// Look up whether the item with `id` can - /// derive partialeq or partialord. + /// Look up whether the item with `id` can derive `Partial{Eq,Ord}`. pub fn lookup_item_id_can_derive_partialeq_or_partialord(&self, id: ItemId) -> bool { assert!( self.in_codegen_phase(), @@ -2162,8 +2176,7 @@ impl BindgenContext { !self.cannot_derive_partialeq_or_partialord.as_ref().unwrap().contains(&id) } - /// Look up whether the item with `id` can - /// derive copy or not. + /// Look up whether the item with `id` can derive `Copy` or not. pub fn lookup_item_id_can_derive_copy(&self, id: ItemId) -> bool { assert!( self.in_codegen_phase(), diff --git a/src/ir/derive.rs b/src/ir/derive.rs index f518152a..cafbd3b1 100644 --- a/src/ir/derive.rs +++ b/src/ir/derive.rs @@ -1,27 +1,32 @@ //! Traits for determining whether we can derive traits for a thing or not. +//! +//! These traits tend to come in pairs: +//! +//! 1. A "trivial" version, whose implementations aren't allowed to recursively +//! look at other types or the results of fix point analyses. +//! +//! 2. A "normal" version, whose implementations simply query the results of a +//! fix point analysis. +//! +//! The former is used by the analyses when creating the results queried by the +//! second. use super::context::BindgenContext; /// A trait that encapsulates the logic for whether or not we can derive `Debug` /// for a given thing. -/// -/// This should ideally be a no-op that just returns `true`, but instead needs -/// to be a recursive method that checks whether all the proper members can -/// derive debug or not, because of the limit rust has on 32 items as max in the -/// array. pub trait CanDeriveDebug { /// Return `true` if `Debug` can be derived for this thing, `false` /// otherwise. fn can_derive_debug(&self, ctx: &BindgenContext) -> bool; } -/// A trait that encapsulates the logic for whether or not we can derive `Debug`. -/// The difference between this trait and the CanDeriveDebug 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. +/// A trait that encapsulates the logic for whether or not we can trivially +/// derive `Debug` without looking at any other types or the results of a fix +/// point analysis. This is a helper trait for the fix point analysis. pub trait CanTriviallyDeriveDebug { - /// Return `true` if `Debug` can be derived for this thing, `false` - /// otherwise. + /// Return `true` if `Debug` can trivially be derived for this thing, + /// `false` otherwise. fn can_trivially_derive_debug(&self) -> bool; } @@ -33,72 +38,50 @@ pub trait CanDeriveCopy<'a> { fn can_derive_copy(&'a self, ctx: &'a BindgenContext) -> bool; } -/// A trait that encapsulates the logic for whether or not we can derive `Copy`. -/// The difference between this trait and the CanDeriveCopy 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. +/// A trait that encapsulates the logic for whether or not we can trivially +/// derive `Copy` without looking at any other types or results of fix point +/// analsyses. This is a helper trait for fix point analysis. pub trait CanTriviallyDeriveCopy { - /// Return `true` if `Copy` can be derived for this thing, `false` + /// Return `true` if `Copy` can be trivially derived for this thing, `false` /// otherwise. fn can_trivially_derive_copy(&self) -> bool; } -/// A trait that encapsulates the logic for whether or not we can derive `Default` -/// for a given thing. -/// -/// This should ideally be a no-op that just returns `true`, but instead needs -/// 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. +/// A trait that encapsulates the logic for whether or not we can derive +/// `Default` for a given thing. pub trait CanDeriveDefault { /// Return `true` if `Default` can be derived for this thing, `false` /// otherwise. fn can_derive_default(&self, 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. +/// A trait that encapsulates the logic for whether or not we can trivially +/// derive `Default` without looking at any other types or results of fix point +/// analyses. This is a helper trait for the fix point analysis. pub trait CanTriviallyDeriveDefault { - /// Return `true` if `Default` can be derived for this thing, `false` + /// Return `true` if `Default` can trivially derived for this thing, `false` /// otherwise. fn can_trivially_derive_default(&self) -> bool; } /// A trait that encapsulates the logic for whether or not we can derive `Hash` /// for a given thing. -/// -/// This should ideally be a no-op that just returns `true`, but instead needs -/// 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 CanDeriveHash { - /// Return `true` if `Default` can be derived for this thing, `false` + /// Return `true` if `Hash` can be derived for this thing, `false` /// otherwise. fn can_derive_hash(&self, ctx: &BindgenContext) -> bool; } -/// A trait that encapsulates the logic for whether or not we can derive `PartialEq` -/// for a given thing. -/// -/// This should ideally be a no-op that just returns `true`, but instead needs -/// 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. +/// A trait that encapsulates the logic for whether or not we can derive +/// `PartialEq` for a given thing. pub trait CanDerivePartialEq { /// Return `true` if `PartialEq` can be derived for this thing, `false` /// otherwise. fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool; } -/// A trait that encapsulates the logic for whether or not we can derive `PartialOrd` -/// for a given thing. -/// -/// This should ideally be a no-op that just returns `true`, but instead needs -/// to be a recursive method that checks whether all the proper members can -/// derive partial ord or not, because of the limit rust has on 32 items as max in the -/// array. +/// A trait that encapsulates the logic for whether or not we can derive +/// `PartialOrd` for a given thing. pub trait CanDerivePartialOrd { /// Return `true` if `PartialOrd` can be derived for this thing, `false` /// otherwise. @@ -107,50 +90,32 @@ pub trait CanDerivePartialOrd { /// A trait that encapsulates the logic for whether or not we can derive `Eq` /// for a given thing. -/// -/// This should ideally be a no-op that just returns `true`, but instead needs -/// to be a recursive method that checks whether all the proper members can -/// derive eq or not, because of the limit rust has on 32 items as max in the -/// array. pub trait CanDeriveEq { - - /// Return `true` if `Eq` can be derived for this thing, `false` - /// otherwise. - fn can_derive_eq(&self, - ctx: &BindgenContext) - -> bool; + /// Return `true` if `Eq` can be derived for this thing, `false` otherwise. + fn can_derive_eq(&self, ctx: &BindgenContext) -> bool; } /// A trait that encapsulates the logic for whether or not we can derive `Ord` /// for a given thing. -/// -/// This should ideally be a no-op that just returns `true`, but instead needs -/// to be a recursive method that checks whether all the proper members can -/// derive ord or not, because of the limit rust has on 32 items as max in the -/// array. pub trait CanDeriveOrd { - /// Return `true` if `Ord` can be derived for this thing, `false` - /// otherwise. + /// Return `true` if `Ord` can be derived for this thing, `false` otherwise. fn can_derive_ord(&self, ctx: &BindgenContext) -> bool; } -/// A trait that encapsulates the logic for whether or not we can derive `Hash`. -/// The difference between this trait and the CanDeriveHash 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. +/// A trait that encapsulates the logic for whether or not we can derive `Hash` +/// without looking at any other types or the results of any fix point +/// analyses. This is a helper trait for the fix point analysis. pub trait CanTriviallyDeriveHash { - /// Return `true` if `Hash` can be derived for this thing, `false` + /// Return `true` if `Hash` can trivially be derived for this thing, `false` /// otherwise. fn can_trivially_derive_hash(&self) -> bool; } -/// A trait that encapsulates the logic for whether or not we can derive `PartialEq` -/// or `PartialOrd`. -/// The difference between this trait and the CanDerivePartialEq 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. +/// A trait that encapsulates the logic for whether or not we can trivially +/// derive `PartialEq` or `PartialOrd` without looking at any other types or +/// results of fix point analyses. This is a helper for the fix point analysis. pub trait CanTriviallyDerivePartialEqOrPartialOrd { - /// Return `true` if `PartialEq` or `PartialOrd` can be derived for this thing, `false` - /// otherwise. + /// Return `true` if `PartialEq` or `PartialOrd` can trivially be derived + /// for this thing, `false` otherwise. fn can_trivially_derive_partialeq_or_partialord(&self) -> bool; } diff --git a/src/ir/function.rs b/src/ir/function.rs index f37f0f3c..402a0230 100644 --- a/src/ir/function.rs +++ b/src/ir/function.rs @@ -437,6 +437,26 @@ impl FunctionSig { // variadic functions without an initial argument. self.is_variadic && !self.argument_types.is_empty() } + + /// Are function pointers with this signature able to derive Rust traits? + /// Rust only supports deriving traits for function pointers with a limited + /// number of parameters and a couple ABIs. + /// + /// For more details, see: + /// + /// * https://github.com/rust-lang-nursery/rust-bindgen/issues/547, + /// * https://github.com/rust-lang/rust/issues/38848, + /// * and https://github.com/rust-lang/rust/issues/40158 + pub fn function_pointers_can_derive(&self) -> bool { + if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT { + return false; + } + + match self.abi { + Abi::C | Abi::Unknown(..) => true, + _ => false, + } + } } impl ClangSubItemParser for Function { @@ -523,48 +543,20 @@ impl Trace for FunctionSig { } } -// Function pointers follow special rules, see: -// -// https://github.com/rust-lang-nursery/rust-bindgen/issues/547, -// https://github.com/rust-lang/rust/issues/38848, -// and https://github.com/rust-lang/rust/issues/40158 -// -// Note that copy is always derived, so we don't need to implement it. impl CanTriviallyDeriveDebug for FunctionSig { fn can_trivially_derive_debug(&self) -> bool { - if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT { - return false; - } - - match self.abi { - Abi::C | Abi::Unknown(..) => true, - _ => false, - } + self.function_pointers_can_derive() } } impl CanTriviallyDeriveHash for FunctionSig { fn can_trivially_derive_hash(&self) -> bool { - if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT { - return false; - } - - match self.abi { - Abi::C | Abi::Unknown(..) => true, - _ => false, - } + self.function_pointers_can_derive() } } impl CanTriviallyDerivePartialEqOrPartialOrd for FunctionSig { fn can_trivially_derive_partialeq_or_partialord(&self) -> bool { - if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT { - return false; - } - - match self.abi { - Abi::C | Abi::Unknown(..) => true, - _ => false, - } + self.function_pointers_can_derive() } } diff --git a/src/ir/layout.rs b/src/ir/layout.rs index 298fe54a..2df15ef2 100644 --- a/src/ir/layout.rs +++ b/src/ir/layout.rs @@ -104,44 +104,43 @@ impl Opaque { None } } -} -impl CanTriviallyDeriveDebug for Opaque { - fn can_trivially_derive_debug(&self) -> bool { + /// Return `true` if this opaque layout's array size will fit within the + /// maximum number of array elements that Rust allows deriving traits + /// with. Return `false` otherwise. + pub fn array_size_within_derive_limit(&self) -> bool { self.array_size().map_or(false, |size| { size <= RUST_DERIVE_IN_ARRAY_LIMIT }) } } +impl CanTriviallyDeriveDebug for Opaque { + fn can_trivially_derive_debug(&self) -> bool { + self.array_size_within_derive_limit() + } +} + impl CanTriviallyDeriveDefault for Opaque { fn can_trivially_derive_default(&self) -> bool { - self.array_size().map_or(false, |size| { - size <= RUST_DERIVE_IN_ARRAY_LIMIT - }) + self.array_size_within_derive_limit() } } impl CanTriviallyDeriveCopy for Opaque { fn can_trivially_derive_copy(&self) -> bool { - self.array_size().map_or(false, |size| { - size <= RUST_DERIVE_IN_ARRAY_LIMIT - }) + self.array_size_within_derive_limit() } } impl CanTriviallyDeriveHash for Opaque { fn can_trivially_derive_hash(&self) -> bool { - self.array_size().map_or(false, |size| { - size <= RUST_DERIVE_IN_ARRAY_LIMIT - }) + self.array_size_within_derive_limit() } } impl CanTriviallyDerivePartialEqOrPartialOrd for Opaque { fn can_trivially_derive_partialeq_or_partialord(&self) -> bool { - self.array_size().map_or(false, |size| { - size <= RUST_DERIVE_IN_ARRAY_LIMIT - }) + self.array_size_within_derive_limit() } } diff --git a/src/ir/objc.rs b/src/ir/objc.rs index cabbd389..0f72c399 100644 --- a/src/ir/objc.rs +++ b/src/ir/objc.rs @@ -236,13 +236,21 @@ impl ObjCMethod { ); } + // Get arguments without type signatures to pass to `msg_send!` + let mut args_without_types = vec![]; + for arg in args.iter() { + let name_and_sig: Vec<&str> = arg.as_str().split(' ').collect(); + let name = name_and_sig[0]; + args_without_types.push(quote::Ident::new(name)) + }; + let args = split_name .into_iter() - .zip(args.iter()) - .map(|(arg, ty)| quote! { #arg : #ty }); + .zip(args_without_types) + .map(|(arg, arg_val)| quote! { #arg : #arg_val }); quote! { - #( #args ),* + #( #args )* } } } @@ -247,7 +247,7 @@ impl Builder { output_vector.push("--no-derive-debug".into()); } - if !self.options.impl_debug { + if self.options.impl_debug { output_vector.push("--impl-debug".into()); } @@ -857,8 +857,9 @@ impl Builder { } /// Set whether `PartialEq` should be derived by default. - /// If we don't compute partialeq, we also cannot compute - /// eq. Set the derive_eq to `false` when doit is `false`. + /// + /// If we don't derive `PartialEq`, we also cannot derive `Eq`, so deriving + /// `Eq` is also disabled when `doit` is `false`. pub fn derive_partialeq(mut self, doit: bool) -> Self { self.options.derive_partialeq = doit; if !doit { @@ -868,16 +869,19 @@ impl Builder { } /// Set whether `Eq` should be derived by default. - /// We can't compute Eq without computing PartialEq, so - /// we set the same option to derive_partialeq. + /// + /// We can't derive `Eq` without also deriving `PartialEq`, so we also + /// enable deriving `PartialEq` when `doit` is `true`. pub fn derive_eq(mut self, doit: bool) -> Self { self.options.derive_eq = doit; - self.options.derive_partialeq = doit; + if doit { + self.options.derive_partialeq = doit; + } self } - /// Set whether or not to time bindgen phases, and print - /// information to stderr. + /// Set whether or not to time bindgen phases, and print information to + /// stderr. pub fn time_phases(mut self, doit: bool) -> Self { self.options.time_phases = doit; self @@ -1686,7 +1690,7 @@ fn parse(context: &mut BindgenContext) -> Result<(), ()> { for d in context.translation_unit().diags().iter() { let msg = d.format(); let is_err = d.severity() >= CXDiagnostic_Error; - println!("{}, err: {}", msg, is_err); + eprintln!("{}, err: {}", msg, is_err); any_error |= is_err; } |