RFC-0044:可擴充方法引數

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

我們建議 FIDL 程式庫作者在需要擴充時,使用資料表而非結構,但方法引數將以結構體編碼。這提議在資料表之上建立可擴充方法引數。

作者
提交日期 (年/月)2019-04-08

拒絕原因

RFC-0050:語法 revamp 淘汰。

摘要

我們建議 FIDL 程式庫作者在需要擴充時,使用資料表而非結構,但方法引數將編碼為結構體。這提議在資料表之上建立可擴充的方法引數。

提振精神

如果缺少可擴充方法引數的語法,程式庫作者就不會使用資料表來擴大方法引數。在語法中加入上述內容,即可在設計通訊協定時將擴充性考量放在最顯眼的位置。

Modular 團隊在設計通訊協定時,需要維持 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 版本。可擴充的方法引數包含名為 {Protocol}{Method}RequestExtension{Protocol}{Method}ResponseExtension{Protocol}{Method}EventExtension 的資料表。系統會在這些產生的資料表上設定 [ExtensionArgument] 屬性,讓繫結產生器可以視需要特別處理。

未來的紅外線活動可能會使這個構想更加完善。未來的 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 支援選用的已命名引數,可讓您將 FIDL 概念對應到其語法。Dart 對元組或各變的未來趨勢的支援仍有限。繫結介面可能如下所示:

abstract class Example {
  Future<ExampleFooResponseExtension> foo(int arg1, {String arg2, bool arg3});
}

透過這個語法新增其他擴充功能引數,即可維持來源相容性。

Rust

未定

查看

未定

簡易 C

簡易 C 繫結不支援資料表,因此這項功能與資料表不相容。

導入策略

首先,請在 fidlc 中新增對新語法的支援,並更新參考資料和教學課程說明文件。

接著我們會支援 Dart 繫結,因為這些繫結是最明顯的人體工學優勢。

人體工學

允許改進 FIDL 通訊協定是使用者關注的重要功能。目前變更方法的引數屬於 ABI 和 API 破壞性變更。柔化的方法包括為每個變更導入新方法名稱,並繼續支援舊方法 (只要仍有呼叫端),或納入資料表做為引數,並在該資料表新增引數。本提案可讓您以更符合人體工學的方式表達第二種方法。它會保留方法定義中定義的引數,以便於說明文件註解中輕鬆參照這些引數。

選用引數在許多程式設計語言中都很常見。對圖書館的作者來說,這是個驚人的概念。

資料表上的明確序數會使擴充功能引數與必要引數不一致,但最好將其與資料表保持一致,而不是採用含有雜湊序數的新資料表結構。

說明文件與範例

您應更新 FIDL 參考資料和教學課程說明文件,做為 FIDL 語言的擴充功能。

回溯相容性

現有的 FIDL 程式庫不受這項異動影響。

本提案可大幅改善程式庫作者長期維護 ABI 相容介面的能力。

原始碼相容性的限制仍待定,屆時將瞭解我們計畫繫結支援語言的方式。

效能

資料表的編碼和解碼成本比結構體高,因此重要的通訊協定應謹慎使用此功能

安全性

沒有影響

測試

應將測試新增至 fidlc。危險 ID 測試應測試將危險 ID 做為選用引數使用。

缺點、替代方案和未知

替代選項

我們可以依方法或根據通訊協定,從結構體切換至資料表。我們甚至可以將預設值從結構切換為資料表。這種方法較無彈性。通常只會擴充要求或回應。通常部分引數 (例如 Modular 的模組 ID) 預期長期會保持不變,其他引數則不會。

與其使用資料表,並為每個擴充引數要求序數,我們可以定義類似資料表的資料結構,以雜湊名稱計算基數。這樣做可以簡化原文語言的語法,但同時為編碼器、解碼器和語言繫結增加複雜度。

我們可以設定版本化方法目前這個選項並未深入探討。

開放式問題

我們應決定在 C++、Rust 和 Go 中的繫結方式。

是否應該新增引數以破壞來源相容性?

先前的圖片和參考資料

Protobuf 宣告來自通訊協定方法的訊息。

Flatbuffer 和 Caps proto 使用版本管理。