Aller au contenu

Erreur Rust E0425 : cannot find value in this scope (nom introuvable)

L’erreur E0425 veut dire que Rust a cherché un nom à un endroit précis de votre code et ne l’a pas trouvé. C’est l’une des erreurs les plus fréquentes, et elle se corrige presque toujours très vite : en général, c’est une faute de frappe, une variable qui vit dans un autre bloc, ou une fonction qui a besoin du chemin de son module. Cette page fait partie du guide des erreurs du compilateur 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);
| +

Le compilateur vous dit : « impossible de trouver la valeur total_scor dans cette portée ». Il ajoute qu’une variable locale au nom très proche existe.

Voici le programme qui la provoque :

fn main() {
let total_score = 42;
println!("Final score: {}", total_scor);
}

Les ^^^^ désignent le nom que Rust n’a pas trouvé : total_scor, à la ligne 3. « In this scope » (dans cette portée) veut dire « depuis l’endroit où se trouve cette ligne ». Rust a passé en revue toutes les variables, fonctions et imports visibles à ce point du code, et aucun ne portait ce nom.

Lisez aussi la ligne help:. Ici, rustc a repéré une variable au nom semblable (total_score) et vous montre même la lettre manquante avec un +. Quand vous voyez « a local variable with a similar name exists » (une variable locale au nom semblable existe), c’est une faute de frappe.

C’est comme appeler « Jon ! » à travers une pièce alors que votre ami s’appelle John. Il est juste là, mais personne ne répond au nom de « Jon ».

La même erreur apparaît aussi sous la forme cannot find function ... in this scope (fonction introuvable) quand le nom manquant est une fonction que vous appelez.

Rust décide, avant même que votre programme tourne, à quoi correspond chaque nom. Une variable n’existe qu’entre sa ligne let et l’accolade fermante } du bloc où elle a été déclarée. C’est sa portée (scope). En dehors de cette zone, le nom n’existe tout simplement pas.

Beaucoup de langages vous laisseraient faire, et vous découvririez le problème plus tard. En JavaScript, une faute de frappe peut créer sans bruit une nouvelle variable globale ou vous donner undefined. En Python, vous obtiendriez une NameError à l’exécution, peut-être uniquement dans le cas que vos tests ne couvrent jamais. Rust la détecte à la compilation, à chaque fois.

Les fonctions suivent la même idée avec les modules : une fonction dans mod billing n’est pas visible depuis main tant que vous n’écrivez pas son chemin ou que vous ne l’importez pas avec use.

Choisissez-la quand la ligne help: dit qu’un nom semblable existe. C’est de loin la cause la plus fréquente. Les noms Rust sont aussi sensibles à la casse : Total_score et total_score sont deux noms différents.

fn main() {
let total_score = 42;
println!("Score final : {}", total_score);
}

Sortie :

Score final : 42
▶ Essayez par vous-même

Solution 2 : déclarer la variable là où les deux endroits la voient

Section intitulée « Solution 2 : déclarer la variable là où les deux endroits la voient »

Choisissez-la quand l’aide dit « the binding is available in a different scope in the same function » (la variable existe dans une autre portée de la même fonction). Vous avez créé la variable dans une boucle ou un bloc if, puis vous l’avez utilisée après le }. La version qui ne compile pas ressemble à ceci :

fn main() {
let prices = [120, 300, 80];
for price in prices {
let with_tax = price + price / 10;
println!("{with_tax}");
}
println!("Last price with tax: {}", with_tax); // error[E0425]
}

with_tax est recréée à chaque tour de boucle et jetée au } de la boucle. Si vous avez besoin d’une valeur après la boucle, déclarez-la avant la boucle et mettez-la à jour à l’intérieur :

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!("Dernier prix TTC : {}", last_with_tax);
}

Sortie :

132
330
88
Dernier prix TTC : 88
▶ Essayez par vous-même

La même correction marche si vous avez utilisé une variable avant sa ligne let. Rust lit de haut en bas : remontez simplement le let.

Solution 3 : donner le chemin de la fonction, ou ajouter un use

Section intitulée « Solution 3 : donner le chemin de la fonction, ou ajouter un use »

Choisissez-la pour cannot find function quand la fonction se trouve dans un autre module. Rust affiche :

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

Rustc vous propose d’importer la fonction. Vous pouvez soit l’appeler avec son chemin complet (billing::total_with_tax(50.0)), soit ajouter la ligne use suggérée :

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

Sortie :

60
▶ Essayez par vous-même

La fonction doit aussi être pub. Sans ça, vous obtiendriez une autre erreur (E0603, « function is private », la fonction est privée). Voir Les modules pour comprendre comment fonctionnent les chemins et use.

Choisissez-la dans une méthode, quand le nom manquant est l’un des champs de votre struct. Si vous venez de Java ou de C#, il est naturel d’écrire count en pensant au champ. En Rust, on écrit toujours self.count. Rustc vous le dit : help: you might have meant to use the available field (vous vouliez peut-être utiliser le champ disponible).

struct Counter {
count: u32,
}
impl Counter {
fn report(&self) {
println!("Compteur : {}", self.count);
}
}
fn main() {
let c = Counter { count: 3 };
c.report();
}

Sortie :

Compteur : 3
▶ Essayez par vous-même
  • Une variable définie dans un if. if balance > 50 { let bonus = 10; } suivi de println!("{}", bonus) échoue, car bonus a disparu au }. Correction : faites produire la valeur par le if, let bonus = if balance > 50 { 10 } else { 0 };.

  • Appeler un constructeur sans son type. let p = new("ferris"); donne cannot find function `new` in this scope. Correction : new appartient au type, écrivez donc Player::new("ferris").

  • Utiliser self dans une fonction sans paramètre self. C’est le proche cousin d’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

    Rustc explique que cette fonction n’a pas de paramètre self, et que self n’est disponible que dans les méthodes qui en ont un. Correction : ajoutez un paramètre self. Rustc propose &self, mais ici la fonction modifie un champ, il faut donc fn reset(&mut self).

Petit quiz

1. Rustc dit « help: a local variable with a similar name exists ». Quelle est la cause la plus probable ?

2. Vous écrivez let found = true; dans une boucle for et vous utilisez found après la boucle. Pourquoi ça échoue ?

3. Une fonction send se trouve dans mod mailer. Quelle ligne permet à main de l'appeler avec send() ?

Score : 0 / 3