@@ -143,6 +143,7 @@ use crate::{
143
143
use core:: {
144
144
any:: Any ,
145
145
fmt,
146
+ marker:: PhantomData ,
146
147
sync:: atomic:: { AtomicBool , AtomicUsize , Ordering } ,
147
148
} ;
148
149
@@ -256,12 +257,27 @@ struct State {
256
257
#[ cfg( feature = "std" ) ]
257
258
struct Entered < ' a > ( & ' a State ) ;
258
259
260
+ /// A trait that implements `Sync`, but not `Send`. Used with PhantomData, this
261
+ /// can mark a struct as `!Send`.
262
+ #[ cfg( feature = "std" ) ]
263
+ trait NotSend : Sync { }
264
+
259
265
/// A guard that resets the current default dispatcher to the prior
260
266
/// default dispatcher when dropped.
261
267
#[ cfg( feature = "std" ) ]
262
268
#[ cfg_attr( docsrs, doc( cfg( feature = "std" ) ) ) ]
263
269
#[ derive( Debug ) ]
264
- pub struct DefaultGuard ( Option < Dispatch > ) ;
270
+ pub struct DefaultGuard (
271
+ Option < Dispatch > ,
272
+
273
+ /// ```compile_fail
274
+ /// use tracing_core::dispatch::*;
275
+ /// trait AssertSend: Send {}
276
+ ///
277
+ /// impl AssertSend for DefaultGuard {}
278
+ /// ```
279
+ PhantomData < dyn NotSend > ,
280
+ ) ;
265
281
266
282
/// Sets this dispatch as the default for the duration of a closure.
267
283
///
@@ -290,15 +306,24 @@ pub fn with_default<T>(dispatcher: &Dispatch, f: impl FnOnce() -> T) -> T {
290
306
f ( )
291
307
}
292
308
293
- /// Sets the dispatch as the default dispatch for the duration of the lifetime
294
- /// of the returned DefaultGuard
309
+ /// Sets the dispatch as the current thread's default dispatch for the duration
310
+ /// of the lifetime of the returned DefaultGuard.
295
311
///
296
312
/// <div class="example-wrap" style="display:inline-block">
297
313
/// <pre class="ignore" style="white-space:normal;font:inherit;">
298
314
///
299
315
/// **Note**: This function required the Rust standard library.
300
316
/// `no_std` users should use [`set_global_default`] instead.
317
+ /// </pre></div>
301
318
///
319
+ /// <div class="example-wrap" style="display:inline-block">
320
+ /// <pre class="ignore" style="white-space:normal;font:inherit;">
321
+ ///
322
+ /// **Note**: Because this sets the dispatch for the current thread only, the
323
+ /// returned [`DefaultGuard`] does not implement [`Send`]. If the guard was sent
324
+ /// to another thread and dropped there, we'd try to restore the dispatch value
325
+ /// for the wrong thread. Thus, [`DefaultGuard`] should not be sent between
326
+ /// threads.
302
327
/// </pre></div>
303
328
#[ cfg( feature = "std" ) ]
304
329
#[ cfg_attr( docsrs, doc( cfg( feature = "std" ) ) ) ]
@@ -1009,7 +1034,7 @@ impl State {
1009
1034
. ok ( ) ;
1010
1035
EXISTS . store ( true , Ordering :: Release ) ;
1011
1036
SCOPED_COUNT . fetch_add ( 1 , Ordering :: Release ) ;
1012
- DefaultGuard ( prior)
1037
+ DefaultGuard ( prior, PhantomData )
1013
1038
}
1014
1039
1015
1040
#[ inline]
@@ -1072,6 +1097,9 @@ mod test {
1072
1097
metadata:: { Kind , Level , Metadata } ,
1073
1098
} ;
1074
1099
1100
+ trait AssertSync : Sync { }
1101
+ impl AssertSync for DefaultGuard { }
1102
+
1075
1103
#[ test]
1076
1104
fn dispatch_is ( ) {
1077
1105
let dispatcher = Dispatch :: from_static ( & NO_COLLECTOR ) ;
0 commit comments