Reescrevendo o Bun em Rust
(bun.com)- O Bun, que começou em Zig, cresceu até se tornar um runtime com mais de 22 milhões de downloads por mês, mas os problemas recorrentes de estabilidade causados pela combinação de um engine JavaScript baseado em GC com gerenciamento manual de memória motivaram a migração para Rust
- Em vez de uma pessoa passar 1 ano migrando 535.496 linhas de código Zig, cerca de 50 fluxos de trabalho dinâmicos do Claude Code e até 64 instâncias do Claude foram executados em paralelo por 11 dias
- O port foi validado com
PORTING.md,LIFETIMES.tsv, 1 implementador e pelo menos 2 revisores adversariais, além da suíte de testes existente em TypeScript, e obteve 100% de aprovação em CI em 6 plataformas - Após a migração para Rust, o Bun v1.4.0 corrigiu 128 bugs reproduzíveis no v1.3.14, eliminou todos os vazamentos de memória instrumentáveis e reduziu em cerca de 20% o tamanho dos binários para Linux e Windows
- O Bun v1.3.14 é a última versão em Zig, e o v1.4.0 é a primeira versão em Rust, disponibilizada em canary; a equipe usa borrow checker, Miri, LeakSanitizer e fuzzing baseado em cobertura 24/7 como ferramentas para melhorar a estabilidade
O Bun, que começou em Zig, e os problemas de estabilidade
- O Bun começou como um projeto que fez o port linha por linha do transpiler de JavaScript e TypeScript do esbuild de Go para Zig
- O primeiro código em Zig foi escrito em 16 de abril de 2021, e o controle de baixo nível e o design voltado a desempenho do Zig possibilitaram a implementação inicial do Bun
- O Bun inicial foi escrito em Zig por uma única pessoa ao longo de 1 ano e tinha um escopo muito amplo
- transpiler, minifier e bundler de JavaScript, TypeScript e CSS
- gerenciador de pacotes compatível com npm
- test runner semelhante ao Jest
- resolução de módulos compatível com Node.js e TypeScript
- clientes HTTP/1.1 e WebSocket
- implementação de APIs do Node.js como
fs,netetls
- Atualmente, o CLI do Bun tem mais de 22 milhões de downloads por mês, Claude Code e OpenCode o utilizam como runtime, e Vercel, Railway e DigitalOcean oferecem suporte de primeira parte
Bugs recorrentes de estabilidade de memória
- Entre os exemplos de bugs corrigidos no Bun v1.3.14 estão use-after-free, double-free, vazamentos de memória, acessos out-of-bounds e race conditions
- heap-use-after-free causado pela chamada de
.reset()durante um.write()assíncrono denode:zlib - use-after-free em
node:http2, em que um callback JS reentrante provocava rehash de hashmap e invalidava ponteiros internos de stream - problema em
UDPSocket.send()esendMany()em que callbacksvalueOf()outoString()faziam detach deArrayBuffer - crashes e leituras out-of-bounds em
Buffer#copyeBuffer#fillcausados por detach ou resize deArrayBufferdurante a coerção de argumentos - vazamentos de memória relacionados a
crypto.scrypt,tlsSocket.setSession()efs.watch() - double-free durante o tratamento de vendor prefix e multi-layer background no parser de CSS
- crash por race condition de
MessageEventdurante acesso simultâneo aBroadcastChannelouMessagePort
- heap-use-after-free causado pela chamada de
- Já eram usados vários mecanismos para reforçar a estabilidade
- foi aplicado um patch no compilador Zig para suportar Address Sanitizer, e a suíte de testes com ASAN era executada em todos os commits
- no Windows, eram distribuídas builds Zig ReleaseSafe com verificação de segurança
- a API de runtime do Bun era submetida a fuzzing 24/7 com Fuzzilli
- vários testes end-to-end de vazamento de memória eram mantidos em operação
- A posição não é de que o próprio Zig seja o problema, mas sim de que a exigência de lidar ao mesmo tempo com valores de GC e memória gerenciada manualmente era a principal fonte dos problemas de estabilidade
Por que escolher Rust
- JavaScript é uma linguagem com GC, e engines como JavaScriptCore e V8 têm regras rígidas para tratamento de exceções e GC
- Assim como C, Zig não faz gerenciamento automático de memória; não há construtores nem destrutores, e a limpeza normalmente precisa ser explicitada em cada call site com
defer - No Bun, lidar corretamente com o lifetime de valores de GC e valores gerenciados manualmente era uma grande fonte de problemas de estabilidade
- era preciso verificar onde os bytes alocados seriam liberados
- era preciso garantir que fossem liberados apenas uma vez
- era preciso verificar corretamente o tratamento de exceções JavaScript
- era preciso garantir que ponteiros de GC fossem visíveis ao conservative stack scanner
- O método de cleanup do Zig usa
defereerrdeferexplícitos; C++ usa destructor e move, e Rust usaDrop - No código Zig existente do Bun, havia uma mistura de lifetime de arena, reference counting e revisão cuidadosa
- É possível impor regras de ownership com guia de estilo e code review, mas em código seguro de Rust, use-after-free, double-free e
freeausente em caminhos de erro se tornam erros de compilação - Cerca de 20% do código do Bun é C++, e ele incorpora várias bibliotecas C/C++
- JavaScriptCore
- uWebSockets e usockets
- lshpack e lsquic
- BoringSSL
- SQLite
- C++ também poderia ter sido uma opção, mas ainda dependeria de guia de estilo e code review, e mesmo com ASAN ainda podem ocorrer corrupção de memória e vazamentos
Estratégia de reescrita: de uma vez, de forma mecânica
- O código Zig existente do Bun tinha 535.496 linhas, excluindo comentários, e uma reescrita tradicional foi estimada como um trabalho de cerca de 1 ano para uma pequena equipe de engenharia
- Como não era possível interromper por 1 ano as correções de bugs, correções de segurança e o desenvolvimento de funcionalidades, foi escolhido o port mecânico como a abordagem de menor risco para minimizar mudanças no comportamento observado pelos usuários
- A suíte de testes do Bun foi escrita em TypeScript e não dependia da linguagem de implementação do runtime
- Considerou-se que uma reescrita incremental seria dolorosa no curto e médio prazo por exigir código temporário que depois precisaria ser removido, então toda a base foi migrada de uma vez
- A direção adotada foi escrever o código Rust de forma que parecesse um transpile do código Zig e, após o Bun v1.4, reduzir gradualmente o
unsafee refatorar para um Rust mais idiomático
Fluxos de trabalho dinâmicos do Claude Code
- Na reescrita para Rust, cerca de 50 fluxos de trabalho dinâmicos foram executados continuamente no Claude Code durante 11 dias
- Os fluxos iam desde a criação do guia de port até a conversão de arquivos, correção de erros de compilação, restauração de subcommands, aprovação em toda a suíte de testes e grandes limpezas
- geração de um guia de port que mapeava padrões e tipos de Zig para padrões e tipos de Rust
- port mecânico de todos os arquivos
.zigpara arquivos.rsde acordo comPORTING.mdeLIFETIMES.tsv - correção de erros do compilador por crate
- restauração do funcionamento de subcommands como
bun testebun build - aprovação em toda a suíte de testes
- grandes refatorações e limpezas
- Durante a maior parte do período, uma pessoa lia a saída dos fluxos de trabalho, verificava problemas e bugs e ajustava os prompts para que o Claude corrigisse o loop
- Como preparação, passou-se cerca de 3 horas discutindo com o Claude como mapear os padrões da base de código Zig para Rust, e o resultado foi serializado em
PORTING.md - Para adicionar lifetimes de Rust ao código com gerenciamento manual de memória, foi executado um fluxo de trabalho que analisava o lifetime de todos os campos de struct
- encontrava campos com lifetimes complexos
- sugeria lifetimes
- 2 agentes de revisão adversarial analisavam o resultado
- o feedback era incorporado e salvo em
LIFETIMES.tsv
Método de revisão adversarial
- Cada implementação tinha um Claude revisor adversarial em uma janela de contexto separada do Claude implementador, e o revisor recebia apenas o diff e era instruído a procurar bugs assumindo que o código estava errado
- A estrutura básica era composta por 1 implementador, pelo menos 2 revisores adversariais e 1 fixer
- Todos os bugs que os revisores realmente encontraram compilavam sem problemas, mas tinham falhas de comportamento
uv_closeé assíncrono, masBox<uv::Pipe>era descartado no fim do match arm, fazendo com que o libuv ficasse com memória já liberada, causando use-after-free e double-free- Erro de
timespecem que usartrunc()em file time negativo não inteiro geravansecnegativo - Erro em que
unwrap_oravaliava o argumento eagermente e causava panic no caso de omissão de porcentagem emcolor-mix()
- Assim como na revisão humana, os contextos de autor e revisor foram separados para reduzir o viés que pode surgir quando o implementador quer fazer o merge
Execução do grande porte e paralelização
- Antes de migrar todos os 1.448 arquivos
.zig, o procedimento foi validado primeiro com 3 arquivos- 1 implementador escrevia o arquivo
.rs - 2 revisores verificavam se o comportamento batia com o
.zige se seguiaPORTING.mdeLIFETIMES.tsv - 1 fixer aplicava as sugestões
- 1 implementador escrevia o arquivo
- No início da migração completa dos arquivos, vários Claudes executavam
git stash,git stash popegit reset HEAD --hard, entrando em conflito entre si - Depois, foram adicionadas ao workflow regras proibindo
git stash,git reset, comandosgitque não fossem commits de arquivos específicos e comandos lentos comocargo - No fim, foram usados 4 shards de workflow e 4 worktrees, e em cada shard 16 Claudes faziam commit e push dos arquivos
- Graças à paralelização e à preparação prévia, no pico o Claude escreveu cerca de 1.300 linhas de código por minuto
- Os commits no branch do port, excluindo merges, foram 6.502, a hora de pico teve 695 commits, e o diff final landed foi de +1.009.272 linhas
- Também houve problema por não aumentar o IOPS padrão da instância EC2: um único
greplento podia travar as leituras e gravações em disco por vários minutos
Erros de compilação e separação em crates
- Depois que todo o código foi escrito, o workflow do Claude corrigiu os erros do compilador
- A base de código em Zig era, na prática, uma única compilation unit, e o código Rust seria dividido em cerca de 100 crates para compilar mais rápido
- A categoria de erro mais complicada era a de dependências circulares
- Só o PR de separação em crates feito logo antes da reescrita em Rust não foi suficiente
- Um workflow separado classificou e registrou onde o código com dependência circular deveria ficar
- Outro workflow executou esse refactoring
- Depois de resolver as dependências circulares, apareceram cerca de 16.000 erros de compilador
- Esses erros foram tratados em paralelo por crate
- Em cada crate, era executado
cargo check - A saída era agrupada e salva por arquivo
- Os erros de compilação daquela crate eram corrigidos
- 2 revisores adversariais analisavam as mudanças
- 1 fixer aplicava as correções
- Em cada crate, era executado
- Também houve um false start em que o Claude interpretou “fazer todos os crates compilarem” como gerar stubs de função
- Quando surgiu um padrão de tentar justificar workarounds com comentários explicativos longos, foi adicionada uma regra de revisão: “se precisa de um comentário do tamanho de um parágrafo, o código está errado e o código precisa ser corrigido”
O caminho até passar nos testes
- Depois que
cargo checkpassou, foram resolvidos em sequência erros de linkedição, panic logo na inicialização,bun --versione a execução debun test <file> - Foi usado um workflow que salvava em arquivo stacktraces de falhas por subcomando da CLI e corrigia em um loop de implementador, revisor e fixer
- O workflow dos arquivos de teste distribuía cerca de 100 arquivos de teste aleatórios em 4 worktrees, salvava stacktraces e erros por falha e fazia as correções
- A suíte de testes incluía testes de vazamento de memória e testes de integração que podiam dar timeout em builds de debug
- Teste que executava
next deve verificava se o hot module reloading detectava 100 mudanças - Stress test que esgotava o número máximo de sockets TCP
- Testes de leitura e gravação em disco na casa dos gigabytes
- Teste que fazia spawn de cerca de 10 mil processos
- Teste que executava
- Para isolamento,
systemd-rune cgroups foram usados para limitar uso de memória e CPU e separar o namespace de PID - Ainda assim, a máquina travou várias vezes por falta de espaço em disco
- Dois dias após a primeira execução do CI, os arquivos de teste com falha caíram de 972 para 23, e um dia e meio depois disso o Linux ficou completamente green
- No fim, toda a suíte de testes do CI passou em 6 plataformas
- macOS x64
- macOS arm64
- Linux x64
- Linux arm64
- Windows x64
- Windows arm64
- Depois de 100% dos testes passarem, humanos verificaram manualmente se os testes estavam realmente sendo executados e não pulados, e então fizeram o merge
- O momento em que foi feito o merge em
mainnão foi um release versionado; ainda não havia confiança suficiente para lançar, mas já havia confiança suficiente para se dedicar totalmente à reescrita
Escala dos testes e custo
- Ao longo de 11 dias, do dia 3 de maio até o merge em 14 de maio, foram gerados 6.778 commits
- Os testes não foram deletados nem pulados
- A escala dos testes por plataforma foi a seguinte
- Debian 13 x64:
expect()1.386.826 vezes, 60.624 testes, 4.174 arquivos - macOS 14 arm64:
expect()1.259.953 vezes, 58.850 testes, 4.175 arquivos - Windows 2019 x64:
expect()1.007.544 vezes, 57.337 testes, 4.173 arquivos
- Debian 13 x64:
- No trabalho pré-merge foram usados 5,9 bilhões de input tokens sem cache, 690 milhões de output tokens e 72 bilhões de cached input tokens read
- O custo com base no preço de API foi de cerca de US$ 165 mil
- A avaliação foi de que, se humanos tivessem feito isso diretamente, 3 engenheiros com contexto de toda a base de código levariam cerca de 1 ano
- O modelo usado foi o pre-release Claude Fable 5, e foi incluída a divulgação de que a Bun foi adquirida pela Anthropic em dezembro de 2025
Revisão de segurança, fuzzing e situação do unsafe
- Depois do merge do port em Rust, foram concluídas 11 rodadas de revisão de segurança com Claude Code Security e os findings foram tratados
- Foi adicionado fuzzing contínuo 24/7 com coverage para todos os parsers do Bun
- JavaScript
- TypeScript
- JSX
- CSS
- JSON5
- JSONC
- TOML
- YAML
- Markdown
- INI
- scripts do Bun Shell
- intervalos de semver
- arquivos
.patch - cores CSS
- O fuzzer envia os bugs encontrados ao Claude para que ele abra PRs com reprodução e correção, e humanos revisam os PRs
- Até agora, os parsers foram executados 100 bilhões de vezes, resultando em cerca de 15 PRs
- No momento da redação, cerca de 4% do código Rust estava dentro de blocos
unsafe- Cerca de 13.000 ocorrências da keyword
unsafe - Cerca de 27.000 linhas / cerca de 780.000 linhas no total
- 78% dos blocos
unsafetêm uma única linha e envolvem ponteiros vindos de C++ ou chamadas de bibliotecas C
- Cerca de 13.000 ocorrências da keyword
- Eles afirmam que, como continuam usando bibliotecas C/C++ como o JavaScriptCore, sempre haverá mais
unsafedo que em um projeto puramente Rust
Regressões encontradas após a migração para Rust
- A reescrita em Rust foi uma mudança de grande porte e criou 19 regressões conhecidas, todas corrigidas
- A maioria surgiu em código cuja sintaxe é parecida nas duas linguagens, mas cujo significado é diferente
-
Efeito colateral dentro de
debug_assert!- O
assertdo Zig é uma função, então os argumentos são executados em todas as builds - O
debug_assert!do Rust é uma macro, então em builds release a expressão inteira é removida - A chamada de
insert_staledesapareceu na build release e quebrou um caso específico de HMR em projetos de rota HTML que usam React - Issue relacionada: #30678
- O
-
Slice de tamanho ímpar
- O helper
reinterpretSlice(u16, bytes)do Bun em Zig usava@divTruncpara ignorar o byte ímpar no fim bytemuck::cast_slicedo Rust dá panic com comprimento ímpar- Houve uma regressão em que
Blob.text()com um byte ímpar após o BOM UTF-16 não retornava uma string e fazia o processo entrar em panic - A correção foi voltar a ignorar o byte ímpar com
&buf[..buf.len() & !1] - Issue relacionada: #31188
- O helper
-
Verificações de limites
- O código Zig no macOS e Linux era compilado com
ReleaseFast, removendo as verificações de limites, enquanto a build release em Rust as mantém - O tamanho do bloco de overflow do resolvedor de módulos do Bun ficou com o placeholder
64, reduzindo o teto de 8,4 milhões de nomes de arquivos internados para 270.272 - O erro de off-by-one portado em
ptrs[4095]passou a ser alcançável em projetos reais, e o Rust gerou panic em vez de fazer uma escrita fora dos limites - Issue relacionada: #31503
- O código Zig no macOS e Linux era compilado com
-
Strings de formatação
comptime- Em Zig,
fmtemOutput.prettyécomptime, então os marcadores de cor<r>e<d>são convertidos em escapes ANSI antes da substituição dos argumentos - A função em Rust não tem parâmetro comptime e processou os marcadores na string finalizada, reescrevendo incorretamente até os argumentos
- Em
bun update -i, a terminação de hyperlink OSC 8 e o marcador<r>no fim entravam em conflito, fazendorser exibido como texto - Em Rust, foi necessário usar a macro
bun_core::pretty!("<r>{}<r>", hyperlink) - Issue relacionada: #30693
- Em Zig,
Bugs corrigidos e vazamentos de memória
- O Bun v1.4.0 corrige 128 bugs reproduzíveis na v1.3.14
- O escopo vai de vazamentos de memória e crashes até texto de ajuda colorido incorretamente
- Em Rust,
Dropchama automaticamente a funçãodropquando um valor sai do escopo - Em Zig, era preciso adicionar
deferem cada call site, o que facilitava esquecer uma limpeza ou fazer limpeza duplicada Dropé uma escolha que reduz armadilhas comuns em troca de aceitar um fluxo de controle ocultoDropcorrigiu vários vazamentos de memória relacionados a caminhos de arquivo no código de tratamento de erros- A integração do Bun com o LeakSanitizer foi melhorada para rastrear todas as alocações de memória em código nativo
- Todos os vazamentos de memória instrumentáveis foram corrigidos
-
Melhorias no vazamento de
Bun.build()- No Bun v1.3.14, a cada chamada in-process de
Bun.build(), o texto-fonte analisado e a tabela de símbolos da AST sobreviviam além da vida útil da build, vazando vários MB por vez - Em um teste que empacotou o mesmo projeto de 60 módulos 2.000 vezes no mesmo processo, a v1.3.14 continuou vazando cerca de 3 MB por build
- No Bun v1.4.0, o uso de memória se estabilizou
- | Builds | Bun v1.3.14 | Bun v1.4.0 |
- | --- | ---: | ---: |
- | 500 | 1,914 MB | 526 MB |
- | 1,000 | 3,506 MB | 586 MB |
- | 1,500 | 5,097 MB | 608 MB |
- | 2,000 | 6,745 MB | 609 MB |
- No Bun v1.3.14, a cada chamada in-process de
Tamanho do binário, uso de stack e desempenho
- Só as mudanças iniciais da reescrita em Rust já reduziram o tamanho do binário
- Windows: redução de 3.8 MB
- macOS: redução de 5.5 MB
- Linux: redução de 6.8 MB
- O principal motivo foi o uso excessivo de
comptimeno código Zig - Depois, também foram aplicados o Identical Code Folding, a remoção de dados não usados do ICU e a descompressão tardia de parte da libicu com dicionário zstd
- Somando a reescrita em Rust, as mudanças no ICU e o identical code folding, o tamanho do binário do Bun caiu cerca de 20% em Linux e Windows
| Version | Platform | Size |
|---|---|---|
| Bun v1.4.0 canary | Windows | 76 MB |
| Bun v1.3.14 | Windows | 94 MB |
| Bun v1.4.0 canary | Linux | 70 MB |
| Bun v1.3.14 | Linux | 88 MB |
- O parser TOML e os parsers recursive-descent do Bun passaram a usar menos espaço de stack
- A geração de código LLVM IR do Rust emite os intrinsics
llvm.lifetime.startellvm.lifetime.endpara variáveis de stack, permitindo que o LLVM reutilize slots da stack - Antes, funções especialmente grandes eram refatoradas manualmente em várias funções menores para contornar uma issue aberta do Zig
- O Rust oferece suporte a cross-language link-time optimization entre C/C++ e Rust, permitindo inlining entre linguagens
-
Benchmark Linux x64
- Bun v1.3.14 e Bun v1.4.0 foram comparados em Linux x64 com EC2 Xeon Platinum 8488C
- O throughput HTTP foi medido com oha, e a carga de trabalho de apps com hyperfine
- | server | Bun v1.3.14 | Bun v1.4.0 | Δ |
- | --- | ---: | ---: | ---: |
- | Bun.serve | 169.6k req/s | 177.7k req/s | +4.8% |
- | node:http | 103.8k req/s | 108.5k req/s | +4.5% |
- | Elysia | 158.9k req/s | 163.3k req/s | +2.8% |
- | express | 64.5k req/s | 66.6k req/s | +3.2% |
- | fastify | 91.5k req/s | 95.9k req/s | +4.8% |
- | workload | Bun v1.3.14 | Bun v1.4.0 | Δ |
- | --- | ---: | ---: | ---: |
- | next build | 13.62 s | 13.03 s | +4.5% |
- | vite build | 1.69 s | 1.65 s | +2.2% |
- |
tsc -b --force| 0.94 s | 0.89 s | +4.7% |
Casos de uso reais e status de lançamento
- A Prisma lançou a beta pública do Prisma Compute sobre o rewrite em Rust do Bun
- Segundo a Prisma, eles testaram no rewrite em Rust o failure mode de pool de conexões que não se recupera após pause/resume da VM e de vazamento de memória, e afirmaram que esse failure mode foi bem tratado
- O Claude Code v2.1.181 e as versões lançadas após 17 de junho usam o Bun portado para Rust
- A inicialização do Claude Code no Linux ficou 10% mais rápida, e fora isso a maioria dos usuários quase não percebeu diferença
- O Bun v1.3.14 é a última versão do Bun escrita em Zig
- O Bun v1.4.0 é a primeira versão do Bun escrita em Rust e é fornecida como canary
Ferramentas que a equipe ganhou e trabalho restante
- A nova base de código em Rust mantém uma forma muito semelhante à base de código anterior em Zig
- Foi escrita de modo que quem entende o código original em Zig também consiga entender o código em Rust traduzido mecanicamente
- A revisão do PR de rewrite em Rust foi conduzida com um agente de revisão hostil verificando se ele conseguia detectar corretamente divergências entre Zig e Rust, o guia de portabilidade e o cumprimento do guide de lifetimes, enquanto pessoas liam muito código lado a lado
- O Bun v1.4 torna o Bun mais rápido e menor, reduz o uso de memória e fornece ferramentas para melhorar a estabilidade
- Rust borrow checker
- Miri
- LeakSanitizer
- fuzzing guiado por cobertura 24/7 para o parser
- Ainda restam partes a serem refatoradas, e o bun-unsafe-audit está vinculado
- Um engenheiro monitorou de perto o Fable e o Claude Code, e em apenas 11 dias chegou ao ponto em que toda a suíte de testes passava em todas as plataformas
1 comentários
Comentários no Lobste.rs
extern "C", mas ainda dependeriam de guias de estilo impostos por code review, e mesmo com ASAN ainda haveria corrupção de memória e vazamentosCuriosamente, o Node.js funciona bem em C++, mas nunca vi o Bun como um projeto sério. Agora ele parece mais um benchmark do departamento de marketing da Anthropic, então pretendo continuar mantendo distância
Spoiler: na prática, não tomam tanto cuidado assim e cometem erros
unsafe, e 78% deles têm uma linha só” parece uma formulação para tranquilizar, mas não importa se um blocounsafetem uma linha ou não. Se ele quebrar as garantias de segurança ali dentro, então todo o código fora do bloco também pode ter a soundness comprometidaA fusão inicial do port em Rust do Bun incluía um caso claro desse tipo de unsoundness: https://github.com/oven-sh/bun/issues/30719
Esse issue foi tratado quando os mantenedores ativaram a ferramenta Miri do Rust no CI, e em “What's Next” no artigo também aparece Miri (which runs for a growing chunk of code in CI), então parece bom que estejam trabalhando nisso
Para ser justo, mesmo Rust com violações de segurança ainda pode ser mais fácil de manter do que o código Zig que substituiu, dependendo da qualidade desse código. Ainda assim, linhas de código por bloco unsafe não são um indicador de qualidade, e menos ainda se esses blocos não vieram acompanhados de outras práticas de programação, especialização ou verificações automáticas
unsafenão surgem por causa da portabilidade, e sim por requisitos do projeto. Se você chama bibliotecas C, precisa de blocosunsafe, e não há como removê-los só com refatoraçãoClaro, isso seria possível se reescrevessem também essas bibliotecas C, mas isso talvez pudesse ser avaliado depois
No anúncio “Bun is joining Anthropic”, Jarred disse que contrataria mais engenheiros para trabalhar no Bun, mas olhando o GitHub o time do Bun parece até ter diminuído. Não sei bem que conclusão tirar disso, além de que “o Bun é um time pequeno”
O método em si é interessante, mas o texto soa como matéria de marketing. Faltou análise de quanto isso custou, não há discussão dos riscos de uma reescrita em Rust, e também é fraca a explicação concreta de por que a reescrita aconteceu. Meu palpite é que foi por causa da no ai policy do Zig, ou por alguma diretriz interna da Anthropic de focar em Rust
E sobre o motivo da reescrita, acho que o texto conta uma história bem consistente. O Bun continuava tendo crashes mesmo depois de adotarem medidas para encontrar os problemas, e os desenvolvedores queriam uma forma mais sistemática de evitar esse tipo de falha
O plano inicial era reforçar com mais rigor um certo estilo de código e introduzir smart pointers, mas Jared achou que smart pointers próprios seriam piores de usar do que Rust e não ofereceriam garantias. Então virou algo como “e se testássemos por uma semana se o novo modelo da Anthropic consegue reescrever o Bun em Rust?”, e quando a taxa de aprovação da suíte de testes subiu, o fluxo parece ter mudado de “vale tentar” para “vamos fazer o merge”
Ou seja, não parece que decidiram desde o início por uma reescrita em Rust, mas sim algo mais próximo de “Rust parece resolver o problema, mas o custo de reescrever impede. Só que, testando um port via LLM, parece viável. Então vamos de reescrita com LLM”
Parabéns ao Jarred, ao time do Bun e à Anthropic por terem conseguido fazer isso