@@ -238,16 +238,8 @@ pub struct Formatter<'a> {
238238// NB. Argument is essentially an optimized partially applied formatting function,
239239// equivalent to `exists T.(&T, fn(&T, &mut Formatter<'_>) -> Result`.
240240
241- struct Void {
242- _priv : ( ) ,
243- /// Erases all oibits, because `Void` erases the type of the object that
244- /// will be used to produce formatted output. Since we do not know what
245- /// oibits the real types have (and they can have any or none), we need to
246- /// take the most conservative approach and forbid all oibits.
247- ///
248- /// It was added after #45197 showed that one could share a `!Sync`
249- /// object across threads by passing it into `format_args!`.
250- _oibit_remover : PhantomData < * mut dyn Fn ( ) > ,
241+ extern "C" {
242+ type Opaque ;
251243}
252244
253245/// This struct represents the generic "argument" which is taken by the Xprintf
@@ -259,16 +251,23 @@ struct Void {
259251#[ unstable( feature = "fmt_internals" , reason = "internal to format_args!" , issue = "none" ) ]
260252#[ doc( hidden) ]
261253pub struct ArgumentV1 < ' a > {
262- value : & ' a Void ,
263- formatter : fn ( & Void , & mut Formatter < ' _ > ) -> Result ,
254+ value : & ' a Opaque ,
255+ formatter : fn ( & Opaque , & mut Formatter < ' _ > ) -> Result ,
264256}
265257
266- impl < ' a > ArgumentV1 < ' a > {
267- #[ inline( never) ]
268- fn show_usize ( x : & usize , f : & mut Formatter < ' _ > ) -> Result {
269- Display :: fmt ( x, f)
270- }
258+ // This gurantees a single stable value for the function pointer associated with
259+ // indices/counts in the formatting infrastructure.
260+ //
261+ // Note that a function defined as such would not be correct as functions are
262+ // always tagged unnamed_addr with the current lowering to LLVM IR, so their
263+ // address is not considered important to LLVM and as such the as_usize cast
264+ // could have been miscompiled. In practice, we never call as_usize on non-usize
265+ // containing data (as a matter of static generation of the formatting
266+ // arguments), so this is merely an additional check.
267+ #[ unstable( feature = "fmt_internals" , reason = "internal to format_args!" , issue = "none" ) ]
268+ static USIZE_MARKER : fn ( & usize , & mut Formatter < ' _ > ) -> Result = |_, _| loop { } ;
271269
270+ impl < ' a > ArgumentV1 < ' a > {
272271 #[ doc( hidden) ]
273272 #[ unstable( feature = "fmt_internals" , reason = "internal to format_args!" , issue = "none" ) ]
274273 pub fn new < ' b , T > ( x : & ' b T , f : fn ( & T , & mut Formatter < ' _ > ) -> Result ) -> ArgumentV1 < ' b > {
@@ -278,11 +277,13 @@ impl<'a> ArgumentV1<'a> {
278277 #[ doc( hidden) ]
279278 #[ unstable( feature = "fmt_internals" , reason = "internal to format_args!" , issue = "none" ) ]
280279 pub fn from_usize ( x : & usize ) -> ArgumentV1 < ' _ > {
281- ArgumentV1 :: new ( x, ArgumentV1 :: show_usize )
280+ ArgumentV1 :: new ( x, USIZE_MARKER )
282281 }
283282
284283 fn as_usize ( & self ) -> Option < usize > {
285- if self . formatter as usize == ArgumentV1 :: show_usize as usize {
284+ if self . formatter as usize == USIZE_MARKER as usize {
285+ // SAFETY: The `formatter` field is only set to USIZE_MARKER if
286+ // the value is a usize, so this is safe
286287 Some ( unsafe { * ( self . value as * const _ as * const usize ) } )
287288 } else {
288289 None
@@ -1356,11 +1357,11 @@ impl<'a> Formatter<'a> {
13561357 let mut align = old_align;
13571358 if self . sign_aware_zero_pad ( ) {
13581359 // a sign always goes first
1359- let sign = unsafe { str :: from_utf8_unchecked ( formatted. sign ) } ;
1360+ let sign = formatted. sign ;
13601361 self . buf . write_str ( sign) ?;
13611362
13621363 // remove the sign from the formatted parts
1363- formatted. sign = b "";
1364+ formatted. sign = "" ;
13641365 width = width. saturating_sub ( sign. len ( ) ) ;
13651366 align = rt:: v1:: Alignment :: Right ;
13661367 self . fill = '0' ;
@@ -1392,7 +1393,7 @@ impl<'a> Formatter<'a> {
13921393 }
13931394
13941395 if !formatted. sign . is_empty ( ) {
1395- write_bytes ( self . buf , formatted. sign ) ?;
1396+ self . buf . write_str ( formatted. sign ) ?;
13961397 }
13971398 for part in formatted. parts {
13981399 match * part {
0 commit comments