发布日期:2024-10-03 22:54 点击次数:169
许多东说念主认为 Rust 是一门保险内存安全的理思编程说话樱井莉亚电影,尤其适应新建设者使用。
关联词,Rust 简直恢恢有余吗?并非所有东说念主王人这样认为。
本文作家 Seph 在经过四年的 Rust 建设体验后,将其比作“初代 iPhone”,尽管令东说念主惊艳,却仍有诸多不及。
针对这些问题,Seph 建议了几项我方的革命设思。
作家 | Joseph Gentle
翻译器具 | ChatGPT 责编 | 苏宓
Rust 编程说话嗅觉像是第一代家具。
我的风趣是,它就像第一代 iPhone——绝顶令东说念主惊艳。如果到那时苹果公司围绕多点触控联想了一个完满的操作系统,打造一部莫得实体键盘的智妙手机,而况还有一个可用的网页浏览器,让所有这个词科技圈为之答应。几个月后,咱们王人意志到了 iPhone 真确思成为的样子。关联词,第一代 iPhone 并不完满锻真金不怕火。它莫得 3G 网罗,莫得 GPS 芯片,也莫得应用商店。不外,在接下来的几年里,iPhone 变得越来越好。
如今 Rust 给东说念主的嗅觉就有点像第一代 iPhone。
一运行,当我看到代数数据类型(Algebraic Data Types)、无需葬送性能的内存安全(Memory Safety)、一个当代的包不停器(Package Manager)......我就可爱上了 Rust。
仅仅当今,我编写 Rust 轮番还是有四年傍边了,它给我的嗅觉便是,恒久差点风趣。
而且我不知说念它是否会有真确“锻真金不怕火”的一天。毕竟当下这门说话的发展速率还是放缓了好多。还牢记我当初刚运运用用它时,每个版块似乎王人会为踏实版 Rust 增多一些新的高大功能。而当今呢?
寂静无声。
Rust 的“非踏实功妙手册”(Unstable Book,https://doc.rust-lang.org/unstable-book/the-unstable-book.html)中列出了 700 种不同的非踏实功能——这些功能简略王人还是完了了,但还莫得在踏实版 Rust 中启用。它们中的大多数王人是对规范库的更动。这就意味着有若干能真确插足这个说话的踏实版,外界对此存疑。
甚而不少东说念主以为,Rust 的 RFC(提案)经过险些是一个“好点子的坟场”。
比如协程(Coroutines)这种功能。这个提案还是有 7 年历史了。别诬告,协程其实还是在编译器中完了了。它们只不外对咱们这些使用“踏实版 Rust 的凡东说念主”不可用。如果协程是个孩子的话,当今它王人还是上小学了。到咫尺为止,这个协程的 RFC 存在的时分比第一次或第二次天下大战还长。
我怀疑 Rust 正在变得僵化,因为其养息团队里面迟迟无法达成共鸣。早期,Rust 有一个微型的孝敬者群体,他们不错快速作念出方案。但当今,在 GitHub 的 Rust 说话面孔下,不乏有好多这样的洽商帖——25 个智谋且意图邃密的东说念主花了两年时分、卓越 200 条驳斥,试图找出若何革命 Mutex(互斥锁)。但据我所知,最终他们差未几根除了。
也许这是专门为之。也许咱们也不错自我洗脑,即优秀的说话是一门踏实的说话。也许是技能将 Rust 视为一种锻真金不怕火的说话了——不论它有什么症结。就像 Python 2.7 同样,长期可用。
但对我来说,我无法劝服我方。我仍然思要一个更好的 Rust 说话,但我却嗅觉窝囊为力。我的协程在那处?就连 JavaScript 王人有协程了。
幻思我方篡改 Rust 说话
有技能樱井莉亚电影,我会在夜晚夜弗成眠,幻思着分叉(fork)编译器。我知说念该若何作念。在我的分叉版块中,我会保留所有的 Rust 特质,但会创建我我方的 “seph” 版块。然后我不错为这个版块添加各式壅塞性的新特质。唯有我的编译器还能编译干线 Rust 代码,我就不错连接使用 Cargo 上所有优秀的 crates(Rust 的包不停器中的库)。
我往往会这样思。如果我简直这样作念了,以下是我会修改的内容:
函数特质(甩掉)
Rust 的结构体(structs)上有特征(traits)。这些特征被用在各式场景中。有些是标识特质,有些是编译器内置的(比如 Copy 特质),还有一些是用户自界说的。
我以为 Rust 也应该为函数界说一堆 trait。在其他编程说话中,函数特质粗俗被称为“甩掉”(effects)。
乍一听这可能有点奇怪,但请听我评释。你看,函数实质上有好多不同的“特质”,比如:
这个函数会不会触发 panic?
这个函数有固定的栈大小吗?
这个函数会实施到终局,如故会半途 yield / await(挂起)?
如果这是一个协程(coroutine),它的连接实施类型是什么?
这个函数是纯函数(pure)吗?也便是说,沟通的输入老是产生沟通的输出,而况莫得反作用。
这个函数会不会在半实在的库中(径直或障碍地)运行不安全的代码?
这个函数是否保证会圮绝?
等等。
一个函数的参数和复返类型其实仅仅这个函数的关系类型(associated types):
fn some_iter -> impl Iterator {vec![1,2,3].into_iter}
fn main {// Why doesn't this work already via FnOnce?let x: some_iter::Output = some_iter;}
公开这些属性绝顶有效。举例,Linux 内核但愿在编译时确保某些代码块长期不会触发 panic(轮番崩溃)。咫尺在 Rust 中这是不可能作念到的。但通过使用函数特质(function traits),咱们不错明确标识一个函数是否有可能触发 panic,或者明确它不会触发 panic:
#[disallow(Panic)] // Syntax TBD.fn some_fn { ... }
丝袜控而且如果函数作念了任何可能触发 panic 的操作(即使是递归地触发),编译器会抛出乌有。
实质上,编译器还是在某种进度上为函数完了了雷同 Fn、FnOnce 和 FnMut 的特质(traits)。但不知为何,这些特质绝顶简短。(为什么??)
我思要的是这样的东西:
/// Automatically implemented on all functions.trait Function {type Args,type Output,type Continuation, // Unit type for normal functions// ... and so on.
fn call_once(self, args: Self::Args) -> Self::Output;}
trait NoPanic {} // Marker trait, implemented automatically by the compiler.
/// Automatically implemented on all functions which don't recurse.trait KnownStackSize {const STACK_SIZE: usize,}
然后你不错编写如下代码:
fn some_iter -> impl Iterator {vec![1,2,3].into_iter;}
struct SomeWrapperStruct {iter: some_iter::Output, // In 2024 this is still impossible in stable rust.}
或者使用协程:
coroutine fn numbers -> impl Iterator {yield 1;yield 2;yield 3;}
coroutine fn double>(inner: I) -> impl Iterator {for x in inner {yield x * 2;}}
struct SomeStruct {// Suppose we want to store the iterator. We can name it directly:iterator: double::Continuation,}
或者,举个例子,接管一个函数参数,但条目该参数自己不会触发 panic:
fn foo(f: F)where F: NoPanic + FnOnce -> String{ ... }
编译时材干(Compile-time Capabilities)
大多数 Rust 面孔王人会引入渊博第三方库。其中大部分是微型的实用轮番库——比如 human-size crate,它用于将文献大小情势化为东说念主类易于交融的样式。绝顶棒!但厄运的是,这些微型库王人会增多供应链风险。任何一个库的作家王人有可能发布包含坏心代码的更新,可能加密锁定咱们的斟酌机或就业器,甚而暗暗将坏心代码镶嵌到咱们的二进制文献中。
我认为这个问题雷同于内存安全的问题。固然,偶然轮番员会编写不安全的内存代码,Rust 规范库中也充满了这样的代码。但 Rust 的 unsafe 要津字让建设者不错遴荐性地启用潜在不安全的功能。咱们只在必要时添加 unsafe 块。
咱们不错对特权函数调用(privileged function calls)作念雷同的事情——比如从文献系统或网罗中读取和写入数据。这些功能很有效,但也有潜在的危急。建设者应该主动列入白名单中允许调用这些函数的代码。
要完了这少量樱井莉亚电影,率先咱们需要给规范库中所