Flux de contrôle
<!-- verified-against: seed-llvm; examples: docs-examples-test -->
Conditions et boucles
fn classify(value: i64, values: [3]i64) -> i64 {
let label = if value > 0 { 1 } else if value < 0 { -1 } else { 0 }
let mut index: usize = 0
let mut total = label
while index < len(values) {
total += values[index]
index = index + 1
}
for item in values {
total += item
}
total
}
if est une expression. while et for soutien break et continue. Une boucle dirigée par name: peut être ciblé à partir de boucles imbriquées avec break :name / continue :name; simple break/continue garder le sens de la boucle la plus interne et la réutilisation séquentielle d'une étiquette est autorisée. La sortie exécute un nettoyage spécifique aux bords pour chaque étendue intermédiaire et ne traverse jamais une spawn frontière. Étiqueté break/continue ne prend aucune valeur. for sur des plages, des tableaux, des tranches et text/buffer valeurs (str, string, bytes, shared_bytes) descend à un niveau direct sans allocation index/length boucle. Rendement du texte et des tampons u8 éléments (unités d'octets, indexation correspondante) ; les éléments de déplacement uniquement nécessitent une indexation explicite et une gestion de la propriété. enumerate suit les mêmes types avec un usize indice.
Match et ADT
enum Response {
Ok(i64)
Err(str)
}
fn status(value: Response) -> i64 {
match value {
Ok(code) => code
Err(message) => -1
}
}
Les bras de correspondance n'ont pas besoin de virgules, sauf si la limite est ambiguë : un bras dont le corps se termine par une expression suivie d'un modèle (/[ nécessite la virgule (B044). La correspondance doit être exhaustive, sauf si le flux restant est inaccessible. Les modèles prennent en charge les littéraux, les tuples, les structures, les variantes, les liaisons, les rejets et les gardes. Les charges utiles de déplacement uniquement sont transférées uniquement lorsqu'un bras est sélectionné ; un modèle ou une garde défaillante préserve le propriétaire pour des armes ultérieures.
if let et while let
fn label(found: ?string) -> i64 {
if let Some(text) = found { len(text) as i64 } else { 0 }
}
fn count_down(from: ?i64) -> i64 {
let mut total: i64 = 0
let mut current = from
while let Some(value) = current {
total += value
if value > 0 { current = Some(value - 1) } else { current = None }
}
total
}
Les deux sont des formes de surface sur match et desugar à un match à deux bras dont le deuxième bras est le complément, donc contraignant, move/borrow le comportement, l'exhaustivité et le nettoyage sont exactement les règles du match. if let Some(...) nomme son complément None; un autre modèle de variante conserve un bras générique, qui H032 rejette lorsque le candidat transporte une charge utile de déplacement uniquement (écrivez le message explicite match bras là-bas), et un modèle irréfutable (while let name = value) est rejeté car H029.
Options, résultats et ?
fn find(enabled: bool) -> ?i64 {
if enabled { Some(42) } else { None }
}
fn forward(enabled: bool) -> ?i64 {
let value = find(enabled)?
Some(value)
}
? donne le present/success payload ou renvoie l’échec correspondant. La propagation des résultats peut changer le type de réussite mais préserve le type d'erreur. Aucune allocation ou clonage implicite ne se produit. ? ne peut pas traverser un spawn frontière.
Nettoyage sur les bords du flux
Chute, return, break, et continue exécuter le plan de nettoyage vérifié pour les propriétaires vivants. Panic/trap/abort les bords ne se déroulent jamais et n’effectuent aucun nettoyage.