@@ -121,16 +121,96 @@ macro_rules! s_no_extra_traits {
121121 ) ;
122122}
123123
124- #[ allow( unused_macros) ]
125- macro_rules! f {
126- ( $( pub fn $i: ident( $( $arg: ident: $argty: ty) ,* ) -> $ret: ty {
127- $( $body: stmt) ;*
128- } ) * ) => ( $(
129- #[ inline]
130- pub unsafe extern fn $i( $( $arg: $argty) ,* ) -> $ret {
131- $( $body) ;*
124+ // This is a pretty horrible hack to allow us to conditionally mark
125+ // some functions as 'const', without requiring users of this macro
126+ // to care about the "const-extern-fn" feature.
127+ //
128+ // When 'const-extern-fn' is enabled, we emit the captured 'const' keyword
129+ // in the expanded function.
130+ //
131+ // When 'const-extern-fn' is disabled, we always emit a plain 'pub unsafe extern fn'.
132+ // Note that the expression matched by the macro is exactly the same - this allows
133+ // users of this macro to work whether or not 'const-extern-fn' is enabled
134+ //
135+ // Unfortunately, we need to duplicate most of this macro between the 'cfg_if' blocks.
136+ // This is because 'const unsafe extern fn' won't even parse on older compilers,
137+ // so we need to avoid emitting it at all of 'const-extern-fn'.
138+ //
139+ // Specifically, moving the 'cfg_if' into the macro body will *not* work.
140+ // Doing so would cause the '#[cfg(feature = "const-extern-fn")]' to be emiited
141+ // into user code. The 'cfg' gate will not stop Rust from trying to parse the
142+ // 'pub const unsafe extern fn', so users would get a compiler error even when
143+ // the 'const-extern-fn' feature is disabled
144+ //
145+ // Note that users of this macro need to place 'const' in a weird position
146+ // (after the closing ')' for the arguments, but before the return type).
147+ // This was the only way I could satisfy the following two requirements:
148+ // 1. Avoid ambuguity errors from 'macro_rules!' (which happen when writing '$foo:ident fn'
149+ // 2. Allow users of this macro to mix 'pub fn foo' and 'pub const fn bar' within the same
150+ // 'f!' block
151+ cfg_if ! {
152+ if #[ cfg( feature = "const-extern-fn" ) ] {
153+ #[ allow( unused_macros) ]
154+ macro_rules! f {
155+ ( $( pub $( { $constness: ident} ) * fn $i: ident(
156+ $( $arg: ident: $argty: ty) , *
157+ ) -> $ret: ty {
158+ $( $body: stmt) ; *
159+ } ) * ) => ( $(
160+ #[ inline]
161+ pub $( $constness) * unsafe extern fn $i( $( $arg: $argty) , *
162+ ) -> $ret {
163+ $( $body) ; *
164+ }
165+ ) * )
132166 }
133- ) * )
167+
168+ #[ allow( unused_macros) ]
169+ macro_rules! const_fn {
170+ ( $( $( { $constness: ident} ) * fn $i: ident(
171+ $( $arg: ident: $argty: ty) , *
172+ ) -> $ret: ty {
173+ $( $body: stmt) ; *
174+ } ) * ) => ( $(
175+ #[ inline]
176+ $( $constness) * fn $i( $( $arg: $argty) , *
177+ ) -> $ret {
178+ $( $body) ; *
179+ }
180+ ) * )
181+ }
182+
183+ } else {
184+ #[ allow( unused_macros) ]
185+ macro_rules! f {
186+ ( $( pub $( { $constness: ident} ) * fn $i: ident(
187+ $( $arg: ident: $argty: ty) , *
188+ ) -> $ret: ty {
189+ $( $body: stmt) ; *
190+ } ) * ) => ( $(
191+ #[ inline]
192+ pub unsafe extern fn $i( $( $arg: $argty) , *
193+ ) -> $ret {
194+ $( $body) ; *
195+ }
196+ ) * )
197+ }
198+
199+ #[ allow( unused_macros) ]
200+ macro_rules! const_fn {
201+ ( $( $( { $constness: ident} ) * fn $i: ident(
202+ $( $arg: ident: $argty: ty) , *
203+ ) -> $ret: ty {
204+ $( $body: stmt) ; *
205+ } ) * ) => ( $(
206+ #[ inline]
207+ fn $i( $( $arg: $argty) , *
208+ ) -> $ret {
209+ $( $body) ; *
210+ }
211+ ) * )
212+ }
213+ }
134214}
135215
136216#[ allow( unused_macros) ]
0 commit comments