@@ -22,13 +22,15 @@ pub macro thread_local_inner {
22
22
const INIT_EXPR : $t = $init;
23
23
// If the platform has support for `#[thread_local]`, use it.
24
24
#[ thread_local]
25
- static mut VAL : $t = INIT_EXPR ;
25
+ // We use `UnsafeCell` here instead of `static mut` to ensure any generated TLS shims
26
+ // have a nonnull attribute on their return value.
27
+ static VAL : $crate:: cell:: UnsafeCell < $t> = $crate:: cell:: UnsafeCell :: new ( INIT_EXPR ) ;
26
28
27
29
// If a dtor isn't needed we can do something "very raw" and
28
30
// just get going.
29
31
if !$crate:: mem:: needs_drop :: < $t> ( ) {
30
32
unsafe {
31
- return $crate:: option:: Option :: Some ( & VAL )
33
+ return $crate:: option:: Option :: Some ( & * VAL . get ( ) )
32
34
}
33
35
}
34
36
@@ -55,15 +57,15 @@ pub macro thread_local_inner {
55
57
// so now.
56
58
0 => {
57
59
$crate:: thread:: local_impl:: Key :: < $t> :: register_dtor (
58
- $crate :: ptr :: addr_of_mut! ( VAL ) as * mut $crate:: primitive:: u8 ,
60
+ VAL . get ( ) as * mut $crate:: primitive:: u8 ,
59
61
destroy,
60
62
) ;
61
63
STATE . set ( 1 ) ;
62
- $crate:: option:: Option :: Some ( & VAL )
64
+ $crate:: option:: Option :: Some ( & * VAL . get ( ) )
63
65
}
64
66
// 1 == the destructor is registered and the value
65
67
// is valid, so return the pointer.
66
- 1 => $crate:: option:: Option :: Some ( & VAL ) ,
68
+ 1 => $crate:: option:: Option :: Some ( & * VAL . get ( ) ) ,
67
69
// otherwise the destructor has already run, so we
68
70
// can't give access.
69
71
_ => $crate:: option:: Option :: None ,
0 commit comments