Objetivos do projeto Rust: tipos imóveis e destrutores garantidos
Os mantenedores do Rust estão explorando novos traits no nível de tipo como `!Move` e `!Forget` para dar suporte a tipos imóveis e destrutores garantidos, visando resolver problemas antigos de async, estruturas autorreferenciais e vazamentos de memória. Comentadores destacam como isso poderia permitir concorrência estruturada mais segura (por exemplo, tarefas async com escopo e limpeza garantida) e APIs mais expressivas, como recursos lineares “must-use”, ao mesmo tempo em que apontam desafios sérios de compatibilidade retroativa com traits existentes, coleções e o modelo `Pin`. Há um entusiasmo amplo pelas capacidades que esses recursos poderiam desbloquear, temperado pelo reconhecimento de que o design é complexo, ainda não está finalizado e pode exigir trocas com propostas alternativas como a “ergonomia de pin”.
Ideia de alto nível
- A proposta introduz traits como
!Move,!Forgete, eventualmente,!Destructpara:- Tornar a imobilidade uma propriedade do tipo em vez da localização (substituindo grande parte de
Pin). - Garantir que os destrutores sejam executados (ou que seja impossível vazar) para certos tipos.
- Lançar as bases para tipos lineares / must-move.
- Tornar a imobilidade uma propriedade do tipo em vez da localização (substituindo grande parte de
Rust assíncrono e concorrência estruturada
- A motivação principal é melhorar o async/concorrência estruturada:
- Hoje, tarefas async podem ser canceladas arbitrariamente, então os destrutores talvez nunca sejam executados.
- Isso bloqueia “tarefas com escopo” totalmente seguras, análogas a threads com escopo.
- Com
!Forget, os handles de tarefas poderiam ter a garantia de serem descartados, tornando o async com escopo seguro e ergonômico.
- Também ajuda em:
- Funções async recursivas (sem truques com
Box::pin). - Funções async que fazem borrowing de escopos externos em vez de clonar.
- Funções async recursivas (sem truques com
Tipos imóveis vs Pin
Piné amplamente visto como confuso e como uma “gambiarra”:- Ele fixa localizações e tem semântica de
Unpine regras de projeção complicadas. - Código async de baixo nível que usa
Piné pouco ergonômico e depende deunsafe.
- Ele fixa localizações e tem semântica de
!Movetornaria a imobilidade intrínseca ao tipo:- Permite auto-referências seguras e padrões complexos que
Pinnão consegue suportar totalmente.
- Permite auto-referências seguras e padrões complexos que
- Existe um caminho alternativo de “locais fixados”/ergonomia de pin; esta proposta é explicitamente uma alternativa e pretende descontinuar
Pinno longo prazo.
Controle de vazamentos e !Forget
!Forgetvisa garantir que um destrutor seja executado antes que o armazenamento seja reutilizado.- Vazamentos via
mem::forgetou ciclos de referências:- A proposta é restringi-los exigindo
T: ForgetparaRc/Arce tipos semelhantes. - Loops infinitos ou enviar valores para outras threads não são considerados “esquecer”, já que o escopo nunca termina.
- A proposta é restringi-los exigindo
Tipos lineares / must-move (!Destruct)
- Forçariam caminhos explícitos de destruição:
- APIs como transações poderiam exigir estaticamente exatamente um de
commit/rollback. - Padrões de “rollback silencioso” ou de panic em
Droppoderiam ser evitados.
- APIs como transações poderiam exigir estaticamente exatamente um de
- A destruição normalmente exigiria desestruturação ou funções consumidoras dedicadas no módulo definidor.
Compatibilidade retroativa e impactos em std
- A compatibilidade retroativa é um grande risco:
- Genéricos existentes assumem implicitamente que tudo é móvel e descartável.
- Traits como
Iterator::ItemeDeref::Targettornam-se problemáticos quando alguns tipos são!Move. - Coleções como
Vec<T>movem elementos por natureza; provavelmente não podem suportar tipos!Move, ou apenas via APIs restritas.
- Edições ajudam, mas não resolvem tudo; um design cuidadoso de padrões e limites (
T: MovevsT: ?Move) é crucial e nada trivial.
Relação com efeitos algébricos e C++
- Alguns veem esses traits como semelhantes a efeitos:
drop<T>,move<T>,forget<T>se comportam como efeitos implícitos associados às funções. - Outros argumentam que isso é principalmente sobre propriedades de tipos e futuros sistemas de efeitos.
- Comparações com C++:
- Rust não está adicionando construtores implícitos de move/copy.
- Imobilidade e destrutores garantidos facilitam a interoperabilidade com C++ e certos padrões (auto-referências, grafos de objetos complexos), mas com semânticas explícitas e mais estritas.
Status e incerteza
- Isso é um objetivo de projeto, não uma mudança de linguagem aceita.
- Compete com o objetivo de ergonomia de pin; muitos esperam que tipos imóveis vençam se apenas um sobreviver, mas:
- A mudança é abrangente e complexa.
- Semântica, compatibilidade retroativa e integração com std continuam em aberto e ainda podem inviabilizar ou remodelar significativamente o design.