RFC-0036:結構宣告更新

RFC-0036:結構宣告更新
狀態已遭拒
區域
  • FIDL
說明

為了更明確地傳達重新訂購及重新命名欄位對 ABI 的影響,我們提議進行語法變更,為結構體欄位引進序數 (具有相似的語法規則,然後是資料表的序數規則)。

作者
提交日期 (年/月)2019-03-07
審查日期 (年/月)2019-03-14

拒絕原因

優點

  • 混淆名稱對於 ABI 來說重要或不存在:xunion、struct 和通訊協定雖然看似相似,但規則不同。

缺點

  • 然而,所有擔心都有可能超出這個理解力,因為在結構上引入結構體可以產生序數,而且與通訊協定緩衝區相比更是如此。

  • 目前還有其他措施會處理「這項變更是否為 ABI」:

    • DIFL
    • API 差異比較,例如程式庫的簽名
  • 名稱對於文字格式 (JSON、FIDLText 等) 而言相當重要,且在這種情況下使用訊息時,無法更改名稱。

摘要

為了更明確傳達重新訂購及重新命名欄位對 ABI 的影響,我們提議進行語法變更來導入結構欄位的序數,其中包含類似的語法規則,然後適用於資料表。

提振精神

我們僅關注成員是否能在各種宣告中安全地重新命名或重新排序成員,也具有語法上的差異,這些差異已隨著時間改變,也不會傳達 ABI 可能對潛在變更造成的影響。

此外,目前的結構宣告語法會導致編譯器難以提供協助和發生變更時的指引

以下列舉一些獲選為小型和統一的例子:

struct Name {      table Name {        enum Name {
    T abc;           1: T abc;           ABC = 1;
    U xyz;           2: U xyz;           XYZ = 2;
};                 };                  };

protocol Name {    xunion Name {       bits Name {
    Abc(T t);        T abc;              ABC = 1;
    Xyz(U u);        U xyz;              XYZ = 2;
};                 };                  };

以 ABI 觀點來看,以下是一些觀察結果:

  • 重新排序:除了結構體外,其餘皆可變更順序,且不會受到任何影響。
  • 重新命名:
    • 可以將 struct、資料表、列舉和位元重新命名,而不會受到任何影響
    • 通訊協定和 xunion 遷移事宜,該通訊協定也會對 ABI 造成影響。

(從來源相容性的觀點來看,大多數繫結在重新排序後都將具有來源相容性,而重新命名版本不相容)。

基於這些觀察結果,我們提議導入結構宣告的序數。上述範例現在如下所示:

struct Name {
    1: T abc;
    2: U xyz;
};

具體違規事項如下:

  • 序數的開頭必須是 1,且序數不得允許間隔 (如果最大序數為 7,則所有 1、2、3、4、5、6、7 都必須存在)。請參閱下方原因
  • 每個欄位都無法聲明相同的序數。
  • 欄位序數會決定含有結構體的欄位,而非其語法位置。
  • v1 中的 JSON IR 沒有任何變更,會透過結構宣告中成員的順序傳達序數。請參閱 v2 中 JSON IR 的預定異動。

編譯器指南

為了反映這些準則 (編譯器可以提供建議的語法),我們有幾個範例,並比較兩者的處理方式。

移除中間的欄位

No Ordinals        With Ordinals
----------------   -------------
struct Name {      struct Name {
    T abc;           1: T abc;
-   U def;       -   2: U def;
    V ghi;           3: V ghi;
};                 };
----------------   ---------------
Breaks ABI, no     Breaks ABI,
compiler help      compiler error

移除欄位 (結束)

No Ordinals        With Ordinals
----------------   -------------
struct Name {      struct Name {
    T abc;           1: T abc;
    U def;           2: U def;
-   V ghi;       -   3: V ghi;
};                 };
----------------   ---------------
Breaks ABI, no     Breaks ABI, no
compiler help      compiler help

新增欄位

No Ordinals        With Ordinals
----------------   -------------
struct Name {      struct Name {
    T abc;           1: T abc;
+   U def;       +   3: U def;
    V ghi;           2: V ghi;
};                 };
----------------   ---------------
Breaks ABI, no     Breaks ABI, no
compiler help      compiler error

重新排序欄位

No Ordinals        With Ordinals
----------------   -------------
struct Name {      struct Name {
+   U def;       +   2: U def;
    T abc;           1: T abc;
-   U def;       -   2: U def;
    V ghi;           3: V ghi;
};                 };
----------------   ---------------
Breaks ABI, no     Safe
compiler warning

不允許「保留」的關鍵字

由於我們要調整結構體的序數規則,因此可以一併允許「保留」關鍵字。

我們也應該執行完全相反的做法:正確剖析保留關鍵字的意外使用,並提供明確的編譯器錯誤和說明。例如:「無法保留結構中的成員。新增或移除成員會變更結構版面配置,請考慮改為手動初始化中立成員。」

另外還有一個重要原因,不允許保留關鍵字:

  1. 與資料表不同,在結構中導入邊框間距時,必須使用明確的大小 (即位元組數)。
  2. 當開發人員需要特定的記憶體版面配置時,在結構中使用邊框間距是出於非常具體的用途。這種用途極少發生,甚至不存在,因為 FIDL 版面配置一律對齊 8 個位元組。
  3. 在實作時,我們已說明並解釋「RFC-0066:Programmer Advisory Explicit Defaults」的規定,確保特定值初始化後,某些繫結 (例如 C, LLCPP) 太高。因此,如果在結構中導入「預留的」運算單元,我們就必須向後端公開這個運算單元,以便開發人員順利初始化。這些似乎不需要。

在 JSON (紅線) 路上

為同時支援欄位排序 (依序數) 和文件排序 (應採用宣告順序),建議您:

  • 以「成員」鍵中欄位的顯示順序呈現宣告順序。
  • 導入「一般」鍵的表示序數順序。

設計

未定

導入策略

  1. 開始支援新語法,同時支援舊版語法;
  2. 將所有來源檔案遷移至新語法;
  3. 在使用之前的語法時新增警告,並預留一週的週期,確保先前不會新增任何之前語法的新用途。
  4. 停止支援舊版語法。

人體工學

本提案透過語法將 ABI 的影響傳達給開發人員,藉此改善人體工學。請參閱下文的反轉檢視畫面

說明文件與範例

至少:

回溯相容性

與來源層級回溯不相容。請參閱實作策略,以進行軟遷移。

效能

沒有影響。

安全性

沒有影響。

測試

fidlc 中進行單元測試,可互相驗證:

  • 剖析;
  • 序數從 1 開始,而且不能有間隔;
  • JSON IR 沒有任何變更。

缺點、替代方案和未知

替代做法:資料表的序數雜湊

我們也考慮使用資料表的序數雜湊:語法變更會捨棄明確的序數,讓結構體成為具有這個語法的唯一宣告 (先前用於通訊協定和資料表)。

首先,具有結構體的明確序數的優點仍將保留。開發人員仍可透過語法重新排序欄位,變更序數可能表示 ABI 故障。

其次,由於執行時間成本 (效能較低) 優於人體工學的好處,我們不太可能採取任何行動來移除資料表的序數。

缺點:結構體和表格可能會混淆

由於結構體和資料表會聚合的語法以及序數的語法,有些人可能會混淆結構與資料表,而誤以為移除欄位與 ABI 相容。移除結構體中間的欄位時,由於序數序列中出現缺口,可能造成錯誤,移除具有最大序數的欄位即可無聲。

先前的圖片和參考資料

未定