diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/codegen/derive_debug.rs | 82 | ||||
-rw-r--r-- | src/codegen/helpers.rs | 208 | ||||
-rw-r--r-- | src/codegen/mod.rs | 2133 | ||||
-rw-r--r-- | src/codegen/struct_layout.rs | 37 | ||||
-rw-r--r-- | src/ir/analysis/derive_copy.rs | 19 | ||||
-rw-r--r-- | src/ir/analysis/derive_debug.rs | 19 | ||||
-rw-r--r-- | src/ir/analysis/derive_default.rs | 19 | ||||
-rw-r--r-- | src/ir/analysis/derive_hash.rs | 19 | ||||
-rw-r--r-- | src/ir/analysis/derive_partial_eq.rs | 21 | ||||
-rw-r--r-- | src/ir/analysis/has_destructor.rs | 19 | ||||
-rw-r--r-- | src/ir/analysis/has_float.rs | 18 | ||||
-rw-r--r-- | src/ir/analysis/has_type_param_in_array.rs | 21 | ||||
-rw-r--r-- | src/ir/analysis/has_vtable.rs | 19 | ||||
-rw-r--r-- | src/ir/analysis/template_params.rs | 21 | ||||
-rw-r--r-- | src/ir/context.rs | 174 | ||||
-rw-r--r-- | src/ir/function.rs | 57 | ||||
-rw-r--r-- | src/ir/item.rs | 58 | ||||
-rw-r--r-- | src/ir/objc.rs | 27 | ||||
-rw-r--r-- | src/ir/traversal.rs | 60 | ||||
-rw-r--r-- | src/ir/ty.rs | 31 | ||||
-rw-r--r-- | src/lib.rs | 90 | ||||
-rw-r--r-- | src/main.rs | 1 | ||||
-rw-r--r-- | src/time.rs | 6 |
23 files changed, 1450 insertions, 1709 deletions
diff --git a/src/codegen/derive_debug.rs b/src/codegen/derive_debug.rs index 82456797..7ef108da 100644 --- a/src/codegen/derive_debug.rs +++ b/src/codegen/derive_debug.rs @@ -3,21 +3,17 @@ use ir::context::BindgenContext; use ir::derive::CanTriviallyDeriveDebug; use ir::item::{HasTypeParamInArray, IsOpaque, Item, ItemCanonicalName}; use ir::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, TypeKind}; -use syntax::ast; -use syntax::codemap::DUMMY_SP; -use syntax::parse::token::Token; - -use syntax::tokenstream::TokenTree; +use quote; pub fn gen_debug_impl( ctx: &BindgenContext, fields: &[Field], item: &Item, kind: CompKind, -) -> Vec<ast::ImplItem> { +) -> quote::Tokens { let struct_name = item.canonical_name(ctx); let mut format_string = format!("{} {{{{ ", struct_name); - let mut tokens: Vec<TokenTree> = Vec::new(); + let mut tokens = vec![]; if item.is_opaque(ctx, &()) { format_string.push_str("opaque"); @@ -33,14 +29,11 @@ pub fn gen_debug_impl( }); - for (i, (fstring, token)) in processed_fields.enumerate() { + for (i, (fstring, toks)) 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); - } + tokens.extend(toks); format_string.push_str(&fstring); } } @@ -48,17 +41,12 @@ pub fn gen_debug_impl( } format_string.push_str(" }}"); + tokens.insert(0, quote! { #format_string }); - 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!(), + quote! { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, #( #tokens ),*) + } } } @@ -74,7 +62,7 @@ pub trait ImplDebug<'a> { &self, ctx: &BindgenContext, extra: Self::Extra, - ) -> Option<(String, Vec<TokenTree>)>; + ) -> Option<(String, Vec<quote::Tokens>)>; } impl<'a> ImplDebug<'a> for FieldData { @@ -84,7 +72,7 @@ impl<'a> ImplDebug<'a> for FieldData { &self, ctx: &BindgenContext, _: Self::Extra, - ) -> Option<(String, Vec<TokenTree>)> { + ) -> Option<(String, Vec<quote::Tokens>)> { if let Some(name) = self.name() { ctx.resolve_item(self.ty()).impl_debug(ctx, name) } else { @@ -100,17 +88,18 @@ impl<'a> ImplDebug<'a> for BitfieldUnit { &self, ctx: &BindgenContext, _: Self::Extra, - ) -> Option<(String, Vec<TokenTree>)> { + ) -> Option<(String, Vec<quote::Tokens>)> { let mut format_string = String::new(); - let mut tokens = Vec::new(); + let mut tokens = vec![]; for (i, bu) in self.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())); + tokens.push(quote! { + self.#name_ident () + }); } Some((format_string, tokens)) @@ -123,8 +112,8 @@ impl<'a> ImplDebug<'a> for Item { fn impl_debug( &self, ctx: &BindgenContext, - name: Self::Extra, - ) -> Option<(String, Vec<TokenTree>)> { + name: &str, + ) -> Option<(String, Vec<quote::Tokens>)> { let name_ident = ctx.rust_ident_raw(name); // We don't know if blacklisted items `impl Debug` or not, so we can't @@ -141,13 +130,14 @@ impl<'a> ImplDebug<'a> for Item { }; fn debug_print( - ctx: &BindgenContext, name: &str, - name_ident: ast::Ident, - ) -> Option<(String, Vec<TokenTree>)> { + name_ident: quote::Tokens, + ) -> Option<(String, Vec<quote::Tokens>)> { Some(( format!("{}: {{:?}}", name), - quote_tokens!(ctx.ext_cx(), self.$name_ident), + vec![quote! { + self.#name_ident + }], )) } @@ -166,13 +156,13 @@ impl<'a> ImplDebug<'a> for Item { TypeKind::ObjCInterface(..) | TypeKind::ObjCId | TypeKind::Comp(..) | - TypeKind::ObjCSel => debug_print(ctx, name, name_ident), + TypeKind::ObjCSel => debug_print(name, quote! { #name_ident }), TypeKind::TemplateInstantiation(ref inst) => { if inst.is_opaque(ctx, self) { Some((format!("{}: opaque", name), vec![])) } else { - debug_print(ctx, name, name_ident) + debug_print(name, quote! { #name_ident }) } } @@ -189,18 +179,18 @@ impl<'a> ImplDebug<'a> for Item { ) } else if len < RUST_DERIVE_IN_ARRAY_LIMIT { // The simple case - debug_print(ctx, name, name_ident) + debug_print(name, quote! { #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::<String>()), + vec![quote! { + self.#name_ident + .iter() + .enumerate() + .map(|(i, v)| format!("{}{:?}", if i > 0 { ", " } else { "" }, v)) + .collect::<String>() + }], )) } } @@ -217,9 +207,9 @@ impl<'a> ImplDebug<'a> for Item { match *inner_type.kind() { TypeKind::Function(ref sig) if !sig.can_trivially_derive_debug() => { - Some((format!("{}: FunctionPointer", name), vec![])) + Some((format!("{}: FunctionPointer", name), vec![])) } - _ => debug_print(ctx, name, name_ident), + _ => debug_print(name, quote! { #name_ident }), } } diff --git a/src/codegen/helpers.rs b/src/codegen/helpers.rs index ed165aa9..5136d787 100644 --- a/src/codegen/helpers.rs +++ b/src/codegen/helpers.rs @@ -1,66 +1,59 @@ //! Helpers for code generation that don't need macro expansion. -use aster; use ir::layout::Layout; -use syntax::ast; -use syntax::ptr::P; - +use quote; pub mod attributes { - use aster; - use syntax::ast; - - pub fn allow(which_ones: &[&str]) -> ast::Attribute { - aster::AstBuilder::new() - .attr() - .list("allow") - .words(which_ones) - .build() - } + use quote; - pub fn repr(which: &str) -> ast::Attribute { - aster::AstBuilder::new() - .attr() - .list("repr") - .words(&[which]) - .build() + pub fn repr(which: &str) -> quote::Tokens { + let which = quote::Ident::new(which); + quote! { + #[repr( #which )] + } } - pub fn repr_list(which_ones: &[&str]) -> ast::Attribute { - aster::AstBuilder::new() - .attr() - .list("repr") - .words(which_ones) - .build() + pub fn repr_list(which_ones: &[&str]) -> quote::Tokens { + let which_ones = which_ones.iter().cloned().map(quote::Ident::new); + quote! { + #[repr( #( #which_ones ),* )] + } } - pub fn derives(which_ones: &[&str]) -> ast::Attribute { - aster::AstBuilder::new() - .attr() - .list("derive") - .words(which_ones) - .build() + pub fn derives(which_ones: &[&str]) -> quote::Tokens { + let which_ones = which_ones.iter().cloned().map(quote::Ident::new); + quote! { + #[derive( #( #which_ones ),* )] + } } - pub fn inline() -> ast::Attribute { - aster::AstBuilder::new().attr().word("inline") + pub fn inline() -> quote::Tokens { + quote! { + #[inline] + } } - pub fn doc(comment: String) -> ast::Attribute { - aster::AstBuilder::new().attr().doc(&*comment) + pub fn doc(comment: String) -> quote::Tokens { + // Doc comments are already preprocessed into nice `///` formats by the + // time they get here. Just make sure that we have newlines around it so + // that nothing else gets wrapped into the comment. + let mut tokens = quote! {}; + tokens.append("\n"); + tokens.append(comment); + tokens.append("\n"); + tokens } - pub fn link_name(name: &str) -> ast::Attribute { - aster::AstBuilder::new() - .attr() - .name_value("link_name") - .str(name) + pub fn link_name(name: &str) -> quote::Tokens { + quote! { + #[link_name = #name] + } } } /// Generates a proper type for a field or type with a given `Layout`, that is, /// a type with the correct size and alignment restrictions. -pub fn blob(layout: Layout) -> P<ast::Ty> { +pub fn blob(layout: Layout) -> quote::Tokens { let opaque = layout.opaque(); // FIXME(emilio, #412): We fall back to byte alignment, but there are @@ -75,39 +68,46 @@ pub fn blob(layout: Layout) -> P<ast::Ty> { } }; + let ty_name = quote::Ident::new(ty_name); + let data_len = opaque.array_size().unwrap_or(layout.size); - let inner_ty = aster::AstBuilder::new().ty().path().id(ty_name).build(); if data_len == 1 { - inner_ty + quote! { + #ty_name + } } else { - aster::ty::TyBuilder::new().array(data_len).build(inner_ty) + quote! { + [ #ty_name ; #data_len ] + } } } pub mod ast_ty { - use aster; use ir::context::BindgenContext; use ir::function::FunctionSig; use ir::ty::FloatKind; - use syntax::ast; - use syntax::ptr::P; + use quote; - pub fn raw_type(ctx: &BindgenContext, name: &str) -> P<ast::Ty> { - let ident = ctx.rust_ident_raw(&name); + pub fn raw_type(ctx: &BindgenContext, name: &str) -> quote::Tokens { + let ident = ctx.rust_ident_raw(name); match ctx.options().ctypes_prefix { Some(ref prefix) => { - let prefix = ctx.rust_ident_raw(prefix); - quote_ty!(ctx.ext_cx(), $prefix::$ident) + let prefix = ctx.rust_ident_raw(prefix.as_str()); + quote! { + #prefix::#ident + } } - None => quote_ty!(ctx.ext_cx(), ::std::os::raw::$ident), + None => quote! { + ::std::os::raw::#ident + }, } } pub fn float_kind_rust_type( ctx: &BindgenContext, fk: FloatKind, - ) -> P<ast::Ty> { + ) -> quote::Tokens { // TODO: we probably should just take the type layout into // account? // @@ -116,64 +116,50 @@ pub mod ast_ty { // FIXME: `c_longdouble` doesn't seem to be defined in some // systems, so we use `c_double` directly. match (fk, ctx.options().convert_floats) { - (FloatKind::Float, true) => aster::ty::TyBuilder::new().f32(), + (FloatKind::Float, true) => quote! { f32 }, (FloatKind::Double, true) | - (FloatKind::LongDouble, true) => aster::ty::TyBuilder::new().f64(), + (FloatKind::LongDouble, true) => quote! { f64 }, (FloatKind::Float, false) => raw_type(ctx, "c_float"), (FloatKind::Double, false) | (FloatKind::LongDouble, false) => raw_type(ctx, "c_double"), - (FloatKind::Float128, _) => { - aster::ty::TyBuilder::new().array(16).u8() - } + (FloatKind::Float128, _) => quote! { [u8; 16] }, } } - pub fn int_expr(val: i64) -> P<ast::Expr> { - use std::i64; - let expr = aster::AstBuilder::new().expr(); - - // This is not representable as an i64 if it's negative, so we - // special-case it. - // - // Fix in aster incoming. - if val == i64::MIN { - expr.neg().uint(1u64 << 63) - } else { - expr.int(val) - } + pub fn int_expr(val: i64) -> quote::Tokens { + // Don't use quote! { #val } because that adds the type suffix. + let mut tokens = quote! {}; + tokens.append(val.to_string()); + tokens } - pub fn bool_expr(val: bool) -> P<ast::Expr> { - aster::AstBuilder::new().expr().bool(val) + pub fn uint_expr(val: u64) -> quote::Tokens { + // Don't use quote! { #val } because that adds the type suffix. + let mut tokens = quote! {}; + tokens.append(val.to_string()); + tokens } - pub fn byte_array_expr(bytes: &[u8]) -> P<ast::Expr> { - let mut vec = Vec::with_capacity(bytes.len() + 1); - for byte in bytes { - vec.push(int_expr(*byte as i64)); + pub fn byte_array_expr(bytes: &[u8]) -> quote::Tokens { + let mut bytes: Vec<_> = bytes.iter().cloned().collect(); + bytes.push(0); + quote! { + #bytes } - vec.push(int_expr(0)); - - let kind = ast::ExprKind::Array(vec); - - aster::AstBuilder::new().expr().build_expr_kind(kind) } - pub fn cstr_expr(mut string: String) -> P<ast::Expr> { + pub fn cstr_expr(mut string: String) -> quote::Tokens { string.push('\0'); - aster::AstBuilder::new().expr().build_lit( - aster::AstBuilder::new() - .lit() - .byte_str(string), - ) + let b = quote::ByteStr(&string); + quote! { + #b + } } pub fn float_expr( ctx: &BindgenContext, f: f64, - ) -> Result<P<ast::Expr>, ()> { - use aster::symbol::ToSymbol; - + ) -> Result<quote::Tokens, ()> { if f.is_finite() { let mut string = f.to_string(); @@ -182,21 +168,28 @@ pub mod ast_ty { string.push('.'); } - let kind = - ast::LitKind::FloatUnsuffixed(string.as_str().to_symbol()); - return Ok(aster::AstBuilder::new().expr().lit().build_lit(kind)); + let mut tokens = quote! {}; + tokens.append(string); + return Ok(tokens); } let prefix = ctx.trait_prefix(); + if f.is_nan() { - return Ok(quote_expr!(ctx.ext_cx(), ::$prefix::f64::NAN)); + return Ok(quote! { + ::#prefix::f64::NAN + }); } if f.is_infinite() { return Ok(if f.is_sign_positive() { - quote_expr!(ctx.ext_cx(), ::$prefix::f64::INFINITY) + quote! { + ::#prefix::f64::INFINITY + } } else { - quote_expr!(ctx.ext_cx(), ::$prefix::f64::NEG_INFINITY) + quote! { + ::#prefix::f64::NEG_INFINITY + } }); } @@ -207,23 +200,24 @@ pub mod ast_ty { pub fn arguments_from_signature( signature: &FunctionSig, ctx: &BindgenContext, - ) -> Vec<P<ast::Expr>> { - // TODO: We need to keep in sync the argument names, so we should unify - // this with the other loop that decides them. + ) -> Vec<quote::Tokens> { let mut unnamed_arguments = 0; signature .argument_types() .iter() .map(|&(ref name, _ty)| { - let arg_name = match *name { - Some(ref name) => ctx.rust_mangle(name).into_owned(), + match *name { + Some(ref name) => { + let name = ctx.rust_ident(name); + quote! { #name } + } None => { unnamed_arguments += 1; - format!("arg{}", unnamed_arguments) + let name = ctx.rust_ident(format!("arg{}", unnamed_arguments)); + quote! { #name } } - }; - aster::expr::ExprBuilder::new().id(arg_name) + } }) - .collect::<Vec<_>>() + .collect() } } diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 4697ba21..f13bd65a 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -6,9 +6,6 @@ pub mod struct_layout; use self::helpers::attributes; use self::struct_layout::StructLayoutTracker; -use aster; -use aster::struct_field::StructFieldBuilder; - use ir::annotations::FieldAccessorKind; use ir::comment; use ir::comp::{Base, Bitfield, BitfieldUnit, CompInfo, CompKind, Field, @@ -29,36 +26,33 @@ use ir::template::{AsTemplateParam, TemplateInstantiation, TemplateParameters}; use ir::ty::{Type, TypeKind}; use ir::var::Var; +use quote; + use std::borrow::Cow; use std::cell::Cell; use std::collections::{HashSet, VecDeque}; use std::collections::hash_map::{Entry, HashMap}; use std::fmt::Write; +use std::iter; use std::mem; use std::ops; -use syntax::abi; -use syntax::ast; -use syntax::codemap::{DUMMY_SP, Span, respan}; -use syntax::ptr::P; // Name of type defined in constified enum module pub static CONSTIFIED_ENUM_MODULE_REPR_NAME: &'static str = "Type"; -fn top_level_path(ctx: &BindgenContext, item: &Item) -> Vec<ast::Ident> { - let mut path = vec![ctx.rust_ident_raw("self")]; +fn top_level_path(ctx: &BindgenContext, item: &Item) -> Vec<quote::Tokens> { + let mut path = vec![quote! { self }]; if ctx.options().enable_cxx_namespaces { - let super_ = ctx.rust_ident_raw("super"); - for _ in 0..item.codegen_depth(ctx) { - path.push(super_.clone()); + path.push(quote! { super }); } } path } -fn root_import(ctx: &BindgenContext, module: &Item) -> P<ast::Item> { +fn root_import(ctx: &BindgenContext, module: &Item) -> quote::Tokens { assert!(ctx.options().enable_cxx_namespaces, "Somebody messed it up"); assert!(module.is_module()); @@ -66,20 +60,20 @@ fn root_import(ctx: &BindgenContext, module: &Item) -> P<ast::Item> { let root = ctx.root_module().canonical_name(ctx); let root_ident = ctx.rust_ident(&root); - path.push(root_ident); + path.push(quote! { #root_ident }); + - let use_root = aster::AstBuilder::new() - .item() - .use_() - .ids(path) - .build() - .build(); + let mut tokens = quote! {}; + tokens.append_separated(path, "::"); - quote_item!(ctx.ext_cx(), #[allow(unused_imports)] $use_root).unwrap() + quote! { + #[allow(unused_imports)] + use #tokens ; + } } struct CodegenResult<'a> { - items: Vec<P<ast::Item>>, + items: Vec<quote::Tokens>, /// A monotonic counter used to add stable unique id's to stuff that doesn't /// need to be referenced by anything. @@ -190,7 +184,7 @@ impl<'a> CodegenResult<'a> { self.vars_seen.insert(name.into()); } - fn inner<F>(&mut self, cb: F) -> Vec<P<ast::Item>> + fn inner<F>(&mut self, cb: F) -> Vec<quote::Tokens> where F: FnOnce(&mut Self), { @@ -207,7 +201,7 @@ impl<'a> CodegenResult<'a> { } impl<'a> ops::Deref for CodegenResult<'a> { - type Target = Vec<P<ast::Item>>; + type Target = Vec<quote::Tokens>; fn deref(&self) -> &Self::Target { &self.items @@ -220,70 +214,85 @@ impl<'a> ops::DerefMut for CodegenResult<'a> { } } -struct ForeignModBuilder { - inner: ast::ForeignMod, +/// A trait to convert a rust type into a pointer, optionally const, to the same +/// type. +trait ToPtr { + fn to_ptr(self, is_const: bool) -> quote::Tokens; } -impl ForeignModBuilder { - fn new(abi: abi::Abi) -> Self { - ForeignModBuilder { - inner: ast::ForeignMod { - abi: abi, - items: vec![], - }, +impl ToPtr for quote::Tokens { + fn to_ptr(self, is_const: bool) -> quote::Tokens { + if is_const { + quote! { *const #self } + } else { + quote! { *mut #self } } } - - fn with_foreign_item(mut self, item: ast::ForeignItem) -> Self { - self.inner.items.push(item); - self - } - - #[allow(dead_code)] - fn with_foreign_items<I>(mut self, items: I) -> Self - where - I: IntoIterator<Item = ast::ForeignItem>, - { - self.inner.items.extend(items.into_iter()); - self - } - - fn build(self, ctx: &BindgenContext) -> P<ast::Item> { - P(ast::Item { - ident: ctx.rust_ident(""), - id: ast::DUMMY_NODE_ID, - node: ast::ItemKind::ForeignMod(self.inner), - vis: ast::Visibility::Public, - attrs: vec![], - span: DUMMY_SP, - }) - } } -/// A trait to convert a rust type into a pointer, optionally const, to the same -/// type. -/// -/// This is done due to aster's lack of pointer builder, I guess I should PR -/// there. -trait ToPtr { - fn to_ptr(self, is_const: bool, span: Span) -> P<ast::Ty>; +/// An extension trait for `quote::Tokens` that lets us append any implicit +/// template parameters that exist for some type, if necessary. +trait AppendImplicitTemplateParams { + fn append_implicit_template_params( + &mut self, + ctx: &BindgenContext, + item: &Item, + ); } -impl ToPtr for P<ast::Ty> { - fn to_ptr(self, is_const: bool, span: Span) -> Self { - let ty = ast::TyKind::Ptr(ast::MutTy { - ty: self, - mutbl: if is_const { - ast::Mutability::Immutable - } else { - ast::Mutability::Mutable - }, - }); - P(ast::Ty { - id: ast::DUMMY_NODE_ID, - node: ty, - span: span, - }) +impl AppendImplicitTemplateParams for quote::Tokens { + fn append_implicit_template_params( + &mut self, + ctx: &BindgenContext, + item: &Item, + ) { + let item = item.id() + .into_resolver() + .through_type_refs() + .resolve(ctx); + + match *item.expect_type().kind() { + TypeKind::UnresolvedTypeRef(..) => { + unreachable!("already resolved unresolved type refs") + } + TypeKind::ResolvedTypeRef(..) => { + unreachable!("we resolved item through type refs") + } + + // None of these types ever have implicit template parameters. + TypeKind::Void | + TypeKind::NullPtr | + TypeKind::Pointer(..) | + TypeKind::Int(..) | + TypeKind::Float(..) | + TypeKind::Complex(..) | + TypeKind::Array(..) | + TypeKind::TypeParam | + TypeKind::Opaque | + TypeKind::Function(..) | + TypeKind::Enum(..) | + TypeKind::BlockPointer | + TypeKind::ObjCId | + TypeKind::ObjCSel | + TypeKind::TemplateInstantiation(..) => return, + + _ => {}, + } + + if let Some(params) = item.used_template_params(ctx) { + if params.is_empty() { + return; + } + + let params = params.into_iter().map(|p| { + p.try_to_rust_ty(ctx, &()) + .expect("template params cannot fail to be a rust type") + }); + + self.append(quote! { + < #( #params ),* > + }); + } } } @@ -376,7 +385,7 @@ impl CodeGenerator for Module { utils::prepend_incomplete_array_types(ctx, &mut *result); } if ctx.need_bindegen_complex_type() { - utils::prepend_complex_type(ctx, &mut *result); + utils::prepend_complex_type(&mut *result); } if result.saw_objc { utils::prepend_objc_header(ctx, &mut *result); @@ -403,27 +412,23 @@ impl CodeGenerator for Module { return; } - let module = ast::ItemKind::Mod(ast::Mod { - inner: ctx.span(), - items: inner_items, - }); - let name = item.canonical_name(ctx); - let item_builder = aster::AstBuilder::new().item().pub_(); - let item = if name == "root" { - let attrs = &[ - "non_snake_case", - "non_camel_case_types", - "non_upper_case_globals", - ]; - item_builder - .with_attr(attributes::allow(attrs)) - .build_item_kind(name, module) - } else { - item_builder.build_item_kind(name, module) - }; - result.push(item); + result.push(if name == "root" { + quote! { + #[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] + pub mod root { + #( #inner_items )* + } + } + } else { + let ident = ctx.rust_ident(name); + quote! { + pub mod #ident { + #( #inner_items )* + } + } + }); } } @@ -446,6 +451,8 @@ impl CodeGenerator for Var { } result.saw_var(&canonical_name); + let canonical_ident = ctx.rust_ident(&canonical_name); + // We can't generate bindings to static variables of templates. The // number of actual variables for a single declaration are open ended // and we don't know what instantiations do or don't exist. @@ -459,17 +466,17 @@ impl CodeGenerator for Var { let ty = self.ty().to_rust_ty_or_opaque(ctx, &()); if let Some(val) = self.val() { - let const_item = aster::AstBuilder::new() - .item() - .pub_() - .const_(canonical_name) - .expr(); - let item = match *val { + match *val { VarType::Bool(val) => { - const_item.build(helpers::ast_ty::bool_expr(val)).build(ty) + result.push(quote! { + pub const #canonical_ident : #ty = #val ; + }); } VarType::Int(val) => { - const_item.build(helpers::ast_ty::int_expr(val)).build(ty) + let val = helpers::ast_ty::int_expr(val); + result.push(quote! { + pub const #canonical_ident : #ty = #val ; + }); } VarType::String(ref bytes) => { // Account the trailing zero. @@ -477,35 +484,39 @@ impl CodeGenerator for Var { // TODO: Here we ignore the type we just made up, probably // we should refactor how the variable type and ty id work. let len = bytes.len() + 1; - let ty = quote_ty!(ctx.ext_cx(), [u8; $len]); + let ty = quote! { + [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)) + let cstr = helpers::ast_ty::cstr_expr(string); + result.push(quote! { + pub const #canonical_ident : &'static #ty = #cstr ; + }); } Err(..) => { - const_item - .build(helpers::ast_ty::byte_array_expr(bytes)) - .build(ty) + let bytes = helpers::ast_ty::byte_array_expr(bytes); + result.push(quote! { + pub const #canonical_ident : #ty = #bytes ; + }); } } } VarType::Float(f) => { match helpers::ast_ty::float_expr(ctx, f) { - Ok(expr) => const_item.build(expr).build(ty), + Ok(expr) => result.push(quote! { + pub const #canonical_ident : #ty = #expr ; + }), Err(..) => return, } } VarType::Char(c) => { - const_item - .build(aster::AstBuilder::new().expr().lit().byte(c)) - .build(ty) + result.push(quote! { + pub const #canonical_ident : #ty = #c ; + }); } - }; - - result.push(item); + } } else { let mut attrs = vec![]; if let Some(mangled) = self.mangled_name() { @@ -514,19 +525,21 @@ impl CodeGenerator for Var { attrs.push(attributes::link_name(self.name())); } - let item = ast::ForeignItem { - ident: ctx.rust_ident_raw(&canonical_name), - attrs: attrs, - node: ast::ForeignItemKind::Static(ty, !self.is_const()), - id: ast::DUMMY_NODE_ID, - span: ctx.span(), - vis: ast::Visibility::Public, + let mut tokens = quote! { + extern "C" }; + tokens.append("{\n"); + if !attrs.is_empty() { + tokens.append_separated(attrs, "\n"); + tokens.append("\n"); + } + tokens.append("pub static mut "); + tokens.append(quote! { #canonical_ident }); + tokens.append(" : "); + tokens.append(quote! { #ty }); + tokens.append(";\n}"); - let item = ForeignModBuilder::new(abi::Abi::C) - .with_foreign_item(item) - .build(ctx); - result.push(item); + result.push(tokens); } } } @@ -567,7 +580,9 @@ impl CodeGenerator for Type { TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item), TypeKind::TemplateAlias(inner, _) | TypeKind::Alias(inner) => { - let inner_item = ctx.resolve_item(inner); + let inner_item = inner.into_resolver() + .through_type_refs() + .resolve(ctx); let name = item.canonical_name(ctx); // Try to catch the common pattern: @@ -587,17 +602,25 @@ impl CodeGenerator for Type { return; } - let mut used_template_params = item.used_template_params(ctx); + let mut outer_params = item.used_template_params(ctx) + .and_then(|ps| if ps.is_empty() { + None + } else { + Some(ps) + }); + let inner_rust_type = if item.is_opaque(ctx, &()) { - used_template_params = None; + outer_params = None; self.to_opaque(ctx, item) } else { // 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 + let mut inner_ty = inner_item .try_to_rust_ty_or_opaque(ctx, &()) - .unwrap_or_else(|_| self.to_opaque(ctx, item)) + .unwrap_or_else(|_| self.to_opaque(ctx, item)); + inner_ty.append_implicit_template_params(ctx, inner_item); + inner_ty }; { @@ -625,68 +648,71 @@ impl CodeGenerator for Type { } let rust_name = ctx.rust_ident(&name); - let mut typedef = aster::AstBuilder::new().item().pub_(); - if let Some(comment) = item.comment(ctx) { - typedef = typedef.with_attr(attributes::doc(comment)); - } + let mut tokens = if let Some(comment) = item.comment(ctx) { + attributes::doc(comment) + } else { + quote! {} + }; // 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() - .canonical_type(ctx) - .is_enum() && - p.segments.iter().all(|p| p.parameters.is_none()) - { - Some(p.clone()) - } else { - None - } - } - _ => None, - }; + if inner_rust_type.as_str() + .chars() + .all(|c| match c { + // These are the only characters allowed in simple + // paths, eg `good::dogs::Bront`. + 'A'...'Z' | 'a'...'z' | '0'...'9' | ':' | '_' | ' ' => true, + _ => false, + }) && + outer_params.is_none() && + inner_item.expect_type().canonical_type(ctx).is_enum() + { + tokens.append(quote! { + pub use + }); + let path = top_level_path(ctx, item); + tokens.append_separated(path, "::"); + tokens.append(quote! { + :: #inner_rust_type as #rust_name ; + }); + result.push(tokens); + return; + } - 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, - }, + tokens.append(quote! { + pub type #rust_name + }); + + if let Some(params) = outer_params { + let params: Vec<_> = params.into_iter() + .filter_map(|p| p.as_template_param(ctx, &())) + .collect(); + if params.iter().any(|p| ctx.resolve_type(*p).is_invalid_type_param()) { + warn!( + "Item contained invalid template \ + parameter: {:?}", + item ); + return; } - typedef.use_().build(p).as_(rust_name) - } else { - let mut generics = typedef.type_(rust_name).generics(); - if let Some(ref params) = used_template_params { - for template_param in params { - if let Some(id) = template_param - .as_template_param(ctx, &()) - { - let template_param = ctx.resolve_type(id); - if template_param.is_invalid_type_param() { - warn!( - "Item contained invalid template \ - parameter: {:?}", - item - ); - return; - } - generics = - generics.ty_param_id( - template_param.name().unwrap(), - ); - } - } - } - generics.build().build_ty(inner_rust_type) - }; - result.push(typedef) + + let params = params.iter() + .map(|p| { + p.try_to_rust_ty(ctx, &()) + .expect("type parameters can always convert to rust ty OK") + }); + + tokens.append(quote! { + < #( #params ),* > + }); + } + + tokens.append(quote! { + = #inner_rust_type ; + }); + + result.push(tokens); } TypeKind::Enum(ref ei) => ei.codegen(ctx, result, item), TypeKind::ObjCId | TypeKind::ObjCSel => { @@ -738,17 +764,12 @@ impl<'a> CodeGenerator for Vtable<'a> { // For now, generate an empty struct, later we should generate function // pointers and whatnot. - let attributes = vec![attributes::repr("C")]; - - let vtable = aster::AstBuilder::new() - .item() - .pub_() - .with_attrs(attributes) - .tuple_struct(self.canonical_name(ctx)) - .field() - .build_ty(helpers::ast_ty::raw_type(ctx, "c_void")) - .build(); - result.push(vtable); + let name = ctx.rust_ident(&self.canonical_name(ctx)); + let void = helpers::ast_ty::raw_type(ctx, "c_void"); + result.push(quote! { + #[repr(C)] + pub struct #name ( #void ); + }); } } @@ -765,8 +786,11 @@ impl<'a> TryToRustTy for Vtable<'a> { &self, ctx: &BindgenContext, _: &(), - ) -> error::Result<P<ast::Ty>> { - Ok(aster::ty::TyBuilder::new().id(self.canonical_name(ctx))) + ) -> error::Result<quote::Tokens> { + let name = ctx.rust_ident(self.canonical_name(ctx)); + Ok(quote! { + #name + }) } } @@ -812,26 +836,28 @@ impl CodeGenerator for TemplateInstantiation { write!(&mut fn_name, "_{}", times_seen).unwrap(); } - let fn_name = ctx.rust_ident_raw(&fn_name); + let fn_name = ctx.rust_ident_raw(fn_name); let prefix = ctx.trait_prefix(); let ident = item.to_rust_ty_or_opaque(ctx, &()); - let size_of_expr = quote_expr!(ctx.ext_cx(), - ::$prefix::mem::size_of::<$ident>()); - let align_of_expr = quote_expr!(ctx.ext_cx(), - ::$prefix::mem::align_of::<$ident>()); + let size_of_expr = quote! { + ::#prefix::mem::size_of::<#ident>() + }; + let align_of_expr = quote! { + ::#prefix::mem::align_of::<#ident>() + }; - let item = quote_item!( - ctx.ext_cx(), + let item = quote! { #[test] - fn $fn_name() { - assert_eq!($size_of_expr, $size, + fn #fn_name() { + assert_eq!(#size_of_expr, #size, concat!("Size of template specialization: ", - stringify!($ident))); - assert_eq!($align_of_expr, $align, + stringify!(#ident))); + assert_eq!(#align_of_expr, #align, concat!("Alignment of template specialization: ", - stringify!($ident))); - }).unwrap(); + stringify!(#ident))); + } + }; result.push(item); } @@ -874,8 +900,8 @@ trait FieldCodegen<'a> { methods: &mut M, extra: Self::Extra, ) where - F: Extend<ast::StructField>, - M: Extend<ast::ImplItem>; + F: Extend<quote::Tokens>, + M: Extend<quote::Tokens>; } impl<'a> FieldCodegen<'a> for Field { @@ -895,8 +921,8 @@ impl<'a> FieldCodegen<'a> for Field { methods: &mut M, _: (), ) where - F: Extend<ast::StructField>, - M: Extend<ast::ImplItem>, + F: Extend<quote::Tokens>, + M: Extend<quote::Tokens>, { match *self { Field::DataMember(ref data) => { @@ -950,22 +976,27 @@ impl<'a> FieldCodegen<'a> for FieldData { methods: &mut M, _: (), ) where - F: Extend<ast::StructField>, - M: Extend<ast::ImplItem>, + F: Extend<quote::Tokens>, + M: Extend<quote::Tokens>, { // Bitfields are handled by `FieldCodegen` implementations for // `BitfieldUnit` and `Bitfield`. assert!(self.bitfield().is_none()); - let field_ty = ctx.resolve_type(self.ty()); - let ty = self.ty().to_rust_ty_or_opaque(ctx, &()); + let field_item = self.ty().into_resolver().through_type_refs().resolve(ctx); + let field_ty = field_item.expect_type(); + let mut ty = self.ty().to_rust_ty_or_opaque(ctx, &()); // NB: If supported, we use proper `union` types. let ty = if parent.is_union() && !parent.can_be_rust_union(ctx) { if ctx.options().enable_cxx_namespaces { - quote_ty!(ctx.ext_cx(), root::__BindgenUnionField<$ty>) + quote! { + root::__BindgenUnionField<#ty> + } } else { - quote_ty!(ctx.ext_cx(), __BindgenUnionField<$ty>) + quote! { + __BindgenUnionField<#ty> + } } } else if let Some(item) = field_ty.is_incomplete_array(ctx) { result.saw_incomplete_array(); @@ -973,20 +1004,25 @@ impl<'a> FieldCodegen<'a> for FieldData { let inner = item.to_rust_ty_or_opaque(ctx, &()); if ctx.options().enable_cxx_namespaces { - quote_ty!(ctx.ext_cx(), root::__IncompleteArrayField<$inner>) + quote! { + root::__IncompleteArrayField<#inner> + } } else { - quote_ty!(ctx.ext_cx(), __IncompleteArrayField<$inner>) + quote! { + __IncompleteArrayField<#inner> + } } } else { + ty.append_implicit_template_params(ctx, field_item); ty }; - let mut attrs = vec![]; + let mut field = quote! {}; if ctx.options().generate_comments { if let Some(raw_comment) = self.comment() { let comment = comment::preprocess(raw_comment, codegen_depth + 1); - attrs.push(attributes::doc(comment)) + field = attributes::doc(comment); } } @@ -994,6 +1030,7 @@ impl<'a> FieldCodegen<'a> for FieldData { self.name() .map(|name| ctx.rust_mangle(name).into_owned()) .unwrap_or_else(|| anon_field_names.next().unwrap()); + let field_ident = ctx.rust_ident_raw(field_name.as_str()); if !parent.is_union() { if let Some(padding_field) = @@ -1010,14 +1047,16 @@ impl<'a> FieldCodegen<'a> for FieldData { let accessor_kind = self.annotations().accessor_kind().unwrap_or(accessor_kind); - let mut field = StructFieldBuilder::named(&field_name); - - if !is_private { - field = field.pub_(); + if is_private { + field.append(quote! { + #field_ident : #ty , + }); + } else { + field.append(quote! { + pub #field_ident : #ty , + }); } - let field = field.with_attrs(attrs).build_ty(ty.clone()); - fields.extend(Some(field)); // TODO: Factor the following code out, please! @@ -1025,98 +1064,58 @@ 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); + 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 { + methods.extend(Some(match accessor_kind { FieldAccessorKind::None => unreachable!(), FieldAccessorKind::Regular => { - quote_item!(ctx.ext_cx(), - impl X { - #[inline] - pub fn $getter_name(&self) -> &$ty { - &self.$field_name - } + quote! { + #[inline] + pub fn #getter_name(&self) -> & #ty { + &self.#field_name + } - #[inline] - pub fn $mutable_getter_name(&mut self) -> &mut $ty { - &mut self.$field_name - } + #[inline] + pub fn #mutable_getter_name(&mut self) -> &mut #ty { + &mut self.#field_name } - ) + } } FieldAccessorKind::Unsafe => { - quote_item!(ctx.ext_cx(), - impl X { - #[inline] - pub unsafe fn $getter_name(&self) -> &$ty { - &self.$field_name - } + quote! { + #[inline] + pub unsafe fn #getter_name(&self) -> & #ty { + &self.#field_name + } - #[inline] - pub unsafe fn $mutable_getter_name(&mut self) - -> &mut $ty { - &mut self.$field_name - } + #[inline] + pub unsafe fn #mutable_getter_name(&mut self) -> &mut #ty { + &mut self.#field_name } - ) + } } FieldAccessorKind::Immutable => { - quote_item!(ctx.ext_cx(), - impl X { - #[inline] - pub fn $getter_name(&self) -> &$ty { - &self.$field_name - } + quote! { + #[inline] + pub fn #getter_name(&self) -> & #ty { + &self.#field_name } - ) - } - }; - - match accessor_methods_impl.unwrap().node { - ast::ItemKind::Impl(_, _, _, _, _, ref items) => { - methods.extend(items.clone()) + } } - _ => unreachable!(), - } + })); } } impl BitfieldUnit { /// Get the constructor name for this bitfield unit. - fn ctor_name(&self, ctx: &BindgenContext) -> ast::Ident { - let ctor_name = format!("new_bitfield_{}", self.nth()); - ctx.ext_cx().ident_of(&ctor_name) - } - - /// 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<ast::Ty>, - ) -> P<ast::Item> { - let ctor_name = self.ctor_name(ctx); - - // If supported, add the const. - let fn_prefix = if ctx.options().rust_features().const_fn() { - quote_tokens!(ctx.ext_cx(), pub const fn) - } else { - quote_tokens!(ctx.ext_cx(), pub fn) - }; - - quote_item!( - ctx.ext_cx(), - impl XxxUnused { - #[inline] - $fn_prefix $ctor_name() -> $unit_field_int_ty { - 0 - } - } - ).unwrap() + fn ctor_name(&self) -> quote::Tokens { + let ctor_name = quote::Ident::new(format!("new_bitfield_{}", self.nth())); + quote! { + #ctor_name + } } } @@ -1131,57 +1130,26 @@ impl Bitfield { fn extend_ctor_impl( &self, ctx: &BindgenContext, - parent: &CompInfo, - ctor_impl: P<ast::Item>, - ctor_name: &ast::Ident, - unit_field_int_ty: &P<ast::Ty>, - ) -> P<ast::Item> { - let items = match ctor_impl.unwrap().node { - 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), - _ => unreachable!(), - }; - - let params = sig.decl.clone().unwrap().inputs; - let param_name = bitfield_getter_name(ctx, parent, self.name()); - - let bitfield_ty_item = ctx.resolve_item(self.ty()); - let bitfield_ty = bitfield_ty_item.expect_type(); + param_name: quote::Tokens, + ctor_impl: quote::Tokens, + unit_field_int_ty: "e::Tokens, + ) -> quote::Tokens { + let bitfield_ty = ctx.resolve_type(self.ty()); let bitfield_ty_layout = bitfield_ty.layout(ctx).expect( "Bitfield without layout? Gah!", ); let bitfield_int_ty = helpers::blob(bitfield_ty_layout); - let bitfield_ty = - bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item); let offset = self.offset_into_unit(); let mask = self.mask(); - // If supported, add the const. - let fn_prefix = if ctx.options().rust_features().const_fn() { - quote_tokens!(ctx.ext_cx(), pub const fn) - } else { - quote_tokens!(ctx.ext_cx(), pub fn) - }; - - // Don't use variables or blocks because const function does not allow them. - quote_item!( - ctx.ext_cx(), - impl XxxUnused { - #[inline] - $fn_prefix $ctor_name($params $param_name : $bitfield_ty) - -> $unit_field_int_ty { - ($body | - (($param_name as $bitfield_int_ty as $unit_field_int_ty) << $offset) & - ($mask as $unit_field_int_ty)) - } - } - ).unwrap() + // Don't use variables or blocks because const functions do not allow + // them. + quote! { + (#ctor_impl | + ((#param_name as #bitfield_int_ty as #unit_field_int_ty) << #offset) & + (#mask as #unit_field_int_ty)) + } } } @@ -1202,15 +1170,16 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { methods: &mut M, _: (), ) where - F: Extend<ast::StructField>, - M: Extend<ast::ImplItem>, + F: Extend<quote::Tokens>, + M: Extend<quote::Tokens>, { let field_ty = helpers::blob(self.layout()); let unit_field_name = format!("_bitfield_{}", self.nth()); + let unit_field_ident = ctx.rust_ident(&unit_field_name); - let field = StructFieldBuilder::named(&unit_field_name) - .pub_() - .build_ty(field_ty.clone()); + let field = quote! { + pub #unit_field_ident : #field_ty , + }; fields.extend(Some(field)); let mut field_int_size = self.layout().size; @@ -1219,10 +1188,10 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { } let unit_field_int_ty = match field_int_size { - 8 => quote_ty!(ctx.ext_cx(), u64), - 4 => quote_ty!(ctx.ext_cx(), u32), - 2 => quote_ty!(ctx.ext_cx(), u16), - 1 => quote_ty!(ctx.ext_cx(), u8), + 8 => quote! { u64 }, + 4 => quote! { u32 }, + 2 => quote! { u16 }, + 1 => quote! { u8 }, size => { debug_assert!(size > 8); // Can't generate bitfield accessors for unit sizes larget than @@ -1232,8 +1201,9 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { } }; - let ctor_name = self.ctor_name(ctx); - let mut ctor_impl = self.initial_ctor_impl(ctx, &unit_field_int_ty); + let ctor_name = self.ctor_name(); + let mut ctor_params = vec![]; + let mut ctor_impl = quote! { 0 }; for bf in self.bitfields() { bf.codegen( @@ -1250,23 +1220,36 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { (&unit_field_name, unit_field_int_ty.clone()), ); + let param_name = bitfield_getter_name(ctx, parent, bf.name()); + let bitfield_ty_item = ctx.resolve_item(bf.ty()); + let bitfield_ty = bitfield_ty_item.expect_type(); + let bitfield_ty = + bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item); + + ctor_params.push(quote! { + #param_name : #bitfield_ty + }); ctor_impl = bf.extend_ctor_impl( ctx, - parent, + param_name, 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!(), + let const_ = if ctx.options().rust_features().const_fn() { + quote! { const } + } else { + quote! { } }; + methods.extend(Some(quote! { + #[inline] + pub #const_ fn #ctor_name ( #( #ctor_params ),* ) -> #unit_field_int_ty { + #ctor_impl + } + })); + struct_layout.saw_bitfield_unit(self.layout()); } } @@ -1297,23 +1280,25 @@ fn bitfield_getter_name( ctx: &BindgenContext, parent: &CompInfo, bitfield_name: &str, -) -> ast::Ident { +) -> quote::Tokens { let name = ctx.rust_mangle(bitfield_name); if parent_has_method(ctx, parent, &name) { let mut name = name.to_string(); name.push_str("_bindgen_bitfield"); - return ctx.ext_cx().ident_of(&name); + let name = ctx.rust_ident(name); + return quote! { #name }; } - ctx.ext_cx().ident_of(&name) + let name = ctx.rust_ident(name); + quote! { #name } } fn bitfield_setter_name( ctx: &BindgenContext, parent: &CompInfo, bitfield_name: &str, -) -> ast::Ident { +) -> quote::Tokens { let setter = format!("set_{}", bitfield_name); let mut setter = ctx.rust_mangle(&setter).to_string(); @@ -1321,11 +1306,12 @@ fn bitfield_setter_name( setter.push_str("_bindgen_bitfield"); } - ctx.ext_cx().ident_of(&setter) + let setter = ctx.rust_ident(setter); + quote! { #setter } } impl<'a> FieldCodegen<'a> for Bitfield { - type Extra = (&'a str, P<ast::Ty>); + type Extra = (&'a str, quote::Tokens); fn codegen<F, M>( &self, @@ -1339,15 +1325,15 @@ impl<'a> FieldCodegen<'a> for Bitfield { _struct_layout: &mut StructLayoutTracker, _fields: &mut F, methods: &mut M, - (unit_field_name, unit_field_int_ty): (&'a str, P<ast::Ty>), + (unit_field_name, unit_field_int_ty): (&'a str, quote::Tokens), ) where - F: Extend<ast::StructField>, - M: Extend<ast::ImplItem>, + F: Extend<quote::Tokens>, + M: Extend<quote::Tokens>, { let prefix = ctx.trait_prefix(); let getter_name = bitfield_getter_name(ctx, parent, self.name()); let setter_name = bitfield_setter_name(ctx, parent, self.name()); - let unit_field_ident = ctx.ext_cx().ident_of(unit_field_name); + let unit_field_ident = quote::Ident::new(unit_field_name); let bitfield_ty_item = ctx.resolve_item(self.ty()); let bitfield_ty = bitfield_ty_item.expect_type(); @@ -1363,67 +1349,57 @@ impl<'a> FieldCodegen<'a> for Bitfield { let offset = self.offset_into_unit(); let mask = self.mask(); - let impl_item = quote_item!( - ctx.ext_cx(), - impl XxxIgnored { - #[inline] - pub fn $getter_name(&self) -> $bitfield_ty { - let mut unit_field_val: $unit_field_int_ty = unsafe { - ::$prefix::mem::uninitialized() - }; + methods.extend(Some(quote! { + #[inline] + pub fn #getter_name(&self) -> #bitfield_ty { + let mut unit_field_val: #unit_field_int_ty = unsafe { + ::#prefix::mem::uninitialized() + }; - unsafe { - ::$prefix::ptr::copy_nonoverlapping( - &self.$unit_field_ident as *const _ as *const u8, - &mut unit_field_val as *mut $unit_field_int_ty as *mut u8, - ::$prefix::mem::size_of::<$unit_field_int_ty>(), - ) - }; + unsafe { + ::#prefix::ptr::copy_nonoverlapping( + &self.#unit_field_ident as *const _ as *const u8, + &mut unit_field_val as *mut #unit_field_int_ty as *mut u8, + ::#prefix::mem::size_of::<#unit_field_int_ty>(), + ) + }; - let mask = $mask as $unit_field_int_ty; - let val = (unit_field_val & mask) >> $offset; - unsafe { - ::$prefix::mem::transmute(val as $bitfield_int_ty) - } + let mask = #mask as #unit_field_int_ty; + let val = (unit_field_val & mask) >> #offset; + unsafe { + ::#prefix::mem::transmute(val as #bitfield_int_ty) } + } - #[inline] - pub fn $setter_name(&mut self, val: $bitfield_ty) { - let mask = $mask as $unit_field_int_ty; - let val = val as $bitfield_int_ty as $unit_field_int_ty; + #[inline] + pub fn #setter_name(&mut self, val: #bitfield_ty) { + let mask = #mask as #unit_field_int_ty; + let val = val as #bitfield_int_ty as #unit_field_int_ty; - let mut unit_field_val: $unit_field_int_ty = unsafe { - ::$prefix::mem::uninitialized() - }; + let mut unit_field_val: #unit_field_int_ty = unsafe { + ::#prefix::mem::uninitialized() + }; - unsafe { - ::$prefix::ptr::copy_nonoverlapping( - &self.$unit_field_ident as *const _ as *const u8, - &mut unit_field_val as *mut $unit_field_int_ty as *mut u8, - ::$prefix::mem::size_of::<$unit_field_int_ty>(), - ) - }; + unsafe { + ::#prefix::ptr::copy_nonoverlapping( + &self.#unit_field_ident as *const _ as *const u8, + &mut unit_field_val as *mut #unit_field_int_ty as *mut u8, + ::#prefix::mem::size_of::< #unit_field_int_ty >(), + ) + }; - unit_field_val &= !mask; - unit_field_val |= (val << $offset) & mask; + unit_field_val &= !mask; + unit_field_val |= (val << #offset) & mask; - unsafe { - ::$prefix::ptr::copy_nonoverlapping( - &unit_field_val as *const _ as *const u8, - &mut self.$unit_field_ident as *mut _ as *mut u8, - ::$prefix::mem::size_of::<$unit_field_int_ty>(), - ); - } + unsafe { + ::#prefix::ptr::copy_nonoverlapping( + &unit_field_val as *const _ as *const u8, + &mut self.#unit_field_ident as *mut _ as *mut u8, + ::#prefix::mem::size_of::< #unit_field_int_ty >(), + ); } } - ).unwrap(); - - match impl_item.unwrap().node { - ast::ItemKind::Impl(_, _, _, _, _, items) => { - methods.extend(items.into_iter()); - } - _ => unreachable!(), - }; + })); } } @@ -1454,13 +1430,12 @@ impl CodeGenerator for CompInfo { // collisions. if self.is_forward_declaration() && used_template_params.is_none() { let struct_name = item.canonical_name(ctx); - let struct_name = ctx.rust_ident_raw(&struct_name); - let tuple_struct = quote_item!(ctx.ext_cx(), - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct $struct_name { _unused: [u8; 0] }; - ) - .unwrap(); + let struct_name = ctx.rust_ident_raw(struct_name); + let tuple_struct = quote! { + #[repr(C)] + #[derive(Debug, Copy, Clone)] + pub struct #struct_name { _unused: [u8; 0] } + }; result.push(tuple_struct); return; } @@ -1527,18 +1502,17 @@ impl CodeGenerator for CompInfo { } let canonical_name = item.canonical_name(ctx); - let builder = if is_union && self.can_be_rust_union(ctx) { - aster::AstBuilder::new() - .item() - .pub_() - .with_attrs(attributes) - .union_(&canonical_name) + let canonical_ident = ctx.rust_ident(&canonical_name); + let mut tokens = if is_union && self.can_be_rust_union(ctx) { + quote! { + #( #attributes )* + pub union #canonical_ident + } } else { - aster::AstBuilder::new() - .item() - .pub_() - .with_attrs(attributes) - .struct_(&canonical_name) + quote! { + #( #attributes )* + pub struct #canonical_ident + } }; // Generate the vtable from the method list if appropriate. @@ -1567,15 +1541,13 @@ impl CodeGenerator for CompInfo { let vtable_type = vtable .try_to_rust_ty(ctx, &()) .expect("vtable to Rust type conversion is infallible") - .to_ptr(true, ctx.span()); + .to_ptr(true); - let vtable_field = StructFieldBuilder::named("vtable_") - .pub_() - .build_ty(vtable_type); + fields.push(quote! { + pub vtable_: #vtable_type , + }); struct_layout.saw_vtable(); - - fields.push(vtable_field); } for (i, base) in self.base_members().iter().enumerate() { @@ -1596,17 +1568,17 @@ impl CodeGenerator for CompInfo { } let inner = base.ty.to_rust_ty_or_opaque(ctx, &()); - let field_name = if i == 0 { + let field_name = ctx.rust_ident(if i == 0 { "_base".into() } else { format!("_base_{}", i) - }; + }); struct_layout.saw_base(base_ty); - let field = - StructFieldBuilder::named(field_name).pub_().build_ty(inner); - fields.extend(Some(field)); + fields.push(quote! { + pub #field_name : #inner , + }); } } if is_union { @@ -1647,17 +1619,17 @@ impl CodeGenerator for CompInfo { let layout = layout.expect("Unable to get layout information?"); let ty = helpers::blob(layout); - let field = if self.can_be_rust_union(ctx) { - StructFieldBuilder::named("_bindgen_union_align").build_ty(ty) + fields.push(if self.can_be_rust_union(ctx) { + quote! { + _bindgen_union_align: #ty , + } } else { struct_layout.saw_union(layout); - StructFieldBuilder::named("bindgen_union_field") - .pub_() - .build_ty(ty) - }; - - fields.push(field); + quote! { + pub bindgen_union_field: #ty , + } + }); } if is_opaque { @@ -1668,11 +1640,9 @@ impl CodeGenerator for CompInfo { match layout { Some(l) => { let ty = helpers::blob(l); - let field = StructFieldBuilder::named( - "_bindgen_opaque_blob", - ).pub_() - .build_ty(ty); - fields.push(field); + fields.push(quote! { + pub _bindgen_opaque_blob: #ty , + }); } None => { warn!("Opaque type without layout! Expect dragons!"); @@ -1713,41 +1683,45 @@ impl CodeGenerator for CompInfo { if has_address { let ty = helpers::blob(Layout::new(1, 1)); - let field = - StructFieldBuilder::named("_address").pub_().build_ty(ty); - fields.push(field); + fields.push(quote! { + pub _address: #ty, + }); } } - let mut generics = aster::AstBuilder::new().generics(); + let mut generics = quote! {}; if let Some(ref params) = used_template_params { - for (idx, ty) in params.iter().enumerate() { - let param = ctx.resolve_type(*ty); - let name = param.name().unwrap(); - let ident = ctx.rust_ident(name); + if !params.is_empty() { + let mut param_names = vec![]; - generics = generics.ty_param_id(ident); + for (idx, ty) in params.iter().enumerate() { + let param = ctx.resolve_type(*ty); + let name = param.name().unwrap(); + let ident = ctx.rust_ident(name); + param_names.push(ident.clone()); - let prefix = ctx.trait_prefix(); - let phantom_ty = quote_ty!( - ctx.ext_cx(), - ::$prefix::marker::PhantomData<::$prefix::cell::UnsafeCell<$ident>>); - let phantom_field = StructFieldBuilder::named( - format!("_phantom_{}", idx), - ).pub_() - .build_ty(phantom_ty); - fields.push(phantom_field); + let prefix = ctx.trait_prefix(); + let field_name = ctx.rust_ident(format!("_phantom_{}", idx)); + fields.push(quote! { + pub #field_name : ::#prefix::marker::PhantomData< + ::#prefix::cell::UnsafeCell<#ident> + > , + }); + } + + generics = quote! { + < #( #param_names ),* > + }; } } - let generics = generics.build(); - - let rust_struct = builder - .with_generics(generics.clone()) - .with_fields(fields) - .build(); - result.push(rust_struct); + tokens.append(quote! { + #generics { + #( #fields )* + } + }); + result.push(tokens); // Generate the inner types and all that stuff. // @@ -1765,7 +1739,7 @@ impl CodeGenerator for CompInfo { if self.found_unknown_attr() { warn!( "Type {} has an unkown attribute that may affect layout", - canonical_name + canonical_ident ); } @@ -1779,14 +1753,15 @@ impl CodeGenerator for CompInfo { if ctx.options().layout_tests { if let Some(layout) = layout { 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); + format!("bindgen_test_layout_{}", canonical_ident); + let fn_name = ctx.rust_ident_raw(fn_name); let prefix = ctx.trait_prefix(); - let size_of_expr = quote_expr!(ctx.ext_cx(), - ::$prefix::mem::size_of::<$type_name>()); - let align_of_expr = quote_expr!(ctx.ext_cx(), - ::$prefix::mem::align_of::<$type_name>()); + let size_of_expr = quote! { + ::#prefix::mem::size_of::<#canonical_ident>() + }; + let align_of_expr = quote! { + ::#prefix::mem::align_of::<#canonical_ident>() + }; let size = layout.size; let align = layout.align; @@ -1795,11 +1770,12 @@ impl CodeGenerator for CompInfo { // 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))); - ) + Some(quote! { + assert_eq!(#align_of_expr, + #align, + concat!("Alignment of ", stringify!(#canonical_ident))); + + }) }; // FIXME when [issue #465](https://github.com/rust-lang-nursery/rust-bindgen/issues/465) ready @@ -1814,43 +1790,43 @@ impl CodeGenerator for CompInfo { let check_field_offset = if should_skip_field_offset_checks { - None + vec![] } else { let asserts = self.fields() - .iter() - .filter_map(|field| match *field { - Field::DataMember(ref f) if f.name().is_some() => Some(f), - _ => None, - }) - .flat_map(|field| { - let name = field.name().unwrap(); - field.offset().and_then(|offset| { - let field_offset = offset / 8; - let field_name = ctx.rust_ident(name); - - quote_item!(ctx.ext_cx(), - assert_eq!(unsafe { &(*(0 as *const $type_name)).$field_name as *const _ as usize }, - $field_offset, - concat!("Alignment of field: ", stringify!($type_name), "::", stringify!($field_name))); - ) - }) - }) - .collect::<Vec<P<ast::Item>>>(); - - Some(asserts) + .iter() + .filter_map(|field| match *field { + Field::DataMember(ref f) if f.name().is_some() => Some(f), + _ => None, + }) + .flat_map(|field| { + let name = field.name().unwrap(); + field.offset().and_then(|offset| { + let field_offset = offset / 8; + let field_name = ctx.rust_ident(name); + + Some(quote! { + assert_eq!(unsafe { &(*(0 as *const #canonical_ident)).#field_name as *const _ as usize }, + #field_offset, + concat!("Alignment of field: ", stringify!(#canonical_ident), "::", stringify!(#field_name))); + }) + }) + }) + .collect::<Vec<quote::Tokens>>(); + + asserts }; - let item = quote_item!(ctx.ext_cx(), + let item = quote! { #[test] - fn $fn_name() { - assert_eq!($size_of_expr, - $size, - concat!("Size of: ", stringify!($type_name))); + fn #fn_name() { + assert_eq!(#size_of_expr, + #size, + concat!("Size of: ", stringify!(#canonical_ident))); - $check_struct_align - $check_field_offset - }) - .unwrap(); + #check_struct_align + #( #check_field_offset )* + } + }; result.push(item); } } @@ -1907,63 +1883,25 @@ impl CodeGenerator for CompInfo { // NB: We can't use to_rust_ty here since for opaque types this tries to // use the specialization knowledge to generate a blob field. - let ty_for_impl = aster::AstBuilder::new() - .ty() - .path() - .segment(&canonical_name) - .with_generics(generics.clone()) - .build() - .build(); + let ty_for_impl = quote! { + #canonical_ident #generics + }; if needs_clone_impl { - let impl_ = quote_item!(ctx.ext_cx(), - impl X { + result.push(quote! { + impl #generics Clone for #ty_for_impl { fn clone(&self) -> Self { *self } } - ); - - let impl_ = match impl_.unwrap().node { - ast::ItemKind::Impl(_, _, _, _, _, ref items) => items.clone(), - _ => unreachable!(), - }; - - let clone_impl = aster::AstBuilder::new() - .item() - .impl_() - .trait_() - .id("Clone") - .build() - .with_generics(generics.clone()) - .with_items(impl_) - .build_ty(ty_for_impl.clone()); - - result.push(clone_impl); + }); } if needs_default_impl { let prefix = ctx.trait_prefix(); - let impl_ = quote_item!(ctx.ext_cx(), - impl X { - fn default() -> Self { unsafe { ::$prefix::mem::zeroed() } } + result.push(quote! { + impl #generics Default for #ty_for_impl { + fn default() -> Self { unsafe { ::#prefix::mem::zeroed() } } } - ); - - let impl_ = match impl_.unwrap().node { - ast::ItemKind::Impl(_, _, _, _, _, ref items) => items.clone(), - _ => unreachable!(), - }; - - let default_impl = aster::AstBuilder::new() - .item() - .impl_() - .trait_() - .id("Default") - .build() - .with_generics(generics.clone()) - .with_items(impl_) - .build_ty(ty_for_impl.clone()); - - result.push(default_impl); + }); } if needs_debug_impl { @@ -1974,27 +1912,19 @@ impl CodeGenerator for CompInfo { 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); + result.push(quote! { + impl #generics ::std::fmt::Debug for #ty_for_impl { + #impl_ + } + }); } if !methods.is_empty() { - let methods = aster::AstBuilder::new() - .item() - .impl_() - .with_generics(generics) - .with_items(methods) - .build_ty(ty_for_impl); - result.push(methods); + result.push(quote! { + impl #generics #ty_for_impl { + #( #methods )* + } + }); } } } @@ -2003,7 +1933,7 @@ trait MethodCodegen { fn codegen_method<'a>( &self, ctx: &BindgenContext, - methods: &mut Vec<ast::ImplItem>, + methods: &mut Vec<quote::Tokens>, method_names: &mut HashMap<String, usize>, result: &mut CodegenResult<'a>, parent: &CompInfo, @@ -2014,7 +1944,7 @@ impl MethodCodegen for Method { fn codegen_method<'a>( &self, ctx: &BindgenContext, - methods: &mut Vec<ast::ImplItem>, + methods: &mut Vec<quote::Tokens>, method_names: &mut HashMap<String, usize>, result: &mut CodegenResult<'a>, _parent: &CompInfo, @@ -2067,45 +1997,15 @@ impl MethodCodegen for Method { name.push_str(&count.to_string()); } - let function_name = function_item.canonical_name(ctx); - let mut fndecl = utils::rust_fndecl_from_signature(ctx, signature_item) - .unwrap(); + let function_name = ctx.rust_ident(function_item.canonical_name(ctx)); + let mut args = utils::fnsig_arguments(ctx, signature); + let mut ret = utils::fnsig_return_ty(ctx, signature); + if !self.is_static() && !self.is_constructor() { - let mutability = if self.is_const() { - ast::Mutability::Immutable + args[0] = if self.is_const() { + quote! { &self } } else { - ast::Mutability::Mutable - }; - - assert!(!fndecl.inputs.is_empty()); - - // FIXME: use aster here. - 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, - }, - ), - span: ctx.span(), - }), - pat: P(ast::Pat { - id: ast::DUMMY_NODE_ID, - node: ast::PatKind::Ident( - ast::BindingMode::ByValue(ast::Mutability::Immutable), - respan(ctx.span(), ctx.ext_cx().ident_of("self")), - None, - ), - span: ctx.span(), - }), - id: ast::DUMMY_NODE_ID, + quote! { &mut self } }; } @@ -2115,19 +2015,10 @@ impl MethodCodegen for Method { // Note that constructors in Clang are represented as functions with // return-type = void. if self.is_constructor() { - fndecl.inputs.remove(0); - fndecl.output = - ast::FunctionRetTy::Ty(quote_ty!(ctx.ext_cx(), Self)); + args.remove(0); + ret = quote! { -> Self }; } - let sig = ast::MethodSig { - unsafety: ast::Unsafety::Unsafe, - abi: abi::Abi::Rust, - decl: P(fndecl), - generics: ast::Generics::default(), - constness: respan(ctx.span(), ast::Constness::NotConst), - }; - let mut exprs = helpers::ast_ty::arguments_from_signature(&signature, ctx); @@ -2138,67 +2029,60 @@ impl MethodCodegen for Method { if self.is_constructor() { let prefix = ctx.trait_prefix(); let tmp_variable_decl = - quote_stmt!(ctx.ext_cx(), - let mut __bindgen_tmp = ::$prefix::mem::uninitialized()) - .unwrap(); + quote! { + let mut __bindgen_tmp = ::#prefix::mem::uninitialized() + }; stmts.push(tmp_variable_decl); - exprs[0] = quote_expr!(ctx.ext_cx(), &mut __bindgen_tmp); + exprs[0] = quote! { + &mut __bindgen_tmp + }; } else if !self.is_static() { assert!(!exprs.is_empty()); - exprs[0] = quote_expr!(ctx.ext_cx(), self); + exprs[0] = quote! { + self + }; }; - let call = aster::expr::ExprBuilder::new() - .call() - .id(function_name) - .with_args(exprs) - .build(); + let call = quote! { + #function_name (#( #exprs ),* ) + }; - stmts.push(ast::Stmt { - id: ast::DUMMY_NODE_ID, - node: ast::StmtKind::Expr(call), - span: ctx.span(), - }); + stmts.push(call); if self.is_constructor() { - stmts.push(quote_stmt!(ctx.ext_cx(), __bindgen_tmp).unwrap()); + stmts.push(quote! { + __bindgen_tmp + }); } - let block = ast::Block { - stmts: stmts, - id: ast::DUMMY_NODE_ID, - rules: ast::BlockCheckMode::Default, - span: ctx.span(), + let block = quote! { + #( #stmts );* }; let mut attrs = vec![]; attrs.push(attributes::inline()); - let item = ast::ImplItem { - id: ast::DUMMY_NODE_ID, - ident: ctx.rust_ident(&name), - vis: ast::Visibility::Public, - attrs: attrs, - node: ast::ImplItemKind::Method(sig, P(block)), - defaultness: ast::Defaultness::Final, - span: ctx.span(), - }; - - methods.push(item); + let name = ctx.rust_ident(&name); + methods.push(quote! { + #[inline] + pub unsafe fn #name ( #( #args ),* ) #ret { + #block + } + }); } } /// A helper type to construct enums, either bitfield ones or rust-style ones. enum EnumBuilder<'a> { - Rust(aster::item::ItemEnumBuilder<aster::invoke::Identity>), + Rust(quote::Tokens), Bitfield { canonical_name: &'a str, - aster: P<ast::Item>, + tokens: quote::Tokens, }, - Consts { aster: P<ast::Item> }, + Consts(Vec<quote::Tokens>), ModuleConsts { module_name: &'a str, - module_items: Vec<P<ast::Item>>, + module_items: Vec<quote::Tokens>, }, } @@ -2206,41 +2090,47 @@ 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<aster::invoke::Identity>, name: &'a str, - repr: P<ast::Ty>, + attrs: Vec<quote::Tokens>, + repr: quote::Tokens, bitfield_like: bool, constify: bool, constify_module: bool, ) -> Self { + let ident = quote::Ident::new(name); if bitfield_like { EnumBuilder::Bitfield { canonical_name: name, - aster: aster - .tuple_struct(name) - .field() - .pub_() - .build_ty(repr) - .build(), + tokens: quote! { + #( #attrs )* + pub struct #ident (pub #repr); + }, } } else if constify { if constify_module { - let type_definition = aster::item::ItemBuilder::new() - .pub_() - .type_(CONSTIFIED_ENUM_MODULE_REPR_NAME) - .build_ty(repr); + let ident = quote::Ident::new(CONSTIFIED_ENUM_MODULE_REPR_NAME); + let type_definition = quote! { + pub type #ident = #repr; + }; EnumBuilder::ModuleConsts { module_name: name, module_items: vec![type_definition], } } else { - EnumBuilder::Consts { - aster: aster.type_(name).build_ty(repr), - } + EnumBuilder::Consts(vec![ + quote! { + pub type #ident = #repr; + } + ]) } } else { - EnumBuilder::Rust(aster.enum_(name)) + let mut tokens = quote! { + #( #attrs )* + pub enum #ident + }; + tokens.append("{"); + EnumBuilder::Rust(tokens) } } @@ -2250,28 +2140,25 @@ impl<'a> EnumBuilder<'a> { ctx: &BindgenContext, variant: &EnumVariant, mangling_prefix: Option<&String>, - rust_ty: P<ast::Ty>, + rust_ty: quote::Tokens, result: &mut CodegenResult<'b>, ) -> Self { let variant_name = ctx.rust_mangle(variant.name()); - let expr = aster::AstBuilder::new().expr(); let expr = match variant.val() { EnumVariantValue::Signed(v) => helpers::ast_ty::int_expr(v), - EnumVariantValue::Unsigned(v) => expr.uint(v), + EnumVariantValue::Unsigned(v) => helpers::ast_ty::uint_expr(v), }; match self { - EnumBuilder::Rust(b) => { - EnumBuilder::Rust(b.with_variant_(ast::Variant_ { - name: ctx.rust_ident(&*variant_name), - attrs: vec![], - data: ast::VariantData::Unit(ast::DUMMY_NODE_ID), - disr_expr: Some(expr), - })) + EnumBuilder::Rust(tokens) => { + let name = ctx.rust_ident(variant_name); + EnumBuilder::Rust(quote! { + #tokens + #name = #expr, + }) } - EnumBuilder::Bitfield { - canonical_name, .. - } => { + + EnumBuilder::Bitfield { .. } => { let constant_name = match mangling_prefix { Some(prefix) => { Cow::Owned(format!("{}_{}", prefix, variant_name)) @@ -2279,20 +2166,14 @@ impl<'a> EnumBuilder<'a> { None => variant_name, }; - let constant = aster::AstBuilder::new() - .item() - .pub_() - .const_(&*constant_name) - .expr() - .call() - .id(canonical_name) - .arg() - .build(expr) - .build() - .build(rust_ty); - result.push(constant); + let ident = ctx.rust_ident(constant_name); + result.push(quote! { + pub const #ident : #rust_ty = #rust_ty ( #expr ); + }); + self } + EnumBuilder::Consts { .. } => { @@ -2303,37 +2184,22 @@ impl<'a> EnumBuilder<'a> { None => variant_name, }; - let constant = aster::AstBuilder::new() - .item() - .pub_() - .const_(&*constant_name) - .expr() - .build(expr) - .build(rust_ty); + let ident = ctx.rust_ident(constant_name); + result.push(quote! { + pub const #ident : #rust_ty = #expr ; + }); - result.push(constant); self } EnumBuilder::ModuleConsts { module_name, - module_items, - .. + mut module_items, } => { - // Variant type - let inside_module_type = aster::AstBuilder::new().ty().id( - CONSTIFIED_ENUM_MODULE_REPR_NAME, - ); - - let constant = aster::AstBuilder::new() - .item() - .pub_() - .const_(&*variant_name) - .expr() - .build(expr) - .build(inside_module_type.clone()); - - let mut module_items = module_items.clone(); - module_items.push(constant); + let name = ctx.rust_ident(variant_name); + let ty = ctx.rust_ident(CONSTIFIED_ENUM_MODULE_REPR_NAME); + module_items.push(quote! { + pub const #name : #ty = #expr ; + }); EnumBuilder::ModuleConsts { module_name, @@ -2346,86 +2212,74 @@ impl<'a> EnumBuilder<'a> { fn build<'b>( self, ctx: &BindgenContext, - rust_ty: P<ast::Ty>, + rust_ty: quote::Tokens, result: &mut CodegenResult<'b>, - ) -> P<ast::Item> { + ) -> quote::Tokens { match self { - EnumBuilder::Rust(b) => b.build(), + EnumBuilder::Rust(mut t) => { + t.append("}"); + t + } EnumBuilder::Bitfield { canonical_name, - aster, + tokens, } => { let rust_ty_name = ctx.rust_ident_raw(canonical_name); let prefix = ctx.trait_prefix(); - let impl_ = quote_item!(ctx.ext_cx(), - impl ::$prefix::ops::BitOr<$rust_ty> for $rust_ty { + result.push(quote! { + impl ::#prefix::ops::BitOr<#rust_ty> for #rust_ty { type Output = Self; #[inline] fn bitor(self, other: Self) -> Self { - $rust_ty_name(self.0 | other.0) + #rust_ty_name(self.0 | other.0) } } - ).unwrap(); - result.push(impl_); + }); - let impl_ = quote_item!(ctx.ext_cx(), - impl ::$prefix::ops::BitOrAssign for $rust_ty { + result.push(quote! { + impl ::#prefix::ops::BitOrAssign for #rust_ty { #[inline] - fn bitor_assign(&mut self, rhs: $rust_ty) { + fn bitor_assign(&mut self, rhs: #rust_ty) { self.0 |= rhs.0; } } - ).unwrap(); - result.push(impl_); + }); - let impl_ = quote_item!(ctx.ext_cx(), - impl ::$prefix::ops::BitAnd<$rust_ty> for $rust_ty { + result.push(quote! { + impl ::#prefix::ops::BitAnd<#rust_ty> for #rust_ty { type Output = Self; #[inline] fn bitand(self, other: Self) -> Self { - $rust_ty_name(self.0 & other.0) + #rust_ty_name(self.0 & other.0) } } - ).unwrap(); - result.push(impl_); + }); - let impl_ = quote_item!(ctx.ext_cx(), - impl ::$prefix::ops::BitAndAssign for $rust_ty { + result.push(quote! { + impl ::#prefix::ops::BitAndAssign for #rust_ty { #[inline] - fn bitand_assign(&mut self, rhs: $rust_ty) { + fn bitand_assign(&mut self, rhs: #rust_ty) { self.0 &= rhs.0; } } - ).unwrap(); - result.push(impl_); + }); - aster + tokens } - EnumBuilder::Consts { - aster, .. - } => aster, + EnumBuilder::Consts(tokens) => quote! { #( #tokens )* }, 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), - attrs: vec![], - id: ast::DUMMY_NODE_ID, - node: ast::ItemKind::Mod(ast::Mod { - inner: DUMMY_SP, - items: module_items, - }), - vis: ast::Visibility::Public, - span: DUMMY_SP, - }); - - module_item + let ident = ctx.rust_ident(module_name); + quote! { + pub mod #ident { + #( #module_items )* + } + } } } } @@ -2444,6 +2298,7 @@ impl CodeGenerator for Enum { debug_assert!(item.is_enabled_for_codegen(ctx)); let name = item.canonical_name(ctx); + let ident = ctx.rust_ident(&name); let enum_ty = item.expect_type(); let layout = enum_ty.layout(ctx); @@ -2485,8 +2340,6 @@ impl CodeGenerator for Enum { } }; - let mut builder = aster::AstBuilder::new().item().pub_(); - // FIXME(emilio): These should probably use the path so it can // disambiguate between namespaces, just like is_opaque etc. let is_bitfield = { @@ -2511,42 +2364,41 @@ impl CodeGenerator for Enum { let is_rust_enum = !is_bitfield && !is_constified_enum; + let mut attrs = vec![]; + // FIXME: Rust forbids repr with empty enums. Remove this condition when // this is allowed. // // TODO(emilio): Delegate this to the builders? if is_rust_enum { if !self.variants().is_empty() { - builder = builder.with_attr(attributes::repr(repr_name)); + attrs.push(attributes::repr(repr_name)); } } else if is_bitfield { - builder = builder.with_attr(attributes::repr("C")); + attrs.push(attributes::repr("C")); } if let Some(comment) = item.comment(ctx) { - builder = builder.with_attr(attributes::doc(comment)); + attrs.push(attributes::doc(comment)); } if !is_constified_enum { - let derives = - attributes::derives( - &["Debug", "Copy", "Clone", "PartialEq", "Eq", "Hash"], - ); - - builder = builder.with_attr(derives); + attrs.push(attributes::derives( + &["Debug", "Copy", "Clone", "PartialEq", "Eq", "Hash"], + )); } fn add_constant<'a>( ctx: &BindgenContext, enum_: &Type, // Only to avoid recomputing every time. - enum_canonical_name: &str, + enum_canonical_name: "e::Ident, // 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<ast::Ty>, + referenced_name: "e::Ident, + enum_rust_ty: quote::Tokens, result: &mut CodegenResult<'a>, ) { let constant_name = if enum_.name().is_some() { @@ -2558,17 +2410,12 @@ impl CodeGenerator for Enum { } else { variant_name.into() }; + let constant_name = ctx.rust_ident(constant_name); - let constant = aster::AstBuilder::new() - .item() - .pub_() - .const_(constant_name) - .expr() - .path() - .ids(&[&*enum_canonical_name, referenced_name]) - .build() - .build(enum_rust_ty); - result.push(constant); + result.push(quote! { + pub const #constant_name : #enum_rust_ty = + #enum_canonical_name :: #referenced_name ; + }); } let repr = @@ -2577,8 +2424,8 @@ impl CodeGenerator for Enum { .unwrap_or_else(|| helpers::ast_ty::raw_type(ctx, repr_name)); let mut builder = EnumBuilder::new( - builder, &name, + attrs, repr, is_bitfield, is_constified_enum, @@ -2586,7 +2433,7 @@ impl CodeGenerator for Enum { ); // A map where we keep a value -> variant relation. - let mut seen_values = HashMap::<_, String>::new(); + let mut seen_values = HashMap::<_, quote::Ident>::new(); let enum_rust_ty = item.to_rust_ty_or_opaque(ctx, &()); let is_toplevel = item.is_toplevel(ctx); @@ -2646,7 +2493,7 @@ impl CodeGenerator for Enum { add_constant( ctx, enum_ty, - &name, + &ident, &*mangled_name, existing_variant_name, enum_rust_ty.clone(), @@ -2671,7 +2518,7 @@ impl CodeGenerator for Enum { result, ); - let variant_name = ctx.rust_mangle(variant.name()); + let variant_name = ctx.rust_ident(variant.name()); // If it's an unnamed enum, or constification is enforced, // we also generate a constant so it can be properly @@ -2685,29 +2532,33 @@ impl CodeGenerator for Enum { let parent_name = parent_canonical_name.as_ref().unwrap(); - Cow::Owned( - format!("{}_{}", parent_name, variant_name), + quote::Ident::new( + format!( + "{}_{}", + parent_name, + variant_name + ) ) }; add_constant( ctx, enum_ty, - &name, - &mangled_name, + &ident, + mangled_name.as_ref(), &variant_name, enum_rust_ty.clone(), result, ); } - entry.insert(variant_name.into_owned()); + entry.insert(quote::Ident::new(variant_name)); } } } - let enum_ = builder.build(ctx, enum_rust_ty, result); - result.push(enum_); + let item = builder.build(ctx, enum_rust_ty, result); + result.push(item); } } @@ -2731,7 +2582,7 @@ trait TryToOpaque { &self, ctx: &BindgenContext, extra: &Self::Extra, - ) -> error::Result<P<ast::Ty>> { + ) -> error::Result<quote::Tokens> { self.try_get_layout(ctx, extra).map(|layout| { helpers::blob(layout) }) @@ -2759,7 +2610,7 @@ trait ToOpaque: TryToOpaque { &self, ctx: &BindgenContext, extra: &Self::Extra, - ) -> P<ast::Ty> { + ) -> quote::Tokens { let layout = self.get_layout(ctx, extra); helpers::blob(layout) } @@ -2785,7 +2636,7 @@ trait TryToRustTy { &self, ctx: &BindgenContext, extra: &Self::Extra, - ) -> error::Result<P<ast::Ty>>; + ) -> error::Result<quote::Tokens>; } /// Fallible conversion to a Rust type or an opaque blob with the correct size @@ -2800,7 +2651,7 @@ trait TryToRustTyOrOpaque: TryToRustTy + TryToOpaque { &self, ctx: &BindgenContext, extra: &<Self as TryToRustTyOrOpaque>::Extra, - ) -> error::Result<P<ast::Ty>>; + ) -> error::Result<quote::Tokens>; } impl<E, T> TryToRustTyOrOpaque for T @@ -2814,7 +2665,7 @@ where &self, ctx: &BindgenContext, extra: &E, - ) -> error::Result<P<ast::Ty>> { + ) -> error::Result<quote::Tokens> { self.try_to_rust_ty(ctx, extra).or_else( |_| if let Ok(layout) = self.try_get_layout(ctx, extra) @@ -2851,7 +2702,7 @@ trait ToRustTyOrOpaque: TryToRustTy + ToOpaque { &self, ctx: &BindgenContext, extra: &<Self as ToRustTyOrOpaque>::Extra, - ) -> P<ast::Ty>; + ) -> quote::Tokens; } impl<E, T> ToRustTyOrOpaque for T @@ -2864,7 +2715,7 @@ where &self, ctx: &BindgenContext, extra: &E, - ) -> P<ast::Ty> { + ) -> quote::Tokens { self.try_to_rust_ty(ctx, extra).unwrap_or_else(|_| { self.to_opaque(ctx, extra) }) @@ -2890,7 +2741,7 @@ impl TryToRustTy for ItemId { &self, ctx: &BindgenContext, _: &(), - ) -> error::Result<P<ast::Ty>> { + ) -> error::Result<quote::Tokens> { ctx.resolve_item(*self).try_to_rust_ty(ctx, &()) } } @@ -2914,7 +2765,7 @@ impl TryToRustTy for Item { &self, ctx: &BindgenContext, _: &(), - ) -> error::Result<P<ast::Ty>> { + ) -> error::Result<quote::Tokens> { self.kind().expect_type().try_to_rust_ty(ctx, self) } } @@ -2938,7 +2789,7 @@ impl TryToRustTy for Type { &self, ctx: &BindgenContext, item: &Item, - ) -> error::Result<P<ast::Ty>> { + ) -> error::Result<quote::Tokens> { use self::helpers::ast_ty::*; match *self.kind() { @@ -2946,11 +2797,11 @@ impl TryToRustTy for Type { // TODO: we should do something smart with nullptr, or maybe *const // c_void is enough? TypeKind::NullPtr => { - Ok(raw_type(ctx, "c_void").to_ptr(true, ctx.span())) + Ok(raw_type(ctx, "c_void").to_ptr(true)) } TypeKind::Int(ik) => { match ik { - IntKind::Bool => Ok(aster::ty::TyBuilder::new().bool()), + IntKind::Bool => Ok(quote! { bool }), IntKind::Char { .. } => Ok(raw_type(ctx, "c_char")), @@ -2965,25 +2816,27 @@ impl TryToRustTy for Type { IntKind::LongLong => Ok(raw_type(ctx, "c_longlong")), IntKind::ULongLong => Ok(raw_type(ctx, "c_ulonglong")), - IntKind::I8 => Ok(aster::ty::TyBuilder::new().i8()), - IntKind::U8 => Ok(aster::ty::TyBuilder::new().u8()), - IntKind::I16 => Ok(aster::ty::TyBuilder::new().i16()), - IntKind::U16 => Ok(aster::ty::TyBuilder::new().u16()), - IntKind::I32 => Ok(aster::ty::TyBuilder::new().i32()), - 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::I8 => Ok(quote! { i8 }), + IntKind::U8 => Ok(quote! { u8 }), + IntKind::I16 => Ok(quote! { i16 }), + IntKind::U16 => Ok(quote! { u16 }), + IntKind::I32 => Ok(quote! { i32 }), + IntKind::U32 => Ok(quote! { u32 }), + IntKind::I64 => Ok(quote! { i64 }), + IntKind::U64 => Ok(quote! { u64 }), IntKind::Custom { name, .. } => { let ident = ctx.rust_ident_raw(name); - Ok(quote_ty!(ctx.ext_cx(), $ident)) + Ok(quote! { + #ident + }) } // FIXME: This doesn't generate the proper alignment, but we // can't do better right now. We should be able to use // i128/u128 when they're available. IntKind::U128 | IntKind::I128 => { - Ok(aster::ty::TyBuilder::new().array(2).u64()) + Ok(quote! { [u64; 2] }) } } } @@ -2993,9 +2846,13 @@ impl TryToRustTy for Type { ctx.generated_bindegen_complex(); Ok(if ctx.options().enable_cxx_namespaces { - quote_ty!(ctx.ext_cx(), root::__BindgenComplex<$float_path>) + quote! { + root::__BindgenComplex<#float_path> + } } else { - quote_ty!(ctx.ext_cx(), __BindgenComplex<$float_path>) + quote! { + __BindgenComplex<#float_path> + } }) } TypeKind::Function(ref fs) => { @@ -3003,18 +2860,24 @@ impl TryToRustTy for Type { // sizeof(NonZero<_>) optimization with opaque blobs (because // they aren't NonZero), so don't *ever* use an or_opaque // variant here. - let ty = fs.try_to_rust_ty(ctx, item)?; + let ty = fs.try_to_rust_ty(ctx, &())?; let prefix = ctx.trait_prefix(); - Ok(quote_ty!(ctx.ext_cx(), ::$prefix::option::Option<$ty>)) + Ok(quote! { + ::#prefix::option::Option<#ty> + }) } TypeKind::Array(item, len) => { let ty = item.try_to_rust_ty(ctx, &())?; - Ok(aster::ty::TyBuilder::new().array(len).build(ty)) + Ok(quote! { + [ #ty ; #len ] + }) } TypeKind::Enum(..) => { + let mut tokens = quote! {}; let path = item.namespace_aware_canonical_path(ctx); - Ok(aster::AstBuilder::new().ty().path().ids(path).build()) + tokens.append_separated(path.into_iter().map(quote::Ident::new), "::"); + Ok(tokens) } TypeKind::TemplateInstantiation(ref inst) => { inst.try_to_rust_ty(ctx, item) @@ -3039,7 +2902,7 @@ impl TryToRustTy for Type { { Ok(ty) } else { - utils::build_templated_path(item, ctx, template_params) + utils::build_templated_path(item, ctx, vec![]) //template_params) } } TypeKind::Comp(ref info) => { @@ -3050,48 +2913,54 @@ impl TryToRustTy for Type { return self.try_to_opaque(ctx, item); } - let template_params = template_params.unwrap_or(vec![]); - utils::build_templated_path(item, ctx, template_params) + // let template_params = template_params.unwrap_or(vec![]); + utils::build_templated_path(item, ctx, vec![]) } 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(), + false )) } TypeKind::Pointer(inner) | TypeKind::Reference(inner) => { - let inner = ctx.resolve_item(inner); + let is_const = self.is_const() || ctx.resolve_type(inner).is_const(); + + let inner = inner.into_resolver().through_type_refs().resolve(ctx); let inner_ty = inner.expect_type(); // Regardless if we can properly represent the inner type, we // should always generate a proper pointer here, so use // infallible conversion of the inner type. - let ty = inner.to_rust_ty_or_opaque(ctx, &()); + let mut ty = inner.to_rust_ty_or_opaque(ctx, &()); + ty.append_implicit_template_params(ctx, inner); // Avoid the first function pointer level, since it's already // represented in Rust. if inner_ty.canonical_type(ctx).is_function() { Ok(ty) } else { - let is_const = self.is_const() || - inner.expect_type().is_const(); - Ok(ty.to_ptr(is_const, ctx.span())) + Ok(ty.to_ptr(is_const)) } } TypeKind::TypeParam => { let name = item.canonical_name(ctx); let ident = ctx.rust_ident(&name); - Ok(quote_ty!(ctx.ext_cx(), $ident)) + Ok(quote! { + #ident + }) } TypeKind::ObjCSel => { - Ok(quote_ty!(ctx.ext_cx(), objc::runtime::Sel)) + Ok(quote! { + objc::runtime::Sel + }) } TypeKind::ObjCId | - TypeKind::ObjCInterface(..) => Ok(quote_ty!(ctx.ext_cx(), id)), + TypeKind::ObjCInterface(..) => Ok(quote! { + id + }), ref u @ TypeKind::UnresolvedTypeRef(..) => { unreachable!("Should have been resolved after parsing {:?}!", u) } @@ -3120,108 +2989,81 @@ impl TryToRustTy for TemplateInstantiation { &self, ctx: &BindgenContext, item: &Item, - ) -> error::Result<P<ast::Ty>> { + ) -> error::Result<quote::Tokens> { if self.is_opaque(ctx, item) { return Err(error::Error::InstantiationOfOpaqueType); } - let decl = self.template_definition(); - let mut ty = decl.try_to_rust_ty(ctx, &())?.unwrap(); + let def = self.template_definition() + .into_resolver() + .through_type_refs() + .resolve(ctx); - let decl_params = match decl.self_template_params(ctx) { + let mut ty = quote! {}; + let def_path = def.namespace_aware_canonical_path(ctx); + ty.append_separated(def_path.into_iter().map(|p| ctx.rust_ident(p)), "::"); + + let def_params = match def.self_template_params(ctx) { Some(params) => params, None => { // 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, &()) + def.is_opaque(ctx, &()) ); return Err(error::Error::InstantiationOfOpaqueType); } }; - // TODO: If the decl type is a template class/struct - // declaration's member template declaration, it could rely on + // TODO: If the definition type is a template class/struct + // definition's member template definition, it could rely on // generic template parameters from its outer template // class/struct. When we emit bindings for it, it could require // *more* type arguments than we have here, and we will need to // reconstruct them somehow. We don't have any means of doing // that reconstruction at this time. - if let ast::TyKind::Path(_, ref mut path) = ty.node { - let template_args = self.template_arguments() - .iter() - .zip(decl_params.iter()) - // Only pass type arguments for the type parameters that - // the decl uses. - .filter(|&(_, param)| ctx.uses_template_parameter(decl, *param)) - .map(|(arg, _)| arg.try_to_rust_ty(ctx, &())) - .collect::<error::Result<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![], - }, - ))) - } + let template_args = self.template_arguments() + .iter() + .zip(def_params.iter()) + // Only pass type arguments for the type parameters that + // the def uses. + .filter(|&(_, param)| ctx.uses_template_parameter(def.id(), *param)) + .map(|(arg, _)| { + let arg = arg.into_resolver().through_type_refs().resolve(ctx); + let mut ty = arg.try_to_rust_ty(ctx, &())?; + ty.append_implicit_template_params(ctx, arg); + Ok(ty) + }) + .collect::<error::Result<Vec<_>>>()?; + + if template_args.is_empty() { + return Ok(ty); } - Ok(P(ty)) + Ok(quote! { + #ty < #( #template_args ),* > + }) } } impl TryToRustTy for FunctionSig { - type Extra = Item; + type Extra = (); fn try_to_rust_ty( &self, ctx: &BindgenContext, - item: &Item, - ) -> error::Result<P<ast::Ty>> { + _: &(), + ) -> error::Result<quote::Tokens> { // 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); + let abi = self.abi(); - let decl = P(ast::FnDecl { - inputs: arguments, - output: ret, - variadic: self.is_variadic(), - }); - - 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 - ); - } - }; - - let fnty = ast::TyKind::BareFn(P(ast::BareFnTy { - unsafety: ast::Unsafety::Unsafe, - abi: abi, - lifetimes: vec![], - decl: decl, - })); - - Ok(P(ast::Ty { - id: ast::DUMMY_NODE_ID, - node: fnty, - span: ctx.span(), - })) + Ok(quote! { + unsafe extern #abi fn ( #( #arguments ),* ) #ret + }) } } @@ -3270,7 +3112,8 @@ impl CodeGenerator for Function { _ => panic!("Signature kind is not a Function: {:?}", signature), }; - let fndecl = utils::rust_fndecl_from_signature(ctx, signature_item); + let args = utils::fnsig_arguments(ctx, signature); + let ret = utils::fnsig_return_ty(ctx, signature); let mut attributes = vec![]; @@ -3284,9 +3127,6 @@ impl CodeGenerator for Function { attributes.push(attributes::link_name(name)); } - let foreign_item_kind = - ast::ForeignItemKind::Fn(fndecl, ast::Generics::default()); - // Handle overloaded functions by giving each overload its own unique // suffix. let times_seen = result.overload_number(&canonical_name); @@ -3294,17 +3134,7 @@ impl CodeGenerator for Function { write!(&mut canonical_name, "{}", times_seen).unwrap(); } - let foreign_item = ast::ForeignItem { - ident: ctx.rust_ident_raw(&canonical_name), - attrs: attributes, - node: foreign_item_kind, - id: ast::DUMMY_NODE_ID, - span: ctx.span(), - vis: ast::Visibility::Public, - }; - let abi = match signature.abi() { - Abi::Known(abi) => abi, Abi::Unknown(unknown_abi) => { panic!( "Invalid or unknown abi {:?} for function {:?} ({:?})", @@ -3313,13 +3143,29 @@ impl CodeGenerator for Function { self ); } + abi => abi, }; - let item = ForeignModBuilder::new(abi) - .with_foreign_item(foreign_item) - .build(ctx); + let variadic = if signature.is_variadic() { + quote! { ... } + } else { + quote! {} + }; - result.push(item); + let ident = ctx.rust_ident(canonical_name); + let mut tokens = quote! { extern #abi }; + tokens.append("{\n"); + if !attributes.is_empty() { + tokens.append_separated(attributes, "\n"); + tokens.append("\n"); + } + let mut args = args; + args.push(variadic); + tokens.append(quote! { + pub fn #ident ( #( #args ),* ) #ret; + }); + tokens.append("\n}"); + result.push(tokens); } } @@ -3329,86 +3175,53 @@ fn objc_method_codegen( method: &ObjCMethod, class_name: Option<&str>, prefix: &str, -) -> (ast::ImplItem, ast::TraitItem) { +) -> (quote::Tokens, quote::Tokens) { let signature = method.signature(); let fn_args = utils::fnsig_arguments(ctx, signature); let fn_ret = utils::fnsig_return_ty(ctx, signature); let sig = if method.is_class_method() { - aster::AstBuilder::new() - .method_sig() - .unsafe_() - .fn_decl() - .with_args(fn_args.clone()) - .build(fn_ret) + let fn_args = fn_args.clone(); + quote! { + ( #( #fn_args ),* ) #fn_ret + } } else { - aster::AstBuilder::new() - .method_sig() - .unsafe_() - .fn_decl() - .self_() - .build(ast::SelfKind::Value(ast::Mutability::Immutable)) - .with_args(fn_args.clone()) - .build(fn_ret) + let fn_args = fn_args.clone(); + let args = iter::once(quote! { self }) + .chain(fn_args.into_iter()); + quote! { + ( #( #args ),* ) #fn_ret + } }; - // Collect the actual used argument names - 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() - } - _ => { - panic!("odd argument!"); - } - }) - .collect(); - - let methods_and_args = - ctx.rust_ident(&method.format_method_call(&arg_names)); + let methods_and_args = method.format_method_call(&fn_args); let body = if method.is_class_method() { 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]) - .unwrap() + quote! { + msg_send!(objc::runtime::Class::get(#class_name).expect(#expect_msg), #methods_and_args) + } } else { - quote_stmt!(ctx.ext_cx(), msg_send![self, $methods_and_args]).unwrap() - }; - let block = ast::Block { - stmts: vec![body], - id: ast::DUMMY_NODE_ID, - rules: ast::BlockCheckMode::Default, - span: ctx.span(), - }; - - let attrs = vec![]; - - let method_name = format!("{}{}", prefix, method.rust_name()); - - let impl_item = ast::ImplItem { - id: ast::DUMMY_NODE_ID, - ident: ctx.rust_ident(&method_name), - vis: ast::Visibility::Inherited, // Public, - attrs: attrs.clone(), - node: ast::ImplItemKind::Method(sig.clone(), P(block)), - defaultness: ast::Defaultness::Final, - span: ctx.span(), + quote! { + msg_send!(self, #methods_and_args) + } }; - let trait_item = ast::TraitItem { - id: ast::DUMMY_NODE_ID, - ident: ctx.rust_ident(&method_name), - attrs: attrs, - node: ast::TraitItemKind::Method(sig, None), - span: ctx.span(), - }; + let method_name = ctx.rust_ident(format!("{}{}", prefix, method.rust_name())); - (impl_item, trait_item) + ( + quote! { + unsafe fn #method_name #sig { + #body + } + }, + quote! { + unsafe fn #method_name #sig ; + } + ) } impl CodeGenerator for ObjCInterface { @@ -3440,7 +3253,6 @@ impl CodeGenerator for ObjCInterface { .collect(); for class_method in self.class_methods() { - let ambiquity = instance_method_names.contains(&class_method.rust_name()); let prefix = if ambiquity { "class_" } else { "" }; @@ -3454,24 +3266,22 @@ impl CodeGenerator for ObjCInterface { trait_items.push(trait_item) } - let trait_name = self.rust_name(); + let trait_name = ctx.rust_ident(self.rust_name()); - let trait_block = aster::AstBuilder::new() - .item() - .pub_() - .trait_(&trait_name) - .with_items(trait_items) - .build(); + let trait_block = quote! { + pub trait #trait_name { + #( #trait_items )* + } + }; - let ty_for_impl = quote_ty!(ctx.ext_cx(), id); - let impl_block = aster::AstBuilder::new() - .item() - .impl_() - .trait_() - .id(&trait_name) - .build() - .with_items(impl_items) - .build_ty(ty_for_impl); + let ty_for_impl = quote! { + id + }; + let impl_block = quote! { + impl #trait_name for #ty_for_impl { + #( #impl_items )* + } + }; result.push(trait_block); result.push(impl_block); @@ -3479,7 +3289,7 @@ impl CodeGenerator for ObjCInterface { } } -pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> { +pub fn codegen(context: &mut BindgenContext) -> Vec<quote::Tokens> { context.gen(|context| { let _t = context.timer("codegen"); let counter = Cell::new(0); @@ -3511,35 +3321,32 @@ pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> { mod utils { use super::{ToRustTyOrOpaque, TryToRustTy, error}; - use aster; use ir::context::{BindgenContext, ItemId}; use ir::function::FunctionSig; use ir::item::{Item, ItemCanonicalPath}; use ir::ty::TypeKind; + use quote; use std::mem; - use syntax::ast; - use syntax::ptr::P; pub fn prepend_objc_header( ctx: &BindgenContext, - result: &mut Vec<P<ast::Item>>, + result: &mut Vec<quote::Tokens>, ) { let use_objc = if ctx.options().objc_extern_crate { - quote_item!(ctx.ext_cx(), + quote! { #[macro_use] extern crate objc; - ).unwrap() + } } else { - quote_item!(ctx.ext_cx(), + quote! { use objc; - ).unwrap() + } }; - - let id_type = quote_item!(ctx.ext_cx(), + let id_type = quote! { #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; - ).unwrap(); + }; let items = vec![use_objc, id_type]; let old_items = mem::replace(result, items); @@ -3548,90 +3355,88 @@ mod utils { pub fn prepend_union_types( ctx: &BindgenContext, - result: &mut Vec<P<ast::Item>>, + result: &mut Vec<quote::Tokens>, ) { let prefix = ctx.trait_prefix(); // TODO(emilio): The fmt::Debug impl could be way nicer with // std::intrinsics::type_name, but... - let union_field_decl = quote_item!(ctx.ext_cx(), + let union_field_decl = quote! { #[repr(C)] - pub struct __BindgenUnionField<T>( - ::$prefix::marker::PhantomData<T>); - ).unwrap(); + pub struct __BindgenUnionField<T>(::#prefix::marker::PhantomData<T>); + }; - let union_field_impl = quote_item!(&ctx.ext_cx(), + let union_field_impl = quote! { impl<T> __BindgenUnionField<T> { #[inline] pub fn new() -> Self { - __BindgenUnionField(::$prefix::marker::PhantomData) + __BindgenUnionField(::#prefix::marker::PhantomData) } #[inline] pub unsafe fn as_ref(&self) -> &T { - ::$prefix::mem::transmute(self) + ::#prefix::mem::transmute(self) } #[inline] pub unsafe fn as_mut(&mut self) -> &mut T { - ::$prefix::mem::transmute(self) + ::#prefix::mem::transmute(self) } } - ).unwrap(); + }; - let union_field_default_impl = quote_item!(&ctx.ext_cx(), - impl<T> ::$prefix::default::Default for __BindgenUnionField<T> { + let union_field_default_impl = quote! { + impl<T> ::#prefix::default::Default for __BindgenUnionField<T> { #[inline] fn default() -> Self { Self::new() } } - ).unwrap(); + }; - let union_field_clone_impl = quote_item!(&ctx.ext_cx(), - impl<T> ::$prefix::clone::Clone for __BindgenUnionField<T> { + let union_field_clone_impl = quote! { + impl<T> ::#prefix::clone::Clone for __BindgenUnionField<T> { #[inline] fn clone(&self) -> Self { Self::new() } } - ).unwrap(); + }; - let union_field_copy_impl = quote_item!(&ctx.ext_cx(), - impl<T> ::$prefix::marker::Copy for __BindgenUnionField<T> {} - ).unwrap(); + let union_field_copy_impl = quote! { + impl<T> ::#prefix::marker::Copy for __BindgenUnionField<T> {} + }; - let union_field_debug_impl = quote_item!(ctx.ext_cx(), - impl<T> ::$prefix::fmt::Debug for __BindgenUnionField<T> { - fn fmt(&self, fmt: &mut ::$prefix::fmt::Formatter) - -> ::$prefix::fmt::Result { + let union_field_debug_impl = quote! { + impl<T> ::#prefix::fmt::Debug for __BindgenUnionField<T> { + fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter) + -> ::#prefix::fmt::Result { fmt.write_str("__BindgenUnionField") } } - ).unwrap(); + }; // The actual memory of the filed will be hashed, so that's why these // field doesn't do anything with the hash. - let union_field_hash_impl = quote_item!(&ctx.ext_cx(), - impl<T> ::$prefix::hash::Hash for __BindgenUnionField<T> { - fn hash<H: ::$prefix::hash::Hasher>(&self, _state: &mut H) { + let union_field_hash_impl = quote! { + impl<T> ::#prefix::hash::Hash for __BindgenUnionField<T> { + fn hash<H: ::#prefix::hash::Hasher>(&self, _state: &mut H) { } } - ).unwrap(); + }; - let union_field_partialeq_impl = quote_item!(&ctx.ext_cx(), - impl<T> ::$prefix::cmp::PartialEq for __BindgenUnionField<T> { + let union_field_partialeq_impl = quote! { + impl<T> ::#prefix::cmp::PartialEq for __BindgenUnionField<T> { fn eq(&self, _other: &__BindgenUnionField<T>) -> bool { true } } - ).unwrap(); + }; - let union_field_eq_impl = quote_item!(&ctx.ext_cx(), - impl<T> ::$prefix::cmp::Eq for __BindgenUnionField<T> { + let union_field_eq_impl = quote! { + impl<T> ::#prefix::cmp::Eq for __BindgenUnionField<T> { } - ) - .unwrap(); + }; let items = vec![union_field_decl, union_field_impl, @@ -3649,67 +3454,67 @@ mod utils { pub fn prepend_incomplete_array_types( ctx: &BindgenContext, - result: &mut Vec<P<ast::Item>>, + result: &mut Vec<quote::Tokens>, ) { let prefix = ctx.trait_prefix(); - let incomplete_array_decl = quote_item!(ctx.ext_cx(), + let incomplete_array_decl = quote! { #[repr(C)] #[derive(Default)] pub struct __IncompleteArrayField<T>( - ::$prefix::marker::PhantomData<T>); - ).unwrap(); + ::#prefix::marker::PhantomData<T>); + }; - let incomplete_array_impl = quote_item!(&ctx.ext_cx(), + let incomplete_array_impl = quote! { impl<T> __IncompleteArrayField<T> { #[inline] pub fn new() -> Self { - __IncompleteArrayField(::$prefix::marker::PhantomData) + __IncompleteArrayField(::#prefix::marker::PhantomData) } #[inline] pub unsafe fn as_ptr(&self) -> *const T { - ::$prefix::mem::transmute(self) + ::#prefix::mem::transmute(self) } #[inline] pub unsafe fn as_mut_ptr(&mut self) -> *mut T { - ::$prefix::mem::transmute(self) + ::#prefix::mem::transmute(self) } #[inline] pub unsafe fn as_slice(&self, len: usize) -> &[T] { - ::$prefix::slice::from_raw_parts(self.as_ptr(), len) + ::#prefix::slice::from_raw_parts(self.as_ptr(), len) } #[inline] pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { - ::$prefix::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + ::#prefix::slice::from_raw_parts_mut(self.as_mut_ptr(), len) } } - ).unwrap(); + }; - let incomplete_array_debug_impl = quote_item!(ctx.ext_cx(), - impl<T> ::$prefix::fmt::Debug for __IncompleteArrayField<T> { - fn fmt(&self, fmt: &mut ::$prefix::fmt::Formatter) - -> ::$prefix::fmt::Result { + let incomplete_array_debug_impl = quote! { + impl<T> ::#prefix::fmt::Debug for __IncompleteArrayField<T> { + fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter) + -> ::#prefix::fmt::Result { fmt.write_str("__IncompleteArrayField") } } - ).unwrap(); + }; - let incomplete_array_clone_impl = quote_item!(&ctx.ext_cx(), - impl<T> ::$prefix::clone::Clone for __IncompleteArrayField<T> { + let incomplete_array_clone_impl = quote! { + impl<T> ::#prefix::clone::Clone for __IncompleteArrayField<T> { #[inline] fn clone(&self) -> Self { Self::new() } } - ).unwrap(); + }; - let incomplete_array_copy_impl = quote_item!(&ctx.ext_cx(), - impl<T> ::$prefix::marker::Copy for __IncompleteArrayField<T> {} - ).unwrap(); + let incomplete_array_copy_impl = quote! { + impl<T> ::#prefix::marker::Copy for __IncompleteArrayField<T> {} + }; let items = vec![incomplete_array_decl, incomplete_array_impl, @@ -3722,17 +3527,16 @@ mod utils { } pub fn prepend_complex_type( - ctx: &BindgenContext, - result: &mut Vec<P<ast::Item>>, + result: &mut Vec<quote::Tokens>, ) { - let complex_type = quote_item!(ctx.ext_cx(), + let complex_type = quote! { #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)] #[repr(C)] pub struct __BindgenComplex<T> { pub re: T, pub im: T } - ).unwrap(); + }; let items = vec![complex_type]; let old_items = mem::replace(result, items); @@ -3743,53 +3547,38 @@ mod utils { item: &Item, ctx: &BindgenContext, template_params: Vec<ItemId>, - ) -> error::Result<P<ast::Ty>> { + ) -> error::Result<quote::Tokens> { let path = item.namespace_aware_canonical_path(ctx); - let builder = aster::AstBuilder::new().ty().path(); let template_params = template_params .iter() .map(|param| param.try_to_rust_ty(ctx, &())) .collect::<error::Result<Vec<_>>>()?; - // XXX: I suck at aster. - if path.len() == 1 { - return Ok( - builder - .segment(&path[0]) - .with_tys(template_params) - .build() - .build(), - ); - } + let mut tokens = quote! {}; + tokens.append_separated(path.into_iter().map(quote::Ident::new), "::"); - let mut builder = builder.id(&path[0]); - for (i, segment) in path.iter().skip(1).enumerate() { - // Take into account the skip(1) - builder = if i == path.len() - 2 { - // XXX Extra clone courtesy of the borrow checker. - builder - .segment(&segment) - .with_tys(template_params.clone()) - .build() - } else { - builder.segment(&segment).build() - } + if template_params.is_empty() { + Ok(tokens) + } else { + Ok(quote! { + #tokens < #( #template_params ),* > + }) } - - Ok(builder.build()) } - fn primitive_ty(ctx: &BindgenContext, name: &str) -> P<ast::Ty> { - let ident = ctx.rust_ident_raw(&name); - quote_ty!(ctx.ext_cx(), $ident) + fn primitive_ty(ctx: &BindgenContext, name: &str) -> quote::Tokens { + let ident = ctx.rust_ident_raw(name); + quote! { + #ident + } } pub fn type_from_named( ctx: &BindgenContext, name: &str, _inner: ItemId, - ) -> Option<P<ast::Ty>> { + ) -> Option<quote::Tokens> { // 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 { @@ -3809,42 +3598,27 @@ mod utils { }) } - pub fn rust_fndecl_from_signature( - ctx: &BindgenContext, - sig: &Item, - ) -> P<ast::FnDecl> { - 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).expect( - "function signature to Rust type conversion is infallible", - ); - match decl_ty.unwrap().node { - ast::TyKind::BareFn(bare_fn) => bare_fn.unwrap().decl, - _ => panic!("How did this happen exactly?"), - } - } - pub fn fnsig_return_ty( ctx: &BindgenContext, sig: &FunctionSig, - ) -> ast::FunctionRetTy { + ) -> quote::Tokens { let return_item = ctx.resolve_item(sig.return_type()); if let TypeKind::Void = *return_item.kind().expect_type().kind() { - ast::FunctionRetTy::Default(ctx.span()) + quote! { } } else { - ast::FunctionRetTy::Ty(return_item.to_rust_ty_or_opaque(ctx, &())) + let ret_ty = return_item.to_rust_ty_or_opaque(ctx, &()); + quote! { + -> #ret_ty + } } } pub fn fnsig_arguments( ctx: &BindgenContext, sig: &FunctionSig, - ) -> Vec<ast::Arg> { + ) -> Vec<quote::Tokens> { use super::ToPtr; + let mut unnamed_arguments = 0; sig.argument_types().iter().map(|&(ref name, ty)| { let arg_item = ctx.resolve_item(ty); @@ -3861,13 +3635,15 @@ mod utils { let arg_ty = match *arg_ty.canonical_type(ctx).kind() { TypeKind::Array(t, _) => { t.to_rust_ty_or_opaque(ctx, &()) - .to_ptr(ctx.resolve_type(t).is_const(), ctx.span()) + .to_ptr(ctx.resolve_type(t).is_const()) }, TypeKind::Pointer(inner) => { let inner = ctx.resolve_item(inner); let inner_ty = inner.expect_type(); if let TypeKind::ObjCInterface(_) = *inner_ty.canonical_type(ctx).kind() { - quote_ty!(ctx.ext_cx(), id) + quote! { + id + } } else { arg_item.to_rust_ty_or_opaque(ctx, &()) } @@ -3886,12 +3662,11 @@ mod utils { }; assert!(!arg_name.is_empty()); + let arg_name = ctx.rust_ident(arg_name); - ast::Arg { - ty: arg_ty, - pat: aster::AstBuilder::new().pat().id(arg_name), - id: ast::DUMMY_NODE_ID, + quote! { + #arg_name : #arg_ty } - }).collect::<Vec<_>>() + }).collect() } } diff --git a/src/codegen/struct_layout.rs b/src/codegen/struct_layout.rs index 956a1f44..06059853 100644 --- a/src/codegen/struct_layout.rs +++ b/src/codegen/struct_layout.rs @@ -2,22 +2,19 @@ use super::helpers; -use aster::struct_field::StructFieldBuilder; - use ir::comp::CompInfo; use ir::context::BindgenContext; use ir::layout::Layout; use ir::ty::{Type, TypeKind}; +use quote; use std::cmp; use std::mem; -use syntax::ast; - /// Trace the layout of struct. #[derive(Debug)] -pub struct StructLayoutTracker<'a, 'ctx: 'a> { +pub struct StructLayoutTracker<'a> { name: &'a str, - ctx: &'a BindgenContext<'ctx>, + ctx: &'a BindgenContext, comp: &'a CompInfo, latest_offset: usize, padding_count: usize, @@ -80,9 +77,9 @@ fn test_bytes_from_bits_pow2() { } } -impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> { +impl<'a> StructLayoutTracker<'a> { pub fn new( - ctx: &'a BindgenContext<'ctx>, + ctx: &'a BindgenContext, comp: &'a CompInfo, name: &'a str, ) -> Self { @@ -154,7 +151,7 @@ impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> { field_name: &str, field_ty: &Type, field_offset: Option<usize>, - ) -> Option<ast::StructField> { + ) -> Option<quote::Tokens> { let mut field_layout = match field_ty.layout(self.ctx) { Some(l) => l, None => return None, @@ -241,7 +238,7 @@ impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> { padding_layout.map(|layout| self.padding_field(layout)) } - pub fn pad_struct(&mut self, layout: Layout) -> Option<ast::StructField> { + pub fn pad_struct(&mut self, layout: Layout) -> Option<quote::Tokens> { debug!( "pad_struct:\n\tself = {:#?}\n\tlayout = {:#?}", self, @@ -291,17 +288,15 @@ impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> { } } - pub fn align_struct(&self, layout: Layout) -> Option<ast::StructField> { + pub fn align_struct(&self, layout: Layout) -> Option<quote::Tokens> { if self.max_field_align < layout.align && layout.align <= mem::size_of::<*mut ()>() { let ty = helpers::blob(Layout::new(0, layout.align)); - Some( - StructFieldBuilder::named("__bindgen_align") - .pub_() - .build_ty(ty), - ) + Some(quote! { + pub __bindgen_align: #ty , + }) } else { None } @@ -311,19 +306,19 @@ impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> { align_to(self.latest_offset, layout.align) - self.latest_offset } - fn padding_field(&mut self, layout: Layout) -> ast::StructField { + fn padding_field(&mut self, layout: Layout) -> quote::Tokens { let ty = helpers::blob(layout); let padding_count = self.padding_count; self.padding_count += 1; - let padding_field_name = format!("__bindgen_padding_{}", padding_count); + let padding_field_name = quote::Ident::new(format!("__bindgen_padding_{}", padding_count)); self.max_field_align = cmp::max(self.max_field_align, layout.align); - StructFieldBuilder::named(padding_field_name) - .pub_() - .build_ty(ty) + quote! { + pub #padding_field_name : #ty , + } } /// Returns whether the new field is known to merge with a bitfield. diff --git a/src/ir/analysis/derive_copy.rs b/src/ir/analysis/derive_copy.rs index 1890dcec..ef01c65a 100644 --- a/src/ir/analysis/derive_copy.rs +++ b/src/ir/analysis/derive_copy.rs @@ -31,11 +31,8 @@ use std::collections::HashSet; /// derived copy if any of the template arguments or template definition /// cannot derive copy. #[derive(Debug, Clone)] -pub struct CannotDeriveCopy<'ctx, 'gen> -where - 'gen: 'ctx, -{ - ctx: &'ctx BindgenContext<'gen>, +pub struct CannotDeriveCopy<'ctx> { + ctx: &'ctx BindgenContext, // The incremental result of this analysis's computation. Everything in this // set cannot derive copy. @@ -51,7 +48,7 @@ where dependencies: HashMap<ItemId, Vec<ItemId>>, } -impl<'ctx, 'gen> CannotDeriveCopy<'ctx, 'gen> { +impl<'ctx> CannotDeriveCopy<'ctx> { fn consider_edge(kind: EdgeKind) -> bool { match kind { // These are the only edges that can affect whether a type can derive @@ -97,12 +94,12 @@ impl<'ctx, 'gen> CannotDeriveCopy<'ctx, 'gen> { } } -impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> { +impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> { type Node = ItemId; - type Extra = &'ctx BindgenContext<'gen>; + type Extra = &'ctx BindgenContext; type Output = HashSet<ItemId>; - fn new(ctx: &'ctx BindgenContext<'gen>) -> CannotDeriveCopy<'ctx, 'gen> { + fn new(ctx: &'ctx BindgenContext) -> CannotDeriveCopy<'ctx> { let cannot_derive_copy = HashSet::new(); let dependencies = generate_dependencies(ctx, Self::consider_edge); @@ -336,8 +333,8 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveCopy<'ctx, 'gen> { } } -impl<'ctx, 'gen> From<CannotDeriveCopy<'ctx, 'gen>> for HashSet<ItemId> { - fn from(analysis: CannotDeriveCopy<'ctx, 'gen>) -> Self { +impl<'ctx> From<CannotDeriveCopy<'ctx>> for HashSet<ItemId> { + fn from(analysis: CannotDeriveCopy<'ctx>) -> Self { analysis.cannot_derive_copy } } diff --git a/src/ir/analysis/derive_debug.rs b/src/ir/analysis/derive_debug.rs index b7a35132..2bfaff71 100644 --- a/src/ir/analysis/derive_debug.rs +++ b/src/ir/analysis/derive_debug.rs @@ -33,11 +33,8 @@ use std::collections::HashSet; /// derived debug if any of the template arguments or template definition /// cannot derive debug. #[derive(Debug, Clone)] -pub struct CannotDeriveDebug<'ctx, 'gen> -where - 'gen: 'ctx, -{ - ctx: &'ctx BindgenContext<'gen>, +pub struct CannotDeriveDebug<'ctx> { + ctx: &'ctx BindgenContext, // The incremental result of this analysis's computation. Everything in this // set cannot derive debug. @@ -53,7 +50,7 @@ where dependencies: HashMap<ItemId, Vec<ItemId>>, } -impl<'ctx, 'gen> CannotDeriveDebug<'ctx, 'gen> { +impl<'ctx> CannotDeriveDebug<'ctx> { fn consider_edge(kind: EdgeKind) -> bool { match kind { // These are the only edges that can affect whether a type can derive @@ -99,12 +96,12 @@ impl<'ctx, 'gen> CannotDeriveDebug<'ctx, 'gen> { } } -impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> { +impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> { type Node = ItemId; - type Extra = &'ctx BindgenContext<'gen>; + type Extra = &'ctx BindgenContext; type Output = HashSet<ItemId>; - fn new(ctx: &'ctx BindgenContext<'gen>) -> CannotDeriveDebug<'ctx, 'gen> { + fn new(ctx: &'ctx BindgenContext) -> CannotDeriveDebug<'ctx> { let cannot_derive_debug = HashSet::new(); let dependencies = generate_dependencies(ctx, Self::consider_edge); @@ -355,8 +352,8 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> { } } -impl<'ctx, 'gen> From<CannotDeriveDebug<'ctx, 'gen>> for HashSet<ItemId> { - fn from(analysis: CannotDeriveDebug<'ctx, 'gen>) -> Self { +impl<'ctx> From<CannotDeriveDebug<'ctx>> for HashSet<ItemId> { + fn from(analysis: CannotDeriveDebug<'ctx>) -> Self { analysis.cannot_derive_debug } } diff --git a/src/ir/analysis/derive_default.rs b/src/ir/analysis/derive_default.rs index 19f4a842..96805863 100644 --- a/src/ir/analysis/derive_default.rs +++ b/src/ir/analysis/derive_default.rs @@ -30,11 +30,8 @@ use std::collections::HashSet; /// * If T is a compound type, default cannot be derived if any of its base member /// or field cannot be derived default. #[derive(Debug, Clone)] -pub struct CannotDeriveDefault<'ctx, 'gen> -where - 'gen: 'ctx, -{ - ctx: &'ctx BindgenContext<'gen>, +pub struct CannotDeriveDefault<'ctx> { + ctx: &'ctx BindgenContext, // The incremental result of this analysis's computation. Everything in this // set cannot derive default. @@ -50,7 +47,7 @@ where dependencies: HashMap<ItemId, Vec<ItemId>>, } -impl<'ctx, 'gen> CannotDeriveDefault<'ctx, 'gen> { +impl<'ctx> CannotDeriveDefault<'ctx> { fn consider_edge(kind: EdgeKind) -> bool { match kind { // These are the only edges that can affect whether a type can derive @@ -94,12 +91,12 @@ impl<'ctx, 'gen> CannotDeriveDefault<'ctx, 'gen> { } } -impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDefault<'ctx, 'gen> { +impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> { type Node = ItemId; - type Extra = &'ctx BindgenContext<'gen>; + type Extra = &'ctx BindgenContext; type Output = HashSet<ItemId>; - fn new(ctx: &'ctx BindgenContext<'gen>) -> CannotDeriveDefault<'ctx, 'gen> { + fn new(ctx: &'ctx BindgenContext) -> CannotDeriveDefault<'ctx> { let mut dependencies = HashMap::new(); let cannot_derive_default = HashSet::new(); @@ -388,8 +385,8 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDefault<'ctx, 'gen> { } } -impl<'ctx, 'gen> From<CannotDeriveDefault<'ctx, 'gen>> for HashSet<ItemId> { - fn from(analysis: CannotDeriveDefault<'ctx, 'gen>) -> Self { +impl<'ctx> From<CannotDeriveDefault<'ctx>> for HashSet<ItemId> { + fn from(analysis: CannotDeriveDefault<'ctx>) -> Self { analysis.cannot_derive_default } } diff --git a/src/ir/analysis/derive_hash.rs b/src/ir/analysis/derive_hash.rs index ee9cb23a..80ea0abf 100644 --- a/src/ir/analysis/derive_hash.rs +++ b/src/ir/analysis/derive_hash.rs @@ -33,11 +33,8 @@ use std::collections::HashSet; /// derived hash if any of the template arguments or template definition /// cannot derive hash. #[derive(Debug, Clone)] -pub struct CannotDeriveHash<'ctx, 'gen> -where - 'gen: 'ctx, -{ - ctx: &'ctx BindgenContext<'gen>, +pub struct CannotDeriveHash<'ctx> { + ctx: &'ctx BindgenContext, // The incremental result of this analysis's computation. Everything in this // set cannot derive hash. @@ -53,7 +50,7 @@ where dependencies: HashMap<ItemId, Vec<ItemId>>, } -impl<'ctx, 'gen> CannotDeriveHash<'ctx, 'gen> { +impl<'ctx> CannotDeriveHash<'ctx> { fn consider_edge(kind: EdgeKind) -> bool { match kind { // These are the only edges that can affect whether a type can derive @@ -92,12 +89,12 @@ impl<'ctx, 'gen> CannotDeriveHash<'ctx, 'gen> { } } -impl<'ctx, 'gen> MonotoneFramework for CannotDeriveHash<'ctx, 'gen> { +impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> { type Node = ItemId; - type Extra = &'ctx BindgenContext<'gen>; + type Extra = &'ctx BindgenContext; type Output = HashSet<ItemId>; - fn new(ctx: &'ctx BindgenContext<'gen>) -> CannotDeriveHash<'ctx, 'gen> { + fn new(ctx: &'ctx BindgenContext) -> CannotDeriveHash<'ctx> { let cannot_derive_hash = HashSet::new(); let dependencies = generate_dependencies(ctx, Self::consider_edge); @@ -356,8 +353,8 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDeriveHash<'ctx, 'gen> { } } -impl<'ctx, 'gen> From<CannotDeriveHash<'ctx, 'gen>> for HashSet<ItemId> { - fn from(analysis: CannotDeriveHash<'ctx, 'gen>) -> Self { +impl<'ctx> From<CannotDeriveHash<'ctx>> for HashSet<ItemId> { + fn from(analysis: CannotDeriveHash<'ctx>) -> Self { analysis.cannot_derive_hash } } diff --git a/src/ir/analysis/derive_partial_eq.rs b/src/ir/analysis/derive_partial_eq.rs index 45ba67a5..96689601 100644 --- a/src/ir/analysis/derive_partial_eq.rs +++ b/src/ir/analysis/derive_partial_eq.rs @@ -33,11 +33,8 @@ use std::collections::HashSet; /// derived partialeq if any of the template arguments or template definition /// cannot derive partialeq. #[derive(Debug, Clone)] -pub struct CannotDerivePartialEq<'ctx, 'gen> -where - 'gen: 'ctx, -{ - ctx: &'ctx BindgenContext<'gen>, +pub struct CannotDerivePartialEq<'ctx> { + ctx: &'ctx BindgenContext, // The incremental result of this analysis's computation. Everything in this // set cannot derive partialeq. @@ -53,7 +50,7 @@ where dependencies: HashMap<ItemId, Vec<ItemId>>, } -impl<'ctx, 'gen> CannotDerivePartialEq<'ctx, 'gen> { +impl<'ctx> CannotDerivePartialEq<'ctx> { fn consider_edge(kind: EdgeKind) -> bool { match kind { // These are the only edges that can affect whether a type can derive @@ -92,14 +89,14 @@ impl<'ctx, 'gen> CannotDerivePartialEq<'ctx, 'gen> { } } -impl<'ctx, 'gen> MonotoneFramework for CannotDerivePartialEq<'ctx, 'gen> { +impl<'ctx> MonotoneFramework for CannotDerivePartialEq<'ctx> { type Node = ItemId; - type Extra = &'ctx BindgenContext<'gen>; + type Extra = &'ctx BindgenContext; type Output = HashSet<ItemId>; fn new( - ctx: &'ctx BindgenContext<'gen>, - ) -> CannotDerivePartialEq<'ctx, 'gen> { + ctx: &'ctx BindgenContext, + ) -> CannotDerivePartialEq<'ctx> { let cannot_derive_partialeq = HashSet::new(); let dependencies = generate_dependencies(ctx, Self::consider_edge); @@ -365,8 +362,8 @@ impl<'ctx, 'gen> MonotoneFramework for CannotDerivePartialEq<'ctx, 'gen> { } } -impl<'ctx, 'gen> From<CannotDerivePartialEq<'ctx, 'gen>> for HashSet<ItemId> { - fn from(analysis: CannotDerivePartialEq<'ctx, 'gen>) -> Self { +impl<'ctx> From<CannotDerivePartialEq<'ctx>> for HashSet<ItemId> { + fn from(analysis: CannotDerivePartialEq<'ctx>) -> Self { analysis.cannot_derive_partialeq } } diff --git a/src/ir/analysis/has_destructor.rs b/src/ir/analysis/has_destructor.rs index b37dbaaa..f6400d7d 100644 --- a/src/ir/analysis/has_destructor.rs +++ b/src/ir/analysis/has_destructor.rs @@ -23,11 +23,8 @@ use std::collections::HashSet; /// * If T is the type of a field, that field has a destructor if it's not a bitfield, /// and if T has a destructor. #[derive(Debug, Clone)] -pub struct HasDestructorAnalysis<'ctx, 'gen> -where - 'gen: 'ctx, -{ - ctx: &'ctx BindgenContext<'gen>, +pub struct HasDestructorAnalysis<'ctx> { + ctx: &'ctx BindgenContext, // The incremental result of this analysis's computation. Everything in this // set definitely has a destructor. @@ -43,7 +40,7 @@ where dependencies: HashMap<ItemId, Vec<ItemId>>, } -impl<'ctx, 'gen> HasDestructorAnalysis<'ctx, 'gen> { +impl<'ctx> HasDestructorAnalysis<'ctx> { fn consider_edge(kind: EdgeKind) -> bool { match kind { // These are the only edges that can affect whether a type has a @@ -69,12 +66,12 @@ impl<'ctx, 'gen> HasDestructorAnalysis<'ctx, 'gen> { } } -impl<'ctx, 'gen> MonotoneFramework for HasDestructorAnalysis<'ctx, 'gen> { +impl<'ctx> MonotoneFramework for HasDestructorAnalysis<'ctx> { type Node = ItemId; - type Extra = &'ctx BindgenContext<'gen>; + type Extra = &'ctx BindgenContext; type Output = HashSet<ItemId>; - fn new(ctx: &'ctx BindgenContext<'gen>) -> Self { + fn new(ctx: &'ctx BindgenContext) -> Self { let have_destructor = HashSet::new(); let dependencies = generate_dependencies(ctx, Self::consider_edge); @@ -172,8 +169,8 @@ impl<'ctx, 'gen> MonotoneFramework for HasDestructorAnalysis<'ctx, 'gen> { } } -impl<'ctx, 'gen> From<HasDestructorAnalysis<'ctx, 'gen>> for HashSet<ItemId> { - fn from(analysis: HasDestructorAnalysis<'ctx, 'gen>) -> Self { +impl<'ctx> From<HasDestructorAnalysis<'ctx>> for HashSet<ItemId> { + fn from(analysis: HasDestructorAnalysis<'ctx>) -> Self { analysis.have_destructor } } diff --git a/src/ir/analysis/has_float.rs b/src/ir/analysis/has_float.rs index 85fe241e..959a411b 100644 --- a/src/ir/analysis/has_float.rs +++ b/src/ir/analysis/has_float.rs @@ -23,10 +23,8 @@ use ir::comp::FieldMethods; /// float if any of the template arguments or template definition /// has. #[derive(Debug, Clone)] -pub struct HasFloat<'ctx, 'gen> - where 'gen: 'ctx -{ - ctx: &'ctx BindgenContext<'gen>, +pub struct HasFloat<'ctx> { + ctx: &'ctx BindgenContext, // The incremental result of this analysis's computation. Everything in this // set has float. @@ -42,7 +40,7 @@ pub struct HasFloat<'ctx, 'gen> dependencies: HashMap<ItemId, Vec<ItemId>>, } -impl<'ctx, 'gen> HasFloat<'ctx, 'gen> { +impl<'ctx> HasFloat<'ctx> { fn consider_edge(kind: EdgeKind) -> bool { match kind { EdgeKind::BaseMember | @@ -79,12 +77,12 @@ impl<'ctx, 'gen> HasFloat<'ctx, 'gen> { } } -impl<'ctx, 'gen> MonotoneFramework for HasFloat<'ctx, 'gen> { +impl<'ctx> MonotoneFramework for HasFloat<'ctx> { type Node = ItemId; - type Extra = &'ctx BindgenContext<'gen>; + type Extra = &'ctx BindgenContext; type Output = HashSet<ItemId>; - fn new(ctx: &'ctx BindgenContext<'gen>) -> HasFloat<'ctx, 'gen> { + fn new(ctx: &'ctx BindgenContext) -> HasFloat<'ctx> { let has_float = HashSet::new(); let dependencies = generate_dependencies(ctx, Self::consider_edge); @@ -232,8 +230,8 @@ impl<'ctx, 'gen> MonotoneFramework for HasFloat<'ctx, 'gen> { } } -impl<'ctx, 'gen> From<HasFloat<'ctx, 'gen>> for HashSet<ItemId> { - fn from(analysis: HasFloat<'ctx, 'gen>) -> Self { +impl<'ctx> From<HasFloat<'ctx>> for HashSet<ItemId> { + fn from(analysis: HasFloat<'ctx>) -> Self { analysis.has_float } } diff --git a/src/ir/analysis/has_type_param_in_array.rs b/src/ir/analysis/has_type_param_in_array.rs index c361e9d9..f21bae14 100644 --- a/src/ir/analysis/has_type_param_in_array.rs +++ b/src/ir/analysis/has_type_param_in_array.rs @@ -23,11 +23,8 @@ use std::collections::HashSet; /// type parameter in array if any of the template arguments or template definition /// has. #[derive(Debug, Clone)] -pub struct HasTypeParameterInArray<'ctx, 'gen> -where - 'gen: 'ctx, -{ - ctx: &'ctx BindgenContext<'gen>, +pub struct HasTypeParameterInArray<'ctx> { + ctx: &'ctx BindgenContext, // The incremental result of this analysis's computation. Everything in this // set has array. @@ -43,7 +40,7 @@ where dependencies: HashMap<ItemId, Vec<ItemId>>, } -impl<'ctx, 'gen> HasTypeParameterInArray<'ctx, 'gen> { +impl<'ctx> HasTypeParameterInArray<'ctx> { fn consider_edge(kind: EdgeKind) -> bool { match kind { // These are the only edges that can affect whether a type has type parameter @@ -86,14 +83,14 @@ impl<'ctx, 'gen> HasTypeParameterInArray<'ctx, 'gen> { } } -impl<'ctx, 'gen> MonotoneFramework for HasTypeParameterInArray<'ctx, 'gen> { +impl<'ctx> MonotoneFramework for HasTypeParameterInArray<'ctx> { type Node = ItemId; - type Extra = &'ctx BindgenContext<'gen>; + type Extra = &'ctx BindgenContext; type Output = HashSet<ItemId>; fn new( - ctx: &'ctx BindgenContext<'gen>, - ) -> HasTypeParameterInArray<'ctx, 'gen> { + ctx: &'ctx BindgenContext, + ) -> HasTypeParameterInArray<'ctx> { let has_type_parameter_in_array = HashSet::new(); let dependencies = generate_dependencies(ctx, Self::consider_edge); @@ -249,8 +246,8 @@ impl<'ctx, 'gen> MonotoneFramework for HasTypeParameterInArray<'ctx, 'gen> { } } -impl<'ctx, 'gen> From<HasTypeParameterInArray<'ctx, 'gen>> for HashSet<ItemId> { - fn from(analysis: HasTypeParameterInArray<'ctx, 'gen>) -> Self { +impl<'ctx> From<HasTypeParameterInArray<'ctx>> for HashSet<ItemId> { + fn from(analysis: HasTypeParameterInArray<'ctx>) -> Self { analysis.has_type_parameter_in_array } } diff --git a/src/ir/analysis/has_vtable.rs b/src/ir/analysis/has_vtable.rs index bb85d0c9..b0d48738 100644 --- a/src/ir/analysis/has_vtable.rs +++ b/src/ir/analysis/has_vtable.rs @@ -18,11 +18,8 @@ use std::collections::HashSet; /// * If T is an instantiation of an abstract template definition, T has /// vtable if template definition has vtable #[derive(Debug, Clone)] -pub struct HasVtableAnalysis<'ctx, 'gen> -where - 'gen: 'ctx, -{ - ctx: &'ctx BindgenContext<'gen>, +pub struct HasVtableAnalysis<'ctx> { + ctx: &'ctx BindgenContext, // The incremental result of this analysis's computation. Everything in this // set definitely has a vtable. @@ -38,7 +35,7 @@ where dependencies: HashMap<ItemId, Vec<ItemId>>, } -impl<'ctx, 'gen> HasVtableAnalysis<'ctx, 'gen> { +impl<'ctx> HasVtableAnalysis<'ctx> { fn consider_edge(kind: EdgeKind) -> bool { match kind { // These are the only edges that can affect whether a type has a @@ -62,12 +59,12 @@ impl<'ctx, 'gen> HasVtableAnalysis<'ctx, 'gen> { } } -impl<'ctx, 'gen> MonotoneFramework for HasVtableAnalysis<'ctx, 'gen> { +impl<'ctx> MonotoneFramework for HasVtableAnalysis<'ctx> { type Node = ItemId; - type Extra = &'ctx BindgenContext<'gen>; + type Extra = &'ctx BindgenContext; type Output = HashSet<ItemId>; - fn new(ctx: &'ctx BindgenContext<'gen>) -> HasVtableAnalysis<'ctx, 'gen> { + fn new(ctx: &'ctx BindgenContext) -> HasVtableAnalysis<'ctx> { let have_vtable = HashSet::new(); let dependencies = generate_dependencies(ctx, Self::consider_edge); @@ -147,8 +144,8 @@ impl<'ctx, 'gen> MonotoneFramework for HasVtableAnalysis<'ctx, 'gen> { } } -impl<'ctx, 'gen> From<HasVtableAnalysis<'ctx, 'gen>> for HashSet<ItemId> { - fn from(analysis: HasVtableAnalysis<'ctx, 'gen>) -> Self { +impl<'ctx> From<HasVtableAnalysis<'ctx>> for HashSet<ItemId> { + fn from(analysis: HasVtableAnalysis<'ctx>) -> Self { analysis.have_vtable } } diff --git a/src/ir/analysis/template_params.rs b/src/ir/analysis/template_params.rs index caaa8f30..7699a0c2 100644 --- a/src/ir/analysis/template_params.rs +++ b/src/ir/analysis/template_params.rs @@ -146,11 +146,8 @@ use std::collections::{HashMap, HashSet}; /// specially; see `constrain_instantiation_of_blacklisted_template` and its /// documentation for details. #[derive(Debug, Clone)] -pub struct UsedTemplateParameters<'ctx, 'gen> -where - 'gen: 'ctx, -{ - ctx: &'ctx BindgenContext<'gen>, +pub struct UsedTemplateParameters<'ctx> { + ctx: &'ctx BindgenContext, // The Option is only there for temporary moves out of the hash map. See the // comments in `UsedTemplateParameters::constrain` below. @@ -164,7 +161,7 @@ where whitelisted_items: HashSet<ItemId>, } -impl<'ctx, 'gen> UsedTemplateParameters<'ctx, 'gen> { +impl<'ctx> UsedTemplateParameters<'ctx> { fn consider_edge(kind: EdgeKind) -> bool { match kind { // For each of these kinds of edges, if the referent uses a template @@ -367,14 +364,14 @@ impl<'ctx, 'gen> UsedTemplateParameters<'ctx, 'gen> { } } -impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> { +impl<'ctx> MonotoneFramework for UsedTemplateParameters<'ctx> { type Node = ItemId; - type Extra = &'ctx BindgenContext<'gen>; + type Extra = &'ctx BindgenContext; type Output = HashMap<ItemId, ItemSet>; fn new( - ctx: &'ctx BindgenContext<'gen>, - ) -> UsedTemplateParameters<'ctx, 'gen> { + ctx: &'ctx BindgenContext, + ) -> UsedTemplateParameters<'ctx> { let mut used = HashMap::new(); let mut dependencies = HashMap::new(); let whitelisted_items: HashSet<_> = @@ -578,9 +575,9 @@ impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> { } } -impl<'ctx, 'gen> From<UsedTemplateParameters<'ctx, 'gen>> +impl<'ctx> From<UsedTemplateParameters<'ctx>> for HashMap<ItemId, ItemSet> { - fn from(used_templ_params: UsedTemplateParameters<'ctx, 'gen>) -> Self { + fn from(used_templ_params: UsedTemplateParameters<'ctx>) -> Self { used_templ_params .used .into_iter() diff --git a/src/ir/context.rs b/src/ir/context.rs index cfbb3766..af1e95e9 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -22,16 +22,13 @@ use cexpr; use clang::{self, Cursor}; use clang_sys; use parse::ClangItemParser; +use quote; use std::borrow::Cow; use std::cell::Cell; use std::collections::{HashMap, HashSet, hash_map}; use std::collections::btree_map::{self, BTreeMap}; -use std::fmt; use std::iter::IntoIterator; use std::mem; -use syntax::ast::Ident; -use syntax::codemap::{DUMMY_SP, Span}; -use syntax::ext::base::ExtCtxt; /// A single identifier for an item. /// @@ -98,19 +95,9 @@ enum TypeKey { Declaration(Cursor), } -// This is just convenience to avoid creating a manual debug impl for the -// context. -struct GenContext<'ctx>(ExtCtxt<'ctx>); - -impl<'ctx> fmt::Debug for GenContext<'ctx> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "GenContext {{ ... }}") - } -} - /// A context used during parsing and generation of structs. #[derive(Debug)] -pub struct BindgenContext<'ctx> { +pub struct BindgenContext { /// The map of all the items parsed so far. /// /// It's a BTreeMap because we want the keys to be sorted to have consistent @@ -168,9 +155,7 @@ pub struct BindgenContext<'ctx> { collected_typerefs: bool, - /// Dummy structures for code generation. - gen_ctx: Option<&'ctx GenContext<'ctx>>, - span: Span, + in_codegen: bool, /// The clang index for parsing. index: clang::Index, @@ -268,24 +253,17 @@ pub struct BindgenContext<'ctx> { } /// A traversal of whitelisted items. -struct WhitelistedItemsTraversal<'ctx, 'gen> -where - 'gen: 'ctx, -{ - ctx: &'ctx BindgenContext<'gen>, +struct WhitelistedItemsTraversal<'ctx> { + ctx: &'ctx BindgenContext, traversal: ItemTraversal< 'ctx, - 'gen, ItemSet, Vec<ItemId>, for<'a> fn(&'a BindgenContext, Edge) -> bool, >, } -impl<'ctx, 'gen> Iterator for WhitelistedItemsTraversal<'ctx, 'gen> -where - 'gen: 'ctx, -{ +impl<'ctx> Iterator for WhitelistedItemsTraversal<'ctx> { type Item = ItemId; fn next(&mut self) -> Option<ItemId> { @@ -301,13 +279,10 @@ where } } -impl<'ctx, 'gen> WhitelistedItemsTraversal<'ctx, 'gen> -where - 'gen: 'ctx, -{ +impl<'ctx> WhitelistedItemsTraversal<'ctx> { /// Construct a new whitelisted items traversal. pub fn new<R>( - ctx: &'ctx BindgenContext<'gen>, + ctx: &'ctx BindgenContext, roots: R, predicate: for<'a> fn(&'a BindgenContext, Edge) -> bool, ) -> Self @@ -344,7 +319,7 @@ fn find_effective_target(clang_args: &[String]) -> (String, bool) { (HOST_TARGET.to_owned(), false) } -impl<'ctx> BindgenContext<'ctx> { +impl BindgenContext { /// Construct the context for the given `options`. pub fn new(options: BindgenOptions) -> Self { use clang_sys; @@ -402,8 +377,7 @@ impl<'ctx> BindgenContext<'ctx> { parsed_macros: Default::default(), replacements: Default::default(), collected_typerefs: false, - gen_ctx: None, - span: DUMMY_SP, + in_codegen: false, index: index, translation_unit: translation_unit, options: options, @@ -632,24 +606,67 @@ impl<'ctx> BindgenContext<'ctx> { // TODO: Move all this syntax crap to other part of the code. - /// Given that we are in the codegen phase, get the syntex context. - pub fn ext_cx(&self) -> &ExtCtxt<'ctx> { - &self.gen_ctx.expect("Not in gen phase").0 - } - - /// Given that we are in the codegen phase, get the current syntex span. - pub fn span(&self) -> Span { - self.span - } - /// Mangles a name so it doesn't conflict with any keyword. pub fn rust_mangle<'a>(&self, name: &'a str) -> Cow<'a, str> { - use syntax::parse::token; - let ident = self.rust_ident_raw(name); - let token = token::Ident(ident); - if token.is_any_keyword() || name.contains("@") || - name.contains("?") || name.contains("$") || - "bool" == name + if name.contains("@") || + name.contains("?") || + name.contains("$") || + match name { + "abstract" | + "alignof" | + "as" | + "become" | + "box" | + "break" | + "const" | + "continue" | + "crate" | + "do" | + "else" | + "enum" | + "extern" | + "false" | + "final" | + "fn" | + "for" | + "if" | + "impl" | + "in" | + "let" | + "loop" | + "macro" | + "match" | + "mod" | + "move" | + "mut" | + "offsetof" | + "override" | + "priv" | + "proc" | + "pub" | + "pure" | + "ref" | + "return" | + "Self" | + "self" | + "sizeof" | + "static" | + "struct" | + "super" | + "trait" | + "true" | + "type" | + "typeof" | + "unsafe" | + "unsized" | + "use" | + "virtual" | + "where" | + "while" | + "yield" | + "bool" => true, + _ => false, + } { let mut s = name.to_owned(); s = s.replace("@", "_"); @@ -662,13 +679,19 @@ impl<'ctx> BindgenContext<'ctx> { } /// Returns a mangled name as a rust identifier. - pub fn rust_ident(&self, name: &str) -> Ident { - self.rust_ident_raw(&self.rust_mangle(name)) + pub fn rust_ident<S>(&self, name: S) -> quote::Ident + where + S: AsRef<str> + { + self.rust_ident_raw(self.rust_mangle(name.as_ref())) } /// Returns a mangled name as a rust identifier. - pub fn rust_ident_raw(&self, name: &str) -> Ident { - self.ext_cx().ident_of(name) + pub fn rust_ident_raw<T>(&self, name: T) -> quote::Ident + where + T: Into<quote::Ident> + { + name.into() } /// Iterate over all items that have been defined. @@ -891,30 +914,7 @@ impl<'ctx> BindgenContext<'ctx> { where F: FnOnce(&Self) -> Out, { - use aster::symbol::ToSymbol; - use syntax::ext::expand::ExpansionConfig; - use syntax::codemap::{ExpnInfo, MacroBang, NameAndSpan}; - use syntax::ext::base; - use syntax::parse; - - let cfg = ExpansionConfig::default("xxx".to_owned()); - let sess = parse::ParseSess::new(); - let mut loader = base::DummyResolver; - let mut ctx = GenContext(base::ExtCtxt::new(&sess, cfg, &mut loader)); - - ctx.0.bt_push(ExpnInfo { - call_site: self.span, - callee: NameAndSpan { - format: MacroBang("".to_symbol()), - allow_internal_unstable: false, - span: None, - }, - }); - - // FIXME: This is evil, we should move code generation to use a wrapper - // of BindgenContext instead, I guess. Even though we know it's fine - // because we remove it before the end of this function. - self.gen_ctx = Some(unsafe { mem::transmute(&ctx) }); + self.in_codegen = true; self.assert_no_dangling_references(); @@ -950,7 +950,7 @@ impl<'ctx> BindgenContext<'ctx> { self.compute_cannot_derive_partialeq_or_eq(); let ret = cb(self); - self.gen_ctx = None; + self.in_codegen = false; ret } @@ -965,9 +965,9 @@ impl<'ctx> BindgenContext<'ctx> { } } - fn assert_no_dangling_item_traversal<'me>( - &'me self, - ) -> traversal::AssertNoDanglingItemsTraversal<'me, 'ctx> { + fn assert_no_dangling_item_traversal( + &self, + ) -> traversal::AssertNoDanglingItemsTraversal { assert!(self.in_codegen_phase()); assert!(self.current_module == self.root_module); @@ -1735,7 +1735,7 @@ impl<'ctx> BindgenContext<'ctx> { /// Are we in the codegen phase? pub fn in_codegen_phase(&self) -> bool { - self.gen_ctx.is_some() + self.in_codegen } /// Mark the type with the given `name` as replaced by the type with id @@ -2031,7 +2031,7 @@ impl<'ctx> BindgenContext<'ctx> { /// Convenient method for getting the prefix to use for most traits in /// codegen depending on the `use_core` option. - pub fn trait_prefix(&self) -> Ident { + pub fn trait_prefix(&self) -> quote::Ident { if self.options().use_core { self.rust_ident_raw("core") } else { @@ -2244,7 +2244,7 @@ impl ItemResolver { } /// Finish configuring and perform the actual item resolution. - pub fn resolve<'a, 'b>(self, ctx: &'a BindgenContext<'b>) -> &'a Item { + pub fn resolve(self, ctx: &BindgenContext) -> &Item { assert!(ctx.collected_typerefs()); let mut id = self.id; diff --git a/src/ir/function.rs b/src/ir/function.rs index 3cf48db7..b08824af 100644 --- a/src/ir/function.rs +++ b/src/ir/function.rs @@ -11,8 +11,8 @@ use clang_sys::{self, CXCallingConv}; use ir::derive::{CanTriviallyDeriveDebug, CanTriviallyDeriveHash, CanTriviallyDerivePartialEq}; use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult}; +use quote; use std::io; -use syntax::abi; const RUST_DERIVE_FUNPTR_LIMIT: usize = 12; @@ -136,8 +136,16 @@ impl DotAttributes for Function { /// An ABI extracted from a clang cursor. #[derive(Debug, Copy, Clone)] pub enum Abi { - /// A known ABI, that rust also understand. - Known(abi::Abi), + /// The default C ABI. + C, + /// The "stdcall" ABI. + Stdcall, + /// The "fastcall" ABI. + Fastcall, + /// The "aapcs" ABI. + Aapcs, + /// The "win64" ABI. + Win64, /// An unknown or invalid ABI. Unknown(CXCallingConv), } @@ -152,6 +160,22 @@ impl Abi { } } +impl quote::ToTokens for Abi { + fn to_tokens(&self, tokens: &mut quote::Tokens) { + tokens.append(match *self { + Abi::C => quote! { "C" }, + Abi::Stdcall => quote! { "stdcall" }, + Abi::Fastcall => quote! { "fastcall" }, + Abi::Aapcs => quote! { "aapcs" }, + Abi::Win64 => quote! { "win64" }, + Abi::Unknown(cc) => panic!( + "Cannot turn unknown calling convention to tokens: {:?}", + cc + ), + }); + } +} + /// A function signature. #[derive(Debug)] pub struct FunctionSig { @@ -171,15 +195,15 @@ pub struct FunctionSig { fn get_abi(cc: CXCallingConv) -> Abi { use clang_sys::*; - Abi::Known(match cc { - CXCallingConv_Default => abi::Abi::C, - CXCallingConv_C => abi::Abi::C, - CXCallingConv_X86StdCall => abi::Abi::Stdcall, - CXCallingConv_X86FastCall => abi::Abi::Fastcall, - CXCallingConv_AAPCS => abi::Abi::Aapcs, - CXCallingConv_X86_64Win64 => abi::Abi::Win64, - other => return Abi::Unknown(other), - }) + match cc { + CXCallingConv_Default => Abi::C, + CXCallingConv_C => Abi::C, + CXCallingConv_X86StdCall => Abi::Stdcall, + CXCallingConv_X86FastCall => Abi::Fastcall, + CXCallingConv_AAPCS => Abi::Aapcs, + CXCallingConv_X86_64Win64 => Abi::Win64, + other => Abi::Unknown(other), + } } fn mangling_hack_if_needed(ctx: &BindgenContext, symbol: &mut String) { @@ -513,8 +537,7 @@ impl CanTriviallyDeriveDebug for FunctionSig { } match self.abi { - Abi::Known(abi::Abi::C) | - Abi::Unknown(..) => true, + Abi::C | Abi::Unknown(..) => true, _ => false, } } @@ -527,8 +550,7 @@ impl CanTriviallyDeriveHash for FunctionSig { } match self.abi { - Abi::Known(abi::Abi::C) | - Abi::Unknown(..) => true, + Abi::C | Abi::Unknown(..) => true, _ => false, } } @@ -541,8 +563,7 @@ impl CanTriviallyDerivePartialEq for FunctionSig { } match self.abi { - Abi::Known(abi::Abi::C) | - Abi::Unknown(..) => true, + Abi::C | Abi::Unknown(..) => true, _ => false, } } diff --git a/src/ir/item.rs b/src/ir/item.rs index 0dac1287..241bd9ef 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -93,10 +93,10 @@ pub trait HasFloat { /// up to (but not including) the implicit root module. pub trait ItemAncestors { /// Get an iterable over this item's ancestors. - fn ancestors<'a, 'b>( + fn ancestors<'a>( &self, - ctx: &'a BindgenContext<'b>, - ) -> ItemAncestorsIter<'a, 'b>; + ctx: &'a BindgenContext, + ) -> ItemAncestorsIter<'a>; } cfg_if! { @@ -120,20 +120,14 @@ cfg_if! { } /// An iterator over an item and its ancestors. -pub struct ItemAncestorsIter<'a, 'b> -where - 'b: 'a, -{ +pub struct ItemAncestorsIter<'a> { item: ItemId, - ctx: &'a BindgenContext<'b>, + ctx: &'a BindgenContext, seen: DebugOnlyItemSet, } -impl<'a, 'b> ItemAncestorsIter<'a, 'b> -where - 'b: 'a, -{ - fn new(ctx: &'a BindgenContext<'b>, item: ItemId) -> Self { +impl<'a> ItemAncestorsIter<'a> { + fn new(ctx: &'a BindgenContext, item: ItemId) -> Self { ItemAncestorsIter { item: item, ctx: ctx, @@ -142,10 +136,7 @@ where } } -impl<'a, 'b> Iterator for ItemAncestorsIter<'a, 'b> -where - 'b: 'a, -{ +impl<'a> Iterator for ItemAncestorsIter<'a> { type Item = ItemId; fn next(&mut self) -> Option<Self::Item> { @@ -238,19 +229,19 @@ impl ItemCanonicalPath for ItemId { } impl ItemAncestors for ItemId { - fn ancestors<'a, 'b>( + fn ancestors<'a>( &self, - ctx: &'a BindgenContext<'b>, - ) -> ItemAncestorsIter<'a, 'b> { + ctx: &'a BindgenContext, + ) -> ItemAncestorsIter<'a> { ItemAncestorsIter::new(ctx, *self) } } impl ItemAncestors for Item { - fn ancestors<'a, 'b>( + fn ancestors<'a>( &self, - ctx: &'a BindgenContext<'b>, - ) -> ItemAncestorsIter<'a, 'b> { + ctx: &'a BindgenContext, + ) -> ItemAncestorsIter<'a> { self.id().ancestors(ctx) } } @@ -638,10 +629,10 @@ impl Item { } /// Take out item NameOptions - pub fn name<'item, 'ctx>( - &'item self, - ctx: &'item BindgenContext<'ctx>, - ) -> NameOptions<'item, 'ctx> { + pub fn name<'a>( + &'a self, + ctx: &'a BindgenContext, + ) -> NameOptions<'a> { NameOptions::new(self, ctx) } @@ -1773,18 +1764,15 @@ impl ItemCanonicalPath for Item { /// Builder struct for naming variations, which hold inside different /// flags for naming options. #[derive(Debug)] -pub struct NameOptions<'item, 'ctx> -where - 'ctx: 'item, -{ - item: &'item Item, - ctx: &'item BindgenContext<'ctx>, +pub struct NameOptions<'a> { + item: &'a Item, + ctx: &'a BindgenContext, within_namespaces: bool, } -impl<'item, 'ctx> NameOptions<'item, 'ctx> { +impl<'a> NameOptions<'a> { /// Construct a new `NameOptions` - pub fn new(item: &'item Item, ctx: &'item BindgenContext<'ctx>) -> Self { + pub fn new(item: &'a Item, ctx: &'a BindgenContext) -> Self { NameOptions { item: item, ctx: ctx, diff --git a/src/ir/objc.rs b/src/ir/objc.rs index 843dd722..cabbd389 100644 --- a/src/ir/objc.rs +++ b/src/ir/objc.rs @@ -12,6 +12,7 @@ use clang_sys::CXCursor_ObjCClassRef; use clang_sys::CXCursor_ObjCInstanceMethodDecl; use clang_sys::CXCursor_ObjCProtocolDecl; use clang_sys::CXCursor_ObjCProtocolRef; +use quote; /// Objective C interface as used in TypeKind /// @@ -211,13 +212,19 @@ impl ObjCMethod { } /// Formats the method call - pub fn format_method_call(&self, args: &[String]) -> String { - let split_name: Vec<&str> = - self.name.split(':').filter(|p| !p.is_empty()).collect(); + pub fn format_method_call(&self, args: &[quote::Tokens]) -> quote::Tokens { + let split_name: Vec<_> = self.name + .split(':') + .filter(|p| !p.is_empty()) + .map(quote::Ident::new) + .collect(); // No arguments if args.len() == 0 && split_name.len() == 1 { - return split_name[0].to_string(); + let name = &split_name[0]; + return quote! { + #name + }; } // Check right amount of arguments @@ -229,12 +236,14 @@ impl ObjCMethod { ); } - split_name - .iter() + let args = split_name + .into_iter() .zip(args.iter()) - .map(|parts| format!("{}:{} ", parts.0, parts.1)) - .collect::<Vec<_>>() - .join("") + .map(|(arg, ty)| quote! { #arg : #ty }); + + quote! { + #( #args ),* + } } } diff --git a/src/ir/traversal.rs b/src/ir/traversal.rs index e4ce946d..f55acc10 100644 --- a/src/ir/traversal.rs +++ b/src/ir/traversal.rs @@ -241,9 +241,9 @@ pub fn codegen_edges(ctx: &BindgenContext, edge: Edge) -> bool { /// The storage for the set of items that have been seen (although their /// outgoing edges might not have been fully traversed yet) in an active /// traversal. -pub trait TraversalStorage<'ctx, 'gen> { +pub trait TraversalStorage<'ctx> { /// Construct a new instance of this TraversalStorage, for a new traversal. - fn new(ctx: &'ctx BindgenContext<'gen>) -> Self; + fn new(ctx: &'ctx BindgenContext) -> Self; /// Add the given item to the storage. If the item has never been seen /// before, return `true`. Otherwise, return `false`. @@ -253,8 +253,8 @@ pub trait TraversalStorage<'ctx, 'gen> { fn add(&mut self, from: Option<ItemId>, item: ItemId) -> bool; } -impl<'ctx, 'gen> TraversalStorage<'ctx, 'gen> for ItemSet { - fn new(_: &'ctx BindgenContext<'gen>) -> Self { +impl<'ctx> TraversalStorage<'ctx> for ItemSet { + fn new(_: &'ctx BindgenContext) -> Self { ItemSet::new() } @@ -267,18 +267,13 @@ impl<'ctx, 'gen> TraversalStorage<'ctx, 'gen> for ItemSet { /// each item. This is useful for providing debug assertions with meaningful /// diagnostic messages about dangling items. #[derive(Debug)] -pub struct Paths<'ctx, 'gen>( +pub struct Paths<'ctx>( BTreeMap<ItemId, ItemId>, - &'ctx BindgenContext<'gen> -) -where - 'gen: 'ctx; + &'ctx BindgenContext +); -impl<'ctx, 'gen> TraversalStorage<'ctx, 'gen> for Paths<'ctx, 'gen> -where - 'gen: 'ctx, -{ - fn new(ctx: &'ctx BindgenContext<'gen>) -> Self { +impl<'ctx> TraversalStorage<'ctx> for Paths<'ctx> { + fn new(ctx: &'ctx BindgenContext) -> Self { Paths(BTreeMap::new(), ctx) } @@ -388,14 +383,13 @@ pub trait Trace { /// An graph traversal of the transitive closure of references between items. /// /// See `BindgenContext::whitelisted_items` for more information. -pub struct ItemTraversal<'ctx, 'gen, Storage, Queue, Predicate> +pub struct ItemTraversal<'ctx, Storage, Queue, Predicate> where - 'gen: 'ctx, - Storage: TraversalStorage<'ctx, 'gen>, + Storage: TraversalStorage<'ctx>, Queue: TraversalQueue, Predicate: TraversalPredicate, { - ctx: &'ctx BindgenContext<'gen>, + ctx: &'ctx BindgenContext, /// The set of items we have seen thus far in this traversal. seen: Storage, @@ -410,20 +404,19 @@ where currently_traversing: Option<ItemId>, } -impl<'ctx, 'gen, Storage, Queue, Predicate> - ItemTraversal<'ctx, 'gen, Storage, Queue, Predicate> +impl<'ctx, Storage, Queue, Predicate> + ItemTraversal<'ctx, Storage, Queue, Predicate> where - 'gen: 'ctx, - Storage: TraversalStorage<'ctx, 'gen>, + Storage: TraversalStorage<'ctx>, Queue: TraversalQueue, Predicate: TraversalPredicate, { /// Begin a new traversal, starting from the given roots. pub fn new<R>( - ctx: &'ctx BindgenContext<'gen>, + ctx: &'ctx BindgenContext, roots: R, predicate: Predicate, - ) -> ItemTraversal<'ctx, 'gen, Storage, Queue, Predicate> + ) -> ItemTraversal<'ctx, Storage, Queue, Predicate> where R: IntoIterator<Item = ItemId>, { @@ -445,11 +438,10 @@ where } } -impl<'ctx, 'gen, Storage, Queue, Predicate> Tracer - for ItemTraversal<'ctx, 'gen, Storage, Queue, Predicate> +impl<'ctx, Storage, Queue, Predicate> Tracer + for ItemTraversal<'ctx, Storage, Queue, Predicate> where - 'gen: 'ctx, - Storage: TraversalStorage<'ctx, 'gen>, + Storage: TraversalStorage<'ctx>, Queue: TraversalQueue, Predicate: TraversalPredicate, { @@ -467,11 +459,10 @@ where } } -impl<'ctx, 'gen, Storage, Queue, Predicate> Iterator - for ItemTraversal<'ctx, 'gen, Storage, Queue, Predicate> +impl<'ctx, Storage, Queue, Predicate> Iterator + for ItemTraversal<'ctx, Storage, Queue, Predicate> where - 'gen: 'ctx, - Storage: TraversalStorage<'ctx, 'gen>, + Storage: TraversalStorage<'ctx>, Queue: TraversalQueue, Predicate: TraversalPredicate, { @@ -505,11 +496,10 @@ where /// /// See `BindgenContext::assert_no_dangling_item_traversal` for more /// information. -pub type AssertNoDanglingItemsTraversal<'ctx, 'gen> = +pub type AssertNoDanglingItemsTraversal<'ctx> = ItemTraversal< 'ctx, - 'gen, - Paths<'ctx, 'gen>, + Paths<'ctx>, VecDeque<ItemId>, for<'a> fn(&'a BindgenContext, Edge) -> bool, >; diff --git a/src/ir/ty.rs b/src/ir/ty.rs index b588dbb4..8cfbde10 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -443,6 +443,8 @@ impl DotAttributes for TypeKind { where W: io::Write, { + writeln!(out, "<tr><td>type kind</td><td>{}</td></tr>", self.kind_name())?; + if let TypeKind::Comp(ref comp) = *self { comp.dot_attributes(ctx, out)?; } @@ -451,6 +453,35 @@ impl DotAttributes for TypeKind { } } +impl TypeKind { + fn kind_name(&self) -> &'static str { + match *self { + TypeKind::Void => "Void", + TypeKind::NullPtr => "NullPtr", + TypeKind::Comp(..) => "Comp", + TypeKind::Opaque => "Opaque", + TypeKind::Int(..) => "Int", + TypeKind::Float(..) => "Float", + TypeKind::Complex(..) => "Complex", + TypeKind::Alias(..) => "Alias", + TypeKind::TemplateAlias(..) => "TemplateAlias", + TypeKind::Array(..) => "Array", + TypeKind::Function(..) => "Function", + TypeKind::Enum(..) => "Enum", + TypeKind::Pointer(..) => "Pointer", + TypeKind::BlockPointer => "BlockPointer", + TypeKind::Reference(..) => "Reference", + TypeKind::TemplateInstantiation(..) => "TemplateInstantiation", + TypeKind::UnresolvedTypeRef(..) => "UnresolvedTypeRef", + TypeKind::ResolvedTypeRef(..) => "ResolvedTypeRef", + TypeKind::TypeParam => "TypeParam", + TypeKind::ObjCInterface(..) => "ObjCInterface", + TypeKind::ObjCId => "ObjCId", + TypeKind::ObjCSel => "ObjCSel", + } + } +} + #[test] fn is_invalid_type_param_valid() { let ty = Type::new(Some("foo".into()), None, TypeKind::TypeParam, false); @@ -13,19 +13,20 @@ // To avoid rather annoying warnings when matching with CXCursor_xxx as a // constant. #![allow(non_upper_case_globals)] +// `quote!` nests quite deeply. +#![recursion_limit="128"] +extern crate cexpr; #[macro_use] #[allow(unused_extern_crates)] extern crate cfg_if; -extern crate cexpr; -extern crate syntex_syntax as syntax; -extern crate aster; -extern crate quasi; extern crate clang_sys; -extern crate peeking_take_while; -extern crate regex; #[macro_use] extern crate lazy_static; +extern crate peeking_take_while; +#[macro_use] +extern crate quote; +extern crate regex; extern crate which; #[cfg(feature = "logging")] @@ -60,6 +61,7 @@ macro_rules! doc_mod { } mod clang; +mod codegen; mod features; mod ir; mod parse; @@ -68,19 +70,12 @@ mod time; pub mod callbacks; -#[cfg(rustfmt)] -mod codegen; - doc_mod!(clang, clang_docs); doc_mod!(features, features_docs); doc_mod!(ir, ir_docs); doc_mod!(parse, parse_docs); doc_mod!(regex_set, regex_set_docs); -mod codegen { - include!(concat!(env!("OUT_DIR"), "/codegen.rs")); -} - pub use features::{LATEST_STABLE_RUST, RUST_TARGET_STRINGS, RustTarget}; use features::RustFeatures; use ir::context::{BindgenContext, ItemId}; @@ -95,12 +90,6 @@ 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::print::pp::eof; -use syntax::print::pprust; -use syntax::ptr::P; - /// A type used to indicate which kind of items do we have to generate. /// /// TODO(emilio): Use `bitflags!` @@ -948,7 +937,7 @@ impl Builder { } /// Generate the Rust bindings using the options built up thus far. - pub fn generate<'ctx>(mut self) -> Result<Bindings<'ctx>, ()> { + pub fn generate(mut self) -> Result<Bindings, ()> { self.options.input_header = self.input_headers.pop(); self.options.clang_args.extend( self.input_headers @@ -964,7 +953,7 @@ impl Builder { }), ); - Bindings::generate(self.options, None) + Bindings::generate(self.options) } /// Preprocess and dump the input header files to disk. @@ -1353,21 +1342,19 @@ fn ensure_libclang_is_loaded() { /// Generated Rust bindings. #[derive(Debug)] -pub struct Bindings<'ctx> { - context: BindgenContext<'ctx>, - module: ast::Mod, +pub struct Bindings { + context: BindgenContext, + module: quote::Tokens, } -impl<'ctx> Bindings<'ctx> { +impl Bindings { /// Generate bindings for the given options. /// /// Deprecated - use a `Builder` instead #[deprecated] pub fn generate( mut options: BindgenOptions, - span: Option<Span>, - ) -> Result<Bindings<'ctx>, ()> { - let span = span.unwrap_or(DUMMY_SP); + ) -> Result<Bindings, ()> { ensure_libclang_is_loaded(); options.build(); @@ -1436,38 +1423,30 @@ impl<'ctx> Bindings<'ctx> { let time_phases = options.time_phases; let mut context = BindgenContext::new(options); + { let _t = time::Timer::new("parse") .with_output(time_phases); try!(parse(&mut context)); } - let module = ast::Mod { - inner: span, - items: codegen::codegen(&mut context), - }; + let items = codegen::codegen(&mut context); Ok(Bindings { context: context, - module: module, + module: quote! { + #( #items )* + } }) } - /// Convert these bindings into a Rust AST. - pub fn into_ast(self) -> Vec<P<ast::Item>> { - self.module.items - } - /// Convert these bindings into source text (with raw lines prepended). pub fn to_string(&self) -> String { - let mut mod_str = vec![]; - { - let ref_writer = Box::new(mod_str.by_ref()) as Box<Write>; - self.write(ref_writer).expect( - "Could not write bindings to string", - ); - } - String::from_utf8(mod_str).unwrap() + let mut bytes = vec![]; + self.write(Box::new(&mut bytes) as Box<Write>) + .expect("writing to a vec cannot fail"); + String::from_utf8(bytes) + .expect("we should only write bindings that are valid utf-8") } /// Write these bindings as source text to a file. @@ -1488,27 +1467,26 @@ impl<'ctx> Bindings<'ctx> { /// Write these bindings as source text to the given `Write`able. pub fn write<'a>(&self, mut writer: Box<Write + 'a>) -> io::Result<()> { - try!(writer.write( + 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())); - try!(writer.write("\n".as_bytes())); + writer.write(line.as_bytes())?; + writer.write("\n".as_bytes())?; } if !self.context.options().raw_lines.is_empty() { - try!(writer.write("\n".as_bytes())); + writer.write("\n".as_bytes())?; } - let mut ps = pprust::rust_printer(writer); - try!(ps.print_mod(&self.module, &[])); - try!(ps.print_remaining_comments()); - try!(eof(&mut ps.s)); - ps.s.out.flush() + writer.write(self.module.as_str().as_bytes())?; + Ok(()) } /// Checks if rustfmt_bindings is set and runs rustfmt on the file fn rustfmt_generated_file(&self, file: &Path) -> io::Result<()> { + let _t = self.context.timer("rustfmt_generated_file"); + if !self.context.options().rustfmt_bindings { return Ok(()); } diff --git a/src/main.rs b/src/main.rs index dc3572b3..eb3d6caf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,6 @@ extern crate env_logger; #[macro_use] #[cfg(feature = "logging")] extern crate log; -extern crate clang_sys; extern crate clap; use bindgen::clang_version; diff --git a/src/time.rs b/src/time.rs index ebbac702..c841bccf 100644 --- a/src/time.rs +++ b/src/time.rs @@ -37,12 +37,12 @@ impl<'a> Timer<'a> { fn print_elapsed(&mut self) { if self.output { let elapsed = self.elapsed(); - let time = (elapsed.as_secs() as f32) - + (elapsed.subsec_nanos() as f32) / 1e9; + let time = (elapsed.as_secs() as f64) * 1e3 + + (elapsed.subsec_nanos() as f64) / 1e6; let stderr = io::stderr(); // Arbitrary output format, subject to change. writeln!(stderr.lock(), - " time: {:.3} ms.\t{}", + " time: {:>9.3} ms.\t{}", time, self.name) .expect("timer write should not fail"); } |