| RFC-0044:可擴充的方法引數 | |
|---|---|
| 狀態 | 已遭拒 |
| 區域 |
|
| 說明 | 我們建議 FIDL 程式庫作者使用表格,而非結構體 (如果需要擴充性),但方法引數會編碼為結構體。這項提案建議以資料表為基礎,建構可擴充的方法引數。 |
| 作者 | |
| 提交日期 (年-月-日) | 2019-04-08 |
拒絕原因
已由 RFC-0050:語法改版取代。
摘要
我們建議 FIDL 程式庫作者使用表格,而非結構體,但方法引數會編碼為結構體。這項提案建議以資料表為基礎,建構可擴充的方法引數。
提振精神
由於缺少可擴充方法引數的語法,程式庫作者不願使用表格來擴充方法引數。在語法中加入這項資訊,有助於在設計通訊協定時,將擴充性考量放在首要位置。
模組化團隊正在設計通訊協定,這些通訊協定必須維持 ABI 相容性,並在發現新需求和演進設計時可擴充。他們正在考慮以表格形式定義方法,並在行外宣告這些方法。
設計
這項提案會擴充 FIDL 來源語言,並影響語言繫結。
FIDL 語法
建議擴充方法和事件要求/回應引數的語法,在引數結構體中新增表格。
例如這個通訊協定:
protocol Example {
Foo(int32 arg1, { 1: string arg2, 2: bool arg3 }) -> ({});
};
宣告的方法有一個必要引數、兩個選用引數、可擴充的要求和可擴充的回應。這相當於宣告:
table ExampleFooRequestExtension {
1: string arg2;
2: bool arg3;
};
table ExampleFooResponseExtension {
};
protocol Example {
Foo(int32 arg1, ExampleFooRequestExtension extension)
-> (ExampleFooResponseExtension extension);
}
IR
目前的 IR 版本可以回溯相容的方式擴充。
可擴充的方法引數包含名為 {Protocol}{Method}RequestExtension、{Protocol}{Method}ResponseExtension 或 {Protocol}{Method}EventExtension 的資料表。系統會在這些產生的表格上設定 [ExtensionArgument] 屬性,以便繫結產生器視需要特別處理這些表格。
未來的 IR 可能會將這個想法提升為更頂級的結構。未來的 IR 應允許更彈性的宣告命名方式,讓語言能更妥善地選擇擴充資料表的名稱,例如 C++ 可將這些資料表巢狀內嵌在通訊協定定義類別中。
繫結
繫結不需要特別支援可擴充的方法引數。現有的繫結產生器只會將產生的表格做為方法的最後一個引數。
C++
舉例來說,如果上述通訊協定沒有任何變更,C++ 繫結大致會如下所示:
class ExampleFooRequestExtension;
class ExampleFooResponseExtension;
class Example {
using FooCallback = fit::function<void(ExampleFooResponseExtension)>;
virtual void Foo(int32_t arg1,
ExampleFooRequestExtension extension,
FooCallback callback) = 0;
};
繫結這個通訊協定的替代方式如下:
class Example {
using FooCallback = fit::function<void()>;
virtual void Foo(int32_t arg1,
FooCallback callback,
std::optional<std::string> arg2 = std::optional<std::string>(),
std::optional<bool> arg3 = std::optional<bool>()) = 0;
};
這樣會更符合方法的宣告方式,但會將回呼引數放在靜態和可擴充引數之間。
Dart
Dart 支援選用具名引數,因此可將 FIDL 概念對應至其語法。Dart 不支援元組或可變元組的 Future,這仍是一項限制。繫結介面可能如下所示:
abstract class Example {
Future<ExampleFooResponseExtension> foo(int arg1, {String arg2, bool arg3});
}
使用這個語法新增其他擴充功能引數時,會保留來源相容性。
荒漠油廠
未定
查看
未定
Simple C
簡單的 C 繫結不支援表格,因此這項功能與這些繫結不相容。
導入策略
第一步是將新語法支援功能加入 fidlc,並更新參考資料和教學課程文件。
接下來,我們會新增對 Dart 繫結的支援,因為這是最明顯的便利性優勢所在。
人體工學
允許 FIDL 協定演進是使用者尋求的重要功能。目前變更方法的引數是 ABI 和 API 破壞性變更。緩和變更的方法包括:為每項變更導入新的方法名稱,並在仍有呼叫端時繼續支援舊方法;或是將資料表做為引數,並在該資料表中新增引數。這項提案可讓您以更符合人體工學的方式,表達後者的方法。它會保留方法定義中定義的引數,方便在說明文件註解中參照。
許多程式設計語言都有選用引數的概念。對程式庫作者來說,這並非令人意外的概念。
資料表需要明確的序數,導致擴充功能引數與必要引數不一致,但最好還是讓擴充功能引數與資料表保持一致,而不是導入含有雜湊序數的新資料表結構。
說明文件和範例
FIDL 參考資料和教學課程文件應更新為 FIDL 語言的擴充功能。
回溯相容性
現有的 FIDL 程式庫不受這項異動影響。
這項提案可大幅提升程式庫作者長期維護 ABI 相容介面的能力。
原始碼相容性限制仍待確定,將取決於我們如何繫結至支援的語言。
效能
相較於結構體,表格的編碼和解碼成本較高,因此效能至關重要的通訊協定應謹慎使用這項功能
安全性
沒有影響
測試
測試應新增至 fidlc。危險 ID 測試應測試使用危險 ID 做為選用引數。
缺點、替代方案和未知事項
替代方案
我們可以根據方法或通訊協定,從結構體切換至資料表。我們甚至可以將預設值從結構體切換為表格。這種做法的彈性較低。通常只需要擴充要求或回應。通常有些引數 (例如在 Modular 的案例中,模組 ID) 預期會長期保持穩定,其他則不會。
我們不必使用資料表,也不必為每個擴充引數提供序數,而是可以定義類似資料表的資料結構,將名稱雜湊處理來計算序數。這會簡化來源語言的語法,但會增加編碼器、解碼器和語言繫結的複雜度。
我們可以有版本化方法。我們不會深入探討這個選項。
開放式問題
我們應決定如何在 C++、Rust 和 Go 中繫結這個項目。
是否允許新增引數來破壞來源相容性?
既有技術和參考資料
Protobuf 會在通訊協定方法以外宣告訊息。
Flatbuffers 和 cap'n proto 會使用版本控管。