Rustのエラー E0425: cannot find value in this scope(名前が見つからない)
E0425 は、Rust がコードのある場所で名前を探したけれど、そこでは見つからなかった、という意味のエラーです。とてもよく出会うエラーのひとつですが、ほとんどの場合すぐに直せます。原因はたいてい、つづりの間違い、別のブロックの中で作った変数、またはモジュールのパスが必要な関数のどれかです。このシリーズのほかのエラーは、Rustのコンパイルエラー解説を見てください。
エラーメッセージ
Section titled “エラーメッセージ”error[E0425]: cannot find value `total_scor` in this scope --> src/main.rs:3:33 |3 | println!("Final score: {}", total_scor); | ^^^^^^^^^^ |help: a local variable with a similar name exists |3 | println!("Final score: {}", total_score); | +「cannot find value total_scor in this scope」は「このスコープに値 total_scor が見つからない」という意味です。help は「似た名前のローカル変数がある」と教えてくれています。
このエラーが出るのは、次のプログラムです。
fn main() { let total_score = 42; println!("Final score: {}", total_scor);}エラーの意味
Section titled “エラーの意味”^^^^ の印が付いているのが、Rust が見つけられなかった名前です。3行目の total_scor ですね。「in this scope」(このスコープで)とは、「この行の位置から見て」という意味です。Rust はその場所から見えるすべての変数、関数、インポートを調べましたが、その名前のものはありませんでした。
help: の行も読んでみましょう。ここでは rustc が似た名前の変数(total_score)を見つけて、足りない1文字の位置を + で示してくれています。「a local variable with a similar name exists」(似た名前のローカル変数がある)と出たら、それはつづりの間違いです。
友だちの名前は「さとし」なのに、部屋の向こうから「さとう!」と呼びかけたようなものです。本人はすぐそこにいるのに、「さとう」という名前には誰も返事をしません。
足りない名前が呼び出そうとした関数のときは、同じエラーが cannot find function ... in this scope(このスコープに関数が見つからない)という形で表示されます。
Rust がこうする理由
Section titled “Rust がこうする理由”Rust は、プログラムを実行する前に、すべての名前が何を指しているのかを決めます。変数が存在するのは、その let の行から、宣言したブロックの閉じ } までだけです。これがその変数のスコープ(scope)です。その範囲の外では、その名前はそもそも存在しません。
多くの言語では、この間違いがその場では見逃され、あとになって気づくことになります。JavaScript では、つづりを間違えると知らないうちに新しいグローバル変数ができたり、undefined になったりします。Python なら実行時に NameError が出ますが、それはテストで一度も通らなかったコードの道筋でだけ起きるかもしれません。Rust はこれをコンパイル時に、毎回必ず見つけてくれます。
関数もモジュールで同じ考え方に従います。mod billing の中の関数は、パスを書くか use で持ち込むまで、main からは見えません。
直し方1:つづりを直す
Section titled “直し方1:つづりを直す”help: の行に似た名前があると書かれているときは、これを選びましょう。原因としては、これがずば抜けて多いです。Rust の名前は大文字と小文字も区別するので、Total_score と total_score は別の名前です。
fn main() { let total_score = 42; println!("Final score: {}", total_score);}実行結果:
Final score: 42(エラーになる例と比べやすいように、ここでは表示する文字列を英語のままにしています。)
直し方2:両方の場所から見えるところで変数を宣言する
Section titled “直し方2:両方の場所から見えるところで変数を宣言する”help に「the binding is available in a different scope in the same function」(その束縛は同じ関数内の別のスコープにある)と出たときは、これを選びます。ループや if のブロックの中で変数を作り、} のあとでそれを使おうとしたケースです。エラーになるのは、たとえばこんなコードです。
fn main() { let prices = [120, 300, 80]; for price in prices { let with_tax = price + price / 10; println!("{with_tax}"); } println!("最後の税込み価格: {}", with_tax); // error[E0425]}with_tax は、ループが1周するたびに新しく作られ、ループの } で捨てられます。ループのあとでも値が必要なら、ループの前で宣言して、ループの中で更新しましょう。
fn main() { let prices = [120, 300, 80]; let mut last_with_tax = 0;
for price in prices { let with_tax = price + price / 10; println!("{with_tax}"); last_with_tax = with_tax; }
println!("最後の税込み価格: {}", last_with_tax);}実行結果:
13233088最後の税込み価格: 88変数をその let の行より前で使ってしまったときも、同じ直し方が使えます。Rust は上から下へ読むので、let を上に移すだけです。
直し方3:関数のパスを書くか、use を追加する
Section titled “直し方3:関数のパスを書くか、use を追加する”cannot find function と出て、その関数が別のモジュールにあるときは、これを選びます。Rust はこう表示します。
error[E0425]: cannot find function `total_with_tax` in this scope --> src/main.rs:8:17 |8 | let total = total_with_tax(50.0); | ^^^^^^^^^^^^^^ not found in this scope |help: consider importing this function |1 + use crate::billing::total_with_tax; |help は「この関数をインポートしてはどうか」と提案しています。フルパスで呼び出す(billing::total_with_tax(50.0))か、rustc が提案する use の行を追加しましょう。
mod billing { pub fn total_with_tax(amount: f64) -> f64 { amount * 1.2 }}
use crate::billing::total_with_tax;
fn main() { let total = total_with_tax(50.0); println!("{total}");}実行結果:
60関数には pub も必要です。pub がないと、別のエラー(E0603、「function is private」=関数が非公開)になります。パスと use のしくみはモジュールで説明しています。
直し方4:フィールドの前に self. を付ける
Section titled “直し方4:フィールドの前に self. を付ける”メソッドの中で、見つからない名前が自分の構造体のフィールドのときは、これを選びます。Java や C# から来た人は、count と書けばフィールドのことだと思いがちです。でも Rust では、いつも self.count と書きます。rustc は help: you might have meant to use the available field(使えるフィールドのことではありませんか)と教えてくれます。
struct Counter { count: u32,}
impl Counter { fn report(&self) { println!("カウント: {}", self.count); }}
fn main() { let c = Counter { count: 3 }; c.report();}実行結果:
カウント: 3よく出会う場面
Section titled “よく出会う場面”-
ifの中で作った変数。if balance > 50 { let bonus = 10; }のあとでprintln!("{}", bonus)と書くとエラーになります。bonusは}で消えてしまうからです。直し方:ifに値を返させて、let bonus = if balance > 50 { 10 } else { 0 };と書きます。 -
型を付けずにコンストラクタを呼ぶ。
let p = new("ferris");はcannot find function `new` in this scopeになります。直し方:newは型に属しているので、Player::new("ferris")と書きます。 -
self引数のない関数でselfを使う。 これは E0425 の近い親戚、E0424 です。error[E0424]: expected value, found module `self`--> src/main.rs:7:9|6 | fn reset() {| ----- this function doesn't have a `self` parameter7 | self.count = 0;| ^^^^ `self` value is a keyword only available in methods with a `self` parameter「この関数には
self引数がない」「selfはself引数を持つメソッドの中でしか使えないキーワード」という意味です。直し方:self引数を追加します。rustc は&selfを提案しますが、この関数はフィールドを書き換えるので、fn reset(&mut self)にする必要があります。
関連するエラー
Section titled “関連するエラー”- E0599:メソッドが見つからない:メソッドとして呼んだ名前が、その型にない。
- E0382:ムーブされた値の使用:変数はあるけれど、その値はもうムーブされている。
- E0308:型の不一致:名前は見つかったけれど、型が違う。
- E0277:トレイト境界を満たしていない:あるコードが必要とするトレイトを、型が実装していない。
- コンパイルエラーの一覧:エラー解説ページの全リストと、それぞれの短い説明です。
理解度チェック
Section titled “理解度チェック”理解度チェック
1. rustc が「help: a local variable with a similar name exists」と表示しました。いちばん考えられる原因はどれですか?
2. for ループの中で let found = true; と書き、ループのあとで found を使いました。なぜエラーになるのですか?
3. 関数 send は mod mailer の中にあります。main から send() と呼べるようにするのはどの行ですか?
スコア: 0 / 3
さらに詳しく
Section titled “さらに詳しく”- E0425 — Rust error codes index(英語):このエラーの公式の説明です。ほかの例も載っています。
- useキーワードでパスをスコープに持ち込む — The Rust Programming Language 日本語版:
useを使って、ほかのモジュールの関数を見えるようにする方法です。 - スコープとシャドーイング — Rust By Example 日本語版:変数がどこで生まれて、どこで消えるのかを短い例で紹介しています。
- メソッド記法 — The Rust Programming Language 日本語版:メソッドがなぜ
selfを使うのか、selfを通してフィールドにアクセスする方法がわかります。 - E0424 — Rust error codes index(英語):メソッドの外で
selfを使ったときの、関連するエラーです。