aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen/mod.rs')
-rw-r--r--src/codegen/mod.rs142
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, &())
};