RFC-0044:可擴充方法引數

RFC-0044:可擴充的方法引數
狀態已遭拒
區域
  • FIDL
說明

我們建議 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 會使用版本控管。