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
- undeclared identifier — Identificador não declarado no escopo
- unused local variable — Variável declarada mas não utilizada
- ambiguous reference — Referência ambígua entre imports