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 ) ]
@@ -66,7 +67,13 @@ pub(super) enum Flag {
66
67
67
68
#[ derive( Copy , Clone ) ]
68
69
enum ArgumentType < ' a > {
69
- Placeholder { value : & ' a Opaque , formatter : fn ( & Opaque , & mut Formatter < ' _ > ) -> Result } ,
70
+ Placeholder {
71
+ // INVARIANT: `formatter` has type `fn(&T, _) -> _` for some `T`, and `value`
72
+ // was derived from a `&'a T`.
73
+ value : NonNull < ( ) > ,
74
+ formatter : unsafe fn ( NonNull < ( ) > , & mut Formatter < ' _ > ) -> Result ,
75
+ _lifetime : PhantomData < & ' a ( ) > ,
76
+ } ,
70
77
Count ( usize ) ,
71
78
}
72
79
@@ -90,21 +97,15 @@ pub struct Argument<'a> {
90
97
impl < ' a > Argument < ' a > {
91
98
#[ inline( always) ]
92
99
fn new < ' b , T > ( x : & ' b T , f : fn ( & T , & mut Formatter < ' _ > ) -> Result ) -> Argument < ' b > {
93
- // SAFETY: `mem::transmute(x)` is safe because
94
- // 1. `&'b T` keeps the lifetime it originated with `'b`
95
- // (so as to not have an unbounded lifetime)
96
- // 2. `&'b T` and `&'b Opaque` have the same memory layout
97
- // (when `T` is `Sized`, as it is here)
98
- // `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result`
99
- // and `fn(&Opaque, &mut Formatter<'_>) -> Result` have the same ABI
100
- // (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
- }
100
+ Argument {
101
+ // INVARIANT: this creates an `ArgumentType<'b>` from a `&'b T` and
102
+ // a `fn(&T, ...)`, so the invariant is maintained.
103
+ ty : ArgumentType :: Placeholder {
104
+ value : NonNull :: from ( x) . cast ( ) ,
105
+ // SAFETY: function pointers always have the same layout.
106
+ formatter : unsafe { mem:: transmute ( f) } ,
107
+ _lifetime : PhantomData ,
108
+ } ,
108
109
}
109
110
}
110
111
@@ -162,7 +163,14 @@ impl<'a> Argument<'a> {
162
163
#[ inline( always) ]
163
164
pub ( super ) unsafe fn fmt ( & self , f : & mut Formatter < ' _ > ) -> Result {
164
165
match self . ty {
165
- ArgumentType :: Placeholder { formatter, value } => formatter ( value, f) ,
166
+ // SAFETY:
167
+ // Because of the invariant that if `formatter` had the type
168
+ // `fn(&T, _) -> _` then `value` has type `&'b T` where `'b` is
169
+ // the lifetime of the `ArgumentType`, and because references
170
+ // and `NonNull` are ABI-compatible, this is completely equivalent
171
+ // to calling the original function passed to `new` with the
172
+ // original reference, which is sound.
173
+ ArgumentType :: Placeholder { formatter, value, .. } => unsafe { formatter ( value, f) } ,
166
174
// SAFETY: the caller promised this.
167
175
ArgumentType :: Count ( _) => unsafe { unreachable_unchecked ( ) } ,
168
176
}
@@ -208,7 +216,3 @@ impl UnsafeArg {
208
216
Self { _private : ( ) }
209
217
}
210
218
}
211
-
212
- extern "C" {
213
- type Opaque ;
214
- }
0 commit comments