undeclared identifier — Como Resolver em Zig

undeclared identifier — Como Resolver em Zig

O Que Este Erro Significa

O erro undeclared identifier aparece quando você tenta usar um nome (variável, constante, função ou tipo) que o compilador não consegue encontrar no escopo atual. Isso significa que o nome não foi declarado anteriormente, foi digitado incorretamente, ou está em um escopo diferente do que você espera.

A mensagem completa é:

error: use of undeclared identifier 'nome'

Causas Comuns

1. Erro de Digitação no Nome

A causa mais trivial, mas surpreendentemente frequente:

const std = @import("std");

pub fn main() void {
    const mensagem = "Olá";
    std.debug.print("{s}\n", .{mesagem}); // ERRO: 'mesagem' (faltou o 'n')
}

2. Variável Fora de Escopo

Em Zig, variáveis declaradas dentro de um bloco não existem fora dele:

const std = @import("std");

pub fn main() void {
    if (true) {
        const x: u32 = 42;
        _ = x;
    }
    std.debug.print("{}\n", .{x}); // ERRO: 'x' não existe neste escopo
}

3. Esquecer de Importar o Módulo

pub fn main() void {
    std.debug.print("olá\n", .{}); // ERRO: 'std' não declarado
}

Faltou a linha de import:

const std = @import("std"); // Necessário!

4. Usar Função Antes de Declará-la (em Escopo Local)

Diferente de funções no nível do módulo, variáveis locais precisam ser declaradas antes do uso:

pub fn main() void {
    const resultado = calcular(5); // ERRO: se 'calcular' não está no escopo do módulo
    _ = resultado;
}

Note que funções declaradas no nível do arquivo (fora de qualquer função) podem ser chamadas de qualquer lugar do mesmo arquivo, independente da ordem.

5. Acessar Campo de Struct Incorretamente

const Ponto = struct {
    x: f64,
    y: f64,
};

pub fn main() void {
    const p = Ponto{ .x = 1.0, .y = 2.0 };
    _ = p.z; // ERRO: pode gerar um erro de campo, não de identificador
}

6. Confundir Namespace de Enum

const Cor = enum { vermelho, verde, azul };

pub fn main() void {
    const c = vermelho; // ERRO: 'vermelho' não é um identificador global
    _ = c;
}

7. Usar Variável de Captura Fora do Bloco

const std = @import("std");

pub fn main() void {
    const opcional: ?u32 = 42;
    if (opcional) |valor| {
        std.debug.print("{}\n", .{valor});
    }
    std.debug.print("{}\n", .{valor}); // ERRO: 'valor' só existe dentro do if
}

Como Corrigir

Solução 1: Verificar a Ortografia

Compare cuidadosamente o nome usado com o nome declarado:

const std = @import("std");

pub fn main() void {
    const mensagem = "Olá";
    std.debug.print("{s}\n", .{mensagem}); // Corrigido: 'mensagem'
}

Solução 2: Declarar no Escopo Correto

Mova a declaração para um escopo onde ela seja acessível:

const std = @import("std");

pub fn main() void {
    var x: u32 = 0;
    if (true) {
        x = 42;
    }
    std.debug.print("{}\n", .{x}); // OK: 'x' está no escopo de main
}

Solução 3: Adicionar os Imports Necessários

const std = @import("std"); // Sempre importe o que usar

pub fn main() void {
    std.debug.print("olá\n", .{});
}

Solução 4: Usar o Namespace Completo para Enums

const Cor = enum { vermelho, verde, azul };

pub fn main() void {
    const c = Cor.vermelho; // Correto: usa o namespace da enum
    _ = c;
}

Ou use com anotação de tipo:

const c: Cor = .vermelho; // Também funciona com tipo inferido

Solução 5: Ampliar o Escopo da Variável de Captura

const std = @import("std");

pub fn main() void {
    const opcional: ?u32 = 42;
    const valor = opcional orelse 0; // Valor acessível em todo o escopo
    std.debug.print("{}\n", .{valor});
}

Cenários Especiais

Identificadores em @import de Outros Arquivos

Quando você importa um módulo, só tem acesso a declarações pub:

// arquivo: utils.zig
fn funcaoPrivada() void {} // Sem 'pub' — não acessível externamente
pub fn funcaoPublica() void {} // Com 'pub' — acessível

// arquivo: main.zig
const utils = @import("utils.zig");

pub fn main() void {
    utils.funcaoPublica(); // OK
    utils.funcaoPrivada(); // ERRO: não é público
}

Builtin Functions

Funções built-in do Zig começam com @. Se você esquecer o @, terá um erro de identificador:

const tipo = TypeOf(variavel);  // ERRO
const tipo = @TypeOf(variavel); // Correto

Dicas Importantes

  1. Use ZLS (Zig Language Server) — Autocomplete previne erros de digitação
  2. Organize imports no topo — Mantenha todos os @import no início do arquivo
  3. Preste atenção no escopo — Chaves {} criam novos escopos em Zig
  4. Funções no nível do módulo — São acessíveis em qualquer ordem no mesmo arquivo

Erros Relacionados

Continue aprendendo Zig

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