diff options
Diffstat (limited to 'src/codegen/mod.rs')
-rw-r--r-- | src/codegen/mod.rs | 142 |
1 files changed, 82 insertions, 60 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 0f3337a..19886e3 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -48,7 +48,6 @@ use proc_macro2::{self, Ident, Span}; use quote::TokenStreamExt; use crate::{Entry, HashMap, HashSet}; -use std; use std::borrow::Cow; use std::cell::Cell; use std::collections::VecDeque; @@ -58,7 +57,7 @@ use std::ops; use std::str::FromStr; // Name of type defined in constified enum module -pub static CONSTIFIED_ENUM_MODULE_REPR_NAME: &'static str = "Type"; +pub static CONSTIFIED_ENUM_MODULE_REPR_NAME: &str = "Type"; fn top_level_path( ctx: &BindgenContext, @@ -666,10 +665,21 @@ impl CodeGenerator for Var { match String::from_utf8(bytes.clone()) { Ok(string) => { let cstr = helpers::ast_ty::cstr_expr(string); - result.push(quote! { - #(#attrs)* - pub const #canonical_ident : &'static #ty = #cstr ; - }); + if ctx + .options() + .rust_features + .static_lifetime_elision + { + result.push(quote! { + #(#attrs)* + pub const #canonical_ident : &#ty = #cstr ; + }); + } else { + result.push(quote! { + #(#attrs)* + pub const #canonical_ident : &'static #ty = #cstr ; + }); + } } Err(..) => { let bytes = helpers::ast_ty::byte_array_expr(bytes); @@ -681,12 +691,11 @@ impl CodeGenerator for Var { } } VarType::Float(f) => { - match helpers::ast_ty::float_expr(ctx, f) { - Ok(expr) => result.push(quote! { + if let Ok(expr) = helpers::ast_ty::float_expr(ctx, f) { + result.push(quote! { #(#attrs)* pub const #canonical_ident : #ty = #expr ; - }), - Err(..) => return, + }); } } VarType::Char(c) => { @@ -698,7 +707,7 @@ impl CodeGenerator for Var { } } else { // If necessary, apply a `#[link_name]` attribute - let link_name = self.mangled_name().unwrap_or(self.name()); + let link_name = self.mangled_name().unwrap_or_else(|| self.name()); if !utils::names_will_be_identical_after_mangling( &canonical_name, link_name, @@ -756,7 +765,6 @@ impl CodeGenerator for Type { // converted to rust types in fields, arguments, and such. // NOTE(emilio): If you add to this list, make sure to also add // it to BindgenContext::compute_allowlisted_and_codegen_items. - return; } TypeKind::TemplateInstantiation(ref inst) => { inst.codegen(ctx, result, item) @@ -886,12 +894,9 @@ impl CodeGenerator for Type { // We prefer using `pub use` over `pub type` because of: // https://github.com/rust-lang/rust/issues/26264 - if inner_rust_type.to_string().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_empty() && + // These are the only characters allowed in simple + // paths, eg `good::dogs::Bront`. + if inner_rust_type.to_string().chars().all(|c| matches!(c, 'A'..='Z' | 'a'..='z' | '0'..='9' | ':' | '_' | ' ')) && outer_params.is_empty() && !is_opaque && alias_style == AliasVariation::TypeAlias && inner_item.expect_type().canonical_type(ctx).is_enum() @@ -1767,7 +1772,7 @@ impl CodeGenerator for CompInfo { let inner_item = ctx.resolve_item(base.ty); let mut inner = inner_item.to_rust_ty_or_opaque(ctx, &()); - inner.append_implicit_template_params(ctx, &inner_item); + inner.append_implicit_template_params(ctx, inner_item); let field_name = ctx.rust_ident(&base.field_name); struct_layout.saw_base(inner_item.expect_type()); @@ -2023,6 +2028,11 @@ impl CodeGenerator for CompInfo { attributes.push(attributes::derives(&derives)) } + if item.annotations().must_use_type() || ctx.must_use_type_by_name(item) + { + attributes.push(attributes::must_use()); + } + let mut tokens = if is_union && struct_layout.is_rust_union() { quote! { #( #attributes )* @@ -2121,11 +2131,11 @@ impl CodeGenerator for CompInfo { }) .flat_map(|field| { let name = field.name().unwrap(); - field.offset().and_then(|offset| { + field.offset().map(|offset| { let field_offset = offset / 8; let field_name = ctx.rust_ident(name); - Some(quote! { + quote! { assert_eq!( unsafe { &(*(::#prefix::ptr::null::<#canonical_ident>())).#field_name as *const _ as usize @@ -2133,7 +2143,7 @@ impl CodeGenerator for CompInfo { #field_offset, concat!("Offset of field: ", stringify!(#canonical_ident), "::", stringify!(#field_name)) ); - }) + } }) }) .collect::<Vec<proc_macro2::TokenStream>>(); @@ -2343,7 +2353,7 @@ impl MethodCodegen for Method { return; } let function = function_item.expect_function(); - let times_seen = function.codegen(ctx, result, &function_item); + let times_seen = function.codegen(ctx, result, function_item); let times_seen = match times_seen { Some(seen) => seen, None => return, @@ -2409,7 +2419,7 @@ impl MethodCodegen for Method { } let mut exprs = - helpers::ast_ty::arguments_from_signature(&signature, ctx); + helpers::ast_ty::arguments_from_signature(signature, ctx); let mut stmts = vec![]; @@ -2466,8 +2476,7 @@ impl MethodCodegen for Method { #( #stmts );* }; - let mut attrs = vec![]; - attrs.push(attributes::inline()); + let mut attrs = vec![attributes::inline()]; if signature.must_use() && ctx.options().rust_features().must_use_function @@ -2508,19 +2517,13 @@ pub enum EnumVariation { impl EnumVariation { fn is_rust(&self) -> bool { - match *self { - EnumVariation::Rust { .. } => true, - _ => false, - } + matches!(*self, EnumVariation::Rust { .. }) } /// Both the `Const` and `ModuleConsts` variants will cause this to return /// true. fn is_const(&self) -> bool { - match *self { - EnumVariation::Consts | EnumVariation::ModuleConsts => true, - _ => false, - } + matches!(*self, EnumVariation::Consts | EnumVariation::ModuleConsts) } } @@ -2598,10 +2601,7 @@ impl<'a> EnumBuilder<'a> { /// Returns true if the builder is for a rustified enum. fn is_rust_enum(&self) -> bool { - match *self { - EnumBuilder::Rust { .. } => true, - _ => false, - } + matches!(*self, EnumBuilder::Rust { .. }) } /// Create a new enum given an item builder, a canonical name, a name for @@ -2998,18 +2998,43 @@ impl CodeGenerator for Enum { attrs.push(attributes::doc(comment)); } + if item.annotations().must_use_type() || ctx.must_use_type_by_name(item) + { + attrs.push(attributes::must_use()); + } + if !variation.is_const() { let mut derives = derives_of_item(item, ctx); - // For backwards compat, enums always derive Clone/Eq/PartialEq/Hash, even + // For backwards compat, enums always derive Debug/Clone/Eq/PartialEq/Hash, even // if we don't generate those by default. + if !item.annotations().disallow_debug() { + derives.insert(DerivableTraits::DEBUG); + } + if !item.annotations().disallow_copy() { + derives.insert(DerivableTraits::COPY); + } derives.insert( DerivableTraits::CLONE | - DerivableTraits::COPY | DerivableTraits::HASH | DerivableTraits::PARTIAL_EQ | DerivableTraits::EQ, ); - let derives: Vec<_> = derives.into(); + let mut derives: Vec<_> = derives.into(); + for derive in item.annotations().derives().iter() { + if !derives.contains(&derive.as_str()) { + derives.push(derive); + } + } + + // The custom derives callback may return a list of derive attributes; + // add them to the end of the list. + let custom_derives; + if let Some(cb) = &ctx.options().parse_callbacks { + custom_derives = cb.add_derives(&name); + // In most cases this will be a no-op, since custom_derives will be empty. + derives.extend(custom_derives.iter().map(|s| s.as_str())); + }; + attrs.push(attributes::derives(&derives)); } @@ -3067,7 +3092,7 @@ impl CodeGenerator for Enum { let constant_mangling_prefix = if ctx.options().prepend_enum_name { if enum_ty.name().is_none() { - parent_canonical_name.as_ref().map(|n| &**n) + parent_canonical_name.as_deref() } else { Some(&*name) } @@ -3626,13 +3651,12 @@ impl TryToRustTy for Type { let void = c_void(ctx); return Ok(void.to_ptr(/* is_const = */ false)); } - let template_params = item - .used_template_params(ctx) - .into_iter() - .filter(|param| param.is_template_param(ctx, &())) - .collect::<Vec<_>>(); - if item.is_opaque(ctx, &()) && !template_params.is_empty() { + if item.is_opaque(ctx, &()) && + item.used_template_params(ctx) + .into_iter() + .any(|param| param.is_template_param(ctx, &())) + { self.try_to_opaque(ctx, item) } else if let Some(ty) = self .name() @@ -3661,10 +3685,8 @@ impl TryToRustTy for Type { inner.into_resolver().through_type_refs().resolve(ctx); let inner_ty = inner.expect_type(); - let is_objc_pointer = match inner_ty.kind() { - TypeKind::ObjCInterface(..) => true, - _ => false, - }; + let is_objc_pointer = + matches!(inner_ty.kind(), TypeKind::ObjCInterface(..)); // Regardless if we can properly represent the inner type, we // should always generate a proper pointer here, so use @@ -3797,8 +3819,8 @@ impl TryToRustTy for FunctionSig { _: &(), ) -> error::Result<proc_macro2::TokenStream> { // 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 ret = utils::fnsig_return_ty(ctx, self); + let arguments = utils::fnsig_arguments(ctx, self); let abi = self.abi(); match abi { @@ -4040,12 +4062,12 @@ impl CodeGenerator for ObjCInterface { impl_items.push(impl_item); } - let instance_method_names: Vec<_> = - self.methods().iter().map(|m| m.rust_name()).collect(); - for class_method in self.class_methods() { - let ambiquity = - instance_method_names.contains(&class_method.rust_name()); + let ambiquity = self + .methods() + .iter() + .map(|m| m.rust_name()) + .any(|x| x == class_method.rust_name()); let prefix = if ambiquity { "class_" } else { "" }; let impl_item = objc_method_codegen( ctx, @@ -4637,7 +4659,7 @@ pub mod utils { TypeKind::Array(t, _) => { let stream = if ctx.options().array_pointers_in_arguments { - arg_ty.to_rust_ty_or_opaque(ctx, &arg_item) + arg_ty.to_rust_ty_or_opaque(ctx, arg_item) } else { t.to_rust_ty_or_opaque(ctx, &()) }; |