@@ -239,11 +239,30 @@ impl<'a> Executor<'a> {
239
239
} ;
240
240
241
241
// Create the task and register it in the set of active tasks.
242
- let ( runnable, task) = unsafe {
243
- Builder :: new ( )
244
- . propagate_panic ( true )
245
- . spawn_unchecked ( |( ) | future, self . schedule ( ) )
246
- } ;
242
+ //
243
+ // SAFETY:
244
+ //
245
+ // If `future` is not `Send`, this must be a `LocalExecutor` as per this
246
+ // function's unsafe precondition. Since `LocalExecutor` is `!Sync`,
247
+ // `try_tick`, `tick` and `run` can only be called from the origin
248
+ // thread of the `LocalExecutor`. Similarly, `spawn` can only be called
249
+ // from the origin thread, ensuring that `future` and the executor share
250
+ // the same origin thread. The `Runnable` can be scheduled from other
251
+ // threads, but because of the above `Runnable` can only be called or
252
+ // dropped on the origin thread.
253
+ //
254
+ // `future` is not `'static`, but we make sure that the `Runnable` does
255
+ // not outlive `'a`. When the executor is dropped, the `active` field is
256
+ // drained and all of the `Waker`s are woken. Then, the queue inside of
257
+ // the `Executor` is drained of all of its runnables. This ensures that
258
+ // runnables are dropped and this precondition is satisfied.
259
+ //
260
+ // `self.schedule()` is `Send`, `Sync` and `'static`, as checked below.
261
+ // Therefore we do not need to worry about what is done with the
262
+ // `Waker`.
263
+ let ( runnable, task) = Builder :: new ( )
264
+ . propagate_panic ( true )
265
+ . spawn_unchecked ( |( ) | future, self . schedule ( ) ) ;
247
266
entry. insert ( runnable. waker ( ) ) ;
248
267
249
268
runnable. schedule ( ) ;
@@ -1068,6 +1087,7 @@ fn _ensure_send_and_sync() {
1068
1087
1069
1088
fn is_send < T : Send > ( _: T ) { }
1070
1089
fn is_sync < T : Sync > ( _: T ) { }
1090
+ fn is_static < T : ' static > ( _: T ) { }
1071
1091
1072
1092
is_send :: < Executor < ' _ > > ( Executor :: new ( ) ) ;
1073
1093
is_sync :: < Executor < ' _ > > ( Executor :: new ( ) ) ;
@@ -1077,6 +1097,9 @@ fn _ensure_send_and_sync() {
1077
1097
is_sync ( ex. run ( pending :: < ( ) > ( ) ) ) ;
1078
1098
is_send ( ex. tick ( ) ) ;
1079
1099
is_sync ( ex. tick ( ) ) ;
1100
+ is_send ( ex. schedule ( ) ) ;
1101
+ is_sync ( ex. schedule ( ) ) ;
1102
+ is_static ( ex. schedule ( ) ) ;
1080
1103
1081
1104
/// ```compile_fail
1082
1105
/// use async_executor::LocalExecutor;
0 commit comments