@@ -45,25 +45,11 @@ fn generic<T>() -> &'static Option<T> {
45
45
}
46
46
```
47
47
48
- Additionally, despite it being memory safe, it is not currently possible to
49
- create a ` &'static mut ` to a zero-sized type without involving unsafe code:
50
-
51
- ``` rust
52
- fn return_fn_mut_or_default (& mut self ) -> & FnMut (u32 , u32 ) -> u32 {
53
- // error: references in constants may only refer to immutable values
54
- const STATIC_TRAIT_OBJECT : & 'static mut FnMut (u32 , u32 ) -> u32
55
- = & mut | x , y | x * y ;
56
-
57
- self . operator. unwrap_or (STATIC_TRAIT_OBJECT )
58
- }
59
- ```
60
-
61
- Lastly, the compiler already special cases a small subset of rvalue
48
+ However, the compiler already special cases a small subset of rvalue
62
49
const expressions to have static lifetime - namely the empty array expression:
63
50
64
51
``` rust
65
52
let x : & 'static [u8 ] = & [];
66
- let y : & 'static mut [u8 ] = & mut [];
67
53
```
68
54
69
55
And though they don't have to be seen as such, string literals could be regarded
@@ -94,22 +80,8 @@ Inside a function body's block:
94
80
it into a static memory location and give the resulting reference a
95
81
` 'static ` lifetime.
96
82
97
- Likewise,
98
-
99
- - If a mutable reference to a constexpr rvalue is taken. (` &mut <constexpr> ` )
100
- - And the constexpr does not contain a ` UnsafeCell { ... } ` constructor.
101
- - And the constexpr does not contain a const fn call returning a type containing a ` UnsafeCell ` .
102
- - _ And the type of the rvalue is zero-sized._
103
- - Then instead of translating the value into a stack slot, translate
104
- it into a static memory location and give the resulting reference a
105
- ` 'static ` lifetime.
106
-
107
83
The ` UnsafeCell ` restrictions are there to ensure that the promoted value is
108
- truly immutable behind the reference (Though not technically needed in the zero-sized case, see alternatives below).
109
-
110
- The zero-sized restriction for mutable references is there because
111
- aliasing mutable references are only safe for zero sized types
112
- (since you never dereference the pointer for them).
84
+ truly immutable behind the reference.
113
85
114
86
Examples:
115
87
@@ -119,9 +91,6 @@ let a: &'static u32 = &32;
119
91
let b : & 'static Option <UnsafeCell <u32 >> = & None ;
120
92
let c : & 'static Fn () -> u32 = & || 42 ;
121
93
122
- let d : & 'static mut () = & mut ();
123
- let e : & 'static mut Fn () -> u32 = & mut || 42 ;
124
-
125
94
let h : & 'static u32 = & (32 + 64 );
126
95
127
96
fn generic <T >() -> & 'static Option <T > {
@@ -134,7 +103,7 @@ let g: &'static Cell<u32> = &Cell::new(); // assuming conf fn new()
134
103
```
135
104
136
105
These rules above should be consistent with the existing rvalue promotions in ` const `
137
- initializer lists :
106
+ initializer expressions :
138
107
139
108
``` rust
140
109
// If this compiles:
@@ -160,9 +129,49 @@ https://github.com/rust-lang/rust/blob/29ea4eef9fa6e36f40bc1f31eb1e56bf5941ee72/
160
129
161
130
One more feature with seemingly ad-hoc rules to complicate the language...
162
131
163
- # Alternatives
132
+ # Alternatives, Extensions
164
133
[ alternatives ] : #alternatives
165
134
135
+ It would be possible to extend support to ` &'static mut ` references,
136
+ as long as there is the additional constraint that the
137
+ referenced type is zero sized.
138
+
139
+ This again has precedence in the array reference constructor:
140
+
141
+ ``` rust
142
+ // valid code today
143
+ let y : & 'static mut [u8 ] = & mut [];
144
+ ```
145
+
146
+ The rules would be similar:
147
+
148
+ - If a mutable reference to a constexpr rvalue is taken. (` &mut <constexpr> ` )
149
+ - And the constexpr does not contain a ` UnsafeCell { ... } ` constructor.
150
+ - And the constexpr does not contain a const fn call returning a type containing a ` UnsafeCell ` .
151
+ - _ And the type of the rvalue is zero-sized._
152
+ - Then instead of translating the value into a stack slot, translate
153
+ it into a static memory location and give the resulting reference a
154
+ ` 'static ` lifetime.
155
+
156
+ The zero-sized restriction is there because
157
+ aliasing mutable references are only safe for zero sized types
158
+ (since you never dereference the pointer for them).
159
+
160
+ Example:
161
+
162
+ ``` rust
163
+ fn return_fn_mut_or_default (& mut self ) -> & FnMut (u32 , u32 ) -> u32 {
164
+ self . operator. unwrap_or (& mut | x , y | x * y )
165
+ // ^ would be okay, since it would be translated like this:
166
+ // const STATIC_TRAIT_OBJECT: &'static mut FnMut(u32, u32) -> u32
167
+ // = &mut |x, y| x * y;
168
+ // self.operator.unwrap_or(STATIC_TRAIT_OBJECT)
169
+ }
170
+
171
+ let d : & 'static mut () = & mut ();
172
+ let e : & 'static mut Fn () -> u32 = & mut || 42 ;
173
+ ```
174
+
166
175
There are two ways this could be taken further with zero-sized types:
167
176
168
177
1 . Remove the ` UnsafeCell ` restriction if the type of the rvalue is zero-sized.
0 commit comments