- Start Date: 2014-03-20
- RFC PR: rust-lang/rfcs#49
- Rust Issue: rust-lang/rust#12812
- Translators: [@FizzyElt]
- Commit: The commit link this page based on
- Updated: 2022-05-17
概要
允許屬性在配對分支上
動機
有時希望使用屬性來注釋配對語句的分支,例如條件編譯 #[cfg]
或是分支權重(後者為最重要的用途)。
對於條件編譯,暫時得解決辦法是使用 #[cfg]
來重複宣告相同函式來處理不同的案例。一個案例研究是 sfackler 的 bindings to OpenSSL,在多數的發行版本中移除了 SSLv2 支持,因此 Rust bindings 部分需要被條件禁用。支援各種不同 SSL 版本最顯而易見的方法是使用枚舉。
#![allow(unused)] fn main() { pub enum SslMethod { #[cfg(sslv2)] /// Only support the SSLv2 protocol Sslv2, /// Only support the SSLv3 protocol Sslv3, /// Only support the TLSv1 protocol Tlsv1, /// Support the SSLv2, SSLv3 and TLSv1 protocols Sslv23, } }
然而,所有的 match
只能在 cfg
啟用時使用 Sslv2
,例如下面內容是無效的:
#![allow(unused)] fn main() { fn name(method: SslMethod) -> &'static str { match method { Sslv2 => "SSLv2", Sslv3 => "SSLv3", _ => "..." } } }
一個有效的方法則必須有兩個定義:#[cfg(sslv2)] fn name(...)
和 #[cfg(not(sslv2)] fn name(...)
。前者有 Sslv2
的分支,後者沒有。顯然,對於枚舉中每個額外的 cfg
變體,這都會以指數型的方式爆炸。
分支權重將允許仔細的微優化器(micro-optimiser)通知編譯器,例如,鮮少採取某個配對分支:
#![allow(unused)] fn main() { match foo { Common => {} #[cold] Rare => {} } }
詳細設計
一般的屬性語法,應用於整個配對分支。
#![allow(unused)] fn main() { match x { #[attr] Thing => {} #[attr] Foo | Bar => {} #[attr] _ => {} } }
替代方案
實際上沒有通用的替代方案; 人們也許可以用一些巨集(macro)和輔助函數來解決條件枚舉變體的配對問題; 但一般來說,這起不了任何作用。
未解決的問題
無