@@ -206,12 +206,39 @@ impl Not for Choice {
206
206
}
207
207
}
208
208
209
+ /// This function is a best-effort attempt to prevent the compiler from knowing
210
+ /// anything about the value of the returned `u8`, other than its type.
211
+ ///
212
+ /// Because we want to support stable Rust, we don't have access to inline
213
+ /// assembly or test::black_box, so we use the fact that volatile values will
214
+ /// never be elided to register values.
215
+ ///
216
+ /// Note: Rust's notion of "volatile" is subject to change over time. While this
217
+ /// code may break in a non-destructive way in the future, “constant-time” code
218
+ /// is a continually moving target, and this is better than doing nothing.
219
+ #[ inline( never) ]
220
+ fn black_box ( input : u8 ) -> u8 {
221
+ debug_assert ! ( ( input == 0u8 ) | ( input == 1u8 ) ) ;
222
+
223
+ unsafe {
224
+ // Optimization barrier
225
+ //
226
+ // Unsafe is ok, because:
227
+ // - &input is not NULL;
228
+ // - size of input is not zero;
229
+ // - u8 is neither Sync, nor Send;
230
+ // - u8 is Copy, so input is always live;
231
+ // - u8 type is always properly aligned.
232
+ core:: ptr:: read_volatile ( & input as * const u8 )
233
+ }
234
+ }
235
+
209
236
impl From < u8 > for Choice {
210
237
#[ inline]
211
238
fn from ( input : u8 ) -> Choice {
212
239
// Our goal is to prevent the compiler from inferring that the value held inside the
213
240
// resulting `Choice` struct is really an `i1` instead of an `i8`.
214
- Choice ( core :: hint :: black_box ( input) )
241
+ Choice ( black_box ( input) )
215
242
}
216
243
}
217
244
0 commit comments