跳轉到

2012:rustpkg 與自舉之路——套件管理的實驗#

事件#

2012 年,Rust 0.4 發佈,編譯器 rustc 完全自舉(用 Rust 寫成)。同年推出實驗性套件管理工具 rustpkg,嘗試自動從版本控制系統抓取依賴並建置。

為何重要#

  • rustpkg 的教訓:它直接依賴 git URL 與目錄慣例,沒有集中登錄、沒有版本鎖定,重現建置(reproducible build)幾乎不可能。這個失敗直接催生了 2014 年的 Cargo 設計。
  • 類別系統大瘦身:2012–2014 年間,Rust 刪除了大量早期過度設計的特性——GC 指標 @ 與 ~ 的雙軌制、型別類(kind)系統、綠色執行緒(green threads)。
  • 這段「刪除期」確立了 Rust 設計哲學:寧可延後 1.0,也要語言「少而精」。

理論與實用原因#

  • 理論原因:早期 @T(GC 指標)與 ~T(唯一指標)並存,讓型別系統有兩套所有權規則;語言設計者體認到「唯一指標 + 借用」即可表達一切,GC 應交給函式庫而非語言核心。
  • 實用原因:綠色執行緒(每個 task 有自己的 stack)與 Servo 需要的「與 C 程式碼、真實作業系統執行緒互通」相衝突;刪除綠色執行緒換來與 OS 執行緒完全對齊的 1:1 模型。

程式範例#

早期雙軌記憶體模型(2012 年前後,後來被刪除):

// 早期 Rust(已移除的語法)
let gc_box  = @String::from("gc 管理");   // @:垃圾回收指標
let own_box = ~String::from("唯一所有");  // ~:唯一指標(後來成為 Box)

兩套規則並行讓型別系統與學習成本都翻倍,最終刪除 @、把 ~ 改名為 Box:

// 現代 Rust:GC 移出語言核心,交給函式庫型別
let shared = std::rc::Rc::new(String::from("引用計數,單執行緒"));
let thread_shared = std::sync::Arc::new(String::from("原子計數,可跨執行緒"));
let boxed = Box::new([0u8; 64]);   // 唯一所有權,離開作用域即釋放

綠色執行緒被刪除,改為與 OS 執行緒 1:1 對齊:

use std::thread;
// 現代 Rust:thread::spawn 就是真實作業系統執行緒
let h = thread::spawn(|| println!("跑在真正的 OS thread 上"));
h.join().unwrap();

彌補了什麼缺陷#

彌補了 Rust 自己「早期過度設計、語法負擔重、兩套記憶體模型並行」的缺陷——透過刪除而非添加,語言核心縮小到足以長期維護的規模。

相關條目#