後端工坊 2026 年 10 月 4 日

2026-10-04 — Rust 實驗 Generic Const Args,const 引數可含泛型

primary=https://blog.rust-lang.org/inside-rust/2026/10/02/generic-const-args-and-you/ primary=https://github.com/rust-lang/goals/issues/100

Rust 開放實驗版 Generic Const Args,用 gca! 把泛型參數寫進 const 引數

Inside Rust Blog(Const Generics Project Group,BoxyUwU 代筆)· 2026-10-02

Rust 的 const generics 長年只允許兩種 const 引數:裸的泛型參數 { N },或完全具體的常數 { 1 + 1 }。Generic Const Args(GCA)是一組 nightly 實驗功能,要讓 [u8; T::NUM_BYTES] 這類「含泛型參數的表達式」成為合法的 const 引數,並打算取代 generic_const_exprs。

Const Generics Project Group 在 2026-10-02 於 Inside Rust 發文介紹各個 feature gate 目前能做什麼、不能做什麼。文中明說這些功能還離穩定化很遠。

原本的問題

穩定版的 const 引數幾乎不能組合。想寫 [u8; N + 1] 或 [u8; T::NUM_BYTES],穩定版一律拒絕,只能繞路:把長度當額外參數傳入,或改用 Vec。

既有的 generic_const_exprs 自 2021 年 min_const_generics 穩定化後就一直存在,文章稱 GCA 的設計深受它的經驗影響,但 GCA 會讓它成為多餘。

核心改動:三個 feature gate

GCA 以 gca!(..) 巨集標出「這是一個含泛型參數的 const 引數」,再用不同 gate 控制能放什麼進去。

  • gca_adts:可在 const 引數裡建構陣列、tuple 與 struct/enum,內容可含泛型參數。
  • gca_const_items:允許 associated、free、inherent 的 const item 出現在型別系統中,等於間接容納任意表達式。需要不穩定旗標 -Znext-solver。
  • gca_min_const_items:只接受右手邊是 gca!(..) 的 const item,不需要 -Znext-solver。不透明的 const(右手邊不是 gca!(..))會被拒絕。

以下是 gca_adts 與 gca_const_items 的用法對照:

// gca_adts:把泛型參數裝進 struct / 陣列再當 const 引數
#![feature(gca_adts, adt_const_params)]
accepts::<gca!(TupleStruct(N))>();
accepts_arrays::<gca!([N1, 12])>();

// gca_const_items:用 associated const 當陣列長度
fn example<T: Trait>() -> [u8; gca!(T::ASSOC)] { [0x1; _] }

另有屬性 #[rustc_always_gca],可強制 trait 的 associated const 必須以 gca!(..) 實作。文章也提到 gca_const_items 能支援 associated const binding,以及帶 associated const 的 trait 與 dyn 相容。

目前的限制

gca!(..) 內目前不能做算術或函式呼叫。允許的是泛型參數,以及 struct、enum、陣列、tuple 的建構;gca!(1 + 1)、gca!(foo()) 與陣列 repeat 寫法 [N1; 2] 都不行。

寫法目前狀態
gca!(TupleStruct(N))可用(gca_adts)
gca!([N1, 12])可用(gca_adts)
gca!([N1; 2])不支援
gca!(1 + 1)、gca!(foo())不允許

文章給的繞法是:把不支援的表達式寫進一個 const item,再靠 gca_const_items 在型別中引用它。

為什麼還需要巨集

實驗性的 gca_macroless_args 與 gca_macroless_items 想省掉 gca!(..),讓 [u8; T::ASSOC] 直接成立。團隊自承這兩者「很實驗」且運作不佳。

根本困難在語法歧義,下例中兩個呼叫形式相同、需求卻相反:

fn Bar(_: usize) -> usize { 1 }
// Bar(ONE) 是函式呼叫,不能是 gca!(..)
// Foo(N)   是建構子,必須是 gca!(..)

編譯器在解析階段分不出 Bar(ONE) 與 Foo(N),所以目前需要明確標記。

影響範圍

  • 依賴 generic_const_exprs 的 nightly crate(例如以 [u8; N + 1] 做 buffer 的庫):GCA 預定取代它,可開始用 gca_min_const_items 試改,並依文章提供的 experience report 範本回報使用心得。
  • 穩定版使用者:不受影響,文章表示短期內還不會提出 RFC,離穩定化還有一段時間。
  • 想把 trait 的 associated const 當長度的人:需用 gca_const_items,並承擔 -Znext-solver 的不穩定性;只想先試的話,用 gca_min_const_items 並讓 const 右手邊寫成 gca!(..)。

文章把完整設計目標列在 Const Generics project goal,初始實作者為 @camelid,後續實作與設計由 @khyperia 負責。此設計首度討論於 2024 年 6 月的 RustFest Zürich。

原始來源:Generic Const Args and You、Const Generics project goal、GCA experience report


End of article
0
Would love your thoughts, please comment.x
()
x