コンテンツにスキップ

Rustのエラー E0425: cannot find value in this scope(名前が見つからない)

E0425 は、Rust がコードのある場所で名前を探したけれど、そこでは見つからなかった、という意味のエラーです。とてもよく出会うエラーのひとつですが、ほとんどの場合すぐに直せます。原因はたいてい、つづりの間違い、別のブロックの中で作った変数、またはモジュールのパスが必要な関数のどれかです。このシリーズのほかのエラーは、Rustのコンパイルエラー解説を見てください。

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);
}

^^^^ の印が付いているのが、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 は、プログラムを実行する前に、すべての名前が何を指しているのかを決めます。変数が存在するのは、その let の行から、宣言したブロックの閉じ } までだけです。これがその変数のスコープ(scope)です。その範囲の外では、その名前はそもそも存在しません。

多くの言語では、この間違いがその場では見逃され、あとになって気づくことになります。JavaScript では、つづりを間違えると知らないうちに新しいグローバル変数ができたり、undefined になったりします。Python なら実行時に NameError が出ますが、それはテストで一度も通らなかったコードの道筋でだけ起きるかもしれません。Rust はこれをコンパイル時に、毎回必ず見つけてくれます。

関数もモジュールで同じ考え方に従います。mod billing の中の関数は、パスを書くか use で持ち込むまで、main からは見えません。

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);
}

実行結果:

132
330
88
最後の税込み価格: 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
▶ 実際に試してみよう
  • 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` parameter
    7 | 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) にする必要があります。

理解度チェック

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