13 pontos por GN⁺ 2025-10-17 | 2 comentários | Compartilhar no WhatsApp
  • O projeto Rust for Linux está impulsionando recursos centrais da linguagem necessários para o desenvolvimento do kernel e, com isso, contribuindo para a evolução do próprio Rust
  • Três pontos são centrais: Field Projection, In-place Initialization e Arbitrary Self Types
  • Esses recursos permitem expressar de forma mais natural em Rust estruturas típicas do kernel, como smart pointers, memória pinada (Pin) e RCU
  • A equipe do Rust prioriza a estabilidade do design, por isso o desenvolvimento é mais lento, mas o objetivo claro do kernel Linux aumenta o foco no desenvolvimento
  • A mudança também deve impactar o ecossistema Rust fora do kernel, com grande ajuda em tratamento de smart pointers e simplificação de código

Melhorias na linguagem Rust e o papel do kernel Linux

  • O motivo de o desenvolvimento de novos recursos na linguagem Rust ser lento é a cautela para não cristalizar um design ruim na linguagem e o problema de "alignment in attention"
    • Como o projeto Rust é conduzido por voluntários, o desenvolvimento atrasa quando não há pessoas focadas em um recurso específico
  • Como o projeto Rust for Linux é um tema que empolga muita gente, ele ajuda a concentrar esforços em alguns recursos centrais necessários ao kernel
  • O co-líder da equipe de linguagem Rust, Tyler Mandry, apresentou no Kangrejos 2025 os próximos recursos da linguagem Rust e comentou que o projeto Linux kernel atuou como catalisador para a evolução do Rust
    • Recursos principais: Field Projection, in-place initialization e Arbitrary Self Types
    • O desenvolvimento para o kernel ajudou a deixar claros os casos de uso reais e os requisitos técnicos, contribuindo para concretizar a direção do design da linguagem Rust
    • A maior prioridade é padronizar os recursos unstable já usados nos bindings do kernel

Field Projection

  • É um recurso para extrair o ponteiro de um campo específico a partir do ponteiro de uma struct, uma tentativa de generalizar em Rust a expressão &(r->field) de C
  • Antes isso só era possível com referências (&) e ponteiros (*mut), havendo limitações para smart pointers definidas pelo usuário
  • O Rust for Linux está trabalhando para expandir isso e permitir acesso a campos com a mesma sintaxe em todos os tipos de ponteiro
  • Em especial, ao lidar com o tipo Pin (structs que não podem ser movidas), o design prevê conversão automática, na projeção de campos, para Pin<&mut Field> ou &mut Field
  • Quando esse recurso estiver implementado, será possível dar suporte seguro ao padrão RCU (Read-Copy-Update) em Rust, permitindo acesso a dados de alto desempenho mesmo sem locks
  • A discussão está em andamento na tracking issue no GitHub, com meta de estabilização antes do Debian 14 (2027)

Arbitrary Self Types

  • É um recurso que permite definir métodos que aceitam smart pointers
  • Antes, só havia suporte para formas como fn method(&self), mas agora também passam a ser possíveis formas como fn method(self: Pin<&mut MyStruct>)
  • No kernel, é um recurso essencial porque são usados vários wrappers de ponteiro, como Arc, Pin e Mutex
  • Durante a implementação, houve conflito com o trait Deref, mas isso está sendo resolvido com a introdução de um novo trait Receiver
  • O Receiver serve para indicar explicitamente que um ponteiro pode ser usado como um tipo Self arbitrário
  • No desenvolvimento do kernel, isso ajuda a manter concisas as chamadas em cadeia de ponteiros
  • Ding está usando a ferramenta Crater para verificar a compatibilidade com pacotes Rust existentes e mencionou a possibilidade de estabilização dentro de 1 ano

In-place Initialization

  • É um recurso que dá suporte em nível de linguagem ao macro pin_init!() usado no kernel
  • Permite criar um objeto e inicializá-lo diretamente na memória sem movê-lo depois, sendo útil para structs Pin, Future e traits dyn
  • Três propostas estão sendo discutidas em paralelo
    • abordagem com palavra-chave init: reutiliza o trait PinInit com adição mínima de sintaxe
    • abordagem com referência &out: adiciona uma referência somente para escrita, como os out pointers de C, com suporte à inicialização por campo
    • abordagem de otimização no estilo C++: cria diretamente no heap, desde o início, objetos que seriam movidos imediatamente para o heap
  • No fim, o plano é experimentar tanto o PinInit quanto a abordagem de out-reference para validar a usabilidade real
  • Se esse recurso for adotado, a expectativa é que ele contribua para simplificar a estrutura não só do kernel, mas também do código assíncrono em Rust de forma geral

O impacto do Rust for Linux sobre o Rust

  • O kernel Linux está servindo como um testbed realista para a evolução da linguagem Rust
  • Os três recursos nasceram de demandas específicas do kernel, como smart pointers, memória pinada e estruturas de concorrência, mas
    no fim também devem beneficiar desenvolvedores Rust em geral
  • Essas mudanças são vistas como um exemplo de ciclo virtuoso entre o desenvolvimento do kernel e o da linguagem

2 comentários

 
GN⁺ 2025-10-17
Comentários do Hacker News
  • Levei um tempo para ler e entender o documento RFC sobre o recurso de lightweight clones do Rust. No começo, achei esse recurso bastante interessante, mas no fim isso me fez sentir mais uma vez que Rust é uma linguagem complicada de aprender. Para alguém como eu, que não aprendeu Rust nem C++ direito, passa a impressão de que todos os conceitos e recursos do C++ moderno foram combinados com elementos de Haskell. Ainda assim, vendo as pessoas criarem tantas coisas úteis com Rust, dá a sensação de que existe algo realmente sólido ali. Então estou pensando em voltar a usar Rust para valer em breve. Link para o RFC relacionado

    • Pela minha experiência, C++ é muito mais complexo que Rust. Por exemplo, só de formas de inicialização existem 8, e até os tipos de valor são 5, incluindo xvalues. Formatação e convenções de nomenclatura também não são consistentes, e ainda tem rule of 5, tratamento de exceções, a necessidade de sempre checar this != other ao fazer move assignment, perfect forwarding, SFINAE, substitutos de traits e muitas outras complicações. Para usar C++ direito, também é preciso aprender as convenções construídas em cima do padrão para programar de forma segura e rápida, e muitas vezes os métodos, como tratamento de exceções, entram em conflito entre si ou forçam a adoção de abordagens nada ideais

    • Na comunidade Rust, o clima em relação a essa proposta de lightweight clones está ficando cada vez mais negativo. O motivo é que ela é complexa demais. Até no documento oficial do Rust sobre a direção de design, a complexidade aparece como o maior obstáculo. Não é que toda proposta para Rust precise ser simples, mas lightweight clone só tornaria um pouco mais fácil algo que já é possível fazer, e se as pessoas não conseguem entender isso com facilidade, então há um problema

    • Rust parece enorme quando visto de longe, mas quando você realmente começa a programar, se acostuma rápido. Por exemplo, no começo eu não entendia nada do conceito de lifetime, então programava só com Rc<>. Depois de aprender o básico, fui estudar lifetimes de novo e ficou muito mais fácil. Na verdade, a maioria dos usuários nunca vai precisar se preocupar com recursos como lightweight clones

    • Comparado com C, é muito complexo, mas comparado com C++, é uma linguagem bem mais simples. Quase nunca é preciso ficar vasculhando documentação ou referência só para entender o código. Rust ocupa uma posição muito boa: “não é complexo demais a ponto de te arrancar os cabelos, nem simples demais a ponto de o código virar uma bagunça”. Além disso, o código já tende a vir com correctness por padrão

    • A complexidade do Rust também é menos propensa a ser usada errado por acidente do que a do C++. E, se você usa clippy, ele ainda transforma automaticamente o código em algo mais idiomatic, então mesmo recursos novos como lightweight clones podem ser sugeridos sem que você os conheça diretamente. Na maioria dos casos, dá para aplicar isso facilmente só com a opção --fix do clippy. Essa parte é decisively diferente de C++, onde recursos não usados vão se acumulando ou acabam sendo usados de forma excessivamente complexa, e esse efeito colateral continua empilhando complexidade

  • Ouvi dizer que o projeto Rust for Linux ajudou bastante o Rust, então por curiosidade fui procurar por arquivos *.rs na árvore do kernel. Pelo que vi, existe uma camada de compatibilidade de API dentro da pasta rust, e na árvore do kernel há só alguns drivers proof of concept que basicamente reescrevem drivers já existentes (tirando o driver inacabado da Nvidia), então parece que na prática não há nada realmente em uso. Também tive a impressão de que o rewrite em Rust do Android binder mal continua existindo. Minha impressão geral é a de um projetinho experimental simpático, e fico em dúvida se faz sentido fazer esse tipo de experimento de co-desenvolvimento de linguagem na árvore de código-fonte do software mais importante do mundo. Acho que seria melhor fazer isso em um sistema operacional mais experimental, como o Redox

    • O driver de GPU para Apple Silicon foi escrito em Rust, e o próprio autor disse que teria sido muito mais difícil desenvolvê-lo em C. Ainda não foi enviado para upstream, mas ele afirmou: “quando você cria um driver de kernel novo e complexo, é normal aparecerem todos os tipos de problemas, como race condition, memory leak, use-after-free e afins. Mas ao escrever em Rust, ele funciona de forma estável quase sem esses problemas. Graças aos recursos de segurança, tenho confiança de que o driver é thread-safe e memory-safe, e o próprio design naturalmente segue numa direção melhor. Acho que essa é a magia do Rust”. Link para o relato do autor E, sobre a pergunta se é aceitável fazer esse tipo de experimento dentro da árvore do kernel, foi mencionado que Torvalds não concorda com essa crítica

    • A opinião de que “o rewrite em Rust do Android binder mal continua existindo” não é verdadeira. O plano atual desse projeto é substituir completamente a implementação em C. Artigo relacionado Os principais drivers para hardware Apple da linha M também foram escritos em Rust, e não são simples rewrites nem proof of concept

    • Para criar drivers complexos, antes é preciso ter uma camada de interface. O projeto RfL está trabalhando para adicionar essa camada de infraestrutura ao upstream, e é preciso acumular essa base antes de poder escrever drivers complexos. A Red Hat está trabalhando no nova, a Asahi no GPU da Apple e a Collabora no ARM Mali. Se nem três drivers de GPU contam como drivers complexos, então fica a dúvida sobre o que contaria

    • Sobre a afirmação de que o rewrite em Rust do binder está apenas sobrevivendo, as mensagens de commit na árvore do Linus mostram um estado de maturidade alto. O Rust binder já passa por todos os testes de binder do Android Open Source Project, e vários apps e recursos funcionam sem problemas relevantes. Não há problemas para boot nem para execução de apps no emulador cuttlefish e no Pixel 6 Pro. A funcionalidade atual também é equivalente à do binder em C; só faltam alguns recursos de depuração, que devem ser adicionados em breve. Além disso, o projeto Rust for Linux começou originalmente fora da árvore do kernel, mas para testar integração real em algum momento é preciso experimentar dentro da árvore

    • O objetivo desse projeto não é um experimento conjunto de desenvolvimento de linguagem, mas usar Rust no desenvolvimento do kernel Linux. É um projeto iniciado pelos próprios desenvolvedores centrais porque eles queriam usar Rust. Como se trata de um software extremamente importante, o avanço está sendo cauteloso, e fortalecer a base leva tempo. O fato de Rust ganhar benefícios colaterais com isso é só um bônus

  • Vi no artigo a observação de que, na parte relacionada a field projection, foi decidido que todos os campos de struct agora seriam estruturalmente pinados, de modo que tipos como Pin<&mut Field> sempre passem a aparecer, e percebi que eu tinha deixado esse ponto passar antes. É um assunto tecnicamente complexo, mas fico feliz porque essa decisão resolveu um problema que vinha travando várias discussões

  • As pessoas estão discutindo a <i>técnica de otimização prevista, inspirada em C++, em que ao criar um novo valor para alocá-lo no heap e movê-lo imediatamente, ele já seja criado diretamente no heap desde o início</i>. O nome “otimização” aqui pode induzir ao erro, então há discussão sobre mudar esse nome

    • Talvez eu não esteja entendendo direito a complexidade do problema, mas me parece que isso não poderia ser resolvido de forma simples definindo uma calling convention adequada? Se a struct for maior do que x ou tiver um marker type, o caller passa um buffer por outref, e o callee escreve a struct diretamente nesse buffer. Assim, mesmo escrevendo código comum, daria para evitar alocação duplicada no heap, e em outras situações também reduzir cópias desnecessárias. Como esse é um tema em que já foi investido muito esforço, fico curioso para entender por que as soluções propostas seriam mais inconvenientes

    • Acho que, em vez de tratar isso como uma otimização interna, seria mais intuitivo para todo mundo tornar isso explícito com algo como uma função new

    • Em C++, esse tipo de semântica é chamado de elision

    • Foi sugerido um nome como ‘coalesced heap construction’ ou ‘coalesced heap allocation’

  • Sempre que ouço falar de vários recursos do Rust, acabo fazendo a piada: “vamos só não colocar Tokio no kernel de jeito nenhum”. Se Rust evoluir o bastante e surgir um direct composition renderer, permitindo apps que rodem em todo o kernel, isso até poderia virar uma situação bem interessante

    • Implementar um async runtime dentro do kernel é realmente trivial. Na prática, a própria workqueue do kernel já é um runtime

    • Se isso não for brincadeira, então há um mal-entendido fundamental sobre a estrutura de escrever código de kernel em Rust (e em C). Ao programar para kernel, Rust, assim como C, roda em no_std, e você não pode usar cargo nem crates. Para usar Tokio, teria que reescrever metade dele e substituir toda a interação com o sistema operacional, como sockets, por mecanismos do kernel

  • Acho que esses recursos recentes ligados ao Rust que estão entrando no Linux são os primeiros recursos amplamente úteis da linguagem Rust, e não se limitam ao kernel. Fiquei com a impressão de que o foco em desenvolvimento de recursos centrados no kernel vinha atrapalhando um pouco o desenvolvimento de outros recursos da linguagem e de bibliotecas

    • Pelo que sei, systems programming é a área prioritária de adoção do Rust. Interoperability é essencial em sistemas operacionais, embarcados e sistemas complexos baseados em C. Esses recursos não parecem exclusivos para kernel, mas sim utilitários gerais realmente necessários para programação de sistemas no mundo real

    • Há avanços para desenvolvimento de kernel e firmware acontecendo em várias frentes, mas isso nem sempre vira assunto de interesse de todo mundo. O Philipp, em particular, vem liderando grandes mudanças nessa área

    • O principal papel do Rust é programação de sistemas low level. Fora disso, linguagens gerenciadas compiladas para userspace costumam ser escolhas muito melhores, e em sistemas organizados como os de Self, Inferno ou da arquitetura do Android, não vejo problema em focar nesses recursos low level no estilo de C

  • Esses recursos são ótimos o bastante para ajudar não só o kernel, mas também outras áreas (especialmente generalized projections). Fico muito satisfeito em ver o Linux impulsionando a evolução da linguagem Rust

  • Fiquei curioso para saber se existem pesquisas ou ferramentas que usem LLM para converter automaticamente código C para Rust. Pensei se seria possível pedir a um LLM para gerar código Rust para chat, USB, I2C, drivers de GPU etc., e ainda compilar e testar isso, ou se talvez desse para tentar primeiro com projetos “menores”, como sqlite, apache ou nginx

    • Como pesquisa não baseada em LLM, existe o projeto c2rust, que já tem casos reais de uso. LLM, no fundo, continua sendo approximation, então não consegue fazer isso com precisão e acaba introduzindo muitos bugs sutis. Sem combinar com algo como métodos formais, não parece algo prático. Há muitos problemas que testes unitários por si só não conseguem detectar. E os exemplos de projetos “menores” que você citou, na prática, também não são tão pequenos assim. Veja casos reais de aplicação

    • A Darpa também demonstrou interesse nesse tipo de pesquisa e chegou a financiar iniciativas, mas ainda não estamos num estágio em que existam resultados concretos

 
ahwjdekf 2025-10-17

Fanatismo no alinhamento (alignment in dogmatism)