Skip to content

thread_local! has some shadowing issues #147006

@Jules-Bertholet

Description

@Jules-Bertholet

I tried this code:

fn __init() -> u32 { 17 } const __INIT: u32 = 17; const VAL: usize = 0; thread_local! { static FOO: u32 = __init(); static BAR: u32 = const { __INIT }; static BAZ: [u32; VAL] = const { [] }; } fn main() { FOO.with(|&s| assert_eq!(s, 17)); BAR.with(|&s| assert_eq!(s, 17)); BAZ.with(|&s| assert_eq!(s, [])); }

I expected to see this happen: It compiles and runs successfully

Instead, this happened: A bunch of compile errors. If BAR and BAZ are commented out, initializing FOO triggers a stack overflow.

The cause of these issues is shadowing inside thread_local_inner!. rustc_macro_transparency = "opaque" should fix it, but is blocked on fixing #146993.

Meta

rustc --version:

1.92.0-nightly (2025-09-23 975e6c8fec280816d24f) 
Backtrace

error[E0391]: cycle detected when computing type of `BAZ::{constant#1}::{closure#0}::VAL` --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ | note: ...which requires evaluating type-level constant... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires const-evaluating + checking `BAZ::{constant#1}::{closure#0}::VAL::{constant#0}`... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires caching mir of `BAZ::{constant#1}::{closure#0}::VAL::{constant#0}` for CTFE... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires elaborating drops for `BAZ::{constant#1}::{closure#0}::VAL::{constant#0}`... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires borrow-checking `BAZ::{constant#1}::{closure#0}::VAL::{constant#0}`... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires promoting constants in MIR for `BAZ::{constant#1}::{closure#0}::VAL::{constant#0}`... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires const checking `BAZ::{constant#1}::{closure#0}::VAL::{constant#0}`... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires building MIR for `BAZ::{constant#1}::{closure#0}::VAL::{constant#0}`... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires match-checking `BAZ::{constant#1}::{closure#0}::VAL::{constant#0}`... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires type-checking `BAZ::{constant#1}::{closure#0}::VAL::{constant#0}`... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ = note: ...which again requires computing type of `BAZ::{constant#1}::{closure#0}::VAL`, completing the cycle note: cycle used when checking that `BAZ::{constant#1}::{closure#0}::VAL` is well-formed --> src/main.rs:7:1 | 7 | / thread_local! { 8 | | static FOO: u32 = __init(); 9 | | static BAR: u32 = const { __INIT }; 10 | | static BAZ: [u32; VAL] = const { [] }; 11 | | } | |_^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0391]: cycle detected when computing type of `BAZ::{constant#1}::{closure#1}::VAL` --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ | note: ...which requires evaluating type-level constant... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires const-evaluating + checking `BAZ::{constant#1}::{closure#1}::VAL::{constant#0}`... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires caching mir of `BAZ::{constant#1}::{closure#1}::VAL::{constant#0}` for CTFE... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires elaborating drops for `BAZ::{constant#1}::{closure#1}::VAL::{constant#0}`... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires borrow-checking `BAZ::{constant#1}::{closure#1}::VAL::{constant#0}`... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires promoting constants in MIR for `BAZ::{constant#1}::{closure#1}::VAL::{constant#0}`... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires const checking `BAZ::{constant#1}::{closure#1}::VAL::{constant#0}`... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires building MIR for `BAZ::{constant#1}::{closure#1}::VAL::{constant#0}`... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires match-checking `BAZ::{constant#1}::{closure#1}::VAL::{constant#0}`... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ note: ...which requires type-checking `BAZ::{constant#1}::{closure#1}::VAL::{constant#0}`... --> src/main.rs:10:23 | 10 | static BAZ: [u32; VAL] = const { [] }; | ^^^ = note: ...which again requires computing type of `BAZ::{constant#1}::{closure#1}::VAL`, completing the cycle note: cycle used when checking that `BAZ::{constant#1}::{closure#1}::VAL` is well-formed --> src/main.rs:7:1 | 7 | / thread_local! { 8 | | static FOO: u32 = __init(); 9 | | static BAR: u32 = const { __INIT }; 10 | | static BAZ: [u32; VAL] = const { [] }; 11 | | } | |_^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0391]: cycle detected when simplifying constant for the type system `BAR::__INIT` --> src/main.rs:7:1 | 7 | / thread_local! { 8 | | static FOO: u32 = __init(); 9 | | static BAR: u32 = const { __INIT }; 10 | | static BAZ: [u32; VAL] = const { [] }; 11 | | } | |_^ | note: ...which requires const-evaluating + checking `BAR::__INIT`... --> src/main.rs:9:31 | 9 | static BAR: u32 = const { __INIT }; | ^^^^^^ = note: ...which again requires simplifying constant for the type system `BAR::__INIT`, completing the cycle = note: cycle used when running analysis passes on this crate = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) For more information about this error, try `rustc --explain E0391`. 

@rustbot label T-libs A-macros A-thread-locals A-hygiene

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-hygieneArea: Macro hygieneA-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)A-thread-localsArea: Thread local storage (TLS)C-bugCategory: This is a bug.T-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions