@@ -238,16 +238,8 @@ pub struct Formatter<'a> {
238
238
// NB. Argument is essentially an optimized partially applied formatting function,
239
239
// equivalent to `exists T.(&T, fn(&T, &mut Formatter<'_>) -> Result`.
240
240
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 ;
251
243
}
252
244
253
245
/// This struct represents the generic "argument" which is taken by the Xprintf
@@ -259,16 +251,23 @@ struct Void {
259
251
#[ unstable( feature = "fmt_internals" , reason = "internal to format_args!" , issue = "none" ) ]
260
252
#[ doc( hidden) ]
261
253
pub 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 ,
264
256
}
265
257
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 { } ;
271
269
270
+ impl < ' a > ArgumentV1 < ' a > {
272
271
#[ doc( hidden) ]
273
272
#[ unstable( feature = "fmt_internals" , reason = "internal to format_args!" , issue = "none" ) ]
274
273
pub fn new < ' b , T > ( x : & ' b T , f : fn ( & T , & mut Formatter < ' _ > ) -> Result ) -> ArgumentV1 < ' b > {
@@ -278,11 +277,13 @@ impl<'a> ArgumentV1<'a> {
278
277
#[ doc( hidden) ]
279
278
#[ unstable( feature = "fmt_internals" , reason = "internal to format_args!" , issue = "none" ) ]
280
279
pub fn from_usize ( x : & usize ) -> ArgumentV1 < ' _ > {
281
- ArgumentV1 :: new ( x, ArgumentV1 :: show_usize )
280
+ ArgumentV1 :: new ( x, USIZE_MARKER )
282
281
}
283
282
284
283
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
286
287
Some ( unsafe { * ( self . value as * const _ as * const usize ) } )
287
288
} else {
288
289
None
@@ -1356,11 +1357,11 @@ impl<'a> Formatter<'a> {
1356
1357
let mut align = old_align;
1357
1358
if self . sign_aware_zero_pad ( ) {
1358
1359
// a sign always goes first
1359
- let sign = unsafe { str :: from_utf8_unchecked ( formatted. sign ) } ;
1360
+ let sign = formatted. sign ;
1360
1361
self . buf . write_str ( sign) ?;
1361
1362
1362
1363
// remove the sign from the formatted parts
1363
- formatted. sign = b "";
1364
+ formatted. sign = "" ;
1364
1365
width = width. saturating_sub ( sign. len ( ) ) ;
1365
1366
align = rt:: v1:: Alignment :: Right ;
1366
1367
self . fill = '0' ;
@@ -1392,7 +1393,7 @@ impl<'a> Formatter<'a> {
1392
1393
}
1393
1394
1394
1395
if !formatted. sign . is_empty ( ) {
1395
- write_bytes ( self . buf , formatted. sign ) ?;
1396
+ self . buf . write_str ( formatted. sign ) ?;
1396
1397
}
1397
1398
for part in formatted. parts {
1398
1399
match * part {
0 commit comments