@@ -65,61 +65,73 @@ pub struct Argument<'a> {
65
65
ty : ArgumentType < ' a > ,
66
66
}
67
67
68
- #[ rustc_diagnostic_item = "ArgumentMethods" ]
69
- impl Argument < ' _ > {
70
- #[ inline]
71
- const fn new < ' a , T > ( x : & ' a T , f : fn ( & T , & mut Formatter < ' _ > ) -> Result ) -> Argument < ' a > {
68
+ macro_rules! argument_new {
69
+ ( $t: ty, $x: expr, $f: expr) => {
72
70
Argument {
73
71
// INVARIANT: this creates an `ArgumentType<'a>` from a `&'a T` and
74
72
// a `fn(&T, ...)`, so the invariant is maintained.
75
73
ty: ArgumentType :: Placeholder {
76
- value : NonNull :: from_ref ( x) . cast ( ) ,
77
- // SAFETY: function pointers always have the same layout.
78
- formatter : unsafe { mem:: transmute ( f) } ,
74
+ value: NonNull :: <$t>:: from_ref( $x) . cast( ) ,
75
+ #[ cfg( not( any( sanitize = "cfi" , sanitize = "kcfi" ) ) ) ]
76
+ formatter: {
77
+ let f: fn ( & $t, & mut Formatter <' _>) -> Result = $f;
78
+ // SAFETY: This is only called with `value`, which has the right type.
79
+ unsafe { mem:: transmute( f) }
80
+ } ,
81
+ #[ cfg( any( sanitize = "cfi" , sanitize = "kcfi" ) ) ]
82
+ formatter: |ptr: NonNull <( ) >, fmt: & mut Formatter <' _>| {
83
+ let func = $f;
84
+ // SAFETY: This is the same type as the `value` field.
85
+ let r = unsafe { ptr. cast:: <$t>( ) . as_ref( ) } ;
86
+ ( func) ( r, fmt)
87
+ } ,
79
88
_lifetime: PhantomData ,
80
89
} ,
81
90
}
82
- }
91
+ } ;
92
+ }
83
93
94
+ #[ rustc_diagnostic_item = "ArgumentMethods" ]
95
+ impl Argument < ' _ > {
84
96
#[ inline]
85
97
pub fn new_display < T : Display > ( x : & T ) -> Argument < ' _ > {
86
- Self :: new ( x, Display :: fmt)
98
+ argument_new ! ( T , x, < T as Display > :: fmt)
87
99
}
88
100
#[ inline]
89
101
pub fn new_debug < T : Debug > ( x : & T ) -> Argument < ' _ > {
90
- Self :: new ( x, Debug :: fmt)
102
+ argument_new ! ( T , x, < T as Debug > :: fmt)
91
103
}
92
104
#[ inline]
93
105
pub fn new_debug_noop < T : Debug > ( x : & T ) -> Argument < ' _ > {
94
- Self :: new ( x, |_, _| Ok ( ( ) ) )
106
+ argument_new ! ( T , x, |_: & T , _| Ok ( ( ) ) )
95
107
}
96
108
#[ inline]
97
109
pub fn new_octal < T : Octal > ( x : & T ) -> Argument < ' _ > {
98
- Self :: new ( x, Octal :: fmt)
110
+ argument_new ! ( T , x, < T as Octal > :: fmt)
99
111
}
100
112
#[ inline]
101
113
pub fn new_lower_hex < T : LowerHex > ( x : & T ) -> Argument < ' _ > {
102
- Self :: new ( x, LowerHex :: fmt)
114
+ argument_new ! ( T , x, < T as LowerHex > :: fmt)
103
115
}
104
116
#[ inline]
105
117
pub fn new_upper_hex < T : UpperHex > ( x : & T ) -> Argument < ' _ > {
106
- Self :: new ( x, UpperHex :: fmt)
118
+ argument_new ! ( T , x, < T as UpperHex > :: fmt)
107
119
}
108
120
#[ inline]
109
121
pub fn new_pointer < T : Pointer > ( x : & T ) -> Argument < ' _ > {
110
- Self :: new ( x, Pointer :: fmt)
122
+ argument_new ! ( T , x, < T as Pointer > :: fmt)
111
123
}
112
124
#[ inline]
113
125
pub fn new_binary < T : Binary > ( x : & T ) -> Argument < ' _ > {
114
- Self :: new ( x, Binary :: fmt)
126
+ argument_new ! ( T , x, < T as Binary > :: fmt)
115
127
}
116
128
#[ inline]
117
129
pub fn new_lower_exp < T : LowerExp > ( x : & T ) -> Argument < ' _ > {
118
- Self :: new ( x, LowerExp :: fmt)
130
+ argument_new ! ( T , x, < T as LowerExp > :: fmt)
119
131
}
120
132
#[ inline]
121
133
pub fn new_upper_exp < T : UpperExp > ( x : & T ) -> Argument < ' _ > {
122
- Self :: new ( x, UpperExp :: fmt)
134
+ argument_new ! ( T , x, < T as UpperExp > :: fmt)
123
135
}
124
136
#[ inline]
125
137
#[ track_caller]
@@ -135,11 +147,6 @@ impl Argument<'_> {
135
147
/// # Safety
136
148
///
137
149
/// This argument must actually be a placeholder argument.
138
- ///
139
- // FIXME: Transmuting formatter in new and indirectly branching to/calling
140
- // it here is an explicit CFI violation.
141
- #[ allow( inline_no_sanitize) ]
142
- #[ no_sanitize( cfi, kcfi) ]
143
150
#[ inline]
144
151
pub ( super ) unsafe fn fmt ( & self , f : & mut Formatter < ' _ > ) -> Result {
145
152
match self . ty {
0 commit comments