Snap for 8730993 from 5c9f86bcc640cc6face7d5dc55896cdff801a9ee to mainline-tzdata3-release

Change-Id: I6de340372b46843c054fbe9315907678047ded75
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 2d04484..349cbda 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,5 @@
 {
   "git": {
-    "sha1": "672e9525bbc2e5682c380d36974f34716b963591"
-  },
-  "path_in_vcs": "impl"
-}
\ No newline at end of file
+    "sha1": "1b0a84996b9492c0dc5779127a91c930f23a259e"
+  }
+}
diff --git a/Android.bp b/Android.bp
index d3c9ef4..11a5817 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,4 +1,4 @@
-// This file is generated by cargo2android.py --config cargo2android.json.
+// This file is generated by cargo2android.py --run --dependencies --device.
 // Do not modify this file as changes will be overridden on upgrade.
 
 package {
@@ -42,8 +42,6 @@
 rust_proc_macro {
     name: "libthiserror_impl",
     crate_name: "thiserror_impl",
-    cargo_env_compat: true,
-    cargo_pkg_version: "1.0.30",
     srcs: ["src/lib.rs"],
     edition: "2018",
     rustlibs: [
@@ -52,3 +50,9 @@
         "libsyn",
     ],
 }
+
+// dependent_library ["feature_list"]
+//   proc-macro2-1.0.24 "default,proc-macro"
+//   quote-1.0.9 "default,proc-macro"
+//   syn-1.0.60 "clone-impls,default,derive,parsing,printing,proc-macro,quote"
+//   unicode-xid-0.2.1 "default"
diff --git a/Cargo.toml b/Cargo.toml
index 97e0042..a9b7471 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,17 +3,17 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies.
+# to registry (e.g., crates.io) dependencies
 #
-# If you are reading this file be aware that the original Cargo.toml
-# will likely look very different (and much more reasonable).
-# See Cargo.toml.orig for the original contents.
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
 
 [package]
 edition = "2018"
-rust-version = "1.31"
 name = "thiserror-impl"
-version = "1.0.30"
+version = "1.0.24"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 description = "Implementation detail of the `thiserror` crate"
 license = "MIT OR Apache-2.0"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index e2ad11b..3963fe2 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,9 +1,8 @@
 [package]
 name = "thiserror-impl"
-version = "1.0.30"
+version = "1.0.24"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
-rust-version = "1.31"
 license = "MIT OR Apache-2.0"
 description = "Implementation detail of the `thiserror` crate"
 repository = "https://github.com/dtolnay/thiserror"
diff --git a/METADATA b/METADATA
index 594ab80..2616031 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/thiserror-impl/thiserror-impl-1.0.30.crate"
+    value: "https://static.crates.io/crates/thiserror-impl/thiserror-impl-1.0.24.crate"
   }
-  version: "1.0.30"
+  version: "1.0.24"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2022
-    month: 3
-    day: 1
+    year: 2021
+    month: 2
+    day: 18
   }
 }
diff --git a/TEST_MAPPING b/TEST_MAPPING
index eea7991..743367a 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,150 +1,53 @@
 // Generated by update_crate_tests.py for tests that depend on this crate.
 {
-  "imports": [
-    {
-      "path": "external/rust/crates/anyhow"
-    },
-    {
-      "path": "external/rust/crates/jni"
-    },
-    {
-      "path": "external/rust/crates/serde-xml-rs"
-    }
-  ],
   "presubmit": [
     {
-      "name": "ZipFuseTest"
-    },
-    {
-      "name": "apkdmverity.test"
-    },
-    {
-      "name": "authfs_device_test_src_lib"
-    },
-    {
-      "name": "diced_open_dice_cbor_test"
-    },
-    {
-      "name": "diced_sample_inputs_test"
-    },
-    {
-      "name": "diced_test"
-    },
-    {
-      "name": "diced_utils_test"
-    },
-    {
-      "name": "diced_vendor_test"
-    },
-    {
-      "name": "doh_unit_test"
-    },
-    {
-      "name": "keystore2_crypto_test_rust"
-    },
-    {
-      "name": "keystore2_selinux_concurrency_test"
+      "name": "anyhow_device_test_tests_test_autotrait"
     },
     {
       "name": "keystore2_selinux_test"
     },
     {
+      "name": "anyhow_device_test_tests_test_repr"
+    },
+    {
+      "name": "anyhow_device_test_tests_test_convert"
+    },
+    {
+      "name": "anyhow_device_test_tests_test_context"
+    },
+    {
+      "name": "anyhow_device_test_tests_test_boxed"
+    },
+    {
+      "name": "anyhow_device_test_tests_test_downcast"
+    },
+    {
       "name": "keystore2_test"
     },
     {
-      "name": "keystore2_test_utils_test"
+      "name": "anyhow_device_test_tests_test_source"
     },
     {
-      "name": "keystore2_vintf_test"
+      "name": "anyhow_device_test_src_lib"
     },
     {
-      "name": "legacykeystore_test"
+      "name": "anyhow_device_test_tests_test_fmt"
     },
     {
-      "name": "libapkverify.integration_test"
+      "name": "anyhow_device_test_tests_test_ffi"
     },
     {
-      "name": "libapkverify.test"
+      "name": "anyhow_device_test_tests_test_chain"
     },
     {
-      "name": "libcert_request_validator_tests"
-    },
-    {
-      "name": "librustutils_test"
-    },
-    {
-      "name": "microdroid_manager_test"
-    },
-    {
-      "name": "virtualizationservice_device_test"
-    }
-  ],
-  "presubmit-rust": [
-    {
-      "name": "ZipFuseTest"
-    },
-    {
-      "name": "apkdmverity.test"
-    },
-    {
-      "name": "authfs_device_test_src_lib"
-    },
-    {
-      "name": "diced_open_dice_cbor_test"
-    },
-    {
-      "name": "diced_sample_inputs_test"
-    },
-    {
-      "name": "diced_test"
-    },
-    {
-      "name": "diced_utils_test"
-    },
-    {
-      "name": "diced_vendor_test"
-    },
-    {
-      "name": "doh_unit_test"
+      "name": "libsqlite3-sys_device_test_src_lib"
     },
     {
       "name": "keystore2_crypto_test_rust"
     },
     {
-      "name": "keystore2_selinux_concurrency_test"
-    },
-    {
-      "name": "keystore2_selinux_test"
-    },
-    {
-      "name": "keystore2_test"
-    },
-    {
-      "name": "keystore2_test_utils_test"
-    },
-    {
-      "name": "keystore2_vintf_test"
-    },
-    {
-      "name": "legacykeystore_test"
-    },
-    {
-      "name": "libapkverify.integration_test"
-    },
-    {
-      "name": "libapkverify.test"
-    },
-    {
-      "name": "libcert_request_validator_tests"
-    },
-    {
-      "name": "librustutils_test"
-    },
-    {
-      "name": "microdroid_manager_test"
-    },
-    {
-      "name": "virtualizationservice_device_test"
+      "name": "anyhow_device_test_tests_test_macros"
     }
   ]
 }
diff --git a/cargo2android.json b/cargo2android.json
deleted file mode 100644
index bf78496..0000000
--- a/cargo2android.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "device": true,
-  "run": true
-}
\ No newline at end of file
diff --git a/src/ast.rs b/src/ast.rs
index 2aa7246..8698ecf 100644
--- a/src/ast.rs
+++ b/src/ast.rs
@@ -1,5 +1,4 @@
 use crate::attr::{self, Attrs};
-use crate::generics::ParamsInScope;
 use proc_macro2::Span;
 use syn::{
     Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Generics, Ident, Index, Member, Result,
@@ -39,7 +38,6 @@
     pub attrs: Attrs<'a>,
     pub member: Member,
     pub ty: &'a Type,
-    pub contains_generic: bool,
 }
 
 impl<'a> Input<'a> {
@@ -58,9 +56,8 @@
 impl<'a> Struct<'a> {
     fn from_syn(node: &'a DeriveInput, data: &'a DataStruct) -> Result<Self> {
         let mut attrs = attr::get(&node.attrs)?;
-        let scope = ParamsInScope::new(&node.generics);
         let span = attrs.span().unwrap_or_else(Span::call_site);
-        let fields = Field::multiple_from_syn(&data.fields, &scope, span)?;
+        let fields = Field::multiple_from_syn(&data.fields, span)?;
         if let Some(display) = &mut attrs.display {
             display.expand_shorthand(&fields);
         }
@@ -77,13 +74,12 @@
 impl<'a> Enum<'a> {
     fn from_syn(node: &'a DeriveInput, data: &'a DataEnum) -> Result<Self> {
         let attrs = attr::get(&node.attrs)?;
-        let scope = ParamsInScope::new(&node.generics);
         let span = attrs.span().unwrap_or_else(Span::call_site);
         let variants = data
             .variants
             .iter()
             .map(|node| {
-                let mut variant = Variant::from_syn(node, &scope, span)?;
+                let mut variant = Variant::from_syn(node, span)?;
                 if let display @ None = &mut variant.attrs.display {
                     *display = attrs.display.clone();
                 }
@@ -106,37 +102,28 @@
 }
 
 impl<'a> Variant<'a> {
-    fn from_syn(node: &'a syn::Variant, scope: &ParamsInScope<'a>, span: Span) -> Result<Self> {
+    fn from_syn(node: &'a syn::Variant, span: Span) -> Result<Self> {
         let attrs = attr::get(&node.attrs)?;
         let span = attrs.span().unwrap_or(span);
         Ok(Variant {
             original: node,
             attrs,
             ident: node.ident.clone(),
-            fields: Field::multiple_from_syn(&node.fields, scope, span)?,
+            fields: Field::multiple_from_syn(&node.fields, span)?,
         })
     }
 }
 
 impl<'a> Field<'a> {
-    fn multiple_from_syn(
-        fields: &'a Fields,
-        scope: &ParamsInScope<'a>,
-        span: Span,
-    ) -> Result<Vec<Self>> {
+    fn multiple_from_syn(fields: &'a Fields, span: Span) -> Result<Vec<Self>> {
         fields
             .iter()
             .enumerate()
-            .map(|(i, field)| Field::from_syn(i, field, scope, span))
+            .map(|(i, field)| Field::from_syn(i, field, span))
             .collect()
     }
 
-    fn from_syn(
-        i: usize,
-        node: &'a syn::Field,
-        scope: &ParamsInScope<'a>,
-        span: Span,
-    ) -> Result<Self> {
+    fn from_syn(i: usize, node: &'a syn::Field, span: Span) -> Result<Self> {
         Ok(Field {
             original: node,
             attrs: attr::get(&node.attrs)?,
@@ -147,7 +134,6 @@
                 })
             }),
             ty: &node.ty,
-            contains_generic: scope.intersects(&node.ty),
         })
     }
 }
diff --git a/src/attr.rs b/src/attr.rs
index 9963fd6..1ab1e28 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -1,6 +1,5 @@
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, ToTokens};
-use std::collections::BTreeSet as Set;
 use std::iter::FromIterator;
 use syn::parse::{Nothing, ParseStream};
 use syn::{
@@ -22,7 +21,6 @@
     pub fmt: LitStr,
     pub args: TokenStream,
     pub has_bonus_display: bool,
-    pub implied_bounds: Set<(usize, Trait)>,
 }
 
 #[derive(Copy, Clone)]
@@ -31,19 +29,6 @@
     pub span: Span,
 }
 
-#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
-pub enum Trait {
-    Debug,
-    Display,
-    Octal,
-    LowerHex,
-    UpperHex,
-    Pointer,
-    Binary,
-    LowerExp,
-    UpperExp,
-}
-
 pub fn get(input: &[Attribute]) -> Result<Attrs> {
     let mut attrs = Attrs {
         display: None,
@@ -106,7 +91,6 @@
             fmt: input.parse()?,
             args: parse_token_expr(input, false)?,
             has_bonus_display: false,
-            implied_bounds: Set::new(),
         };
         if attrs.display.is_some() {
             return Err(Error::new_spanned(
@@ -204,10 +188,3 @@
         });
     }
 }
-
-impl ToTokens for Trait {
-    fn to_tokens(&self, tokens: &mut TokenStream) {
-        let trait_name = format_ident!("{}", format!("{:?}", self));
-        tokens.extend(quote!(std::fmt::#trait_name));
-    }
-}
diff --git a/src/expand.rs b/src/expand.rs
index 435ad48..fa85cbb 100644
--- a/src/expand.rs
+++ b/src/expand.rs
@@ -1,13 +1,8 @@
 use crate::ast::{Enum, Field, Input, Struct};
-use crate::attr::Trait;
-use crate::generics::InferredBounds;
 use proc_macro2::TokenStream;
 use quote::{format_ident, quote, quote_spanned, ToTokens};
-use std::collections::BTreeSet as Set;
 use syn::spanned::Spanned;
-use syn::{
-    Data, DeriveInput, GenericArgument, Member, PathArguments, Result, Token, Type, Visibility,
-};
+use syn::{Data, DeriveInput, Member, PathArguments, Result, Type, Visibility};
 
 pub fn derive(node: &DeriveInput) -> Result<TokenStream> {
     let input = Input::from_syn(node)?;
@@ -21,23 +16,14 @@
 fn impl_struct(input: Struct) -> TokenStream {
     let ty = &input.ident;
     let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
-    let mut error_inferred_bounds = InferredBounds::new();
 
     let source_body = if input.attrs.transparent.is_some() {
-        let only_field = &input.fields[0];
-        if only_field.contains_generic {
-            error_inferred_bounds.insert(only_field.ty, quote!(std::error::Error));
-        }
-        let member = &only_field.member;
+        let only_field = &input.fields[0].member;
         Some(quote! {
-            std::error::Error::source(self.#member.as_dyn_error())
+            std::error::Error::source(self.#only_field.as_dyn_error())
         })
     } else if let Some(source_field) = input.source_field() {
         let source = &source_field.member;
-        if source_field.contains_generic {
-            let ty = unoptional_type(source_field.ty);
-            error_inferred_bounds.insert(ty, quote!(std::error::Error + 'static));
-        }
         let asref = if type_is_option(source_field.ty) {
             Some(quote_spanned!(source.span()=> .as_ref()?))
         } else {
@@ -72,9 +58,7 @@
                     self.#source.as_dyn_error().backtrace()
                 }
             };
-            let combinator = if source == backtrace {
-                source_backtrace
-            } else if type_is_option(backtrace_field.ty) {
+            let combinator = if type_is_option(backtrace_field.ty) {
                 quote! {
                     #source_backtrace.or(self.#backtrace.as_ref())
                 }
@@ -103,15 +87,12 @@
         }
     });
 
-    let mut display_implied_bounds = Set::new();
     let display_body = if input.attrs.transparent.is_some() {
         let only_field = &input.fields[0].member;
-        display_implied_bounds.insert((0, Trait::Display));
         Some(quote! {
             std::fmt::Display::fmt(&self.#only_field, __formatter)
         })
     } else if let Some(display) = &input.attrs.display {
-        display_implied_bounds = display.implied_bounds.clone();
         let use_as_display = if display.has_bonus_display {
             Some(quote! {
                 #[allow(unused_imports)]
@@ -131,17 +112,9 @@
         None
     };
     let display_impl = display_body.map(|body| {
-        let mut display_inferred_bounds = InferredBounds::new();
-        for (field, bound) in display_implied_bounds {
-            let field = &input.fields[field];
-            if field.contains_generic {
-                display_inferred_bounds.insert(field.ty, bound);
-            }
-        }
-        let display_where_clause = display_inferred_bounds.augment_where_clause(input.generics);
         quote! {
             #[allow(unused_qualifications)]
-            impl #impl_generics std::fmt::Display for #ty #ty_generics #display_where_clause {
+            impl #impl_generics std::fmt::Display for #ty #ty_generics #where_clause {
                 #[allow(clippy::used_underscore_binding)]
                 fn fmt(&self, __formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
                     #body
@@ -151,8 +124,8 @@
     });
 
     let from_impl = input.from_field().map(|from_field| {
-        let backtrace_field = input.distinct_backtrace_field();
-        let from = unoptional_type(from_field.ty);
+        let backtrace_field = input.backtrace_field();
+        let from = from_field.ty;
         let body = from_initializer(from_field, backtrace_field);
         quote! {
             #[allow(unused_qualifications)]
@@ -166,16 +139,10 @@
     });
 
     let error_trait = spanned_error_trait(input.original);
-    if input.generics.type_params().next().is_some() {
-        let self_token = <Token![Self]>::default();
-        error_inferred_bounds.insert(self_token, Trait::Debug);
-        error_inferred_bounds.insert(self_token, Trait::Display);
-    }
-    let error_where_clause = error_inferred_bounds.augment_where_clause(input.generics);
 
     quote! {
         #[allow(unused_qualifications)]
-        impl #impl_generics #error_trait for #ty #ty_generics #error_where_clause {
+        impl #impl_generics #error_trait for #ty #ty_generics #where_clause {
             #source_method
             #backtrace_method
         }
@@ -187,27 +154,18 @@
 fn impl_enum(input: Enum) -> TokenStream {
     let ty = &input.ident;
     let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
-    let mut error_inferred_bounds = InferredBounds::new();
 
     let source_method = if input.has_source() {
         let arms = input.variants.iter().map(|variant| {
             let ident = &variant.ident;
             if variant.attrs.transparent.is_some() {
-                let only_field = &variant.fields[0];
-                if only_field.contains_generic {
-                    error_inferred_bounds.insert(only_field.ty, quote!(std::error::Error));
-                }
-                let member = &only_field.member;
+                let only_field = &variant.fields[0].member;
                 let source = quote!(std::error::Error::source(transparent.as_dyn_error()));
                 quote! {
-                    #ty::#ident {#member: transparent} => #source,
+                    #ty::#ident {#only_field: transparent} => #source,
                 }
             } else if let Some(source_field) = variant.source_field() {
                 let source = &source_field.member;
-                if source_field.contains_generic {
-                    let ty = unoptional_type(source_field.ty);
-                    error_inferred_bounds.insert(ty, quote!(std::error::Error + 'static));
-                }
                 let asref = if type_is_option(source_field.ty) {
                     Some(quote_spanned!(source.span()=> .as_ref()?))
                 } else {
@@ -276,27 +234,6 @@
                         }
                     }
                 }
-                (Some(backtrace_field), Some(source_field))
-                    if backtrace_field.member == source_field.member =>
-                {
-                    let backtrace = &backtrace_field.member;
-                    let varsource = quote!(source);
-                    let source_backtrace = if type_is_option(source_field.ty) {
-                        quote_spanned! {backtrace.span()=>
-                            #varsource.as_ref().and_then(|source| source.as_dyn_error().backtrace())
-                        }
-                    } else {
-                        quote_spanned! {backtrace.span()=>
-                            #varsource.as_dyn_error().backtrace()
-                        }
-                    };
-                    quote! {
-                        #ty::#ident {#backtrace: #varsource, ..} => {
-                            use thiserror::private::AsDynError;
-                            #source_backtrace
-                        }
-                    }
-                }
                 (Some(backtrace_field), _) => {
                     let backtrace = &backtrace_field.member;
                     let body = if type_is_option(backtrace_field.ty) {
@@ -326,7 +263,6 @@
     };
 
     let display_impl = if input.has_display() {
-        let mut display_inferred_bounds = InferredBounds::new();
         let use_as_display = if input.variants.iter().any(|v| {
             v.attrs
                 .display
@@ -346,38 +282,25 @@
             None
         };
         let arms = input.variants.iter().map(|variant| {
-            let mut display_implied_bounds = Set::new();
             let display = match &variant.attrs.display {
-                Some(display) => {
-                    display_implied_bounds = display.implied_bounds.clone();
-                    display.to_token_stream()
-                }
+                Some(display) => display.to_token_stream(),
                 None => {
                     let only_field = match &variant.fields[0].member {
                         Member::Named(ident) => ident.clone(),
                         Member::Unnamed(index) => format_ident!("_{}", index),
                     };
-                    display_implied_bounds.insert((0, Trait::Display));
                     quote!(std::fmt::Display::fmt(#only_field, __formatter))
                 }
             };
-            for (field, bound) in display_implied_bounds {
-                let field = &variant.fields[field];
-                if field.contains_generic {
-                    display_inferred_bounds.insert(field.ty, bound);
-                }
-            }
             let ident = &variant.ident;
             let pat = fields_pat(&variant.fields);
             quote! {
                 #ty::#ident #pat => #display
             }
         });
-        let arms = arms.collect::<Vec<_>>();
-        let display_where_clause = display_inferred_bounds.augment_where_clause(input.generics);
         Some(quote! {
             #[allow(unused_qualifications)]
-            impl #impl_generics std::fmt::Display for #ty #ty_generics #display_where_clause {
+            impl #impl_generics std::fmt::Display for #ty #ty_generics #where_clause {
                 fn fmt(&self, __formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
                     #use_as_display
                     #[allow(unused_variables, deprecated, clippy::used_underscore_binding)]
@@ -393,9 +316,9 @@
 
     let from_impls = input.variants.iter().filter_map(|variant| {
         let from_field = variant.from_field()?;
-        let backtrace_field = variant.distinct_backtrace_field();
+        let backtrace_field = variant.backtrace_field();
         let variant = &variant.ident;
-        let from = unoptional_type(from_field.ty);
+        let from = from_field.ty;
         let body = from_initializer(from_field, backtrace_field);
         Some(quote! {
             #[allow(unused_qualifications)]
@@ -409,16 +332,10 @@
     });
 
     let error_trait = spanned_error_trait(input.original);
-    if input.generics.type_params().next().is_some() {
-        let self_token = <Token![Self]>::default();
-        error_inferred_bounds.insert(self_token, Trait::Debug);
-        error_inferred_bounds.insert(self_token, Trait::Display);
-    }
-    let error_where_clause = error_inferred_bounds.augment_where_clause(input.generics);
 
     quote! {
         #[allow(unused_qualifications)]
-        impl #impl_generics #error_trait for #ty #ty_generics #error_where_clause {
+        impl #impl_generics #error_trait for #ty #ty_generics #where_clause {
             #source_method
             #backtrace_method
         }
@@ -444,11 +361,6 @@
 
 fn from_initializer(from_field: &Field, backtrace_field: Option<&Field>) -> TokenStream {
     let from_member = &from_field.member;
-    let some_source = if type_is_option(from_field.ty) {
-        quote!(std::option::Option::Some(source))
-    } else {
-        quote!(source)
-    };
     let backtrace = backtrace_field.map(|backtrace_field| {
         let backtrace_member = &backtrace_field.member;
         if type_is_option(backtrace_field.ty) {
@@ -462,43 +374,25 @@
         }
     });
     quote!({
-        #from_member: #some_source,
+        #from_member: source,
         #backtrace
     })
 }
 
 fn type_is_option(ty: &Type) -> bool {
-    type_parameter_of_option(ty).is_some()
-}
-
-fn unoptional_type(ty: &Type) -> TokenStream {
-    let unoptional = type_parameter_of_option(ty).unwrap_or(ty);
-    quote!(#unoptional)
-}
-
-fn type_parameter_of_option(ty: &Type) -> Option<&Type> {
     let path = match ty {
         Type::Path(ty) => &ty.path,
-        _ => return None,
+        _ => return false,
     };
 
     let last = path.segments.last().unwrap();
     if last.ident != "Option" {
-        return None;
+        return false;
     }
 
-    let bracketed = match &last.arguments {
-        PathArguments::AngleBracketed(bracketed) => bracketed,
-        _ => return None,
-    };
-
-    if bracketed.args.len() != 1 {
-        return None;
-    }
-
-    match &bracketed.args[0] {
-        GenericArgument::Type(arg) => Some(arg),
-        _ => None,
+    match &last.arguments {
+        PathArguments::AngleBracketed(bracketed) => bracketed.args.len() == 1,
+        _ => false,
     }
 }
 
diff --git a/src/fmt.rs b/src/fmt.rs
index 807dfb9..e12e94b 100644
--- a/src/fmt.rs
+++ b/src/fmt.rs
@@ -1,8 +1,8 @@
 use crate::ast::Field;
-use crate::attr::{Display, Trait};
+use crate::attr::Display;
 use proc_macro2::TokenTree;
 use quote::{format_ident, quote_spanned};
-use std::collections::{BTreeSet as Set, HashMap as Map};
+use std::collections::HashSet as Set;
 use syn::ext::IdentExt;
 use syn::parse::{ParseStream, Parser};
 use syn::{Ident, Index, LitStr, Member, Result, Token};
@@ -12,10 +12,7 @@
     pub fn expand_shorthand(&mut self, fields: &[Field]) {
         let raw_args = self.args.clone();
         let mut named_args = explicit_named_args.parse2(raw_args).unwrap();
-        let mut member_index = Map::new();
-        for (i, field) in fields.iter().enumerate() {
-            member_index.insert(&field.member, i);
-        }
+        let fields: Set<Member> = fields.iter().map(|f| f.member.clone()).collect();
 
         let span = self.fmt.span();
         let fmt = self.fmt.value();
@@ -23,7 +20,6 @@
         let mut out = String::new();
         let mut args = self.args.clone();
         let mut has_bonus_display = false;
-        let mut implied_bounds = Set::new();
 
         let mut has_trailing_comma = false;
         if let Some(TokenTree::Punct(punct)) = args.clone().into_iter().last() {
@@ -51,7 +47,7 @@
                         Ok(index) => Member::Unnamed(Index { index, span }),
                         Err(_) => return,
                     };
-                    if !member_index.contains_key(&member) {
+                    if !fields.contains(&member) {
                         out += &int;
                         continue;
                     }
@@ -64,24 +60,6 @@
                 }
                 _ => continue,
             };
-            if let Some(&field) = member_index.get(&member) {
-                let end_spec = match read.find('}') {
-                    Some(end_spec) => end_spec,
-                    None => return,
-                };
-                let bound = match read[..end_spec].chars().next_back() {
-                    Some('?') => Trait::Debug,
-                    Some('o') => Trait::Octal,
-                    Some('x') => Trait::LowerHex,
-                    Some('X') => Trait::UpperHex,
-                    Some('p') => Trait::Pointer,
-                    Some('b') => Trait::Binary,
-                    Some('e') => Trait::LowerExp,
-                    Some('E') => Trait::UpperExp,
-                    Some(_) | None => Trait::Display,
-                };
-                implied_bounds.insert((field, bound));
-            }
             let local = match &member {
                 Member::Unnamed(index) => format_ident!("_{}", index),
                 Member::Named(ident) => ident.clone(),
@@ -104,7 +82,7 @@
                 args.extend(quote_spanned!(span=> ,));
             }
             args.extend(quote_spanned!(span=> #formatvar = #local));
-            if read.starts_with('}') && member_index.contains_key(&member) {
+            if read.starts_with('}') && fields.contains(&member) {
                 has_bonus_display = true;
                 args.extend(quote_spanned!(span=> .as_display()));
             }
@@ -115,7 +93,6 @@
         self.fmt = LitStr::new(&out, self.fmt.span());
         self.args = args;
         self.has_bonus_display = has_bonus_display;
-        self.implied_bounds = implied_bounds;
     }
 }
 
diff --git a/src/generics.rs b/src/generics.rs
deleted file mode 100644
index 254c2ed..0000000
--- a/src/generics.rs
+++ /dev/null
@@ -1,82 +0,0 @@
-use proc_macro2::TokenStream;
-use quote::ToTokens;
-use std::collections::btree_map::Entry;
-use std::collections::{BTreeMap as Map, BTreeSet as Set};
-use syn::punctuated::Punctuated;
-use syn::{parse_quote, GenericArgument, Generics, Ident, PathArguments, Token, Type, WhereClause};
-
-pub struct ParamsInScope<'a> {
-    names: Set<&'a Ident>,
-}
-
-impl<'a> ParamsInScope<'a> {
-    pub fn new(generics: &'a Generics) -> Self {
-        ParamsInScope {
-            names: generics.type_params().map(|param| &param.ident).collect(),
-        }
-    }
-
-    pub fn intersects(&self, ty: &Type) -> bool {
-        let mut found = false;
-        crawl(self, ty, &mut found);
-        found
-    }
-}
-
-fn crawl(in_scope: &ParamsInScope, ty: &Type, found: &mut bool) {
-    if let Type::Path(ty) = ty {
-        if ty.qself.is_none() {
-            if let Some(ident) = ty.path.get_ident() {
-                if in_scope.names.contains(ident) {
-                    *found = true;
-                }
-            }
-        }
-        for segment in &ty.path.segments {
-            if let PathArguments::AngleBracketed(arguments) = &segment.arguments {
-                for arg in &arguments.args {
-                    if let GenericArgument::Type(ty) = arg {
-                        crawl(in_scope, ty, found);
-                    }
-                }
-            }
-        }
-    }
-}
-
-pub struct InferredBounds {
-    bounds: Map<String, (Set<String>, Punctuated<TokenStream, Token![+]>)>,
-    order: Vec<TokenStream>,
-}
-
-impl InferredBounds {
-    pub fn new() -> Self {
-        InferredBounds {
-            bounds: Map::new(),
-            order: Vec::new(),
-        }
-    }
-
-    pub fn insert(&mut self, ty: impl ToTokens, bound: impl ToTokens) {
-        let ty = ty.to_token_stream();
-        let bound = bound.to_token_stream();
-        let entry = self.bounds.entry(ty.to_string());
-        if let Entry::Vacant(_) = entry {
-            self.order.push(ty);
-        }
-        let (set, tokens) = entry.or_default();
-        if set.insert(bound.to_string()) {
-            tokens.push(bound);
-        }
-    }
-
-    pub fn augment_where_clause(&self, generics: &Generics) -> WhereClause {
-        let mut generics = generics.clone();
-        let where_clause = generics.make_where_clause();
-        for ty in &self.order {
-            let (_set, bounds) = &self.bounds[&ty.to_string()];
-            where_clause.predicates.push(parse_quote!(#ty: #bounds));
-        }
-        generics.where_clause.unwrap()
-    }
-}
diff --git a/src/lib.rs b/src/lib.rs
index a4d5ae7..b0d4618 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,7 +1,6 @@
 #![allow(
     clippy::blocks_in_if_conditions,
     clippy::cast_possible_truncation,
-    clippy::manual_map,
     clippy::map_unwrap_or,
     clippy::needless_pass_by_value,
     clippy::option_if_let_else,
@@ -16,7 +15,6 @@
 mod attr;
 mod expand;
 mod fmt;
-mod generics;
 mod prop;
 mod valid;
 
diff --git a/src/prop.rs b/src/prop.rs
index 6d8a924..e011848 100644
--- a/src/prop.rs
+++ b/src/prop.rs
@@ -13,11 +13,6 @@
     pub(crate) fn backtrace_field(&self) -> Option<&Field> {
         backtrace_field(&self.fields)
     }
-
-    pub(crate) fn distinct_backtrace_field(&self) -> Option<&Field> {
-        let backtrace_field = self.backtrace_field()?;
-        distinct_backtrace_field(backtrace_field, self.from_field())
-    }
 }
 
 impl Enum<'_> {
@@ -59,11 +54,6 @@
     pub(crate) fn backtrace_field(&self) -> Option<&Field> {
         backtrace_field(&self.fields)
     }
-
-    pub(crate) fn distinct_backtrace_field(&self) -> Option<&Field> {
-        let backtrace_field = self.backtrace_field()?;
-        distinct_backtrace_field(backtrace_field, self.from_field())
-    }
 }
 
 impl Field<'_> {
@@ -75,7 +65,7 @@
 fn from_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> {
     for field in fields {
         if field.attrs.from.is_some() {
-            return Some(field);
+            return Some(&field);
         }
     }
     None
@@ -84,12 +74,12 @@
 fn source_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> {
     for field in fields {
         if field.attrs.from.is_some() || field.attrs.source.is_some() {
-            return Some(field);
+            return Some(&field);
         }
     }
     for field in fields {
         match &field.member {
-            Member::Named(ident) if ident == "source" => return Some(field),
+            Member::Named(ident) if ident == "source" => return Some(&field),
             _ => {}
         }
     }
@@ -99,31 +89,17 @@
 fn backtrace_field<'a, 'b>(fields: &'a [Field<'b>]) -> Option<&'a Field<'b>> {
     for field in fields {
         if field.attrs.backtrace.is_some() {
-            return Some(field);
+            return Some(&field);
         }
     }
     for field in fields {
         if field.is_backtrace() {
-            return Some(field);
+            return Some(&field);
         }
     }
     None
 }
 
-// The #[backtrace] field, if it is not the same as the #[from] field.
-fn distinct_backtrace_field<'a, 'b>(
-    backtrace_field: &'a Field<'b>,
-    from_field: Option<&Field>,
-) -> Option<&'a Field<'b>> {
-    if from_field.map_or(false, |from_field| {
-        from_field.member == backtrace_field.member
-    }) {
-        None
-    } else {
-        Some(backtrace_field)
-    }
-}
-
 fn type_is_backtrace(ty: &Type) -> bool {
     let path = match ty {
         Type::Path(ty) => &ty.path,
diff --git a/src/valid.rs b/src/valid.rs
index 7657265..7246d0c 100644
--- a/src/valid.rs
+++ b/src/valid.rs
@@ -188,7 +188,7 @@
         }
     }
     if let Some(source_field) = source_field.or(from_field) {
-        if contains_non_static_lifetime(source_field.ty) {
+        if contains_non_static_lifetime(&source_field.ty) {
             return Err(Error::new_spanned(
                 &source_field.original.ty,
                 "non-static lifetimes are not allowed in the source of an error, because std::error::Error requires the source is dyn Error + 'static",