shadows declaration from outer scope — Como Resolver em Zig

shadows declaration from outer scope — Como Resolver em Zig

O Que Este Erro Significa

O erro shadows declaration from outer scope ocorre quando você declara uma variável ou constante com o mesmo nome de outra que já existe em um escopo externo. Em Zig, o sombreamento de variáveis (shadowing) é proibido por padrão. Isso é diferente de linguagens como Rust, JavaScript ou Python, onde é possível redeclarar uma variável com o mesmo nome em escopos internos.

A decisão de proibir shadowing foi feita para evitar bugs sutis onde o programador pensa estar usando uma variável, mas está usando outra com o mesmo nome.

Causas Comuns

1. Variável com Mesmo Nome em Bloco Interno

pub fn main() void {
    const x: u32 = 10;
    {
        const x: u32 = 20; // ERRO: 'x' shadows declaration from outer scope
        _ = x;
    }
    _ = x;
}

2. Captura de Iteração com Nome de Variável Existente

pub fn main() void {
    const item: u32 = 42;
    const arr = [_]u32{ 1, 2, 3 };
    for (arr) |item| { // ERRO: 'item' shadows declaration from outer scope
        _ = item;
    }
    _ = item;
}

3. Captura de Optional com Nome Conflitante

pub fn main() void {
    const valor: u32 = 10;
    const opcional: ?u32 = 42;
    if (opcional) |valor| { // ERRO: 'valor' shadows declaration
        _ = valor;
    }
    _ = valor;
}

4. Captura de Erro com Nome Conflitante

fn falhar() !u32 {
    return error.Falha;
}

pub fn main() void {
    const err = "alguma coisa";
    _ = falhar() catch |err| { // ERRO: 'err' shadows declaration
        _ = err;
    };
    _ = err;
}

5. Parâmetro de Função com Nome de Global

const limite = 100;

fn verificar(limite: u32) bool { // ERRO: 'limite' shadows module-level declaration
    return limite > 50;
}

Como Corrigir

Solução 1: Renomear a Variável Interna

Use um nome diferente que descreva melhor o propósito:

pub fn main() void {
    const x: u32 = 10;
    {
        const y: u32 = 20; // Nome diferente
        _ = y;
    }
    _ = x;
}

Solução 2: Renomear Captura de Iteração

pub fn main() void {
    const item: u32 = 42;
    const arr = [_]u32{ 1, 2, 3 };
    for (arr) |elemento| { // Nome diferente: 'elemento'
        _ = elemento;
    }
    _ = item;
}

Solução 3: Renomear Captura de Optional

pub fn main() void {
    const valor: u32 = 10;
    const opcional: ?u32 = 42;
    if (opcional) |valor_desempacotado| { // Nome descritivo
        _ = valor_desempacotado;
    }
    _ = valor;
}

Solução 4: Renomear Captura de Erro

fn falhar() !u32 {
    return error.Falha;
}

pub fn main() void {
    const msg_erro = "alguma coisa";
    _ = falhar() catch |err| { // Nomes distintos
        _ = err;
    };
    _ = msg_erro;
}

Solução 5: Renomear Parâmetro de Função

const limite_global = 100; // Renomear o global

fn verificar(limite: u32) bool {
    return limite > 50;
}

Ou renomear o parâmetro:

const limite = 100;

fn verificar(valor_limite: u32) bool { // Renomear o parâmetro
    return valor_limite > 50;
}

Boas Práticas de Nomenclatura

Para evitar conflitos de nome, siga estas convenções:

Use Nomes Descritivos

// Ruim: nomes genéricos que facilmente conflitam
const x = 10;
const valor = "texto";
const resultado = calcular();

// Bom: nomes específicos ao contexto
const largura_maxima = 10;
const nome_usuario = "texto";
const resultado_calculo = calcular();

Prefixos em Capturas

// Em loops, use nomes que descrevam o item
for (usuarios) |usuario| { ... }
for (pontuacoes) |pontuacao| { ... }

// Em error handling, use nomes descritivos
catch |err_leitura| { ... }
catch |err_conexao| { ... }

Evite Conflito com Imports

const std = @import("std");
const mem = std.mem; // Atalho comum

fn processar(memoria: []u8) void { // Não use 'mem' como parâmetro
    _ = memoria;
}

Por Que Zig Proíbe Shadowing?

O shadowing pode causar bugs difíceis de encontrar:

// Em uma linguagem que permite shadowing (exemplo conceitual):
fn calcular_preco(quantidade: u32) u32 {
    const taxa = 10;
    if (quantidade > 100) {
        const taxa = 5; // Shadow! Programador pode não perceber
        return quantidade * taxa;
    }
    return quantidade * taxa; // Usa a taxa original
}

O programador pode pensar que está usando a mesma variável taxa em ambos os caminhos, mas na verdade são variáveis diferentes. Ao proibir shadowing, Zig força clareza.

Erros Relacionados

Continue aprendendo Zig

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