シナリオ標準の #[tokio::main] マクロを使用する代わりに、Tokio ランタイムを手動で管理することにしたとします。Cargo.toml に依存関係を追加し、ランタイムをインスタンス化して、タスクを spawn しようとします。理論上、コードはドキュメント通りに見えます。しかし、cargo build を実行すると、すぐに不可解なエラーで失敗します。
use tokio::runtime::Runtime;
fn main() {
let rt = Runtime::new().unwrap();
// コンパイラはこのメソッドが存在しないかのように振る舞います
rt.spawn(async {
println!("ランタイムからの挨拶");
});
}
コンパイラの出力は以下のようになります。
error[E0599]: no method named 'spawn' found for struct 'tokio::runtime::Runtime' in the current scope
--> src/main.rs:7:8
|
7 | rt.spawn(async {
| ^^^^^ method not found in 'tokio::runtime::Runtime'
なぜメソッドが見つからないのか?Rust のクレートは、コンパイルを最適化するために 機能フラグ(Feature Flags) をよく使用します。Tokio は巨大なライブラリです。低レベルの TCP ソケットから高レベルのタスクスケジューリングまで、あらゆるものを処理します。Cargo がデフォルトですべてのコンポーネントをダウンロードしてコンパイルすると、ビルド時間が大幅に長くなってしまいます。
設定に tokio = "1.35" を追加したとき、Cargo は「デフォルト」の機能のみを有効にします。Tokio の場合、デフォルトセットはほぼ空です。基本的な型は含まれますが、実際のランタイムロジックは除外されます。つまり、spawn メソッドはサイズを節約するためにビルドから文字通り削られているのです。
spawn メソッドは条件付きでコンパイルされます。これは、rt または rt-multi-thread 機能を明示的に要求した場合にのみ存在します。これらがないと、コンパイラは Runtime 構造体は認識しますが、それに関連付けられたメソッドは認識しません。これが、クレートが見つからないエラーではなく、E0599 エラーが発生する理由です。
クイックフィックスこれを解決する最も速い方法は、full 機能セットを有効にすることです。これには Tokio が提供するすべてのツールが含まります。プロジェクトのルートでターミナルを開き、以下を実行してください。
cargo add tokio --features full
このコマンドは Cargo.toml を自動的に更新します。これにより、spawn、block_on、およびすべてのネットワーキングトレイトが使用可能になります。これは、バイナリサイズが厳密な懸念事項ではないプロトタイピングや小規模なプロジェクトに最適です。
本番環境向けの正確な修正本番環境で features = ["full"] を使用するのは過剰な場合があります。実際には必要のない 30 以上の余分な依存関係が取り込まれる可能性があります。これにより、最終的なバイナリサイズが数メガバイト増加する可能性があります。ビルドを軽量に保つには、Runtime 構造体に必要な特定の機能のみを有効にします。
Cargo.toml ファイルを編集し、Tokio のエントリを更新します。
[dependencies]
tokio = { version = "1.35", features = ["rt", "rt-multi-thread"] }
主な機能の内訳- rt: 基本的なシングルスレッドランタイムを提供します。- rt-multi-thread: マルチスレッドスケジューラをデフォルトとする Runtime::new() を使用する場合に必要です。- macros: #[tokio::main] を使用したい場合に有効にします。- net: TcpStream や UdpSocket に不可欠です。- time: tokio::time::sleep やタイムアウトに必要です。Web サービスの標準的なセットアップでは、通常次のような組み合わせが必要です。
[dependencies]
tokio = { version = "1.35", features = ["rt-multi-thread", "macros", "net", "time"] }
他のクレートで不足している機能を確認するこの問題は、複雑な Rust クレートで頻繁に発生します。特定のメソッドがあるはずの型で E0599 が発生した場合は、docs.rs のドキュメントを確認してください。「This is supported on feature X only(この機能は feature X でのみサポートされています)」というタグを探します。そのタグがある場合は、マニフェストにその機能を追加する必要があります。
確認これが機能したかどうかを確認するために、フルコンパイルを待つ必要はありません。cargo check を実行してください。これはバイナリを生成せずに高速な型チェックを行います。E0599 エラーが消えれば、機能フラグが正しく設定されています。
動作する例rt と rt-multi-thread を有効にすると、このコードはコンパイルされ実行可能になります。
use tokio::runtime::Runtime;
fn main() {
// Runtime::new() には "rt-multi-thread" が必要です
let rt = Runtime::new().expect("ランタイムの作成に失敗しました");
rt.block_on(async {
println!("ランタイムがアクティブです。");
// タスクの spawn には "rt" 機能が必要です
tokio::spawn(async {
println!("タスクが正常に spawn されました!");
}).await.unwrap();
});
}

