ambiguous reference — Como Resolver em Zig
O Que Este Erro Significa
O erro ambiguous reference ocorre quando o compilador Zig encontra um identificador que pode se referir a mais de uma declaração. Isso geralmente acontece quando dois módulos importados exportam símbolos com o mesmo nome, ou quando há conflito entre uma declaração local e uma importada. Zig não tenta adivinhar qual você quis usar — ele exige que a referência seja inequívoca.
Causas Comuns
1. Dois Imports com o Mesmo Nome de Símbolo
const std = @import("std");
// Suponha que ambos os módulos exportem 'Config'
const modulo_a = @import("modulo_a.zig");
const modulo_b = @import("modulo_b.zig");
pub fn main() void {
// Se ambos módulos têm um tipo 'Config', 'using' causa ambiguidade
const c = Config{}; // ERRO: ambiguous reference to 'Config'
_ = c;
}
2. usingnamespace com Conflito
O usingnamespace traz todos os símbolos públicos de um namespace para o escopo atual, o que pode causar conflitos:
const a = struct {
pub const valor = 10;
};
const b = struct {
pub const valor = 20;
};
usingnamespace a;
usingnamespace b;
pub fn main() void {
_ = valor; // ERRO: ambiguous reference — 'valor' existe em 'a' e 'b'
}
3. Conflito entre Import e Declaração Local
const std = @import("std");
const math = std.math;
// Declaração local com mesmo nome de algo importado
const inf = 999;
pub fn main() void {
// Se usar 'usingnamespace math', 'inf' pode conflitar
_ = inf;
}
4. Nomes Conflitantes em Structs Aninhadas
const Outer = struct {
const Inner = struct {
pub const nome = "inner";
};
pub const nome = "outer"; // Mesmo nome que Inner.nome
usingnamespace Inner;
// Agora 'nome' é ambíguo dentro de Outer
};
Como Corrigir
Solução 1: Usar Nomes Qualificados (Fully Qualified)
Em vez de usar o nome diretamente, especifique o módulo de origem:
const modulo_a = @import("modulo_a.zig");
const modulo_b = @import("modulo_b.zig");
pub fn main() void {
const config_a = modulo_a.Config{}; // Sem ambiguidade
const config_b = modulo_b.Config{}; // Sem ambiguidade
_ = config_a;
_ = config_b;
}
Solução 2: Criar Aliases Específicos
const modulo_a = @import("modulo_a.zig");
const modulo_b = @import("modulo_b.zig");
const ConfigA = modulo_a.Config;
const ConfigB = modulo_b.Config;
pub fn main() void {
const c = ConfigA{}; // Claro e sem ambiguidade
_ = c;
}
Solução 3: Evitar usingnamespace
A recomendação oficial da comunidade Zig é evitar usingnamespace quando possível. Use imports qualificados:
// Em vez de:
// usingnamespace std.math;
// Faça:
const math = std.math;
pub fn main() void {
const raiz = math.sqrt(@as(f64, 16.0)); // Qualificado
_ = raiz;
}
Solução 4: Renomear Declarações Conflitantes
const a = struct {
pub const valor_a = 10; // Renomeado
};
const b = struct {
pub const valor_b = 20; // Renomeado
};
pub fn main() void {
_ = a.valor_a; // Sem conflito
_ = b.valor_b; // Sem conflito
}
Solução 5: Importar Apenas o Necessário
Em vez de importar tudo com usingnamespace, importe apenas o que precisa:
const std = @import("std");
// Importações específicas
const Allocator = std.mem.Allocator;
const ArrayList = std.ArrayList;
const print = std.debug.print;
pub fn main() void {
print("Olá!\n", .{}); // Sem ambiguidade
}
Boas Práticas para Evitar Ambiguidade
1. Prefira Imports Qualificados
// Bom: imports claros e sem ambiguidade
const std = @import("std");
const fs = std.fs;
const mem = std.mem;
const io = std.io;
2. Use Aliases Descritivos
const HttpClient = std.http.Client;
const TcpStream = std.net.Stream;
3. Evite usingnamespace em Código de Produção
O usingnamespace é útil para prototipagem rápida, mas em código de produção, imports explícitos são preferíveis. A própria documentação do Zig desencoraja o uso indiscriminado.
4. Organize Imports no Topo do Arquivo
// Imports da biblioteca padrão
const std = @import("std");
const mem = std.mem;
const Allocator = mem.Allocator;
// Imports do projeto
const config = @import("config.zig");
const utils = @import("utils.zig");
// Tipos e constantes locais
const BUFFER_SIZE = 4096;
Erros Relacionados
- undeclared identifier — Identificador não encontrado
- shadows declaration from outer scope — Sombreamento de variável
- expected type ‘X’, found ‘Y’ — Tipo inesperado