diff --git a/src/codegen/derive_debug.rs b/src/codegen/derive_debug.rs new file mode 100644 index 0000000000..a47d37d152 --- /dev/null +++ b/src/codegen/derive_debug.rs @@ -0,0 +1,197 @@ +use ir::comp::{BitfieldUnit, CompKind, Field, FieldData, FieldMethods}; +use ir::context::BindgenContext; +use ir::derive::CanTriviallyDeriveDebug; +use ir::item::{IsOpaque, Item, ItemCanonicalName}; +use ir::ty::{TypeKind, RUST_DERIVE_IN_ARRAY_LIMIT}; +use syntax::ast; +use syntax::codemap::DUMMY_SP; +use syntax::parse::token::Token; + +use syntax::tokenstream::TokenTree; + +pub fn gen_debug_impl( + ctx: &BindgenContext, + fields: &[Field], + item: &Item, + kind: CompKind, +) -> Vec { + let struct_name = item.canonical_name(ctx); + let mut format_string = format!("{} {{{{ ", struct_name); + let mut tokens: Vec = Vec::new(); + + if item.is_opaque(ctx, &()) { + format_string.push_str("opaque"); + } else { + match kind { + CompKind::Union => { + format_string.push_str("union"); + } + CompKind::Struct => { + let processed_fields = fields.iter().filter_map(|f| match f { + &Field::DataMember(ref fd) => { + gen_field_data_debug_impl(ctx, fd) + } + &Field::Bitfields(ref bu) => { + gen_bitfield_unit_debug_impl(ctx, bu) + } + }); + + + for (i, (fstring, token)) in processed_fields.enumerate() { + if i > 0 { + format_string.push_str(", "); + } + if !token.is_empty() { + tokens.push(TokenTree::Token(DUMMY_SP, Token::Comma)); + tokens.extend(token); + } + format_string.push_str(&fstring); + } + } + } + } + + format_string.push_str(" }}"); + + let impl_ = quote_item!(ctx.ext_cx(), + impl X { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, $format_string $tokens) + } + }); + + match impl_.unwrap().node { + ast::ItemKind::Impl(_, _, _, _, _, ref items) => items.clone(), + _ => unreachable!(), + } +} + +fn gen_field_data_debug_impl( + ctx: &BindgenContext, + data: &FieldData, +) -> Option<(String, Vec)> { + if let Some(name) = data.name() { + gen_item_debug_impl(ctx, ctx.resolve_item(data.ty()), name) + } else { + None + } +} + +fn gen_bitfield_unit_debug_impl( + ctx: &BindgenContext, + data: &BitfieldUnit, +) -> Option<(String, Vec)> { + let mut format_string = String::new(); + let mut tokens = Vec::new(); + for (i, bu) in data.bitfields().iter().enumerate() { + if i > 0 { + format_string.push_str(", "); + tokens.push(TokenTree::Token(DUMMY_SP, Token::Comma)); + } + format_string.push_str(&format!("{} : {{:?}}", bu.name())); + let name_ident = ctx.rust_ident_raw(bu.name()); + tokens.extend(quote_tokens!(ctx.ext_cx(), self.$name_ident())); + } + + Some((format_string, tokens)) +} + +fn gen_item_debug_impl( + ctx: &BindgenContext, + item: &Item, + name: &str, +) -> Option<(String, Vec)> { + let name_ident = ctx.rust_ident_raw(name); + + let ty = match item.as_type() { + Some(ty) => ty, + None => { + return None; + } + }; + + fn debug_print( + ctx: &BindgenContext, + name: &str, + name_ident: ast::Ident, + ) -> Option<(String, Vec)> { + Some(( + format!("{}: {{:?}}", name), + quote_tokens!(ctx.ext_cx(), self.$name_ident), + )) + } + + match *ty.kind() { + // Handle the simple cases. + TypeKind::Void | + TypeKind::NullPtr | + TypeKind::Int(..) | + TypeKind::Float(..) | + TypeKind::Complex(..) | + TypeKind::Function(..) | + TypeKind::Enum(..) | + TypeKind::Reference(..) | + TypeKind::BlockPointer | + TypeKind::UnresolvedTypeRef(..) | + TypeKind::ObjCInterface(..) | + TypeKind::ObjCId | + TypeKind::Comp(..) | + TypeKind::ObjCSel => debug_print(ctx, name, name_ident), + + TypeKind::TemplateInstantiation(ref inst) => { + if inst.is_opaque(ctx, item) { + Some((format!("{}: opaque", name), vec![])) + } else { + debug_print(ctx, name, name_ident) + } + } + + // The generic is not required to implement Debug, so we can not debug print that type + TypeKind::Named => { + Some((format!("{}: Non-debuggable generic", name), vec![])) + } + + TypeKind::Array(_, len) => { + // Generics are not required to implement Debug + if ctx.lookup_item_id_has_type_param_in_array(&item.id()) { + Some((format!("{}: Array with length {}", name, len), vec![])) + } else if len < RUST_DERIVE_IN_ARRAY_LIMIT { + // The simple case + debug_print(ctx, name, name_ident) + } else { + // Let's implement our own print function + Some(( + format!("{}: [{{}}]", name), + quote_tokens!( + ctx.ext_cx(), + self.$name_ident + .iter() + .enumerate() + .map(|(i, v)| format!("{}{:?}", if i > 0 { ", " } else { "" }, v)) + .collect::()), + )) + } + } + + TypeKind::ResolvedTypeRef(t) | + TypeKind::TemplateAlias(t, _) | + TypeKind::Alias(t) => { + // We follow the aliases + gen_item_debug_impl(ctx, ctx.resolve_item(t), name) + } + + TypeKind::Pointer(inner) => { + let inner_type = ctx.resolve_type(inner).canonical_type(ctx); + match *inner_type.kind() { + TypeKind::Function(ref sig) + if !sig.can_trivially_derive_debug() => + { + Some((format!("{}: FunctionPointer", name), vec![])) + } + _ => debug_print(ctx, name, name_ident), + } + } + + TypeKind::Opaque => None, + } +} diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 5c00a53d27..7324a0edc1 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1,17 +1,18 @@ +mod derive_debug; mod error; mod helpers; pub mod struct_layout; -use self::helpers::{BlobTyBuilder, attributes}; +use self::helpers::{attributes, BlobTyBuilder}; use self::struct_layout::StructLayoutTracker; use aster; use aster::struct_field::StructFieldBuilder; use ir::annotations::FieldAccessorKind; -use ir::comp::{Base, BitfieldUnit, Bitfield, CompInfo, CompKind, Field, - FieldData, FieldMethods, Method, MethodKind}; use ir::comment; +use ir::comp::{Base, Bitfield, BitfieldUnit, CompInfo, CompKind, Field, + FieldData, FieldMethods, Method, MethodKind}; use ir::context::{BindgenContext, ItemId}; use ir::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault}; use ir::dot; @@ -36,7 +37,7 @@ use std::mem; use std::ops; use syntax::abi; use syntax::ast; -use syntax::codemap::{DUMMY_SP, Span, respan}; +use syntax::codemap::{respan, Span, DUMMY_SP}; use syntax::ptr::P; // Name of type defined in constified enum module @@ -181,7 +182,8 @@ impl<'a> CodegenResult<'a> { } fn inner(&mut self, cb: F) -> Vec> - where F: FnOnce(&mut Self), + where + F: FnOnce(&mut Self), { let mut new = Self::new(self.codegen_id); @@ -230,7 +232,8 @@ impl ForeignModBuilder { #[allow(dead_code)] fn with_foreign_items(mut self, items: I) -> Self - where I: IntoIterator, + where + I: IntoIterator, { self.inner.items.extend(items.into_iter()); self @@ -279,27 +282,33 @@ trait CodeGenerator { /// Extra information from the caller. type Extra; - fn codegen<'a>(&self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - extra: &Self::Extra); + fn codegen<'a>( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'a>, + extra: &Self::Extra, + ); } impl CodeGenerator for Item { type Extra = (); - fn codegen<'a>(&self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - _extra: &()) { + fn codegen<'a>( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'a>, + _extra: &(), + ) { if !self.is_enabled_for_codegen(ctx) { return; } if self.is_hidden(ctx) || result.seen(self.id()) { - debug!("::codegen: Ignoring hidden or seen: \ - self = {:?}", - self); + debug!( + "::codegen: Ignoring hidden or seen: \ + self = {:?}", + self + ); return; } @@ -333,10 +342,12 @@ impl CodeGenerator for Item { impl CodeGenerator for Module { type Extra = Item; - fn codegen<'a>(&self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - item: &Item) { + fn codegen<'a>( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'a>, + item: &Item, + ) { debug!("::codegen: item = {:?}", item); let codegen_self = |result: &mut CodegenResult, @@ -344,8 +355,7 @@ impl CodeGenerator for Module { for child in self.children() { if ctx.codegen_items().contains(child) { *found_any = true; - ctx.resolve_item(*child) - .codegen(ctx, result, &()); + ctx.resolve_item(*child).codegen(ctx, result, &()); } } @@ -366,7 +376,9 @@ impl CodeGenerator for Module { }; if !ctx.options().enable_cxx_namespaces || - (self.is_inline() && !ctx.options().conservative_inline_namespaces) { + (self.is_inline() && + !ctx.options().conservative_inline_namespaces) + { codegen_self(result, &mut false); return; } @@ -388,14 +400,15 @@ impl CodeGenerator for Module { }); let name = item.canonical_name(ctx); - let item_builder = aster::AstBuilder::new() - .item() - .pub_(); + let item_builder = aster::AstBuilder::new().item().pub_(); let item = if name == "root" { - let attrs = &["non_snake_case", + let attrs = &[ + "non_snake_case", "non_camel_case_types", - "non_upper_case_globals"]; - item_builder.with_attr(attributes::allow(attrs)) + "non_upper_case_globals", + ]; + item_builder + .with_attr(attributes::allow(attrs)) .build_item_kind(name, module) } else { item_builder.build_item_kind(name, module) @@ -407,10 +420,12 @@ impl CodeGenerator for Module { impl CodeGenerator for Var { type Extra = Item; - fn codegen<'a>(&self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - item: &Item) { + fn codegen<'a>( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'a>, + item: &Item, + ) { use ir::var::VarType; debug!("::codegen: item = {:?}", item); debug_assert!(item.is_enabled_for_codegen(ctx)); @@ -456,30 +471,23 @@ impl CodeGenerator for Var { let ty = quote_ty!(ctx.ext_cx(), [u8; $len]); match String::from_utf8(bytes.clone()) { - Ok(string) => { - const_item.build(helpers::ast_ty::cstr_expr(string)) - .build(quote_ty!(ctx.ext_cx(), &'static $ty)) - } - Err(..) => { - const_item - .build(helpers::ast_ty::byte_array_expr(bytes)) - .build(ty) - } + Ok(string) => const_item + .build(helpers::ast_ty::cstr_expr(string)) + .build(quote_ty!(ctx.ext_cx(), &'static $ty)), + Err(..) => const_item + .build(helpers::ast_ty::byte_array_expr(bytes)) + .build(ty), } } VarType::Float(f) => { match helpers::ast_ty::float_expr(ctx, f) { - Ok(expr) => { - const_item.build(expr).build(ty) - } + Ok(expr) => const_item.build(expr).build(ty), Err(..) => return, } } - VarType::Char(c) => { - const_item - .build(aster::AstBuilder::new().expr().lit().byte(c)) - .build(ty) - } + VarType::Char(c) => const_item + .build(aster::AstBuilder::new().expr().lit().byte(c)) + .build(ty), }; result.push(item); @@ -511,10 +519,12 @@ impl CodeGenerator for Var { impl CodeGenerator for Type { type Extra = Item; - fn codegen<'a>(&self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - item: &Item) { + fn codegen<'a>( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'a>, + item: &Item, + ) { debug!("::codegen: item = {:?}", item); debug_assert!(item.is_enabled_for_codegen(ctx)); @@ -539,11 +549,8 @@ impl CodeGenerator for Type { TypeKind::TemplateInstantiation(ref inst) => { inst.codegen(ctx, result, item) } - TypeKind::Comp(ref ci) => { - ci.codegen(ctx, result, item) - } - TypeKind::TemplateAlias(inner, _) | - TypeKind::Alias(inner) => { + TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item), + TypeKind::TemplateAlias(inner, _) | TypeKind::Alias(inner) => { let inner_item = ctx.resolve_item(inner); let name = item.canonical_name(ctx); @@ -572,7 +579,8 @@ impl CodeGenerator for Type { // Its possible that we have better layout information than // the inner type does, so fall back to an opaque blob based // on our layout if converting the inner item fails. - inner_item.try_to_rust_ty_or_opaque(ctx, &()) + inner_item + .try_to_rust_ty_or_opaque(ctx, &()) .unwrap_or_else(|_| self.to_opaque(ctx, item)) }; @@ -587,13 +595,15 @@ impl CodeGenerator for Type { // with invalid template parameters, and at least this way // they can be replaced, instead of generating plain invalid // code. - let inner_canon_type = inner_item.expect_type() - .canonical_type(ctx); + let inner_canon_type = + inner_item.expect_type().canonical_type(ctx); if inner_canon_type.is_invalid_named_type() { - warn!("Item contained invalid named type, skipping: \ - {:?}, {:?}", - item, - inner_item); + warn!( + "Item contained invalid named type, skipping: \ + {:?}, {:?}", + item, + inner_item + ); return; } } @@ -608,27 +618,30 @@ impl CodeGenerator for Type { // We prefer using `pub use` over `pub type` because of: // https://github.com/rust-lang/rust/issues/26264 let simple_enum_path = match inner_rust_type.node { - ast::TyKind::Path(None, ref p) => { - if used_template_params.is_none() && - inner_item.expect_type() + ast::TyKind::Path(None, ref p) => if used_template_params + .is_none() && + inner_item + .expect_type() .canonical_type(ctx) .is_enum() && - p.segments.iter().all(|p| p.parameters.is_none()) { - Some(p.clone()) - } else { - None - } - } + p.segments.iter().all(|p| p.parameters.is_none()) + { + Some(p.clone()) + } else { + None + }, _ => None, }; let typedef = if let Some(mut p) = simple_enum_path { for ident in top_level_path(ctx, item).into_iter().rev() { - p.segments.insert(0, - ast::PathSegment { - identifier: ident, - parameters: None, - }); + p.segments.insert( + 0, + ast::PathSegment { + identifier: ident, + parameters: None, + }, + ); } typedef.use_().build(p).as_(rust_name) } else { @@ -636,17 +649,21 @@ impl CodeGenerator for Type { if let Some(ref params) = used_template_params { for template_param in params { if let Some(id) = - template_param.as_template_param(ctx, &()) { + template_param.as_template_param(ctx, &()) + { let template_param = ctx.resolve_type(id); if template_param.is_invalid_named_type() { - warn!("Item contained invalid template \ - parameter: {:?}", - item); + warn!( + "Item contained invalid template \ + parameter: {:?}", + item + ); return; } generics = - generics.ty_param_id(template_param.name() - .unwrap()); + generics.ty_param_id( + template_param.name().unwrap(), + ); } } } @@ -654,9 +671,7 @@ impl CodeGenerator for Type { }; result.push(typedef) } - TypeKind::Enum(ref ei) => { - ei.codegen(ctx, result, item) - } + TypeKind::Enum(ref ei) => ei.codegen(ctx, result, item), TypeKind::ObjCId | TypeKind::ObjCSel => { result.saw_objc(); } @@ -679,10 +694,11 @@ struct Vtable<'a> { } impl<'a> Vtable<'a> { - fn new(item_id: ItemId, - methods: &'a [Method], - base_classes: &'a [Base]) - -> Self { + fn new( + item_id: ItemId, + methods: &'a [Method], + base_classes: &'a [Base], + ) -> Self { Vtable { item_id: item_id, methods: methods, @@ -694,10 +710,12 @@ impl<'a> Vtable<'a> { impl<'a> CodeGenerator for Vtable<'a> { type Extra = Item; - fn codegen<'b>(&self, - ctx: &BindgenContext, - result: &mut CodegenResult<'b>, - item: &Item) { + fn codegen<'b>( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'b>, + item: &Item, + ) { assert_eq!(item.id(), self.item_id); debug_assert!(item.is_enabled_for_codegen(ctx)); @@ -726,9 +744,11 @@ impl<'a> ItemCanonicalName for Vtable<'a> { impl<'a> TryToRustTy for Vtable<'a> { type Extra = (); - fn try_to_rust_ty(&self, - ctx: &BindgenContext, - _: &()) -> error::Result> { + fn try_to_rust_ty( + &self, + ctx: &BindgenContext, + _: &(), + ) -> error::Result> { Ok(aster::ty::TyBuilder::new().id(self.canonical_name(ctx))) } } @@ -736,10 +756,12 @@ impl<'a> TryToRustTy for Vtable<'a> { impl CodeGenerator for TemplateInstantiation { type Extra = Item; - fn codegen<'a>(&self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - item: &Item) { + fn codegen<'a>( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'a>, + item: &Item, + ) { debug_assert!(item.is_enabled_for_codegen(ctx)); // Although uses of instantiations don't need code generation, and are @@ -749,7 +771,7 @@ impl CodeGenerator for TemplateInstantiation { // properly understand it (maybe because of specializations), and so we // shouldn't emit layout tests either. if !ctx.options().layout_tests || self.is_opaque(ctx, item) { - return + return; } // If there are any unbound type parameters, then we can't generate a @@ -766,7 +788,8 @@ impl CodeGenerator for TemplateInstantiation { let align = layout.align; let name = item.full_disambiguated_name(ctx); - let mut fn_name = format!("__bindgen_test_layout_{}_instantiation", name); + let mut fn_name = + format!("__bindgen_test_layout_{}_instantiation", name); let times_seen = result.overload_number(&fn_name); if times_seen > 0 { write!(&mut fn_name, "_{}", times_seen).unwrap(); @@ -791,8 +814,7 @@ impl CodeGenerator for TemplateInstantiation { assert_eq!($align_of_expr, $align, concat!("Alignment of template specialization: ", stringify!($ident))); - }) - .unwrap(); + }).unwrap(); result.push(item); } @@ -821,66 +843,74 @@ impl Iterator for AnonFieldNames { trait FieldCodegen<'a> { type Extra; - fn codegen(&self, - ctx: &BindgenContext, - fields_should_be_private: bool, - codegen_depth: usize, - accessor_kind: FieldAccessorKind, - parent: &CompInfo, - anon_field_names: &mut AnonFieldNames, - result: &mut CodegenResult, - struct_layout: &mut StructLayoutTracker, - fields: &mut F, - methods: &mut M, - extra: Self::Extra) - where F: Extend, - M: Extend; + fn codegen( + &self, + ctx: &BindgenContext, + fields_should_be_private: bool, + codegen_depth: usize, + accessor_kind: FieldAccessorKind, + parent: &CompInfo, + anon_field_names: &mut AnonFieldNames, + result: &mut CodegenResult, + struct_layout: &mut StructLayoutTracker, + fields: &mut F, + methods: &mut M, + extra: Self::Extra, + ) where + F: Extend, + M: Extend; } impl<'a> FieldCodegen<'a> for Field { type Extra = (); - fn codegen(&self, - ctx: &BindgenContext, - fields_should_be_private: bool, - codegen_depth: usize, - accessor_kind: FieldAccessorKind, - parent: &CompInfo, - anon_field_names: &mut AnonFieldNames, - result: &mut CodegenResult, - struct_layout: &mut StructLayoutTracker, - fields: &mut F, - methods: &mut M, - _: ()) - where F: Extend, - M: Extend + fn codegen( + &self, + ctx: &BindgenContext, + fields_should_be_private: bool, + codegen_depth: usize, + accessor_kind: FieldAccessorKind, + parent: &CompInfo, + anon_field_names: &mut AnonFieldNames, + result: &mut CodegenResult, + struct_layout: &mut StructLayoutTracker, + fields: &mut F, + methods: &mut M, + _: (), + ) where + F: Extend, + M: Extend, { match *self { Field::DataMember(ref data) => { - data.codegen(ctx, - fields_should_be_private, - codegen_depth, - accessor_kind, - parent, - anon_field_names, - result, - struct_layout, - fields, - methods, - ()); + data.codegen( + ctx, + fields_should_be_private, + codegen_depth, + accessor_kind, + parent, + anon_field_names, + result, + struct_layout, + fields, + methods, + (), + ); } Field::Bitfields(ref unit) => { - unit.codegen(ctx, - fields_should_be_private, - codegen_depth, - accessor_kind, - parent, - anon_field_names, - result, - struct_layout, - fields, - methods, - ()); + unit.codegen( + ctx, + fields_should_be_private, + codegen_depth, + accessor_kind, + parent, + anon_field_names, + result, + struct_layout, + fields, + methods, + (), + ); } } } @@ -889,20 +919,22 @@ impl<'a> FieldCodegen<'a> for Field { impl<'a> FieldCodegen<'a> for FieldData { type Extra = (); - fn codegen(&self, - ctx: &BindgenContext, - fields_should_be_private: bool, - codegen_depth: usize, - accessor_kind: FieldAccessorKind, - parent: &CompInfo, - anon_field_names: &mut AnonFieldNames, - result: &mut CodegenResult, - struct_layout: &mut StructLayoutTracker, - fields: &mut F, - methods: &mut M, - _: ()) - where F: Extend, - M: Extend + fn codegen( + &self, + ctx: &BindgenContext, + fields_should_be_private: bool, + codegen_depth: usize, + accessor_kind: FieldAccessorKind, + parent: &CompInfo, + anon_field_names: &mut AnonFieldNames, + result: &mut CodegenResult, + struct_layout: &mut StructLayoutTracker, + fields: &mut F, + methods: &mut M, + _: (), + ) where + F: Extend, + M: Extend, { // Bitfields are handled by `FieldCodegen` implementations for // `BitfieldUnit` and `Bitfield`. @@ -918,8 +950,7 @@ impl<'a> FieldCodegen<'a> for FieldData { } else { quote_ty!(ctx.ext_cx(), __BindgenUnionField<$ty>) } - } else if let Some(item) = - field_ty.is_incomplete_array(ctx) { + } else if let Some(item) = field_ty.is_incomplete_array(ctx) { result.saw_incomplete_array(); let inner = item.to_rust_ty_or_opaque(ctx, &()); @@ -936,7 +967,8 @@ impl<'a> FieldCodegen<'a> for FieldData { let mut attrs = vec![]; if ctx.options().generate_comments { if let Some(raw_comment) = self.comment() { - let comment = comment::preprocess(raw_comment, codegen_depth + 1); + let comment = + comment::preprocess(raw_comment, codegen_depth + 1); attrs.push(attributes::doc(comment)) } } @@ -947,7 +979,8 @@ impl<'a> FieldCodegen<'a> for FieldData { if !parent.is_union() { if let Some(padding_field) = - struct_layout.pad_field(&field_name, field_ty, self.offset()) { + struct_layout.pad_field(&field_name, field_ty, self.offset()) + { fields.extend(Some(padding_field)); } } @@ -956,9 +989,8 @@ impl<'a> FieldCodegen<'a> for FieldData { .private_fields() .unwrap_or(fields_should_be_private); - let accessor_kind = self.annotations() - .accessor_kind() - .unwrap_or(accessor_kind); + let accessor_kind = + self.annotations().accessor_kind().unwrap_or(accessor_kind); let mut field = StructFieldBuilder::named(&field_name); @@ -966,8 +998,7 @@ impl<'a> FieldCodegen<'a> for FieldData { field = field.pub_(); } - let field = field.with_attrs(attrs) - .build_ty(ty.clone()); + let field = field.with_attrs(attrs).build_ty(ty.clone()); fields.extend(Some(field)); @@ -976,16 +1007,14 @@ impl<'a> FieldCodegen<'a> for FieldData { return; } - let getter_name = - ctx.rust_ident_raw(&format!("get_{}", field_name)); + let getter_name = ctx.rust_ident_raw(&format!("get_{}", field_name)); let mutable_getter_name = ctx.rust_ident_raw(&format!("get_{}_mut", field_name)); let field_name = ctx.rust_ident_raw(&field_name); let accessor_methods_impl = match accessor_kind { FieldAccessorKind::None => unreachable!(), - FieldAccessorKind::Regular => { - quote_item!(ctx.ext_cx(), + FieldAccessorKind::Regular => quote_item!(ctx.ext_cx(), impl X { #[inline] pub fn $getter_name(&self) -> &$ty { @@ -997,10 +1026,8 @@ impl<'a> FieldCodegen<'a> for FieldData { &mut self.$field_name } } - ) - } - FieldAccessorKind::Unsafe => { - quote_item!(ctx.ext_cx(), + ), + FieldAccessorKind::Unsafe => quote_item!(ctx.ext_cx(), impl X { #[inline] pub unsafe fn $getter_name(&self) -> &$ty { @@ -1013,18 +1040,15 @@ impl<'a> FieldCodegen<'a> for FieldData { &mut self.$field_name } } - ) - } - FieldAccessorKind::Immutable => { - quote_item!(ctx.ext_cx(), + ), + FieldAccessorKind::Immutable => quote_item!(ctx.ext_cx(), impl X { #[inline] pub fn $getter_name(&self) -> &$ty { &self.$field_name } } - ) - } + ), }; match accessor_methods_impl.unwrap().node { @@ -1046,10 +1070,11 @@ impl BitfieldUnit { /// Get the initial bitfield unit constructor that just returns 0. This will /// then be extended by each bitfield in the unit. See `extend_ctor_impl` /// below. - fn initial_ctor_impl(&self, - ctx: &BindgenContext, - unit_field_int_ty: &P) - -> P { + fn initial_ctor_impl( + &self, + ctx: &BindgenContext, + unit_field_int_ty: &P, + ) -> P { let ctor_name = self.ctor_name(ctx); // If we're generating unstable Rust, add the const. @@ -1079,25 +1104,22 @@ impl Bitfield { /// /// 2. Bitwise or'ing the parameter into the final value of the constructed /// bitfield unit. - fn extend_ctor_impl(&self, - ctx: &BindgenContext, - parent: &CompInfo, - ctor_impl: P, - ctor_name: &ast::Ident, - unit_field_int_ty: &P) - -> P { + fn extend_ctor_impl( + &self, + ctx: &BindgenContext, + parent: &CompInfo, + ctor_impl: P, + ctor_name: &ast::Ident, + unit_field_int_ty: &P, + ) -> P { let items = match ctor_impl.unwrap().node { - ast::ItemKind::Impl(_, _, _, _, _, items) => { - items - } + ast::ItemKind::Impl(_, _, _, _, _, items) => items, _ => unreachable!(), }; assert_eq!(items.len(), 1); let (sig, body) = match items[0].node { - ast::ImplItemKind::Method(ref sig, ref body) => { - (sig, body) - } + ast::ImplItemKind::Method(ref sig, ref body) => (sig, body), _ => unreachable!(), }; @@ -1106,11 +1128,12 @@ impl Bitfield { let bitfield_ty_item = ctx.resolve_item(self.ty()); let bitfield_ty = bitfield_ty_item.expect_type(); - let bitfield_ty_layout = bitfield_ty.layout(ctx) + let bitfield_ty_layout = bitfield_ty + .layout(ctx) .expect("Bitfield without layout? Gah!"); let bitfield_int_ty = BlobTyBuilder::new(bitfield_ty_layout).build(); - let bitfield_ty = bitfield_ty - .to_rust_ty_or_opaque(ctx, bitfield_ty_item); + let bitfield_ty = + bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item); let offset = self.offset_into_unit(); let mask = self.mask(); @@ -1141,20 +1164,22 @@ impl Bitfield { impl<'a> FieldCodegen<'a> for BitfieldUnit { type Extra = (); - fn codegen(&self, - ctx: &BindgenContext, - fields_should_be_private: bool, - codegen_depth: usize, - accessor_kind: FieldAccessorKind, - parent: &CompInfo, - anon_field_names: &mut AnonFieldNames, - result: &mut CodegenResult, - struct_layout: &mut StructLayoutTracker, - fields: &mut F, - methods: &mut M, - _: ()) - where F: Extend, - M: Extend + fn codegen( + &self, + ctx: &BindgenContext, + fields_should_be_private: bool, + codegen_depth: usize, + accessor_kind: FieldAccessorKind, + parent: &CompInfo, + anon_field_names: &mut AnonFieldNames, + result: &mut CodegenResult, + struct_layout: &mut StructLayoutTracker, + fields: &mut F, + methods: &mut M, + _: (), + ) where + F: Extend, + M: Extend, { let field_ty = BlobTyBuilder::new(self.layout()).build(); let unit_field_name = format!("_bitfield_{}", self.nth()); @@ -1187,30 +1212,34 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { let mut ctor_impl = self.initial_ctor_impl(ctx, &unit_field_int_ty); for bf in self.bitfields() { - bf.codegen(ctx, - fields_should_be_private, - codegen_depth, - accessor_kind, - parent, - anon_field_names, - result, - struct_layout, - fields, - methods, - (&unit_field_name, unit_field_int_ty.clone())); - - ctor_impl = bf.extend_ctor_impl(ctx, - parent, - ctor_impl, - &ctor_name, - &unit_field_int_ty); + bf.codegen( + ctx, + fields_should_be_private, + codegen_depth, + accessor_kind, + parent, + anon_field_names, + result, + struct_layout, + fields, + methods, + (&unit_field_name, unit_field_int_ty.clone()), + ); + + ctor_impl = bf.extend_ctor_impl( + ctx, + parent, + ctor_impl, + &ctor_name, + &unit_field_int_ty, + ); } match ctor_impl.unwrap().node { ast::ItemKind::Impl(_, _, _, _, _, items) => { assert_eq!(items.len(), 1); methods.extend(items.into_iter()); - }, + } _ => unreachable!(), }; @@ -1218,27 +1247,31 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { } } -fn parent_has_method(ctx: &BindgenContext, - parent: &CompInfo, - name: &str) - -> bool { +fn parent_has_method( + ctx: &BindgenContext, + parent: &CompInfo, + name: &str, +) -> bool { parent.methods().iter().any(|method| { let method_name = match *ctx.resolve_item(method.signature()).kind() { ItemKind::Function(ref func) => func.name(), - ref otherwise => panic!("a method's signature should always be a \ - item of kind ItemKind::Function, found: \ - {:?}", - otherwise), + ref otherwise => panic!( + "a method's signature should always be a \ + item of kind ItemKind::Function, found: \ + {:?}", + otherwise + ), }; method_name == name || ctx.rust_mangle(&method_name) == name }) } -fn bitfield_getter_name(ctx: &BindgenContext, - parent: &CompInfo, - bitfield_name: &str) - -> ast::Ident { +fn bitfield_getter_name( + ctx: &BindgenContext, + parent: &CompInfo, + bitfield_name: &str, +) -> ast::Ident { let name = ctx.rust_mangle(bitfield_name); if parent_has_method(ctx, parent, &name) { @@ -1250,10 +1283,11 @@ fn bitfield_getter_name(ctx: &BindgenContext, ctx.ext_cx().ident_of(&name) } -fn bitfield_setter_name(ctx: &BindgenContext, - parent: &CompInfo, - bitfield_name: &str) - -> ast::Ident { +fn bitfield_setter_name( + ctx: &BindgenContext, + parent: &CompInfo, + bitfield_name: &str, +) -> ast::Ident { let setter = format!("set_{}", bitfield_name); let mut setter = ctx.rust_mangle(&setter).to_string(); @@ -1267,21 +1301,22 @@ fn bitfield_setter_name(ctx: &BindgenContext, impl<'a> FieldCodegen<'a> for Bitfield { type Extra = (&'a str, P); - fn codegen(&self, - ctx: &BindgenContext, - _fields_should_be_private: bool, - _codegen_depth: usize, - _accessor_kind: FieldAccessorKind, - parent: &CompInfo, - _anon_field_names: &mut AnonFieldNames, - _result: &mut CodegenResult, - _struct_layout: &mut StructLayoutTracker, - _fields: &mut F, - methods: &mut M, - (unit_field_name, - unit_field_int_ty): (&'a str, P)) - where F: Extend, - M: Extend + fn codegen( + &self, + ctx: &BindgenContext, + _fields_should_be_private: bool, + _codegen_depth: usize, + _accessor_kind: FieldAccessorKind, + parent: &CompInfo, + _anon_field_names: &mut AnonFieldNames, + _result: &mut CodegenResult, + _struct_layout: &mut StructLayoutTracker, + _fields: &mut F, + methods: &mut M, + (unit_field_name, unit_field_int_ty): (&'a str, P), + ) where + F: Extend, + M: Extend, { let prefix = ctx.trait_prefix(); let getter_name = bitfield_getter_name(ctx, parent, self.name()); @@ -1291,11 +1326,13 @@ impl<'a> FieldCodegen<'a> for Bitfield { let bitfield_ty_item = ctx.resolve_item(self.ty()); let bitfield_ty = bitfield_ty_item.expect_type(); - let bitfield_ty_layout = bitfield_ty.layout(ctx) + let bitfield_ty_layout = bitfield_ty + .layout(ctx) .expect("Bitfield without layout? Gah!"); let bitfield_int_ty = BlobTyBuilder::new(bitfield_ty_layout).build(); - let bitfield_ty = bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item); + let bitfield_ty = + bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item); let offset = self.offset_into_unit(); let mask = self.mask(); @@ -1358,7 +1395,7 @@ impl<'a> FieldCodegen<'a> for Bitfield { match impl_item.unwrap().node { ast::ItemKind::Impl(_, _, _, _, _, items) => { methods.extend(items.into_iter()); - }, + } _ => unreachable!(), }; } @@ -1367,10 +1404,12 @@ impl<'a> FieldCodegen<'a> for Bitfield { impl CodeGenerator for CompInfo { type Extra = Item; - fn codegen<'a>(&self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - item: &Item) { + fn codegen<'a>( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'a>, + item: &Item, + ) { debug!("::codegen: item = {:?}", item); debug_assert!(item.is_enabled_for_codegen(ctx)); @@ -1403,6 +1442,7 @@ impl CodeGenerator for CompInfo { let mut attributes = vec![]; let mut needs_clone_impl = false; let mut needs_default_impl = false; + let mut needs_debug_impl = false; if let Some(comment) = item.comment(ctx) { attributes.push(attributes::doc(comment)); } @@ -1416,6 +1456,9 @@ impl CodeGenerator for CompInfo { let mut derives = vec![]; if item.can_derive_debug(ctx) { derives.push("Debug"); + } else { + needs_debug_impl = + ctx.options().derive_debug && ctx.options().impl_debug } if item.can_derive_default(ctx) { @@ -1424,8 +1467,7 @@ impl CodeGenerator for CompInfo { needs_default_impl = ctx.options().derive_default; } - if item.can_derive_copy(ctx) && - !item.annotations().disallow_copy() { + if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() { derives.push("Copy"); if used_template_params.is_some() { // FIXME: This requires extra logic if you have a big array in a @@ -1472,13 +1514,15 @@ impl CodeGenerator for CompInfo { // Also, we need to generate the vtable in such a way it "inherits" from // the parent too. let mut fields = vec![]; - let mut struct_layout = StructLayoutTracker::new(ctx, self, &canonical_name); + let mut struct_layout = + StructLayoutTracker::new(ctx, self, &canonical_name); if self.needs_explicit_vtable(ctx, item) { let vtable = Vtable::new(item.id(), self.methods(), self.base_members()); vtable.codegen(ctx, result, item); - let vtable_type = vtable.try_to_rust_ty(ctx, &()) + let vtable_type = vtable + .try_to_rust_ty(ctx, &()) .expect("vtable to Rust type conversion is infallible") .to_ptr(true, ctx.span()); @@ -1517,9 +1561,8 @@ impl CodeGenerator for CompInfo { struct_layout.saw_base(base_ty); - let field = StructFieldBuilder::named(field_name) - .pub_() - .build_ty(inner); + let field = + StructFieldBuilder::named(field_name).pub_().build_ty(inner); fields.extend(Some(field)); } if is_union { @@ -1528,9 +1571,8 @@ impl CodeGenerator for CompInfo { let layout = item.kind().expect_type().layout(ctx); - let fields_should_be_private = item.annotations() - .private_fields() - .unwrap_or(false); + let fields_should_be_private = + item.annotations().private_fields().unwrap_or(false); let struct_accessor_kind = item.annotations() .accessor_kind() .unwrap_or(FieldAccessorKind::None); @@ -1539,17 +1581,19 @@ impl CodeGenerator for CompInfo { let mut anon_field_names = AnonFieldNames::default(); let codegen_depth = item.codegen_depth(ctx); for field in self.fields() { - field.codegen(ctx, - fields_should_be_private, - codegen_depth, - struct_accessor_kind, - self, - &mut anon_field_names, - result, - &mut struct_layout, - &mut fields, - &mut methods, - ()); + field.codegen( + ctx, + fields_should_be_private, + codegen_depth, + struct_accessor_kind, + self, + &mut anon_field_names, + result, + &mut struct_layout, + &mut fields, + &mut methods, + (), + ); } if is_union && !ctx.options().unstable_rust { @@ -1573,10 +1617,10 @@ impl CodeGenerator for CompInfo { match layout { Some(l) => { let ty = BlobTyBuilder::new(l).build(); - let field = - StructFieldBuilder::named("_bindgen_opaque_blob") - .pub_() - .build_ty(ty); + let field = StructFieldBuilder::named( + "_bindgen_opaque_blob", + ).pub_() + .build_ty(ty); fields.push(field); } None => { @@ -1585,14 +1629,14 @@ impl CodeGenerator for CompInfo { } } else if !is_union && !self.is_unsized(ctx, &item.id()) { if let Some(padding_field) = - layout.and_then(|layout| { - struct_layout.pad_struct(layout) - }) { + layout.and_then(|layout| struct_layout.pad_struct(layout)) + { fields.push(padding_field); } if let Some(align_field) = - layout.and_then(|layout| struct_layout.align_struct(layout)) { + layout.and_then(|layout| struct_layout.align_struct(layout)) + { fields.push(align_field); } } @@ -1618,9 +1662,8 @@ impl CodeGenerator for CompInfo { if has_address { let ty = BlobTyBuilder::new(Layout::new(1, 1)).build(); - let field = StructFieldBuilder::named("_address") - .pub_() - .build_ty(ty); + let field = + StructFieldBuilder::named("_address").pub_().build_ty(ty); fields.push(field); } } @@ -1639,8 +1682,9 @@ impl CodeGenerator for CompInfo { let phantom_ty = quote_ty!( ctx.ext_cx(), ::$prefix::marker::PhantomData<::$prefix::cell::UnsafeCell<$ident>>); - let phantom_field = StructFieldBuilder::named(format!("_phantom_{}", idx)) - .pub_() + let phantom_field = StructFieldBuilder::named( + format!("_phantom_{}", idx), + ).pub_() .build_ty(phantom_ty); fields.push(phantom_field); } @@ -1648,7 +1692,8 @@ impl CodeGenerator for CompInfo { let generics = generics.build(); - let rust_struct = builder.with_generics(generics.clone()) + let rust_struct = builder + .with_generics(generics.clone()) .with_fields(fields) .build(); result.push(rust_struct); @@ -1667,21 +1712,23 @@ impl CodeGenerator for CompInfo { // affect layout, so we're bad and pray to the gods for avoid sending // all the tests to shit when parsing things like max_align_t. if self.found_unknown_attr() { - warn!("Type {} has an unkown attribute that may affect layout", - canonical_name); + warn!( + "Type {} has an unkown attribute that may affect layout", + canonical_name + ); } if used_template_params.is_none() { if !is_opaque { for var in self.inner_vars() { - ctx.resolve_item(*var) - .codegen(ctx, result, &()); + ctx.resolve_item(*var).codegen(ctx, result, &()); } } if ctx.options().layout_tests { if let Some(layout) = layout { - let fn_name = format!("bindgen_test_layout_{}", canonical_name); + let fn_name = + format!("bindgen_test_layout_{}", canonical_name); let fn_name = ctx.rust_ident_raw(&fn_name); let type_name = ctx.rust_ident_raw(&canonical_name); let prefix = ctx.trait_prefix(); @@ -1692,32 +1739,33 @@ impl CodeGenerator for CompInfo { let size = layout.size; let align = layout.align; - let check_struct_align = if align > mem::size_of::<*mut ()>() { - // FIXME when [RFC 1358](https://github.com/rust-lang/rust/issues/33626) ready - None - } else { - quote_item!(ctx.ext_cx(), + let check_struct_align = + if align > mem::size_of::<*mut ()>() { + // FIXME when [RFC 1358](https://github.com/rust-lang/rust/issues/33626) ready + None + } else { + quote_item!(ctx.ext_cx(), assert_eq!($align_of_expr, $align, concat!("Alignment of ", stringify!($type_name))); ) - }; + }; // FIXME when [issue #465](https://github.com/rust-lang-nursery/rust-bindgen/issues/465) ready let too_many_base_vtables = self.base_members() .iter() - .filter(|base| { - ctx.lookup_item_id_has_vtable(&base.ty) - }) - .count() > 1; + .filter(|base| ctx.lookup_item_id_has_vtable(&base.ty)) + .count() > + 1; let should_skip_field_offset_checks = is_opaque || too_many_base_vtables; - let check_field_offset = if should_skip_field_offset_checks { - None - } else { - let asserts = self.fields() + let check_field_offset = + if should_skip_field_offset_checks { + None + } else { + let asserts = self.fields() .iter() .filter_map(|field| match *field { Field::DataMember(ref f) if f.name().is_some() => Some(f), @@ -1738,8 +1786,8 @@ impl CodeGenerator for CompInfo { }) .collect::>>(); - Some(asserts) - }; + Some(asserts) + }; let item = quote_item!(ctx.ext_cx(), #[test] @@ -1760,25 +1808,30 @@ impl CodeGenerator for CompInfo { if ctx.options().codegen_config.methods { for method in self.methods() { assert!(method.kind() != MethodKind::Constructor); - method.codegen_method(ctx, - &mut methods, - &mut method_names, - result, - self); + method.codegen_method( + ctx, + &mut methods, + &mut method_names, + result, + self, + ); } } if ctx.options().codegen_config.constructors { for sig in self.constructors() { - Method::new(MethodKind::Constructor, - *sig, - /* const */ - false) - .codegen_method(ctx, - &mut methods, - &mut method_names, - result, - self); + Method::new( + MethodKind::Constructor, + *sig, + /* const */ + false, + ).codegen_method( + ctx, + &mut methods, + &mut method_names, + result, + self, + ); } } @@ -1790,12 +1843,13 @@ impl CodeGenerator for CompInfo { MethodKind::Destructor }; - Method::new(kind, destructor, false) - .codegen_method(ctx, - &mut methods, - &mut method_names, - result, - self); + Method::new(kind, destructor, false).codegen_method( + ctx, + &mut methods, + &mut method_names, + result, + self, + ); } } } @@ -1861,6 +1915,27 @@ impl CodeGenerator for CompInfo { result.push(default_impl); } + if needs_debug_impl { + let impl_ = derive_debug::gen_debug_impl( + ctx, + self.fields(), + item, + self.kind(), + ); + + let debug_impl = aster::AstBuilder::new() + .item() + .impl_() + .trait_() + .id("::std::fmt::Debug") + .build() + .with_generics(generics.clone()) + .with_items(impl_) + .build_ty(ty_for_impl.clone()); + + result.push(debug_impl); + } + if !methods.is_empty() { let methods = aster::AstBuilder::new() .item() @@ -1874,30 +1949,34 @@ impl CodeGenerator for CompInfo { } trait MethodCodegen { - fn codegen_method<'a>(&self, - ctx: &BindgenContext, - methods: &mut Vec, - method_names: &mut HashMap, - result: &mut CodegenResult<'a>, - parent: &CompInfo); + fn codegen_method<'a>( + &self, + ctx: &BindgenContext, + methods: &mut Vec, + method_names: &mut HashMap, + result: &mut CodegenResult<'a>, + parent: &CompInfo, + ); } impl MethodCodegen for Method { - fn codegen_method<'a>(&self, - ctx: &BindgenContext, - methods: &mut Vec, - method_names: &mut HashMap, - result: &mut CodegenResult<'a>, - _parent: &CompInfo) { + fn codegen_method<'a>( + &self, + ctx: &BindgenContext, + methods: &mut Vec, + method_names: &mut HashMap, + result: &mut CodegenResult<'a>, + _parent: &CompInfo, + ) { assert!({ let cc = &ctx.options().codegen_config; match self.kind() { MethodKind::Constructor => cc.constructors, MethodKind::Destructor => cc.destructors, MethodKind::VirtualDestructor => cc.destructors, - MethodKind::Static | - MethodKind::Normal | - MethodKind::Virtual => cc.methods, + MethodKind::Static | MethodKind::Normal | MethodKind::Virtual => { + cc.methods + } } }); @@ -1929,8 +2008,7 @@ impl MethodCodegen for Method { } let count = { - let mut count = method_names.entry(name.clone()) - .or_insert(0); + let mut count = method_names.entry(name.clone()).or_insert(0); *count += 1; *count - 1 }; @@ -1940,8 +2018,8 @@ impl MethodCodegen for Method { } let function_name = function_item.canonical_name(ctx); - let mut fndecl = utils::rust_fndecl_from_signature(ctx, signature_item) - .unwrap(); + let mut fndecl = + utils::rust_fndecl_from_signature(ctx, signature_item).unwrap(); if !self.is_static() && !self.is_constructor() { let mutability = if self.is_const() { ast::Mutability::Immutable @@ -1955,14 +2033,17 @@ impl MethodCodegen for Method { fndecl.inputs[0] = ast::Arg { ty: P(ast::Ty { id: ast::DUMMY_NODE_ID, - node: ast::TyKind::Rptr(None, ast::MutTy { - ty: P(ast::Ty { - id: ast::DUMMY_NODE_ID, - node: ast::TyKind::ImplicitSelf, - span: ctx.span() - }), - mutbl: mutability, - }), + node: ast::TyKind::Rptr( + None, + ast::MutTy { + ty: P(ast::Ty { + id: ast::DUMMY_NODE_ID, + node: ast::TyKind::ImplicitSelf, + span: ctx.span(), + }), + mutbl: mutability, + }, + ), span: ctx.span(), }), pat: P(ast::Pat { @@ -1970,7 +2051,7 @@ impl MethodCodegen for Method { node: ast::PatKind::Ident( ast::BindingMode::ByValue(ast::Mutability::Immutable), respan(ctx.span(), ctx.ext_cx().ident_of("self")), - None + None, ), span: ctx.span(), }), @@ -1985,8 +2066,8 @@ impl MethodCodegen for Method { // return-type = void. if self.is_constructor() { fndecl.inputs.remove(0); - fndecl.output = ast::FunctionRetTy::Ty(quote_ty!(ctx.ext_cx(), - Self)); + fndecl.output = + ast::FunctionRetTy::Ty(quote_ty!(ctx.ext_cx(), Self)); } let sig = ast::MethodSig { @@ -1997,8 +2078,8 @@ impl MethodCodegen for Method { constness: respan(ctx.span(), ast::Constness::NotConst), }; - let mut exprs = helpers::ast_ty::arguments_from_signature(&signature, - ctx); + let mut exprs = + helpers::ast_ty::arguments_from_signature(&signature, ctx); let mut stmts = vec![]; @@ -2074,17 +2155,19 @@ enum EnumBuilder<'a> { impl<'a> EnumBuilder<'a> { /// Create a new enum given an item builder, a canonical name, a name for /// the representation, and whether it should be represented as a rust enum. - fn new(aster: aster::item::ItemBuilder, - name: &'a str, - repr: P, - bitfield_like: bool, - constify: bool, - constify_module: bool) - -> Self { + fn new( + aster: aster::item::ItemBuilder, + name: &'a str, + repr: P, + bitfield_like: bool, + constify: bool, + constify_module: bool, + ) -> Self { if bitfield_like { EnumBuilder::Bitfield { canonical_name: name, - aster: aster.tuple_struct(name) + aster: aster + .tuple_struct(name) .field() .pub_() .build_ty(repr) @@ -2101,7 +2184,7 @@ impl<'a> EnumBuilder<'a> { module_name: name, module_items: vec![type_definition], } - } else { + } else { EnumBuilder::Consts { aster: aster.type_(name).build_ty(repr), } @@ -2112,13 +2195,14 @@ impl<'a> EnumBuilder<'a> { } /// Add a variant to this enum. - fn with_variant<'b>(self, - ctx: &BindgenContext, - variant: &EnumVariant, - mangling_prefix: Option<&String>, - rust_ty: P, - result: &mut CodegenResult<'b>) - -> Self { + fn with_variant<'b>( + self, + ctx: &BindgenContext, + variant: &EnumVariant, + mangling_prefix: Option<&String>, + rust_ty: P, + result: &mut CodegenResult<'b>, + ) -> Self { let variant_name = ctx.rust_mangle(variant.name()); let expr = aster::AstBuilder::new().expr(); let expr = match variant.val() { @@ -2135,7 +2219,9 @@ impl<'a> EnumBuilder<'a> { disr_expr: Some(expr), })) } - EnumBuilder::Bitfield { canonical_name, .. } => { + EnumBuilder::Bitfield { + canonical_name, .. + } => { let constant_name = match mangling_prefix { Some(prefix) => { Cow::Owned(format!("{}_{}", prefix, variant_name)) @@ -2157,7 +2243,9 @@ impl<'a> EnumBuilder<'a> { result.push(constant); self } - EnumBuilder::Consts { .. } => { + EnumBuilder::Consts { + .. + } => { let constant_name = match mangling_prefix { Some(prefix) => { Cow::Owned(format!("{}_{}", prefix, variant_name)) @@ -2176,10 +2264,15 @@ impl<'a> EnumBuilder<'a> { result.push(constant); self } - EnumBuilder::ModuleConsts { module_name, module_items, .. } => { + EnumBuilder::ModuleConsts { + module_name, + module_items, + .. + } => { // Variant type - let inside_module_type = - aster::AstBuilder::new().ty().id(CONSTIFIED_ENUM_MODULE_REPR_NAME); + let inside_module_type = aster::AstBuilder::new() + .ty() + .id(CONSTIFIED_ENUM_MODULE_REPR_NAME); let constant = aster::AstBuilder::new() .item() @@ -2200,14 +2293,18 @@ impl<'a> EnumBuilder<'a> { } } - fn build<'b>(self, - ctx: &BindgenContext, - rust_ty: P, - result: &mut CodegenResult<'b>) - -> P { + fn build<'b>( + self, + ctx: &BindgenContext, + rust_ty: P, + result: &mut CodegenResult<'b>, + ) -> P { match self { EnumBuilder::Rust(b) => b.build(), - EnumBuilder::Bitfield { canonical_name, aster } => { + EnumBuilder::Bitfield { + canonical_name, + aster, + } => { let rust_ty_name = ctx.rust_ident_raw(canonical_name); let prefix = ctx.trait_prefix(); @@ -2220,8 +2317,7 @@ impl<'a> EnumBuilder<'a> { $rust_ty_name(self.0 | other.0) } } - ) - .unwrap(); + ).unwrap(); result.push(impl_); let impl_ = quote_item!(ctx.ext_cx(), @@ -2231,8 +2327,7 @@ impl<'a> EnumBuilder<'a> { self.0 |= rhs.0; } } - ) - .unwrap(); + ).unwrap(); result.push(impl_); let impl_ = quote_item!(ctx.ext_cx(), @@ -2244,8 +2339,7 @@ impl<'a> EnumBuilder<'a> { $rust_ty_name(self.0 & other.0) } } - ) - .unwrap(); + ).unwrap(); result.push(impl_); let impl_ = quote_item!(ctx.ext_cx(), @@ -2255,14 +2349,19 @@ impl<'a> EnumBuilder<'a> { self.0 &= rhs.0; } } - ) - .unwrap(); + ).unwrap(); result.push(impl_); aster } - EnumBuilder::Consts { aster, .. } => aster, - EnumBuilder::ModuleConsts { module_items, module_name, .. } => { + EnumBuilder::Consts { + aster, .. + } => aster, + EnumBuilder::ModuleConsts { + module_items, + module_name, + .. + } => { // Create module item with type and variant definitions let module_item = P(ast::Item { ident: ast::Ident::from_str(module_name), @@ -2285,10 +2384,12 @@ impl<'a> EnumBuilder<'a> { impl CodeGenerator for Enum { type Extra = Item; - fn codegen<'a>(&self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - item: &Item) { + fn codegen<'a>( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'a>, + item: &Item, + ) { debug!("::codegen: item = {:?}", item); debug_assert!(item.is_enabled_for_codegen(ctx)); @@ -2298,21 +2399,22 @@ impl CodeGenerator for Enum { let repr = self.repr().map(|repr| ctx.resolve_type(repr)); let repr = match repr { - Some(repr) => { - match *repr.canonical_type(ctx).kind() { - TypeKind::Int(int_kind) => int_kind, - _ => panic!("Unexpected type as enum repr"), - } - } + Some(repr) => match *repr.canonical_type(ctx).kind() { + TypeKind::Int(int_kind) => int_kind, + _ => panic!("Unexpected type as enum repr"), + }, None => { - warn!("Guessing type of enum! Forward declarations of enums \ - shouldn't be legal!"); + warn!( + "Guessing type of enum! Forward declarations of enums \ + shouldn't be legal!" + ); IntKind::Int } }; let signed = repr.is_signed(); - let size = layout.map(|l| l.size) + let size = layout + .map(|l| l.size) .or_else(|| repr.known_size()) .unwrap_or(0); @@ -2337,21 +2439,22 @@ impl CodeGenerator for Enum { // disambiguate between namespaces, just like is_opaque etc. let is_bitfield = { ctx.options().bitfield_enums.matches(&name) || - (enum_ty.name().is_none() && - self.variants() - .iter() - .any(|v| ctx.options().bitfield_enums.matches(&v.name()))) + (enum_ty.name().is_none() && + self.variants().iter().any( + |v| ctx.options().bitfield_enums.matches(&v.name()), + )) }; - let is_constified_enum_module = self.is_constified_enum_module(ctx, item); + let is_constified_enum_module = + self.is_constified_enum_module(ctx, item); - let is_constified_enum = { + let is_constified_enum = { is_constified_enum_module || - ctx.options().constified_enums.matches(&name) || - (enum_ty.name().is_none() && - self.variants() - .iter() - .any(|v| ctx.options().constified_enums.matches(&v.name()))) + ctx.options().constified_enums.matches(&name) || + (enum_ty.name().is_none() && + self.variants().iter().any( + |v| ctx.options().constified_enums.matches(&v.name()), + )) }; let is_rust_enum = !is_bitfield && !is_constified_enum; @@ -2373,27 +2476,26 @@ impl CodeGenerator for Enum { } if !is_constified_enum { - let derives = attributes::derives(&["Debug", - "Copy", - "Clone", - "PartialEq", - "Eq", - "Hash"]); + let derives = attributes::derives( + &["Debug", "Copy", "Clone", "PartialEq", "Eq", "Hash"], + ); builder = builder.with_attr(derives); } - fn add_constant<'a>(ctx: &BindgenContext, - enum_: &Type, - // Only to avoid recomputing every time. - enum_canonical_name: &str, - // May be the same as "variant" if it's because the - // enum is unnamed and we still haven't seen the - // value. - variant_name: &str, - referenced_name: &str, - enum_rust_ty: P, - result: &mut CodegenResult<'a>) { + fn add_constant<'a>( + ctx: &BindgenContext, + enum_: &Type, + // Only to avoid recomputing every time. + enum_canonical_name: &str, + // May be the same as "variant" if it's because the + // enum is unnamed and we still haven't seen the + // value. + variant_name: &str, + referenced_name: &str, + enum_rust_ty: P, + result: &mut CodegenResult<'a>, + ) { let constant_name = if enum_.name().is_some() { if ctx.options().prepend_enum_name { format!("{}_{}", enum_canonical_name, variant_name) @@ -2420,12 +2522,14 @@ impl CodeGenerator for Enum { .and_then(|repr| repr.try_to_rust_ty_or_opaque(ctx, &()).ok()) .unwrap_or_else(|| helpers::ast_ty::raw_type(ctx, repr_name)); - let mut builder = EnumBuilder::new(builder, - &name, - repr, - is_bitfield, - is_constified_enum, - is_constified_enum_module); + let mut builder = EnumBuilder::new( + builder, + &name, + repr, + is_bitfield, + is_constified_enum, + is_constified_enum_module, + ); // A map where we keep a value -> variant relation. let mut seen_values = HashMap::<_, String>::new(); @@ -2455,8 +2559,9 @@ impl CodeGenerator for Enum { let mut constified_variants = VecDeque::new(); let mut iter = self.variants().iter().peekable(); - while let Some(variant) = iter.next() - .or_else(|| constified_variants.pop_front()) { + while let Some(variant) = + iter.next().or_else(|| constified_variants.pop_front()) + { if variant.hidden() { continue; } @@ -2467,43 +2572,46 @@ impl CodeGenerator for Enum { } match seen_values.entry(variant.val()) { - Entry::Occupied(ref entry) => { - if is_rust_enum { - let variant_name = ctx.rust_mangle(variant.name()); - let mangled_name = if is_toplevel || - enum_ty.name().is_some() { - variant_name - } else { - let parent_name = parent_canonical_name.as_ref() - .unwrap(); + Entry::Occupied(ref entry) => if is_rust_enum { + let variant_name = ctx.rust_mangle(variant.name()); + let mangled_name = if is_toplevel || + enum_ty.name().is_some() + { + variant_name + } else { + let parent_name = + parent_canonical_name.as_ref().unwrap(); - Cow::Owned(format!("{}_{}", - parent_name, - variant_name)) - }; + Cow::Owned(format!("{}_{}", parent_name, variant_name)) + }; - let existing_variant_name = entry.get(); - add_constant(ctx, - enum_ty, - &name, - &*mangled_name, - existing_variant_name, - enum_rust_ty.clone(), - result); - } else { - builder = builder.with_variant(ctx, - variant, - constant_mangling_prefix, - enum_rust_ty.clone(), - result); - } - } + let existing_variant_name = entry.get(); + add_constant( + ctx, + enum_ty, + &name, + &*mangled_name, + existing_variant_name, + enum_rust_ty.clone(), + result, + ); + } else { + builder = builder.with_variant( + ctx, + variant, + constant_mangling_prefix, + enum_rust_ty.clone(), + result, + ); + }, Entry::Vacant(entry) => { - builder = builder.with_variant(ctx, - variant, - constant_mangling_prefix, - enum_rust_ty.clone(), - result); + builder = builder.with_variant( + ctx, + variant, + constant_mangling_prefix, + enum_rust_ty.clone(), + result, + ); let variant_name = ctx.rust_mangle(variant.name()); @@ -2511,25 +2619,28 @@ impl CodeGenerator for Enum { // we also generate a constant so it can be properly // accessed. if (is_rust_enum && enum_ty.name().is_none()) || - variant.force_constification() { + variant.force_constification() + { let mangled_name = if is_toplevel { variant_name.clone() } else { - let parent_name = parent_canonical_name.as_ref() - .unwrap(); + let parent_name = + parent_canonical_name.as_ref().unwrap(); - Cow::Owned(format!("{}_{}", - parent_name, - variant_name)) + Cow::Owned( + format!("{}_{}", parent_name, variant_name), + ) }; - add_constant(ctx, - enum_ty, - &name, - &mangled_name, - &variant_name, - enum_rust_ty.clone(), - result); + add_constant( + ctx, + enum_ty, + &name, + &mangled_name, + &variant_name, + enum_rust_ty.clone(), + result, + ); } entry.insert(variant_name.into_owned()); @@ -2551,16 +2662,18 @@ trait TryToOpaque { type Extra; /// Get the layout for this thing, if one is available. - fn try_get_layout(&self, - ctx: &BindgenContext, - extra: &Self::Extra) - -> error::Result; + fn try_get_layout( + &self, + ctx: &BindgenContext, + extra: &Self::Extra, + ) -> error::Result; /// Do not override this provided trait method. - fn try_to_opaque(&self, - ctx: &BindgenContext, - extra: &Self::Extra) - -> error::Result> { + fn try_to_opaque( + &self, + ctx: &BindgenContext, + extra: &Self::Extra, + ) -> error::Result> { self.try_get_layout(ctx, extra) .map(|layout| BlobTyBuilder::new(layout).build()) } @@ -2577,26 +2690,26 @@ trait TryToOpaque { /// Don't implement this directly. Instead implement `TryToOpaque`, and then /// leverage the blanket impl for this trait. trait ToOpaque: TryToOpaque { - fn get_layout(&self, - ctx: &BindgenContext, - extra: &Self::Extra) - -> Layout { + fn get_layout(&self, ctx: &BindgenContext, extra: &Self::Extra) -> Layout { self.try_get_layout(ctx, extra) .unwrap_or_else(|_| Layout::for_size(1)) } - fn to_opaque(&self, - ctx: &BindgenContext, - extra: &Self::Extra) - -> P { + fn to_opaque( + &self, + ctx: &BindgenContext, + extra: &Self::Extra, + ) -> P { let layout = self.get_layout(ctx, extra); BlobTyBuilder::new(layout).build() } } impl ToOpaque for T - where T: TryToOpaque -{} +where + T: TryToOpaque, +{ +} /// Fallible conversion from an IR thing to an *equivalent* Rust type. /// @@ -2608,10 +2721,11 @@ impl ToOpaque for T trait TryToRustTy { type Extra; - fn try_to_rust_ty(&self, - ctx: &BindgenContext, - extra: &Self::Extra) - -> error::Result>; + fn try_to_rust_ty( + &self, + ctx: &BindgenContext, + extra: &Self::Extra, + ) -> error::Result>; } /// Fallible conversion to a Rust type or an opaque blob with the correct size @@ -2622,29 +2736,31 @@ trait TryToRustTy { trait TryToRustTyOrOpaque: TryToRustTy + TryToOpaque { type Extra; - fn try_to_rust_ty_or_opaque(&self, - ctx: &BindgenContext, - extra: &::Extra) - -> error::Result>; + fn try_to_rust_ty_or_opaque( + &self, + ctx: &BindgenContext, + extra: &::Extra, + ) -> error::Result>; } impl TryToRustTyOrOpaque for T - where T: TryToRustTy + TryToOpaque +where + T: TryToRustTy + TryToOpaque, { type Extra = E; - fn try_to_rust_ty_or_opaque(&self, - ctx: &BindgenContext, - extra: &E) - -> error::Result> { - self.try_to_rust_ty(ctx, extra) - .or_else(|_| { - if let Ok(layout) = self.try_get_layout(ctx, extra) { - Ok(BlobTyBuilder::new(layout).build()) - } else { - Err(error::Error::NoLayoutForOpaqueBlob) - } - }) + fn try_to_rust_ty_or_opaque( + &self, + ctx: &BindgenContext, + extra: &E, + ) -> error::Result> { + self.try_to_rust_ty(ctx, extra).or_else( + |_| if let Ok(layout) = self.try_get_layout(ctx, extra) { + Ok(BlobTyBuilder::new(layout).build()) + } else { + Err(error::Error::NoLayoutForOpaqueBlob) + }, + ) } } @@ -2668,21 +2784,24 @@ impl TryToRustTyOrOpaque for T trait ToRustTyOrOpaque: TryToRustTy + ToOpaque { type Extra; - fn to_rust_ty_or_opaque(&self, - ctx: &BindgenContext, - extra: &::Extra) - -> P; + fn to_rust_ty_or_opaque( + &self, + ctx: &BindgenContext, + extra: &::Extra, + ) -> P; } impl ToRustTyOrOpaque for T - where T: TryToRustTy + ToOpaque +where + T: TryToRustTy + ToOpaque, { type Extra = E; - fn to_rust_ty_or_opaque(&self, - ctx: &BindgenContext, - extra: &E) - -> P { + fn to_rust_ty_or_opaque( + &self, + ctx: &BindgenContext, + extra: &E, + ) -> P { self.try_to_rust_ty(ctx, extra) .unwrap_or_else(|_| self.to_opaque(ctx, extra)) } @@ -2691,10 +2810,11 @@ impl ToRustTyOrOpaque for T impl TryToOpaque for ItemId { type Extra = (); - fn try_get_layout(&self, - ctx: &BindgenContext, - _: &()) - -> error::Result { + fn try_get_layout( + &self, + ctx: &BindgenContext, + _: &(), + ) -> error::Result { ctx.resolve_item(*self).try_get_layout(ctx, &()) } } @@ -2702,10 +2822,11 @@ impl TryToOpaque for ItemId { impl TryToRustTy for ItemId { type Extra = (); - fn try_to_rust_ty(&self, - ctx: &BindgenContext, - _: &()) - -> error::Result> { + fn try_to_rust_ty( + &self, + ctx: &BindgenContext, + _: &(), + ) -> error::Result> { ctx.resolve_item(*self).try_to_rust_ty(ctx, &()) } } @@ -2713,10 +2834,11 @@ impl TryToRustTy for ItemId { impl TryToOpaque for Item { type Extra = (); - fn try_get_layout(&self, - ctx: &BindgenContext, - _: &()) - -> error::Result { + fn try_get_layout( + &self, + ctx: &BindgenContext, + _: &(), + ) -> error::Result { self.kind().expect_type().try_get_layout(ctx, self) } } @@ -2724,10 +2846,11 @@ impl TryToOpaque for Item { impl TryToRustTy for Item { type Extra = (); - fn try_to_rust_ty(&self, - ctx: &BindgenContext, - _: &()) - -> error::Result> { + fn try_to_rust_ty( + &self, + ctx: &BindgenContext, + _: &(), + ) -> error::Result> { self.kind().expect_type().try_to_rust_ty(ctx, self) } } @@ -2735,10 +2858,11 @@ impl TryToRustTy for Item { impl TryToOpaque for Type { type Extra = Item; - fn try_get_layout(&self, - ctx: &BindgenContext, - _: &Item) - -> error::Result { + fn try_get_layout( + &self, + ctx: &BindgenContext, + _: &Item, + ) -> error::Result { self.layout(ctx).ok_or(error::Error::NoLayoutForOpaqueBlob) } } @@ -2746,10 +2870,11 @@ impl TryToOpaque for Type { impl TryToRustTy for Type { type Extra = Item; - fn try_to_rust_ty(&self, - ctx: &BindgenContext, - item: &Item) - -> error::Result> { + fn try_to_rust_ty( + &self, + ctx: &BindgenContext, + item: &Item, + ) -> error::Result> { use self::helpers::ast_ty::*; match *self.kind() { @@ -2762,7 +2887,9 @@ impl TryToRustTy for Type { TypeKind::Int(ik) => { match ik { IntKind::Bool => Ok(aster::ty::TyBuilder::new().bool()), - IntKind::Char { .. } => Ok(raw_type(ctx, "c_char")), + IntKind::Char { + .. + } => Ok(raw_type(ctx, "c_char")), IntKind::SChar => Ok(raw_type(ctx, "c_schar")), IntKind::UChar => Ok(raw_type(ctx, "c_uchar")), IntKind::Short => Ok(raw_type(ctx, "c_short")), @@ -2782,7 +2909,9 @@ impl TryToRustTy for Type { IntKind::U32 => Ok(aster::ty::TyBuilder::new().u32()), IntKind::I64 => Ok(aster::ty::TyBuilder::new().i64()), IntKind::U64 => Ok(aster::ty::TyBuilder::new().u64()), - IntKind::Custom { name, .. } => { + IntKind::Custom { + name, .. + } => { let ident = ctx.rust_ident_raw(name); Ok(quote_ty!(ctx.ext_cx(), $ident)) } @@ -2821,18 +2950,13 @@ impl TryToRustTy for Type { } TypeKind::Enum(..) => { let path = item.namespace_aware_canonical_path(ctx); - Ok(aster::AstBuilder::new() - .ty() - .path() - .ids(path) - .build()) + Ok(aster::AstBuilder::new().ty().path().ids(path).build()) } TypeKind::TemplateInstantiation(ref inst) => { inst.try_to_rust_ty(ctx, item) } TypeKind::ResolvedTypeRef(inner) => inner.try_to_rust_ty(ctx, &()), - TypeKind::TemplateAlias(inner, _) | - TypeKind::Alias(inner) => { + TypeKind::TemplateAlias(inner, _) | TypeKind::Alias(inner) => { let template_params = item.used_template_params(ctx) .unwrap_or(vec![]) .into_iter() @@ -2842,9 +2966,9 @@ impl TryToRustTy for Type { let spelling = self.name().expect("Unnamed alias?"); if item.is_opaque(ctx, &()) && !template_params.is_empty() { self.try_to_opaque(ctx, item) - } else if let Some(ty) = utils::type_from_named(ctx, - spelling, - inner) { + } else if let Some(ty) = + utils::type_from_named(ctx, spelling, inner) + { Ok(ty) } else { utils::build_templated_path(item, ctx, template_params) @@ -2853,26 +2977,24 @@ impl TryToRustTy for Type { TypeKind::Comp(ref info) => { let template_params = item.used_template_params(ctx); if info.has_non_type_template_params() || - (item.is_opaque(ctx, &()) && template_params.is_some()) { + (item.is_opaque(ctx, &()) && template_params.is_some()) + { return self.try_to_opaque(ctx, item); } let template_params = template_params.unwrap_or(vec![]); - utils::build_templated_path(item, - ctx, - template_params) - } - TypeKind::Opaque => { - self.try_to_opaque(ctx, item) + utils::build_templated_path(item, ctx, template_params) } + TypeKind::Opaque => self.try_to_opaque(ctx, item), TypeKind::BlockPointer => { let void = raw_type(ctx, "c_void"); - Ok(void.to_ptr(/* is_const = */ - false, - ctx.span())) + Ok(void.to_ptr( + /* is_const = */ + false, + ctx.span(), + )) } - TypeKind::Pointer(inner) | - TypeKind::Reference(inner) => { + TypeKind::Pointer(inner) | TypeKind::Reference(inner) => { let inner = ctx.resolve_item(inner); let inner_ty = inner.expect_type(); @@ -2886,8 +3008,8 @@ impl TryToRustTy for Type { if inner_ty.canonical_type(ctx).is_function() { Ok(ty) } else { - let is_const = self.is_const() || - inner.expect_type().is_const(); + let is_const = + self.is_const() || inner.expect_type().is_const(); Ok(ty.to_ptr(is_const, ctx.span())) } } @@ -2896,9 +3018,12 @@ impl TryToRustTy for Type { let ident = ctx.rust_ident(&name); Ok(quote_ty!(ctx.ext_cx(), $ident)) } - TypeKind::ObjCSel => Ok(quote_ty!(ctx.ext_cx(), objc::runtime::Sel)), - TypeKind::ObjCId | - TypeKind::ObjCInterface(..) => Ok(quote_ty!(ctx.ext_cx(), id)), + TypeKind::ObjCSel => { + Ok(quote_ty!(ctx.ext_cx(), objc::runtime::Sel)) + } + TypeKind::ObjCId | TypeKind::ObjCInterface(..) => { + Ok(quote_ty!(ctx.ext_cx(), id)) + } ref u @ TypeKind::UnresolvedTypeRef(..) => { unreachable!("Should have been resolved after parsing {:?}!", u) } @@ -2909,21 +3034,25 @@ impl TryToRustTy for Type { impl TryToOpaque for TemplateInstantiation { type Extra = Item; - fn try_get_layout(&self, - ctx: &BindgenContext, - item: &Item) - -> error::Result { - item.expect_type().layout(ctx).ok_or(error::Error::NoLayoutForOpaqueBlob) + fn try_get_layout( + &self, + ctx: &BindgenContext, + item: &Item, + ) -> error::Result { + item.expect_type() + .layout(ctx) + .ok_or(error::Error::NoLayoutForOpaqueBlob) } } impl TryToRustTy for TemplateInstantiation { type Extra = Item; - fn try_to_rust_ty(&self, - ctx: &BindgenContext, - item: &Item) - -> error::Result> { + fn try_to_rust_ty( + &self, + ctx: &BindgenContext, + item: &Item, + ) -> error::Result> { if self.is_opaque(ctx, item) { return Err(error::Error::InstantiationOfOpaqueType); } @@ -2937,10 +3066,12 @@ impl TryToRustTy for TemplateInstantiation { // This can happen if we generated an opaque type for a partial // template specialization, and we've hit an instantiation of // that partial specialization. - extra_assert!(decl.into_resolver() - .through_type_refs() - .resolve(ctx) - .is_opaque(ctx, &())); + extra_assert!( + decl.into_resolver() + .through_type_refs() + .resolve(ctx) + .is_opaque(ctx, &()) + ); return Err(error::Error::InstantiationOfOpaqueType); } }; @@ -2963,18 +3094,18 @@ impl TryToRustTy for TemplateInstantiation { .map(|(arg, _)| arg.try_to_rust_ty(ctx, &())) .collect::>>()?; - path.segments.last_mut().unwrap().parameters = if - template_args.is_empty() { - None - } else { - Some(P(ast::PathParameters::AngleBracketed( - ast::AngleBracketedParameterData { - lifetimes: vec![], - types: template_args, - bindings: vec![], - } - ))) - } + path.segments.last_mut().unwrap().parameters = + if template_args.is_empty() { + None + } else { + Some(P(ast::PathParameters::AngleBracketed( + ast::AngleBracketedParameterData { + lifetimes: vec![], + types: template_args, + bindings: vec![], + }, + ))) + } } Ok(P(ty)) @@ -2984,10 +3115,11 @@ impl TryToRustTy for TemplateInstantiation { impl TryToRustTy for FunctionSig { type Extra = Item; - fn try_to_rust_ty(&self, - ctx: &BindgenContext, - item: &Item) - -> error::Result> { + fn try_to_rust_ty( + &self, + ctx: &BindgenContext, + item: &Item, + ) -> error::Result> { // TODO: we might want to consider ignoring the reference return value. let ret = utils::fnsig_return_ty(ctx, &self); let arguments = utils::fnsig_arguments(ctx, &self); @@ -3001,8 +3133,12 @@ impl TryToRustTy for FunctionSig { let abi = match self.abi() { Abi::Known(abi) => abi, Abi::Unknown(unknown_abi) => { - panic!("Invalid or unknown abi {:?} for function {:?} {:?}", - unknown_abi, item.canonical_name(ctx), self); + panic!( + "Invalid or unknown abi {:?} for function {:?} {:?}", + unknown_abi, + item.canonical_name(ctx), + self + ); } }; @@ -3024,10 +3160,12 @@ impl TryToRustTy for FunctionSig { impl CodeGenerator for Function { type Extra = Item; - fn codegen<'a>(&self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - item: &Item) { + fn codegen<'a>( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'a>, + item: &Item, + ) { debug!("::codegen: item = {:?}", item); debug_assert!(item.is_enabled_for_codegen(ctx)); @@ -3100,8 +3238,12 @@ impl CodeGenerator for Function { let abi = match signature.abi() { Abi::Known(abi) => abi, Abi::Unknown(unknown_abi) => { - panic!("Invalid or unknown abi {:?} for function {:?} ({:?})", - unknown_abi, canonical_name, self); + panic!( + "Invalid or unknown abi {:?} for function {:?} ({:?})", + unknown_abi, + canonical_name, + self + ); } }; @@ -3114,11 +3256,12 @@ impl CodeGenerator for Function { } -fn objc_method_codegen(ctx: &BindgenContext, - method: &ObjCMethod, - class_name: Option<&str>, - prefix: &str) - -> (ast::ImplItem, ast::TraitItem) { +fn objc_method_codegen( + ctx: &BindgenContext, + method: &ObjCMethod, + class_name: Option<&str>, + prefix: &str, +) -> (ast::ImplItem, ast::TraitItem) { let signature = method.signature(); let fn_args = utils::fnsig_arguments(ctx, signature); let fn_ret = utils::fnsig_return_ty(ctx, signature); @@ -3142,7 +3285,8 @@ fn objc_method_codegen(ctx: &BindgenContext, }; // Collect the actual used argument names - let arg_names: Vec<_> = fn_args.iter() + let arg_names: Vec<_> = fn_args + .iter() .map(|ref arg| match arg.pat.node { ast::PatKind::Ident(_, ref spanning, _) => { spanning.node.name.as_str().to_string() @@ -3157,9 +3301,9 @@ fn objc_method_codegen(ctx: &BindgenContext, ctx.rust_ident(&method.format_method_call(&arg_names)); let body = if method.is_class_method() { - let class_name = - class_name.expect("Generating a class method without class name?") - .to_owned(); + let class_name = class_name + .expect("Generating a class method without class name?") + .to_owned(); let expect_msg = format!("Couldn't find {}", class_name); quote_stmt!(ctx.ext_cx(), msg_send![objc::runtime::Class::get($class_name).expect($expect_msg), $methods_and_args]) @@ -3202,10 +3346,12 @@ fn objc_method_codegen(ctx: &BindgenContext, impl CodeGenerator for ObjCInterface { type Extra = Item; - fn codegen<'a>(&self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - item: &Item) { + fn codegen<'a>( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'a>, + item: &Item, + ) { debug_assert!(item.is_enabled_for_codegen(ctx)); let mut impl_items = vec![]; @@ -3218,18 +3364,20 @@ impl CodeGenerator for ObjCInterface { trait_items.push(trait_item) } - let instance_method_names : Vec<_> = self.methods().iter().map( { |m| m.rust_name() } ).collect(); + let instance_method_names: Vec<_> = + self.methods().iter().map({ |m| m.rust_name() }).collect(); for class_method in self.class_methods() { - let ambiquity = instance_method_names.contains(&class_method.rust_name()); - let prefix = if ambiquity { - "class_" - } else { - "" - }; - let (impl_item, trait_item) = - objc_method_codegen(ctx, class_method, Some(self.name()), prefix); + let ambiquity = + instance_method_names.contains(&class_method.rust_name()); + let prefix = if ambiquity { "class_" } else { "" }; + let (impl_item, trait_item) = objc_method_codegen( + ctx, + class_method, + Some(self.name()), + prefix, + ); impl_items.push(impl_item); trait_items.push(trait_item) } @@ -3289,7 +3437,7 @@ pub fn codegen(context: &mut BindgenContext) -> Vec> { } mod utils { - use super::{error, TryToRustTy, ToRustTyOrOpaque}; + use super::{error, ToRustTyOrOpaque, TryToRustTy}; use aster; use ir::context::{BindgenContext, ItemId}; use ir::function::FunctionSig; @@ -3299,35 +3447,36 @@ mod utils { use syntax::ast; use syntax::ptr::P; - pub fn prepend_objc_header(ctx: &BindgenContext, - result: &mut Vec>) { + pub fn prepend_objc_header( + ctx: &BindgenContext, + result: &mut Vec>, + ) { let use_objc = if ctx.options().objc_extern_crate { quote_item!(ctx.ext_cx(), #[macro_use] extern crate objc; - ) - .unwrap() + ).unwrap() } else { quote_item!(ctx.ext_cx(), use objc; - ) - .unwrap() + ).unwrap() }; let id_type = quote_item!(ctx.ext_cx(), #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; - ) - .unwrap(); + ).unwrap(); let items = vec![use_objc, id_type]; let old_items = mem::replace(result, items); result.extend(old_items.into_iter()); } - pub fn prepend_union_types(ctx: &BindgenContext, - result: &mut Vec>) { + pub fn prepend_union_types( + ctx: &BindgenContext, + result: &mut Vec>, + ) { let prefix = ctx.trait_prefix(); // TODO(emilio): The fmt::Debug impl could be way nicer with @@ -3336,8 +3485,7 @@ mod utils { #[repr(C)] pub struct __BindgenUnionField( ::$prefix::marker::PhantomData); - ) - .unwrap(); + ).unwrap(); let union_field_impl = quote_item!(&ctx.ext_cx(), impl __BindgenUnionField { @@ -3356,8 +3504,7 @@ mod utils { ::$prefix::mem::transmute(self) } } - ) - .unwrap(); + ).unwrap(); let union_field_default_impl = quote_item!(&ctx.ext_cx(), impl ::$prefix::default::Default for __BindgenUnionField { @@ -3366,8 +3513,7 @@ mod utils { Self::new() } } - ) - .unwrap(); + ).unwrap(); let union_field_clone_impl = quote_item!(&ctx.ext_cx(), impl ::$prefix::clone::Clone for __BindgenUnionField { @@ -3376,13 +3522,11 @@ mod utils { Self::new() } } - ) - .unwrap(); + ).unwrap(); let union_field_copy_impl = quote_item!(&ctx.ext_cx(), impl ::$prefix::marker::Copy for __BindgenUnionField {} - ) - .unwrap(); + ).unwrap(); let union_field_debug_impl = quote_item!(ctx.ext_cx(), impl ::$prefix::fmt::Debug for __BindgenUnionField { @@ -3391,8 +3535,7 @@ mod utils { fmt.write_str("__BindgenUnionField") } } - ) - .unwrap(); + ).unwrap(); let items = vec![union_field_decl, union_field_impl, @@ -3405,8 +3548,10 @@ mod utils { result.extend(old_items.into_iter()); } - pub fn prepend_incomplete_array_types(ctx: &BindgenContext, - result: &mut Vec>) { + pub fn prepend_incomplete_array_types( + ctx: &BindgenContext, + result: &mut Vec>, + ) { let prefix = ctx.trait_prefix(); let incomplete_array_decl = quote_item!(ctx.ext_cx(), @@ -3414,8 +3559,7 @@ mod utils { #[derive(Default)] pub struct __IncompleteArrayField( ::$prefix::marker::PhantomData); - ) - .unwrap(); + ).unwrap(); let incomplete_array_impl = quote_item!(&ctx.ext_cx(), impl __IncompleteArrayField { @@ -3444,8 +3588,7 @@ mod utils { ::$prefix::slice::from_raw_parts_mut(self.as_mut_ptr(), len) } } - ) - .unwrap(); + ).unwrap(); let incomplete_array_debug_impl = quote_item!(ctx.ext_cx(), impl ::$prefix::fmt::Debug for __IncompleteArrayField { @@ -3454,8 +3597,7 @@ mod utils { fmt.write_str("__IncompleteArrayField") } } - ) - .unwrap(); + ).unwrap(); let incomplete_array_clone_impl = quote_item!(&ctx.ext_cx(), impl ::$prefix::clone::Clone for __IncompleteArrayField { @@ -3464,13 +3606,11 @@ mod utils { Self::new() } } - ) - .unwrap(); + ).unwrap(); let incomplete_array_copy_impl = quote_item!(&ctx.ext_cx(), impl ::$prefix::marker::Copy for __IncompleteArrayField {} - ) - .unwrap(); + ).unwrap(); let items = vec![incomplete_array_decl, incomplete_array_impl, @@ -3482,8 +3622,10 @@ mod utils { result.extend(old_items.into_iter()); } - pub fn prepend_complex_type(ctx: &BindgenContext, - result: &mut Vec>) { + pub fn prepend_complex_type( + ctx: &BindgenContext, + result: &mut Vec>, + ) { let complex_type = quote_item!(ctx.ext_cx(), #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] #[repr(C)] @@ -3491,31 +3633,35 @@ mod utils { pub re: T, pub im: T } - ) - .unwrap(); + ).unwrap(); let items = vec![complex_type]; let old_items = mem::replace(result, items); result.extend(old_items.into_iter()); } - pub fn build_templated_path(item: &Item, - ctx: &BindgenContext, - template_params: Vec) - -> error::Result> { + pub fn build_templated_path( + item: &Item, + ctx: &BindgenContext, + template_params: Vec, + ) -> error::Result> { let path = item.namespace_aware_canonical_path(ctx); let builder = aster::AstBuilder::new().ty().path(); - let template_params = template_params.iter() + let template_params = template_params + .iter() .map(|param| param.try_to_rust_ty(ctx, &())) .collect::>>()?; // XXX: I suck at aster. if path.len() == 1 { - return Ok(builder.segment(&path[0]) - .with_tys(template_params) - .build() - .build()); + return Ok( + builder + .segment(&path[0]) + .with_tys(template_params) + .build() + .build(), + ); } let mut builder = builder.id(&path[0]); @@ -3523,7 +3669,8 @@ mod utils { // Take into account the skip(1) builder = if i == path.len() - 2 { // XXX Extra clone courtesy of the borrow checker. - builder.segment(&segment) + builder + .segment(&segment) .with_tys(template_params.clone()) .build() } else { @@ -3539,10 +3686,11 @@ mod utils { quote_ty!(ctx.ext_cx(), $ident) } - pub fn type_from_named(ctx: &BindgenContext, - name: &str, - _inner: ItemId) - -> Option> { + pub fn type_from_named( + ctx: &BindgenContext, + name: &str, + _inner: ItemId, + ) -> Option> { // FIXME: We could use the inner item to check this is really a // primitive type but, who the heck overrides these anyway? Some(match name { @@ -3557,23 +3705,23 @@ mod utils { "uintptr_t" | "size_t" => primitive_ty(ctx, "usize"), - "intptr_t" | "ptrdiff_t" | "ssize_t" => { - primitive_ty(ctx, "isize") - } + "intptr_t" | "ptrdiff_t" | "ssize_t" => primitive_ty(ctx, "isize"), _ => return None, }) } - pub fn rust_fndecl_from_signature(ctx: &BindgenContext, - sig: &Item) - -> P { + pub fn rust_fndecl_from_signature( + ctx: &BindgenContext, + sig: &Item, + ) -> P { let signature = sig.kind().expect_type().canonical_type(ctx); let signature = match *signature.kind() { TypeKind::Function(ref sig) => sig, _ => panic!("How?"), }; - let decl_ty = signature.try_to_rust_ty(ctx, sig) + let decl_ty = signature + .try_to_rust_ty(ctx, sig) .expect("function signature to Rust type conversion is infallible"); match decl_ty.unwrap().node { ast::TyKind::BareFn(bare_fn) => bare_fn.unwrap().decl, @@ -3581,9 +3729,10 @@ mod utils { } } - pub fn fnsig_return_ty(ctx: &BindgenContext, - sig: &FunctionSig) - -> ast::FunctionRetTy { + pub fn fnsig_return_ty( + ctx: &BindgenContext, + sig: &FunctionSig, + ) -> ast::FunctionRetTy { let return_item = ctx.resolve_item(sig.return_type()); if let TypeKind::Void = *return_item.kind().expect_type().kind() { ast::FunctionRetTy::Default(ctx.span()) @@ -3592,9 +3741,10 @@ mod utils { } } - pub fn fnsig_arguments(ctx: &BindgenContext, - sig: &FunctionSig) - -> Vec { + pub fn fnsig_arguments( + ctx: &BindgenContext, + sig: &FunctionSig, + ) -> Vec { use super::ToPtr; let mut unnamed_arguments = 0; sig.argument_types().iter().map(|&(ref name, ty)| { diff --git a/src/lib.rs b/src/lib.rs index 3a85382940..437de16e80 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,15 +4,12 @@ //! functions and use types defined in the header. //! //! See the [`Builder`](./struct.Builder.html) struct for usage. - #![deny(missing_docs)] #![deny(warnings)] #![deny(unused_extern_crates)] - // We internally use the deprecated BindgenOptions all over the place. Once we // remove its `pub` declaration, we can un-deprecate it and remove this pragma. #![allow(deprecated)] - // To avoid rather annoying warnings when matching with CXCursor_xxx as a // constant. #![allow(non_upper_case_globals)] @@ -86,14 +83,14 @@ use parse::{ClangItemParser, ParseError}; use regex_set::RegexSet; use std::fs::{File, OpenOptions}; -use std::iter; use std::io::{self, Write}; +use std::iter; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::sync::Arc; use syntax::ast; -use syntax::codemap::{DUMMY_SP, Span}; +use syntax::codemap::{Span, DUMMY_SP}; use syntax::print::pp::eof; use syntax::print::pprust; use syntax::ptr::P; @@ -179,7 +176,7 @@ pub fn builder() -> Builder { } impl Builder { - /// Generates the command line flags use for creating `Builder`. + /// Generates the command line flags use for creating `Builder`. pub fn command_line_flags(&self) -> Vec { let mut output_vector: Vec = Vec::new(); @@ -193,9 +190,11 @@ impl Builder { .get_items() .iter() .map(|item| { - output_vector.push("--bitfield-enum".into()); - output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into()); - }) + output_vector.push("--bitfield-enum".into()); + output_vector.push( + item.trim_left_matches("^").trim_right_matches("$").into(), + ); + }) .count(); self.options @@ -203,9 +202,11 @@ impl Builder { .get_items() .iter() .map(|item| { - output_vector.push("--constified-enum".into()); - output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into()); - }) + output_vector.push("--constified-enum".into()); + output_vector.push( + item.trim_left_matches("^").trim_right_matches("$").into(), + ); + }) .count(); self.options @@ -213,9 +214,11 @@ impl Builder { .get_items() .iter() .map(|item| { - output_vector.push("--constified-enum-module".into()); - output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into()); - }) + output_vector.push("--constified-enum-module".into()); + output_vector.push( + item.trim_left_matches("^").trim_right_matches("$").into(), + ); + }) .count(); self.options @@ -223,9 +226,11 @@ impl Builder { .get_items() .iter() .map(|item| { - output_vector.push("--blacklist-type".into()); - output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into()); - }) + output_vector.push("--blacklist-type".into()); + output_vector.push( + item.trim_left_matches("^").trim_right_matches("$").into(), + ); + }) .count(); if !self.options.layout_tests { @@ -236,6 +241,10 @@ impl Builder { output_vector.push("--no-derive-debug".into()); } + if !self.options.impl_debug { + output_vector.push("--force-derive-debug".into()); + } + if !self.options.derive_default { output_vector.push("--no-derive-default".into()); } else { @@ -285,9 +294,11 @@ impl Builder { .links .iter() .map(|&(ref item, _)| { - output_vector.push("--framework".into()); - output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into()); - }) + output_vector.push("--framework".into()); + output_vector.push( + item.trim_left_matches("^").trim_right_matches("$").into(), + ); + }) .count(); if !self.options.codegen_config.functions { @@ -297,7 +308,7 @@ impl Builder { output_vector.push("--generate".into()); //Temporary placeholder for below 4 options - let mut options:Vec = Vec::new(); + let mut options: Vec = Vec::new(); if self.options.codegen_config.functions { options.push("function".into()); } @@ -327,9 +338,11 @@ impl Builder { .links .iter() .map(|&(ref item, _)| { - output_vector.push("--clang-args".into()); - output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into()); - }) + output_vector.push("--clang-args".into()); + output_vector.push( + item.trim_left_matches("^").trim_right_matches("$").into(), + ); + }) .count(); if !self.options.convert_floats { @@ -349,27 +362,33 @@ impl Builder { .get_items() .iter() .map(|item| { - output_vector.push("--opaque-type".into()); - output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into()); - }) + output_vector.push("--opaque-type".into()); + output_vector.push( + item.trim_left_matches("^").trim_right_matches("$").into(), + ); + }) .count(); self.options .raw_lines .iter() .map(|item| { - output_vector.push("--raw-line".into()); - output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into()); - }) + output_vector.push("--raw-line".into()); + output_vector.push( + item.trim_left_matches("^").trim_right_matches("$").into(), + ); + }) .count(); self.options .links .iter() .map(|&(ref item, _)| { - output_vector.push("--static".into()); - output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into()); - }) + output_vector.push("--static".into()); + output_vector.push( + item.trim_left_matches("^").trim_right_matches("$").into(), + ); + }) .count(); if self.options.use_core { @@ -385,9 +404,11 @@ impl Builder { .get_items() .iter() .map(|item| { - output_vector.push("--whitelist-function".into()); - output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into()); - }) + output_vector.push("--whitelist-function".into()); + output_vector.push( + item.trim_left_matches("^").trim_right_matches("$").into(), + ); + }) .count(); self.options @@ -395,9 +416,11 @@ impl Builder { .get_items() .iter() .map(|item| { - output_vector.push("--whitelist-type".into()); - output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into()); - }) + output_vector.push("--whitelist-type".into()); + output_vector.push( + item.trim_left_matches("^").trim_right_matches("$").into(), + ); + }) .count(); self.options @@ -405,24 +428,25 @@ impl Builder { .get_items() .iter() .map(|item| { - output_vector.push("--whitelist-var".into()); - output_vector.push(item.trim_left_matches("^").trim_right_matches("$").into()); - }) + output_vector.push("--whitelist-var".into()); + output_vector.push( + item.trim_left_matches("^").trim_right_matches("$").into(), + ); + }) .count(); output_vector.push("--".into()); if !self.options.clang_args.is_empty() { - output_vector.extend( - self.options - .clang_args - .iter() - .cloned() - ); + output_vector.extend(self.options.clang_args.iter().cloned()); } if self.input_headers.len() > 1 { - output_vector.extend(self.input_headers[..self.input_headers.len() - 1].iter().cloned()); + output_vector.extend( + self.input_headers[..self.input_headers.len() - 1] + .iter() + .cloned(), + ); } output_vector @@ -459,7 +483,8 @@ impl Builder { /// /// The file `name` will be added to the clang arguments. pub fn header_contents(mut self, name: &str, contents: &str) -> Builder { - self.input_header_contents.push((name.into(), contents.into())); + self.input_header_contents + .push((name.into(), contents.into())); self } @@ -595,8 +620,10 @@ impl Builder { /// Add arguments to be passed straight through to clang. pub fn clang_args(mut self, iter: I) -> Builder - where I: IntoIterator, - I::Item: AsRef { + where + I: IntoIterator, + I::Item: AsRef, + { for arg in iter { self = self.clang_arg(arg.as_ref()) } @@ -617,7 +644,9 @@ impl Builder { /// Make the generated bindings link the given framework. pub fn link_framework>(mut self, library: T) -> Builder { - self.options.links.push((library.into(), LinkType::Framework)); + self.options + .links + .push((library.into(), LinkType::Framework)); self } @@ -646,6 +675,12 @@ impl Builder { self } + /// Set whether `Debug` should be implemented, if it can not be derived automatically. + pub fn impl_debug(mut self, doit: bool) -> Self { + self.options.impl_debug = doit; + self + } + /// Set whether `Default` should be derived by default. pub fn derive_default(mut self, doit: bool) -> Self { self.options.derive_default = doit; @@ -763,7 +798,10 @@ impl Builder { /// Allows configuring types in different situations, see the /// [`ParseCallbacks`](./callbacks/trait.ParseCallbacks.html) documentation. - pub fn parse_callbacks(mut self, cb: Box) -> Self { + pub fn parse_callbacks( + mut self, + cb: Box, + ) -> Self { self.options.parse_callbacks = Some(cb); self } @@ -785,18 +823,17 @@ impl Builder { pub fn generate<'ctx>(mut self) -> Result, ()> { self.options.input_header = self.input_headers.pop(); self.options.clang_args.extend( - self.input_headers - .drain(..) - .flat_map(|header| { - iter::once("-include".into()) - .chain(iter::once(header)) - }) + self.input_headers.drain(..).flat_map(|header| { + iter::once("-include".into()).chain(iter::once(header)) + }), ); self.options.input_unsaved_files.extend( self.input_header_contents .drain(..) - .map(|(name, contents)| clang::UnsavedFile::new(&name, &contents)) + .map(|(name, contents)| { + clang::UnsavedFile::new(&name, &contents) + }), ); Bindings::generate(self.options, None) @@ -809,8 +846,12 @@ impl Builder { /// `__bindgen.ii` pub fn dump_preprocessed_input(&self) -> io::Result<()> { let clang = clang_sys::support::Clang::find(None, &[]) - .ok_or_else(|| io::Error::new(io::ErrorKind::Other, - "Cannot find clang executable"))?; + .ok_or_else(|| { + io::Error::new( + io::ErrorKind::Other, + "Cannot find clang executable", + ) + })?; // The contents of a wrapper file that includes all the input header // files. @@ -879,8 +920,10 @@ impl Builder { if child.wait()?.success() { Ok(()) } else { - Err(io::Error::new(io::ErrorKind::Other, - "clang exited with non-zero status")) + Err(io::Error::new( + io::ErrorKind::Other, + "clang exited with non-zero status", + )) } } } @@ -951,6 +994,10 @@ pub struct BindgenOptions { /// and types. pub derive_debug: bool, + /// True if we should implement the Debug trait for C/C++ structures and types + /// that do not support automatically deriving Debug. + pub impl_debug: bool, + /// True if we should derive Default trait implementations for C/C++ structures /// and types. pub derive_default: bool, @@ -1063,6 +1110,7 @@ impl Default for BindgenOptions { emit_ir_graphviz: None, layout_tests: true, derive_debug: true, + impl_debug: false, derive_default: false, enable_cxx_namespaces: false, disable_name_namespacing: false, @@ -1135,9 +1183,10 @@ impl<'ctx> Bindings<'ctx> { /// /// Deprecated - use a `Builder` instead #[deprecated] - pub fn generate(mut options: BindgenOptions, - span: Option) - -> Result, ()> { + pub fn generate( + mut options: BindgenOptions, + span: Option, + ) -> Result, ()> { let span = span.unwrap_or(DUMMY_SP); ensure_libclang_is_loaded(); @@ -1171,10 +1220,13 @@ impl<'ctx> Bindings<'ctx> { }; // TODO: Make this path fixup configurable? - if let Some(clang) = clang_sys::support::Clang::find(None, &clang_args_for_clang_sys) { + if let Some(clang) = + clang_sys::support::Clang::find(None, &clang_args_for_clang_sys) + { // If --target is specified, assume caller knows what they're doing // and don't mess with include paths for them - let has_target_arg = options.clang_args + let has_target_arg = options + .clang_args .iter() .rposition(|arg| arg.starts_with("--target")) .is_some(); @@ -1224,25 +1276,29 @@ impl<'ctx> Bindings<'ctx> { let mut mod_str = vec![]; { let ref_writer = Box::new(mod_str.by_ref()) as Box; - self.write(ref_writer).expect("Could not write bindings to string"); + self.write(ref_writer) + .expect("Could not write bindings to string"); } String::from_utf8(mod_str).unwrap() } /// Write these bindings as source text to a file. pub fn write_to_file>(&self, path: P) -> io::Result<()> { - let file = try!(OpenOptions::new() - .write(true) - .truncate(true) - .create(true) - .open(path)); + let file = try!( + OpenOptions::new() + .write(true) + .truncate(true) + .create(true) + .open(path) + ); self.write(Box::new(file)) } /// Write these bindings as source text to the given `Write`able. pub fn write<'a>(&self, mut writer: Box) -> io::Result<()> { - try!(writer.write("/* automatically generated by rust-bindgen */\n\n" - .as_bytes())); + try!(writer.write( + "/* automatically generated by rust-bindgen */\n\n".as_bytes(), + )); for line in self.context.options().raw_lines.iter() { try!(writer.write(line.as_bytes())); @@ -1267,10 +1323,11 @@ fn filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool { } /// Parse one `Item` from the Clang cursor. -pub fn parse_one(ctx: &mut BindgenContext, - cursor: clang::Cursor, - parent: Option) - -> clang_sys::CXChildVisitResult { +pub fn parse_one( + ctx: &mut BindgenContext, + cursor: clang::Cursor, + parent: Option, +) -> clang_sys::CXChildVisitResult { if !filter_builtins(ctx, &cursor) { return CXChildVisit_Continue; } @@ -1321,8 +1378,10 @@ fn parse(context: &mut BindgenContext) -> Result<(), ()> { cursor.visit(|cursor| parse_one(context, cursor, None)) }); - assert!(context.current_module() == context.root_module(), - "How did this happen?"); + assert!( + context.current_module() == context.root_module(), + "How did this happen?" + ); Ok(()) } @@ -1343,25 +1402,24 @@ pub fn clang_version() -> ClangVersion { } let raw_v: String = clang::extract_clang_version(); - let split_v: Option> = raw_v.split_whitespace() + let split_v: Option> = raw_v + .split_whitespace() .nth(2) .map(|v| v.split('.').collect()); match split_v { - Some(v) => { - if v.len() >= 2 { - let maybe_major = v[0].parse::(); - let maybe_minor = v[1].parse::(); - match (maybe_major, maybe_minor) { - (Ok(major), Ok(minor)) => { - return ClangVersion { - parsed: Some((major, minor)), - full: raw_v.clone(), - } + Some(v) => if v.len() >= 2 { + let maybe_major = v[0].parse::(); + let maybe_minor = v[1].parse::(); + match (maybe_major, maybe_minor) { + (Ok(major), Ok(minor)) => { + return ClangVersion { + parsed: Some((major, minor)), + full: raw_v.clone(), } - _ => {} } + _ => {} } - } + }, None => {} }; ClangVersion { @@ -1377,30 +1435,45 @@ fn commandline_flag_unit_test_function() { let bindings = ::builder(); let command_line_flags = bindings.command_line_flags(); - let test_cases = vec!["--no-derive-default", - "--generate", "function,types,vars,methods,constructors,destructors"] - .iter() - .map(|&x| x.into()) - .collect::>(); + let test_cases = vec![ + "--no-derive-default", + "--generate", + "function,types,vars,methods,constructors,destructors", + ].iter() + .map(|&x| x.into()) + .collect::>(); - assert!(test_cases.iter().all(|ref x| command_line_flags.contains(x)) ); + assert!( + test_cases + .iter() + .all(|ref x| command_line_flags.contains(x),) + ); //Test 2 - let bindings = ::builder().header("input_header") - .whitelisted_type("Distinct_Type") - .whitelisted_function("safe_function"); + let bindings = ::builder() + .header("input_header") + .whitelisted_type("Distinct_Type") + .whitelisted_function("safe_function"); let command_line_flags = bindings.command_line_flags(); - let test_cases = vec!["input_header", - "--no-derive-default", - "--generate", "function,types,vars,methods,constructors,destructors", - "--whitelist-type", "Distinct_Type", - "--whitelist-function", "safe_function"] - .iter() - .map(|&x| x.into()) - .collect::>(); + let test_cases = vec![ + "input_header", + "--no-derive-default", + "--generate", + "function,types,vars,methods,constructors,destructors", + "--whitelist-type", + "Distinct_Type", + "--whitelist-function", + "safe_function", + ].iter() + .map(|&x| x.into()) + .collect::>(); println!("{:?}", command_line_flags); - assert!(test_cases.iter().all(|ref x| command_line_flags.contains(x)) ); + assert!( + test_cases + .iter() + .all(|ref x| command_line_flags.contains(x),) + ); } diff --git a/src/options.rs b/src/options.rs index f2ed549410..b122f39db9 100644 --- a/src/options.rs +++ b/src/options.rs @@ -1,13 +1,14 @@ -use bindgen::{Builder, CodegenConfig, builder}; +use bindgen::{builder, Builder, CodegenConfig}; use clap::{App, Arg}; use std::fs::File; use std::io::{self, Error, ErrorKind}; /// Construct a new [`Builder`](./struct.Builder.html) from command line flags. -pub fn builder_from_flags - (args: I) - -> Result<(Builder, Box, bool), io::Error> - where I: Iterator, +pub fn builder_from_flags( + args: I, +) -> Result<(Builder, Box, bool), io::Error> +where + I: Iterator, { let matches = App::new("bindgen") .version(env!("CARGO_PKG_VERSION")) @@ -55,6 +56,9 @@ pub fn builder_from_flags Arg::with_name("no-derive-debug") .long("no-derive-debug") .help("Avoid deriving Debug on any type."), + Arg::with_name("force-derive-debug") + .long("force-derive-debug") + .help("Create Debug implementation, if it can not be derived automatically."), Arg::with_name("no-derive-default") .long("no-derive-default") .hidden(true) @@ -261,6 +265,10 @@ pub fn builder_from_flags builder = builder.derive_debug(false); } + if matches.is_present("force-derive-debug") { + builder = builder.impl_debug(true); + } + if matches.is_present("with-derive-default") { builder = builder.derive_default(true); } @@ -294,9 +302,10 @@ pub fn builder_from_flags "constructors" => config.constructors = true, "destructors" => config.destructors = true, otherwise => { - return Err(Error::new(ErrorKind::Other, - format!("Unknown generate item: {}", - otherwise))); + return Err(Error::new( + ErrorKind::Other, + format!("Unknown generate item: {}", otherwise), + )); } } } diff --git a/tests/expectations/tests/derive-debug-bitfield.rs b/tests/expectations/tests/derive-debug-bitfield.rs new file mode 100644 index 0000000000..62e941e4a8 --- /dev/null +++ b/tests/expectations/tests/derive-debug-bitfield.rs @@ -0,0 +1,119 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +#[derive(Copy)] +pub struct C { + pub _bitfield_1: u8, + pub large_array: [::std::os::raw::c_int; 50usize], +} +#[test] +fn bindgen_test_layout_C() { + assert_eq!(::std::mem::size_of::() , 204usize , concat ! ( + "Size of: " , stringify ! ( C ) )); + assert_eq! (::std::mem::align_of::() , 4usize , concat ! ( + "Alignment of " , stringify ! ( C ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const C ) ) . large_array as * const _ as usize + } , 4usize , concat ! ( + "Alignment of field: " , stringify ! ( C ) , "::" , stringify + ! ( large_array ) )); +} +impl Clone for C { + fn clone(&self) -> Self { *self } +} +impl Default for C { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +impl ::std::fmt::Debug for C { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f , "C {{ a : {:?}, b : {:?}, large_array: [{}] }}" , self . a + ( ) , self . b ( ) , self . large_array . iter ( ) . + enumerate ( ) . map ( + | ( i , v ) | format ! ( + "{}{:?}" , if i > 0 { ", " } else { "" } , v ) ) . collect :: < + String > ( )) + } +} +impl C { + #[inline] + pub fn a(&self) -> bool { + let mut unit_field_val: u8 = unsafe { ::std::mem::uninitialized() }; + unsafe { + ::std::ptr::copy_nonoverlapping(&self._bitfield_1 as *const _ as + *const u8, + &mut unit_field_val as *mut u8 as + *mut u8, + ::std::mem::size_of::()) + }; + let mask = 1u64 as u8; + let val = (unit_field_val & mask) >> 0usize; + unsafe { ::std::mem::transmute(val as u8) } + } + #[inline] + pub fn set_a(&mut self, val: bool) { + let mask = 1u64 as u8; + let val = val as u8 as u8; + let mut unit_field_val: u8 = unsafe { ::std::mem::uninitialized() }; + unsafe { + ::std::ptr::copy_nonoverlapping(&self._bitfield_1 as *const _ as + *const u8, + &mut unit_field_val as *mut u8 as + *mut u8, + ::std::mem::size_of::()) + }; + unit_field_val &= !mask; + unit_field_val |= (val << 0usize) & mask; + unsafe { + ::std::ptr::copy_nonoverlapping(&unit_field_val as *const _ as + *const u8, + &mut self._bitfield_1 as *mut _ as + *mut u8, + ::std::mem::size_of::()); + } + } + #[inline] + pub fn b(&self) -> bool { + let mut unit_field_val: u8 = unsafe { ::std::mem::uninitialized() }; + unsafe { + ::std::ptr::copy_nonoverlapping(&self._bitfield_1 as *const _ as + *const u8, + &mut unit_field_val as *mut u8 as + *mut u8, + ::std::mem::size_of::()) + }; + let mask = 254u64 as u8; + let val = (unit_field_val & mask) >> 1usize; + unsafe { ::std::mem::transmute(val as u8) } + } + #[inline] + pub fn set_b(&mut self, val: bool) { + let mask = 254u64 as u8; + let val = val as u8 as u8; + let mut unit_field_val: u8 = unsafe { ::std::mem::uninitialized() }; + unsafe { + ::std::ptr::copy_nonoverlapping(&self._bitfield_1 as *const _ as + *const u8, + &mut unit_field_val as *mut u8 as + *mut u8, + ::std::mem::size_of::()) + }; + unit_field_val &= !mask; + unit_field_val |= (val << 1usize) & mask; + unsafe { + ::std::ptr::copy_nonoverlapping(&unit_field_val as *const _ as + *const u8, + &mut self._bitfield_1 as *mut _ as + *mut u8, + ::std::mem::size_of::()); + } + } + #[inline] + pub fn new_bitfield_1(a: bool, b: bool) -> u8 { + ({ ({ 0 } | ((a as u8 as u8) << 0usize) & (1u64 as u8)) } | + ((b as u8 as u8) << 1usize) & (254u64 as u8)) + } +} diff --git a/tests/expectations/tests/derive-debug-function-pointer.rs b/tests/expectations/tests/derive-debug-function-pointer.rs new file mode 100644 index 0000000000..03cafe9769 --- /dev/null +++ b/tests/expectations/tests/derive-debug-function-pointer.rs @@ -0,0 +1,47 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +#[derive(Copy)] +pub struct Nice { + pub pointer: Nice_Function, + pub large_array: [::std::os::raw::c_int; 34usize], +} +pub type Nice_Function = + ::std::option::Option; +#[test] +fn bindgen_test_layout_Nice() { + assert_eq!(::std::mem::size_of::() , 144usize , concat ! ( + "Size of: " , stringify ! ( Nice ) )); + assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( + "Alignment of " , stringify ! ( Nice ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Nice ) ) . pointer as * const _ as usize + } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( Nice ) , "::" , + stringify ! ( pointer ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Nice ) ) . large_array as * const _ as + usize } , 8usize , concat ! ( + "Alignment of field: " , stringify ! ( Nice ) , "::" , + stringify ! ( large_array ) )); +} +impl Clone for Nice { + fn clone(&self) -> Self { *self } +} +impl Default for Nice { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +impl ::std::fmt::Debug for Nice { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f , "Nice {{ pointer: {:?}, large_array: [{}] }}" , self . + pointer , self . large_array . iter ( ) . enumerate ( ) . map + ( + | ( i , v ) | format ! ( + "{}{:?}" , if i > 0 { ", " } else { "" } , v ) ) . collect :: < + String > ( )) + } +} diff --git a/tests/expectations/tests/derive-debug-generic.rs b/tests/expectations/tests/derive-debug-generic.rs new file mode 100644 index 0000000000..f238234afd --- /dev/null +++ b/tests/expectations/tests/derive-debug-generic.rs @@ -0,0 +1,19 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +pub struct Generic { + pub t: [T; 40usize], + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, +} +impl Default for Generic { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +impl ::std::fmt::Debug for Generic { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f , "Generic {{ t: Array with length 40 }}") + } +} diff --git a/tests/expectations/tests/derive-debug-opaque-template-instantiation.rs b/tests/expectations/tests/derive-debug-opaque-template-instantiation.rs new file mode 100644 index 0000000000..e552925527 --- /dev/null +++ b/tests/expectations/tests/derive-debug-opaque-template-instantiation.rs @@ -0,0 +1,30 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +pub struct Instance { + pub val: [u32; 50usize], +} +#[test] +fn bindgen_test_layout_Instance() { + assert_eq!(::std::mem::size_of::() , 200usize , concat ! ( + "Size of: " , stringify ! ( Instance ) )); + assert_eq! (::std::mem::align_of::() , 4usize , concat ! ( + "Alignment of " , stringify ! ( Instance ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Instance ) ) . val as * const _ as usize + } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( Instance ) , "::" , + stringify ! ( val ) )); +} +impl Default for Instance { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +impl ::std::fmt::Debug for Instance { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f , "Instance {{ val: opaque }}") + } +} diff --git a/tests/expectations/tests/derive-debug-opaque.rs b/tests/expectations/tests/derive-debug-opaque.rs new file mode 100644 index 0000000000..267aca11f4 --- /dev/null +++ b/tests/expectations/tests/derive-debug-opaque.rs @@ -0,0 +1,49 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +pub struct Opaque { + pub _bindgen_opaque_blob: [u32; 41usize], +} +#[test] +fn bindgen_test_layout_Opaque() { + assert_eq!(::std::mem::size_of::() , 164usize , concat ! ( + "Size of: " , stringify ! ( Opaque ) )); + assert_eq! (::std::mem::align_of::() , 4usize , concat ! ( + "Alignment of " , stringify ! ( Opaque ) )); +} +impl Default for Opaque { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +impl ::std::fmt::Debug for Opaque { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f , "Opaque {{ opaque }}") + } +} +#[repr(C)] +pub struct OpaqueUser { + pub opaque: Opaque, +} +#[test] +fn bindgen_test_layout_OpaqueUser() { + assert_eq!(::std::mem::size_of::() , 164usize , concat ! ( + "Size of: " , stringify ! ( OpaqueUser ) )); + assert_eq! (::std::mem::align_of::() , 4usize , concat ! ( + "Alignment of " , stringify ! ( OpaqueUser ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const OpaqueUser ) ) . opaque as * const _ as + usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( OpaqueUser ) , "::" , + stringify ! ( opaque ) )); +} +impl Default for OpaqueUser { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +impl ::std::fmt::Debug for OpaqueUser { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f , "OpaqueUser {{ opaque: {:?} }}" , self . opaque) + } +} diff --git a/tests/headers/derive-debug-bitfield.hpp b/tests/headers/derive-debug-bitfield.hpp new file mode 100644 index 0000000000..4d8c377113 --- /dev/null +++ b/tests/headers/derive-debug-bitfield.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --opaque-type "Opaque" --force-derive-debug + +class C { + bool a: 1; + bool b: 7; + int large_array[50]; +}; diff --git a/tests/headers/derive-debug-function-pointer.hpp b/tests/headers/derive-debug-function-pointer.hpp new file mode 100644 index 0000000000..df746da5f1 --- /dev/null +++ b/tests/headers/derive-debug-function-pointer.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --force-derive-debug + +class Nice { + typedef void (*Function) (int data); + Function pointer; + int large_array[34]; +}; diff --git a/tests/headers/derive-debug-generic.hpp b/tests/headers/derive-debug-generic.hpp new file mode 100644 index 0000000000..58afac45a7 --- /dev/null +++ b/tests/headers/derive-debug-generic.hpp @@ -0,0 +1,6 @@ +// bindgen-flags: --force-derive-debug + +template +class Generic { + T t[40]; +}; diff --git a/tests/headers/derive-debug-opaque-template-instantiation.hpp b/tests/headers/derive-debug-opaque-template-instantiation.hpp new file mode 100644 index 0000000000..555ba82613 --- /dev/null +++ b/tests/headers/derive-debug-opaque-template-instantiation.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --force-derive-debug + +template +class Opaque { + T array[N]; +}; + +class Instance { + Opaque val; +}; diff --git a/tests/headers/derive-debug-opaque.hpp b/tests/headers/derive-debug-opaque.hpp new file mode 100644 index 0000000000..05c504a983 --- /dev/null +++ b/tests/headers/derive-debug-opaque.hpp @@ -0,0 +1,10 @@ +// bindgen-flags: --opaque-type "Opaque" --force-derive-debug + +class Opaque { + int i; + int not_debug[40]; +}; + +class OpaqueUser { + Opaque opaque; +};