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);}这个错误是什么意思
Section titled “这个错误是什么意思”^^^^ 标出的就是 Rust 找不到的名字:第 3 行的 total_scor。“in this scope”(在这个作用域里)指的是“从这一行所在的位置看过去”。Rust 检查了在这个位置能看到的所有变量、函数和导入,没有一个叫这个名字。
help: 那一行也要看。这里 rustc 发现了一个名字很像的变量(total_score),还用 + 标出了少写的那个字母。看到 “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 在每一轮循环里都会重新创建,到循环的 } 就被扔掉了。如果循环结束后还需要某个值,就在循环之前声明它,在循环里更新它:
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 的。少了它,你会得到另一个错误(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` 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)。
- E0599:找不到方法:你当作方法调用的名字,在这个类型上不存在。
- E0382:使用已移动的值:变量存在,但它的值已经被移走了。
- E0308:类型不匹配:名字找到了,但类型不对。
- E0277:未实现 trait:某个类型缺少代码需要的 trait。
- 所有编译错误:完整列表,每个错误都附有简短说明。
小测验
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
- E0425 — Rust error codes index(英文):这个错误的官方说明,还有更多示例。
- 使用 use 关键字将路径引入作用域 — Rust 程序设计语言:
use怎样让其他模块里的函数变得可见。 - 作用域和遮蔽 — 通过例子学 Rust:用简短的例子展示变量在哪里产生、在哪里消失。
- 方法语法 — Rust 程序设计语言:方法为什么要用
self,以及怎样通过它访问字段。 - E0424 — Rust error codes index(英文):在方法之外使用
self时出现的相关错误。