Skip to content

Conversation

@nnethercote
Copy link
Contributor

From the thread_local docs:

This macro supports a special const {} syntax that can be used when
the initialization expression can be evaluated as a constant. This can
enable a more efficient thread local implementation that can avoid
lazy initialization. For types that do not need to be dropped, this
can enable an even more efficient implementation that does not need to
track any additional state.

The RECURSIVE_COUNT_* values currently don't use this, but they can. This changes the generated code from this:

    #[allow(non_upper_case_globals)]
    const RECURSIVE_COUNT_Example: ::std::thread::LocalKey<::core::cell::Cell<u32>> = {
        #[inline]
        fn __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>>() {
                    |init| {
                        #[thread_local]
                        static VAL: ::std::thread::local_impl::LazyStorage<
                            ::core::cell::Cell<u32>,
                            (),
                        > = ::std::thread::local_impl::LazyStorage::new();
                        VAL.get_or_init(init, __init)
                    }
                } else {
                    |init| {
                        #[thread_local]
                        static VAL: ::std::thread::local_impl::LazyStorage<
                            ::core::cell::Cell<u32>,
                            !,
                        > = ::std::thread::local_impl::LazyStorage::new();
                        VAL.get_or_init(init, __init)
                    }
                }
            })
        }
    };

to this:

    #[allow(non_upper_case_globals)]
    const RECURSIVE_COUNT_Example: ::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
                    }
                }
            })
        }
    };

Note in both cases the else block is the relevant one because Cell<u32> doesn't need drop.

From the `thread_local` docs:

> This macro supports a special `const {}` syntax that can be used when
> the initialization expression can be evaluated as a constant. This can
> enable a more efficient thread local implementation that can avoid
> lazy initialization. For types that do not need to be dropped, this
> can enable an even more efficient implementation that does not need to
> track any additional state.

The `RECURSIVE_COUNT_*` values currently don't use this, but they can.
This changes the generated code from this:
```
    #[allow(non_upper_case_globals)]
    const RECURSIVE_COUNT_Example: ::std::thread::LocalKey<::core::cell::Cell<u32>> = {
        #[inline]
        fn __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>>() {
                    |init| {
                        #[thread_local]
                        static VAL: ::std::thread::local_impl::LazyStorage<
                            ::core::cell::Cell<u32>,
                            (),
                        > = ::std::thread::local_impl::LazyStorage::new();
                        VAL.get_or_init(init, __init)
                    }
                } else {
                    |init| {
                        #[thread_local]
                        static VAL: ::std::thread::local_impl::LazyStorage<
                            ::core::cell::Cell<u32>,
                            !,
                        > = ::std::thread::local_impl::LazyStorage::new();
                        VAL.get_or_init(init, __init)
                    }
                }
            })
        }
    };
```
to this:
```
    #[allow(non_upper_case_globals)]
    const RECURSIVE_COUNT_Example: ::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
                    }
                }
            })
        }
    };
```
Note in both cases the `else` block is the relevant one because
`Cell<u32>` doesn't need drop.
Copy link
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! Thanks!

@fitzgen fitzgen merged commit 9029685 into rust-fuzz:main Aug 7, 2025
6 checks passed
@nnethercote nnethercote deleted the const-recursive_count branch August 7, 2025 22:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants