Skip to content
/ rust Public
forked from rust-lang/rust

Commit a9d80cb

Browse files
authored
Rollup merge of rust-lang#131866 - jieyouxu:thread_local, r=jhpratt
Avoid use imports in `thread_local_inner!` Previously, the use imports in `thread_local_inner!` can shadow user-provided types or type aliases of the names `Storage`, `EagerStorage`, `LocalStorage` and `LocalKey`. This PR fixes that by dropping the use imports and instead refer to the std-internal types via fully qualified paths. A basic test is added to ensure `thread_local!`s with static decls with type names that match the aforementioned std-internal type names can successfully compile. Fixes rust-lang#131863.
2 parents c4edbb2 + 7b2320c commit a9d80cb

File tree

3 files changed

+49
-22
lines changed

3 files changed

+49
-22
lines changed

library/std/src/sys/thread_local/native/mod.rs

+15-16
Original file line numberDiff line numberDiff line change
@@ -49,20 +49,21 @@ pub use lazy::Storage as LazyStorage;
4949
#[unstable(feature = "thread_local_internals", issue = "none")]
5050
#[rustc_macro_transparency = "semitransparent"]
5151
pub macro thread_local_inner {
52-
// used to generate the `LocalKey` value for const-initialized thread locals
52+
// NOTE: we cannot import `LocalKey`, `LazyStorage` or `EagerStorage` with a `use` because that
53+
// can shadow user provided type or type alias with a matching name. Please update the shadowing
54+
// test in `tests/thread.rs` if these types are renamed.
55+
56+
// Used to generate the `LocalKey` value for const-initialized thread locals.
5357
(@key $t:ty, const $init:expr) => {{
5458
const __INIT: $t = $init;
5559

5660
unsafe {
57-
use $crate::mem::needs_drop;
58-
use $crate::thread::LocalKey;
59-
use $crate::thread::local_impl::EagerStorage;
60-
61-
LocalKey::new(const {
62-
if needs_drop::<$t>() {
61+
$crate::thread::LocalKey::new(const {
62+
if $crate::mem::needs_drop::<$t>() {
6363
|_| {
6464
#[thread_local]
65-
static VAL: EagerStorage<$t> = EagerStorage::new(__INIT);
65+
static VAL: $crate::thread::local_impl::EagerStorage<$t>
66+
= $crate::thread::local_impl::EagerStorage::new(__INIT);
6667
VAL.get()
6768
}
6869
} else {
@@ -84,21 +85,19 @@ pub macro thread_local_inner {
8485
}
8586

8687
unsafe {
87-
use $crate::mem::needs_drop;
88-
use $crate::thread::LocalKey;
89-
use $crate::thread::local_impl::LazyStorage;
90-
91-
LocalKey::new(const {
92-
if needs_drop::<$t>() {
88+
$crate::thread::LocalKey::new(const {
89+
if $crate::mem::needs_drop::<$t>() {
9390
|init| {
9491
#[thread_local]
95-
static VAL: LazyStorage<$t, ()> = LazyStorage::new();
92+
static VAL: $crate::thread::local_impl::LazyStorage<$t, ()>
93+
= $crate::thread::local_impl::LazyStorage::new();
9694
VAL.get_or_init(init, __init)
9795
}
9896
} else {
9997
|init| {
10098
#[thread_local]
101-
static VAL: LazyStorage<$t, !> = LazyStorage::new();
99+
static VAL: $crate::thread::local_impl::LazyStorage<$t, !>
100+
= $crate::thread::local_impl::LazyStorage::new();
102101
VAL.get_or_init(init, __init)
103102
}
104103
}

library/std/src/sys/thread_local/os.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,24 @@ pub macro thread_local_inner {
1515
$crate::thread::local_impl::thread_local_inner!(@key $t, { const INIT_EXPR: $t = $init; INIT_EXPR })
1616
},
1717

18-
// used to generate the `LocalKey` value for `thread_local!`
18+
// NOTE: we cannot import `Storage` or `LocalKey` with a `use` because that can shadow user
19+
// provided type or type alias with a matching name. Please update the shadowing test in
20+
// `tests/thread.rs` if these types are renamed.
21+
22+
// used to generate the `LocalKey` value for `thread_local!`.
1923
(@key $t:ty, $init:expr) => {{
2024
#[inline]
2125
fn __init() -> $t { $init }
2226

27+
// NOTE: this cannot import `LocalKey` or `Storage` with a `use` because that can shadow
28+
// user provided type or type alias with a matching name. Please update the shadowing test
29+
// in `tests/thread.rs` if these types are renamed.
2330
unsafe {
24-
use $crate::thread::LocalKey;
25-
use $crate::thread::local_impl::Storage;
26-
2731
// Inlining does not work on windows-gnu due to linking errors around
2832
// dllimports. See https://github.com/rust-lang/rust/issues/109797.
29-
LocalKey::new(#[cfg_attr(windows, inline(never))] |init| {
30-
static VAL: Storage<$t> = Storage::new();
33+
$crate::thread::LocalKey::new(#[cfg_attr(windows, inline(never))] |init| {
34+
static VAL: $crate::thread::local_impl::Storage<$t>
35+
= $crate::thread::local_impl::Storage::new();
3136
VAL.get(init, __init)
3237
})
3338
}

library/std/tests/thread.rs

+23
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,29 @@ fn thread_local_containing_const_statements() {
3838
assert_eq!(REFCELL.take(), 1);
3939
}
4040

41+
#[test]
42+
fn thread_local_hygeiene() {
43+
// Previously `thread_local_inner!` had use imports for `LocalKey`, `Storage`, `EagerStorage`
44+
// and `LazyStorage`. The use imports will shadow a user-provided type or type alias if the
45+
// user-provided type or type alias has the same name. Make sure that this does not happen. See
46+
// <https://github.com/rust-lang/rust/issues/131863>.
47+
//
48+
// NOTE: if the internal implementation details change (i.e. get renamed), this test should be
49+
// updated.
50+
51+
#![allow(dead_code)]
52+
type LocalKey = ();
53+
type Storage = ();
54+
type LazyStorage = ();
55+
type EagerStorage = ();
56+
thread_local! {
57+
static A: LocalKey = const { () };
58+
static B: Storage = const { () };
59+
static C: LazyStorage = const { () };
60+
static D: EagerStorage = const { () };
61+
}
62+
}
63+
4164
#[test]
4265
// Include an ignore list on purpose, so that new platforms don't miss it
4366
#[cfg_attr(

0 commit comments

Comments
 (0)