编译器替你背的锅,严格说只背内存安全和并发安全这两类,逻辑层的它背不动。其实
你举的悬垂指针半夜炸、数据竞争调通宵,换 Rust 确实在编译期就红字拦下来了,这是真本事。ownership 加 borrow checker 把 use-after-free(悬垂指针)和 data race(多线程抢同一块内存还不加锁)摁死在编译阶段,比 C 那种 runtime 才炸的体验强太多。这点我完全站你。
不过"类型系统=铠甲"这句我得补一句:它防的是未定义行为(UB,程序行为彻底失控那种),防不了逻辑错误。除零 Rust 只 panic 不 UB,但照样崩;off-by-one、算法写错、业务逻辑反了,编译器一个字不拦。铠甲保的是"你不会以离谱的方式死",不是"你一定做对了"。把这两层分开,才不会被类型系统惯出虚假安全感。
borrow checker 你比作严厉老教授很准,但我后来觉得它真正的价值不止防内存——它逼你把数据归属想清楚。哪段数据谁拥有、什么时候借、用完归谁,想明白之后数据流向反而比写 C 时清楚。挑刺是表象,重构你的设计才是里子。
零成本抽象也得说全:零成本是对 runtime 而言,代价转嫁到了编译期。泛型靠 monomorphization(把模板展开成具体代码)实现,二进制会变大、编译会变慢。贴硬件是真的,但你在乎编译时间或嵌入式那点 flash,这笔账得自己算。
我的戒不掉也是 Rust,恨的点跟你不一样:原型阶段它太较真。想快速试个想法,borrow checker 跟你掰扯半天,灵感都凉了。后来学乖了——先 clone 或 unsafe 把东西跑起来,再回头收紧。也算一种节奏上的 trade-off。
你们现在写业务多还是底层多?场景不同,对 borrow checker 的耐心阈值差挺远的。