From b541f4c98e549391e1f51a3f05be96dcd1305386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20K=C3=B6cher?= Date: Fri, 4 Aug 2017 17:15:41 +0200 Subject: [PATCH] Implements Debug trait for types which do not support derive Debug For types that do not support derive Debug be implemented automatically by rust, we know can generate implementations of the Debug trait. This code generation is hidden behind the '--force-derive-debug' command-line flag. --- src/codegen/derive_debug.rs | 197 ++ src/codegen/mod.rs | 1656 +++++++++-------- src/lib.rs | 305 +-- src/options.rs | 25 +- .../tests/derive-debug-bitfield.rs | 119 ++ .../tests/derive-debug-function-pointer.rs | 47 + .../tests/derive-debug-generic.rs | 19 + ...ive-debug-opaque-template-instantiation.rs | 30 + .../expectations/tests/derive-debug-opaque.rs | 49 + tests/headers/derive-debug-bitfield.hpp | 7 + .../headers/derive-debug-function-pointer.hpp | 7 + tests/headers/derive-debug-generic.hpp | 6 + ...ve-debug-opaque-template-instantiation.hpp | 10 + tests/headers/derive-debug-opaque.hpp | 10 + 14 files changed, 1610 insertions(+), 877 deletions(-) create mode 100644 src/codegen/derive_debug.rs create mode 100644 tests/expectations/tests/derive-debug-bitfield.rs create mode 100644 tests/expectations/tests/derive-debug-function-pointer.rs create mode 100644 tests/expectations/tests/derive-debug-generic.rs create mode 100644 tests/expectations/tests/derive-debug-opaque-template-instantiation.rs create mode 100644 tests/expectations/tests/derive-debug-opaque.rs create mode 100644 tests/headers/derive-debug-bitfield.hpp create mode 100644 tests/headers/derive-debug-function-pointer.hpp create mode 100644 tests/headers/derive-debug-generic.hpp create mode 100644 tests/headers/derive-debug-opaque-template-instantiation.hpp create mode 100644 tests/headers/derive-debug-opaque.hpp 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; +};