Merge branch 'upstream/master'

Change-Id: I81cd804771c8b0657da2db82282db8f60962cefe
diff --git a/.github/workflows/bindgen.yml b/.github/workflows/bindgen.yml
index 7080352..bc525ed 100644
--- a/.github/workflows/bindgen.yml
+++ b/.github/workflows/bindgen.yml
@@ -23,7 +23,7 @@
           # features.
           toolchain: nightly
           override: true
-          components: rustfmt
+          components: rustfmt, clippy
 
       - name: Run rustfmt
         uses: actions-rs/cargo@v1
@@ -31,6 +31,11 @@
           command: fmt
           args: -- --check
 
+      - name: Run clippy
+        uses: actions-rs/cargo@v1
+        with:
+          command: clippy
+
   msrv:
     runs-on: ubuntu-latest
     steps:
@@ -42,11 +47,11 @@
           profile: minimal
           # MSRV below is documented in README.md, please update that if you
           # change this.
-          toolchain: 1.44.0
+          toolchain: 1.46.0
           override: true
 
       - name: Build with msrv
-        run: rm Cargo.lock && cargo +1.44.0 build --lib
+        run: rm Cargo.lock && cargo +1.46.0 build --lib
 
   quickchecking:
     runs-on: ubuntu-latest
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a5e8bea..73c405c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -144,6 +144,8 @@
 
 ## Changed
 
+ * cexpr and nom have been updated, new msrv is 1.46 (#2107).
+
 ## Deprecated
 
 ## Removed
diff --git a/Cargo.lock b/Cargo.lock
index 06dae40..400fb11 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -61,22 +61,10 @@
 checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
 [[package]]
-name = "bitvec"
-version = "0.19.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321"
-dependencies = [
- "funty",
- "radium",
- "tap",
- "wyz",
-]
-
-[[package]]
 name = "cexpr"
-version = "0.5.0"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db507a7679252d2276ed0dd8113c6875ec56d3089f9225b2b42c30cc1f8e5c89"
+checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
 dependencies = [
  "nom",
 ]
@@ -139,12 +127,6 @@
 ]
 
 [[package]]
-name = "funty"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
-
-[[package]]
 name = "getrandom"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -220,14 +202,19 @@
 checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
 
 [[package]]
-name = "nom"
-version = "6.2.1"
+name = "minimal-lexical"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6"
+checksum = "9c64630dcdd71f1a64c435f54885086a0de5d6a12d104d69b165fb7d5286d677"
+
+[[package]]
+name = "nom"
+version = "7.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ffd9d26838a953b4af82cbeb9f1592c6798916983959be223a7124e992742c1"
 dependencies = [
- "bitvec",
- "funty",
  "memchr",
+ "minimal-lexical",
  "version_check",
 ]
 
@@ -262,12 +249,6 @@
 ]
 
 [[package]]
-name = "radium"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
-
-[[package]]
 name = "rand"
 version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -361,12 +342,6 @@
 checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
-name = "tap"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
-
-[[package]]
 name = "tempfile"
 version = "3.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -469,9 +444,3 @@
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
-name = "wyz"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
diff --git a/Cargo.toml b/Cargo.toml
index 0b04cda..26fd6cb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -47,7 +47,7 @@
 
 [dependencies]
 bitflags = "1.0.3"
-cexpr = "0.5"
+cexpr = "0.6"
 # This kinda sucks: https://github.com/rust-lang/cargo/issues/1982
 clap = { version = "2", optional = true }
 clang-sys = { version = "1", features = ["clang_6_0"] }
diff --git a/README.md b/README.md
index 00f66eb..7b2dbbc 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,7 @@
 
 ## MSRV
 
-The minimum supported Rust version is **1.44**.
+The minimum supported Rust version is **1.46**.
 
 No MSRV bump policy has been established yet, so MSRV may increase in any release.
 
diff --git a/src/clang.rs b/src/clang.rs
index db6467e..36ccd26 100644
--- a/src/clang.rs
+++ b/src/clang.rs
@@ -4,9 +4,7 @@
 #![allow(non_upper_case_globals, dead_code)]
 
 use crate::ir::context::BindgenContext;
-use cexpr;
 use clang_sys::*;
-use regex;
 use std::ffi::{CStr, CString};
 use std::fmt;
 use std::hash::Hash;
@@ -85,7 +83,7 @@
 
             let mut result = Vec::with_capacity(count);
             for i in 0..count {
-                let string_ptr = (*manglings).Strings.offset(i as isize);
+                let string_ptr = (*manglings).Strings.add(i);
                 result.push(cxstring_to_string_leaky(*string_ptr));
             }
             clang_disposeStringSet(manglings);
@@ -223,12 +221,12 @@
     /// not tracking the type declaration but the location of the cursor, given
     /// clang doesn't expose a proper declaration for these types.
     pub fn is_template_like(&self) -> bool {
-        match self.kind() {
+        matches!(
+            self.kind(),
             CXCursor_ClassTemplate |
-            CXCursor_ClassTemplatePartialSpecialization |
-            CXCursor_TypeAliasTemplateDecl => true,
-            _ => false,
-        }
+                CXCursor_ClassTemplatePartialSpecialization |
+                CXCursor_TypeAliasTemplateDecl
+        )
     }
 
     /// Is this Cursor pointing to a function-like macro definition?
@@ -275,7 +273,7 @@
             return parent.is_in_non_fully_specialized_template();
         }
 
-        return true;
+        true
     }
 
     /// Is this cursor pointing a valid referent?
@@ -402,12 +400,9 @@
     where
         Visitor: FnMut(Cursor) -> CXChildVisitResult,
     {
+        let data = &mut visitor as *mut Visitor;
         unsafe {
-            clang_visitChildren(
-                self.x,
-                visit_children::<Visitor>,
-                mem::transmute(&mut visitor),
-            );
+            clang_visitChildren(self.x, visit_children::<Visitor>, data.cast());
         }
     }
 
@@ -900,7 +895,7 @@
 where
     Visitor: FnMut(Cursor) -> CXChildVisitResult,
 {
-    let func: &mut Visitor = unsafe { mem::transmute(data) };
+    let func: &mut Visitor = unsafe { &mut *(data as *mut Visitor) };
     let child = Cursor { x: cur };
 
     (*func)(child)
@@ -1027,7 +1022,7 @@
         let s = unsafe { cxstring_into_string(clang_getTypeSpelling(self.x)) };
         // Clang 5.0 introduced changes in the spelling API so it returned the
         // full qualified name. Let's undo that here.
-        if s.split("::").all(|s| is_valid_identifier(s)) {
+        if s.split("::").all(is_valid_identifier) {
             if let Some(s) = s.split("::").last() {
                 return s.to_owned();
             }
@@ -1055,7 +1050,7 @@
                 ctx.target_pointer_size() as c_longlong
             }
             // Work-around https://bugs.llvm.org/show_bug.cgi?id=40813
-            CXType_Auto if self.is_non_deductible_auto_type() => return -6,
+            CXType_Auto if self.is_non_deductible_auto_type() => -6,
             _ => unsafe { clang_Type_getSizeOf(self.x) },
         }
     }
@@ -1068,7 +1063,7 @@
                 ctx.target_pointer_size() as c_longlong
             }
             // Work-around https://bugs.llvm.org/show_bug.cgi?id=40813
-            CXType_Auto if self.is_non_deductible_auto_type() => return -6,
+            CXType_Auto if self.is_non_deductible_auto_type() => -6,
             _ => unsafe { clang_Type_getAlignOf(self.x) },
         }
     }
@@ -1286,12 +1281,12 @@
         // nasty... But can happen in <type_traits>. Unfortunately I couldn't
         // reduce it enough :(
         self.template_args().map_or(false, |args| args.len() > 0) &&
-            match self.declaration().kind() {
+            !matches!(
+                self.declaration().kind(),
                 CXCursor_ClassTemplatePartialSpecialization |
-                CXCursor_TypeAliasTemplateDecl |
-                CXCursor_TemplateTemplateParameter => false,
-                _ => true,
-            }
+                    CXCursor_TypeAliasTemplateDecl |
+                    CXCursor_TemplateTemplateParameter
+            )
     }
 
     /// Is this type an associated template type? Eg `T::Associated` in
@@ -1704,11 +1699,7 @@
             Contents: contents.as_ptr(),
             Length: contents.as_bytes().len() as c_ulong,
         };
-        UnsavedFile {
-            x: x,
-            name: name,
-            contents: contents,
-        }
+        UnsavedFile { x, name, contents }
     }
 }
 
@@ -1819,7 +1810,7 @@
 
         if let Some(refd) = c.referenced() {
             if refd != *c {
-                println!("");
+                println!();
                 print_cursor(
                     depth,
                     String::from(prefix) + "referenced.",
@@ -1830,7 +1821,7 @@
 
         let canonical = c.canonical();
         if canonical != *c {
-            println!("");
+            println!();
             print_cursor(
                 depth,
                 String::from(prefix) + "canonical.",
@@ -1840,7 +1831,7 @@
 
         if let Some(specialized) = c.specialized() {
             if specialized != *c {
-                println!("");
+                println!();
                 print_cursor(
                     depth,
                     String::from(prefix) + "specialized.",
@@ -1850,7 +1841,7 @@
         }
 
         if let Some(parent) = c.fallible_semantic_parent() {
-            println!("");
+            println!();
             print_cursor(
                 depth,
                 String::from(prefix) + "semantic-parent.",
@@ -1898,34 +1889,34 @@
 
         let canonical = ty.canonical_type();
         if canonical != *ty {
-            println!("");
+            println!();
             print_type(depth, String::from(prefix) + "canonical.", &canonical);
         }
 
         if let Some(pointee) = ty.pointee_type() {
             if pointee != *ty {
-                println!("");
+                println!();
                 print_type(depth, String::from(prefix) + "pointee.", &pointee);
             }
         }
 
         if let Some(elem) = ty.elem_type() {
             if elem != *ty {
-                println!("");
+                println!();
                 print_type(depth, String::from(prefix) + "elements.", &elem);
             }
         }
 
         if let Some(ret) = ty.ret_type() {
             if ret != *ty {
-                println!("");
+                println!();
                 print_type(depth, String::from(prefix) + "return.", &ret);
             }
         }
 
         let named = ty.named();
         if named != *ty && named.is_valid() {
-            println!("");
+            println!();
             print_type(depth, String::from(prefix) + "named.", &named);
         }
     }
@@ -1933,13 +1924,13 @@
     print_indent(depth, "(");
     print_cursor(depth, "", c);
 
-    println!("");
+    println!();
     let ty = c.cur_type();
     print_type(depth, "type.", &ty);
 
     let declaration = ty.declaration();
     if declaration != *c && declaration.kind() != CXCursor_NoDeclFound {
-        println!("");
+        println!();
         print_cursor(depth, "type.declaration.", &declaration);
     }
 
@@ -1947,7 +1938,7 @@
     let mut found_children = false;
     c.visit(|s| {
         if !found_children {
-            println!("");
+            println!();
             found_children = true;
         }
         ast_dump(&s, depth + 1)
diff --git a/src/codegen/helpers.rs b/src/codegen/helpers.rs
index 205995b..2ce6894 100644
--- a/src/codegen/helpers.rs
+++ b/src/codegen/helpers.rs
@@ -230,14 +230,14 @@
     }
 
     pub fn byte_array_expr(bytes: &[u8]) -> TokenStream {
-        let mut bytes: Vec<_> = bytes.iter().cloned().collect();
+        let mut bytes: Vec<_> = bytes.to_vec();
         bytes.push(0);
         quote! { [ #(#bytes),* ] }
     }
 
     pub fn cstr_expr(mut string: String) -> TokenStream {
         string.push('\0');
-        let b = proc_macro2::Literal::byte_string(&string.as_bytes());
+        let b = proc_macro2::Literal::byte_string(string.as_bytes());
         quote! {
             #b
         }
@@ -271,7 +271,7 @@
         }
 
         warn!("Unknown non-finite float number: {:?}", f);
-        return Err(());
+        Err(())
     }
 
     pub fn arguments_from_signature(
diff --git a/src/codegen/impl_debug.rs b/src/codegen/impl_debug.rs
index 661711e..0e2cd33 100644
--- a/src/codegen/impl_debug.rs
+++ b/src/codegen/impl_debug.rs
@@ -2,7 +2,6 @@
 use crate::ir::context::BindgenContext;
 use crate::ir::item::{HasTypeParamInArray, IsOpaque, Item, ItemCanonicalName};
 use crate::ir::ty::{TypeKind, RUST_DERIVE_IN_ARRAY_LIMIT};
-use proc_macro2;
 
 pub fn gen_debug_impl(
     ctx: &BindgenContext,
@@ -23,8 +22,8 @@
             }
             CompKind::Struct => {
                 let processed_fields = fields.iter().filter_map(|f| match f {
-                    &Field::DataMember(ref fd) => fd.impl_debug(ctx, ()),
-                    &Field::Bitfields(ref bu) => bu.impl_debug(ctx, ()),
+                    Field::DataMember(ref fd) => fd.impl_debug(ctx, ()),
+                    Field::Bitfields(ref bu) => bu.impl_debug(ctx, ()),
                 });
 
                 for (i, (fstring, toks)) in processed_fields.enumerate() {
@@ -186,24 +185,22 @@
                 {
                     // The simple case
                     debug_print(name, quote! { #name_ident })
+                } else if ctx.options().use_core {
+                    // There is no String in core; reducing field visibility to avoid breaking
+                    // no_std setups.
+                    Some((format!("{}: [...]", name), vec![]))
                 } else {
-                    if ctx.options().use_core {
-                        // There is no String in core; reducing field visibility to avoid breaking
-                        // no_std setups.
-                        Some((format!("{}: [...]", name), vec![]))
-                    } else {
-                        // Let's implement our own print function
-                        Some((
-                            format!("{}: [{{}}]", name),
-                            vec![quote! {
-                                self.#name_ident
-                                    .iter()
-                                    .enumerate()
-                                    .map(|(i, v)| format!("{}{:?}", if i > 0 { ", " } else { "" }, v))
-                                    .collect::<String>()
-                            }],
-                        ))
-                    }
+                    // Let's implement our own print function
+                    Some((
+                        format!("{}: [{{}}]", name),
+                        vec![quote! {
+                            self.#name_ident
+                                .iter()
+                                .enumerate()
+                                .map(|(i, v)| format!("{}{:?}", if i > 0 { ", " } else { "" }, v))
+                                .collect::<String>()
+                        }],
+                    ))
                 }
             }
             TypeKind::Vector(_, len) => {
diff --git a/src/codegen/impl_partialeq.rs b/src/codegen/impl_partialeq.rs
index 5a1ba3f..960306f 100644
--- a/src/codegen/impl_partialeq.rs
+++ b/src/codegen/impl_partialeq.rs
@@ -2,7 +2,6 @@
 use crate::ir::context::BindgenContext;
 use crate::ir::item::{IsOpaque, Item};
 use crate::ir::ty::{TypeKind, RUST_DERIVE_IN_ARRAY_LIMIT};
-use proc_macro2;
 
 /// Generate a manual implementation of `PartialEq` trait for the
 /// specified compound type.
@@ -51,7 +50,7 @@
                 }
                 Field::Bitfields(ref bu) => {
                     for bitfield in bu.bitfields() {
-                        if let Some(_) = bitfield.name() {
+                        if bitfield.name().is_some() {
                             let getter_name = bitfield.getter_name();
                             let name_ident = ctx.rust_ident_raw(getter_name);
                             tokens.push(quote! {
@@ -104,7 +103,7 @@
         TypeKind::Opaque => quote_equals(name_ident),
 
         TypeKind::TemplateInstantiation(ref inst) => {
-            if inst.is_opaque(ctx, &ty_item) {
+            if inst.is_opaque(ctx, ty_item) {
                 quote! {
                     &self. #name_ident [..] == &other. #name_ident [..]
                 }
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 8858377..69dde2c 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -48,7 +48,6 @@
 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::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,
@@ -681,12 +680,11 @@
                     }
                 }
                 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 +696,7 @@
             }
         } 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 +754,6 @@
                 // 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 +883,9 @@
 
                 // 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 +1761,7 @@
 
                 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());
@@ -2126,11 +2120,11 @@
                                 })
                                 .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
@@ -2138,7 +2132,7 @@
                                                 #field_offset,
                                                 concat!("Offset of field: ", stringify!(#canonical_ident), "::", stringify!(#field_name))
                                             );
-                                        })
+                                        }
                                     })
                                 })
                                 .collect::<Vec<proc_macro2::TokenStream>>();
@@ -2348,7 +2342,7 @@
             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,
@@ -2414,7 +2408,7 @@
         }
 
         let mut exprs =
-            helpers::ast_ty::arguments_from_signature(&signature, ctx);
+            helpers::ast_ty::arguments_from_signature(signature, ctx);
 
         let mut stmts = vec![];
 
@@ -2471,8 +2465,7 @@
             #( #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
@@ -2513,19 +2506,13 @@
 
 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)
     }
 }
 
@@ -2603,10 +2590,7 @@
 
     /// 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
@@ -3027,7 +3011,7 @@
             let mut derives: Vec<_> = derives.into();
             for derive in item.annotations().derives().iter() {
                 if !derives.contains(&derive.as_str()) {
-                    derives.push(&derive);
+                    derives.push(derive);
                 }
             }
             attrs.push(attributes::derives(&derives));
@@ -3087,7 +3071,7 @@
 
         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)
             }
@@ -3646,13 +3630,12 @@
                     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()
@@ -3681,10 +3664,8 @@
                     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
@@ -3817,8 +3798,8 @@
         _: &(),
     ) -> 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 {
@@ -4060,12 +4041,12 @@
             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,
@@ -4657,7 +4638,7 @@
                     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, &())
                             };
diff --git a/src/codegen/struct_layout.rs b/src/codegen/struct_layout.rs
index 1c6b977..657be0b 100644
--- a/src/codegen/struct_layout.rs
+++ b/src/codegen/struct_layout.rs
@@ -279,6 +279,11 @@
             return None;
         }
 
+        // Padding doesn't make sense for rust unions.
+        if self.is_rust_union {
+            return None;
+        }
+
         if self.latest_offset == comp_layout.size {
             // This struct does not contain tail padding.
             return None;
@@ -428,6 +433,6 @@
 
         // Else, just align the obvious way.
         self.latest_offset += self.padding_bytes(layout);
-        return false;
+        false
     }
 }
diff --git a/src/ir/analysis/derive.rs b/src/ir/analysis/derive.rs
index 44e6702..f63458e 100644
--- a/src/ir/analysis/derive.rs
+++ b/src/ir/analysis/derive.rs
@@ -9,6 +9,7 @@
 use crate::ir::derive::CanDerive;
 use crate::ir::function::FunctionSig;
 use crate::ir::item::{IsOpaque, Item};
+use crate::ir::layout::Layout;
 use crate::ir::template::TemplateParameters;
 use crate::ir::traversal::{EdgeKind, Trace};
 use crate::ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
@@ -159,7 +160,7 @@
             return can_derive;
         }
 
-        if self.derive_trait.not_by_name(self.ctx, &item) {
+        if self.derive_trait.not_by_name(self.ctx, item) {
             trace!(
                 "    cannot derive {} for explicitly excluded type",
                 self.derive_trait
@@ -223,13 +224,13 @@
                 let inner_type =
                     self.ctx.resolve_type(inner).canonical_type(self.ctx);
                 if let TypeKind::Function(ref sig) = *inner_type.kind() {
-                    return self.derive_trait.can_derive_fnptr(sig);
+                    self.derive_trait.can_derive_fnptr(sig)
                 } else {
-                    return self.derive_trait.can_derive_pointer();
+                    self.derive_trait.can_derive_pointer()
                 }
             }
             TypeKind::Function(ref sig) => {
-                return self.derive_trait.can_derive_fnptr(sig)
+                self.derive_trait.can_derive_fnptr(sig)
             }
 
             // Complex cases need more information
@@ -255,7 +256,7 @@
                     return CanDerive::No;
                 }
 
-                if self.derive_trait.can_derive_large_array(&self.ctx) {
+                if self.derive_trait.can_derive_large_array(self.ctx) {
                     trace!("    array can derive {}", self.derive_trait);
                     return CanDerive::Yes;
                 }
@@ -270,7 +271,7 @@
                     "    array is small enough to derive {}",
                     self.derive_trait
                 );
-                return CanDerive::Yes;
+                CanDerive::Yes
             }
             TypeKind::Vector(t, len) => {
                 let inner_type =
@@ -285,7 +286,7 @@
                     return CanDerive::No;
                 }
                 assert_ne!(len, 0, "vectors cannot have zero length");
-                return self.derive_trait.can_derive_vector();
+                self.derive_trait.can_derive_vector()
             }
 
             TypeKind::Comp(ref info) => {
@@ -377,7 +378,7 @@
                 // Bitfield units are always represented as arrays of u8, but
                 // they're not traced as arrays, so we need to check here
                 // instead.
-                if !self.derive_trait.can_derive_large_array(&self.ctx) &&
+                if !self.derive_trait.can_derive_large_array(self.ctx) &&
                     info.has_too_large_bitfield_unit() &&
                     !item.is_opaque(self.ctx, &())
                 {
@@ -389,7 +390,7 @@
                 }
 
                 let pred = self.derive_trait.consider_edge_comp();
-                return self.constrain_join(item, pred);
+                self.constrain_join(item, pred)
             }
 
             TypeKind::ResolvedTypeRef(..) |
@@ -397,12 +398,12 @@
             TypeKind::Alias(..) |
             TypeKind::BlockPointer(..) => {
                 let pred = self.derive_trait.consider_edge_typeref();
-                return self.constrain_join(item, pred);
+                self.constrain_join(item, pred)
             }
 
             TypeKind::TemplateInstantiation(..) => {
                 let pred = self.derive_trait.consider_edge_tmpl_inst();
-                return self.constrain_join(item, pred);
+                self.constrain_join(item, pred)
             }
 
             TypeKind::Opaque => unreachable!(
@@ -470,10 +471,7 @@
     fn consider_edge_comp(&self) -> EdgePredicate {
         match self {
             DeriveTrait::PartialEqOrPartialOrd => consider_edge_default,
-            _ => |kind| match kind {
-                EdgeKind::BaseMember | EdgeKind::Field => true,
-                _ => false,
-            },
+            _ => |kind| matches!(kind, EdgeKind::BaseMember | EdgeKind::Field),
         }
     }
 
@@ -498,53 +496,35 @@
 
     fn can_derive_large_array(&self, ctx: &BindgenContext) -> bool {
         if ctx.options().rust_features().larger_arrays {
-            match self {
-                DeriveTrait::Default => false,
-                _ => true,
-            }
+            !matches!(self, DeriveTrait::Default)
         } else {
-            match self {
-                DeriveTrait::Copy => true,
-                _ => false,
-            }
+            matches!(self, DeriveTrait::Copy)
         }
     }
 
     fn can_derive_union(&self) -> bool {
-        match self {
-            DeriveTrait::Copy => true,
-            _ => false,
-        }
+        matches!(self, DeriveTrait::Copy)
     }
 
     fn can_derive_compound_with_destructor(&self) -> bool {
-        match self {
-            DeriveTrait::Copy => false,
-            _ => true,
-        }
+        !matches!(self, DeriveTrait::Copy)
     }
 
     fn can_derive_compound_with_vtable(&self) -> bool {
-        match self {
-            DeriveTrait::Default => false,
-            _ => true,
-        }
+        !matches!(self, DeriveTrait::Default)
     }
 
     fn can_derive_compound_forward_decl(&self) -> bool {
-        match self {
-            DeriveTrait::Copy | DeriveTrait::Debug => true,
-            _ => false,
-        }
+        matches!(self, DeriveTrait::Copy | DeriveTrait::Debug)
     }
 
     fn can_derive_incomplete_array(&self) -> bool {
-        match self {
+        !matches!(
+            self,
             DeriveTrait::Copy |
-            DeriveTrait::Hash |
-            DeriveTrait::PartialEqOrPartialOrd => false,
-            _ => true,
-        }
+                DeriveTrait::Hash |
+                DeriveTrait::PartialEqOrPartialOrd
+        )
     }
 
     fn can_derive_fnptr(&self, f: &FunctionSig) -> CanDerive {
@@ -693,10 +673,10 @@
             Some(ty) => {
                 let mut can_derive = self.constrain_type(item, ty);
                 if let CanDerive::Yes = can_derive {
-                    if !self.derive_trait.can_derive_large_array(&self.ctx) &&
-                        ty.layout(self.ctx).map_or(false, |l| {
-                            l.align > RUST_DERIVE_IN_ARRAY_LIMIT
-                        })
+                    let is_reached_limit =
+                        |l: Layout| l.align > RUST_DERIVE_IN_ARRAY_LIMIT;
+                    if !self.derive_trait.can_derive_large_array(self.ctx) &&
+                        ty.layout(self.ctx).map_or(false, is_reached_limit)
                     {
                         // We have to be conservative: the struct *could* have enough
                         // padding that we emit an array that is longer than
diff --git a/src/ir/analysis/has_destructor.rs b/src/ir/analysis/has_destructor.rs
index 5fa22e3..74fd73d 100644
--- a/src/ir/analysis/has_destructor.rs
+++ b/src/ir/analysis/has_destructor.rs
@@ -41,16 +41,16 @@
 
 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
-            // destructor or not.
+        // These are the only edges that can affect whether a type has a
+        // destructor or not.
+        matches!(
+            kind,
             EdgeKind::TypeReference |
-            EdgeKind::BaseMember |
-            EdgeKind::Field |
-            EdgeKind::TemplateArgument |
-            EdgeKind::TemplateDeclaration => true,
-            _ => false,
-        }
+                EdgeKind::BaseMember |
+                EdgeKind::Field |
+                EdgeKind::TemplateArgument |
+                EdgeKind::TemplateDeclaration
+        )
     }
 
     fn insert<Id: Into<ItemId>>(&mut self, id: Id) -> ConstrainResult {
diff --git a/src/ir/analysis/has_vtable.rs b/src/ir/analysis/has_vtable.rs
index 7f5f911..8ac47a6 100644
--- a/src/ir/analysis/has_vtable.rs
+++ b/src/ir/analysis/has_vtable.rs
@@ -79,14 +79,14 @@
 
 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
-            // vtable or not.
+        // These are the only edges that can affect whether a type has a
+        // vtable or not.
+        matches!(
+            kind,
             EdgeKind::TypeReference |
-            EdgeKind::BaseMember |
-            EdgeKind::TemplateDeclaration => true,
-            _ => false,
-        }
+                EdgeKind::BaseMember |
+                EdgeKind::TemplateDeclaration
+        )
     }
 
     fn insert<Id: Into<ItemId>>(
diff --git a/src/ir/analysis/mod.rs b/src/ir/analysis/mod.rs
index ec4d20f..eb9a1c0 100644
--- a/src/ir/analysis/mod.rs
+++ b/src/ir/analysis/mod.rs
@@ -184,7 +184,7 @@
     let mut dependencies = HashMap::default();
 
     for &item in ctx.allowlisted_items() {
-        dependencies.entry(item).or_insert(vec![]);
+        dependencies.entry(item).or_insert_with(Vec::new);
 
         {
             // We reverse our natural IR graph edges to find dependencies
@@ -197,7 +197,7 @@
                     {
                         dependencies
                             .entry(sub_item)
-                            .or_insert(vec![])
+                            .or_insert_with(Vec::new)
                             .push(item);
                     }
                 },
diff --git a/src/ir/analysis/sizedness.rs b/src/ir/analysis/sizedness.rs
index a3ef753..251c374 100644
--- a/src/ir/analysis/sizedness.rs
+++ b/src/ir/analysis/sizedness.rs
@@ -112,17 +112,17 @@
 
 impl<'ctx> SizednessAnalysis<'ctx> {
     fn consider_edge(kind: EdgeKind) -> bool {
-        match kind {
-            // These are the only edges that can affect whether a type is
-            // zero-sized or not.
+        // These are the only edges that can affect whether a type is
+        // zero-sized or not.
+        matches!(
+            kind,
             EdgeKind::TemplateArgument |
-            EdgeKind::TemplateParameterDefinition |
-            EdgeKind::TemplateDeclaration |
-            EdgeKind::TypeReference |
-            EdgeKind::BaseMember |
-            EdgeKind::Field => true,
-            _ => false,
-        }
+                EdgeKind::TemplateParameterDefinition |
+                EdgeKind::TemplateDeclaration |
+                EdgeKind::TypeReference |
+                EdgeKind::BaseMember |
+                EdgeKind::Field
+        )
     }
 
     /// Insert an incremental result, and return whether this updated our
diff --git a/src/ir/analysis/template_params.rs b/src/ir/analysis/template_params.rs
index c2f18b1..e88b774 100644
--- a/src/ir/analysis/template_params.rs
+++ b/src/ir/analysis/template_params.rs
@@ -239,7 +239,7 @@
 
         let args = instantiation
             .template_arguments()
-            .into_iter()
+            .iter()
             .map(|a| {
                 a.into_resolver()
                     .through_type_refs()
@@ -399,8 +399,8 @@
             .collect();
 
         for item in allowlisted_and_blocklisted_items {
-            dependencies.entry(item).or_insert(vec![]);
-            used.entry(item).or_insert(Some(ItemSet::new()));
+            dependencies.entry(item).or_insert_with(Vec::new);
+            used.entry(item).or_insert_with(|| Some(ItemSet::new()));
 
             {
                 // We reverse our natural IR graph edges to find dependencies
@@ -408,10 +408,11 @@
                 item.trace(
                     ctx,
                     &mut |sub_item: ItemId, _| {
-                        used.entry(sub_item).or_insert(Some(ItemSet::new()));
+                        used.entry(sub_item)
+                            .or_insert_with(|| Some(ItemSet::new()));
                         dependencies
                             .entry(sub_item)
-                            .or_insert(vec![])
+                            .or_insert_with(Vec::new)
                             .push(item);
                     },
                     &(),
@@ -421,39 +422,42 @@
             // Additionally, whether a template instantiation's template
             // arguments are used depends on whether the template declaration's
             // generic template parameters are used.
-            ctx.resolve_item(item).as_type().map(|ty| match ty.kind() {
-                &TypeKind::TemplateInstantiation(ref inst) => {
-                    let decl = ctx.resolve_type(inst.template_definition());
-                    let args = inst.template_arguments();
+            let item_kind =
+                ctx.resolve_item(item).as_type().map(|ty| ty.kind());
+            if let Some(&TypeKind::TemplateInstantiation(ref inst)) = item_kind
+            {
+                let decl = ctx.resolve_type(inst.template_definition());
+                let args = inst.template_arguments();
 
-                    // Although template definitions should always have
-                    // template parameters, there is a single exception:
-                    // opaque templates. Hence the unwrap_or.
-                    let params = decl.self_template_params(ctx);
+                // Although template definitions should always have
+                // template parameters, there is a single exception:
+                // opaque templates. Hence the unwrap_or.
+                let params = decl.self_template_params(ctx);
 
-                    for (arg, param) in args.iter().zip(params.iter()) {
-                        let arg = arg
-                            .into_resolver()
-                            .through_type_aliases()
-                            .through_type_refs()
-                            .resolve(ctx)
-                            .id();
+                for (arg, param) in args.iter().zip(params.iter()) {
+                    let arg = arg
+                        .into_resolver()
+                        .through_type_aliases()
+                        .through_type_refs()
+                        .resolve(ctx)
+                        .id();
 
-                        let param = param
-                            .into_resolver()
-                            .through_type_aliases()
-                            .through_type_refs()
-                            .resolve(ctx)
-                            .id();
+                    let param = param
+                        .into_resolver()
+                        .through_type_aliases()
+                        .through_type_refs()
+                        .resolve(ctx)
+                        .id();
 
-                        used.entry(arg).or_insert(Some(ItemSet::new()));
-                        used.entry(param).or_insert(Some(ItemSet::new()));
+                    used.entry(arg).or_insert_with(|| Some(ItemSet::new()));
+                    used.entry(param).or_insert_with(|| Some(ItemSet::new()));
 
-                        dependencies.entry(arg).or_insert(vec![]).push(param);
-                    }
+                    dependencies
+                        .entry(arg)
+                        .or_insert_with(Vec::new)
+                        .push(param);
                 }
-                _ => {}
-            });
+            }
         }
 
         if cfg!(feature = "testing_only_extra_assertions") {
@@ -482,10 +486,10 @@
         }
 
         UsedTemplateParameters {
-            ctx: ctx,
-            used: used,
-            dependencies: dependencies,
-            allowlisted_items: allowlisted_items,
+            ctx,
+            used,
+            dependencies,
+            allowlisted_items,
         }
     }
 
diff --git a/src/ir/annotations.rs b/src/ir/annotations.rs
index 4b571ea..9bcda50 100644
--- a/src/ir/annotations.rs
+++ b/src/ir/annotations.rs
@@ -25,7 +25,7 @@
 /// documentation:
 ///
 /// http://www.stack.nl/~dimitri/doxygen/manual/docblocks.html
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Default, Clone, PartialEq, Debug)]
 pub struct Annotations {
     /// Whether this item is marked as opaque. Only applies to types.
     opaque: bool,
@@ -77,24 +77,6 @@
     }
 }
 
-impl Default for Annotations {
-    fn default() -> Self {
-        Annotations {
-            opaque: false,
-            hide: false,
-            use_instead_of: None,
-            disallow_copy: false,
-            disallow_debug: false,
-            disallow_default: false,
-            must_use_type: false,
-            private_fields: None,
-            accessor_kind: None,
-            constify_enum_variant: false,
-            derives: vec![],
-        }
-    }
-}
-
 impl Annotations {
     /// Construct new annotations for the given cursor and its bindgen comments
     /// (if any).
@@ -143,7 +125,7 @@
     ///
     /// That is, code for `Foo` is used to generate `Bar`.
     pub fn use_instead_of(&self) -> Option<&[String]> {
-        self.use_instead_of.as_ref().map(|s| &**s)
+        self.use_instead_of.as_deref()
     }
 
     /// The list of derives that have been specified in this annotation.
diff --git a/src/ir/comment.rs b/src/ir/comment.rs
index 4ebe19a..c96e3eb 100644
--- a/src/ir/comment.rs
+++ b/src/ir/comment.rs
@@ -1,7 +1,5 @@
 //! Utilities for manipulating C/C++ comments.
 
-use std::iter;
-
 /// The type of a comment.
 #[derive(Debug, PartialEq, Eq)]
 enum Kind {
@@ -15,7 +13,7 @@
 
 /// Preprocesses a C/C++ comment so that it is a valid Rust comment.
 pub fn preprocess(comment: &str, indent: usize) -> String {
-    match self::kind(&comment) {
+    match self::kind(comment) {
         Some(Kind::SingleLines) => preprocess_single_lines(comment, indent),
         Some(Kind::MultiLine) => preprocess_multi_line(comment, indent),
         None => comment.to_owned(),
@@ -35,7 +33,7 @@
 
 fn make_indent(indent: usize) -> String {
     const RUST_INDENTATION: usize = 4;
-    iter::repeat(' ').take(indent * RUST_INDENTATION).collect()
+    " ".repeat(indent * RUST_INDENTATION)
 }
 
 /// Preprocesses multiple single line comments.
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
index 9798330..a221e52 100644
--- a/src/ir/comp.rs
+++ b/src/ir/comp.rs
@@ -111,11 +111,10 @@
 
     /// Is this a virtual method?
     pub fn is_virtual(&self) -> bool {
-        match self.kind {
-            MethodKind::Virtual { .. } |
-            MethodKind::VirtualDestructor { .. } => true,
-            _ => false,
-        }
+        matches!(
+            self.kind,
+            MethodKind::Virtual { .. } | MethodKind::VirtualDestructor { .. }
+        )
     }
 
     /// Is this a static method?
@@ -630,7 +629,7 @@
                         bitfield_unit_count,
                         unit_size_in_bits,
                         unit_align,
-                        mem::replace(&mut bitfields_in_unit, vec![]),
+                        mem::take(&mut bitfields_in_unit),
                         packed,
                     );
 
@@ -639,15 +638,12 @@
                     offset = 0;
                     unit_align = 0;
                 }
-            } else {
-                if offset != 0 &&
-                    (bitfield_width == 0 ||
-                        (offset & (bitfield_align * 8 - 1)) +
-                            bitfield_width >
-                            bitfield_size * 8)
-                {
-                    offset = align_to(offset, bitfield_align * 8);
-                }
+            } else if offset != 0 &&
+                (bitfield_width == 0 ||
+                    (offset & (bitfield_align * 8 - 1)) + bitfield_width >
+                        bitfield_size * 8)
+            {
+                offset = align_to(offset, bitfield_align * 8);
             }
         }
 
@@ -706,24 +702,24 @@
 /// after.
 #[derive(Debug)]
 enum CompFields {
-    BeforeComputingBitfieldUnits(Vec<RawField>),
-    AfterComputingBitfieldUnits {
+    Before(Vec<RawField>),
+    After {
         fields: Vec<Field>,
         has_bitfield_units: bool,
     },
-    ErrorComputingBitfieldUnits,
+    Error,
 }
 
 impl Default for CompFields {
     fn default() -> CompFields {
-        CompFields::BeforeComputingBitfieldUnits(vec![])
+        CompFields::Before(vec![])
     }
 }
 
 impl CompFields {
     fn append_raw_field(&mut self, raw: RawField) {
         match *self {
-            CompFields::BeforeComputingBitfieldUnits(ref mut raws) => {
+            CompFields::Before(ref mut raws) => {
                 raws.push(raw);
             }
             _ => {
@@ -736,9 +732,7 @@
 
     fn compute_bitfield_units(&mut self, ctx: &BindgenContext, packed: bool) {
         let raws = match *self {
-            CompFields::BeforeComputingBitfieldUnits(ref mut raws) => {
-                mem::replace(raws, vec![])
-            }
+            CompFields::Before(ref mut raws) => mem::take(raws),
             _ => {
                 panic!("Already computed bitfield units");
             }
@@ -748,25 +742,23 @@
 
         match result {
             Ok((fields, has_bitfield_units)) => {
-                *self = CompFields::AfterComputingBitfieldUnits {
+                *self = CompFields::After {
                     fields,
                     has_bitfield_units,
                 };
             }
             Err(()) => {
-                *self = CompFields::ErrorComputingBitfieldUnits;
+                *self = CompFields::Error;
             }
         }
     }
 
     fn deanonymize_fields(&mut self, ctx: &BindgenContext, methods: &[Method]) {
         let fields = match *self {
-            CompFields::AfterComputingBitfieldUnits {
-                ref mut fields, ..
-            } => fields,
+            CompFields::After { ref mut fields, .. } => fields,
             // Nothing to do here.
-            CompFields::ErrorComputingBitfieldUnits => return,
-            CompFields::BeforeComputingBitfieldUnits(_) => {
+            CompFields::Error => return,
+            CompFields::Before(_) => {
                 panic!("Not yet computed bitfield units.");
             }
         };
@@ -778,7 +770,7 @@
         ) -> bool {
             methods.iter().any(|method| {
                 let method_name = ctx.resolve_func(method.signature()).name();
-                method_name == name || ctx.rust_mangle(&method_name) == name
+                method_name == name || ctx.rust_mangle(method_name) == name
             })
         }
 
@@ -820,7 +812,7 @@
         for field in fields.iter_mut() {
             match *field {
                 Field::DataMember(FieldData { ref mut name, .. }) => {
-                    if let Some(_) = *name {
+                    if name.is_some() {
                         continue;
                     }
 
@@ -858,13 +850,13 @@
         T: Tracer,
     {
         match *self {
-            CompFields::ErrorComputingBitfieldUnits => {}
-            CompFields::BeforeComputingBitfieldUnits(ref fields) => {
+            CompFields::Error => {}
+            CompFields::Before(ref fields) => {
                 for f in fields {
                     tracer.visit_kind(f.ty().into(), EdgeKind::Field);
                 }
             }
-            CompFields::AfterComputingBitfieldUnits { ref fields, .. } => {
+            CompFields::After { ref fields, .. } => {
                 for f in fields {
                     f.trace(context, tracer, &());
                 }
@@ -900,7 +892,7 @@
 
 impl FieldMethods for FieldData {
     fn name(&self) -> Option<&str> {
-        self.name.as_ref().map(|n| &**n)
+        self.name.as_deref()
     }
 
     fn ty(&self) -> TypeId {
@@ -908,7 +900,7 @@
     }
 
     fn comment(&self) -> Option<&str> {
-        self.comment.as_ref().map(|c| &**c)
+        self.comment.as_deref()
     }
 
     fn bitfield_width(&self) -> Option<u32> {
@@ -1131,11 +1123,9 @@
     /// Get this type's set of fields.
     pub fn fields(&self) -> &[Field] {
         match self.fields {
-            CompFields::ErrorComputingBitfieldUnits => &[],
-            CompFields::AfterComputingBitfieldUnits { ref fields, .. } => {
-                fields
-            }
-            CompFields::BeforeComputingBitfieldUnits(..) => {
+            CompFields::Error => &[],
+            CompFields::After { ref fields, .. } => fields,
+            CompFields::Before(..) => {
                 panic!("Should always have computed bitfield units first");
             }
         }
@@ -1143,13 +1133,9 @@
 
     fn has_fields(&self) -> bool {
         match self.fields {
-            CompFields::ErrorComputingBitfieldUnits => false,
-            CompFields::AfterComputingBitfieldUnits { ref fields, .. } => {
-                !fields.is_empty()
-            }
-            CompFields::BeforeComputingBitfieldUnits(ref raw_fields) => {
-                !raw_fields.is_empty()
-            }
+            CompFields::Error => false,
+            CompFields::After { ref fields, .. } => !fields.is_empty(),
+            CompFields::Before(ref raw_fields) => !raw_fields.is_empty(),
         }
     }
 
@@ -1159,15 +1145,15 @@
         mut callback: impl FnMut(Layout),
     ) {
         match self.fields {
-            CompFields::ErrorComputingBitfieldUnits => return,
-            CompFields::AfterComputingBitfieldUnits { ref fields, .. } => {
+            CompFields::Error => {}
+            CompFields::After { ref fields, .. } => {
                 for field in fields.iter() {
                     if let Some(layout) = field.layout(ctx) {
                         callback(layout);
                     }
                 }
             }
-            CompFields::BeforeComputingBitfieldUnits(ref raw_fields) => {
+            CompFields::Before(ref raw_fields) => {
                 for field in raw_fields.iter() {
                     let field_ty = ctx.resolve_type(field.0.ty);
                     if let Some(layout) = field_ty.layout(ctx) {
@@ -1180,12 +1166,11 @@
 
     fn has_bitfields(&self) -> bool {
         match self.fields {
-            CompFields::ErrorComputingBitfieldUnits => false,
-            CompFields::AfterComputingBitfieldUnits {
-                has_bitfield_units,
-                ..
+            CompFields::Error => false,
+            CompFields::After {
+                has_bitfield_units, ..
             } => has_bitfield_units,
-            CompFields::BeforeComputingBitfieldUnits(_) => {
+            CompFields::Before(_) => {
                 panic!("Should always have computed bitfield units first");
             }
         }
@@ -1776,7 +1761,7 @@
         // is a type parameter), then we can't compute bitfield units. We are
         // left with no choice but to make the whole struct opaque, or else we
         // might generate structs with incorrect sizes and alignments.
-        if let CompFields::ErrorComputingBitfieldUnits = self.fields {
+        if let CompFields::Error = self.fields {
             return true;
         }
 
diff --git a/src/ir/context.rs b/src/ir/context.rs
index 44df063..874fb5d 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -299,7 +299,7 @@
 /// types.
 #[derive(Eq, PartialEq, Hash, Debug)]
 enum TypeKey {
-    USR(String),
+    Usr(String),
     Declaration(Cursor),
 }
 
@@ -640,7 +640,7 @@
 
     /// Get the user-provided callbacks by reference, if any.
     pub fn parse_callbacks(&self) -> Option<&dyn ParseCallbacks> {
-        self.options().parse_callbacks.as_ref().map(|t| &**t)
+        self.options().parse_callbacks.as_deref()
     }
 
     /// Add another path to the set of included files.
@@ -702,8 +702,10 @@
         // Unnamed items can have an USR, but they can't be referenced from
         // other sites explicitly and the USR can match if the unnamed items are
         // nested, so don't bother tracking them.
-        if is_type && !is_template_instantiation && declaration.is_some() {
-            let mut declaration = declaration.unwrap();
+        if !is_type || is_template_instantiation {
+            return;
+        }
+        if let Some(mut declaration) = declaration {
             if !declaration.is_valid() {
                 if let Some(location) = location {
                     if location.is_template_like() {
@@ -732,7 +734,7 @@
             let key = if is_unnamed {
                 TypeKey::Declaration(declaration)
             } else if let Some(usr) = declaration.usr() {
-                TypeKey::USR(usr)
+                TypeKey::Usr(usr)
             } else {
                 warn!(
                     "Valid declaration with no USR: {:?}, {:?}",
@@ -829,31 +831,32 @@
     // TODO: Move all this syntax crap to other part of the code.
 
     /// Mangles a name so it doesn't conflict with any keyword.
+    #[rustfmt::skip]
     pub fn rust_mangle<'a>(&self, name: &'a str) -> Cow<'a, str> {
-        if name.contains("@") ||
-            name.contains("?") ||
-            name.contains("$") ||
-            match name {
+        if name.contains('@') ||
+            name.contains('?') ||
+            name.contains('$') ||
+            matches!(
+                name,
                 "abstract" | "alignof" | "as" | "async" | "become" |
-                "box" | "break" | "const" | "continue" | "crate" | "do" |
-                "dyn" | "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" | "str" | "bool" | "f32" | "f64" |
-                "usize" | "isize" | "u128" | "i128" | "u64" | "i64" |
-                "u32" | "i32" | "u16" | "i16" | "u8" | "i8" | "_" => true,
-                _ => false,
-            }
+                    "box" | "break" | "const" | "continue" | "crate" | "do" |
+                    "dyn" | "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" | "str" | "bool" | "f32" | "f64" |
+                    "usize" | "isize" | "u128" | "i128" | "u64" | "i64" |
+                    "u32" | "i32" | "u16" | "i16" | "u8" | "i8" | "_"
+            )
         {
             let mut s = name.to_owned();
             s = s.replace("@", "_");
             s = s.replace("?", "_");
             s = s.replace("$", "_");
-            s.push_str("_");
+            s.push('_');
             return Cow::Owned(s);
         }
         Cow::Borrowed(name)
@@ -903,11 +906,10 @@
                 None => continue,
             };
 
-            match *ty.kind() {
-                TypeKind::UnresolvedTypeRef(ref ty, loc, parent_id) => {
-                    typerefs.push((id, ty.clone(), loc, parent_id));
-                }
-                _ => {}
+            if let TypeKind::UnresolvedTypeRef(ref ty, loc, parent_id) =
+                *ty.kind()
+            {
+                typerefs.push((id, *ty, loc, parent_id));
             };
         }
         typerefs
@@ -978,7 +980,7 @@
         assert!(self.collected_typerefs());
 
         let need_bitfield_allocation =
-            mem::replace(&mut self.need_bitfield_allocation, vec![]);
+            mem::take(&mut self.need_bitfield_allocation);
         for id in need_bitfield_allocation {
             self.with_loaned_item(id, |ctx, item| {
                 let ty = item.kind_mut().as_type_mut().unwrap();
@@ -1121,7 +1123,8 @@
                     .ancestors(immut_self)
                     .find(|id| immut_self.resolve_item(*id).is_module())
             };
-            let new_module = new_module.unwrap_or(self.root_module.into());
+            let new_module =
+                new_module.unwrap_or_else(|| self.root_module.into());
 
             if new_module == old_module {
                 // Already in the correct module.
@@ -1329,12 +1332,12 @@
             // any sense of template parameter usage, and you're on your own.
             let mut used_params = HashMap::default();
             for &id in self.allowlisted_items() {
-                used_params.entry(id).or_insert(
+                used_params.entry(id).or_insert_with(|| {
                     id.self_template_params(self)
                         .into_iter()
                         .map(|p| p.into())
-                        .collect(),
-                );
+                        .collect()
+                });
             }
             self.used_template_parameters = Some(used_params);
         }
@@ -1815,7 +1818,7 @@
             .or_else(|| {
                 decl.cursor()
                     .usr()
-                    .and_then(|usr| self.types.get(&TypeKey::USR(usr)))
+                    .and_then(|usr| self.types.get(&TypeKey::Usr(usr)))
             })
             .cloned()
     }
@@ -1848,32 +1851,32 @@
                 //     of it, or
                 //   * we have already parsed and resolved this type, and
                 //     there's nothing left to do.
-                if decl.cursor().is_template_like() &&
-                    *ty != decl.cursor().cur_type() &&
-                    location.is_some()
-                {
-                    let location = location.unwrap();
-
-                    // For specialized type aliases, there's no way to get the
-                    // template parameters as of this writing (for a struct
-                    // specialization we wouldn't be in this branch anyway).
-                    //
-                    // Explicitly return `None` if there aren't any
-                    // unspecialized parameters (contains any `TypeRef`) so we
-                    // resolve the canonical type if there is one and it's
-                    // exposed.
-                    //
-                    // This is _tricky_, I know :(
-                    if decl.cursor().kind() == CXCursor_TypeAliasTemplateDecl &&
-                        !location.contains_cursor(CXCursor_TypeRef) &&
-                        ty.canonical_type().is_valid_and_exposed()
+                if let Some(location) = location {
+                    if decl.cursor().is_template_like() &&
+                        *ty != decl.cursor().cur_type()
                     {
-                        return None;
-                    }
+                        // For specialized type aliases, there's no way to get the
+                        // template parameters as of this writing (for a struct
+                        // specialization we wouldn't be in this branch anyway).
+                        //
+                        // Explicitly return `None` if there aren't any
+                        // unspecialized parameters (contains any `TypeRef`) so we
+                        // resolve the canonical type if there is one and it's
+                        // exposed.
+                        //
+                        // This is _tricky_, I know :(
+                        if decl.cursor().kind() ==
+                            CXCursor_TypeAliasTemplateDecl &&
+                            !location.contains_cursor(CXCursor_TypeRef) &&
+                            ty.canonical_type().is_valid_and_exposed()
+                        {
+                            return None;
+                        }
 
-                    return self
-                        .instantiate_template(with_id, id, ty, location)
-                        .or_else(|| Some(id));
+                        return self
+                            .instantiate_template(with_id, id, ty, location)
+                            .or(Some(id));
+                    }
                 }
 
                 return Some(self.build_ty_wrapper(with_id, id, parent_id, ty));
@@ -1933,7 +1936,7 @@
             with_id,
             None,
             None,
-            parent_id.unwrap_or(self.current_module.into()),
+            parent_id.unwrap_or_else(|| self.current_module.into()),
             ItemKind::Type(ty),
         );
         self.add_builtin_item(item);
@@ -2074,10 +2077,7 @@
         id: Id,
     ) -> bool {
         let id = id.into();
-        match self.replacements.get(path) {
-            Some(replaced_by) if *replaced_by != id => true,
-            _ => false,
-        }
+        matches!(self.replacements.get(path), Some(replaced_by) if *replaced_by != id)
     }
 
     /// Is the type with the given `name` marked as opaque?
@@ -2112,11 +2112,9 @@
             module_name = Some(spelling)
         }
 
-        let tokens = cursor.tokens();
-        let mut iter = tokens.iter();
         let mut kind = ModuleKind::Normal;
         let mut found_namespace_keyword = false;
-        while let Some(token) = iter.next() {
+        for token in cursor.tokens().iter() {
             match token.spelling() {
                 b"inline" => {
                     assert!(!found_namespace_keyword);
@@ -2399,7 +2397,7 @@
         let codegen_items = if self.options().allowlist_recursively {
             AllowlistedItemsTraversal::new(
                 self,
-                roots.clone(),
+                roots,
                 traversal::codegen_edges,
             )
             .collect::<ItemSet>()
@@ -2700,7 +2698,7 @@
     pub fn new<Id: Into<ItemId>>(id: Id) -> ItemResolver {
         let id = id.into();
         ItemResolver {
-            id: id,
+            id,
             through_type_refs: false,
             through_type_aliases: false,
         }
@@ -2767,7 +2765,7 @@
     /// Construct a new `PartialType`.
     pub fn new(decl: Cursor, id: ItemId) -> PartialType {
         // assert!(decl == decl.canonical());
-        PartialType { decl: decl, id: id }
+        PartialType { decl, id }
     }
 
     /// The cursor pointing to this partial type's declaration location.
diff --git a/src/ir/enum_ty.rs b/src/ir/enum_ty.rs
index 15d4136..97455c9 100644
--- a/src/ir/enum_ty.rs
+++ b/src/ir/enum_ty.rs
@@ -86,7 +86,7 @@
         } else {
             Some(type_name)
         };
-        let type_name = type_name.as_ref().map(String::as_str);
+        let type_name = type_name.as_deref();
 
         let definition = declaration.definition().unwrap_or(declaration);
         definition.visit(|cursor| {
@@ -286,7 +286,7 @@
 
     /// Get this variant's documentation.
     pub fn comment(&self) -> Option<&str> {
-        self.comment.as_ref().map(|s| &**s)
+        self.comment.as_deref()
     }
 
     /// Returns whether this variant should be enforced to be a constant by code
diff --git a/src/ir/function.rs b/src/ir/function.rs
index 661ee59..a3a2bbf 100644
--- a/src/ir/function.rs
+++ b/src/ir/function.rs
@@ -123,7 +123,7 @@
 
     /// Get this function's name.
     pub fn mangled_name(&self) -> Option<&str> {
-        self.mangled_name.as_ref().map(|n| &**n)
+        self.mangled_name.as_deref()
     }
 
     /// Get this function's signature type.
@@ -187,10 +187,7 @@
 impl Abi {
     /// Returns whether this Abi is known or not.
     fn is_unknown(&self) -> bool {
-        match *self {
-            Abi::Unknown(..) => true,
-            _ => false,
-        }
+        matches!(*self, Abi::Unknown(..))
     }
 }
 
@@ -340,7 +337,7 @@
             });
 
             let cursor = arg_cur.unwrap_or(*cursor);
-            let ty = arg_ty.unwrap_or(cursor.cur_type());
+            let ty = arg_ty.unwrap_or_else(|| cursor.cur_type());
             (name, Item::from_ty_or_ref(ty, cursor, None, ctx))
         })
         .collect()
@@ -360,7 +357,7 @@
             argument_types,
             is_variadic,
             must_use,
-            abi: abi,
+            abi,
         }
     }
 
@@ -411,7 +408,7 @@
             CXCursor_CXXMethod |
             CXCursor_ObjCInstanceMethodDecl |
             CXCursor_ObjCClassMethodDecl => {
-                args_from_ty_and_cursor(&ty, &cursor, ctx)
+                args_from_ty_and_cursor(ty, &cursor, ctx)
             }
             _ => {
                 // For non-CXCursor_FunctionDecl, visiting the cursor's children
@@ -434,7 +431,7 @@
                     // right AST for functions tagged as stdcall and such...
                     //
                     // https://bugs.llvm.org/show_bug.cgi?id=45919
-                    args_from_ty_and_cursor(&ty, &cursor, ctx)
+                    args_from_ty_and_cursor(ty, &cursor, ctx)
                 } else {
                     args
                 }
@@ -522,7 +519,7 @@
             warn!("Unknown calling convention: {:?}", call_conv);
         }
 
-        Ok(Self::new(ret.into(), args, ty.is_variadic(), must_use, abi))
+        Ok(Self::new(ret, args, ty.is_variadic(), must_use, abi))
     }
 
     /// Get this function signature's return type.
@@ -567,10 +564,7 @@
             return false;
         }
 
-        match self.abi {
-            Abi::C | Abi::Unknown(..) => true,
-            _ => false,
-        }
+        matches!(self.abi, Abi::C | Abi::Unknown(..))
     }
 }
 
diff --git a/src/ir/item.rs b/src/ir/item.rs
index a38c8e5..730271e 100644
--- a/src/ir/item.rs
+++ b/src/ir/item.rs
@@ -436,15 +436,15 @@
     ) -> Self {
         debug_assert!(id != parent_id || kind.is_module());
         Item {
-            id: id,
+            id,
             local_id: LazyCell::new(),
             next_child_local_id: Cell::new(1),
             canonical_name: LazyCell::new(),
             path_for_allowlisting: LazyCell::new(),
-            parent_id: parent_id,
-            comment: comment,
+            parent_id,
+            comment,
             annotations: annotations.unwrap_or_default(),
-            kind: kind,
+            kind,
         }
     }
 
@@ -612,10 +612,7 @@
 
     /// Is this item a module?
     pub fn is_module(&self) -> bool {
-        match self.kind {
-            ItemKind::Module(..) => true,
-            _ => false,
-        }
+        matches!(self.kind, ItemKind::Module(..))
     }
 
     /// Get this item's annotations.
@@ -641,7 +638,7 @@
             match self.kind {
                 ItemKind::Type(..) => {
                     ctx.options().blocklisted_types.matches(&name) ||
-                        ctx.is_replaced_type(&path, self.id)
+                        ctx.is_replaced_type(path, self.id)
                 }
                 ItemKind::Function(..) => {
                     ctx.options().blocklisted_functions.matches(&name)
@@ -658,10 +655,7 @@
 
     /// Is this item a var type?
     pub fn is_var(&self) -> bool {
-        match *self.kind() {
-            ItemKind::Var(..) => true,
-            _ => false,
-        }
+        matches!(*self.kind(), ItemKind::Var(..))
     }
 
     /// Take out item NameOptions
@@ -722,7 +716,7 @@
                         .through_type_refs()
                         .resolve(ctx)
                         .push_disambiguated_name(ctx, to, level + 1);
-                    to.push_str("_");
+                    to.push('_');
                 }
                 to.push_str(&format!("close{}", level));
             }
@@ -835,7 +829,7 @@
             if ctx.options().enable_cxx_namespaces {
                 return path.last().unwrap().clone();
             }
-            return path.join("_").to_owned();
+            return path.join("_");
         }
 
         let base_name = target.base_name(ctx);
@@ -873,7 +867,7 @@
 
             // If target is anonymous we need find its first named ancestor.
             if target.is_anon() {
-                while let Some(id) = ids_iter.next() {
+                for id in ids_iter.by_ref() {
                     ids.push(id);
 
                     if !ctx.resolve_item(id).is_anon() {
@@ -1104,7 +1098,7 @@
         );
         self.annotations.opaque() ||
             self.as_type().map_or(false, |ty| ty.is_opaque(ctx, self)) ||
-            ctx.opaque_by_name(&self.path_for_allowlisting(ctx))
+            ctx.opaque_by_name(self.path_for_allowlisting(ctx))
     }
 }
 
@@ -1114,20 +1108,16 @@
 {
     fn has_vtable(&self, ctx: &BindgenContext) -> bool {
         let id: ItemId = (*self).into();
-        id.as_type_id(ctx)
-            .map_or(false, |id| match ctx.lookup_has_vtable(id) {
-                HasVtableResult::No => false,
-                _ => true,
-            })
+        id.as_type_id(ctx).map_or(false, |id| {
+            !matches!(ctx.lookup_has_vtable(id), HasVtableResult::No)
+        })
     }
 
     fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool {
         let id: ItemId = (*self).into();
-        id.as_type_id(ctx)
-            .map_or(false, |id| match ctx.lookup_has_vtable(id) {
-                HasVtableResult::SelfHasVtable => true,
-                _ => false,
-            })
+        id.as_type_id(ctx).map_or(false, |id| {
+            matches!(ctx.lookup_has_vtable(id), HasVtableResult::SelfHasVtable)
+        })
     }
 }
 
@@ -1392,7 +1382,7 @@
                     }
                     ctx.known_semantic_parent(definition)
                         .or(parent_id)
-                        .unwrap_or(ctx.current_module().into())
+                        .unwrap_or_else(|| ctx.current_module().into())
                 }
                 None => relevant_parent_id,
             };
@@ -1524,7 +1514,7 @@
                 potential_id,
                 None,
                 None,
-                parent_id.unwrap_or(current_module.into()),
+                parent_id.unwrap_or_else(|| current_module.into()),
                 ItemKind::Type(Type::new(None, None, kind, is_const)),
             ),
             None,
@@ -1603,7 +1593,7 @@
             Annotations::new(&decl).or_else(|| Annotations::new(&location));
 
         if let Some(ref annotations) = annotations {
-            if let Some(ref replaced) = annotations.use_instead_of() {
+            if let Some(replaced) = annotations.use_instead_of() {
                 ctx.replace(replaced, id);
             }
         }
@@ -1851,11 +1841,7 @@
                 clang_sys::CXChildVisit_Continue
             });
 
-            if let Some(def) = definition {
-                def
-            } else {
-                return None;
-            }
+            definition?
         };
         assert!(is_template_with_spelling(&definition, &ty_spelling));
 
@@ -1939,7 +1925,7 @@
             path.push(CONSTIFIED_ENUM_MODULE_REPR_NAME.into());
         }
 
-        return path;
+        path
     }
 
     fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> {
@@ -1972,8 +1958,8 @@
     /// Construct a new `NameOptions`
     pub fn new(item: &'a Item, ctx: &'a BindgenContext) -> Self {
         NameOptions {
-            item: item,
-            ctx: ctx,
+            item,
+            ctx,
             within_namespaces: false,
             user_mangled: UserMangled::Yes,
         }
diff --git a/src/ir/layout.rs b/src/ir/layout.rs
index 28a6604..6cf9113 100644
--- a/src/ir/layout.rs
+++ b/src/ir/layout.rs
@@ -64,7 +64,7 @@
             next_align *= 2;
         }
         Layout {
-            size: size,
+            size,
             align: next_align / 2,
             packed: false,
         }
diff --git a/src/ir/module.rs b/src/ir/module.rs
index 13b7c19..d5aca94 100644
--- a/src/ir/module.rs
+++ b/src/ir/module.rs
@@ -32,15 +32,15 @@
     /// Construct a new `Module`.
     pub fn new(name: Option<String>, kind: ModuleKind) -> Self {
         Module {
-            name: name,
-            kind: kind,
+            name,
+            kind,
             children: ItemSet::new(),
         }
     }
 
     /// Get this module's name.
     pub fn name(&self) -> Option<&str> {
-        self.name.as_ref().map(|n| &**n)
+        self.name.as_deref()
     }
 
     /// Get a mutable reference to this module's children.
diff --git a/src/ir/objc.rs b/src/ir/objc.rs
index 91855c6..0845ad0 100644
--- a/src/ir/objc.rs
+++ b/src/ir/objc.rs
@@ -89,12 +89,10 @@
     pub fn rust_name(&self) -> String {
         if let Some(ref cat) = self.category {
             format!("{}_{}", self.name(), cat)
+        } else if self.is_protocol {
+            format!("P{}", self.name())
         } else {
-            if self.is_protocol {
-                format!("P{}", self.name())
-            } else {
-                format!("I{}", self.name().to_owned())
-            }
+            format!("I{}", self.name().to_owned())
         }
     }
 
@@ -149,28 +147,34 @@
                     // Gather protocols this interface conforms to
                     let needle = format!("P{}", c.spelling());
                     let items_map = ctx.items();
-                    debug!("Interface {} conforms to {}, find the item", interface.name, needle);
+                    debug!(
+                        "Interface {} conforms to {}, find the item",
+                        interface.name, needle
+                    );
 
-                    for (id, item) in items_map
-                    {
+                    for (id, item) in items_map {
                         if let Some(ty) = item.as_type() {
-                            match *ty.kind() {
-                                TypeKind::ObjCInterface(ref protocol) => {
-                                    if protocol.is_protocol
-                                    {
-                                        debug!("Checking protocol {}, ty.name {:?}", protocol.name, ty.name());
-                                        if Some(needle.as_ref()) == ty.name() {
-                                            debug!("Found conforming protocol {:?}", item);
-                                            interface.conforms_to.push(id);
-                                            break;
-                                        }
+                            if let TypeKind::ObjCInterface(ref protocol) =
+                                *ty.kind()
+                            {
+                                if protocol.is_protocol {
+                                    debug!(
+                                        "Checking protocol {}, ty.name {:?}",
+                                        protocol.name,
+                                        ty.name()
+                                    );
+                                    if Some(needle.as_ref()) == ty.name() {
+                                        debug!(
+                                            "Found conforming protocol {:?}",
+                                            item
+                                        );
+                                        interface.conforms_to.push(id);
+                                        break;
                                     }
                                 }
-                                _ => {}
                             }
                         }
                     }
-
                 }
                 CXCursor_ObjCInstanceMethodDecl |
                 CXCursor_ObjCClassMethodDecl => {
@@ -178,8 +182,10 @@
                     let signature =
                         FunctionSig::from_ty(&c.cur_type(), &c, ctx)
                             .expect("Invalid function sig");
-                    let is_class_method = c.kind() == CXCursor_ObjCClassMethodDecl;
-                    let method = ObjCMethod::new(&name, signature, is_class_method);
+                    let is_class_method =
+                        c.kind() == CXCursor_ObjCClassMethodDecl;
+                    let method =
+                        ObjCMethod::new(&name, signature, is_class_method);
                     interface.add_method(method);
                 }
                 CXCursor_TemplateTypeParameter => {
@@ -189,7 +195,7 @@
                 CXCursor_ObjCSuperClassRef => {
                     let item = Item::from_ty_or_ref(c.cur_type(), c, None, ctx);
                     interface.parent_class = Some(item.into());
-                },
+                }
                 _ => {}
             }
             CXChildVisit_Continue
@@ -218,7 +224,7 @@
 
         ObjCMethod {
             name: name.to_owned(),
-            rust_name: rust_name.to_owned(),
+            rust_name,
             signature,
             is_class_method,
         }
@@ -261,7 +267,7 @@
             .collect();
 
         // No arguments
-        if args.len() == 0 && split_name.len() == 1 {
+        if args.is_empty() && split_name.len() == 1 {
             let name = &split_name[0];
             return quote! {
                 #name
@@ -269,13 +275,12 @@
         }
 
         // Check right amount of arguments
-        if args.len() != split_name.len() - 1 {
-            panic!(
-                "Incorrect method name or arguments for objc method, {:?} vs {:?}",
-                args,
-                split_name,
-            );
-        }
+        assert!(
+            args.len() == split_name.len() - 1,
+            "Incorrect method name or arguments for objc method, {:?} vs {:?}",
+            args,
+            split_name
+        );
 
         // Get arguments without type signatures to pass to `msg_send!`
         let mut args_without_types = vec![];
diff --git a/src/ir/template.rs b/src/ir/template.rs
index b519fff..8b06748 100644
--- a/src/ir/template.rs
+++ b/src/ir/template.rs
@@ -134,10 +134,10 @@
     where
         Self: ItemAncestors,
     {
-        let ancestors: Vec<_> = self.ancestors(ctx).collect();
+        let mut ancestors: Vec<_> = self.ancestors(ctx).collect();
+        ancestors.reverse();
         ancestors
             .into_iter()
-            .rev()
             .flat_map(|id| id.self_template_params(ctx).into_iter())
             .collect()
     }
diff --git a/src/ir/traversal.rs b/src/ir/traversal.rs
index 430dd02..088e744 100644
--- a/src/ir/traversal.rs
+++ b/src/ir/traversal.rs
@@ -24,9 +24,9 @@
     }
 }
 
-impl Into<ItemId> for Edge {
-    fn into(self) -> ItemId {
-        self.to
+impl From<Edge> for ItemId {
+    fn from(val: Edge) -> Self {
+        val.to
     }
 }
 
@@ -424,10 +424,10 @@
         }
 
         ItemTraversal {
-            ctx: ctx,
-            seen: seen,
-            queue: queue,
-            predicate: predicate,
+            ctx,
+            seen,
+            queue,
+            predicate,
             currently_traversing: None,
         }
     }
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index e049ed6..d573408 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -87,23 +87,17 @@
 
     /// Get this type's name.
     pub fn name(&self) -> Option<&str> {
-        self.name.as_ref().map(|name| &**name)
+        self.name.as_deref()
     }
 
     /// Whether this is a block pointer type.
     pub fn is_block_pointer(&self) -> bool {
-        match self.kind {
-            TypeKind::BlockPointer(..) => true,
-            _ => false,
-        }
+        matches!(self.kind, TypeKind::BlockPointer(..))
     }
 
     /// Is this a compound type?
     pub fn is_comp(&self) -> bool {
-        match self.kind {
-            TypeKind::Comp(..) => true,
-            _ => false,
-        }
+        matches!(self.kind, TypeKind::Comp(..))
     }
 
     /// Is this a union?
@@ -116,58 +110,43 @@
 
     /// Is this type of kind `TypeKind::TypeParam`?
     pub fn is_type_param(&self) -> bool {
-        match self.kind {
-            TypeKind::TypeParam => true,
-            _ => false,
-        }
+        matches!(self.kind, TypeKind::TypeParam)
     }
 
     /// Is this a template instantiation type?
     pub fn is_template_instantiation(&self) -> bool {
-        match self.kind {
-            TypeKind::TemplateInstantiation(..) => true,
-            _ => false,
-        }
+        matches!(self.kind, TypeKind::TemplateInstantiation(..))
     }
 
     /// Is this a template alias type?
     pub fn is_template_alias(&self) -> bool {
-        match self.kind {
-            TypeKind::TemplateAlias(..) => true,
-            _ => false,
-        }
+        matches!(self.kind, TypeKind::TemplateAlias(..))
     }
 
     /// Is this a function type?
     pub fn is_function(&self) -> bool {
-        match self.kind {
-            TypeKind::Function(..) => true,
-            _ => false,
-        }
+        matches!(self.kind, TypeKind::Function(..))
     }
 
     /// Is this an enum type?
     pub fn is_enum(&self) -> bool {
-        match self.kind {
-            TypeKind::Enum(..) => true,
-            _ => false,
-        }
+        matches!(self.kind, TypeKind::Enum(..))
     }
 
     /// Is this either a builtin or named type?
     pub fn is_builtin_or_type_param(&self) -> bool {
-        match self.kind {
+        matches!(
+            self.kind,
             TypeKind::Void |
-            TypeKind::NullPtr |
-            TypeKind::Function(..) |
-            TypeKind::Array(..) |
-            TypeKind::Reference(..) |
-            TypeKind::Pointer(..) |
-            TypeKind::Int(..) |
-            TypeKind::Float(..) |
-            TypeKind::TypeParam => true,
-            _ => false,
-        }
+                TypeKind::NullPtr |
+                TypeKind::Function(..) |
+                TypeKind::Array(..) |
+                TypeKind::Reference(..) |
+                TypeKind::Pointer(..) |
+                TypeKind::Int(..) |
+                TypeKind::Float(..) |
+                TypeKind::TypeParam
+        )
     }
 
     /// Creates a new named type, with name `name`.
@@ -178,26 +157,17 @@
 
     /// Is this a floating point type?
     pub fn is_float(&self) -> bool {
-        match self.kind {
-            TypeKind::Float(..) => true,
-            _ => false,
-        }
+        matches!(self.kind, TypeKind::Float(..))
     }
 
     /// Is this a boolean type?
     pub fn is_bool(&self) -> bool {
-        match self.kind {
-            TypeKind::Int(IntKind::Bool) => true,
-            _ => false,
-        }
+        matches!(self.kind, TypeKind::Int(IntKind::Bool))
     }
 
     /// Is this an integer type?
     pub fn is_integer(&self) -> bool {
-        match self.kind {
-            TypeKind::Int(..) => true,
-            _ => false,
-        }
+        matches!(self.kind, TypeKind::Int(..))
     }
 
     /// Cast this type to an integer kind, or `None` if it is not an integer
@@ -216,19 +186,15 @@
 
     /// Is this a reference to another type?
     pub fn is_type_ref(&self) -> bool {
-        match self.kind {
-            TypeKind::ResolvedTypeRef(_) |
-            TypeKind::UnresolvedTypeRef(_, _, _) => true,
-            _ => false,
-        }
+        matches!(
+            self.kind,
+            TypeKind::ResolvedTypeRef(_) | TypeKind::UnresolvedTypeRef(_, _, _)
+        )
     }
 
     /// Is this an unresolved reference?
     pub fn is_unresolved_ref(&self) -> bool {
-        match self.kind {
-            TypeKind::UnresolvedTypeRef(_, _, _) => true,
-            _ => false,
-        }
+        matches!(self.kind, TypeKind::UnresolvedTypeRef(_, _, _))
     }
 
     /// Is this a incomplete array type?
@@ -278,14 +244,14 @@
         match self.kind {
             TypeKind::TypeParam => {
                 let name = self.name().expect("Unnamed named type?");
-                !clang::is_valid_identifier(&name)
+                !clang::is_valid_identifier(name)
             }
             _ => false,
         }
     }
 
     /// Takes `name`, and returns a suitable identifier representation for it.
-    fn sanitize_name<'a>(name: &'a str) -> Cow<'a, str> {
+    fn sanitize_name(name: &str) -> Cow<str> {
         if clang::is_valid_identifier(name) {
             return Cow::Borrowed(name);
         }
@@ -300,12 +266,8 @@
         ctx: &BindgenContext,
     ) -> Option<Cow<'a, str>> {
         let name_info = match *self.kind() {
-            TypeKind::Pointer(inner) => {
-                Some((inner.into(), Cow::Borrowed("ptr")))
-            }
-            TypeKind::Reference(inner) => {
-                Some((inner.into(), Cow::Borrowed("ref")))
-            }
+            TypeKind::Pointer(inner) => Some((inner, Cow::Borrowed("ptr"))),
+            TypeKind::Reference(inner) => Some((inner, Cow::Borrowed("ref"))),
             TypeKind::Array(inner, length) => {
                 Some((inner, format!("array{}", length).into()))
             }
@@ -375,16 +337,16 @@
     /// There are some types we don't want to stop at when finding an opaque
     /// item, so we can arrive to the proper item that needs to be generated.
     pub fn should_be_traced_unconditionally(&self) -> bool {
-        match self.kind {
+        matches!(
+            self.kind,
             TypeKind::Comp(..) |
-            TypeKind::Function(..) |
-            TypeKind::Pointer(..) |
-            TypeKind::Array(..) |
-            TypeKind::Reference(..) |
-            TypeKind::TemplateInstantiation(..) |
-            TypeKind::ResolvedTypeRef(..) => true,
-            _ => false,
-        }
+                TypeKind::Function(..) |
+                TypeKind::Pointer(..) |
+                TypeKind::Array(..) |
+                TypeKind::Reference(..) |
+                TypeKind::TemplateInstantiation(..) |
+                TypeKind::ResolvedTypeRef(..)
+        )
     }
 }
 
@@ -791,7 +753,7 @@
             (ty.template_args().is_some() && ty_kind != CXType_Typedef)
         {
             // This is a template instantiation.
-            match TemplateInstantiation::from_ty(&ty, ctx) {
+            match TemplateInstantiation::from_ty(ty, ctx) {
                 Some(inst) => TypeKind::TemplateInstantiation(inst),
                 None => TypeKind::Opaque,
             }
@@ -1120,7 +1082,16 @@
                     let inner = cursor.typedef_type().expect("Not valid Type?");
                     let inner =
                         Item::from_ty_or_ref(inner, location, None, ctx);
-                    TypeKind::Alias(inner)
+                    if inner == potential_id {
+                        warn!(
+                            "Generating oqaque type instead of self-referential \
+                            typedef");
+                        // This can happen if we bail out of recursive situations
+                        // within the clang parsing.
+                        TypeKind::Opaque
+                    } else {
+                        TypeKind::Alias(inner)
+                    }
                 }
                 CXType_Enum => {
                     let enum_ = Enum::from_ty(ty, ctx).expect("Not an enum?");
diff --git a/src/ir/var.rs b/src/ir/var.rs
index 49c4f30..cd17937 100644
--- a/src/ir/var.rs
+++ b/src/ir/var.rs
@@ -88,7 +88,7 @@
 
     /// Get this variable's mangled name.
     pub fn mangled_name(&self) -> Option<&str> {
-        self.mangled_name.as_ref().map(|n| &**n)
+        self.mangled_name.as_deref()
     }
 }
 
@@ -282,7 +282,7 @@
                             .parse_callbacks()
                             .and_then(|c| c.int_macro(&name, value))
                             .unwrap_or_else(|| {
-                                default_macro_constant_type(&ctx, value)
+                                default_macro_constant_type(ctx, value)
                             });
 
                         (TypeKind::Int(kind), VarType::Int(value))
@@ -398,11 +398,8 @@
 
     let parser = expr::IdentifierParser::new(ctx.parsed_macros());
 
-    match parser.macro_definition(&cexpr_tokens) {
-        Ok((_, (id, val))) => {
-            return Some((id.into(), val));
-        }
-        _ => {}
+    if let Ok((_, (id, val))) = parser.macro_definition(&cexpr_tokens) {
+        return Some((id.into(), val));
     }
 
     // Try without the last token, to workaround a libclang bug in versions
diff --git a/src/lib.rs b/src/lib.rs
index 67cfeb3..1129efe 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -89,7 +89,7 @@
 pub(crate) use std::collections::hash_map::Entry;
 
 /// Default prefix for the anon fields.
-pub const DEFAULT_ANON_FIELDS_PREFIX: &'static str = "__bindgen_anon_";
+pub const DEFAULT_ANON_FIELDS_PREFIX: &str = "__bindgen_anon_";
 
 fn file_is_cpp(name_file: &str) -> bool {
     name_file.ends_with(".hpp") ||
@@ -2148,7 +2148,7 @@
     module: proc_macro2::TokenStream,
 }
 
-pub(crate) const HOST_TARGET: &'static str =
+pub(crate) const HOST_TARGET: &str =
     include_str!(concat!(env!("OUT_DIR"), "/host-target.txt"));
 
 // Some architecture triplets are different between rust and libclang, see #1211
@@ -2156,7 +2156,8 @@
 fn rust_to_clang_target(rust_target: &str) -> String {
     if rust_target.starts_with("aarch64-apple-") {
         let mut clang_target = "arm64-apple-".to_owned();
-        clang_target.push_str(&rust_target["aarch64-apple-".len()..]);
+        clang_target
+            .push_str(rust_target.strip_prefix("aarch64-apple-").unwrap());
         return clang_target;
     }
     rust_target.to_owned()
@@ -2278,10 +2279,7 @@
 
             // Whether we are working with C or C++ inputs.
             let is_cpp = args_are_cpp(&options.clang_args) ||
-                options
-                    .input_header
-                    .as_ref()
-                    .map_or(false, |i| file_is_cpp(&i));
+                options.input_header.as_deref().map_or(false, file_is_cpp);
 
             let search_paths = if is_cpp {
                 clang.cpp_search_paths
@@ -2369,15 +2367,6 @@
         })
     }
 
-    /// Convert these bindings into source text (with raw lines prepended).
-    pub fn to_string(&self) -> String {
-        let mut bytes = vec![];
-        self.write(Box::new(&mut bytes) as Box<dyn 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.
     pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
         let file = OpenOptions::new()
@@ -2427,7 +2416,7 @@
     }
 
     /// Gets the rustfmt path to rustfmt the generated bindings.
-    fn rustfmt_path<'a>(&'a self) -> io::Result<Cow<'a, PathBuf>> {
+    fn rustfmt_path(&self) -> io::Result<Cow<PathBuf>> {
         debug_assert!(self.options.rustfmt_bindings);
         if let Some(ref p) = self.options.rustfmt_path {
             return Ok(Cow::Borrowed(p));
@@ -2518,6 +2507,18 @@
     }
 }
 
+impl std::fmt::Display for Bindings {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let mut bytes = vec![];
+        self.write(Box::new(&mut bytes) as Box<dyn Write>)
+            .expect("writing to a vec cannot fail");
+        f.write_str(
+            std::str::from_utf8(&bytes)
+                .expect("we should only write bindings that are valid utf-8"),
+        )
+    }
+}
+
 /// Determines whether the given cursor is in any of the files matched by the
 /// options.
 fn filter_builtins(ctx: &BindgenContext, cursor: &clang::Cursor) -> bool {
@@ -2566,7 +2567,7 @@
     if context.options().emit_ast {
         fn dump_if_not_builtin(cur: &clang::Cursor) -> CXChildVisitResult {
             if !cur.is_builtin() {
-                clang::ast_dump(&cur, 0)
+                clang::ast_dump(cur, 0)
             } else {
                 CXChildVisit_Continue
             }
@@ -2603,26 +2604,19 @@
     let raw_v: String = clang::extract_clang_version();
     let split_v: Option<Vec<&str>> = raw_v
         .split_whitespace()
-        .filter(|t| t.chars().next().map_or(false, |v| v.is_ascii_digit()))
-        .next()
+        .find(|t| t.chars().next().map_or(false, |v| v.is_ascii_digit()))
         .map(|v| v.split('.').collect());
-    match split_v {
-        Some(v) => {
-            if v.len() >= 2 {
-                let maybe_major = v[0].parse::<u32>();
-                let maybe_minor = v[1].parse::<u32>();
-                match (maybe_major, maybe_minor) {
-                    (Ok(major), Ok(minor)) => {
-                        return ClangVersion {
-                            parsed: Some((major, minor)),
-                            full: raw_v.clone(),
-                        }
-                    }
-                    _ => {}
-                }
+    if let Some(v) = split_v {
+        if v.len() >= 2 {
+            let maybe_major = v[0].parse::<u32>();
+            let maybe_minor = v[1].parse::<u32>();
+            if let (Ok(major), Ok(minor)) = (maybe_major, maybe_minor) {
+                return ClangVersion {
+                    parsed: Some((major, minor)),
+                    full: raw_v.clone(),
+                };
             }
         }
-        None => {}
     };
     ClangVersion {
         parsed: None,
diff --git a/src/log_stubs.rs b/src/log_stubs.rs
index 4af496c..8315983 100644
--- a/src/log_stubs.rs
+++ b/src/log_stubs.rs
@@ -1,32 +1,32 @@
 #![allow(unused)]
 
 macro_rules! log {
-    (target: $target:expr, $lvl:expr, $($arg:tt)+) => {
+    (target: $target:expr, $lvl:expr, $($arg:tt)+) => {{
         let _ = $target;
         let _ = log!($lvl, $($arg)+);
-    };
+    }};
     ($lvl:expr, $($arg:tt)+) => {{
         let _ = $lvl;
         let _ = format_args!($($arg)+);
     }};
 }
 macro_rules! error {
-    (target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); };
-    ($($arg:tt)*) => { log!("", $($arg)*); };
+    (target: $target:expr, $($arg:tt)+) => { log!(target: $target, "", $($arg)+) };
+    ($($arg:tt)+) => { log!("", $($arg)+) };
 }
 macro_rules! warn {
-    (target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); };
-    ($($arg:tt)*) => { log!("", $($arg)*); };
+    (target: $target:expr, $($arg:tt)*) => { log!(target: $target, "", $($arg)*) };
+    ($($arg:tt)*) => { log!("", $($arg)*) };
 }
 macro_rules! info {
-    (target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); };
-    ($($arg:tt)*) => { log!("", $($arg)*); };
+    (target: $target:expr, $($arg:tt)+) => { log!(target: $target, "", $($arg)+) };
+    ($($arg:tt)+) => { log!("", $($arg)+) };
 }
 macro_rules! debug {
-    (target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); };
-    ($($arg:tt)*) => { log!("", $($arg)*); };
+    (target: $target:expr, $($arg:tt)+) => { log!(target: $target, "", $($arg)+) };
+    ($($arg:tt)+) => { log!("", $($arg)+) };
 }
 macro_rules! trace {
-    (target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); };
-    ($($arg:tt)*) => { log!("", $($arg)*); };
+    (target: $target:expr, $($arg:tt)+) => { log!(target: $target, "", $($arg)+) };
+    ($($arg:tt)+) => { log!("", $($arg)+) };
 }
diff --git a/src/main.rs b/src/main.rs
index 1768ed8..f3398db 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -37,7 +37,7 @@
     );
 
     if expected_version.is_some() {
-        assert_eq!(version.parsed, version.parsed);
+        // assert_eq!(version.parsed, version.parsed);
     }
 }
 
@@ -45,9 +45,7 @@
     #[cfg(feature = "logging")]
     env_logger::init();
 
-    let bind_args: Vec<_> = env::args().collect();
-
-    match builder_from_flags(bind_args.into_iter()) {
+    match builder_from_flags(env::args()) {
         Ok((builder, output, verbose)) => {
             clang_version_check();
             let builder_result = panic::catch_unwind(|| {
diff --git a/src/options.rs b/src/options.rs
index 0524871..9aac5da 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -717,7 +717,7 @@
 
     if let Some(what_to_generate) = matches.value_of("generate") {
         let mut config = CodegenConfig::empty();
-        for what in what_to_generate.split(",") {
+        for what in what_to_generate.split(',') {
             match what {
                 "functions" => config.insert(CodegenConfig::FUNCTIONS),
                 "types" => config.insert(CodegenConfig::TYPES),
diff --git a/tests/expectations/tests/constified-enum-module-overflow.rs b/tests/expectations/tests/constified-enum-module-overflow.rs
new file mode 100644
index 0000000..4a799ef
--- /dev/null
+++ b/tests/expectations/tests/constified-enum-module-overflow.rs
@@ -0,0 +1,54 @@
+#![allow(
+    dead_code,
+    non_snake_case,
+    non_camel_case_types,
+    non_upper_case_globals
+)]
+
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct B {
+    pub _address: u8,
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct C {
+    pub _address: u8,
+}
+pub type C_U = B;
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct A {
+    pub u: u8,
+}
+#[test]
+fn bindgen_test_layout_A() {
+    assert_eq!(
+        ::std::mem::size_of::<A>(),
+        1usize,
+        concat!("Size of: ", stringify!(A))
+    );
+    assert_eq!(
+        ::std::mem::align_of::<A>(),
+        1usize,
+        concat!("Alignment of ", stringify!(A))
+    );
+    assert_eq!(
+        unsafe { &(*(::std::ptr::null::<A>())).u as *const _ as usize },
+        0usize,
+        concat!("Offset of field: ", stringify!(A), "::", stringify!(u))
+    );
+}
+#[test]
+fn __bindgen_test_layout_C_open0_A_close0_instantiation() {
+    assert_eq!(
+        ::std::mem::size_of::<C>(),
+        1usize,
+        concat!("Size of template specialization: ", stringify!(C))
+    );
+    assert_eq!(
+        ::std::mem::align_of::<C>(),
+        1usize,
+        concat!("Alignment of template specialization: ", stringify!(C))
+    );
+}
diff --git a/tests/expectations/tests/explicit-padding.rs b/tests/expectations/tests/explicit-padding.rs
index e395e5d..3c42975 100644
--- a/tests/expectations/tests/explicit-padding.rs
+++ b/tests/expectations/tests/explicit-padding.rs
@@ -63,3 +63,68 @@
         )
     );
 }
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union dont_pad_me {
+    pub first: u8,
+    pub second: u32,
+    pub third: u16,
+}
+#[test]
+fn bindgen_test_layout_dont_pad_me() {
+    assert_eq!(
+        ::std::mem::size_of::<dont_pad_me>(),
+        4usize,
+        concat!("Size of: ", stringify!(dont_pad_me))
+    );
+    assert_eq!(
+        ::std::mem::align_of::<dont_pad_me>(),
+        4usize,
+        concat!("Alignment of ", stringify!(dont_pad_me))
+    );
+    assert_eq!(
+        unsafe {
+            &(*(::std::ptr::null::<dont_pad_me>())).first as *const _ as usize
+        },
+        0usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(dont_pad_me),
+            "::",
+            stringify!(first)
+        )
+    );
+    assert_eq!(
+        unsafe {
+            &(*(::std::ptr::null::<dont_pad_me>())).second as *const _ as usize
+        },
+        0usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(dont_pad_me),
+            "::",
+            stringify!(second)
+        )
+    );
+    assert_eq!(
+        unsafe {
+            &(*(::std::ptr::null::<dont_pad_me>())).third as *const _ as usize
+        },
+        0usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(dont_pad_me),
+            "::",
+            stringify!(third)
+        )
+    );
+}
+impl Default for dont_pad_me {
+    fn default() -> Self {
+        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
+        unsafe {
+            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+            s.assume_init()
+        }
+    }
+}
diff --git a/tests/headers/constified-enum-module-overflow.hpp b/tests/headers/constified-enum-module-overflow.hpp
new file mode 100644
index 0000000..d48f2be
--- /dev/null
+++ b/tests/headers/constified-enum-module-overflow.hpp
@@ -0,0 +1,8 @@
+template <typename> class B{};
+template <typename c> class C {
+public:
+  using U = B<c>;
+};
+class A : C<A> {
+  U u;
+};
diff --git a/tests/headers/explicit-padding.h b/tests/headers/explicit-padding.h
index d228961..4abaafb 100644
--- a/tests/headers/explicit-padding.h
+++ b/tests/headers/explicit-padding.h
@@ -9,3 +9,9 @@
         uint32_t second;
         uint16_t third;
 };
+
+union dont_pad_me {
+        uint8_t first;
+        uint32_t second;
+        uint16_t third;
+};
diff --git a/tests/stylo_sanity.rs b/tests/stylo_sanity.rs
index 2ea7762..39777cd 100755
--- a/tests/stylo_sanity.rs
+++ b/tests/stylo_sanity.rs
@@ -545,14 +545,14 @@
 
     let now = Instant::now();
 
-    println!("");
-    println!("");
+    println!();
+    println!();
     println!(
         "Generated Stylo bindings in: {:?}",
         now.duration_since(then)
     );
-    println!("");
-    println!("");
+    println!();
+    println!();
 
     // panic!("Uncomment this line to get timing logs");
 }