RFC-0024:強制原始碼相容性 | |
---|---|
狀態 | 已接受 |
領域 |
|
說明 | 為 FIDL 語言繫結制定來源相容性標準,以及演進該標準的流程。 |
作者 | |
提交日期 (年月分) | 2019-04-02 |
審查日期 (年-月-日) | 2019-04-11 |
摘要
為 FIDL 語言繫結建立來源相容性標準,以及演進該標準的程序。
提振精神
目前,語言繫結產生的程式碼有一些撰寫規則。一般是預期符合特定線路 ABI,但繫結作者對 API 形狀的方式有很多種。任何 FIDL 定義有所變更,都會對產生的繫結產生任意變更。
實際上,使用者會預期某種「常識」清單,且應與來源相容,例如定義新的頂層類型。不過,目前並沒有明確的規定。 雖然這個案例看起來不太好,但它展現了缺乏規格會如何破壞使用者的期望。實際範例包含在資料表中新增欄位、新增 xunion 變化版本,或是在結構中新增預設欄位。使用者可合理預期這些變更不會造成原始碼中斷,但並未指定這類變更,且所有變更都會導致目前一或多個語言繫結的來源層級故障 (例如在 C++ 或 Go 中位置初始化器,或 Rust 中的結構模式)。
此外,某些 FIDL 語言繫結的擴充功能過去曾因與來源相容性互動而遭到拒絕。例如在不含控點的類型中加入 copy
或 clone
函式。無法複製含有任意控點的類型,因此為類型新增控制點會導致該類型無法提供 clone
函式 (或無法以任何速率提供「可正常運作」的本機副本函式)。基於缺少控點而將 clone
函式有條件納入為產生 Rust 繫結的變更,已多次遭到拒絕,其原因是其對來源相容性的影響。因此,Fusia 開發人員必須手動擲出自己的 clone
函式,並針對透過這些手動捲動方法 clone
的 FIDL 產生的類型新增包裝函式類型。本文件提出一致的標準,我們希望能藉此評估功能,這希望能為開發人員提供更符合人體工學、容易使用且無樣板的使用體驗。
設計
流程
這個 FTP 會建立一組原始的相容性限制。系統會透過 Fuchsia 來源樹狀結構的文件追蹤這份清單。 您必須使用 FTP 程序新增其他來源相容性限制。為了輕鬆新增與新功能相關的來源相容性規則,我們修訂 FTP 範本的「回溯相容性」部分,加入新來源相容性限制的建議 (如適用)。
定義:來源相容性和轉換性
以下變更必須與來源相容 (即非原始碼中斷) 或可轉換。
與來源相容的變更不得造成來源中斷,避免對所產生 FIDL 繫結的有效 (編譯) 使用 API 造成破壞。有一些合理引數會限制初始 API 屬於「公用 API」的一部分功能;此外,這些引數的可行性亦不可如此。因此,本文中的「公用 API」應視為使用不需要額外語言體操 (例如反射) 或開發人員明確語言 API 的繫結,因而不得違反__private_dont_use_me_function_2()
「可轉換」變更是指「可以」編寫程式碼,可在變更前後編譯。每個可轉換的來源相容性規則都必須明確指定在轉換期間必須執行的 API「用途」。
初始來源相容性限制
以下列出必須與來源相容的變更:
- 新增頂層項目 (通訊協定、類型或常數)。
- 動機:使用者會期望在不中斷 FIDL 程式庫的現有使用者的情況下,宣告新的通訊協定、類型和常數。
- 豁免:如果從命名空間匯入使用「*」或大量匯入項目,可能會導致不同程式庫中多個名稱相同的項目之間出現差異,導致用量中斷。
- 新增欄位至非嚴格資料表。
- 動機:資料表是為易於擴充,且應在不中斷的情況下支援額外欄位。如要選擇加入故障,可以使用
strict
修飾符。
- 動機:資料表是為易於擴充,且應在不中斷的情況下支援額外欄位。如要選擇加入故障,可以使用
- 將變化版本新增至非嚴格的可延伸聯集。
- 動機:可擴充的聯集專為易於擴充而設計,且應在不中斷的情況下支援其他變化版本。如要選擇採用破壞性,可使用
strict
修飾符。
- 動機:可擴充的聯集專為易於擴充而設計,且應在不中斷的情況下支援其他變化版本。如要選擇採用破壞性,可使用
- 將成員新增至非嚴格列舉
- 動機:非嚴格的列舉會以隱含形式選擇可擴展性,因此應該要能在沒有來源中斷的情況下展開。
- 將成員新增至非嚴格的「位元」
- 動機:非嚴格位元會間接啟用可性,因此應該要能在沒有來源中斷的情況下展開
- 將
[Layout = "Simple"]
新增至現有的通訊協定- 動機:已有
[Layout = "Simple"]
,以便在簡易 C 繫結中使用。符合現有通訊協定的現有通訊協定無需變更來源,即可指定可在簡易 C 繫結中使用。
- 動機:已有
- 將
[MaxHandles]
新增至現有類型- 動機:
[MaxHandles]
的目的是提供類型的額外資訊,以便更寬鬆地使用。系統不會要求破壞來源變更,從而指定類型已包含固定的控點數量上限,系統可能會假設該類型繼續包含最多的控點。
- 動機:
以下列出必須可轉移的變更:
- 將
[Transitional]
新增至方法- 使用:您必須能夠實作通訊協定,並在將
[Transitional]
屬性新增至該方法前後,採用相同的來源實作方法。 - 動機:必須能夠逐步新增或移除通訊協定的方法,但前提是所有現有的實作項目都能逐步進行調整。
- 使用:您必須能夠實作通訊協定,並在將
- 新增
[Transitional]
方法- 使用:實作新的
[Transitional]
方法前後,必須採用相同的來源實作通訊協定 (但 API 不允許在轉換期間實作該方法)。 - 動機:必須能夠逐步新增或移除通訊協定的方法,但前提是所有現有的實作項目都能逐步進行調整。
- 使用:實作新的
- 移除
[Transitional]
方法- 使用:在移除
[Transitional]
方法前後,必須使用相同的來源實作通訊協定 (但 API 不允許在轉換期間實作該方法)。 - 動機:必須能夠逐步新增或移除通訊協定的方法,但前提是所有現有的實作項目都能逐步適應。
- 使用:在移除
- 移除非嚴格資料表的欄位
- 使用:在移除資料表欄位之前和之後,您必須能夠使用相同來源建立資料表並存取其欄位 (已移除的欄位除外)。
- 動機:資料表旨在輕鬆演進,且應能在不中斷的情況下移除資料表。如要選擇加入破壞性,您可以在資料表上使用
strict
修飾符。
- 移除非嚴格擴充聯集的變化版本
- 使用:在移除 xunion 變數前後,系統必須能夠建立 xunion 並存取其變化版本 (不包括已移除的變化版本)。
- 動機:x Union 可輕鬆進化,且應在移除時保持良好狀態。如要選擇加入破壞性,您可以在資料表上使用
strict
修飾符。
- 將類型標示為
strict
- 使用:必須可以存取資料表或「位元」的所有欄位,以及在新增
strict
前後,使用同一來源存取列舉或 Xunion 的所有變化版本。 - 動機:
strict
會在類型穩定後加入類型宣告中,以增加推理和開發人員工具。不過,這只需要做為可轉移的變更,而非非破壞性變更,因為擴充類型可能會想允許存取無法辨識的欄位或變化版本。這些功能對strict
類型來說並不合理,因為無法辨識的欄位或變化版本將遭到拒絕。
- 使用:必須可以存取資料表或「位元」的所有欄位,以及在新增
- 將
[Transitional]
新增至列舉或位元、資料表欄位或可擴充聯集的變化版本。- 使用:必須可以存取所有非轉換式成員/位元/欄位/變化版本,以及建構不含
[Transitional]
值且在[Transitional]
導入前後使用相同來源的列舉值。 - 動機:必須能夠逐步移除成員、欄位或變化版本。
- 使用:必須可以存取所有非轉換式成員/位元/欄位/變化版本,以及建構不含
- 新增列舉或位元、資料表欄位或標示為
[Transitional]
的擴充聯集變化版本。- 使用:必須可以存取所有非轉換成員/位元/欄位/變化版本,以及建構新的
[Transitional]
值在新[Transitional]
欄位前後都沒有包含相同來源的列舉/位元/資料表/可延伸聯集值。 - 動機:必須可逐步新增成員、欄位或變化版本。
- 使用:必須可以存取所有非轉換成員/位元/欄位/變化版本,以及建構新的
- 移除列舉或位元的成員、資料表欄位或標示為
[Transitional].
的擴充聯集變化版本- 使用:必須可以存取所有非轉換式成員/位元/欄位/變化版本,以及建構不含
[Transitional]
值的列舉/位元/資料表/可延伸聯集值,而且在移除[Transitional]
欄位前後都使用相同的來源。 - 動機:必須能夠逐步移除成員、欄位或變化版本。
- 使用:必須可以存取所有非轉換式成員/位元/欄位/變化版本,以及建構不含
下列是已從這份清單中省略的潛在限制,包括省略這些限制的理由:
- 在結構中新增或移除欄位 (已指定或不預設)
- 這是 ABI 破壞性變更,因此需要其他重大措施以確保相容的轉換方式。如要做出這項非破壞性變更,必須消除對類型進行「針對所有欄位」樣式的推理,包括自動方法衍生 (例如「這個類型是否包含任何浮點值」)、位置初始化器,以及詳盡欄位比對和建構功能。
- 在嚴格資料表和 xunion 中新增或移除欄位/變化版本 (預設或不設定)
strict
旨在啟用可依賴「所有欄位」樣式推理的額外開發人員工具,包括自動方法衍生 (例如「此類型是否包含任何浮點值」)、位置初始化器,以及詳盡欄位比對和結構。使用此政策並非具破壞性的變更將禁止此目的。
- 將包含控制代碼的欄位或變化版本新增至未標示為
[MaxHandles]
的類型- 基於其他原因,將欄位新增至嚴格類型或結構,屬於原始碼破壞性變更,因此使用處理常式新增欄位類似於破壞性變更,可能會影響產生的 API。
導入策略
這個 FTP 可確立最初提議的語言相容性標準。我們會回報錯誤並指派給每個語言繫結的作者,確保其語言繫結符合規定。
人體工學
這項變更讓 FIDL 更容易使用,方法是針對來源相容性設定明確的標準,以便自動檢查,以及更輕鬆地手動檢查 FIDL 變更的來源相容性,同時為繫結作者提供更清楚的原始碼相容性指引,讓繫結作者能自由做出符合語言語言習慣的繫結,同時仍必須遵守專案的標準要求。
說明文件與範例
接受此 FTP 後,FTP 所建立的程序以及來源相容性規則本身就會與其他 FIDL 參考說明文件一起發布。
回溯相容性
如要應用我們提出的指引,可能需要變更繫結和使用這些繫結的用途,至於相關變更,則是由各個繫結作者決定。
本節 (「回溯相容性」一節) 將修改為包含下列文字:
「如果您要推出新的資料類型或語言功能,請先考量會預期使用者需要進行哪些 FIDL 定義變更,而不會破壞產生的程式碼。如果功能對產生的語言繫結設下任何新的來源相容性限制,請在這裡列出。」
請注意,您應加入來源相容性文字做為這個 FTP 的實際連結,如下所示:
[source compatibility](/docs/contribute/governance/rfcs/0024_mandatory_source_compatibility.md)
效能
此 FTP 不會限制執行階段行為,不過來源 API 的限制可能會導致語言繫結作者設計較多或較少的效能 API。推出新的來源相容性限制時,應考量使用支援語言建立效能繫結的可行性。
這項功能可能會影響編譯時間的效能,因為推送的模式需要更大量的內嵌和編譯器最佳化作業,才能提升效能 (例如將複雜的建構工具 API 最佳化為簡單的結構初始化)。繫結作者應盡力做出不會大幅妨礙編譯時間的設計選擇,但特定語言 API 的編譯時間結果不應不一定能防範新的來源相容性限制。
安全性
這項功能不會影響安全性。
測試
許多來源相容性規則的格式為「在這項變更前,所有編譯過的使用者程式碼都不存在,但這項變更不會生效。」遺憾的是,這些限制很難測試或無法測試,因為需要在變更前列舉 API 的所有可能使用情況。
不過,我們 (也應該) 將項目新增至 FIDL 變更測試套件,以證明在變更後仍然有效的 API 使用前有「部分」使用方式。這只是必要條件,但不足以滿足來源相容性需求。
缺點、替代項目和未知
- 請勿採用這種規格。允許繫結作者選擇他們希望變更的破壞性或非破壞性。這與目前的狀態類似,但會讓繫結作者享有比在目前系統中授予的更多彈性,其中有些來源相容性與託管變更收到了拒絕。
- 建立規格,說明哪些變更「可以」成為來源中斷,而不是「不得」讓哪些變更成為來源中斷。這種做法較難強制執行,而且會要求繫結作者預測其繫結必須保持與來源相容的變更。
- 小幅修改是指定同時指定「本身」且「不是」的變更,並在未指定變更以其中一種方式預設變更,基本上與此 FTP 或上述替代選項基本上是相同的,不過視預設值而定,雖然它可以對記錄不同 FIDL 變更的影響設定了更正式的期望。
優先藝術與參考資料
我們先前曾嘗試透過 [MaxHandles]
屬性,推出變革性限制。本提案的前面部分已討論了這項設計及預期的修改項目。