@compileError em Zig
O @compileError gera um erro de compilação com uma mensagem personalizada. É usado principalmente em código genérico e metaprogramação para rejeitar tipos ou configurações inválidos em tempo de compilação, antes que o programa seja executado. Esse mecanismo garante que problemas sejam detectados o mais cedo possível.
Sintaxe
@compileError(comptime msg: []const u8) noreturn
O que faz
O @compileError interrompe a compilação e exibe a mensagem fornecida como erro. O compilador aponta exatamente a linha onde o @compileError foi invocado, facilitando a identificação do problema. Esse builtin é especialmente poderoso em branches de switch ou if em comptime que representam caminhos de código inválidos.
Parâmetros
- msg (
[]const u8, comptime): A mensagem de erro a ser exibida pelo compilador. Deve ser uma string conhecida em tempo de compilação. Pode ser construída por concatenação de strings literais.
Valor de retorno
O tipo de retorno é noreturn — a compilação é interrompida e nenhum valor é produzido.
Exemplos práticos
Exemplo 1: Validação de tipos em funções genéricas
const std = @import("std");
fn somar(a: anytype, b: anytype) @TypeOf(a, b) {
const T = @TypeOf(a, b);
const info = @typeInfo(T);
switch (info) {
.int, .comptime_int => return a + b,
.float, .comptime_float => return a + b,
else => @compileError(
"somar() requer tipos numéricos, recebeu: " ++ @typeName(T),
),
}
}
test "somar numéricos" {
try std.testing.expect(somar(@as(i32, 10), @as(i32, 20)) == 30);
try std.testing.expect(somar(@as(f64, 1.5), @as(f64, 2.5)) == 4.0);
// A linha abaixo geraria erro de compilação:
// _ = somar("hello", "world");
// Erro: somar() requer tipos numéricos, recebeu: *const [5:0]u8
}
Exemplo 2: Restrições de plataforma
const std = @import("std");
const builtin = @import("builtin");
fn funcaoApenasLinux() void {
if (builtin.os.tag != .linux) {
@compileError("Esta função só é suportada em Linux");
}
// Implementação específica de Linux...
}
fn funcaoApenas64Bits() void {
if (@sizeOf(usize) != 8) {
@compileError("Esta função requer uma arquitetura de 64 bits");
}
// Implementação que depende de ponteiros de 64 bits...
}
Exemplo 3: Validação de campos de struct em comptime
const std = @import("std");
fn validarModelo(comptime T: type) void {
const info = @typeInfo(T);
if (info != .@"struct") {
@compileError("validarModelo requer uma struct, recebeu: " ++ @typeName(T));
}
const fields = info.@"struct".fields;
// Verificar que a struct tem campo "id"
comptime {
var tem_id = false;
for (fields) |f| {
if (std.mem.eql(u8, f.name, "id")) {
tem_id = true;
break;
}
}
if (!tem_id) {
@compileError(@typeName(T) ++ " deve ter um campo 'id'");
}
}
}
const Usuario = struct {
id: u64,
nome: []const u8,
};
// Isso compila normalmente
comptime {
validarModelo(Usuario);
}
// const Invalido = struct { nome: []const u8 };
// validarModelo(Invalido); // Erro: Invalido deve ter um campo 'id'
Casos de uso comuns
- Validação de tipos genéricos: Rejeitar tipos que não satisfazem os requisitos de uma função ou struct genérica.
- Restrições de plataforma: Impedir compilação em plataformas não suportadas.
- Funcionalidade não implementada: Marcar caminhos de código que ainda não foram implementados, diferente de
@panicque ocorre em runtime. - Validação de constantes: Verificar que constantes de configuração têm valores válidos.
- API segura: Guiar desenvolvedores com mensagens de erro claras quando usam uma API incorretamente.
Diferença entre @compileError e @panic
@compileErrorinterrompe a compilação — o programa nunca chega a ser executado.@panicinterrompe a execução — o programa compila mas falha ao encontrar o panic em runtime.
Use @compileError quando o erro pode ser detectado estaticamente. Use @panic para erros que só podem ser detectados em tempo de execução.
Builtins relacionados
- @compileLog — Imprime valores em tempo de compilação para depuração
- @typeName — Útil para construir mensagens de erro descritivas
- @typeInfo — Inspeciona tipos para validação
- @hasField — Verifica existência de campos
- @hasDecl — Verifica existência de declarações