RFC-0036:結構宣告更新

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

為了更清楚說明重新排序和重新命名欄位的 ABI 影響,我們建議進行語法變更,為結構體欄位引入序數,並採用與資料表相似的語法規則。

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

拒絕理由

優點

  • 對於名稱是否對 ABI 重要,存在著疑惑:xunion、結構體和通訊協定都看起來很相似,但規則不同。

缺點

  • 不過,所有相關人士都認為,在結構體中引入序數會造成的混淆遠遠大於這項優點,尤其是與 protobuf 相比。

  • 我們也正在著手處理「是否會變更 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 的角度來看,我們觀察到以下幾點:

  • 重新排序:除了結構體之外,所有項目都可以重新排序,不會造成任何影響。
  • 重新命名:
    • 結構體、表格、列舉和位元可重新命名,不會造成任何影響
    • 通訊協定和 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

禁止使用「reserved」關鍵字

由於我們會將結構體的序數規則與資料表的序數規則對齊,因此我們可以考慮也允許使用「reserved」關鍵字。

我們應該採取相反的做法:正確剖析誤用保留字的情況,並提供清楚的編譯器錯誤和說明。例如「無法在結構體中保留成員。新增或移除成員會改變結構版面配置,建議您改為手動初始化中立成員。」

以下還有其他重要原因,允許使用「保留」關鍵字:

  1. 與表格不同,在結構體中引入填充值時,必須使用明確的大小 (即位元組數);
  2. 在結構體中使用填充值,是為了特定用途,例如開發人員需要特定記憶體配置。由於 FIDL 版面配置一律會對齊 8 個位元組,因此這種用途很少見,甚至不存在。
  3. 在實作方面,我們已在 RFC-0066:程式設計師建議明確的預設值 中說明,保證特定值會初始化,對於特定繫結 (例如 C、LLCPP) 來說,這項要求過於嚴格。因此,如果我們要在結構體中引入「保留」的空格,就必須將其公開給後端,以便向開發人員公開,以便進行適當的初始化。這一切似乎都不是必要的。

未來的 JSON IR

為了同時支援欄位排序 (依序號) 和為文件目的排序 (應遵循宣告順序),建議您:

  • 宣告順序代表「members」鍵中欄位的呈現順序。
  • 透過引入「ordinal」鍵來表示序數。

設計

未定

導入策略

  1. 同時支援新語法和舊語法;
  2. 將所有來源檔案遷移至新語法。
  3. 在使用舊版語法時加入警告,並提供一週的時間,確保不會新增舊版語法的使用方式;
  4. 停止支援舊版語法。

人體工學

本提案透過語法向開發人員傳達 ABI 影響,以改善人因工程。請參閱下方的相反觀點

說明文件和範例

至少:

回溯相容性

這不是源碼層級的回溯相容性。請參閱實作策略,瞭解如何進行軟遷移。

成效

沒有影響。

安全性

沒有影響。

測試

fidlc 中進行單元測試,驗證以下項目:

  • 剖析;
  • 序數從 1 開始,且不得有空缺;
  • JSON IR 沒有任何變更。

缺點、替代方案和未知事項

替代方案:為資料表進行序號雜湊

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

首先,為結構體提供明確的序數的好處仍會保留。開發人員仍可透過語法重新排序欄位,而變更序數會表示 ABI 損壞。

其次,我們不太可能根據探索結果從表格中移除序數,因為執行時間成本 (較低的效能) 與人體工學效益之間的權衡,會超過人體工學效益。

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

由於結構體和資料表之間的語法趨於一致,且引入了序數,因此有些人可能會將結構體與資料表混淆,並誤以為移除欄位與 ABI 相容。雖然移除結構體中間的欄位會因序數序列出現空隙而導致錯誤,但移除具有最大序數的欄位則不會造成任何影響。

既有技術與參考資料

未定