Rust 1.45 发布:修复了 Cast Unsoundness 并稳定了 Web 框架 Rocket 的支持

孤人 提交于 2020-08-04 09:17:15

云栖号资讯:【点击查看更多行业资讯
在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来!

Rust 1.45 修复了一个长期存在的浮点数强制转换问题,该问题可能导致未定义行为(undefined behaviour )异常,并稳定了流行 Web 框架 Rocket 所使用的特性。

将浮点数转换为整数时,Rest 会抛出一个 未定义行为(undefined behaviour)的已知异常。如果你对Rust 的 value proposition 有所了解的话,可能会对此感到惊讶。具体来说,下面的代码片段虽然编译时不会报错,但由于使用了 cast ( as ) 将浮点数 300 强制转换为 8 位无符号整数(仅表示值介于 0 到 255 之间的整数),在 Rust 1.44 中会抛出未定义行为的异常:

fn cast(x: f32) -> u8 { 
    x as u8 
} 
fn main() { 
    let f = 300.0; 
    let x = cast(f); 
    println!("x: {}", x); 
} 

在底层,这个问题与 LLVM 的 fptoui 指令有关,该指令在上述情况下使用会生成一个“有毒”的值。回想一下,Rust 提供了 unsafe 关键字来标记希望 挂起Rust 安全保证的代码块。上面所示的代码片段虽然没有被标记为不安全,但它却包含了不安全的代码,这违背了Rust 作为安全语言的承诺。

Rust 团队花了几年的时间来修复这个不健全的强制转换问题,主要是因为不清楚怎样才能正确地处理它。最终,他们决定让 as 执行“saturating”强制转换,这意味着将过大的浮点数强制转换为可表示的最大整数,将过小的浮点数和 NaN 强制转换为 0。此外,他们还引入了一种新的 unsafe 强制转换,如果你想要跳过 Rust 的安全行为可以使用如下代码:

let x: f32 = 1.0; 
let y: u8 = unsafe { x.to_int_unchecked() }; 

虽然 saturating 强制转换提供了一种处理溢出的安全方法,但从数学角度来看,它仍然会产生错误的结果。 这就是为什么 as 在Rust 中不被视为值间转换的惯用方法,并且还被Rust 的Clipply linter 标记的原因。在Rust 中,将浮点数转换为整数更惯用的方法是,使用 into 来进行不会出错的强制转换,而使用 try_into 来进行可能会出错的强制转换。

Rust 1.45 还在三个新地方增加了对调用过程宏的支持,即:作为表达式的一部分、在模式匹配中或作为语句。过程宏在 Rust 1.30 中进行了扩展,以支持类函数宏的定义(即看起来像函数的宏)。例如,下面的代码片段定义了一个 sql 宏,该宏可生成解析 SQL 语句所需的 Rust 语法树:

// 解析 SQL 语句 
let sql = sql!(SELECT * FROM posts WHERE id=1); 
#[proc_macro] 
pub fn sql(input: TokenStream) -> TokenStream { 
   ... 
} 

该变更版本的重要性还和 它在Rocket 中的使用有关,Rocket 是一个流行的声明式Web 框架,它使用了几个仅在nightly Rust 中可用的实验特性。由于Rocket 非常受欢迎,Rust 团队一直在努力稳定其中的一些特性,而Rocket 则移除了其他的一些特性。作为这一努力的结果,尚未发布的Rocket 0.5 将成为首个能够使用稳定的Rust 进行编译的Rocket 版本。

除了本文提到的内容之外,Rust 1.45 还包含了许多其他特性的稳定和修复。 请不要错过官方发布的详细说明。

【云栖号在线课堂】每天都有产品技术专家分享!
课程地址:https://yqh.aliyun.com/zhibo

立即加入社群,与专家面对面,及时了解课程最新动态!
【云栖号在线课堂 社群】https://c.tb.cn/F3.Z8gvnK

原文发布时间:2020-07-28
本文作者:Sergio De Simone
本文来自:“InfoQ”,了解相关信息可以关注“InfoQ

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!