Error Payload Not Used — Como Resolver em Zig

Error Payload Not Used — Como Resolver em Zig

O Que Este Erro Significa

O erro de compilação error payload capture is not used ocorre quando você captura o payload (valor) de um catch ou else em uma variável, mas nunca usa essa variável no corpo do bloco. Zig não permite variáveis não utilizadas — isso é tratado como um possível bug no código.

A mensagem do compilador:

error: unused capture

Ou:

error: error payload capture 'err' is not used

Esse comportamento é consistente com a filosofia de Zig de não tolerar código “morto” que pode indicar um bug lógico.

Causas Comuns

1. Capturar Erro em catch sem Usar

const std = @import("std");

pub fn main() void {
    const file = std.fs.cwd().openFile("dados.txt", .{}) catch |err| {
        // ERRO DE COMPILAÇÃO: err não é usado
        std.debug.print("Falha ao abrir arquivo\n", .{});
        return;
    };
    defer file.close();
}

2. Capturar Valor em if/else sem Usar

const std = @import("std");

fn obterDados() ![]const u8 {
    return error.Falha;
}

pub fn main() void {
    if (obterDados()) |dados| {
        // ERRO: dados não é usado
        std.debug.print("Sucesso\n", .{});
    } else |err| {
        // ERRO: err não é usado
        std.debug.print("Erro ocorreu\n", .{});
    }
}

3. Capturar Payload de Optional sem Usar

const std = @import("std");

pub fn main() void {
    const valor: ?u32 = 42;
    if (valor) |v| {
        // ERRO: v não é usado
        std.debug.print("Tem valor\n", .{});
    }
}

4. Capturar Erro para Log que Foi Removido

const std = @import("std");

fn processar() !void {
    return error.Falha;
}

pub fn main() void {
    processar() catch |err| {
        // Linha de log comentada, err ficou sem uso
        // std.debug.print("Erro: {}\n", .{err});
        return;
    };
}

Como Corrigir

Solucao 1: Usar o Payload Capturado

A solução mais óbvia — use a variável capturada:

const std = @import("std");

pub fn main() void {
    const file = std.fs.cwd().openFile("dados.txt", .{}) catch |err| {
        std.debug.print("Falha ao abrir arquivo: {}\n", .{err}); // Usa err
        return;
    };
    defer file.close();
}

Solucao 2: Usar Underscore para Descartar

Se você realmente não precisa do payload, use _:

const std = @import("std");

pub fn main() void {
    const file = std.fs.cwd().openFile("dados.txt", .{}) catch |_| {
        std.debug.print("Falha ao abrir arquivo\n", .{});
        return;
    };
    defer file.close();
}

Solucao 3: Omitir a Captura Quando Possível

Em alguns casos, você pode omitir a captura totalmente:

const std = @import("std");

pub fn main() void {
    // Sem captura — catch com bloco simples
    const file = std.fs.cwd().openFile("dados.txt", .{}) catch {
        std.debug.print("Falha ao abrir arquivo\n", .{});
        return;
    };
    defer file.close();
}

Solucao 4: Usar _ para Optional Payload

const std = @import("std");

pub fn main() void {
    const valor: ?u32 = 42;
    if (valor) |_| {
        std.debug.print("Tem valor\n", .{});
    }

    // Ou, se só quer testar existência:
    if (valor != null) {
        std.debug.print("Tem valor\n", .{});
    }
}

Solucao 5: Tratar Erros Específicos com switch

const std = @import("std");

pub fn main() void {
    const file = std.fs.cwd().openFile("dados.txt", .{}) catch |err| switch (err) {
        error.FileNotFound => {
            std.debug.print("Arquivo não encontrado\n", .{});
            return;
        },
        error.AccessDenied => {
            std.debug.print("Sem permissão\n", .{});
            return;
        },
        else => {
            std.debug.print("Erro: {}\n", .{err}); // err é usado aqui
            return;
        },
    };
    defer file.close();
}

Solucao 6: Simplificar com catch e Valor

const std = @import("std");

fn dividir(a: u32, b: u32) !u32 {
    if (b == 0) return error.DivisaoPorZero;
    return a / b;
}

pub fn main() void {
    // Se não precisa do erro, use catch com valor direto
    const resultado = dividir(10, 0) catch 0;
    std.debug.print("resultado: {}\n", .{resultado});
}

Formas Idiomáticas em Zig

catch sem Captura

// Quando o tipo do erro não importa
funcao() catch {
    // Trata qualquer erro
    return;
};

catch com Captura Usada

// Quando precisa logar ou tratar por tipo
funcao() catch |err| {
    log.err("Falha: {}", .{err}); // err é usado
    return;
};

catch com Descarte Explícito

// Quando captura é obrigatória mas valor não é necessário
funcao() catch |_| {
    // _ descarta explicitamente o erro
    return;
};

Por Que Zig Exige Isso

Zig trata variáveis não utilizadas como erros de compilação, não avisos, por uma razão: código não usado frequentemente indica bugs. Se você captura um erro mas não o examina, pode estar perdendo informação importante para depuração. A política de Zig é:

  1. Se precisa do valor, use-o.
  2. Se não precisa, declare explicitamente com _.
  3. Se nenhuma captura é necessária, omita-a.

Isso torna o código mais explícito e reduz bugs silenciosos.

Erros Relacionados

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.