問題点
ドキュメントを確認し、std::fs::File にメソッドが存在することを確認して呼び出します。しかし、コンパイラは苛立たしい E0599 エラーで停止します。そのメソッドが標準ライブラリの一部であるにもかかわらず、Rust は現在のスコープに存在しないと主張します。
error[E0599]: no method named 'read_to_string' found for struct 'File' in the current scope
--> src/main.rs:7:10
|
7 | file.read_to_string(&mut contents)?;
| ^^^^^^^^^^^^^^ method not found in 'File'
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a 'use' for it:
|
1 + use std::io::Read;
|
クイック修正
Rust では、トレイト (trait) 内で定義されたメソッドは、そのトレイトがモジュールにインポートされている場合にのみ表示されます。File オブジェクトでの read_to_string エラーを修正するには、main.rs または lib.rs の先頭に以下のインポートを追加してください。
use std::io::Read;
tokio 1.0 以降を使用して非同期コードを扱っている場合は、通常、拡張トレイトが必要です。
use tokio::io::AsyncReadExt;
なぜこれが起こるのか?
Java や Python の経験がある場合、メソッドはクラスに直接組み込まれているものと期待するかもしれません。しかし、Rust は異なります。Rust はトレイトを使用して、型を越えて動作を共有します。File のような構造体は、実際には read_to_string を「所有」していません。その代わりに、その機能を提供する Read トレイトを実装しています。
この設計は「名前空間の汚染」を防ぎます。このルールがないと、新しいクレートをインポートした際に、既存の変数に誤って数十ものメソッドが追加され、名前の競合が発生する可能性があります。明示的な use ステートメントを要求することで、Rust はすべてのメソッドがどこから来ているのかを正確に把握できるようにしています。
エラーが発生するコードの例
以下のコードは、コンパイラが File の存在を知っていても、利用可能なメソッドについて Read トレイトを確認するように指示されていないため、失敗します。
use std::fs::File;
fn main() -> std::io::Result<()> {
let mut file = File::open("config.toml")?;
let mut contents = String::new();
// 失敗:std::io::Read がスコープ内にありません
file.read_to_string(&mut contents)?;
Ok(())
}
E0599 の解決方法
1. コンパイラのアドバイスに従う
Rust コンパイラは非常に親切です。エラー出力を確認すると、通常、必要な正確なトレイトを特定してくれます。提案された use 行をコピーして、ソースファイルの先頭に貼り付けるだけです。
2. 一般的な I/O トレイトをインポートする
頻繁に I/O 処理を行う場合は、prelude をインポートして、いくつかの一般的なトレイトを一度に取り込むことができます。これには Read、Write、BufRead が含まれます。
use std::io::prelude::*;
3. 非同期拡張トレイトを確認する
tokio や futures などの非同期クレートは、多くの場合、メソッドを「拡張 (Extension)」トレイトの中に隠しています。非同期ストリームで .read() や .write_all() が動作しない場合は、おそらく以下のいずれかが必要です。
use tokio::io::AsyncReadExt;use tokio::io::AsyncWriteExt;use futures::stream::StreamExt;
4. 変数の型を検査する
変数が想定している型ではないために E0599 が発生することがあります。よくある間違いは、Result や Option の中にある値ではなく、それら自体に対してメソッドを呼び出してしまうことです。例えば、File::open は Result<File, Error> を返します。
// Result には read_to_string メソッドがないため、これは失敗します
let file = File::open("data.txt");
file.read_to_string(&mut s);
// '?' 演算子が File をアンラップするため、これは動作します
let mut file = File::open("data.txt")?;
file.read_to_string(&mut s);
一般的なトレイトのチートシート
E0599 に遭遇した場合は、メソッドが以下の標準トレイトのいずれかに属しているか確認してください。
メソッド
必要なトレイト
`read_to_string`, `read_exact`
`std::io::Read`
`write_all`, `flush`
`std::io::Write`
`next`, `collect`, `map`
`std::iter::Iterator`
`try_into`
`std::convert::TryInto`
`stream.next()` (非同期)
`futures::stream::StreamExt`
ワークフローを高速化するには、IDE で rust-analyzer を使用してください。トレイトのインポートが必要なメソッド名を入力するたびに、「クイック修正」(Cmd+. または Alt+Enter)を介してこれらのインポートを自動的に追加できます。

