Avoid shadowing user provided types or type aliases in thread_local!
By using qualified imports, i.e. `$crate::...::LocalKey`.
This commit is contained in:
parent
d9c4b8d475
commit
7b2320c3df
@ -49,20 +49,21 @@
|
|||||||
#[unstable(feature = "thread_local_internals", issue = "none")]
|
#[unstable(feature = "thread_local_internals", issue = "none")]
|
||||||
#[rustc_macro_transparency = "semitransparent"]
|
#[rustc_macro_transparency = "semitransparent"]
|
||||||
pub macro thread_local_inner {
|
pub macro thread_local_inner {
|
||||||
// used to generate the `LocalKey` value for const-initialized thread locals
|
// NOTE: we cannot import `LocalKey`, `LazyStorage` or `EagerStorage` with a `use` because that
|
||||||
|
// can shadow user provided type or type alias with a matching name. Please update the shadowing
|
||||||
|
// test in `tests/thread.rs` if these types are renamed.
|
||||||
|
|
||||||
|
// Used to generate the `LocalKey` value for const-initialized thread locals.
|
||||||
(@key $t:ty, const $init:expr) => {{
|
(@key $t:ty, const $init:expr) => {{
|
||||||
const __INIT: $t = $init;
|
const __INIT: $t = $init;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
use $crate::mem::needs_drop;
|
$crate::thread::LocalKey::new(const {
|
||||||
use $crate::thread::LocalKey;
|
if $crate::mem::needs_drop::<$t>() {
|
||||||
use $crate::thread::local_impl::EagerStorage;
|
|
||||||
|
|
||||||
LocalKey::new(const {
|
|
||||||
if needs_drop::<$t>() {
|
|
||||||
|_| {
|
|_| {
|
||||||
#[thread_local]
|
#[thread_local]
|
||||||
static VAL: EagerStorage<$t> = EagerStorage::new(__INIT);
|
static VAL: $crate::thread::local_impl::EagerStorage<$t>
|
||||||
|
= $crate::thread::local_impl::EagerStorage::new(__INIT);
|
||||||
VAL.get()
|
VAL.get()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -84,21 +85,19 @@ fn __init() -> $t {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
use $crate::mem::needs_drop;
|
$crate::thread::LocalKey::new(const {
|
||||||
use $crate::thread::LocalKey;
|
if $crate::mem::needs_drop::<$t>() {
|
||||||
use $crate::thread::local_impl::LazyStorage;
|
|
||||||
|
|
||||||
LocalKey::new(const {
|
|
||||||
if needs_drop::<$t>() {
|
|
||||||
|init| {
|
|init| {
|
||||||
#[thread_local]
|
#[thread_local]
|
||||||
static VAL: LazyStorage<$t, ()> = LazyStorage::new();
|
static VAL: $crate::thread::local_impl::LazyStorage<$t, ()>
|
||||||
|
= $crate::thread::local_impl::LazyStorage::new();
|
||||||
VAL.get_or_init(init, __init)
|
VAL.get_or_init(init, __init)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|init| {
|
|init| {
|
||||||
#[thread_local]
|
#[thread_local]
|
||||||
static VAL: LazyStorage<$t, !> = LazyStorage::new();
|
static VAL: $crate::thread::local_impl::LazyStorage<$t, !>
|
||||||
|
= $crate::thread::local_impl::LazyStorage::new();
|
||||||
VAL.get_or_init(init, __init)
|
VAL.get_or_init(init, __init)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,19 +15,24 @@
|
|||||||
$crate::thread::local_impl::thread_local_inner!(@key $t, { const INIT_EXPR: $t = $init; INIT_EXPR })
|
$crate::thread::local_impl::thread_local_inner!(@key $t, { const INIT_EXPR: $t = $init; INIT_EXPR })
|
||||||
},
|
},
|
||||||
|
|
||||||
// used to generate the `LocalKey` value for `thread_local!`
|
// NOTE: we cannot import `Storage` or `LocalKey` with a `use` because that can shadow user
|
||||||
|
// provided type or type alias with a matching name. Please update the shadowing test in
|
||||||
|
// `tests/thread.rs` if these types are renamed.
|
||||||
|
|
||||||
|
// used to generate the `LocalKey` value for `thread_local!`.
|
||||||
(@key $t:ty, $init:expr) => {{
|
(@key $t:ty, $init:expr) => {{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn __init() -> $t { $init }
|
fn __init() -> $t { $init }
|
||||||
|
|
||||||
|
// NOTE: this cannot import `LocalKey` or `Storage` with a `use` because that can shadow
|
||||||
|
// user provided type or type alias with a matching name. Please update the shadowing test
|
||||||
|
// in `tests/thread.rs` if these types are renamed.
|
||||||
unsafe {
|
unsafe {
|
||||||
use $crate::thread::LocalKey;
|
|
||||||
use $crate::thread::local_impl::Storage;
|
|
||||||
|
|
||||||
// Inlining does not work on windows-gnu due to linking errors around
|
// Inlining does not work on windows-gnu due to linking errors around
|
||||||
// dllimports. See https://github.com/rust-lang/rust/issues/109797.
|
// dllimports. See https://github.com/rust-lang/rust/issues/109797.
|
||||||
LocalKey::new(#[cfg_attr(windows, inline(never))] |init| {
|
$crate::thread::LocalKey::new(#[cfg_attr(windows, inline(never))] |init| {
|
||||||
static VAL: Storage<$t> = Storage::new();
|
static VAL: $crate::thread::local_impl::Storage<$t>
|
||||||
|
= $crate::thread::local_impl::Storage::new();
|
||||||
VAL.get(init, __init)
|
VAL.get(init, __init)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,29 @@ fn thread_local_containing_const_statements() {
|
|||||||
assert_eq!(REFCELL.take(), 1);
|
assert_eq!(REFCELL.take(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn thread_local_hygeiene() {
|
||||||
|
// Previously `thread_local_inner!` had use imports for `LocalKey`, `Storage`, `EagerStorage`
|
||||||
|
// and `LazyStorage`. The use imports will shadow a user-provided type or type alias if the
|
||||||
|
// user-provided type or type alias has the same name. Make sure that this does not happen. See
|
||||||
|
// <https://github.com/rust-lang/rust/issues/131863>.
|
||||||
|
//
|
||||||
|
// NOTE: if the internal implementation details change (i.e. get renamed), this test should be
|
||||||
|
// updated.
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
type LocalKey = ();
|
||||||
|
type Storage = ();
|
||||||
|
type LazyStorage = ();
|
||||||
|
type EagerStorage = ();
|
||||||
|
thread_local! {
|
||||||
|
static A: LocalKey = const { () };
|
||||||
|
static B: Storage = const { () };
|
||||||
|
static C: LazyStorage = const { () };
|
||||||
|
static D: EagerStorage = const { () };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
// Include an ignore list on purpose, so that new platforms don't miss it
|
// Include an ignore list on purpose, so that new platforms don't miss it
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
|
Loading…
Reference in New Issue
Block a user