首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Rust 生态观察 | 9 月热点思考

Rust 生态观察 | 9 月热点思考

作者头像
张汉东
发布2023-10-06 12:40:59
发布2023-10-06 12:40:59
80600
代码可运行
举报
文章被收录于专栏:Rust 编程Rust 编程
运行总次数:0
代码可运行

如果您喜欢本文,请多多点赞转发,以及请我喝杯咖啡,这样可以帮助我加强写作动力。感谢您!

Reddit Rust 频道九月 Top 15 贴

Reddit 统计了九月 Top 15 的话题。本文是我对这十五篇帖子的内容的延伸性思考笔记

  1. RustRover 发布是喜是忧?Introducing RustRover – A Standalone Rust IDE by JetBrains[1] 🔥 782
  2. 微软 Azure 量子开发工具包用 Rust 重写,提速 100 倍 Microsoft rewrote Azure Quantum Development Kit (QDK) in Rust, now it is 100x faster, 100x smaller, and it runs in the browser![2] 🔥 466
  3. 异步 Rust 吐槽与进展 Stabilization PR for async fn in traits[3] 🔥 457
  4. 传说中的 ???? 操作符 The legendary ???? operator[4] 🔥 392
  5. InfluxDB 正式从 Go 切换到 Rust influxdb officially made the switch from Go => Rust[5] 🔥 369
  6. 我爱上了这个语言 I'm in love with this fucking language[6] 🔥 348
  7. 我再也不想回到Python了 I never want to return to Python[7] 🔥 292
  8. 你最喜欢的用Rust编写的(简单)开源工具是什么?What are your favorite (simple) Open Source tools written in Rust?[8] 🔥 291
  9. 语义违规的问题需要更好的工具 Semver violations are common, better tooling is the answer[9] 🔥 277
  10. 为什么 ring 不与Rust Crypto项目合作?Why doesn’t the ring project work together with the Rust Crypto project?[10] 🔥 271
  11. mrustc 的价值?mrustc now has (half of) a borrow checker[11] 🔥 265
  12. 改变Rust的规则: 关于线性类型的探讨 Changing the rules of Rust[12] 🔥 264
  13. 考虑使用 Cpp 而非 Rust ? Considering C++ over Rust[13] 🔥 253
  14. 下一代 Rust 借用检查器 Polonius Polonius revisited, part 1: the next generation of the Rust borrow checker[14] 🔥 252
  15. 当Zig超越Rust——内存高效的枚举数组 When Zig Outshines Rust - Memory Efficient Enum Arrays[15] 🔥 239

1. RustRover 发布是喜是忧?

众所周知,JetBrains 推出了 Rust 语言商业独立 IDE RustRover。这件事对 Rust 语言来说,算是一个里程碑。独立的商业 IDE 意味着 Rust 语言迈入了主流语言行列。这说明 JetBrains 应该有足够的理由和数据让他们相信 Rust 已经足够受欢迎,值得有一个全职开发团队支持一个独立的商业 IDE 开发。

“人们通常会问应该学习哪种语言。我总是会提出一个论点:“看看JetBrains是否为该语言提供了专用的IDE”。我认为JetBrains在预期语言的市场份额会增长时,会创建IDE而不是插件。最近的例子是Goland,自那以后,Go语言变得更加成熟,JetBrains的判断是正确的。总之,现在是学习Rust的时候了!

对于 Rust 语言来说,这是好事。但是,这件事在社区里也出现了一些反对的声音。因为 JetBrains 同时宣布将停止免费的插件版本的更新和维护。这让社区很多人认为这是从开源走向闭源。

VSCode 是开源的,JetBrains 是闭源的,但是两者的商业模式是完全不同的。VSCode 开源旨在向开发者推广 Azure 。而 JetBrains 是直接以软件交换金钱为业务的传统模式。

JetBrains 提供付费服务,意味着他们必须使其优于免费的替代品。付费本身是一种强大的激励机制,可以改进技术水平,从而为 Rust 开发者带来好处。好的工具可以极大地提升工作效率。

评论里还有人提到了 JetBrains 的俄罗斯“基因”。然而,JetBrains 成功地将大部分员工从俄罗斯搬迁出来。由于个人原因无法搬迁的人,不得不与他们分道扬镳。可以想象,搬迁800多人及其家人(还有宠物)是一项艰巨的任务。幸运的是,JetBrains 能够将人员分配到他们在欧洲的办公室,包括在阿姆斯特丹、慕尼黑和柏林的最大研发中心。还在塞浦路斯、塞尔维亚和亚美尼亚开设了新的办事处。从而免受其员工受战争影响。

目前 RustRover 还没有让很多 Rust 开发者满意,但既然 JetBrains 已经开了这个头,我想它应该会越来越好。

2.微软 Azure 量子开发工具包用 Rust 重写,提速 100 倍

微软将Azure Quantum Development Kit(QDK)改用Rust进行重写,现在它的速度提升了100倍,体积缩小了100倍,并且可以在浏览器中运行(基于 WebAssembly)!

“Quantum Development Kit (QDK) 是与 Azure Quantum 服务进行交互所需的 SDK。它内置于 Azure Quantum 门户,可在其中使用免费托管的 Jupyter Notebook 开发程序。还可以在计算机上本地安装 QDK,以使用自己的本地开发环境,并使用 Azure Quantum 服务联机和脱机工作。使用 , Quantum Development Kit可以生成在 Azure Quantum[16] 中的量子硬件上运行的程序。

QDK 包括量子编程语言 Q#,这是一种高级 开源 编程语言,可用于将工作重点放在算法和应用程序级别以创建量子程序。

QDK 支持 Q#、 Qiskit[17]Cirq[18] 进行量子计算,因此,如果你已经在使用其他开发语言,还可以在 Azure Quantum 上运行线路。

  • Rust用于产品的核心。这具有"一揽子"的好处,可以使用Cargo来管理依赖、构建、测试等。
  • Python,作为我们在QDK中构建和发布软件包,并在实际情况下在代码库中使用Python进行脚本任务的一部分。
  • JavaScript(包括TypeScript),我们正在构建一个VS Code扩展并编写一些Web集成代码。

对于这三种语言,QDK 中尽量减少依赖关系,几乎所有的依赖关系都可以在存储库根目录下的Cargo.toml和package.json文件中找到。

那么,Azure 量子开发包可以用来构建什么样的应用程序?能够破解RSA类型的算法吗?

没有,即使是顶级的量子计算机也没有类似的东西,更不用说免费的了。通常它们用于学生研究量子计算。算法开发和测试,模拟等。

“所以,各位的钱包还是安全的

3. 异步 Rust 吐槽与进展

最近关于异步的讨论出现了一些反对的声音:

  • Async Rust is a Bad Language[19] (原文已被作者删除)

我理解,这是刚开始使用 Rust 的新人对 异步 Rust 的一种吐槽,但没吐槽到点子上。被社区的人教育之后,知道自己错在哪里了。

async/await 只是语法糖,语法糖之下隐藏了 异步 Rust 的复杂性。这也许是那位新人面对 Async Rust 的困惑之处。因为想完全熟练掌握 异步 Rust ,就必须了解这语法糖背后的复杂性。

如果想就此指责 异步 Rust 的设计,那就大可不必。因为目前 Async Rust 的设计已经是这么多年讨论和实践验证后的最佳设计了。改进空间肯定很大,但是除非你能给出更好的设计并且容易落地,否则就免开尊口吧。

异步 Rust 的设计牺牲了抗阻塞能力,以换取可嵌入性(可在微控制器上运行,可作为库从任何语言调用)和非常高的性能。而 Go / Erlang 这种含有抢占式调度器的绿色线程语言可以防止阻塞,但会增加 CPU 开销。这种设计也造成了异步 Rust 应用的难点所在,因为在开发时你需要防止阻塞。

当前 Rust 的异步设计,也造成了另一个生态问题,就是 异步运行时的耦合。当前 tokio 已经成为大部分场景中异步运行时的首选,所以生态中很多相关的库都是基于 tokio 来实现,而无法与其他运行时兼容。

async_std 是另外一个异步运行时。它的想法是完全复制一个异步的标准库,但目前它受到了一些阻碍。完全复制标准库的异步版本可能不太现实。但目前也有很多第三方库依赖着它。

目前也有一些吐槽 tokio 的声音。

“比如:Rust异步编程的原罪是默认将其变为多线程。如果过早优化是万恶之源,那么这就是所有过早优化的母亲,它会给你的代码带来不祥的 Send + 'static ,甚至更糟的是 Send + Sync + 'static ,这将完全摧毁你写Rust的乐趣。— Maciej Hirsz[20]

吐槽背后的原因是 tokio 默认给使用者强加了一些设计,比如推荐使用多线程,使用 ArcMutex,这样会导致与编写异步代码无关的意外复杂性。

整个异步生态似乎已经被绑死在 tokio 上面,当然,异步生态还在不断前行与探索。还有其他异步运行时也值得关注:

  • smol[21] 一个小巧的异步运行时,易于理解。整个执行器的代码大约有1000行,生态系统的其他部分也同样小巧。
  • embassy[22],嵌入式系统的异步运行时,给嵌入式开发带来了创新,它可以平替 RTOS 。该运行时很可能是嵌入式异步的未来(当你不需要硬实时性时)。
  • glommio[23],一个基于io_uring构建的异步运行时,适用于I/O密集型工作负载,并采用每核心一个线程的模型。当然字节也开源了类似的基于 io_uring 的异步运行时 volo[24]

“一个忠告:新手应该谨慎使用异步。如果你不需要异步来提高性能,线程通常是更简单的选择。--- the Async Book[25]

无论如何,Rust 官方团队还在推动着 异步 Rust 迈向真正的零成本抽象。最近的稳定 PR 正在将 async fn 和 返回位置的 impl Trait 推向稳定。

代码语言:javascript
代码运行次数:0
运行
复制
// async fn in trait (AFIT)
trait Bar {
    async fn bar(self);
}

impl Bar for () {
    async fn bar(self) {}
}

// return-position impl Trait in trait (RPITIT)
trait Bar {
    fn bar(self) -> impl Send;
}

impl Bar for () {
    fn bar(self) -> impl Send {}
}

// async fn 魔法:
async fn foo() -> i32 { 100 }

// Equivalent to:
fn foo() -> impl Future<Output = i32> { async { 100 } }

async fn 稳定之后,现在异步代码中经常见的 #[async_trait] 就可以移除了。

4. 传说中的 ???? 操作符

https://github.com/nix-rust/nix/blob/master/src/mount/linux.rs#L127[26] 有下面这段代码:

代码语言:javascript
代码运行次数:0
运行
复制
    let res = with_opt_nix_path(source, |s| {
        target.with_nix_path(|t| {
            with_opt_nix_path(fstype, |ty| {
                with_opt_nix_path(data, |d| unsafe {
                    libc::mount(
                        s,
                        t.as_ptr(),
                        ty,
                        flags.bits(),
                        d as *const libc::c_void,
                    )
                })
            })
        })
    })????;

代码中因为 Rust 错误处理,出现了四个并排的 ? 操作符,整个代码看上去非常难以理解。这应该是为了解开 Result<Result<Result<Result<T, _>, _>, _>, _> 这样的嵌套 Result 类型。

Reddit 社区的人甚至提出 Rust 可以引入 ?+?*?{n,m}?^?$这样的操作符来解决此类问题。。。

也许我们真的需要 try { ... }

5. InfluxDB 正式从 Go 切换到 Rust

“是否一场清除 Go 代码运动似乎在悄悄打响?

前几天看到 envoy proxy 作者也是 bitdrift.io 的 CTO Matt 说从他们的技术栈里清除了最后一点 Go 代码。

今天看到 InfluxDB 已经删除了所有的Go代码,现在99.5%是 Rust!为此,InfluxDB的联合创始人兼首席技术官就此事现身说法:

  • 当我选择用Rust做v3的时候,我也认为我们最终会使用大量的C++代码。结果我们最终决定使用纯Rust语言的Apache Arrow DataFusion引擎。在过去的三年里,我们对其做出了重大贡献,我们的一位员工工程师Andrew Lamb,由于他在组织和编程方面的努力,现在成为了Arrow PMC的一员。
  • 为什么我们要进行重写?因为我们想要满足一些重要的需求,这些需求决定了我们必须重写数据库核心。只要我在Influx,这将是我们所需的最后一次重写。我绝对没有精力再来一次 ;)
  • 如果我再做一次,我会更渐进地用Rust替换现有系统的部分,但我们可能不会达到同样的结果。所以谁知道呢。

评论中另外一家公司也正在从 Go 迁移到 Rust 。

  • 我们正在将我们的技术栈迁移到Rust。包括从Golang迁移到Rust的进展。我们正在逐步按服务进行这个迁移。我们发现Rust的延迟更低,错误/缺陷更少。我们经常发现Golang中意外的空指针引用错误。我们在Golang代码库上一直很勤奋,但我们仍然看到我们的Rust部署取得了更好的结果。
  • 现实世界中Go与Rust的生产对比。我们有一个正在运行的应用程序,用于处理API调用。我们的Rust和Golang代码库都提供相同数量的流量。我们正在进行迁移阶段。以下是我们目前的结果:
    • 5% CPU 使用率
    • 0毫秒延迟“亚毫秒级”(p50)
    • 25% CPU 使用率
    • 5毫秒延迟(p50)
    • Golang
    • Rust

6. 我爱上了这门语言

一位 Reddit 用户,他在几年前尝试 Rust ,对 Rust 的感觉是:“什么狗屎玩意?”,然后就不再碰 Rust 了。

在过去的一年左右,他一直在深入学习C++、学习C语言、学习Crystal Lang(它的语法很像Ruby)。他开始对真正的计算机科学产生了浓厚的兴趣。在过去的一周里,他一直在尝试Rust,...

然后他说,他爱上了这门语言。

我想说,谁不是呢?评论区的一些回复:

你呢?

7. 我再也不想回到Python了

“一旦你开始使用静态类型,就再也回不去了。

Rust 为什么那么有魅力呢?自己去探索吧。

8. 你最喜欢的用Rust编写的(简单)开源工具是什么?

不出意外,这里是大家最喜欢的开源 Rust 工具列表:

  • starship[27] ,真正可定制的跨平台提示,适合任何 shell。
  • ruff[28] Python代码检查 lint。
  • polars[29] , 极速 DataFrame 分析,(几乎)已经准备好取代 pandas
  • typst[30] ,终于有了LaTeX的现代继任者,这对于排版师来说是个好消息
  • delta[31] ,一个用于git、diff和grep输出的语法高亮分页器
  • `atuin`[32],更好的shell历史记录工具
  • bat[33],更加人性化的 cat 替代品(语法高亮、自动分页等)。
  • `bottom`[34] , 一个 gotop 的更好的平替工具
  • `fd` [35], find 更好的 find 平替工具
  • `hyperfine`[36], ad hoc 基准测试
  • `ripgrep` [37],更好的grep
  • zoxide[38],更智能的 cd 命令
  • eza[39], 很棒的 ls 选择
  • Helix[40],类 vim 的现代化文本编辑器
  • Alacritty[41] ,终端模拟器,使用GPU加速
  • zellij[42], 是一个很酷的替代tmux的选择
  • mask[43],一个由简单的 markdown 文件定义的 CLI 任务运行器,代替 makefile
  • Zola[44], Cobalt[45],静态网站生成器
  • Minisign[46], Signify[47],签名工具
  • Gitoxide (git based VCS)[48], Pijul (New VCS)[49],Gitoxide(基于Git的版本控制系统),Pijul(新的版本控制系统)
  • Glide[50] 媒体播放器
  • Lemmy (Reddit Clone w/ Federation)[51], Plume (Blogging)[52],Lemmy(Reddit克隆版,带有联邦功能),Plume(博客平台)
  • [yazi](https://github.com/sxyazi/yazi[53]) ,用Rust编写的快速终端文件管理器,基于异步I/O
  • typos[54],快速检查源代码中的拼写错误,可以修复变量名称中的拼写错误,还有一个与CI集成的优秀的GitHub操作
  • hyperlink[55],检查网站是否有损坏的链接和损坏的锚链接,还可以与CI集成
  • feroxbuster[56],使用暴力破解和字典列表的组合来搜索目标目录中的未链接内容。这些资源可能存储有关Web应用程序和操作系统的敏感信息,例如源代码、凭据、内部网络地址等等...
  • tokei[57] ,提供目录中每个文件类型的详细代码行数/注释行数/空行数
  • RustQuant[58],为量化交易而生

欢迎补充。这里并没有列出全部。

9. 语义违规的问题需要更好的工具

SemVer(语义版本控制)是一个版本号命名规范,旨在使得版本号的分配和增加更加清晰和预测。它遵循的格式是MAJOR.MINOR.PATCH,其中:

  • MAJOR:大版本号,当你做了不兼容的API更改时,增加。
  • MINOR:小版本号,当你添加了向后兼容的新功能时,增加。
  • PATCH:补丁版本号,当你做了向后兼容的错误修复时,增加。

SemVer 违规(Semver violations)通常指的是软件库或应用不遵守这些规则的情况。例如:

  1. 非向后兼容的更改:如果一个库在不更改主版本号的情况下引入了破坏向后兼容性的更改,这会是一个 SemVer 违规。
  2. 未适当增加版本号:例如,如果一个库添加了新功能但未增加小版本号,或修复了错误但未增加补丁版本号,这也会是一个 SemVer 违规。

SemVer 违规可能会导致依赖该库的其他软件出现问题,因为它们可能期望某些功能或API保持不变,但实际上已经发生了变化。这可能会导致错误、程序崩溃或其他不可预见的问题。遵守 SemVer 规则可以帮助开发人员更好地理解库或应用的更改,并更好地管理他们的依赖关系。

语义化版本(semver)的错误是很常见的。即使是由经验丰富的维护者精心开发的项目也会发生这种情况。维护者并不应受到责备,改进的工具是我们前进的最佳途径。 cargo-semver-checks 是改进工具的一部分,因为它发现了我们在这里报告的每一个语义化版本违规。

对维护人员要求完美是幼稚、不合理和不公平的。每当勤奋、有责任心、出于善意的人犯错时,失败并不在于人,而在于系统。

“Rust 语言的哲学:人的错误无法避免, 用更好的工具来解决人的错误。

以下是对原文的 GPT 总结:

Tomasz Nowak 和 Predrag Gruevski 分析了Rust中的semver(语义版本)遵从性,发现即使在最受欢迎的crates中,偶尔也会出现 semver 违规。这些违规并非人为错误,而是工具的不足。文章通过使用 cargo-semver-checks工具对 crates.io 上下载量最高的 1000 个库进行检查,得到了大量有价值的数据。结果显示,semver 违规是很常见的,即使是由经验丰富的维护者运行的最仔细开发的项目中也会发生。维护者并不应该受到责备,改进工具是我们前进的最佳方式。

三个引人深思的问题或见解:

  1. 工具还是人的问题? 虽然semver违规是常见的,但这并不是维护者的错。这是工具的失败,而不是人为的。我们应该如何改进现有的工具来避免这些违规?
  2. semver违规的常见来源是什么? 文章提到,最常见的semver违规来源包括对详尽类型的更改,例如向现有枚举添加新变量,或向只包含公共字段的现有结构添加新字段。如何确保在进行这些更改时遵循semver规则?
  3. 如何更好地利用cargo-semver-checks工具? cargo-semver-checks工具在检测semver违规方面非常有效。那么,如何确保更多的Rust开发者知道并使用这个工具来避免semver违规?

10. 为什么 ring 不与Rust Crypto项目合作?

ring[59] 是比较知名的加密库,还有另外一个知名的加密库 Rust Crypto [60]。社区中的很多人都好奇为什么 ring 不与Rust Crypto项目合作?

人们之所以问这个问题,是因为 ring 和 Rust Crypto 实现了类似的功能,而 Rust Crypto 是 100% Rust 编写的,而 ring 则是 Rust、C 和汇编语言的混合。为什么这些东西存在并行而不是合作?

最近 ring 作者 Brian 发文希望与 Rust Crypto 合作,以便有一个单一的地方来存放所有由 ring 实现的纯 Rust 编写的基础密码学代码。而 RustCrypto 的负责人也非常乐意合作。

ring 作者对这次合作有一个愿望:我希望看到Ring继承的 Unsafe 汇编语言在性能方面被Rust Crypto的纯 Rust 实现所超越。对此,RustCrypto 负责人给出了回应:

“就个人而言,我对消除 unsafe 并不是那么狂热。我认为使用内部函数和 asm! 对于高效和正确实现加密算法至关重要。不幸的是,编译器可能会非常古怪和脆弱,正如这个问题所示(它们可能存在错误编译的漏洞 1[61], 2[62])。就性能而言,手写汇编通常也胜过“软”(即目标无关)的实现。虽然有一些新的发展可以帮助减少基于内部函数的代码中的 unsafe 数量,但我怀疑它会完全没有 unsafe 。显然,任何 unsafe 代码都应该受到严格审查和良好隔离(就像我们在 `block-buffer`[63]`inout`[64]创建的情况下一样)。幸运的是,我们得到了越来越多来自第三方审计和依赖我们创建的公司(如谷歌)的内部审查的关注。我相信我们能够在不影响性能的情况下消除绝大部分 unsafe 。但是,我强调在 ring 中消除 unsafe 并不是对Rust Crypto使用 unsafe 的批评。“

“我认为在密码编码、内部函数和低级优化(例如在 unsafe 包中)中使用 asm! 是可以的。但我相信我们应该努力减少对C库的依赖(除了像 libc 这样的东西,这通常是与操作系统和其他系统通信的唯一稳定方式),以及由外部编译器编译的汇编文件。即使在安全方面之外,使用这些方法也会导致构建人性化和可移植性方面的各种问题,正如ring所清楚展示的那样。在RustCrypto中,我们有一个实验性的asm-hashes存储库,其中的crate使用 cc 来构建 .S 文件。但是这种方法存在一些问题,因此我们正在逐步弃用这些crate,并将它们替换为直接在哈希crate内部使用 asm! 后端。”

看来如何平衡 Unsafe 代码,在这个领域还是充满了挑战。

11.mrustc 的价值?

mrustc[65] 是 Cpp 实现的 Rust 编译器,旨在创建一个用于编译 rustc 的Rust编译器,而无需现有的 rustc 二进制文件。它能够从源代码编译出Rustc 1.19、1.29、1.39和1.54版本。但最终 mrustc 可能会成为一个完全独立的 Rust 编译器重新实现版本。

我很好奇,mrustc 可以用在哪些场景呢?我直接用 rustc 不行吗?作者在 reddit 评论中回答了该问题。

官方的Rust编译器本身就是用Rust编写的。所以要能够构建它,你需要已经能够以某种方式编译Rust代码。这是一个先有鸡还是先有蛋的问题。mrustc 解决了这个问题,因为它是用C++编写的。所以你可以拥有一个干净的引导链:汇编 -> 最小的C编译器 -> 正确的C编译器 -> C++编译器 -> mrustc -> 官方Rust编译器。

希望能够在没有预先存在的 Rust 编译器的情况下进行构建的主要原因是,希望在构建整个链时无需依赖于不可审计的二进制文件(或者只希望信任一个二进制文件,例如 C 编译器)。有一篇半著名的论文《对信任的思考》[66]提出了一种理论攻击,即对编译器进行修补,使其在某些进程(例如ssh服务器)中添加后门,并能够检测自身的源代码,并将这种逻辑复制到新构建的编译器中。从而使得这种妥协能够在尝试编译“干净”的编译器时存活下来。

类似的攻击事件已经发生过,这里只找到一个[例子](https://nakedsecurity.sophos.com/2009/08/18/compileavirus/[67])。随着 Rust 语言成为基础设施主流语言,这种攻击手段将变得越来越有价值。基础设施的一个漏洞可能会影响数百万用户的人,就好像最近被披露的两个 0Day 漏洞,直接影响 Chrome 和 Firefox 所有用户。

这么看来,mrustc 的价值还是很大的。

那么作者为什么选择 C++ 来开发 mrustc 呢?作者说 Cpp 是他的日常工作语言,而且非常通用。mrustc 最近已经支持了(一半)借用检查器,目前工作还在继续。

12.改变 Rust 的规则:关于线性类型的探讨

最近 Rust 社区多了线性类型和并发性的一些讨论。我们来了解下什么是线性类型?

来自 GPT-4 的解释

“Prompt: 什么是 linear types? 线性类型和仿射类型区别? Rust 所有权是哪种类型?

线性类型(Linear Types)是类型系统中的一个概念,用于确保某个值在其生命周期中只被使用一次。这种“一次性使用”的特性对于某些应用场景,如资源管理和并发编程,非常有用。

以下是线性类型的一些关键点:

  1. 资源管理:线性类型可以确保资源(如文件句柄、网络连接等)在使用后被正确释放,从而避免资源泄露。
  2. 不可变性:由于线性类型的值只能使用一次,这意味着它们在使用后不能被修改或再次使用,从而实现了不可变性。
  3. 并发编程:线性类型可以帮助避免并发编程中的某些问题,如数据竞争和死锁,因为它们确保一个资源在给定时刻只被一个线程使用。
  4. 函数效果:线性类型可以用来表示函数的效果。例如,一个函数可能会消耗一个线性类型的值并产生一个新的线性类型的值,这可以用来表示某种副作用。
  5. 内存管理:在某些编程语言中,线性类型可以用于确保内存被正确管理,例如确保数据结构在不再需要时被正确地回收。

线性类型和仿射类型(Affine Types)都是类型系统中的概念,用于描述值的使用模式和约束。尽管它们在某些方面有所相似,但它们之间存在明确的区别:

  1. 线性类型 (Linear Types):
    • 线性类型要求值在其生命周期中恰好被使用一次
    • 这意味着一旦线性类型的值被使用,它就不能再次被引用或使用。
    • 线性类型在资源管理、并发编程和某些函数效果中非常有用,因为它们确保资源在使用后被正确释放或转移。
  2. 仿射类型 (Affine Types):
    • 仿射类型要求值在其生命周期中最多被使用一次
    • 这意味着仿射类型的值可以被使用,也可以不被使用,但绝对不能被使用多次。
    • 仿射类型比线性类型更加宽松,因为它允许值被丢弃,但不允许值被多次使用。

简而言之,线性类型确保值恰好被使用一次,而仿射类型确保值最多被使用一次。这两种类型都可以帮助避免资源泄露、数据竞争和其他并发或资源管理问题,但它们的使用约束和应用场景有所不同。

Rust 的所有权系统最接近于仿射类型(Affine Types)。

在 Rust 中,每个值都有一个称为其“所有者”的变量。一次只能有一个所有者,这确保了在任何给定时刻,只有一个变量可以对值进行修改。当所有者超出作用域时,值将被丢弃。但是,Rust 允许你将值的所有权转移给另一个变量(称为移动),在这种情况下,原始变量将不再是值的所有者并且不能再次使用该值。这确保了每个值在其生命周期中最多只有一个所有者,这与仿射类型的定义相符。

值得注意的是,Rust 还提供了引用和借用的概念,允许多个变量同时访问同一个值,但这些引用必须遵循特定的规则,以确保内存安全和数据竞争的自由。

总的来说,尽管 Rust 的所有权系统具有仿射类型的特性,但它还包括其他概念和规则,如借用检查器,使其成为一个独特和强大的系统,专为内存安全和并发编程设计。

线性类型

Rust 中引入线性类型,会有很多好处。比如保证析构函数将被调用,以便可以依靠它们来确保程序的正确性。所以 Rust 线性类型也可以被定义为保证其析构函数将被调用的类型

Yoshua Wuyts 在三月份,提供了一个[关于"线性类型"的最小可行性设计](https://blog.yoshuawuyts.com/linear-types-one-pager/ "关于"线性类型"的最小可行性设计") 。

该设计中引入 Leak trait,目的是为了提供一个机制,使得Rust的类型系统可以明确地处理线性类型,同时还保持与现有的非线性类型的兼容性。这种设计允许开发者在需要的地方使用线性类型,而在其他地方继续使用传统的Rust类型。

以下是关于 Leak trait的主要点:

  1. 区分线性和非线性类型:通过引入 Leak trait,可以明确标记哪些类型是线性的(即它们的析构函数必须被调用)和哪些类型可以被安全地泄露。
  2. 隐式边界:所有的边界默认都带有一个隐式的+ Leak边界,就像默认的+ Sized边界一样。这意味着,除非明确指定,否则所有类型都被认为是可以安全泄露的。
  3. 选择性地支持线性:函数可以选择性地支持线性类型,通过接受+ ?Leak边界。这意味着这些函数可以处理线性类型,但也可以处理非线性类型。
  4. 标记线性类型:要将某个类型标记为线性类型,可以实现!Leak或在字段中放置一个PhantomLeak类型。
  5. 与某些API的交互:某些函数,如mem::forget,总是需要+ Leak边界,因为它们允许值被安全地泄露。线性类型不能被安全地传递给这些API。

Rust 有两种方式可以添加这个新 trait:

  • auto trait,可以添加一个新的自动特性,比如 SendSync
  • ?Trait ,可以添加一个新的“?Leak”,例如 Sized。默认是所有类型都可以安全 Leak , mem::forget 也不需要添加新的 Leak trait,只有在要编写一个接受线性类型的泛型函数,你必须写一个 ?Leak 的限制。
代码语言:javascript
代码运行次数:0
运行
复制
 <T>         
 <T: Leak>   // needs leak
 <T: !Leak>  // needs not leak
 <T: ?Leak>  // don't care about leak

无论哪种方式,都对向后兼容提出了挑战。而 Rust 语言向后兼容是最重要的保证。在最近 GOSIM Rust 语言论坛上面 Rust 语言共同负责人 Josh 也说到即便到 2051 年,Rust 语言代码也是向后兼容的。

Rust Project 决定在 2024 Edition 中添加 Leak trait。引入 Leak trait 有助于简化结构化并发的 API 和 增强其安全性,许多系统 API 的安全封装可能会更容易。但是这个 Leak trait 很可能带来破坏性更改,目前官方团队还没有什么解法。

withoutboats 坦言,如果回到 2015 年,他会强烈要求 Rust 团队在 1.0 时增加这个 trait。

话说回来,即便 withoutboats 回到 2015 年,他也不一定能改变什么。因为 Rust 团队中不存在 BDFL。

“善良的终身独裁者(BDFL, Benevolent dictator for life)是一个称号,赋予少数开源软件开发领导者,通常是项目创始人,在社区内争议或争论中保留最终决定权。

很显然,Rust 的创始人 Graydon 并非 BDFL 。因为在Graydon 的博客[68]上披露了他对现在 Rust 特性有很多不喜欢的设计。比如异步 Rust ,他想要的其实是类似于 Go 的绿色线程。他甚至也不喜欢 Rust 的 trait 机制。也许我们该庆幸,Graydon 不是 BDFL , Rust 团队中没有 BDFL。

回到 2015 年,那么 withoutboats 就能把 Leak trait 加进去吗?不一定。

13. 考虑使用 Cpp 而非 Rust

这个话题我之前发过文章介绍了,可以移步:Reddit 观察:你何时会考虑使用 Cpp 而非 Rust ?

14. 下一代 Rust 借用检查器 Polonius

polonius[69] 是 Rust 团队正在进行的下一代 Rust 借用检查器。目前官方正在努力解决最后几个性能问题,并考虑用这个新的重新实现来替换现有的借用检查器。这项工作对于 Rust 用户来说基本是无感的。

“Polonius 这个名字来自于莎士比亚的《哈姆雷特》中人物波洛尼厄斯(Polonius)的名言:“不借钱,也不借给别人。”

Polonius 相比于目前的借用检查器的区别在于改变了生命周期分析的方式。NLL 将 'r 视为由一组程序点组成的生命周期,Polonius 中则将 'r 称为包含一组“借贷”(loans)的起源。换句话说,Polonius 不再追踪引用将被使用的代码部分,而是追踪引用可能来自的位置。

代码语言:javascript
代码运行次数:0
运行
复制
let mut x = 22;
let mut y = 44;
let mut p: &'0 u32 = &x; // 借用 `x`,借贷标记为 L0
y += 1;                  // (A) Mutate `y` -- is this ok?
let mut q: &'1 u32 = &y; // 借用 `y`,借贷标记为 L1
if something() {
    p = q;               // `p` 现在指向 `y`
    x += 1;              // (B) 修改 `x` -- is this ok?
} else {
    y += 1;              // (C) 修改 `y` -- is this ok?
}
y += 1;                  // (D) 修改 `y` -- is this ok?
read_value(p);           // 再次使用 `p` 

用不同的借用检查工具检查后得到下面结果:

代码位置

当前借用检查器

Polonius

MiniRust

A

✔️

✔️

OK

B

✔️

✔️

OK

C

✔️

OK

D

Can cause UB, if true branch is taken

minirust[70] 是官方团队成员 RalfJung 开发的用于描述 Rust 语义规范的类型 MIR 语言。它也包含了类型检查和借用检查等功能。

分析:

  1. 借用和生命周期: 在这个示例中,有两个借用:L0和L1,分别代表对xy的借用。这两个借用都有关联的生命周期:'0'1
  2. 活跃借贷: 当我们在代码中创建一个引用(例如&x),我们实际上是在创建一个借贷(Loan)。这个借贷在某些代码段中是活跃的,这意味着我们不能修改被借用的值。
  3. Polonius的分析: Polonius的关键思想是改变我们进行分析的方式。与其跟踪引用将在程序的哪些部分被使用,不如跟踪引用可能来自的地方。这种方法更直观,也更容易理解。
  4. 错误分析: 在上述示例中,Rust的当前借用检查器会报告两个错误(C和D)。但如果使用MiniRust运行此示例,只有D实际上会导致未定义的行为。这是因为在C点,我们修改了y,但唯一引用y的变量是q,它将不再被使用。当前的借用检查器报告错误是因为它过于保守。而Polonius则正确地处理了这种情况。

活跃借贷的计算和重新分配是Polonius分析方法的核心部分。以下是详细的解释:

活跃借贷的计算

  1. 定义:活跃借贷是指在某个特定的程序点,一个变量持有的引用(或借贷)仍然可以在后续的代码中被访问或使用。
  2. 计算方法
    • 首先,我们需要知道在给定的程序点哪些变量是活跃的。这通常是通过数据流分析来完成的。
    • 对于每一个活跃的变量,我们查看它可能引用的所有借贷。这意味着,如果一个变量可能引用多个不同的借贷,那么所有这些借贷都被认为是活跃的。
    • 结果是在给定的程序点所有可能的活跃借贷的集合。
  3. 例子:在文章中的示例代码中,当我们到达点(B)时,变量p是活跃的,因为它在后面被用于read_value(p)。由于p可能引用L0或L1(取决于something()的结果),所以L0和L1都被认为是活跃的。

重新分配的影响

  1. 定义:重新分配是指改变一个变量的值,例如通过赋值操作。
  2. 影响
    • 当一个变量被重新分配时,它之前持有的所有引用(或借贷)都不再被认为是活跃的,因为这些引用已经被新值替代。
    • 这意味着,重新分配可以“结束”一个或多个活跃借贷,即使这些借贷在重新分配之前是活跃的。
  3. 例子:在文章中的示例代码中,当执行p = q;时,变量p被重新分配。这意味着,之前p持有的L0引用不再活跃,因为它已经被L1替代。

总的来说,活跃借贷的计算是确定在给定程序点哪些引用仍然有效的关键,而重新分配的影响则是确定哪些引用不再有效的关键。这两个概念共同为Polonius 提供了一个更准确和直观的方法来分析Rust代码中的借用和生命周期。

Polonius 也正在引入流敏感(Flow-sensitive)分析来提升精准度。流敏感的类型检查考虑了代码的执行顺序。这意味着它会根据代码的实际执行路径来检查类型,而不是简单地检查每一行代码。这种方法可以更准确地捕获潜在的类型错误,特别是在有条件语句或循环的代码中。

15.当 Zig 超越 Rust——内存高效的枚举数组

在 Rust 中,变体大小不同的枚举(或标记联合)容易导致严重的内存碎片化。因为需要内存对齐,所以要分配足够的数据来容纳最大的变体。

比如下面这个枚举:

代码语言:javascript
代码运行次数:0
运行
复制
pub enum Foo { 
  A(u8), 
  B(u16),
  C(u32),
  D(u64),
}

当将大量这样对枚举存到 Vec 或 HashMap 中时,会带来很大的麻烦。

以一个简单的例子来说明一个有3个变量的枚举类型,成员大小分别为8、16和32位。将它们存储在一个普通的Vec中将会是这样的:

为了降低内存碎片的一个优化策略就是标记索引, 比如许多运行时实现了标记指针来避免空间开销。

标记索引(Tagged Index)

“本部分为GPT-4 创作。

“Prompt: 标记索引如何解决内存碎片化?

标记索引(Tagged Index)是一种优化技术,用于解决内存碎片化问题,特别是在处理不同大小的枚举变体时。这种技术的核心思想是使用一个小的标记(tag)来表示枚举的当前变体,而不是为每个可能的变体分配最大的空间。

  1. 基本概念
    • 在传统的枚举表示中,为了确保可以存储任何变体,每个枚举值都会分配足够的空间来容纳最大的变体。这导致了内存浪费和碎片化。
    • 标记索引的方法是将枚举的数据和标记分开。数据存储在一个紧凑的、连续的内存区域中,而标记则存储在另一个区域中。
  2. 如何工作
    • 对于每个枚举值,其实际数据存储在一个紧凑的数组或向量中,而标记则存储在另一个数组中。
    • 标记用于确定当前枚举值的变体,从而知道如何解释存储在数据数组中的值。
    • 由于每个标记的大小都是固定的,所以标记数组的大小是固定的。数据数组的大小则取决于实际存储的数据。
  3. 优势
    • 减少内存浪费:由于不再为每个枚举值分配最大的空间,所以内存使用更为高效。
    • 提高缓存效率:数据存储得更紧凑,有助于提高缓存的命中率。
    • 灵活性:可以根据需要调整标记的大小和表示,以适应不同的场景。
  4. 在Rust中的应用
    • Rust的编译器和其他高性能代码中经常使用标记索引技术。例如,`tagged_index crate`[71]就是Rust编译器中使用的一个库,它提供了标记索引的实现。
  5. 与其他技术的比较
    • 标记索引是解决内存碎片化问题的众多方法之一。其他方法还包括结构体的数组(SoA)转换和使用特定的数据结构来存储枚举值。

总的来说,标记索引是一种有效的技术,可以显著减少内存碎片化,特别是在处理具有不同大小变体的枚举时。这种技术在高性能编程中尤为重要,因为它可以提高内存使用效率并减少缓存未命中的次数。

Zig 超越 Rust 的地方

有一种更好的优化内存碎片的方法是 SOA 转换。

结构体的数组(Array of Structures, AoS)和结构体数组(Structure of Arrays, SoA)是两种常见的数据布局策略,它们在内存布局、访问模式和性能优化方面有着根本的区别。在某些情况下,从AoS转换为SoA可以带来显著的性能提升。

Rust 也有一个第三方库来完成这种转换 soa-derive[72]

代码语言:javascript
代码运行次数:0
运行
复制
#[derive(StructOfArray)]
pub struct Cheese {
    pub smell: f64,
    pub color: (f64, f64, f64),
    pub with_mushrooms: bool,
    pub name: String,
}

转换为

代码语言:javascript
代码运行次数:0
运行
复制
pub struct CheeseVec {
    pub smell: Vec<f64>,
    pub color: Vec<(f64, f64, f64)>,
    pub with_mushrooms: Vec<bool>,
    pub name: Vec<String>,
}

SOA 转换的好处有:

  • 缓存友好:当处理大量数据时,SoA布局可以更好地利用CPU缓存。如果只需要处理结构体的一个或几个字段,SoA布局可以确保这些字段连续地存储在内存中,从而提高缓存的命中率。
  • 并行处理:SoA布局更容易进行并行处理,因为可以独立地处理每个数组。
  • 数据压缩:在某些情况下,SoA布局可以更有效地压缩数据,因为相似的数据值存储在一起。

SoA布局特别适用于以下场景:

  • 图形处理:在图形处理中,经常需要处理大量的顶点和像素数据。SoA布局可以提高数据处理的速度和效率。
  • 物理模拟:在物理模拟中,SoA布局可以提高对大量粒子或对象的处理速度。
  • 数据库和数据处理:在处理大量结构化数据时,SoA布局可以提高查询和处理的速度。

那么回到枚举中,采用 SOA 转换的思想,将枚举判别式和变体值分别存储在两个独立的分配中。为了真正消除值中的碎片化,我们可以为每个变体创建一个Vec。

这个转换在 Rust 中只可以依赖于过程宏来实现。

在 Zig 中创建这样的数据结构非常简单,依赖于 Zig 分阶段编译的特性。但是在Rust中使用过程宏创建这些示例基本上是不可能的 。原因是过程宏无法访问类型信息,如大小或对齐方式。虽然你可以使用过程宏生成一个计算特定枚举的簇的 const fn,但是这个函数不能用于指定泛型类型的数组长度。

在 Rust 中编写非常高效的通用数据结构并不总是容易的 。在某些情况下,它们会带来许多意外的复杂性,而在其他情况下,它们基本上是不可能实现的。

Zig 分阶段编译介绍

分阶段编译,更通用的一个术语是多阶段(multi stage)编程。

一般而言,编译过程被划分为一系列(实际上是一个有向无环图)的编译阶段,每个阶段生成的代码被下一个阶段使用,而且每个阶段都是有效的代码并且经过了正确的类型检查。这就允许开发者编写基本上是类型安全的宏,并且可以访问部分编译程序的能力,这也是分阶段编译与类似 Lisp 宏的东西之间的区别所在。

Zig 的分阶段编译(Staged Compilation)是 Zig 编程语言中的一个核心特性,它允许在编译时执行代码并生成代码。这种能力使得 Zig 可以在编译时进行各种计算、代码生成和优化,从而为开发者提供了极大的灵活性和控制力。

以下是Zig的分阶段编译的一些关键点:

  1. comptime:Zig中的 comptime 关键字表示在编译时执行某段代码。这意味着你可以在编译时进行计算、决策和代码生成,而不是在运行时。
  2. 类型和代码生成:通过分阶段编译,Zig 可以在编译时生成类型和代码。这为泛型编程、元编程和代码优化提供了强大的工具。
  3. 条件编译:与其他语言中的预处理器宏不同,Zig 的 comptime 允许你在编译时进行复杂的条件判断,从而决定是否包含或排除某些代码。
  4. 性能优化:由于可以在编译时进行各种计算和优化,Zig 的分阶段编译可以帮助生成更高效的代码。
  5. 减少运行时开销:通过在编译时执行更多的工作,Zig 可以减少运行时的开销,从而提高程序的性能。
  6. 灵活的错误处理:Zig 允许在编译时检查错误条件并生成适当的错误消息,这为错误处理提供了更多的灵活性。总的来说,Zig 的分阶段编译是其语言设计中的一个核心特性,它为开发者提供了强大的工具来生成高效、优化和定制的代码。这种在编译时执行代码的能力使 Zig 在性能、灵活性和控制方面都具有显著的优势。

反观 Rust 语言,要实现编译期反射还需要一段路要走啊!

参考资料

[1]

Introducing RustRover – A Standalone Rust IDE by JetBrains: https://reddit.com/r/rust/comments/16hiw6o/introducing_rustrover_a_standalone_rust_ide_by/

[2]

Microsoft rewrote Azure Quantum Development Kit (QDK) in Rust, now it is 100x faster, 100x smaller, and it runs in the browser!: https://reddit.com/r/rust/comments/16p86ww/microsoft_rewrote_azure_quantum_development_kit/

[3]

Stabilization PR for async fn in traits: https://reddit.com/r/rust/comments/16hv2i4/stabilization_pr_for_async_fn_in_traits/

[4]

The legendary ???? operator: https://reddit.com/r/rust/comments/16t8tap/the_legendary_operator/

[5]

influxdb officially made the switch from Go => Rust: https://reddit.com/r/rust/comments/16v13l5/influxdb_officially_made_the_switch_from_go_rust/

[6]

I'm in love with this fucking language: https://reddit.com/r/rust/comments/16jz0yz/im_in_love_with_this_fucking_language/

[7]

I never want to return to Python: https://reddit.com/r/rust/comments/16mv8bb/i_never_want_to_return_to_python/

[8]

What are your favorite (simple) Open Source tools written in Rust?: https://reddit.com/r/rust/comments/16g38gp/what_are_your_favorite_simple_open_source_tools/

[9]

Semver violations are common, better tooling is the answer: https://reddit.com/r/rust/comments/16cj1mo/semver_violations_are_common_better_tooling_is/

[10]

Why doesn’t the ring project work together with the Rust Crypto project?: https://reddit.com/r/rust/comments/16soday/why_doesnt_the_ring_project_work_together_with/

[11]

mrustc now has (half of) a borrow checker: https://reddit.com/r/rust/comments/168qvrt/mrustc_now_has_half_of_a_borrow_checker/

[12]

Changing the rules of Rust: https://reddit.com/r/rust/comments/16kzuvz/changing_the_rules_of_rust/

[13]

Considering C++ over Rust: https://reddit.com/r/rust/comments/16bkx6b/considering_c_over_rust/

[14]

Polonius revisited, part 1: the next generation of the Rust borrow checker: https://reddit.com/r/rust/comments/16pld9h/polonius_revisited_part_1_the_next_generation_of/

[15]

When Zig Outshines Rust - Memory Efficient Enum Arrays: https://reddit.com/r/rust/comments/16ltlsv/when_zig_outshines_rust_memory_efficient_enum/

[16]

Azure Quantum: https://learn.microsoft.com/zh-cn/azure/quantum/overview-azure-quantum

[17]

Qiskit: https://learn.microsoft.com/zh-cn/azure/quantum/quickstart-microsoft-qiskit-portal

[18]

Cirq: https://learn.microsoft.com/zh-cn/azure/quantum/quickstart-microsoft-cirq-portal

[19]

Async Rust is a Bad Language: https://www.reddit.com/r/rust/comments/16dk9ya/async_rust_is_a_bad_language/

[20]

Maciej Hirsz: https://maciej.codes/2022-06-09-local-async.html

[21]

smol: https://github.com/smol-rs/smol

[22]

embassy: https://github.com/embassy-rs/embassy

[23]

glommio: https://github.com/DataDog/glommio

[24]

volo: github.com/cloudwego/volo

[25]

the Async Book: https://rust-lang.github.io/async-book/01_getting_started/02_why_async.html#async-vs-threads-in-rust

[26]

https://github.com/nix-rust/nix/blob/master/src/mount/linux.rs#L127: https://github.com/nix-rust/nix/blob/master/src/mount/linux.rs#L127

[27]

starship: https://starship.rs/

[28]

ruff: https://github.com/astral-sh/ruff

[29]

polars: https://www.pola.rs/

[30]

typst: https://typst.app/

[31]

delta: https://dandavison.github.io/delta/

[32]

atuin: https://github.com/atuinsh/atuin

[33]

bat: https://github.com/sharkdp/bat

[34]

bottom: https://crates.io/crates/bottom

[35]

fd : https://github.com/sharkdp/fd

[36]

hyperfine: https://github.com/sharkdp/hyperfine

[37]

ripgrep : https://github.com/BurntSushi/ripgrep

[38]

zoxide: https://github.com/ajeetdsouza/zoxide

[39]

eza: https://github.com/eza-community/eza

[40]

Helix: https://helix-editor.com/

[41]

Alacritty: https://github.com/alacritty/alacritty

[42]

zellij: https://github.com/zellij-org/zellij

[43]

mask: https://github.com/jacobdeichert/mask

[44]

Zola: https://github.com/getzola/zola

[45]

Cobalt: https://github.com/cobalt-org/cobalt.rs

[46]

Minisign: https://github.com/jedisct1/rust-minisign

[47]

Signify: https://github.com/badboy/signify-rs

[48]

Gitoxide (git based VCS): https://github.com/Byron/gitoxide

[49]

Pijul (New VCS): https://nest.pijul.com/pijul/pijul

[50]

Glide: https://github.com/philn/glide

[51]

Lemmy (Reddit Clone w/ Federation): https://github.com/LemmyNet/lemmy

[52]

Plume (Blogging): https://github.com/Plume-org/Plume

[53]

yazi: https://github.com/sxyazi/yazi

[54]

typos: https://github.com/crate-ci/typos

[55]

hyperlink: https://github.com/untitaker/hyperlink

[56]

feroxbuster: https://github.com/epi052/feroxbuster

[57]

tokei: https://github.com/XAMPPRocky/tokei

[58]

RustQuant: https://github.com/avhz/RustQuant

[59]

ring: https://github.com/briansmith/ring

[60]

Rust Crypto : https://github.com/RustCrypto

[61]

1: https://github.com/rust-lang/rust/issues/101346

[62]

2: https://github.com/rust-lang/rust/issues/63791

[63]

block-buffer: https://docs.rs/block-buffer

[64]

inout: https://docs.rs/inout

[65]

mrustc: https://github.com/thepowersgang/mrustc

[66]

《对信任的思考》: https://www.cs.cmu.edu/~rdriley/487/papers/Thompson_1984_ReflectionsonTrustingTrust.pdf

[67]

例子: https://nakedsecurity.sophos.com/2009/08/18/compileavirus/

[68]

Graydon 的博客: https://graydon2.dreamwidth.org/307291.html

[69]

polonius: https://github.com/rust-lang/polonius/

[70]

minirust: https://github.com/minirust/minirust

[71]

tagged_index crate: https://doc.rust-lang.org/stable/nightly-rustc/rustc_data_structures/tagged_ptr/index.html

[72]

soa-derive: https://github.com/lumol-org/soa-derive

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-10-02 17:24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 觉学社 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Reddit Rust 频道九月 Top 15 贴
  • 1. RustRover 发布是喜是忧?
  • 2.微软 Azure 量子开发工具包用 Rust 重写,提速 100 倍
  • 3. 异步 Rust 吐槽与进展
  • 4. 传说中的 ???? 操作符
  • 5. InfluxDB 正式从 Go 切换到 Rust
  • 6. 我爱上了这门语言
  • 7. 我再也不想回到Python了
  • 8. 你最喜欢的用Rust编写的(简单)开源工具是什么?
  • 9. 语义违规的问题需要更好的工具
  • 10. 为什么 ring 不与Rust Crypto项目合作?
  • 11.mrustc 的价值?
  • 12.改变 Rust 的规则:关于线性类型的探讨
    • 来自 GPT-4 的解释
    • 线性类型
  • 13. 考虑使用 Cpp 而非 Rust
  • 14. 下一代 Rust 借用检查器 Polonius
  • 15.当 Zig 超越 Rust——内存高效的枚举数组
    • 标记索引(Tagged Index)
    • Zig 超越 Rust 的地方
    • Zig 分阶段编译介绍
    • 参考资料
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档