#9512 - Rewrite It in Rust
- O shell Fish foi reescrito em Rust. Não há nenhum código C++ e ele é composto quase 100% de Rust puro
- Há cerca de 2 anos, foi aberto o PR (#9512) para migrar o Fish de C++ para Rust
- O Fish já havia passado por uma transição de C para C++ no passado, mas a mudança para Rust foi um projeto muito maior
Problemas no C++
- Diferenças de ferramentas e compiladores: as ferramentas de C++ não são boas, e adotar padrões modernos de C++ traz complexidade para mantenedores de pacotes e contribuidores.
- Segurança de threads: a execução interna de comandos do Fish atualmente ocorre de forma serial, e adicionar prompt assíncrono ou conclusão não bloqueante exige processamento paralelo.
- Complexidade da linguagem: arquivos de cabeçalho, templates e tratamento de strings em C++ são complexos e inseguros.
- Comunidade: C++ não atrai muitos contribuidores.
- Problemas de dependência: havia incômodo com a instabilidade e os problemas de build de certas bibliotecas C (
curses).
Por que escolher Rust
- Diversão e interesse: o Fish é um projeto de hobby, então precisava de uma linguagem divertida e interessante. Rust é mais atraente para contribuidores.
- Ótimas ferramentas: é possível instalar o compilador facilmente com
rustup, e as mensagens de erro são claras.
- Ergonomia: oferece um sistema explícito de
use e recursos seguros como Option e Result.
- Bom design de linguagem: o sistema de ponteiros e opções do Rust é muito mais seguro que o do C++.
- Suporte a paralelismo:
Send e Sync do Rust permitem processamento paralelo com segurança.
- Gerenciamento de dependências: é fácil adicionar suporte a formatos externos como YAML e JSON.
Suporte a plataformas
- A maioria das principais plataformas (macOS, Linux, BSD etc.) é suportada, e suporte nativo ao Windows não é um objetivo
- O Fish é um shell centrado em UNIX, focado em APIs UNIX e linguagens de script, mais do que no ambiente Windows
Processo de port
- O Fish fez a transição gradual de C++ para Rust no estilo "o peixe de Theseus". Os componentes foram migrados um a um para Rust, configurando a coexistência entre C++ e Rust
- Navio de Teseu (Ship of Theseus): “Se todas as tábuas de madeira de um navio forem substituídas por novas, ele ainda será o mesmo navio?”
- Uso de FFI: foi usado
autocxx para gerar bindings entre C++ e Rust, portando um componente por vez.
- Port de grande escala: certas partes (como processamento de I/O) foram migradas de uma vez para reduzir código FFI complexo.
- Melhoria de ferramentas: durante o port, o
autocxx foi customizado para resolver problemas de interoperabilidade entre Rust e C++.
Linha do tempo
- Janeiro de 2023: PR inicial aberto
- Janeiro de 2024: código C++ completamente removido
- Dezembro de 2024: lançamento da versão beta do Fish 4.0
Atritos com Rust
- Problemas de portabilidade: a abordagem
#[cfg(...)] do Rust é ineficiente para lidar com diferenças de sistema em baixo nível.
- Localização: strings de formatação em Rust são verificadas em tempo de compilação, mas não podem ser traduzidas.
- Tempo de build: usar LTO e o build de release padrão pode aumentar o tempo de compilação.
- Alguns erros foram cometidos durante o port, mas a maioria foi resolvida com facilidade.
Principais resultados
- Remoção de
curses: o banco de dados terminfo foi substituído por um crate Rust, resolvendo estado global e problemas de build
- Executável único: agora é possível gerar um binário do Fish com todas as dependências incluídas
- Isso torna o pacote do Fish auto-instalável, facilitando o uso pelos usuários
- Melhoria de desempenho: otimização do uso de memória e maior facilidade para adicionar novos recursos
Limitações
- Não foi possível remover completamente o CMake
- Suporte ao Cygwin foi descontinuado: não há target Rust para ele
- No Windows, ainda só é possível executar via WSL
Presente e futuro
- O Fish 4.0 foi portado com sucesso e teve melhorias de desempenho.
- O Fish continua sendo um shell UNIX, e a transição para Rust abriu espaço para adicionar novos recursos.
- Agora ele tem uma base de código totalmente migrada para Rust, mais fácil de manter e expandir do que antes. Será possível adicionar novos recursos aproveitando as vantagens do Rust
- Essa transição foi concluída com sucesso e teve impacto positivo tanto para contribuidores quanto para usuários
3 comentários
Invejo a usabilidade do fish, mas por causa de problemas como compatibilidade e desempenho, venho configurando o zsh para ficar o mais parecido possível com o fish. Estou curioso para ver como ficou o fish depois das mudanças 👀
Shell interativo amigável - Fish
Comentários no Hacker News
Parabéns à equipe do Fish, e os detalhes do projeto são interessantes. Fico curioso se este é o maior projeto a fazer uma migração completa de C++ para Rust. Pode trazer lições úteis para outros projetos
A principal reclamação sobre Rust é o suporte à detecção por versão. A detecção por funcionalidade é melhor para distribuições, navegadores web e compiladores
Um dos objetivos da migração era remover o CMake, mas isso falhou. O Cargo é excelente para build, mas é simples demais para instalação. O Fish tem muitos scripts e documentação, então não se encaixa bem no caso de uso do Cargo
Alguns anos atrás, quando migrei de bash para zsh, fiquei satisfeito, mas ao experimentar o fish em um computador novo, o zsh passou a parecer incômodo e ultrapassado. Recomendo usar o fish por algumas semanas
É uma pena que não haja suporte ao Cygwin. Espero que Rust passe a oferecer suporte ao Cygwin como alvo de build
Impressiona o esforço da equipe do Fish, e há expectativa para ver como o projeto vai evoluir
Fico curioso sobre quão fácil será para os mantenedores de pacotes empacotar o Rust-fish seguindo as diretrizes do Debian
Parabéns à equipe do Fish, a opinião é que o melhor shell ficou ainda melhor. Sugerem atualizar o tagline do projeto para "Finally, a shell for the 00s!"
Depois de mudar de zsh para Fish, a configuração ficou mais simples, e como o Fish funciona como esperado, não há intenção de mudar de novo
O macro
cfg!é compilado para true/false, então o código dentro de um guardaifprecisa ser compilado. Se compilar semmy_feature, isso pode falharO Fish usa threads para autocompletar e destacar sintaxe, e existe um projeto de longo prazo para adicionar concorrência à linguagem