Rust 1.30发布

Rust开发团队很高兴地宣布发布Rust的新版本:1.30.0。 Rust是一种针对安全性,速度和并行代码执行的系统编程语言。


如果您使用rustup安装了先前版本的Rust,那么要将Rust升级到1.30.0版本,您只需执行以下操作:


 $ rustup update stable 

如果尚未安装rustup ,则可以从我们网站的相应页面进行安装 。 可以在GitHub上找到Rust 1.30.0的详细发行说明


稳定版1.30.0中包含什么


Rust 1.30是具有许多重要创新的出色发行版。 但是在星期一,官方博客将发布请求,以检查Rust 1.31的beta版本,这将是“ Rust 2018”的第一个版本。 您可以在我们之前的出版物“ What is Rust 2018”中找到有关此的更多信息。


程序宏


回到Rust 1.15,我们添加了定义“自定义派生宏”的功能。 例如,使用serde_derive ,您可以声明:


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

并将Pet转换为JSON并使用serde_json返回结构。 这可以归功于使用serde_derive过程宏对SerializeDeserialize Serialize Deserialize的自动推断。


Rust 1.30通过添加定义两种其他类型的宏的功能来扩展过程宏的功能:“属性过程宏”和“功能过程宏”。


属性宏类似于自动输出的派生宏,但是它们不仅仅为#[derive]属性生成代码,而是允许用户创建自己的新属性。 这使它们更加灵活:派生宏仅适用于结构和枚举,但是属性可以应用于其他对象,例如函数。 例如,使用网络框架时,属性宏将允许您执行以下操作:


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

此属性#[route]将在框架本身中定义为程序宏。 他的签名将如下所示:


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

在这里,我们有两个TokenStream类型的输入参数:第一个是属性本身的内容,即GET, "/"参数GET, "/" 。 第二个是应用属性的对象的主体。 在我们的例子中,这是fn index() {}和函数主体的其余部分。


功能宏定义了其用法类似于函数调用的宏。 例如, sql!


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

这个宏本身将解析SQL表达式并检查其语法正确性。 类似的宏应声明如下:


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

这类似于derive宏的签名:我们获得括号内的令牌,并返回由它们生成的代码。


宏和use


现在,您可以使用use关键字将宏导入作用域 。 例如,要使用serde-json包中的json宏,该条目以前为:


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

现在,您将必须编写:


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

在这里,宏以及其他元素也被导入,因此不需要使用macro_use批注。


最后, proc_macro软件包已稳定下来 ,它提供了编写过程宏所需的API。 它还大大改善了错误处理API,并且synquote这样的程序包已经在使用它。 例如,先前:


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

导致此错误:


 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` 

现在将发布:


 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` 

改善模块系统


长期以来,模块系统一直是Rust初学者的痛点; 它的某些规则在实践中不方便。 这些更改是我们简化模块系统所采取的第一步。


除了上述对宏的更改之外,使用use还有两个新的改进。 首先, 现在将外部软件包添加到前奏中 ,即:


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

值得注意的是,由于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("..."); } } 

只需将函数移至子模块即可破坏代码,这很烦人。 现在将检查路径的第一部分,如果它对应于某个extern crate ,则无论调用在模块层次结构中的位置如何,都将使用它。


最后, use开始支持使用以crate开头的路径将元素导入当前范围


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

路径开头的crate关键字表示路径将从数据包的根开始。 以前, use导入行中指示的路径始终是相对于包的根目录指定的,但是直接引用元素的其余代码中的路径是相对于当前模块指定的,这导致路径的行为不一致:


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

新样式一经广泛使用,就有望使绝对路径更清晰,而无需使用丑陋的前缀::


所有这些更改共同简化了对路径解析方式的理解。 无论您在哪里看到路径a::b::c ,除了use语句,您都可以问:


  • 是包裹名称吗? 然后,您需要在其中查找b::c
  • 是关键字crate吗? 然后,您需要从当前包的根目录中查找b::c
  • 否则,您需要从模块层次结构中的当前位置查找a::b::c

始终从包根开始use中路径的旧行为仍然适用。 但是,一次性过渡到新样式后,这些规则将统一应用于所有路径,并且在移动代码时您不必担心导入。


原始标识符


现在,您可以使用以下新语法将关键字用作标识符


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

到目前为止,对您有用的情况并不多。 但是有一天,您将在Rust 2018的项目中尝试使用Rust 2015的软件包,反之亦然,那么它们的关键字集会有所不同。 我们将在即将发布的Rust 2018公告中进一步讨论这一点。


没有标准库的应用程序


在Rust 1.6中,我们宣布了稳定“ no_std”和libcore的功能,以创建没有标准库的项目。 但是,有一个澄清:可以仅创建库,而不能创建应用程序。


在Rust 1.30中,可以使用#[panic_handler]属性独立实现恐慌。 这意味着现在您可以创建应用程序,而不仅仅是不使用标准库的库。


其他


最后一件事:在宏中,您现在可以使用vis限定符映射范围修饰符 ,例如pub 。 此外,“稳定的工具属性”(例如#[rustfmt::skip]现在已稳定 。 适用于静态分析工具 ,例如#[allow(clippy::something)] ,它们尚不稳定。


有关更多详细信息,请参见发行说明


稳定标准库


此版本中稳定以下API


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

此外,标准库长期以来就有删除某些文本一侧空格的功能,例如trim_left 。 但是,对于RTL语言,此处“右”和“左”的含义会引起混淆。 因此,我们为这些功能引入了新的名称:


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

我们计划在Rust 1.33中声明旧名称(但不能删除)。


有关更多详细信息,请参见发行说明


货运增强


此版本中对Cargo的最大改进是,我们现在有了进度栏!


演示gif


有关更多详细信息,请参见发行说明


开发人员1.30.0


很多人一起创建了Rust 1.30。 没有你们每个人,我们不可能完成工作。 谢谢你


译者:我特别感谢Rustycrate社区的成员以及vitvakatuVirtuos86的翻译和校对工作。

Source: https://habr.com/ru/post/zh-CN428073/


All Articles