diff options
author | Haibo Huang <hhb@google.com> | 2021-02-10 12:42:26 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-02-10 12:42:26 +0000 |
commit | 0527bafdf765c59465d8ca813c85edff696026d3 (patch) | |
tree | 6dc94fd6e23850663b29f797dde288a41e6eef78 | |
parent | 49f22523c3eb148cf71047fb6a43cf895c1cf447 (diff) | |
parent | d9012bc2cc6de16229ca3e546715296f338a5190 (diff) | |
download | derive_arbitrary-0527bafdf765c59465d8ca813c85edff696026d3.tar.gz |
Upgrade rust/crates/derive_arbitrary to 1.0.0-rc2 am: c16f810b6d am: 7849cd8689 am: 910c875070 am: d9012bc2cc
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/derive_arbitrary/+/1582217
MUST ONLY BE SUBMITTED BY AUTOMERGER
Change-Id: I2a8898577f7e794aba7c0d3b7d0230a8e1b61128
-rw-r--r-- | .cargo_vcs_info.json | 2 | ||||
-rw-r--r-- | Android.bp | 4 | ||||
-rw-r--r-- | Cargo.toml | 6 | ||||
-rw-r--r-- | Cargo.toml.orig | 12 | ||||
-rw-r--r-- | METADATA | 10 | ||||
-rw-r--r-- | src/lib.rs | 144 |
6 files changed, 66 insertions, 112 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index 79657dc..36e1045 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,5 +1,5 @@ { "git": { - "sha1": "ab4adcf12045858148e93e70b85a93559ae6e214" + "sha1": "89a6e201efdbfe6bd1495e15ded0b1a67d651525" } } @@ -14,6 +14,6 @@ rust_proc_macro { // dependent_library ["feature_list"] // proc-macro2-1.0.24 "default,proc-macro" -// quote-1.0.7 "default,proc-macro" -// syn-1.0.51 "clone-impls,default,derive,parsing,printing,proc-macro,quote" +// quote-1.0.8 "default,proc-macro" +// syn-1.0.60 "clone-impls,default,derive,parsing,printing,proc-macro,quote" // unicode-xid-0.2.1 "default" @@ -13,15 +13,15 @@ [package] edition = "2018" name = "derive_arbitrary" -version = "0.4.7" -authors = ["The Rust-Fuzz Project Developers", "Nick Fitzgerald <fitzgen@gmail.com>", "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>"] +version = "1.0.0-rc2" +authors = ["The Rust-Fuzz Project Developers", "Nick Fitzgerald <fitzgen@gmail.com>", "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>", "Corey Farwell <coreyf@rwell.org>"] description = "Derives arbitrary traits" documentation = "https://docs.rs/arbitrary/" readme = "README.md" keywords = ["arbitrary", "testing", "derive", "macro"] categories = ["development-tools::testing"] license = "MIT/Apache-2.0" -repository = "https://github.com/nagisa/rust_arbitrary" +repository = "https://github.com/rust-fuzz/arbitrary" [lib] proc_macro = true diff --git a/Cargo.toml.orig b/Cargo.toml.orig index f084540..09fc58a 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,14 +1,20 @@ [package] name = "derive_arbitrary" -version = "0.4.7" # Make sure it matches the version of the arbitrary crate itself. -authors = ["The Rust-Fuzz Project Developers", "Nick Fitzgerald <fitzgen@gmail.com>", "Manish Goregaokar <manishsmail@gmail.com>", "Andre Bogus <bogusandre@gmail.com>"] +version = "1.0.0-rc2" # Make sure it matches the version of the arbitrary crate itself. +authors = [ + "The Rust-Fuzz Project Developers", + "Nick Fitzgerald <fitzgen@gmail.com>", + "Manish Goregaokar <manishsmail@gmail.com>", + "Andre Bogus <bogusandre@gmail.com>", + "Corey Farwell <coreyf@rwell.org>", +] categories = ["development-tools::testing"] edition = "2018" keywords = ["arbitrary", "testing", "derive", "macro"] readme = "README.md" description = "Derives arbitrary traits" license = "MIT/Apache-2.0" -repository = "https://github.com/nagisa/rust_arbitrary" +repository = "https://github.com/rust-fuzz/arbitrary" documentation = "https://docs.rs/arbitrary/" [dependencies] @@ -7,13 +7,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/derive_arbitrary/derive_arbitrary-0.4.7.crate" + value: "https://static.crates.io/crates/derive_arbitrary/derive_arbitrary-1.0.0-rc2.crate" } - version: "0.4.7" + version: "1.0.0-rc2" license_type: NOTICE last_upgrade_date { - year: 2020 - month: 11 - day: 17 + year: 2021 + month: 2 + day: 9 } } @@ -1,51 +1,83 @@ extern crate proc_macro; -use proc_macro2::{Literal, TokenStream}; +use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::*; +static ARBITRARY_LIFETIME_NAME: &str = "'arbitrary"; + #[proc_macro_derive(Arbitrary)] pub fn derive_arbitrary(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream { let input = syn::parse_macro_input!(tokens as syn::DeriveInput); + let (lifetime_without_bounds, lifetime_with_bounds) = + build_arbitrary_lifetime(input.generics.clone()); - let arbitrary_method = gen_arbitrary_method(&input); + let arbitrary_method = gen_arbitrary_method(&input, lifetime_without_bounds.clone()); let size_hint_method = gen_size_hint_method(&input); - let shrink_method = gen_shrink_method(&input); let name = input.ident; // Add a bound `T: Arbitrary` to every type parameter T. - let generics = add_trait_bounds(input.generics); - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let generics = add_trait_bounds(input.generics, lifetime_without_bounds.clone()); + + // Build ImplGeneric with a lifetime (https://github.com/dtolnay/syn/issues/90) + let mut generics_with_lifetime = generics.clone(); + generics_with_lifetime + .params + .push(GenericParam::Lifetime(lifetime_with_bounds)); + let (impl_generics, _, _) = generics_with_lifetime.split_for_impl(); + + // Build TypeGenerics and WhereClause without a lifetime + let (_, ty_generics, where_clause) = generics.split_for_impl(); + (quote! { - impl #impl_generics arbitrary::Arbitrary for #name #ty_generics #where_clause { + impl #impl_generics arbitrary::Arbitrary<#lifetime_without_bounds> for #name #ty_generics #where_clause { #arbitrary_method #size_hint_method - #shrink_method } }) .into() } +// Returns: (lifetime without bounds, lifetime with bounds) +// Example: ("'arbitrary", "'arbitrary: 'a + 'b") +fn build_arbitrary_lifetime(generics: Generics) -> (LifetimeDef, LifetimeDef) { + let lifetime_without_bounds = + LifetimeDef::new(Lifetime::new(ARBITRARY_LIFETIME_NAME, Span::call_site())); + let mut lifetime_with_bounds = lifetime_without_bounds.clone(); + + for param in generics.params.iter() { + if let GenericParam::Lifetime(lifetime_def) = param { + lifetime_with_bounds + .bounds + .push(lifetime_def.lifetime.clone()); + } + } + + (lifetime_without_bounds, lifetime_with_bounds) +} + // Add a bound `T: Arbitrary` to every type parameter T. -fn add_trait_bounds(mut generics: Generics) -> Generics { +fn add_trait_bounds(mut generics: Generics, lifetime: LifetimeDef) -> Generics { for param in generics.params.iter_mut() { if let GenericParam::Type(type_param) = param { - type_param.bounds.push(parse_quote!(arbitrary::Arbitrary)); + type_param + .bounds + .push(parse_quote!(arbitrary::Arbitrary<#lifetime>)); } } generics } -fn gen_arbitrary_method(input: &DeriveInput) -> TokenStream { +fn gen_arbitrary_method(input: &DeriveInput, lifetime: LifetimeDef) -> TokenStream { let ident = &input.ident; let arbitrary_structlike = |fields| { let arbitrary = construct(fields, |_, _| quote!(arbitrary::Arbitrary::arbitrary(u)?)); let arbitrary_take_rest = construct_take_rest(fields); quote! { - fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> { + fn arbitrary(u: &mut arbitrary::Unstructured<#lifetime>) -> arbitrary::Result<Self> { Ok(#ident #arbitrary) } - fn arbitrary_take_rest(mut u: arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> { + fn arbitrary_take_rest(mut u: arbitrary::Unstructured<#lifetime>) -> arbitrary::Result<Self> { Ok(#ident #arbitrary_take_rest) } } @@ -70,7 +102,7 @@ fn gen_arbitrary_method(input: &DeriveInput) -> TokenStream { }); let count = data.variants.len() as u64; quote! { - fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> { + fn arbitrary(u: &mut arbitrary::Unstructured<#lifetime>) -> arbitrary::Result<Self> { // Use a multiply + shift to generate a ranged random number // with slight bias. For details, see: // https://lemire.me/blog/2016/06/30/fast-random-shuffling @@ -80,7 +112,7 @@ fn gen_arbitrary_method(input: &DeriveInput) -> TokenStream { }) } - fn arbitrary_take_rest(mut u: arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> { + fn arbitrary_take_rest(mut u: arbitrary::Unstructured<#lifetime>) -> arbitrary::Result<Self> { // Use a multiply + shift to generate a ranged random number // with slight bias. For details, see: // https://lemire.me/blog/2016/06/30/fast-random-shuffling @@ -162,87 +194,3 @@ fn gen_size_hint_method(input: &DeriveInput) -> TokenStream { } } } - -fn gen_shrink_method(input: &DeriveInput) -> TokenStream { - let ident = &input.ident; - let shrink_structlike = |fields| { - let inner = shrink("e!(#ident), fields, |i, field| match &field.ident { - Some(i) => quote!(&self.#i), - None => { - let i = Literal::usize_unsuffixed(i); - quote!(&self.#i) - } - }); - quote! { - fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { - #inner - } - } - }; - - return match &input.data { - Data::Struct(data) => shrink_structlike(&data.fields), - Data::Union(data) => shrink_structlike(&Fields::Named(data.fields.clone())), - Data::Enum(data) => { - let variants = data.variants.iter().map(|variant| { - let mut binding_names = Vec::new(); - let bindings = match &variant.fields { - Fields::Named(_) => { - let names = variant.fields.iter().map(|f| { - let name = f.ident.as_ref().unwrap(); - binding_names.push(quote!(#name)); - name - }); - quote!({#(#names),*}) - } - Fields::Unnamed(_) => { - let names = (0..variant.fields.len()).map(|i| { - let name = quote::format_ident!("f{}", i); - binding_names.push(quote!(#name)); - name - }); - quote!((#(#names),*)) - } - Fields::Unit => quote!(), - }; - let variant_name = &variant.ident; - let shrink = shrink("e!(#ident::#variant_name), &variant.fields, |i, _| { - binding_names[i].clone() - }); - quote!(#ident::#variant_name #bindings => { #shrink }) - }); - quote! { - fn shrink(&self) -> Box<dyn Iterator<Item = Self>> { - match self { - #(#variants)* - } - } - } - } - }; - - fn shrink( - prefix: &TokenStream, - fields: &Fields, - access_field: impl Fn(usize, &Field) -> TokenStream, - ) -> TokenStream { - if fields.len() == 0 { - return quote!(Box::new(None.into_iter())); - } - let iters = fields.iter().enumerate().map(|(i, f)| { - let name = quote::format_ident!("field{}", i); - let field = access_field(i, f); - quote! { let mut #name = arbitrary::Arbitrary::shrink(#field); } - }); - let ctor = construct(fields, |i, _| { - let iter = quote::format_ident!("field{}", i); - quote!(#iter.next()?) - }); - quote! { - #(#iters)* - Box::new(std::iter::from_fn(move || { - Some(#prefix #ctor) - })) - } - } -} |