Slice Type Mismatch — Como Resolver em Zig
O Que Este Erro Significa
O erro de incompatibilidade de tipo de slice ocorre quando o código tenta usar um slice de um tipo onde outro tipo de slice é esperado. Slices em Zig carregam informações sobre mutabilidade (const ou não), tipo do elemento, sentinel (terminador) e alinhamento. Uma incompatibilidade em qualquer dessas propriedades causa erro de compilação.
Mensagens típicas:
error: expected type '[]const u8', found '[]u8'
error: expected type '[]u8', found '*[5]u8'
error: expected type '[:0]const u8', found '[]const u8'
Causas Comuns
1. Passar Slice Mutável onde const É Esperado
fn imprimir(dados: []u8) void { // Espera []u8 mutável
_ = dados;
}
pub fn main() void {
const texto: []const u8 = "olá";
imprimir(texto); // ERRO: []const u8 não coerce para []u8
}
2. Confundir Array com Slice
fn processar(dados: []const u8) void {
_ = dados;
}
pub fn main() void {
const arr = [_]u8{ 1, 2, 3 };
processar(arr); // ERRO: [3]u8 não é []const u8
// Precisa de &arr
}
3. Sentinel Mismatch
fn funcaoC(texto: [:0]const u8) void { // Espera string terminada em 0
_ = texto;
}
pub fn main() void {
const slice: []const u8 = "olá";
funcaoC(slice); // ERRO: []const u8 não tem sentinel, esperado [:0]const u8
}
4. Tipo de Elemento Diferente
fn processar(dados: []const u32) void {
_ = dados;
}
pub fn main() void {
const bytes = [_]u8{ 1, 2, 3, 4 };
processar(&bytes); // ERRO: []const u8, esperado []const u32
}
5. Retorno de Tipo Errado
fn obterDados() []const u8 {
var buffer: [100]u8 = undefined;
return buffer; // ERRO: [100]u8 não é []const u8
}
Como Corrigir
Solucao 1: Usar Referência de Array para Obter Slice
fn processar(dados: []const u8) void {
_ = dados;
}
pub fn main() void {
const arr = [_]u8{ 1, 2, 3 };
processar(&arr); // &[3]u8 coerce para []const u8
}
Solucao 2: Aceitar const Quando Não Precisa Mutar
// ERRADO: exige mutabilidade desnecessariamente
fn contar(dados: []u8) usize {
return dados.len;
}
// CORRETO: aceita const já que não modifica
fn contarCorreto(dados: []const u8) usize {
return dados.len;
}
pub fn main() void {
const texto = "olá mundo";
// contar(texto); // ERRO
_ = contarCorreto(texto); // OK
}
Solucao 3: Converter Sentinel Slice
fn funcaoC(texto: [:0]const u8) void {
_ = texto;
}
pub fn main() void {
// String literals em Zig já são [:0]const u8
const texto: [:0]const u8 = "olá";
funcaoC(texto); // OK
// Para converter []const u8 para [:0]const u8, precisa garantir o sentinel
const slice: []const u8 = texto; // Perde o sentinel
// funcaoC(slice); // ERRO
_ = slice;
// Pode usar o literal diretamente
funcaoC("olá"); // OK — literais são [:0]const u8
}
Solucao 4: Usar @constCast (Com Cuidado)
fn funcaoLegada(dados: [*]u8) void { // API que exige ponteiro mutável
_ = dados;
}
pub fn main() void {
var buffer = [_]u8{ 1, 2, 3 };
const slice: []const u8 = &buffer;
// @constCast remove const — use APENAS quando seguro
funcaoLegada(@constCast(slice.ptr));
}
Solucao 5: Converter entre Tipos de Slice com std.mem
const std = @import("std");
pub fn main() void {
var buffer align(4) = [_]u8{ 0, 0, 0, 1, 0, 0, 0, 2 };
// Converter []u8 para []u32 (requer alinhamento correto)
const u32_slice = std.mem.bytesAsSlice(u32, &buffer);
std.debug.print("primeiro: {}\n", .{u32_slice[0]});
// Converter []u32 de volta para []u8
const byte_slice = std.mem.sliceAsBytes(u32_slice);
std.debug.print("bytes: {}\n", .{byte_slice.len});
}
Solucao 6: Usar Slicing para Obter Tipo Correto
pub fn main() void {
var arr = [_]u8{ 1, 2, 3, 4, 5 };
// *[5]u8 -> []u8 via slicing
const slice: []u8 = arr[0..];
// []u8 -> []const u8 (coerção automática — widening de const)
const const_slice: []const u8 = slice;
_ = const_slice;
}
Regras de Coerção de Slice
Coerções Permitidas (Automáticas)
pub fn main() void {
var arr = [_]u8{ 1, 2, 3 };
// *[N]T -> []T (array pointer para slice)
const s1: []u8 = &arr;
// []T -> []const T (adicionar const)
const s2: []const u8 = s1;
// *[N:s]T -> [:s]T (sentinel array pointer para sentinel slice)
const literal: [:0]const u8 = "abc";
// [:s]T -> []T (sentinel slice para slice — perde sentinel)
const s3: []const u8 = literal;
_ = s2;
_ = s3;
}
Coerções Proibidas
// []const T -> []T NÃO (remover const)
// []T -> *[N]T NÃO (slice para array pointer)
// []const u8 -> [:0]const u8 NÃO (adicionar sentinel)
// []u8 -> []u32 NÃO (mudar tipo de elemento)
String Literals
Um ponto de confusão frequente: string literals em Zig são *const [N:0]u8, que coerce para [:0]const u8 e para []const u8:
pub fn main() void {
const a: *const [3:0]u8 = "abc"; // Tipo exato
const b: [:0]const u8 = "abc"; // Coerção para sentinel slice
const c: []const u8 = "abc"; // Coerção para slice (perde sentinel)
_ = a;
_ = b;
_ = c;
}
Erros Relacionados
- Sentinel mismatch — Incompatibilidade de sentinel
- Type coercion failed — Falha na coerção de tipos
- Pointer cast alignment — Alinhamento de ponteiro
- Type mismatch assignment — Tipo incompatível