Rust 1.30 Release

A equipe de desenvolvimento do Rust tem o prazer de anunciar o lançamento de uma nova versão do Rust: 1.30.0. Rust é uma linguagem de programação de sistema destinada a segurança, velocidade e execução de código paralelo.


Se você possui uma versão anterior do Rust instalada usando rustup , para fazer o upgrade do Rust para a versão 1.30.0, basta fazer o seguinte:


 $ rustup update stable 

Se você ainda não instalou o rustup , poderá instalá-lo na página correspondente do nosso site. Notas de versão detalhadas do Rust 1.30.0 estão disponíveis no GitHub.


O que está incluído na versão estável 1.30.0


O Rust 1.30 é um excelente lançamento com várias inovações importantes. Mas na segunda-feira, o blog oficial será publicado com uma solicitação para verificar a versão beta do Rust 1.31, que será o primeiro lançamento do "Rust 2018". Você encontrará mais informações sobre isso em nossa publicação anterior “What is Rust 2018” .


Macros procedurais


De volta ao Rust 1.15, adicionamos a capacidade de definir "macros de derivação personalizadas". Por exemplo, usando serde_derive , você pode declarar:


 #[derive(Serialize, Deserialize, Debug)] struct Pet { name: String, } 

E converta Pet em JSON e volte à estrutura usando serde_json . Isso é possível graças à inferência automática de Deserialize Serialize e Deserialize usando macros procedurais em serde_derive .


O Rust 1.30 estende a funcionalidade das macros procedurais adicionando a capacidade de definir dois outros tipos de macros: “atribuir macros procedurais” e “macros procedurais funcionais”.


As macros de atributo são semelhantes às macros derivadas para saída automática, mas, em vez de gerar código apenas para o atributo #[derive] , elas permitem que os usuários criem seus próprios novos atributos. Isso os torna mais flexíveis: as macros derivadas funcionam apenas para estruturas e enumerações, mas os atributos podem ser aplicados a outros objetos, como funções. Por exemplo, as macros de atributo permitirão que você faça o seguinte ao usar uma estrutura da web:


 #[route(GET, "/")] fn index() { 

Este atributo #[route] será definido na própria estrutura como uma macro processual. A assinatura dele ficará assim:


 #[proc_macro_attribute] pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream { 

Aqui temos dois parâmetros de entrada do tipo TokenStream : o primeiro é para o conteúdo do próprio atributo, ou seja, esses são os parâmetros GET, "/" . O segundo é o corpo do objeto ao qual o atributo é aplicado. No nosso caso, este é fn index() {} e o restante do corpo da função.


Macros funcionais definem macros cujo uso se parece com uma chamada de função. Por exemplo, a sql! :


 let sql = sql!(SELECT * FROM posts WHERE id=1); 

Essa macro em si analisará as expressões SQL e as verificará quanto à correção sintática. Uma macro semelhante deve ser declarada da seguinte maneira:


 #[proc_macro] pub fn sql(input: TokenStream) -> TokenStream { 

Isso é semelhante à assinatura da macro derivada: obtemos os tokens que estão dentro dos colchetes e retornamos o código gerado por eles.


Macros e use


Agora você pode importar macros para o escopo usando a palavra-chave use . Por exemplo, para usar a macro serde-json pacote serde-json , a entrada costumava ser:


 #[macro_use] extern crate serde_json; let john = json!({ "name": "John Doe", "age": 43, "phones": [ "+44 1234567", "+44 2345678" ] }); 

E agora você terá que escrever:


 extern crate serde_json; use serde_json::json; let john = json!({ "name": "John Doe", "age": 43, "phones": [ "+44 1234567", "+44 2345678" ] }); 

Aqui, a macro é importada, assim como outros elementos, portanto, não há necessidade de usar a anotação macro_use .


Finalmente, o pacote proc_macro é estabilizado , o que fornece a API necessária para gravar macros procedurais. Também melhorou significativamente a API de tratamento de erros, e pacotes como syn e quote já a usam. Por exemplo, anteriormente:


 #[derive(Serialize)] struct Demo { ok: String, bad: std::thread::Thread, } 

levou a este erro:


 error[E0277]: the trait bound `std::thread::Thread: _IMPL_SERIALIZE_FOR_Demo::_serde::Serialize` is not satisfied --> src/main.rs:3:10 | 3 | #[derive(Serialize)] | ^^^^^^^^^ the trait `_IMPL_SERIALIZE_FOR_Demo::_serde::Serialize` is not implemented for `std::thread::Thread` 

Agora será emitido:


 error[E0277]: the trait bound `std::thread::Thread: serde::Serialize` is not satisfied --> src/main.rs:7:5 | 7 | bad: std::thread::Thread, | ^^^ the trait `serde::Serialize` is not implemented for `std::thread::Thread` 

Melhorando o sistema do módulo


O sistema de módulos tem sido um ponto dolorido para iniciantes em Rust; algumas de suas regras eram inconvenientes na prática. Essas mudanças são o primeiro passo que estamos dando para simplificar o sistema de módulos.


Além da alteração acima para macros, há duas novas melhorias para use . Primeiro, pacotes externos agora são adicionados ao prelúdio , ou seja:


 //  let json = ::serde_json::from_str("..."); //  let json = serde_json::from_str("..."); 

O problema é que o estilo antigo nem sempre era necessário devido aos recursos do sistema do módulo Rust:


 extern crate serde_json; fn main() { //   ;     ,  `serde_json` //     let json = serde_json::from_str("..."); } mod foo { fn bar() { //   ;     `foo`,  `serde_json` //    let json = serde_json::from_str("..."); } //   -        `use` use serde_json; fn baz() { //   -   `::serde_json`,   //  ,   let json = ::serde_json::from_str("..."); } } 

Era irritante obter código quebrado simplesmente movendo a função para um submódulo. Agora a primeira parte do caminho será verificada e, se corresponder a alguma extern crate , será usada independentemente da posição da chamada na hierarquia do módulo.


Por fim, o uso começou a dar suporte à importação de elementos para o escopo atual com caminhos que começam na caixa :


 mod foo { pub fn bar() { // ... } } //  use ::foo::bar; //  use foo::bar; //  use crate::foo::bar; 

A palavra-chave crate no início do caminho indica que o caminho começará na raiz do pacote. Anteriormente, os caminhos indicados na linha de importação de use sempre eram especificados em relação à raiz do pacote, mas os caminhos no restante do código que se referem diretamente aos elementos eram especificados em relação ao módulo atual, o que levava a um comportamento inconsistente dos caminhos:


 mod foo { pub fn bar() { // ... } } mod baz { pub fn qux() { //  ::foo::bar(); //  ,    `use`: // foo::bar(); //  crate::foo::bar(); } } 

Assim que o novo estilo for amplamente utilizado, esperamos tornar os caminhos absolutos mais claros sem a necessidade de usar o prefixo feio :: .


Todas essas alterações juntas simplificam a compreensão de como os caminhos são resolvidos. Onde quer que você veja o caminho a::b::c , exceto a instrução use , você pode perguntar:


  • É um nome de pacote? Então você precisa procurar b::c dentro dele.
  • É a crate palavras a chave? Então você precisa procurar b::c na raiz do pacote atual.
  • Caso contrário, você precisa procurar a::b::c da posição atual na hierarquia do módulo.

O antigo comportamento dos caminhos em use , sempre começando na raiz do pacote, ainda é aplicável. Porém, com uma transição única para um novo estilo, essas regras serão aplicadas uniformemente a caminhos em todos os lugares, e você terá que se preocupar muito menos com as importações ao mover o código.


Identificadores brutos


Agora você pode usar palavras-chave como identificadores usando a seguinte nova sintaxe:


 //      `for` let r#for = true; //     `for` fn r#for() { // ... } //    r#for(); 

Até o momento, não há muitos casos em que isso seja útil para você. Mas um dia você tentará usar o pacote para o Rust 2015 em um projeto para o Rust 2018 ou vice-versa, e o conjunto de palavras-chave será diferente. Falaremos mais sobre isso no próximo anúncio do Rust 2018.


Aplicativos sem uma biblioteca padrão


De volta ao Rust 1.6, anunciamos a estabilização de "no_std" e libcore para criar projetos sem uma biblioteca padrão. No entanto, com um esclarecimento: foi possível criar apenas bibliotecas, mas não aplicativos.


No Rust 1.30, você pode usar o atributo #[panic_handler] para implementar independentemente o pânico. Isso significa que agora você pode criar aplicativos, não apenas bibliotecas que não usam a biblioteca padrão.


Outros


Uma última coisa: nas macros, agora você pode mapear modificadores de escopo , como pub , usando o qualificador vis . Além disso, "atributos da ferramenta", como #[rustfmt::skip] , agora estão estabilizados . Verdadeiro para uso com ferramentas de análise estática , como #[allow(clippy::something)] , elas ainda não são estáveis.


Veja as notas de versão para mais detalhes.


Estabilização da biblioteca padrão


As seguintes APIs foram estabilizadas nesta versão:


  • Ipv4Addr::{BROADCAST, LOCALHOST, UNSPECIFIED}
  • Ipv6Addr::{BROADCAST, LOCALHOST, UNSPECIFIED}
  • Iterator::find_map

Além disso, há muito tempo a biblioteca padrão possui funções para remover espaços em um lado de algum texto, como trim_left . No entanto, para linguagens RTL, o significado de "direita" e "esquerda" aqui leva à confusão. Portanto, introduzimos novos nomes para essas funções:


  • trim_left -> trim_start
  • trim_right -> trim_end
  • trim_left_matches -> trim_start_matches
  • trim_right_matches -> trim_end_matches

Planejamos declarar obsoletos os nomes antigos (mas não excluir, é claro) no Rust 1.33.


Veja as notas de versão para mais detalhes.


Aprimoramentos de carga


A maior melhoria do Cargo neste lançamento é que agora temos uma barra de progresso!


gif de demonstração


Veja as notas de versão para mais detalhes.


Desenvolvedores 1.30.0


Muitas pessoas juntas criaram o Rust 1.30. Não poderíamos ter concluído o trabalho sem cada um de vocês. Obrigada


De um tradutor: expresso gratidão especial aos membros da comunidade Rustycrate e pessoalmente ao vitvakatu e ao Virtuos86 por sua ajuda na tradução e revisão.

Source: https://habr.com/ru/post/pt428073/


All Articles