Skip to content

Allow elided ('static) lifetimes in thread_local!#159564

Open
zachs18 wants to merge 2 commits into
rust-lang:mainfrom
zachs18:fix-159358
Open

Allow elided ('static) lifetimes in thread_local!#159564
zachs18 wants to merge 2 commits into
rust-lang:mainfrom
zachs18:fix-159358

Conversation

@zachs18

@zachs18 zachs18 commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

with or without a const initializer, on all platforms.

Lifetime elision includes named lifetimes and 'static, so if we give the macro-generated __rust_std_internal_init_fn function an argument mentioning 'static, then elided lifetimes in the return type default to 'static. This uses PhantomData<&'static ()> so that it should probably compile down to nothing (at least in release mode).

Before this change, elided 'static lifetimes were allowed only with const initializers on the "no-threads" and "native" thread_local! implementations, not on the "os" implementation, and not with non-const initializers.

After this change, they are allowed in all thread_local! implementations, with or without a const initializer (A and B both compile on targets with all three thread_local! implementations.)

// Const initializer
std::thread_local!(static A: &str = const { "" });
// Non-const initializer
std::thread_local!(static B: &str = "");
thread_local! implementation const initializer (A) non-const initializer (B)
no-threads (e.g. x86_64-unknown-uefi) ✅️ ❌️ -> ✅️
target_thread_local (e.g. x86_64-unknown-linux-gnu) ✅️ ❌️ -> ✅️
os (e.g. x86_64-pc-windows-gnu) ❌️ -> ✅️ ❌️ -> ✅️

An alternative implementation that would only fix the inconsistency, but not add support for elision with non-const initializers, would be to do this same thing, but only on the os implementation, and only if the initializer is const (i.e. split const initializers to a different macro arm; currently const and non-const initializers generate the same code under the os thread_local! implementation).

Fixes #159538

with or without a const initializer, on all platforms.
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jul 19, 2026
@rustbot

rustbot commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

r? @JohnTitor

rustbot has assigned @JohnTitor.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: @ChrisDenton, libs
  • @ChrisDenton, libs expanded to 13 candidates
  • Random selection from 6 candidates

@zachs18

zachs18 commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

Question for reviewer: (how) should I add a test for this? I tried adding a test to tests/ui/thread-local with revisions for different targets, but ui tests don't seem to build the stdlib for anything but the current target by default, so it failed with "could not find crate core" on the other two non-x86_64-unknown-linux-gnu targets unless I manually ran with --target x86_64-unknown-uefi or --target x86_64-pc-windows-gnu (in which case that target succeeded and the other non-native target still failed).

attempted UI test
// Test each of the three `thread_local!` implementations,
// that it defaults elided lifetimes in the type to `'static`.
// Regression test for 159358.
//@ check-pass

// no-threads
//@ revisions: x86_64-uefi
//@[x86_64-uefi] compile-flags: --target x86_64-unknown-uefi
//@[x86_64-uefi] needs-llvm-components: x86

// target_thread_local
//@ revisions: x86_64-linux
//@[x86_64-linux] compile-flags: --target x86_64-unknown-linux-gnu
//@[x86_64-linux] needs-llvm-components: x86

// os
//@ revisions: x86_64-windows-gnu
//@[x86_64-windows-gnu] compile-flags: --target x86_64-pc-windows-gnu
//@[x86_64-windows-gnu] needs-llvm-components: x86

// Const initializer, non-Drop
std::thread_local!(static A: &str = const { "" });
// Non-const initializer, non-Drop
std::thread_local!(static B: &str = "");

fn main() {}

(Dropness isn't relevant here)

@zachs18 zachs18 changed the title Allow elided ('static) lifetimes in #[thread_local] Allow elided ('static) lifetimes in thread_local! Jul 19, 2026
@zachs18

zachs18 commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

@rustbot label T-libs-api

I think this needs T-libs-api approval, at least for the non-const-initializer part?

@rustbot rustbot added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Jul 19, 2026
@rust-log-analyzer

This comment has been minimized.

It was testing diagnostics emitted for missing lifetime specifiers in `thread_local!`,
but now elided lifetimes in `thread_local!` are `'static`, so there's nothing to test.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Decl within thread_local! reports missing lifetime specifiers only on x86_64-pc-windows-gnu

4 participants