-
Notifications
You must be signed in to change notification settings - Fork 91
Avoid recursive count guard for fieldless enums #228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Avoid recursive count guard for fieldless enums #228
Conversation
It's simpler.
`u32` is not a recursive type, so there is no need to use `try_size_hint`.
Fieldless enums cannot trigger recursion. Avoiding the recursive count guard for them makes the generated code a lot smaller and faster.
|
Best reviewed one commit at a time. This change came about after I ran the compiler with the new An example: for const _: () = {
#[allow(non_upper_case_globals)]
const RECURSIVE_COUNT_Fieldless: ::std::thread::LocalKey<::core::cell::Cell<u32>> = {
const __INIT: ::core::cell::Cell<u32> = { ::core::cell::Cell::new(0) };
unsafe {
::std::thread::LocalKey::new(const {
if ::std::mem::needs_drop::<::core::cell::Cell<u32>>() {
|_| {
#[thread_local]
static VAL: ::std::thread::local_impl::EagerStorage<
::core::cell::Cell<u32>,
> = ::std::thread::local_impl::EagerStorage::new(__INIT);
VAL.get()
}
} else {
|_| {
#[thread_local]
static VAL: ::core::cell::Cell<u32> = __INIT;
&VAL
}
}
})
}
};
#[automatically_derived]
impl<'arbitrary> arbitrary::Arbitrary<'arbitrary> for Fieldless {
fn arbitrary(
u: &mut arbitrary::Unstructured<'arbitrary>,
) -> arbitrary::Result<Self> {
let guard_against_recursion = u.is_empty();
if guard_against_recursion {
RECURSIVE_COUNT_Fieldless
.with(|count| {
if count.get() > 0 {
return Err(arbitrary::Error::NotEnoughData);
}
count.set(count.get() + 1);
Ok(())
})?;
}
let result = (|| {
Ok(
match (u64::from(<u32 as arbitrary::Arbitrary>::arbitrary(u)?)
* 2u64) >> 32
{
0u64 => Fieldless::A,
1u64 => Fieldless::B,
_ => {
::core::panicking::panic(
"internal error: entered unreachable code",
)
}
},
)
})();
if guard_against_recursion {
RECURSIVE_COUNT_Fieldless
.with(|count| {
count.set(count.get() - 1);
});
}
result
}
fn arbitrary_take_rest(
mut u: arbitrary::Unstructured<'arbitrary>,
) -> arbitrary::Result<Self> {
let guard_against_recursion = u.is_empty();
if guard_against_recursion {
RECURSIVE_COUNT_Fieldless
.with(|count| {
if count.get() > 0 {
return Err(arbitrary::Error::NotEnoughData);
}
count.set(count.get() + 1);
Ok(())
})?;
}
let result = (|| {
Ok(
match (u64::from(<u32 as arbitrary::Arbitrary>::arbitrary(&mut u)?)
* 2u64) >> 32
{
0u64 => Fieldless::A,
1u64 => Fieldless::B,
_ => {
::core::panicking::panic(
"internal error: entered unreachable code",
)
}
},
)
})();
if guard_against_recursion {
RECURSIVE_COUNT_Fieldless
.with(|count| {
count.set(count.get() - 1);
});
}
result
}
fn size_hint(depth: usize) -> (usize, ::core::option::Option<usize>) {
Self::try_size_hint(depth).unwrap_or_default()
}
#[inline]
fn try_size_hint(
depth: usize,
) -> ::core::result::Result<
(usize, ::core::option::Option<usize>),
arbitrary::MaxRecursionReached,
> {
Ok(
arbitrary::size_hint::and(
<u32 as arbitrary::Arbitrary>::try_size_hint(depth)?,
arbitrary::size_hint::try_recursion_guard(
depth,
|depth| {
Ok(
arbitrary::size_hint::or_all(
&[
Ok(arbitrary::size_hint::and_all(&[]))?,
Ok(arbitrary::size_hint::and_all(&[]))?,
],
),
)
},
)?,
),
)
}
}
};The new generated code is this: const _: () = {
#[automatically_derived]
impl<'arbitrary> arbitrary::Arbitrary<'arbitrary> for Fieldless {
fn arbitrary(
u: &mut arbitrary::Unstructured<'arbitrary>,
) -> arbitrary::Result<Self> {
Ok(
match (u64::from(<u32 as arbitrary::Arbitrary>::arbitrary(u)?) * 2u64)
>> 32
{
0u64 => Fieldless::A,
1u64 => Fieldless::B,
_ => {
::core::panicking::panic(
"internal error: entered unreachable code",
)
}
},
)
}
fn arbitrary_take_rest(
mut u: arbitrary::Unstructured<'arbitrary>,
) -> arbitrary::Result<Self> {
Ok(
match (u64::from(<u32 as arbitrary::Arbitrary>::arbitrary(&mut u)?)
* 2u64) >> 32
{
0u64 => Fieldless::A,
1u64 => Fieldless::B,
_ => {
::core::panicking::panic(
"internal error: entered unreachable code",
)
}
},
)
}
fn size_hint(depth: usize) -> (usize, ::core::option::Option<usize>) {
<u32 as arbitrary::Arbitrary>::size_hint(depth)
}
}
}; |
fitzgen
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
Fieldless enums cannot trigger recursion. Avoiding the recursive count guard for them makes the generated code a lot smaller and faster.