55
66use super :: * ;
77use crate :: hint:: unreachable_unchecked;
8+ use crate :: ptr:: NonNull ;
89
910#[ lang = "format_placeholder" ]
1011#[ derive( Copy , Clone ) ]
@@ -65,8 +66,11 @@ pub(super) enum Flag {
6566}
6667
6768#[ derive( Copy , Clone ) ]
68- enum ArgumentType < ' a > {
69- Placeholder { value : & ' a Opaque , formatter : fn ( & Opaque , & mut Formatter < ' _ > ) -> Result } ,
69+ enum ArgumentType {
70+ Placeholder {
71+ value : NonNull < ( ) > ,
72+ formatter : unsafe fn ( NonNull < ( ) > , & mut Formatter < ' _ > ) -> Result ,
73+ } ,
7074 Count ( usize ) ,
7175}
7276
@@ -83,7 +87,8 @@ enum ArgumentType<'a> {
8387#[ lang = "format_argument" ]
8488#[ derive( Copy , Clone ) ]
8589pub struct Argument < ' a > {
86- ty : ArgumentType < ' a > ,
90+ ty : ArgumentType ,
91+ _lifetime : PhantomData < & ' a ( ) > ,
8792}
8893
8994#[ rustc_diagnostic_item = "ArgumentMethods" ]
@@ -98,13 +103,13 @@ impl<'a> Argument<'a> {
98103 // `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result`
99104 // and `fn(&Opaque, &mut Formatter<'_>) -> Result` have the same ABI
100105 // (as long as `T` is `Sized`)
101- unsafe {
102- Argument {
103- ty : ArgumentType :: Placeholder {
104- formatter : mem :: transmute ( f ) ,
105- value : mem:: transmute ( x ) ,
106- } ,
107- }
106+ Argument {
107+ ty : ArgumentType :: Placeholder {
108+ value : NonNull :: from ( x ) . cast ( ) ,
109+ // SAFETY: function pointers always have the same layout.
110+ formatter : unsafe { mem:: transmute ( f ) } ,
111+ } ,
112+ _lifetime : PhantomData ,
108113 }
109114 }
110115
@@ -146,7 +151,7 @@ impl<'a> Argument<'a> {
146151 }
147152 #[ inline( always) ]
148153 pub fn from_usize ( x : & usize ) -> Argument < ' _ > {
149- Argument { ty : ArgumentType :: Count ( * x) }
154+ Argument { ty : ArgumentType :: Count ( * x) , _lifetime : PhantomData }
150155 }
151156
152157 /// Format this placeholder argument.
@@ -162,7 +167,14 @@ impl<'a> Argument<'a> {
162167 #[ inline( always) ]
163168 pub ( super ) unsafe fn fmt ( & self , f : & mut Formatter < ' _ > ) -> Result {
164169 match self . ty {
165- ArgumentType :: Placeholder { formatter, value } => formatter ( value, f) ,
170+ // SAFETY:
171+ // `Argument` is constructed so that if `formatter` originally had
172+ // the type `fn(&T, ...)` then `value` has type `&T`. Since we use
173+ // `value` within the lifetime 'a of the reference and references
174+ // and `NonNull` are ABI-compatible, this is completely equivalent
175+ // to calling the original function passed to `new` with the original
176+ // reference, which is always sound.
177+ ArgumentType :: Placeholder { formatter, value } => unsafe { formatter ( value, f) } ,
166178 // SAFETY: the caller promised this.
167179 ArgumentType :: Count ( _) => unsafe { unreachable_unchecked ( ) } ,
168180 }
@@ -208,7 +220,3 @@ impl UnsafeArg {
208220 Self { _private : ( ) }
209221 }
210222}
211-
212- extern "C" {
213- type Opaque ;
214- }
0 commit comments