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:
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() {
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() {
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:
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!

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.