もうすこし忖度してほしい
asyncブロックはFuture<Output=何らかの戻り値型>
になるのですが、Output
型を直接指定する構文がありません。
なので例えば以下のようなコードを書くと:
main.rs
use std::error::Error;
use tokio::{self, signal};
async fn async_func() -> Result<(), Box<dyn Error>> {
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
println!("Done");
Ok(())
}
#[tokio::main]
pub async fn main() -> Result<(), Box<dyn Error>> {
let sig_term = async {
let mut s = signal::unix::signal(signal::unix::SignalKind::terminate())?;
s.recv().await;
Ok(())
};
tokio::select! {
result = sig_term => {
result?;
log::info!("SIGTERM");
}
val = async_func() => {
val?
}
}
Ok(())
}
sig_term
変数の型の推測ができずコンパイルできません。
error[E0698]: type inside `async` block must be known in this context
--> src/main.rs:14:9
|
14 | Ok(())
| ^^ cannot infer type for type parameter `E` declared on the enum `Result`
|
note: the type is part of the `async` block because of this `await`
--> src/main.rs:17:5
|
17 | / tokio::select! {
18 | | result = sig_term => {
19 | | result?;
20 | | log::info!("SIGTERM");
... |
24 | | }
25 | | }
| |_____^
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0698`.
error: could not compile `playground`
To learn more, run the command again with --verbose.
すっきり解決
以下のスレッドにいろんな解決方法がありましたが、型変換を行うトレイトOutputting
を用意し、Future
に対して実装することで明示的に指定してみます。
https://internals.rust-lang.org/t/return-type-annotation-of-async-block/12561/14
main.rs
use std::error::Error;
use tokio::{self, signal};
// Outputting トレイト
trait Outputting: Sized {
fn outputting<O>(self) -> Self
where
Self: std::future::Future<Output = O>,
{
self
}
}
// Futureに実装
impl<T: std::future::Future> Outputting for T {}
async fn async_func() -> Result<(), Box<dyn Error>> {
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
println!("Done");
Ok(())
}
#[tokio::main]
pub async fn main() -> Result<(), Box<dyn Error>> {
let sig_term = async {
let mut s = signal::unix::signal(signal::unix::SignalKind::terminate())?;
s.recv().await;
Ok(())
}.outputting::<Result<(), Box<dyn Error>>>(); // asyncブロックに対してOutputの型を指定する
tokio::select! {
result = sig_term => {
result?;
log::info!("SIGTERM");
}
val = async_func() => {
val?
}
}
Ok(())
}
コンパイル出来ました。