Skip to content

Commit 5be4ab3

Browse files
committed
Make recommended changes
1 parent 19dc8a8 commit 5be4ab3

File tree

1 file changed

+62
-32
lines changed

1 file changed

+62
-32
lines changed

src/rust-2018/macros/macro-changes.md

Lines changed: 62 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -90,35 +90,49 @@ For example, let's make a simplified (and slightly contrived) version of the `lo
9090
edition style:
9191

9292
```rust,ignore
93+
/// How important/severe the log message is.
94+
#[derive(Copy, Clone)]
9395
pub struct LogLevel {
9496
Warn,
9597
Error
9698
}
9799
100+
impl fmt::Display for LogLevel {
101+
pub fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
102+
match self {
103+
LogLevel::Warn => write!(f, "warning"),
104+
LogLevel::Error => write!(f, "error"),
105+
}
106+
}
107+
}
108+
109+
// A helper macro to log the message.
98110
#[doc(hidden)]
99111
#[macro_export]
100-
macro_rules! log {
101-
($level:expr, $msg:expr) => {
112+
macro_rules! __impl_log {
113+
($level:expr, $msg:expr) => {{
102114
println!("{}: {}", $level, $msg)
103-
}
115+
}}
104116
}
105117
118+
/// Warn level log message
106119
#[macro_export]
107120
macro_rules! warn {
108-
($msg:expr) => {
109-
log!(stringify!($crate::LogLevel::Warn), $msg)
121+
($($args:tt)*) => {
122+
__impl_log!($crate::LogLevel::Warn, format_args!($($args)*))
110123
}
111124
}
112125
126+
/// Error level log message
113127
#[macro_export]
114128
macro_rules! error {
115-
($msg:expr) => {
116-
log!(stringify!($crate::LogLevel::Error), $msg)
129+
($($args:tt)*) => {
130+
__impl_log!($crate::LogLevel::Error, format_args!($($args)*))
117131
}
118132
}
119133
```
120134

121-
Our `log!` macro is private to our module, but needs to be exported as it is called by other
135+
Our `__impl_log!` macro is private to our module, but needs to be exported as it is called by other
122136
macros, and in 2015 edition all used macros must be exported.
123137

124138
Now, in 2018 this example will not compile:
@@ -131,14 +145,14 @@ fn main() {
131145
}
132146
```
133147

134-
will give an error message about not finding the `log!` macro. This is because unlike in the 2015
135-
edition, macros are namespaced and we must import them. We could do
148+
will give an error message about not finding the `__impl_log!` macro. This is because unlike in
149+
the 2015 edition, macros are namespaced and we must import them. We could do
136150

137151
```rust,ignore
138-
use log::{log, error};
152+
use log::{__impl_log, error};
139153
```
140154

141-
which would make our code compile, but `log` is meant to be an implementation detail!
155+
which would make our code compile, but `__impl_log` is meant to be an implementation detail!
142156

143157
#### Macros with `$crate::` prefix.
144158

@@ -147,8 +161,8 @@ you would for any other path. Versions of the compiler >= 1.30 will handle this
147161

148162
```rust,ignore
149163
macro_rules! warn {
150-
($msg:expr) => {
151-
$crate::log!(stringify!($crate::LogLevel::Warn), $msg)
164+
($($args:tt)*) => {
165+
$crate::__impl_log!($crate::LogLevel::Warn, format_args!($($args)*))
152166
}
153167
}
154168
@@ -167,24 +181,26 @@ modifier). The downside is that it's a bit messier:
167181
```rust,ignore
168182
#[macro_export(local_inner_macros)]
169183
macro_rules! warn {
170-
($msg:expr) => {
171-
log!(stringify!($crate::LogLevel::Warn), $msg)
184+
($($args:tt)*) => {
185+
__impl_log!($crate::LogLevel::Warn, format_args!($($args)*))
172186
}
173187
}
174188
```
175189

176190
So the code knows to look for any macros used locally. But wait - this won't compile, because we
177-
use the `stringify!` macro that isn't in our local crate (hence the convoluted example). The
178-
solution is to add a level of indirection: we crate a macro that wraps stringify, but is local to
179-
our crate. That way everything works in both editions (sadly we have to pollute the global
191+
use the `format_args!` macro that isn't in our local crate (hence the convoluted example). The
192+
solution is to add a level of indirection: we crate a macro that wraps `format_args`, but is local
193+
to our crate. That way everything works in both editions (sadly we have to pollute the global
180194
namespace a bit, but that's ok).
181195

182196
```rust,ignore
197+
// I've used the pattern `_<my crate name>__<macro name>` to name this macro, hopefully avoiding
198+
// name clashes.
183199
#[doc(hidden)]
184200
#[macro_export]
185-
macro_rules! my_special_stringify {
201+
macro_rules! _log__format_args {
186202
($($inner:tt)*) => {
187-
stringify!($($inner)*)
203+
format_args! { $($inner)* }
188204
}
189205
}
190206
```
@@ -194,39 +210,53 @@ whatever tokens we get to the inner macro, and rely on it to report errors.
194210

195211
So the full 2015/2018 working example would be:
196212

197-
```rust,ignore
213+
```rust
214+
/// How important/severe the log message is.
215+
#[derive(Copy, Clone)]
198216
pub struct LogLevel {
199217
Warn,
200218
Error
201219
}
202220

221+
impl fmt::Display for LogLevel {
222+
pub fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
223+
match self {
224+
LogLevel::Warn => write!(f, "warning"),
225+
LogLevel::Error => write!(f, "error"),
226+
}
227+
}
228+
}
229+
230+
// A helper macro to log the message.
203231
#[doc(hidden)]
204232
#[macro_export]
205-
macro_rules! log {
206-
($level:expr, $msg:expr) => {
233+
macro_rules! __impl_log {
234+
($level:expr, $msg:expr) => {{
207235
println!("{}: {}", $level, $msg)
208-
}
236+
}}
209237
}
210238

239+
/// Warn level log message
211240
#[macro_export(local_inner_macros)]
212241
macro_rules! warn {
213-
($msg:expr) => {
214-
log!(my_special_stringify!($crate::LogLevel::Warn), $msg)
242+
($($args:tt)*) => {
243+
__impl_log!($crate::LogLevel::Warn, format_args!($($args)*))
215244
}
216245
}
217246

247+
/// Error level log message
218248
#[macro_export(local_inner_macros)]
219249
macro_rules! error {
220-
($msg:expr) => {
221-
log!(my_special_stringify!($crate::LogLevel::Error), $msg)
250+
($($args:tt)*) => {
251+
__impl_log!($crate::LogLevel::Error, format_args!($($args)*))
222252
}
223253
}
224254

225255
#[doc(hidden)]
226256
#[macro_export]
227-
macro_rules! my_special_stringify {
228-
($($args:tt)*) => {
229-
stringify!($($args)*)
257+
macro_rules! _log__format_args {
258+
($($inner:tt)*) => {
259+
format_args! { $($inner)* }
230260
}
231261
}
232262
```

0 commit comments

Comments
 (0)