Type Mismatch in Assignment — Como Resolver em Zig
O Que Este Erro Significa
O erro de incompatibilidade de tipo em atribuição ocorre quando você tenta atribuir um valor a uma variável cujo tipo não é compatível com o valor fornecido. Zig é extremamente rigoroso com tipos — não há conversões implícitas entre a maioria dos tipos, mesmo quando a conversão seria “segura” em outras linguagens.
A mensagem de erro geralmente aparece como:
error: expected type 'X', found 'Y'
note: cannot implicitly convert ...
Causas Comuns
1. Atribuir Tipo Inteiro Diferente
pub fn main() void {
var x: u16 = 100;
const y: u32 = 200;
x = y; // ERRO: expected type 'u16', found 'u32'
}
2. Atribuir Float para Inteiro ou Vice-Versa
pub fn main() void {
var x: i32 = 0;
const pi: f64 = 3.14;
x = pi; // ERRO: expected type 'i32', found 'f64'
}
3. Atribuir Optional para Tipo Base
pub fn main() void {
var nome: []const u8 = "padrão";
const talvez_nome: ?[]const u8 = "Zig";
nome = talvez_nome; // ERRO: expected '[]const u8', found '?[]const u8'
}
4. Atribuir Error Union para Tipo Base
fn ler() !u32 {
return 42;
}
pub fn main() void {
var valor: u32 = 0;
valor = ler(); // ERRO: expected 'u32', found '!u32' (error union)
}
5. Atribuir Ponteiro de Tipo Diferente
pub fn main() void {
var buffer: [10]u8 = undefined;
var ptr: [*]u32 = &buffer; // ERRO: tipos de ponteiro incompatíveis
_ = ptr;
}
6. Atribuir Resultado de Função com Tipo Diferente
fn obterTexto() []const u8 {
return "olá";
}
pub fn main() void {
var numero: u32 = 0;
numero = obterTexto(); // ERRO: expected 'u32', found '[]const u8'
_ = numero;
}
Como Corrigir
Solução 1: Converter Explicitamente Entre Inteiros
Use @intCast para conversões entre tipos inteiros:
pub fn main() void {
var x: u16 = 100;
const y: u32 = 200;
x = @intCast(y); // Conversão explícita — verificada em Debug
}
Solução 2: Converter Entre Float e Inteiro
pub fn main() void {
var x: i32 = 0;
const pi: f64 = 3.14;
x = @intFromFloat(pi); // Converte float para inteiro (trunca)
}
Para a conversão inversa:
pub fn main() void {
var y: f64 = 0.0;
const n: i32 = 42;
y = @floatFromInt(n); // Converte inteiro para float
}
Solução 3: Desempacotar Optional com orelse
pub fn main() void {
var nome: []const u8 = "padrão";
const talvez_nome: ?[]const u8 = "Zig";
nome = talvez_nome orelse "desconhecido"; // Desempacota optional
}
Solução 4: Tratar Error Union com try ou catch
fn ler() !u32 {
return 42;
}
pub fn main() !void {
var valor: u32 = 0;
valor = try ler(); // 'try' desempacota o error union
}
Ou com catch:
pub fn main() void {
var valor: u32 = 0;
valor = ler() catch 0; // Valor padrão se houver erro
}
Solução 5: Usar o Tipo Correto na Declaração
Às vezes a melhor solução é declarar a variável com o tipo certo:
pub fn main() void {
var x: u32 = 100; // Usar u32 ao invés de u16
const y: u32 = 200;
x = y; // OK: mesmos tipos
}
Solução 6: Usar @as Para Coerção Explícita
pub fn main() void {
var x: u64 = 0;
x = @as(u64, 42); // Explicitamente diz que 42 é u64
}
Entendendo as Regras de Coerção do Zig
Zig permite algumas coerções automáticas em situações específicas:
- Ponteiro para slice:
*[N]Tpode ser convertido para[]T - Enum para int: Se o enum tem representação inteira
- Widening de inteiros em comptime: Literais comptime podem ser atribuídos a qualquer tipo que os comporte
Mas não permite:
u32parau16(pode perder dados)i32parau32(pode ser negativo)f64parai32(perda de informação)?TparaT(pode ser null)!TparaT(pode ser erro)
Padrão: Verificar Tipo com @TypeOf
Quando não tem certeza do tipo de uma expressão:
pub fn main() void {
const x = alguma_funcao();
@compileLog(@TypeOf(x)); // Imprime o tipo durante compilação
}
Erros Relacionados
- expected type ‘X’, found ‘Y’ — Erro genérico de tipo incompatível
- type coercion failed — Falha específica na coerção
- integer truncation — Truncamento ao converter inteiros
- signed/unsigned mismatch — Misturar tipos com e sem sinal