1 pontos por GN⁺ 2026-03-12 | 1 comentários | Compartilhar no WhatsApp
  • A lógica de resolução de tipos (type resolution) do compilador Zig foi completamente redesenhada, simplificando a estrutura interna e trazendo melhorias visíveis também para os usuários
  • O novo design passa a tratar de forma preguiçosa (lazy) a análise dos campos de tipos, evitando inspecionar desnecessariamente a estrutura detalhada de tipos não inicializados
  • As mensagens de erro de loop de dependência (dependency loop) foram aprimoradas de forma mais específica, permitindo identificar com clareza a causa do loop
  • O problema de análise excessiva na compilação incremental (incremental compilation) e vários bugs foram corrigidos, aumentando significativamente a velocidade de build
  • Esta mudança inclui dezenas de correções de bugs e pequenos aprimoramentos na linguagem, fortalecendo de forma geral o desempenho e a experiência de desenvolvimento do compilador Zig

Redesenho da lógica de resolução de tipos

  • Um PR de cerca de 30 mil linhas foi mesclado, reescrevendo a lógica de resolução de tipos do compilador Zig com uma estrutura mais lógica e intuitiva
    • Nesse processo, a estrutura interna do compilador foi reorganizada, com efeitos de melhoria também perceptíveis diretamente pelos usuários
  • O compilador foi alterado para fazer avaliação preguiçosa da análise de campos de tipos, deixando de explorar desnecessariamente a estrutura detalhada de tipos não inicializados
    • No código de exemplo, quando uma struct que inclui um campo @compileError é usada apenas como namespace, antes ocorria erro de compilação, mas agora a compilação acontece normalmente
    • Isso evita dependências de código desnecessárias ao usar tipos em forma de namespace, como std.Io.Writer

Melhoria nas mensagens de erro de loop de dependência

  • Antes, as mensagens de erro de loop de dependência eram ambíguas, mas agora mostram com clareza a causa e a posição do loop
    • No código de exemplo, quando as structs Foo e Bar referenciam uma à outra, a mensagem de erro aponta de forma específica o local de dependência de cada tipo
    • A mensagem inclui o comprimento do loop, a posição de declaração de cada campo e a posição da consulta de alinhamento
  • Mesmo em loops complexos, ela fornece informação suficiente para identificar facilmente a causa do problema

Melhorias de desempenho na compilação incremental

  • Com esta mudança, vários bugs da compilação incremental foram corrigidos
    • Em especial, o problema de “análise excessiva (over-analysis)” foi resolvido, otimizando a recompilação para atingir apenas as partes alteradas
    • Como resultado, em muitos casos a velocidade de compilação aumenta bastante
  • Os desenvolvedores podem ativar a compilação incremental no Zig 0.15.1 ou superior para experimentar uma experiência de desenvolvimento melhorada

Outras melhorias

  • Este PR inclui dezenas de correções de bugs, pequenas mudanças na linguagem e melhorias de desempenho do compilador
    • A maioria diz respeito a casos detalhados ou específicos
  • O histórico completo das mudanças pode ser visto no Codeberg em PR #31403
  • Ao encontrar novos bugs, recomenda-se reportar uma issue

Significado da mudança

  • Com a simplificação da lógica de resolução de tipos e a otimização da compilação incremental, a estabilidade e a eficiência do compilador Zig foram reforçadas
  • Os desenvolvedores passam a receber feedback mais rápido e mais claro, e podem esperar ganhos de produtividade mesmo em codebases grandes

1 comentários

 
GN⁺ 2026-03-12
Comentários no Hacker News
  • Sou o autor deste devlog
    Entendo a preocupação com a quebra de compatibilidade causada por mudanças na linguagem, mas quero deixar claro que esta alteração no compilador não está num nível de impacto tão grande
    Por exemplo, ao compilar o ZLS com a nova branch, só foi preciso fazer mudanças como trocar .{} por .empty. Isso aconteceu por causa da remoção do valor padrão de std.ArrayList, que já estava em estado deprecated há 1 ano
    E no caso do projeto Awebo, também só houve três pontos a corrigir em toda a árvore de dependências — mudança para .empty, adição de comptime e adição de orelse @alignOf(T)
    A maioria dessas correções são mudanças simples que, para a maior parte dos desenvolvedores Zig, viram quase um reflexo automático
    O ponto principal deste PR não é a quebra, e sim a correção de bugs e a melhora da compilação incremental

    • Fui um dos autores dos comentários que pareciam críticos às mudanças
      Acho que a qualidade e o planejamento do PR são muito altos, e minha intenção nunca foi menosprezar o esforço do autor
      Só tirei disso a lição de que, no futuro, devo comentar mais e deixar opiniões com mais cuidado
    • Não trabalho diretamente com Zig, mas fiquei curioso ao ver o comentário adicionado em lib/std/multi_array_list.zig
      Não entendo por que usar @alignOf(T) na definição de MultiArrayList(T) causaria uma dependência circular
      Mesmo que T fosse o próprio MultiArrayList, isso não seria um tipo monomórfico completamente separado? Acho que estou deixando passar alguma coisa
      Código relacionado: link
  • Tenho curiosidade sobre a experiência de quem usa Zig em ambiente de produção
    Como a linguagem muda com frequência, queria saber como são os ciclos de atualização ou reescrita, e se acontece de pacotes dependentes ficarem para trás em relação à versão da linguagem
    Sei que o Bun aproveita bem Zig, mas gostaria de ouvir outros casos também

    • Mantenho uma base de código de compilador em Zig com cerca de 250 mil LoC (roc-lang/roc)
      Nos últimos 1~2 anos, as mudanças na linguagem e na biblioteca padrão avançaram sem grandes problemas
      Antes os upgrades eram incômodos, mas hoje parecem algo como um “pequeno transtorno
      Se alguém me perguntar sobre a experiência de usar Zig, essa parte é tão estável que eu quase nem mencionaria
    • Trabalhei em duas bases de código Zig de produção, tigerbeetle e sig
      Projetos grandes assim fazem upgrade com base em releases tagueadas, e normalmente concluem a migração em alguns dias ou poucas semanas
      Também quase não há dependências, então o peso do upgrade não é grande
    • O Zig 0.15 é bem estável
      Mas às vezes um pequeno erro de digitação causa um crash do compilador com SIGBUS, o que dificulta o debug
      O .zig-cache já chegou a 173GB, o que também pode causar problemas em VPS ARM
      Ao atualizar o lightpanda de 0.14 para 0.15, tudo correu bem. O 0.16 também não deve trazer grandes problemas
      Mas, como desenvolvedor de biblioteca, é difícil acompanhar o ritmo acelerado das mudanças no 0.16
      No momento estou lidando com isso só de forma experimental na branch “dev”
    • Estou rodando em produção cerca de 20 mil LoC de código Zig 0.16 em modo DebugSafe
      Reescrevi módulos de Node.js/TypeScript em Zig, e ficou 2x mais rápido com 70% menos uso de memória
      O suporte de Zig para serialização sqlite/JSON foi uma grande vantagem
      O ponto fraco é a falta de sintaxe para closures ou vtables, o que dificulta separar melhor as camadas do código
      Usei Arcs e alocadores bump para garantir segurança de memória, e pretendo continuar operando em modo DebugSafe
      Mudar para ReleaseFast trouxe um ganho de 25% em velocidade, mas não o bastante para compensar a perda de segurança
    • Acho que a promessa de compatibilidade retroativa eterna do C++ acabou sendo, na verdade, um erro que travou a evolução da linguagem
      Mesmo que seja preciso ajustar código, no longo prazo essa é a abordagem correta
  • Fiquei impressionado com o trabalho da equipe do Zig
    Uso com frequência o terminal ghostty feito em Zig, e ele é muito estável
    Mas, pessoalmente, prefiro Rust
    Rust adota um modelo de “mundo fechado”, enquanto Zig segue um modelo de “mundo aberto”
    Em Rust é preciso implementar traits explicitamente, mas em Zig basta o formato (shape) do tipo bater para funcionar
    Isso permite um metaprogramação poderosa em Zig, mas também tem a desvantagem de tornar inferência de tipos, autocompletar, documentação e suporte de LSP mais difíceis

    • Queria ver um exemplo concreto
      Pela explicação, isso parece parecido com interfaces de Go, mas até onde sei Zig não tem um conceito correspondente direto
  • A transição de kernel32 para Ntdll foi interessante
    É uma ideia que também pode ser aplicada à API de espaço de usuário no Linux
    Em especial, a forma de tratar erros na fronteira entre kernel e usuário é parecida
    Mas no Linux libc e kernel estão tão ligados que o uso de errno é indispensável
    Fico curioso sobre por que esse padrão também surgiu no Windows

    • O padrão de errno ou GetLastError() é um legado da era anterior às threads
      No passado havia escalonamento cooperativo, então variáveis globais eram seguras, mas isso ficou perigoso com o surgimento de multicore e threads
      Por isso o thread local apareceu como alternativa
  • Em vez de usar tipos como namespaces, será que não seria melhor adicionar namespaces explícitos à linguagem?

    • Zig busca o minimalismo da linguagem
      A abordagem é adicionar algo só quando for uma funcionalidade que traga otimização em vários pontos
    • Na verdade isso não é um contorno, e sim uma elegância de design
      Em Zig, @import transforma um arquivo em uma struct, e namespaces são representados simplesmente como structs aninhadas
      Ou seja, namespace não passa de outro import
      (Ainda não tomei café o bastante, então não garanto total precisão)
  • Há um ponto que muitas vezes passa despercebido em discussões sobre mudanças na linguagem — o impacto no ecossistema
    Se a linguagem quebra com frequência, não são só os apps que precisam acompanhar, mas também bibliotecas, ferramentas e tutoriais
    No fim, isso tende a puxar o ecossistema para projetos ativamente mantidos, em vez de bibliotecas feitas uma vez e depois abandonadas
    Isso pode ser um trade-off razoável na fase inicial de design da linguagem, mas no longo prazo afeta o crescimento do ecossistema
    Outras linguagens novas estão investindo bastante em minimizar esse cansaço de mudança
    Também é interessante observar que resultado a abordagem do Zig vai produzir

    • Um exemplo é o ecossistema de addons do Blender
      O Blender quebra a API com frequência, mas a maioria das correções é pequena
      Ainda assim, alguém precisa fazer essas correções, e quando a manutenção para, o usuário acaba tendo de aplicar patch por conta própria
      Addons pagos têm mais chance de continuar sendo mantidos, mas nem isso é garantia
    • Ainda assim, acho que Zig vale a pena
      Biblioteca sem manutenção já é código ruim de qualquer forma
      Em vez de criticar Zig, queria que parassem de promover outras linguagens (como C3)
  • A afirmação no PR do Zig de que “Chromium, boringssl, Firefox e Rust chamam SystemFunction036 de advapi32.dll” não é verdadeira
    Eles já usam ProcessPrng, e desde o Windows 10 isso não falha
    A base para isso está no whitepaper da Microsoft
    O sistema foi projetado para que pedidos de RNG nunca falhem, e se isso acontecer o próprio processo é encerrado
    Ou seja, ele não retorna código de erro justamente para garantir números aleatórios de alta qualidade

    • (Esta é uma resposta a outro devlog na mesma página)
  • A semântica da linguagem de Zig parece simples na superfície, mas as interações são sutis
    Isso me faz pensar que, com o tempo, podem surgir casos de borda complexos, como aconteceu com as regras de templates de C++

  • Um PR com 30 mil linhas é uma conquista impressionante
    Mas fiquei surpreso porque mudar a semântica da linguagem é algo muito sério
    Entendo que Zig ainda não chegou ao 1.0 e por isso as mudanças são rápidas, mas a forma casual de dizer “mudei a semântica nesta branch” me pareceu um pouco desconcertante
    Fico curioso se esse tipo de mudança grande faz parte da cultura do Zig, ou se sou eu que estou ficando para trás
    A expressão “modern Zig” também me fez rir, considerando a velocidade com que a linguagem muda

    • O tom casual não deve ser confundido com uma postura leviana
      O devlog não é texto de marketing, e sim algo mais próximo de um registro para iniciados, e Zig ainda não é 1.0
      O PR traz contexto e fundamentação suficientes
      Ao escolher Zig, você já aceita um certo nível de risco de mudança na linguagem
      Na verdade, limpar essas coisas agora tende a ser melhor no longo prazo
      (Basta pensar em heranças impossíveis de corrigir, como a precedência dos operadores de bits em C)
    • mlugg é contribuidor central do Zig e membro da Zig Foundation
      Esta mudança foi feita para eliminar dependências circulares e reorganizar o sistema de tipos
      As propostas relacionadas estão públicas em #3257 e #15909
      Com isso, a resolução de tipos do Zig passa a ser organizada como um DAG (grafo acíclico direcionado), melhorando muito a estabilidade do compilador
      Zig opera sob um modelo BDFN (Benevolent Dictator For Now), e a palavra final é de Andrew Kelley
      Mas a equipe é uma organização sem fins lucrativos e coloca a confiança dos usuários e a qualidade da linguagem acima de tudo
      Pessoalmente, é uma grande honra trabalhar com Matthew
    • Talvez essa postura também seja resultado de usar a história caótica da linguagem C como exemplo do que não repetir
      Ela era formalmente perfeita, mas na prática virou uma linguagem do caos