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 不支援元組或可變參數的未來值,這仍是限制。繫結介面可能會如下所示:
abstract class Example {
Future<ExampleFooResponseExtension> foo(int arg1, {String arg2, bool arg3});
}
使用這個語法新增其他擴充引數,可保留來源相容性。
荒漠油廠
未定
查看
未定
簡易 C
簡單的 C 繫結不支援資料表,因此這項功能與這些繫結不相容。
導入策略
第一步是將新語法支援功能新增至 fidlc
,並更新參考資料和教學課程說明文件。
接下來,我們會為 Dart 繫結新增支援功能,因為這類繫結最能帶來明顯的人體工學效益。
人體工學
允許 FIDL 通訊協定演進是使用者所需的重要功能。目前變更方法的引數會造成 ABI 和 API 的破壞性變更。軟化方法的做法是為每個變更引進新的類別名稱,並在仍有呼叫端的情況下繼續支援舊方法,或是將資料表納入引數,並在該資料表中新增引數。這項提案可讓您以更符合人體工學的方式表達後一種方法。它會保留方法定義中定義的引數,方便在說明文件註解中參照。
許多程式設計語言都會使用可選的引數。這對程式庫作者來說並非新概念。
資料表需要明確的序數,因此擴充引數與必要引數不一致,但最好還是讓兩者保持一致,不要引入使用雜湊序數的新表格式結構。
說明文件和範例
作為 FIDL 語言的擴充功能,應更新 FIDL 參考資料和教學課程文件。
回溯相容性
現有的 FIDL 程式庫不會受到這項異動影響。
這項提案大幅提升了程式庫作者長期維護 ABI 相容介面的效能。
原始碼相容性的限制仍未確定,我們會根據綁定支援語言的方式提供相關資訊。
成效
相較於結構體,編碼和解碼表格所需的成本較高,因此效能至關重要的通訊協定應盡量少用這項功能
安全性
沒有影響
測試
測試應新增至 fidlc
。危險 ID 測試應測試危險 ID 是否用於選用引數。
缺點、替代方案和未知事項
替代方案
我們可以根據個別方法或個別通訊協定,從結構體切換至資料表。我們甚至可以將預設值從結構體切換為資料表。這種做法較不靈活。通常只會延長要求或回應。通常,部分引數 (例如 Modular 中的模組 ID) 預期會長期保持穩定,其他則不會。
我們可以定義類似表格的資料結構,讓系統為每個擴充引數產生哈希值,以便計算序數,而無需使用表格和為每個擴充引數要求序數。這會簡化原始語言的語法,但會增加編碼器、解碼器和語言繫結的複雜度。
我們可以使用版本化方法。我們並未深入探討這個選項。
開放式問題
我們應決定如何在 C++、Rust 和 Go 中綁定此項目。
是否應允許新增引數破壞來源相容性?
既有技術與參考資料
Protobuf 會在通訊協定方法之外宣告訊息。
Flatbuffers 和 cap'n proto 會使用版本。