5
5
6
6
use super :: * ;
7
7
use crate :: hint:: unreachable_unchecked;
8
+ use crate :: ptr:: NonNull ;
8
9
9
10
#[ lang = "format_placeholder" ]
10
11
#[ derive( Copy , Clone ) ]
@@ -65,8 +66,11 @@ pub(super) enum Flag {
65
66
}
66
67
67
68
#[ 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
+ } ,
70
74
Count ( usize ) ,
71
75
}
72
76
@@ -83,7 +87,8 @@ enum ArgumentType<'a> {
83
87
#[ lang = "format_argument" ]
84
88
#[ derive( Copy , Clone ) ]
85
89
pub struct Argument < ' a > {
86
- ty : ArgumentType < ' a > ,
90
+ ty : ArgumentType ,
91
+ _lifetime : PhantomData < & ' a ( ) > ,
87
92
}
88
93
89
94
#[ rustc_diagnostic_item = "ArgumentMethods" ]
@@ -98,13 +103,13 @@ impl<'a> Argument<'a> {
98
103
// `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result`
99
104
// and `fn(&Opaque, &mut Formatter<'_>) -> Result` have the same ABI
100
105
// (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 ,
108
113
}
109
114
}
110
115
@@ -146,7 +151,7 @@ impl<'a> Argument<'a> {
146
151
}
147
152
#[ inline( always) ]
148
153
pub fn from_usize ( x : & usize ) -> Argument < ' _ > {
149
- Argument { ty : ArgumentType :: Count ( * x) }
154
+ Argument { ty : ArgumentType :: Count ( * x) , _lifetime : PhantomData }
150
155
}
151
156
152
157
/// Format this placeholder argument.
@@ -162,7 +167,14 @@ impl<'a> Argument<'a> {
162
167
#[ inline( always) ]
163
168
pub ( super ) unsafe fn fmt ( & self , f : & mut Formatter < ' _ > ) -> Result {
164
169
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) } ,
166
178
// SAFETY: the caller promised this.
167
179
ArgumentType :: Count ( _) => unsafe { unreachable_unchecked ( ) } ,
168
180
}
@@ -208,7 +220,3 @@ impl UnsafeArg {
208
220
Self { _private : ( ) }
209
221
}
210
222
}
211
-
212
- extern "C" {
213
- type Opaque ;
214
- }
0 commit comments