Upgrade derive_arbitrary to 1.2.0

This project was upgraded with external_updater.
Usage: tools/external_updater/updater.sh update rust/crates/derive_arbitrary
For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md

Test: TreeHugger
Change-Id: I9352815d507bc2be7ee58896358c0fe935f01971
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 30c0308..0724802 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "8e7b857f4f78b06920a36212ed2f392bc523c1f6"
+    "sha1": "48c4bfd52b167da94a5db906fe7dd2da7b92215e"
   },
   "path_in_vcs": "derive"
 }
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index e5183a8..04e8dca 100644
--- a/Android.bp
+++ b/Android.bp
@@ -43,9 +43,9 @@
     name: "libderive_arbitrary",
     crate_name: "derive_arbitrary",
     cargo_env_compat: true,
-    cargo_pkg_version: "1.1.3",
+    cargo_pkg_version: "1.2.0",
     srcs: ["src/lib.rs"],
-    edition: "2018",
+    edition: "2021",
     rustlibs: [
         "libproc_macro2",
         "libquote",
diff --git a/Cargo.toml b/Cargo.toml
index 68714a1..db2f6be 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,9 +10,10 @@
 # See Cargo.toml.orig for the original contents.
 
 [package]
-edition = "2018"
+edition = "2021"
+rust-version = "1.63.0"
 name = "derive_arbitrary"
-version = "1.1.3"
+version = "1.2.0"
 authors = [
     "The Rust-Fuzz Project Developers",
     "Nick Fitzgerald <fitzgen@gmail.com>",
@@ -32,6 +33,7 @@
 categories = ["development-tools::testing"]
 license = "MIT/Apache-2.0"
 repository = "https://github.com/rust-fuzz/arbitrary"
+resolver = "1"
 
 [lib]
 proc_macro = true
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 6896426..f83eff0 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "derive_arbitrary"
-version = "1.1.3" # Make sure it matches the version of the arbitrary crate itself.
+version = "1.2.0" # Make sure it matches the version of the arbitrary crate itself.
 authors = [
     "The Rust-Fuzz Project Developers",
     "Nick Fitzgerald <fitzgen@gmail.com>",
@@ -9,13 +9,14 @@
     "Corey Farwell <coreyf@rwell.org>",
 ]
 categories = ["development-tools::testing"]
-edition = "2018"
+edition = "2021"
 keywords = ["arbitrary", "testing", "derive", "macro"]
 readme = "README.md"
 description = "Derives arbitrary traits"
 license = "MIT/Apache-2.0"
 repository = "https://github.com/rust-fuzz/arbitrary"
 documentation = "https://docs.rs/arbitrary/"
+rust-version = "1.63.0"
 
 [dependencies]
 proc-macro2 = "1.0"
diff --git a/METADATA b/METADATA
index 5ee0f1e..b3c0616 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/derive_arbitrary
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
 name: "derive_arbitrary"
 description: "Derives arbitrary traits"
 third_party {
@@ -7,13 +11,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/derive_arbitrary/derive_arbitrary-1.1.3.crate"
+    value: "https://static.crates.io/crates/derive_arbitrary/derive_arbitrary-1.2.0.crate"
   }
-  version: "1.1.3"
+  version: "1.2.0"
   license_type: NOTICE
   last_upgrade_date {
     year: 2022
-    month: 6
-    day: 27
+    month: 12
+    day: 5
   }
 }
diff --git a/src/field_attributes.rs b/src/field_attributes.rs
new file mode 100644
index 0000000..ccaba74
--- /dev/null
+++ b/src/field_attributes.rs
@@ -0,0 +1,117 @@
+use proc_macro2::{Group, Span, TokenStream, TokenTree};
+use quote::quote;
+use syn::{spanned::Spanned, *};
+
+/// Used to filter out necessary field attribute and within error messages.
+static ARBITRARY_ATTRIBUTE_NAME: &str = "arbitrary";
+
+/// Determines how a value for a field should be constructed.
+#[cfg_attr(test, derive(Debug))]
+pub enum FieldConstructor {
+    /// Assume that Arbitrary is defined for the type of this field and use it (default)
+    Arbitrary,
+
+    /// Places `Default::default()` as a field value.
+    Default,
+
+    /// Use custom function or closure to generate a value for a field.
+    With(TokenStream),
+
+    /// Set a field always to the given value.
+    Value(TokenStream),
+}
+
+pub fn determine_field_constructor(field: &Field) -> Result<FieldConstructor> {
+    let opt_attr = fetch_attr_from_field(field)?;
+    let ctor = match opt_attr {
+        Some(attr) => parse_attribute(attr)?,
+        None => FieldConstructor::Arbitrary,
+    };
+    Ok(ctor)
+}
+
+fn fetch_attr_from_field(field: &Field) -> Result<Option<&Attribute>> {
+    let found_attributes: Vec<_> = field
+        .attrs
+        .iter()
+        .filter(|a| {
+            let path = &a.path;
+            let name = quote!(#path).to_string();
+            name == ARBITRARY_ATTRIBUTE_NAME
+        })
+        .collect();
+    if found_attributes.len() > 1 {
+        let name = field.ident.as_ref().unwrap();
+        let msg = format!(
+            "Multiple conflicting #[{ARBITRARY_ATTRIBUTE_NAME}] attributes found on field `{name}`"
+        );
+        return Err(syn::Error::new(field.span(), msg));
+    }
+    Ok(found_attributes.into_iter().next())
+}
+
+fn parse_attribute(attr: &Attribute) -> Result<FieldConstructor> {
+    let group = {
+        let mut tokens_iter = attr.clone().tokens.into_iter();
+        let token = tokens_iter.next().ok_or_else(|| {
+            let msg = format!("#[{ARBITRARY_ATTRIBUTE_NAME}] cannot be empty.");
+            syn::Error::new(attr.span(), msg)
+        })?;
+        match token {
+            TokenTree::Group(g) => g,
+            t => {
+                let msg = format!("#[{ARBITRARY_ATTRIBUTE_NAME}] must contain a group, got: {t})");
+                return Err(syn::Error::new(attr.span(), msg));
+            }
+        }
+    };
+    parse_attribute_internals(group)
+}
+
+fn parse_attribute_internals(group: Group) -> Result<FieldConstructor> {
+    let stream = group.stream();
+    let mut tokens_iter = stream.into_iter();
+    let token = tokens_iter.next().ok_or_else(|| {
+        let msg = format!("#[{ARBITRARY_ATTRIBUTE_NAME}] cannot be empty.");
+        syn::Error::new(group.span(), msg)
+    })?;
+    match token.to_string().as_ref() {
+        "default" => Ok(FieldConstructor::Default),
+        "with" => {
+            let func_path = parse_assigned_value("with", tokens_iter, group.span())?;
+            Ok(FieldConstructor::With(func_path))
+        }
+        "value" => {
+            let value = parse_assigned_value("value", tokens_iter, group.span())?;
+            Ok(FieldConstructor::Value(value))
+        }
+        _ => {
+            let msg = format!("Unknown option for #[{ARBITRARY_ATTRIBUTE_NAME}]: `{token}`");
+            Err(syn::Error::new(token.span(), msg))
+        }
+    }
+}
+
+// Input:
+//     = 2 + 2
+// Output:
+//     2 + 2
+fn parse_assigned_value(
+    opt_name: &str,
+    mut tokens_iter: impl Iterator<Item = TokenTree>,
+    default_span: Span,
+) -> Result<TokenStream> {
+    let eq_sign = tokens_iter.next().ok_or_else(|| {
+        let msg = format!(
+            "Invalid syntax for #[{ARBITRARY_ATTRIBUTE_NAME}], `{opt_name}` is missing assignment."
+        );
+        syn::Error::new(default_span, msg)
+    })?;
+
+    if eq_sign.to_string() == "=" {
+        Ok(tokens_iter.collect())
+    } else {
+        let msg = format!("Invalid syntax for #[{ARBITRARY_ATTRIBUTE_NAME}], expected `=` after `{opt_name}`, got: `{eq_sign}`");
+        Err(syn::Error::new(eq_sign.span(), msg))
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 7b16a8d..4cd80b6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,11 +4,20 @@
 use quote::quote;
 use syn::*;
 
+mod field_attributes;
+use field_attributes::{determine_field_constructor, FieldConstructor};
+
 static ARBITRARY_LIFETIME_NAME: &str = "'arbitrary";
 
-#[proc_macro_derive(Arbitrary)]
+#[proc_macro_derive(Arbitrary, attributes(arbitrary))]
 pub fn derive_arbitrary(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
     let input = syn::parse_macro_input!(tokens as syn::DeriveInput);
+    expand_derive_arbitrary(input)
+        .unwrap_or_else(syn::Error::into_compile_error)
+        .into()
+}
+
+fn expand_derive_arbitrary(input: syn::DeriveInput) -> Result<TokenStream> {
     let (lifetime_without_bounds, lifetime_with_bounds) =
         build_arbitrary_lifetime(input.generics.clone());
 
@@ -18,8 +27,8 @@
     );
 
     let arbitrary_method =
-        gen_arbitrary_method(&input, lifetime_without_bounds.clone(), &recursive_count);
-    let size_hint_method = gen_size_hint_method(&input);
+        gen_arbitrary_method(&input, lifetime_without_bounds.clone(), &recursive_count)?;
+    let size_hint_method = gen_size_hint_method(&input)?;
     let name = input.ident;
     // Add a bound `T: Arbitrary` to every type parameter T.
     let generics = add_trait_bounds(input.generics, lifetime_without_bounds.clone());
@@ -34,7 +43,7 @@
     // Build TypeGenerics and WhereClause without a lifetime
     let (_, ty_generics, where_clause) = generics.split_for_impl();
 
-    (quote! {
+    Ok(quote! {
         const _: () = {
             thread_local! {
                 #[allow(non_upper_case_globals)]
@@ -47,7 +56,6 @@
             }
         };
     })
-    .into()
 }
 
 // Returns: (lifetime without bounds, lifetime with bounds)
@@ -112,18 +120,21 @@
     input: &DeriveInput,
     lifetime: LifetimeDef,
     recursive_count: &syn::Ident,
-) -> TokenStream {
-    let ident = &input.ident;
-
-    let arbitrary_structlike = |fields| {
-        let arbitrary = construct(fields, |_, _| quote!(arbitrary::Arbitrary::arbitrary(u)?));
+) -> Result<TokenStream> {
+    fn arbitrary_structlike(
+        fields: &Fields,
+        ident: &syn::Ident,
+        lifetime: LifetimeDef,
+        recursive_count: &syn::Ident,
+    ) -> Result<TokenStream> {
+        let arbitrary = construct(fields, |_idx, field| gen_constructor_for_field(field))?;
         let body = with_recursive_count_guard(recursive_count, quote! { Ok(#ident #arbitrary) });
 
-        let arbitrary_take_rest = construct_take_rest(fields);
+        let arbitrary_take_rest = construct_take_rest(fields)?;
         let take_rest_body =
             with_recursive_count_guard(recursive_count, quote! { Ok(#ident #arbitrary_take_rest) });
 
-        quote! {
+        Ok(quote! {
             fn arbitrary(u: &mut arbitrary::Unstructured<#lifetime>) -> arbitrary::Result<Self> {
                 #body
             }
@@ -131,27 +142,43 @@
             fn arbitrary_take_rest(mut u: arbitrary::Unstructured<#lifetime>) -> arbitrary::Result<Self> {
                 #take_rest_body
             }
-        }
-    };
+        })
+    }
 
-    match &input.data {
-        Data::Struct(data) => arbitrary_structlike(&data.fields),
-        Data::Union(data) => arbitrary_structlike(&Fields::Named(data.fields.clone())),
+    let ident = &input.ident;
+    let output = match &input.data {
+        Data::Struct(data) => arbitrary_structlike(&data.fields, ident, lifetime, recursive_count)?,
+        Data::Union(data) => arbitrary_structlike(
+            &Fields::Named(data.fields.clone()),
+            ident,
+            lifetime,
+            recursive_count,
+        )?,
         Data::Enum(data) => {
-            let variants = data.variants.iter().enumerate().map(|(i, variant)| {
-                let idx = i as u64;
-                let ctor = construct(&variant.fields, |_, _| {
-                    quote!(arbitrary::Arbitrary::arbitrary(u)?)
-                });
-                let variant_name = &variant.ident;
-                quote! { #idx => #ident::#variant_name #ctor }
-            });
-            let variants_take_rest = data.variants.iter().enumerate().map(|(i, variant)| {
-                let idx = i as u64;
-                let ctor = construct_take_rest(&variant.fields);
-                let variant_name = &variant.ident;
-                quote! { #idx => #ident::#variant_name #ctor }
-            });
+            let variants: Vec<TokenStream> = data
+                .variants
+                .iter()
+                .enumerate()
+                .map(|(i, variant)| {
+                    let idx = i as u64;
+                    let variant_name = &variant.ident;
+                    construct(&variant.fields, |_, field| gen_constructor_for_field(field))
+                        .map(|ctor| quote! { #idx => #ident::#variant_name #ctor })
+                })
+                .collect::<Result<_>>()?;
+
+            let variants_take_rest: Vec<TokenStream> = data
+                .variants
+                .iter()
+                .enumerate()
+                .map(|(i, variant)| {
+                    let idx = i as u64;
+                    let variant_name = &variant.ident;
+                    construct_take_rest(&variant.fields)
+                        .map(|ctor| quote! { #idx => #ident::#variant_name #ctor })
+                })
+                .collect::<Result<_>>()?;
+
             let count = data.variants.len() as u64;
 
             let arbitrary = with_recursive_count_guard(
@@ -190,74 +217,131 @@
                 }
             }
         }
-    }
+    };
+    Ok(output)
 }
 
-fn construct(fields: &Fields, ctor: impl Fn(usize, &Field) -> TokenStream) -> TokenStream {
-    match fields {
+fn construct(
+    fields: &Fields,
+    ctor: impl Fn(usize, &Field) -> Result<TokenStream>,
+) -> Result<TokenStream> {
+    let output = match fields {
         Fields::Named(names) => {
-            let names = names.named.iter().enumerate().map(|(i, f)| {
-                let name = f.ident.as_ref().unwrap();
-                let ctor = ctor(i, f);
-                quote! { #name: #ctor }
-            });
+            let names: Vec<TokenStream> = names
+                .named
+                .iter()
+                .enumerate()
+                .map(|(i, f)| {
+                    let name = f.ident.as_ref().unwrap();
+                    ctor(i, f).map(|ctor| quote! { #name: #ctor })
+                })
+                .collect::<Result<_>>()?;
             quote! { { #(#names,)* } }
         }
         Fields::Unnamed(names) => {
-            let names = names.unnamed.iter().enumerate().map(|(i, f)| {
-                let ctor = ctor(i, f);
-                quote! { #ctor }
-            });
+            let names: Vec<TokenStream> = names
+                .unnamed
+                .iter()
+                .enumerate()
+                .map(|(i, f)| ctor(i, f).map(|ctor| quote! { #ctor }))
+                .collect::<Result<_>>()?;
             quote! { ( #(#names),* ) }
         }
         Fields::Unit => quote!(),
-    }
+    };
+    Ok(output)
 }
 
-fn construct_take_rest(fields: &Fields) -> TokenStream {
-    construct(fields, |idx, _| {
-        if idx + 1 == fields.len() {
-            quote! { arbitrary::Arbitrary::arbitrary_take_rest(u)? }
-        } else {
-            quote! { arbitrary::Arbitrary::arbitrary(&mut u)? }
-        }
+fn construct_take_rest(fields: &Fields) -> Result<TokenStream> {
+    construct(fields, |idx, field| {
+        determine_field_constructor(field).map(|field_constructor| match field_constructor {
+            FieldConstructor::Default => quote!(Default::default()),
+            FieldConstructor::Arbitrary => {
+                if idx + 1 == fields.len() {
+                    quote! { arbitrary::Arbitrary::arbitrary_take_rest(u)? }
+                } else {
+                    quote! { arbitrary::Arbitrary::arbitrary(&mut u)? }
+                }
+            }
+            FieldConstructor::With(function_or_closure) => quote!((#function_or_closure)(&mut u)?),
+            FieldConstructor::Value(value) => quote!(#value),
+        })
     })
 }
 
-fn gen_size_hint_method(input: &DeriveInput) -> TokenStream {
+fn gen_size_hint_method(input: &DeriveInput) -> Result<TokenStream> {
     let size_hint_fields = |fields: &Fields| {
-        let tys = fields.iter().map(|f| &f.ty);
-        quote! {
-            arbitrary::size_hint::and_all(&[
-                #( <#tys as arbitrary::Arbitrary>::size_hint(depth) ),*
-            ])
-        }
+        fields
+            .iter()
+            .map(|f| {
+                let ty = &f.ty;
+                determine_field_constructor(f).map(|field_constructor| {
+                    match field_constructor {
+                        FieldConstructor::Default | FieldConstructor::Value(_) => {
+                            quote!((0, Some(0)))
+                        }
+                        FieldConstructor::Arbitrary => {
+                            quote! { <#ty as arbitrary::Arbitrary>::size_hint(depth) }
+                        }
+
+                        // Note that in this case it's hard to determine what size_hint must be, so size_of::<T>() is
+                        // just an educated guess, although it's gonna be inaccurate for dynamically
+                        // allocated types (Vec, HashMap, etc.).
+                        FieldConstructor::With(_) => {
+                            quote! { (::core::mem::size_of::<#ty>(), None) }
+                        }
+                    }
+                })
+            })
+            .collect::<Result<Vec<TokenStream>>>()
+            .map(|hints| {
+                quote! {
+                    arbitrary::size_hint::and_all(&[
+                        #( #hints ),*
+                    ])
+                }
+            })
     };
     let size_hint_structlike = |fields: &Fields| {
-        let hint = size_hint_fields(fields);
-        quote! {
-            #[inline]
-            fn size_hint(depth: usize) -> (usize, Option<usize>) {
-                arbitrary::size_hint::recursion_guard(depth, |depth| #hint)
+        size_hint_fields(fields).map(|hint| {
+            quote! {
+                #[inline]
+                fn size_hint(depth: usize) -> (usize, Option<usize>) {
+                    arbitrary::size_hint::recursion_guard(depth, |depth| #hint)
+                }
             }
-        }
+        })
     };
     match &input.data {
         Data::Struct(data) => size_hint_structlike(&data.fields),
         Data::Union(data) => size_hint_structlike(&Fields::Named(data.fields.clone())),
-        Data::Enum(data) => {
-            let variants = data.variants.iter().map(|v| size_hint_fields(&v.fields));
-            quote! {
-                #[inline]
-                fn size_hint(depth: usize) -> (usize, Option<usize>) {
-                    arbitrary::size_hint::and(
-                        <u32 as arbitrary::Arbitrary>::size_hint(depth),
-                        arbitrary::size_hint::recursion_guard(depth, |depth| {
-                            arbitrary::size_hint::or_all(&[ #( #variants ),* ])
-                        }),
-                    )
+        Data::Enum(data) => data
+            .variants
+            .iter()
+            .map(|v| size_hint_fields(&v.fields))
+            .collect::<Result<Vec<TokenStream>>>()
+            .map(|variants| {
+                quote! {
+                    #[inline]
+                    fn size_hint(depth: usize) -> (usize, Option<usize>) {
+                        arbitrary::size_hint::and(
+                            <u32 as arbitrary::Arbitrary>::size_hint(depth),
+                            arbitrary::size_hint::recursion_guard(depth, |depth| {
+                                arbitrary::size_hint::or_all(&[ #( #variants ),* ])
+                            }),
+                        )
+                    }
                 }
-            }
-        }
+            }),
     }
 }
+
+fn gen_constructor_for_field(field: &Field) -> Result<TokenStream> {
+    let ctor = match determine_field_constructor(field)? {
+        FieldConstructor::Default => quote!(Default::default()),
+        FieldConstructor::Arbitrary => quote!(arbitrary::Arbitrary::arbitrary(u)?),
+        FieldConstructor::With(function_or_closure) => quote!((#function_or_closure)(u)?),
+        FieldConstructor::Value(value) => quote!(#value),
+    };
+    Ok(ctor)
+}