Skip to content

Commit 92d146f

Browse files
committed
Replace (usize, Option<usize>) with custom type SizeHint and eliminate try_size_hint().
The `SizeHint` type provides these advantages: * Easier to construct by composition, using `&` and `|` or methods. * More self-explanatory. * Distinguishes between “unknown size” and “known to be unbounded” to aid debugging. Since this is a breaking change to the trait, this commit also makes the closely related change of combining `try_size_hint()` and `size_hint()` into a single fallible function. This will make it easier to correctly implement the trait. Also, while I was touching the macro code, I made all the crate paths absolute (`::arbitrary`), as they should be for the maximum compatibility.
1 parent d36482c commit 92d146f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+582
-566
lines changed

derive/src/lib.rs

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ fn expand_derive_arbitrary(input: syn::DeriveInput) -> Result<TokenStream> {
6464
}
6565

6666
#[automatically_derived]
67-
impl #impl_generics arbitrary::Arbitrary<#lifetime_without_bounds> for #name #ty_generics #where_clause {
67+
impl #impl_generics ::arbitrary::Arbitrary<#lifetime_without_bounds> for #name #ty_generics #where_clause {
6868
#arbitrary_method
6969
#size_hint_method
7070
}
@@ -141,7 +141,7 @@ fn add_trait_bounds(mut generics: Generics, lifetime: LifetimeParam) -> Generics
141141
if let GenericParam::Type(type_param) = param {
142142
type_param
143143
.bounds
144-
.push(parse_quote!(arbitrary::Arbitrary<#lifetime>));
144+
.push(parse_quote!(::arbitrary::Arbitrary<#lifetime>));
145145
}
146146
}
147147
generics
@@ -156,7 +156,7 @@ fn with_recursive_count_guard(
156156
if guard_against_recursion {
157157
#recursive_count.with(|count| {
158158
if count.get() > 0 {
159-
return Err(arbitrary::Error::NotEnoughData);
159+
return Err(::arbitrary::Error::NotEnoughData);
160160
}
161161
count.set(count.get() + 1);
162162
Ok(())
@@ -194,11 +194,11 @@ fn gen_arbitrary_method(
194194
with_recursive_count_guard(recursive_count, quote! { Ok(#ident #arbitrary_take_rest) });
195195

196196
Ok(quote! {
197-
fn arbitrary(u: &mut arbitrary::Unstructured<#lifetime>) -> arbitrary::Result<Self> {
197+
fn arbitrary(u: &mut ::arbitrary::Unstructured<#lifetime>) -> ::arbitrary::Result<Self> {
198198
#body
199199
}
200200

201-
fn arbitrary_take_rest(mut u: arbitrary::Unstructured<#lifetime>) -> arbitrary::Result<Self> {
201+
fn arbitrary_take_rest(mut u: ::arbitrary::Unstructured<#lifetime>) -> ::arbitrary::Result<Self> {
202202
#take_rest_body
203203
}
204204
})
@@ -225,7 +225,7 @@ fn gen_arbitrary_method(
225225
// Use a multiply + shift to generate a ranged random number
226226
// with slight bias. For details, see:
227227
// https://lemire.me/blog/2016/06/30/fast-random-shuffling
228-
Ok(match (u64::from(<u32 as arbitrary::Arbitrary>::arbitrary(#unstructured)?) * #count) >> 32 {
228+
Ok(match (u64::from(<u32 as ::arbitrary::Arbitrary>::arbitrary(#unstructured)?) * #count) >> 32 {
229229
#(#variants,)*
230230
_ => unreachable!()
231231
})
@@ -279,11 +279,11 @@ fn gen_arbitrary_method(
279279
let arbitrary_take_rest = arbitrary_enum_method(recursive_count, quote! { &mut u }, &variants_take_rest);
280280

281281
quote! {
282-
fn arbitrary(u: &mut arbitrary::Unstructured<#lifetime>) -> arbitrary::Result<Self> {
282+
fn arbitrary(u: &mut ::arbitrary::Unstructured<#lifetime>) -> ::arbitrary::Result<Self> {
283283
#arbitrary
284284
}
285285

286-
fn arbitrary_take_rest(mut u: arbitrary::Unstructured<#lifetime>) -> arbitrary::Result<Self> {
286+
fn arbitrary_take_rest(mut u: ::arbitrary::Unstructured<#lifetime>) -> ::arbitrary::Result<Self> {
287287
#arbitrary_take_rest
288288
}
289289
}
@@ -344,9 +344,9 @@ fn construct_take_rest(fields: &Fields) -> Result<TokenStream> {
344344
FieldConstructor::Default => quote!(::core::default::Default::default()),
345345
FieldConstructor::Arbitrary => {
346346
if idx + 1 == fields.len() {
347-
quote! { arbitrary::Arbitrary::arbitrary_take_rest(u)? }
347+
quote! { ::arbitrary::Arbitrary::arbitrary_take_rest(u)? }
348348
} else {
349-
quote! { arbitrary::Arbitrary::arbitrary(&mut u)? }
349+
quote! { ::arbitrary::Arbitrary::arbitrary(&mut u)? }
350350
}
351351
}
352352
FieldConstructor::With(function_or_closure) => quote!((#function_or_closure)(&mut u)?),
@@ -364,25 +364,25 @@ fn gen_size_hint_method(input: &DeriveInput) -> Result<TokenStream> {
364364
determine_field_constructor(f).map(|field_constructor| {
365365
match field_constructor {
366366
FieldConstructor::Default | FieldConstructor::Value(_) => {
367-
quote!(Ok((0, Some(0))))
367+
quote!(Ok(::arbitrary::SizeHint::exactly(0)))
368368
}
369369
FieldConstructor::Arbitrary => {
370-
quote! { <#ty as arbitrary::Arbitrary>::try_size_hint(depth) }
370+
quote! { <#ty as ::arbitrary::Arbitrary>::size_hint(depth) }
371371
}
372372

373373
// Note that in this case it's hard to determine what size_hint must be, so size_of::<T>() is
374374
// just an educated guess, although it's gonna be inaccurate for dynamically
375375
// allocated types (Vec, HashMap, etc.).
376376
FieldConstructor::With(_) => {
377-
quote! { Ok((::core::mem::size_of::<#ty>(), None)) }
377+
quote! { Ok(::arbitrary::SizeHint::at_least(::core::mem::size_of::<#ty>())) }
378378
}
379379
}
380380
})
381381
})
382382
.collect::<Result<Vec<TokenStream>>>()
383383
.map(|hints| {
384384
quote! {
385-
Ok(arbitrary::size_hint::and_all(&[
385+
Ok(::arbitrary::SizeHint::and_all(&[
386386
#( #hints? ),*
387387
]))
388388
}
@@ -392,13 +392,8 @@ fn gen_size_hint_method(input: &DeriveInput) -> Result<TokenStream> {
392392
size_hint_fields(fields).map(|hint| {
393393
quote! {
394394
#[inline]
395-
fn size_hint(depth: usize) -> (usize, ::core::option::Option<usize>) {
396-
Self::try_size_hint(depth).unwrap_or_default()
397-
}
398-
399-
#[inline]
400-
fn try_size_hint(depth: usize) -> ::core::result::Result<(usize, ::core::option::Option<usize>), arbitrary::MaxRecursionReached> {
401-
arbitrary::size_hint::try_recursion_guard(depth, |depth| #hint)
395+
fn size_hint(depth: usize) -> ::core::result::Result<::arbitrary::SizeHint, ::arbitrary::MaxRecursionReached> {
396+
::arbitrary::SizeHint::recursion_guard(depth, |depth| #hint)
402397
}
403398
}
404399
})
@@ -418,15 +413,12 @@ fn gen_size_hint_method(input: &DeriveInput) -> Result<TokenStream> {
418413
.collect::<Result<Vec<TokenStream>>>()
419414
.map(|variants| {
420415
quote! {
421-
fn size_hint(depth: usize) -> (usize, ::core::option::Option<usize>) {
422-
Self::try_size_hint(depth).unwrap_or_default()
423-
}
424416
#[inline]
425-
fn try_size_hint(depth: usize) -> ::core::result::Result<(usize, ::core::option::Option<usize>), arbitrary::MaxRecursionReached> {
426-
Ok(arbitrary::size_hint::and(
427-
<u32 as arbitrary::Arbitrary>::try_size_hint(depth)?,
428-
arbitrary::size_hint::try_recursion_guard(depth, |depth| {
429-
Ok(arbitrary::size_hint::or_all(&[ #( #variants? ),* ]))
417+
fn size_hint(depth: usize) -> ::core::result::Result<::arbitrary::SizeHint, ::arbitrary::MaxRecursionReached> {
418+
Ok(::arbitrary::SizeHint::and(
419+
<u32 as ::arbitrary::Arbitrary>::size_hint(depth)?,
420+
::arbitrary::SizeHint::recursion_guard(depth, |depth| {
421+
Ok(::arbitrary::SizeHint::or_all(&[ #( #variants? ),* ]))
430422
})?,
431423
))
432424
}
@@ -438,7 +430,7 @@ fn gen_size_hint_method(input: &DeriveInput) -> Result<TokenStream> {
438430
fn gen_constructor_for_field(field: &Field) -> Result<TokenStream> {
439431
let ctor = match determine_field_constructor(field)? {
440432
FieldConstructor::Default => quote!(::core::default::Default::default()),
441-
FieldConstructor::Arbitrary => quote!(arbitrary::Arbitrary::arbitrary(u)?),
433+
FieldConstructor::Arbitrary => quote!(::arbitrary::Arbitrary::arbitrary(u)?),
442434
FieldConstructor::With(function_or_closure) => quote!((#function_or_closure)(u)?),
443435
FieldConstructor::Value(value) => quote!(#value),
444436
};

src/foreign/alloc/borrow.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use {
2-
crate::{size_hint, Arbitrary, Result, Unstructured},
2+
crate::{Arbitrary, Result, SizeHint, Unstructured},
33
std::borrow::{Cow, ToOwned},
44
};
55

@@ -13,14 +13,9 @@ where
1313
}
1414

1515
#[inline]
16-
fn size_hint(depth: usize) -> (usize, Option<usize>) {
17-
Self::try_size_hint(depth).unwrap_or_default()
18-
}
19-
20-
#[inline]
21-
fn try_size_hint(depth: usize) -> Result<(usize, Option<usize>), crate::MaxRecursionReached> {
22-
size_hint::try_recursion_guard(depth, |depth| {
23-
<<A as ToOwned>::Owned as Arbitrary>::try_size_hint(depth)
16+
fn size_hint(depth: usize) -> Result<SizeHint, crate::MaxRecursionReached> {
17+
SizeHint::recursion_guard(depth, |depth| {
18+
<<A as ToOwned>::Owned as Arbitrary>::size_hint(depth)
2419
})
2520
}
2621
}

src/foreign/alloc/boxed.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use {
2-
crate::{size_hint, Arbitrary, Result, Unstructured},
2+
crate::{Arbitrary, MaxRecursionReached, Result, SizeHint, Unstructured},
33
std::boxed::Box,
44
};
55

@@ -12,13 +12,8 @@ where
1212
}
1313

1414
#[inline]
15-
fn size_hint(depth: usize) -> (usize, Option<usize>) {
16-
Self::try_size_hint(depth).unwrap_or_default()
17-
}
18-
19-
#[inline]
20-
fn try_size_hint(depth: usize) -> Result<(usize, Option<usize>), crate::MaxRecursionReached> {
21-
size_hint::try_recursion_guard(depth, <A as Arbitrary>::try_size_hint)
15+
fn size_hint(depth: usize) -> Result<SizeHint, crate::MaxRecursionReached> {
16+
SizeHint::recursion_guard(depth, <A as Arbitrary>::size_hint)
2217
}
2318
}
2419

@@ -35,8 +30,8 @@ where
3530
}
3631

3732
#[inline]
38-
fn size_hint(_depth: usize) -> (usize, Option<usize>) {
39-
(0, None)
33+
fn size_hint(_depth: usize) -> Result<SizeHint, MaxRecursionReached> {
34+
Ok(SizeHint::at_least(0))
4035
}
4136
}
4237

@@ -46,7 +41,7 @@ impl<'a> Arbitrary<'a> for Box<str> {
4641
}
4742

4843
#[inline]
49-
fn size_hint(depth: usize) -> (usize, Option<usize>) {
44+
fn size_hint(depth: usize) -> Result<SizeHint, MaxRecursionReached> {
5045
<String as Arbitrary>::size_hint(depth)
5146
}
5247
}

src/foreign/alloc/collections/binary_heap.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use {
2-
crate::{Arbitrary, Result, Unstructured},
2+
crate::{Arbitrary, MaxRecursionReached, Result, SizeHint, Unstructured},
33
std::collections::binary_heap::BinaryHeap,
44
};
55

@@ -16,7 +16,7 @@ where
1616
}
1717

1818
#[inline]
19-
fn size_hint(_depth: usize) -> (usize, Option<usize>) {
20-
(0, None)
19+
fn size_hint(_depth: usize) -> Result<SizeHint, MaxRecursionReached> {
20+
Ok(SizeHint::at_least(0))
2121
}
2222
}

src/foreign/alloc/collections/btree_map.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use {
2-
crate::{Arbitrary, Result, Unstructured},
2+
crate::{Arbitrary, MaxRecursionReached, Result, SizeHint, Unstructured},
33
std::collections::btree_map::BTreeMap,
44
};
55

@@ -17,7 +17,7 @@ where
1717
}
1818

1919
#[inline]
20-
fn size_hint(_depth: usize) -> (usize, Option<usize>) {
21-
(0, None)
20+
fn size_hint(_depth: usize) -> Result<SizeHint, MaxRecursionReached> {
21+
Ok(SizeHint::at_least(0))
2222
}
2323
}

src/foreign/alloc/collections/btree_set.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use {
2-
crate::{Arbitrary, Result, Unstructured},
2+
crate::{Arbitrary, MaxRecursionReached, Result, SizeHint, Unstructured},
33
std::collections::btree_set::BTreeSet,
44
};
55

@@ -16,7 +16,7 @@ where
1616
}
1717

1818
#[inline]
19-
fn size_hint(_depth: usize) -> (usize, Option<usize>) {
20-
(0, None)
19+
fn size_hint(_depth: usize) -> Result<SizeHint, MaxRecursionReached> {
20+
Ok(SizeHint::at_least(0))
2121
}
2222
}

src/foreign/alloc/collections/linked_list.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use {
2-
crate::{Arbitrary, Result, Unstructured},
2+
crate::{Arbitrary, MaxRecursionReached, Result, SizeHint, Unstructured},
33
std::collections::linked_list::LinkedList,
44
};
55

@@ -16,7 +16,7 @@ where
1616
}
1717

1818
#[inline]
19-
fn size_hint(_depth: usize) -> (usize, Option<usize>) {
20-
(0, None)
19+
fn size_hint(_depth: usize) -> Result<SizeHint, MaxRecursionReached> {
20+
Ok(SizeHint::at_least(0))
2121
}
2222
}

src/foreign/alloc/collections/vec_deque.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use {
2-
crate::{Arbitrary, Result, Unstructured},
2+
crate::{Arbitrary, MaxRecursionReached, Result, SizeHint, Unstructured},
33
std::collections::vec_deque::VecDeque,
44
};
55

@@ -16,7 +16,7 @@ where
1616
}
1717

1818
#[inline]
19-
fn size_hint(_depth: usize) -> (usize, Option<usize>) {
20-
(0, None)
19+
fn size_hint(_depth: usize) -> Result<SizeHint, MaxRecursionReached> {
20+
Ok(SizeHint::at_least(0))
2121
}
2222
}

src/foreign/alloc/ffi/c_str.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use {
2-
crate::{Arbitrary, Result, Unstructured},
2+
crate::{Arbitrary, MaxRecursionReached, Result, SizeHint, Unstructured},
33
std::ffi::CString,
44
};
55

@@ -13,7 +13,7 @@ impl<'a> Arbitrary<'a> for CString {
1313
}
1414

1515
#[inline]
16-
fn size_hint(depth: usize) -> (usize, Option<usize>) {
16+
fn size_hint(depth: usize) -> Result<SizeHint, MaxRecursionReached> {
1717
<Vec<u8> as Arbitrary>::size_hint(depth)
1818
}
1919
}

src/foreign/alloc/rc.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use {
2-
crate::{size_hint, Arbitrary, Result, Unstructured},
2+
crate::{Arbitrary, MaxRecursionReached, Result, SizeHint, Unstructured},
33
std::rc::Rc,
44
};
55

@@ -12,13 +12,8 @@ where
1212
}
1313

1414
#[inline]
15-
fn size_hint(depth: usize) -> (usize, Option<usize>) {
16-
Self::try_size_hint(depth).unwrap_or_default()
17-
}
18-
19-
#[inline]
20-
fn try_size_hint(depth: usize) -> Result<(usize, Option<usize>), crate::MaxRecursionReached> {
21-
size_hint::try_recursion_guard(depth, <A as Arbitrary>::try_size_hint)
15+
fn size_hint(depth: usize) -> Result<SizeHint, crate::MaxRecursionReached> {
16+
SizeHint::recursion_guard(depth, <A as Arbitrary>::size_hint)
2217
}
2318
}
2419

@@ -35,8 +30,8 @@ where
3530
}
3631

3732
#[inline]
38-
fn size_hint(_depth: usize) -> (usize, Option<usize>) {
39-
(0, None)
33+
fn size_hint(_depth: usize) -> Result<SizeHint, MaxRecursionReached> {
34+
Ok(SizeHint::at_least(0))
4035
}
4136
}
4237

@@ -46,7 +41,7 @@ impl<'a> Arbitrary<'a> for Rc<str> {
4641
}
4742

4843
#[inline]
49-
fn size_hint(depth: usize) -> (usize, Option<usize>) {
44+
fn size_hint(depth: usize) -> Result<SizeHint, MaxRecursionReached> {
5045
<&str as Arbitrary>::size_hint(depth)
5146
}
5247
}

src/foreign/alloc/string.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use {
2-
crate::{Arbitrary, Result, Unstructured},
2+
crate::{Arbitrary, MaxRecursionReached, Result, SizeHint, Unstructured},
33
std::string::String,
44
};
55

@@ -13,7 +13,7 @@ impl<'a> Arbitrary<'a> for String {
1313
}
1414

1515
#[inline]
16-
fn size_hint(depth: usize) -> (usize, Option<usize>) {
16+
fn size_hint(depth: usize) -> Result<SizeHint, MaxRecursionReached> {
1717
<&str as Arbitrary>::size_hint(depth)
1818
}
1919
}

0 commit comments

Comments
 (0)