Fluxo de controle

<!-- verified-against: seed-llvm; examples: docs-examples-test -->

Condições e loops

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 é uma expressão. while e for suporte break e continue. Um loop liderado por name: pode ser direcionado a partir de loops aninhados com break :name / continue :name; simples break/continue continue significando o loop mais interno e a reutilização sequencial de um rótulo é permitida. A saída executa uma limpeza específica da borda para cada escopo intermediário e nunca cruza um spawn limite. Rotulado break/continue não tome nenhum valor. for sobre intervalos, matrizes, fatias e text/buffer valores (str, string, bytes, shared_bytes) reduz para um valor livre de atribuição direta index/length laço. Rendimento de texto e buffers u8 elementos (unidades de bytes, indexação correspondente); elementos somente movimentação requerem indexação explícita e tratamento de propriedade. enumerate segue os mesmos tipos com um usize índice.

Partida e ADTs

enum Response {
    Ok(i64)
    Err(str)
}

fn status(value: Response) -> i64 {
    match value {
        Ok(code) => code
        Err(message) => -1
    }
}

Os braços correspondentes não precisam de vírgulas, a menos que o limite seja ambíguo: um braço cujo corpo termina em uma expressão seguida por um padrão (/[ requer a vírgula (B044). A correspondência deve ser exaustiva, a menos que o fluxo restante seja inacessível. Os padrões suportam literais, tuplas, estruturas, variantes, ligações, descarte e guardas. As cargas úteis somente de movimentação são transferidas somente quando um braço é selecionado; um padrão ou guarda com falha preserva o proprietário para armas posteriores.

if let e 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
}

Ambas são formas superficiais match e açúcar para uma partida de dois braços cujo segundo braço é o complemento, tão vinculativo, move/borrow comportamento, exaustividade e limpeza são exatamente as regras de correspondência. if let Some(...) nomeia seu complemento None; outro padrão variante mantém um braço curinga, que H032 rejeita quando o examinado carrega uma carga útil somente de movimento (escreva o explícito match braços lá) e um padrão irrefutável (while let name = value) é rejeitado como H029.

Opções, resultados e ?

fn find(enabled: bool) -> ?i64 {
    if enabled { Some(42) } else { None }
}

fn forward(enabled: bool) -> ?i64 {
    let value = find(enabled)?
    Some(value)
}

? produz o present/success carga útil ou retorna a falha correspondente. A propagação do resultado pode alterar o tipo de sucesso, mas preserva o tipo de erro. Nenhuma alocação implícita ou clone ocorre. ? não pode cruzar um spawn limite.

Limpeza nas bordas do fluxo

Queda, return, breake continue execute o plano de limpeza verificado para proprietários ativos. Panic/trap/abort as bordas nunca se desenrolam e não fazem limpeza.