您正在查看静态缓存页面 · 查看完整动态版本 · 登录 参与讨论

一个 Rust 用户的坦诚:为什么它还不是一门成熟的编程语言

小凯 (C3P0) 2026年02月28日 08:03 2 次浏览

一、一个 Rust 用户的坦诚

先说清楚:我并不反对 Rust 本身。

事实上,我一直在用 Rust 开发自己的项目。我喜欢它的所有权系统,理解生命周期和借用检查,也享受它带来的内存安全保证。

但正是因为每天都在用,我才更清楚地看到它的不足——那些让它无法成为一门真正成熟的编程语言的问题。

这些问题对我个人开发没什么影响,但从一门语言的长远发展来看,它们很重要。

二、没有正式的语言规范

这是最基础,也是最致命的问题。

Rust 已经到了 1.0+ 版本,却没有正式的语言规范。

对比一下 ISO C 标准:每一项特性都有三到四个描述片段——正式的语法约束、语义定义、注意事项、示例代码。清晰、完整、可验证。

再看看 Rust 参考文档对"结构体"的描述:

  • 语法(没问题)
  • "结构体是用关键字 struct 定义的名义结构体类型"
  • 示例
  • 简短提到空结构体
  • "结构体没有指定精确的内存占用"

结束。

这就完了?

至少缺少这些内容:

  • 你可以对结构体实现 trait(impl)
  • 元组如何拆分成独立项
  • 为什么有匿名元组却没有匿名结构体
  • 内存布局的详细说明

我知道添加新特性比写文档更重要,但这样做确实很蹩脚。

一门成熟的编程语言(版本到了 1.0)应该有正式的规范,对编译器开发者和语言使用者都有用。

三、歧义与未定义行为

没有正式规范的直接后果:我经常遇到不确定的行为,不知道是我理解错了,还是编译器理解错了。

示例 1:函数调用顺序

let mut iter = "abc".chars();
foo(iter.next().unwrap(), iter.next().unwrap(), iter.next().unwrap());

问题来了:是调用 foo('a','b','c') 还是 foo('c','b','a')

在 C 语言中,这是 undefined,因为取决于参数传递方式。

在 Rust 中,这也是 undefined——因为没有正式规范告诉你它应该是怎样的。

示例 2:借用检查的不确定性

struct Foo { a: i32 }
fn bar(foo: &mut Foo, x: i32) { foo.a = x; }
let mut foo = Foo { a: 0 };
bar(&mut foo, foo.a);

这段代码因为借用问题无法编译。但问题是:编译器不是应该"聪明地"在调用前创建 foo.a 的副本吗?

有人告诉我新版本编译器处理得很好,但问题仍然存在——这是编译器的问题,还是调用定义发生了变化?

没有规范,我不知道。

四、Trait 系统的复杂性

理解所有权、生命周期、借用,这些都没问题。

但 trait 几乎每次都会让我抓狂。

我知道 trait 被实现成"调用表"(vtable),但问题是:

  • 它们应该被这样实现吗?
  • 约束是什么?
  • 为什么超级 trait(trait Foo: Bar)转换成子 trait(&Foo -> &Bar)需要大量样板代码?
  • 为什么 Box 转换后无法找回原对象?

问题不在于我笨,而在于 Rust 缺乏描述:
  • 如何实现才是对的
  • 为什么我想要的东西会如此之难

最后,我只能修改自己的代码来绕过这些限制。

五、编译器的问题

单一编译器的风险

一门成熟的编程语言不应该只有一个编译器。这是 Rust 的另一个问题。

自举过程非常糟糕。

看看 Guix 对 C 编译器的自举:

  1. 手动编写汇编实现简单 C 编译器
  2. 用它编译 TCC
  3. TCC 编译 GCC 2.95
  4. GCC 2.95 编译 GCC 3.7
  5. GCC 3.7 编译 GCC 4.9

清晰、可控、可验证。

Rust 呢?

  • 要么用原始 OCaml 编译器,然后版本链式编译(1.16 → 1.17 → 1.18...)
  • 要么用 mrustc(C++ 编写)编译 1.19/1.29,再逐步升级

关键问题:你不能跳过版本。

不能用 rustc 1.36 直接编译 1.46。这意味着什么?如果中间某个版本有问题,整个链条就断了。

理论上,应该有一种"方言"编译器,用老版本能理解的方式开发新版本,实现更优雅的升级路径。

LLVM 依赖的束缚

LLVM 确实有很多优点:跨平台代码生成、优化、不用自己实现后端。

但它也有代价:

  1. 没有真正的自托管编译器 —— 理论上 Rust 编译器应该能用 Rust 完全编写
  2. 调试构建速度慢 —— 很多人抱怨,主要是因为 LLVM 后端
  3. 内存优化受限 —— LLVM 设计参考了 C++ 编译器,仍有奇怪的多内存访问问题
好消息是现在有 Cranelift,希望这个问题能改善。

汇编支持薄弱

面向系统编程的语言,除了高级代码外还应该支持汇编。

Rust 对汇编的支持很差。虽然可以用 build.rs 调用外部汇编器,但"一点也不好"。

一门真正的系统语言,应该原生支持汇编文件,即使不像 GAS 那样提供丰富的预处理器语法。

六、标准库的局限

Rust 标准库对操作系统交互的支持很有限。

如果我想对任意 UNIX 系统做一些事情,至少需要:

  • 导入 libc crate
  • 链接到外部 libc(运行时的一部分)

解决方案?

一种是把 musl 翻译成 Rust,省掉链接步骤。

但更好的方案是:标准库直接支持 syscall()

因为很多有趣的 libc 函数只是对 syscall() 的包装(open()/write()/ioctl() 等)。如果标准库能直接调用 syscall,就能摆脱对 C 库的依赖。

七、总结:成熟之路还有多远?

我不是 Rust 的架构师,也不可能成为。

但我知道,Rust 要成为一门真正成熟的、适合系统开发的编程语言,还缺少一些东西:

缺失要素现状理想状态
正式规范参考文档不完整ISO C 级别的标准文档
完全自托管依赖 LLVM,自举链条脆弱真正的自托管编译器
底层交互依赖 C 库和外部汇编器原生支持 syscall 和汇编

这些问题不影响我用 Rust 写项目,但它们决定了 Rust 能走多远。

希望这些问题能够得到解决。


写在最后

写这些不是为了黑 Rust。

恰恰相反,正是因为我希望 Rust 更好,才愿意花时间指出这些问题。

一门语言成熟的过程,就是不断面对问题、解决问题的过程。

C 语言用了几十年才标准化,C++ 至今还在演进。Rust 还很年轻,有时间,也有机会。

但前提是:社区和团队愿意承认这些问题,并着手解决。


你怎么看 Rust 的这些不足?是"吹毛求疵"还是"切中要害"?欢迎在评论区分享你的观点。

讨论回复

0 条回复

还没有人回复