RFC-0031:型型字符

RFC-0031:型式 Epitaph
狀態已遭拒
區域
  • FIDL
說明

表示 Epitaph 類型的功能和語法。

變更
作者
提交日期 (年/月)2019-02-05
審查日期 (年/月)2021-04-07

拒絕原因

這項提案與服務探索互動不合,且預估實作的複雜度較低,因此遭到拒絕。

與服務探索功能互動

Fuchsia 的一種常見的模式,是透過 fuchsia.io/Directory.Open 呼叫,以名稱呼叫特定通訊協定。我們將這項服務稱為「探索」。在服務探索期間,用戶端會與實作 fuchsia.io/Directory 通訊協定的伺服器互動。伺服器收到服務探索要求時,會搜尋要求的適當服務,然後將管道的伺服器端轉移至要求的服務。這表示用戶端正在與一個伺服器互動 (支援 fuchsia.io/Directory),然後與另一個伺服器互動 (支援要求的服務)。

遺憾的是,服務探索對於蛋白質設有嚴格限制。假設故障導致傳票已送出,用戶端無法判斷發出 API 的對等端,這是伺服器支持 fuchsia.io/Directory,還是要求的服務?

實際上,服務探索可以包含許多超過兩個伺服器,如上所述。因此,縮寫必須非常通用,不可包含特定領域的詳細資料。基本上,API 必須滿足所有可偵測通訊協定中最低的共同分母。

在本提案中,為修正這項限制,我們也討論到服務探索作業中納入所有通訊協定,進而組成 fuchsia/IsDiscoverable 通訊協定。這個通訊協定會定義打字的紀元:


protocol IsDiscoverable {
    epitaph zx.status;
};

fuchsia/IsDiscoverable 的所有子項都無法定義自訂紀律,因此能正確擷取類型系統中的限制。具體而言,本提案的這個部分如下:

一個通訊協定只能宣告一個劇集類型 (包括所有或所有組合的通訊協定)。我們專門防止兩個具有相同類型且語意相等的 Epitaph 類型宣告。

不過,我們無法讓所有可探索的通訊協定組成這個新的 fuchsia/IsDiscoverable。舉例來說,由於設計服務探索是動態的,所以不提供靜態的強制執行。

與要求管道互動

要求管道模式可視為服務探索模式的一般化程序,對 Epitaph 施加類似的嚴格限制。

導入複雜度

雖然 FIDL 的功能相當複雜 (語言規則、JSON IR 的擴充功能、繫結程式碼、產生的程式碼、人體工學),而打字符號在複雜程度上相當高,其實用性也相當低。然而,這類取捨並不代表我們走得開心。

下一步是什麼?

這個部分代表作者的意見 (pascallouis@google.com)。

導入 API 時,「狀態目標」是用來「提供用戶端對伺服器連線關閉的原因」。

Epitaphs 的數值低於這個目標,其實用性更是邊緣。據以為代章的通訊協定,可能會搭配使用自訂事件,這個事件具有上述所有缺點,也沒有因 FIDL 背後的低階優先原則而施加的任何酬載限制

預防措施有益於通訊協定的「乾淨終止」,在大部分情況下,伺服器可以放心,用戶端對等端會與管道解除繫結,且不會發出後續要求。

我們已經浮動,為事件引進了適用於事件的 terminal 修飾符,這樣就能從使用 Epitaph 改為自訂事件,而不會失去此「乾淨的終止」屬性。透過終端機事件,程式庫作者可以隨意定義事件酬載。為支援這一點,我們會擴充傳輸格式以分配一個 交易標頭的標記,表示通訊協定已終止。收到標示為終端機的訊息後,用戶端除了一般處理之外,也會終止連線。如果用戶端不知道事件 (很可能在複雜的要求管道處理情況下),用戶端就能解讀交易標頭,而酬載則會捨棄。

摘要

我們建議:

  1. 新增用於表示通訊協定上特定縮寫的語法 (我們不會變更 Epitaph 的預設類型 zx.status);
  2. 為繫結揭露特殊類型的一種方法,以便在產生程式碼時適當運用這項資訊。
  3. 補充組合模型,指定每個通訊協定的 Epitaph 類型是唯一的,而且會「由組合沿用」

我們預期會使用字符輸入:在「分葉」通訊協定上 (也就是自行定義的或組合其他通訊協定),或一次在「組合樹」中,並將 Eepitaph 類型放置在「top」或「root」通訊協定上。

提振精神

tl;dr 我們喜歡類型,類型則好。我們來看看更多類型。

語法和錯誤類型

RFC-0053: Epitaphs 中,我們引進了 Epitaphs 的概念,表示「一種機制,可讓伺服器在關閉連線前傳送訊息,進而指出連線關閉的原因」。週期包含錯誤狀態,目前已修正為 int32。審查週期時,我們選擇將類型修正為 int32,以便與 zx.status 重疊,並將「使用者錯誤」放在路上,並顯示「通訊協定錯誤」的道路。

RFC-0060:錯誤處理中,我們針對特定類型的錯誤引入了語法,特別註明「錯誤類型必須是 int32、uint32,或是這些類型的列舉。」我們想要允許輸入 epitaph 的錯誤,並選用符合錯誤處理機制的表示法。

在「RFC-023:通訊協定組合模型」中,我們導入了新的語法來宣告通訊協定以及組合通訊協定。我們在這裡為 API 提出的語法就是這樣的樣式。

我們會考慮所有先前做出的決定,以便與提議 (1) 和 (2) 保持一致。

搭配 Epitaphs 的組合模型

主張 (3) 分為兩個面向,分別是每個通訊協定的 Epitaph 類型唯一性,以及組合下的行為。

Epitaph 的語意與特殊事件的語意類似,而且會在每個通訊協定中,回應類型都會重複。

組合下的行為模式與思考方向類似,肯定該詩詞的類型組成。我們會在下文探討另一種定義,以及其缺點。

藉由允許組合類型,我們在距離情境中導入可能的中斷情形。假設通訊協定 ChildWithEpitaph 編寫通訊協定 FarawayParent,並定義其為 SomeSpecificErrorCode 列舉。如果 FarawayParent 後製決定要指定 Epitaph 類型,系統就不會允許組合,而 ChildWithEpitaph 的編譯作業也會失敗。

替代方法:Epitaphs 無法撰寫

另一個做法是考慮只有定義的訊息 (方法和事件) 可以組成另一個通訊協定。在此替代模型中,如果父項通訊協定定義了紀元類型,這個類型將與子項通訊協定的可能獨立的縮寫類型無關。例如,我們允許使用下列定義:

protocol Parent {
    epitaph ParentErrorCode;
};

protocol Child {
    compose Parent;
    epitaph ChildErrorCode;
};

由於我們不提供通訊協定之間的任何關係 (例如沒有任何子假設、無演化規則),因此該替代模型具有部分優勢。同時在同時使用縮寫詞與組合的情況下有更多的自由。

不過,我們近期都有所有意圖和用途,都在近期內定義通訊協定之間的關係,因此應根據這個設計目標評估選擇方式。舉例來說,如果我們引進了正式的假設關係 (「是」),且在另一個通訊協定組合中定義了不相容的 Epitaph 類型,則這些通訊協定會立即失敗提交測試:用戶端預期一種類型的 Epitaph 結果,可處理另一種 Eepitaph 類型。

因此,我們認為在「今天」限制許可類型的使用方式較為妥當,因此為了明天,對擴充功能也保持開啟狀態更好。

設計

語法

我們擴充文法,以在通訊協定宣告中允許 epitaph 段落:


protocol SomeProtocol {
    ExampleMethod(...) -> (...);

    epitaph SomeErrorCode;
};

Epitaph stanza 在語法上與 compose 分位數類似,而且也會遵循為錯誤規格選定的語法。

文法的正式修改如下:

protocol-declaration = ( attribute-list ) , "protocol" , IDENTIFIER ,
                        "{" , ( protocol-member , ";" )*  , "}" ;

protocol-member = ...
                | "epitaph" type-constructor ; [NOTE]

NOTE: The epitaph stanza allows the more liberal type-constructor in the
grammar, but the compiler limits this to int32, uint32, or enum thereof. There
may be only one epitaph stanza per protocol definition.

ABI 和來源相容性

我們在推出 Epitaph 時,已經將類型修正為 int32,並順便將範圍限制在 32 位元。稍後,我們會在導入錯誤語法時確認將錯誤代碼修正為 32 位元。

我們將維持這個選擇,如上所述,將紀元類型限制為 int32、uint32 或列舉。

因此,變更 EBI 類型 (可能從預設值變更為指定類型) 不會修改 ABI 相容性。

不過,變更 Epitaph 類型很有可能是來源層級破壞性變更。繫結作者「可能」破壞原始碼相容性。我們不認為這是個問題 因為現代人目前尚未廣泛使用

JSON IR

我們在 definition/interface 物件中新增為 definitions/type 類型的成員生命週期。

舉例來說,我們可能會:

    {
      "name": "example/SomeProtocol",
      "epitaph": {
          "kind": "primitive",
          "subtype": "uint32"
      },
      "methods": [
        {
          "ordinal": 296942602,

淘汰了類型永遠都會出現在介面宣告中,另外,如未指定,則會設為預設的 zx.status

構思 Epitaphs

將通訊協定組合到另一個時,該時代的類型會沿用。以下列通訊協定為例:

protocol Parent {
    epitaph SomeErrorCode;
};

protocol Child {
    compose Parent;
};

ParentChild 產生的 Epitaph 類型為 SomeErrorCode

一個通訊協定不得含有一個以上的語句類型宣告 (包括任何及所有組合的通訊協定)。我們會明確防止兩個具有相同類型的 Epitaph 類型宣告。

以下範例無效,且應該無法編譯:

protocol Parent1 {
    epitaph SomeErrorCode1;
};

protocol Parent2 {
    epitaph SomeErrorCode2;
};

protocol Child {
    compose Parent1;
    compose Parent2;
};

這個範例也無效,且應無法編譯:

protocol Parent {
    epitaph SomeErrorCode;
};

protocol Child {
    compose Parent;
    epitaph SomeErrorCode;
};

導入策略

(由 FIDL 團隊在經過審查後將決定)。此變更與先前許多變更並不相似。)

人體工學

說明文件與範例

至少:

  • 有線格式規格應指出省略符號為 int32/uint32,需要以適當類型解讀。
  • 開發人員指南應以「ZX_OK (或相關成功程式碼)」等陳述式進一步闡明,藉此擴大開發人員指定的類型建議。

回溯相容性

FIDL 來源:我們擴大了語言文法,因此極具回溯相容性。這項變更之前,任何 FIDL 檔案都不得在通訊協定宣告中含有「epitaph type-constructor;」stanza。

JSON IR:回溯相容於非嚴格剖析器,以允許使用額外的金鑰,因為我們要在所有介面宣告中加入「epitaph」金鑰。

效能

不會影響效能。

安全性

沒有影響,或對額外類型安全略為正面。

測試

fidlc 的單元測試,以及繫結產生測試。

缺點、替代方案和未知

既有圖片與參考資料

(如文中所述)。