Run an async future on a dedicated thread to avoid nested tokio runtime panics. `#[tokio::main]` creates a runtime, and `CompleteEnv::complete()` runs synchronously inside its `block_on`. Creating another runtime on the same thread would panic, so we spawn a new OS thread with its own single-threaded runtime.
(future: F)
| 136 | /// inside its `block_on`. Creating another runtime on the same thread would panic, so |
| 137 | /// we spawn a new OS thread with its own single-threaded runtime. |
| 138 | fn blocking_complete<F>(future: F) -> Vec<CompletionCandidate> |
| 139 | where |
| 140 | F: Future<Output = Option<Vec<CompletionCandidate>>> + Send + 'static, |
| 141 | { |
| 142 | std::thread::spawn(move || { |
| 143 | let rt = tokio::runtime::Builder::new_current_thread() |
| 144 | .enable_all() |
| 145 | .build() |
| 146 | .ok()?; |
| 147 | rt.block_on(future) |
| 148 | }) |
| 149 | .join() |
| 150 | .ok() |
| 151 | .flatten() |
| 152 | .unwrap_or_default() |
| 153 | } |
| 154 | |
| 155 | #[cfg(test)] |
| 156 | mod tests { |
no test coverage detected