RFC-0097:FIDL 工具鍊 | |
---|---|
狀態 | 已接受 |
區域 |
|
說明 | 標準化 FIDL 工具鍊的說明。 |
Gerrit 變更 | |
作者 | |
審查人員 | |
提交日期 (年-月-日) | 2021-04-27 |
審查日期 (年-月-日) | 2021-05-26 |
摘要
我們會說明 FIDL 工具鍊必須符合的要求,並提供分解此問題的方法。
雖然具體實作計畫超出本 RFC 的範圍,但我們預期工具 (例如 fidlc
、fidlgen_go
、banjo
) 和 Fuchsia 來源樹狀結構中的建構規則 (例如 fidl_library.gni) 會隨著需求演進,以符合本文所列的條件。
此外,Fuchsia 來源樹狀結構以外的 FIDL 工具鍊應符合此處列出的規定。(這個 RFC 沒有超出 Fuchsia 的權限,因此我們無法強制遵循,但絕對會強烈建議遵循。)
術語
開始之前,讓我們先定義幾個術語。FIDL 工具鍊的簡易版檢視畫面可概述如下:
FIDL 語言由 fidlc
代表,後者代表前端編譯器 (或簡稱前端)。這就是所有語言驗證作業發生的地方。
前端會為每個編譯的 FIDL 程式庫產生中介表示法 (稱為 JSON IR)。儘管名稱如此,中繼表示法不一定需要以 JSON 檔案呈現。
接著,一或多個backends會處理 JSON IR,以產生輸出內容。請注意,從 FIDL 工具鍊的角度來看,任何 JSON IR 使用者都是後端。
產生的輸出內容通常是目標語言 (例如 C++ 或 Rust) 中的程式碼,可用於操作類型、與通訊協定互動、開啟服務,以及使用常數。這類後端稱為 FIDL 繫結1,且產生的程式碼應遵循繫結規格。我們通常會使用 fidlgen (或 fidlgen_<suffix>
,例如 fidlgen_rust
或 fidlgen_dart
) 做為縮寫,用於參照產生 FIDL 繫結的後端。我們將網域物件稱為目標語言中的類別和類型組合,用於表示 FIDL 類型。舉例來說,FIDL 列舉 fuchsia.fonts/Slant
會在 C++ 中 (以 enum class
的形式) 或 Go 中 (以 type Slant uint32
的形式) 擁有對應的網域物件。
還有許多其他後端,每個後端都有各自的需求和特質。舉例來說:fidldoc
會產生 FIDL 說明文件,例如 fuchsia.fonts 頁面;fidl_api_summarize
會產生 FIDL 程式庫的 API 摘要;fidlcat
會使用 JSON IR 提供執行階段的內省功能。從 FIDL 工具鍊的角度來看,fidlcat
工具是後端,但這只是該工具實際執行的功能的一小部分。
提振精神
FIDL 已逐漸成熟。我們已測試其工具鍊的可表達性。無法充分滿足新規定。需要新的擴充工具鍊。
我們首先說明這些新規定,接著說明如何支援所有規定。
整個節目檢視畫面
目前,FIDL 工具鍊會假設後端會依程式庫個別運作,因此只需要該程式庫的 JSON IR 即可運作。
後端需要存取多個 JSON IR,才能滿足需求。
舉例來說,fidldoc
需要所有正在記錄的程式庫的 JSON IR,才能產生全域索引。fidlcat
也是如此,需要檢視所有程式庫才能運作。measure-tape
需要透過產生測量帶的目標類型,間接存取的程式庫 JSON IR。
滲透中繼資料
部分後端需要關於程式庫的特殊中繼資料才能運作。通常,這些中繼資料必須從程式庫依附元件樹狀結構的葉節點 (「基本程式庫」) 開始,以遞迴方式計算,並將中繼資料滲透到根節點 (正在編譯的程式庫)。
舉例來說,[fidlgen_rust
] 想知道類型是否可能包含浮點數,以便判斷哪些特徵可安全地衍生。不含任何浮點數的 struct
可以有 Eq
,且不含任何浮點數的 strict union
變體也可以有 Eq
,但目前沒有浮點欄位的 flexible table
則無法有 Eq
,因為提供 Eq
會違反來源相容性規則。
另一個例子來自 fidlgen_cpp
,該例子會產生非擁有網域物件。如果這些網域物件的內嵌部分是值,也就是不是資源,就可以安全地複製這些物件。同樣地,計算這個我們稱為「內嵌資源性」的中繼資料,需要從葉節點到根節點重複計算這個值。
最近,在討論為程式庫產生 ABI 指紋的新後端時,我們來回討論功能應存在的位置。目前的想法是基於實際原因,將這項功能託管在 fidlc
編譯器中,但這個答案並不理想。
我們觀察到,需要中繼中繼資料的功能要不就是擱置,要不就是以不正規的方式解決,要不就是轉換為新的編譯器功能,通常會過早強制一般化 (例如上述討論的 ABI 指紋)。
此外,由於 Fuchsia FIDL 團隊能夠輕鬆變更編譯器,因此我們在這方面比第三方更具優勢。因此,我們可以說工具的狀態會損害我們的開放原始碼原則,因為我們希望所有後端都能在公平的競爭環境中運作。
每個目標語言和每個程式庫後端選項
隨著 FIDL 語言用於描述核心 API,以及Driver SDK 的開發工作即將展開,FIDL 已日益普及。
不過,目前工具鍊中 FIDL 語言」和「後端」之間,有著處理特定程式庫的混淆情形。如果目標需要程式庫 fuchsia.fonts
的 Rust 程式碼,我們會叫用 fidlgen_rust
。
這種做法太過簡單,無法說明特定程式庫需要專屬的後端。舉例來說,library zx;
會由 kazoo
處理。這種每個目標、每個程式庫的 fidlgen 選取方式會產生進一步的影響。以 zx/clock
為例,我們希望 kazoo
有朝一日能產生目前手寫的 zx_clock_t 型別定義,以及各種 #define
實體化 zx/clock
的成員。如果 fuchsia.fonts
程式庫依賴 zx/clock
,這表示 fidlgen_cpp
需要知道 API 合約,才能產生繫結程式碼,以便正確連結2其程式碼產生作業和 kazoo
的程式碼。
每個平台一個程式庫
目前,我們不建議使用多個名稱相同的 FIDL 程式庫定義。您可以在來源樹狀結構的不同位置定義多個程式庫 fuchsia.confusing
(但不建議這麼做),並獨立使用所有這些不同的程式庫。
因此,建議您採用平台 ID 概念,在 Fuchsia 來源樹狀結構中,預設為 fuchsia
。我們可以保證並強制執行,確保不會有兩個同名程式庫的定義。
考量這項限制,我們將「平台」定義為共用相同平台 ID 的 FIDL 程式庫集合。
不驗證延遲
目前,後端不允許選擇可能成功或不成功的 FIDL 程式庫。後端應處理任何有效的 JSON IR。這項限制表示我們會避免在後端執行任何延遲驗證。您可以在後端新增驗證機制,以便識別尚未實作的 FIDL 功能;另一個驗證範例是檢查 fidldoc
中的文件註解是否有效,並拒絕產生參考文件。(在兩個範例中,預期會出現優雅降級情形)。
允許延遲驗證會導致令人不悅的遠端中斷情形 (例如 https://fxbug.dev/42144169):在 FIDL 程式庫以 SDK 構件提供並整合至後端存放區的情況下,執行後端的開發人員可能與 FIDL 程式庫作者不同。因此,如果要修正的項目由 FIDL 程式庫作者負責,那麼向使用 FIDL 程式庫的開發人員提供警告或錯誤,充其量會讓人感到沮喪,最糟的情況是,使用 FIDL 程式庫的關鍵因素。
因此,禁止晚期驗證的政策已為 fidlc
編譯器維持健康的壓力,以便「驗證所有項目」,並為後端提供「支援所有項目」的功能。這在很大程度上避免了這種遠端中斷失敗,但代價是缺乏細微差別的狀態 (「在後端中沒有驗證」)。
限制來源存取權
我們並未多加考慮長期後果,而是逐漸允許 JSON IR 複製部分 FIDL 來源。舉例來說,隨著更複雜的運算式加入,我們公開已解析的值,以便後端能夠發出常數,同時在 IR 中保留運算式本身 (文字)。雖然提供運算式文字可在產生的程式碼中產生有意義的註解,但這也可能降低 SDK 發布者 (發布 FIDL 構件) 的隱私權,因為他們無法輕易選擇是否要提供來源。
不難想像,未來會有更多 FIDL 來源會透過這個途徑進入 IR,這並非理想的結果:這不僅會造成重複,還可能導致隱私權界線遭到侵犯。
我們希望設計的 FIDL 工具鍊只包含必要的來源。對於少數需要來源存取權的後端 (例如 fidl-lsp
),我們會使用跨度的參照。請參閱設計部分的詳細說明。
縮放編譯
為了簡化操作,fidlc
編譯器最初的設計是只在來源 (即 .fidl
檔案) 上運作。當程式庫具有依附元件時,編譯程式庫就必須依序編譯其所有依附元件。
舉例來說,編譯 fuchsia.fonts
程式庫時,我們也必須編譯 fuchsia.mem
和 fuchsia.intl
程式庫,並以此類推。這表示今天的編譯作業完全沒有效率。核心程式庫 (例如 fuchsia.mem) 會多次重新編譯。這種架構效率不彰的問題從未造成問題:目前 SDK 中的 FIDL 原始碼行數僅略多於 64K,且由於間接依附元件相對較少,因此不會明顯感受到這種效率不彰的問題。
不過,在思考「理想」的 FIDL 工具鍊時,我們希望能遵循編譯器設計的標準做法。傳統上,編譯器會接收輸入內容 (例如來源檔案),並產生輸出內容 (例如 x86 組合)。隨著程式碼集的擴增,編譯器必須能夠提供某種工作區隔,例如輸入內容的微小更新不需要重新編譯整個程式碼集。
以 javac
編譯器為例:如果您變更某些檔案 SomeCode.java
中的 for
迴圈條件,就必須重新編譯數千個檔案,才能再次執行程式,這會造成不必要的麻煩。您只需重新編譯該單一檔案,即可重複使用所有其他預先編譯的來源 (做為 .class
檔案)。
為了成功分割工作,標準做法是定義編譯單元 (例如 FIDL 的程式庫),並產生中間結果 (例如 JSON IR),讓編譯程序的輸入內容同時是來源和直接依附元件的中間結果。這樣一來,您就能將總編譯時間 (假設無限並行) 限制在編譯時間最長的依附元件鏈結上。這也簡化了建構規則,這是du jour主題。
設計
我們將設計分為三個部分:
- 首先,指導原則可提供設計選擇的參考依據,並錨定採用的方法和路徑;
- 說明 標準 FIDL 工具鍊,以此為例說明如何分解 FIDL 建構作業,以便考量所有說明的需求。
- 最後,Fuchsia FIDL 團隊會進行一些特定清理作業,讓核心工具與本 RFC 的指導方針保持一致。
指導原則
IR 應能輕鬆支援常見的後端
雖然複雜的後端應可行 (例如整個程式檢視畫面),但 IR 必須設計成只處理所處理程式庫的單一 IR,才能建構常見的後端。
根據經驗,大多數後端都相當簡單。我們會以簡單的用途 (而非專家用途) 為目標,盡可能簡化 IR,並以此確保後端生態系統蓬勃發展。
舉例來說,請考慮在 fidlc
中執行的「型別形狀」計算。您可以將這項作業移至專用的彙整後端。不過,這會強制所有產生目標程式碼的後端 (主要用途) 同時依賴 IR 和這個「型別形狀」後端。
IR 應保持在最低程度
為了方便納入常見的後端,您必須盡力追求最小化,因為「包含所有東西」很容易 (或很誘人),但這並非完成工作的唯一方法。
舉例來說,在 fidlc
中計算「宣告順序」的現行反模式。只有少數後端會依循這個順序 (C 家族,甚至每天更少),而且會讓編譯器變得過度複雜。這也讓人難以理解為何需要這類命令,且經常造成混淆。由於後端應獨立於核心編譯器發展,因此這項做法也缺乏彈性,這也是阻礙支援遞迴型別的進展的原因之一。
IR 不得包含來源
IR 應只包含必要的來源,以便輕鬆容納常見的後端 (例如名稱)。IR 可視情況提供來源跨距參照。來源區間參照是三元組:
(filename, start position, end position)
其中位置為元組 (line number, character number)
。
後端不應仰賴來源存取權才能運作。如果後端必須具備來源存取權才能運作 (例如 fidl-lsp
),則必須明確指出這項要求,並在無法存取來源時適當失敗。
在選擇這個分解作業時,我們會明確選擇為 SDK 發布者 (發布 FIDL 構件者) 提供是否要納入來源 FIDL 的選項。目前,由於來源的部分內容會進入 IR,因此這並非完全由他們自行決定。
除了名稱之外,IR 中的重要來源就是說明文件註解。這些註解依規格而言是 API 的一部分,也就是 FIDL 程式庫作者明確選擇將這些註解公開。此外,大多數後端都會使用這些說明文件註解 (例如在產生的程式碼中發出註解),因此符合「隨時可支援常見後端」原則。這些文件註解不會以原始來源形式顯示在註解中,而是會經過一些預先處理 (前置縮排、///
和空白字元會裁剪)。如簡短介紹,我們打算日後進一步處理文件註解。
後端一視同仁
FIDL 語言、其作為 fidlc
編譯器的實作方式,以及中介表示法的定義,應設計為允許包容的後端生態系統,其中所有後端 (無論是否以 Fuchsia 專案的一部分建構) 都處於平等地位。
在選擇這條分界線時,我們明確做出選擇,避免為 Fuchsia FIDL 團隊擁有的後端,提供短期需求的便捷性,而是著重於 FIDL 生態系統的長期可行性。
後端不會發生錯誤
後端在處理有效的 IR 時必須成功。如果後端在環境中遇到問題 (例如檔案系統存取錯誤),或是 IR 無效,後端可能會失敗。如果後端無法處理符合 IR 結構定義的 IR,則不得發生錯誤。
在選擇這條分界線時,我們會明確強制所有驗證作業都在前端執行,也就是說,驗證作業必須提升為 FIDL 語言限制。這麼做有兩個重要原因:
- 這項規則的推論是,如果有有效的 IR,則可使用與此 IR 相容的所有後端。也就是說,如果您是 SDK 發布者,只要確保 FIDL 程式庫能順利編譯,所有使用者都能使用這些程式庫,前提是他們使用的 FIDL 工具鍊版本與發布者使用的版本相容。
- 從語言設計的角度來看,這項非常嚴格的規定是有利的強制函式,可確保語言設計符合後端的需求。舉例來說,如果某個謹慎的後端擁有者基於某些原因需要驗證,就會向 Fuchsia FIDL 團隊提出這個問題 (fidl-dev@fuchsia.dev 或透過 RFC),以便在語言規格中納入。這可能會改善語言,讓所有人都能從中受益,或是重新調整後端,讓後端更符合 FIDL 工具鍊原則。
舉例來說,請考慮 Rust 中的特徵衍生:Eq
特徵無法衍生含有浮點數的型別。您可以將屬性 @for_rust_has_floats
新增至含有浮點數 (float32
或 float64
) 的 FIDL 類型,然後在 fidlgen_rust
中利用這項屬性,以條件方式發出 Eq
特徵,並驗證是否正確使用這項屬性 (類似於 值-資源區分)。但這項誘惑違反了原則,因為這表示 fidlgen_rust
可能有誤。在 fidlc
中驗證這類專屬屬性也不理想,因為這會導致 FIDL 因眾多目標語言特定問題而變得複雜。3
標準 FIDL 工具鍊
標準的 FIDL 工具鍊以程式庫分解為主,並會包含兩種建構節點。
滲透建構節點
滲透節點會將程式庫的來源和程式庫直接依附元件的物件檔案提供給工具,並產生最終結果和目標物件檔案。
舉例來說,目前大多數的 fidlgen 後端都遵循以下模式:來源是 JSON IR,最終結果是產生的程式碼。這些工具沒有依附物件檔案 (DOF),也不會產生目標物件檔案 (TOF)。
另一個例子是預定的 ABI 指紋記錄工具,需要計算類型的結構性屬性。這項工具會使用 JSON IR (來源),並產生 ABI 摘要 (最終結果) 和隨附的目標物件檔案 (TOF)。在處理具有依附元件的程式庫時,系統會使用這些程式庫的 TOF (即 DOF),以及 JSON IR,以產生下一個最終結果。最終結果和 TOF 可能只有格式不同,因為前者是供人類閱讀,後者則是供工具剖析。
整個檢視畫面建構節點
整個檢視節點會提供來源,包括所有可透過轉換存取的依附程式庫,以便產生最終結果。
舉例來說,measure-tape
需要所有可透過遞迴存取的程式庫的 IR,才能定義要編譯的類型,而這類型會自然地以整個檢視節點表示。目前,fidlc
節點會以整個檢視區塊節點的形式運作,因為它需要存取所有來源才能運作 (詳情請參閱「縮放編譯」)。fidlcat
和 fidldoc
都需要整個檢視畫面,並依附於正在編譯的整個 fuchsia 平台。
雖然整個檢視節點的效率確實不如滲透節點,但我們可能不想重新建構所有工具,以便以滲透方式運作,而是選擇將部分複雜度推入建構系統。
在 Fuchsia 來源樹狀結構建構作業中,我們會產生 all_fidl_json.txt 檔案。有了更明確的整體檢視節點需求,我們就能更妥善地建構這項匯總資料。舉例來說,如果將這項匯總資料依平台分類,並為每個程式庫記錄其來源、JSON IR 和直接依附元件,我們就能輕鬆利用這項匯總資料,快速產生全貌檢視工具所需的輸入內容。開發人員工具 (例如 fidl-lsp
或 fidlbolt
) 也會使用這項匯總資料。
工具選項
特定建構節點中的工具選取應取決於目標 (例如「產生低階 C++ 程式碼」),以及要編譯的程式庫 (例如「library zx」)。我們定義的總函式會接收元組 (目標生成器、程式庫),並傳回工具 (例如 kazoo
或 fidlgen_cpp
),做為工具鍊的全域設定。
舉例來說,在 Fuchsia 來源樹狀結構中,我們預期的設定如下:
(*, library zx) → kazoo
(low_level_cpp, not library zx) → fidlgen_llcpp
(high_level_cpp, not library zx) → fidlgen_hlcpp
(rust, not library zx) → fidlgen_rust
(docs, *) → fidldoc
使用統一 C++ 繫結後,這項設定會變更為:
(*, library zx) → kazoo
(cpp, not library zx) → fidlgen_cpp
(rust, not library zx) → fidlgen_rust
(docs, *) → fidldoc
對增量編譯的影響
當您查看增量編譯作業 (即透過將現有編譯的構件與新編譯的構件結合,以最少的工作量回應來源變更) 時,這裡所述的兩種節點就會有所不同。
一般來說,當其中一個或多個來源 (也稱為「來源集合」) 發生變更時,就需要叫用編譯圖中的節點。
與整個檢視節點相比,滲透節點的來源集合較小,因為其來源集合是直接的「來源」和目標物件檔案 (TOF)。不過,如果使用了這些節點的滲透行為,就會將來源變更傳播至 TOF 變更,進而變更依附滲透節點的來源集。舉例來說,假設 fidlgen_rust
後端經過擴充,也能產生 TOF fuchsia.some.library.fidlgen_rust.tof
。當一個程式庫變更時,如果其 TOF 也變更,則所有相依的程式庫也需要變更,進而導致對 fidlgen_rust
後端的叫用次數增加 (依此類推)。
與滲透節點相比,整個檢視節點的來源集更廣泛。整個檢視區塊節點可分為兩大類,一類是依賴所有傳遞式依附元件 (例如 measure-tape
),另一類則是依賴平台中的所有程式庫 (例如 fidldoc
)。因此,任何變更都可能導致需要叫用這些節點。
整個檢視區塊節點的增量編譯成本是雙重打擊,這些節點需要更頻繁地執行,且由於檢視更多來源,因此會執行更多工作。只要稍微調整一下 (有人說這只是「簡單的程式設計問題」),任何需要完整檢視畫面的後端都能演變為滲透節點。考慮這種演進方式 (通常會帶來許多複雜性和維護負擔) 的健康壓力,就是考量漸進式編譯的速度優勢,並在成本難以負擔時嘗試採用這種做法。
除了工具鍊本身的逐漸增加編譯成本外,也要考量後續影響。由於大多數工具鍊都會產生原始碼 (例如 C++、Rust、Dart),因此會更接近整體建構圖的根節點,因此對工具鍊輸出的任何變更 (例如對產生的 C++ 標頭進行變更) 都會對下游編譯作業造成重大影響 (例如所有程式碼都直接或間接地依賴這個產生的 C++ 標頭)。因此,請盡量減少對產生來源的變更。例如,將產生器的輸出內容標準化 (避免變更無意義的空白字元),或將輸出內容與快取版本進行比較,以免覆寫內容,進而避免只變更時間戳記 (請參閱 GN 輸出內容的詳細資訊範例)。
清理舊有技術債,避免產生更多技術債
根據這裡所述的原則,我們將從 fidlc
移除 C 繫結和編碼表產生功能。由於過去的建構作業複雜,因此我們將這兩種產生方式嵌入核心編譯器。
我們也打算從 IR 中移除「宣告順序」,改為將任何特殊排序推送至特定後端。
如擴充編譯一文所述,FIDL 編譯器 fidlc
會進化為分割工作,只要求直接依附元件的輸出內容 (可能是 JSON IR 本身),而非所有傳遞依附元件的來源。
最後,我們將避免累積更多技術債,而是專注於讓工作與這裡所述方向一致。舉例來說,下一個要考慮的後端 ABI 指紋會是滲透後端,而不是嵌入核心編譯器。
既有技術
請比較/對比這項作業與 C++ 編譯:C++ 編譯器通常會讀取一個 C++ 來源檔案,並產生一個物件檔案。在稱為「連結」的最終程式組合階段,連結器會將所有物件檔案合併為一個二進位檔。這種做法有效的原因是,在獨立編譯一個 C++ 來源檔案時,編譯器會透過使用標頭,在目前檔案所依賴的其他 C++ 來源檔案中,看到外部函式的函式宣告。同樣地,我們目前的 JSON IR 會提供外部程式庫類型的最少資訊,類似於函式宣告。
不過,如果您想要進行更深入的最佳化,這個 C++ 編譯模式的表現就會不佳:當編譯器只能查看宣告時,就必須非常保守地處理函式的實際行為 (例如,函式是否一律終止?是否會變異指標 X?是否會保留指標 Y,進而讓指標逃逸?)。同樣地,在 FIDL 中,如果程式碼產生後端能夠進一步瞭解所參照的外部型別,就可能產生更精簡且更優質的程式碼。在資源性和來源相容性方面,我們的規定導致後端無法產生正確的程式碼,除非後端知道所有參照外部類型的資源性。
為解決這個問題,在 C++ 中,各種編譯器實作開始在物件檔案中注入越來越多的輔助資料。舉例來說,GCC 和 Clang 都開發了可序列化的 IR 格式,進一步說明這些 C++ 函式的行為,並將這些函式與其組合包裝在一起。連結器會同時使用組譯和 IR,並產生更優質的程式碼 (稱為連結時間最佳化)。在 FIDL 中,由於各種後端可能需要不同的外部類型知識,因此將「輔助資料」與「物件檔案」分離,也就是在主要 JSON IR 旁邊產生後端專屬的附屬檔案,可能會更有益處。確實,許多後端都需要資源性質這項常見屬性。不過,在未來,LLCPP 在產生關閉句柄的程式碼時,會希望知道類型是否間接包含離線物件 (同樣適用於編碼和解碼);Rust 則會決定類型是否間接包含浮點值,以便在更多情況下衍生 Eq (但需要編譯器保證,才能避免來源相容性問題)。
說明文件
這份 RFC 可做為改善 FIDL 工具鍊文件的基礎,我們鼓勵工具鍊作者妥善記錄所提供的建構規則。
實作
如先前所述。
成效
不會影響效能,此 RFC 說明瞭已達成的必要條件和問題分解作業,但並未以清晰的方式達成。
人體工學
不適用。
回溯相容性
不適用。
安全性考量
沒有安全性考量。
隱私權注意事項
將來源與 IR 分開,可改善隱私權。
測試
工具鍊的標準測試。
缺點、替代方案和未知事項
如文中所述。
-
從技術層面來說,我們稱 FIDL 繫結為程式碼產生工具、使用產生程式碼所需的支援執行階段程式庫,以及產生的程式碼。 ↩
-
C 系列 fidlgen 不會為
zx/clock
產生自己的網域物件,而是選擇#include
從kazoo
產生的標頭。同樣地,Rust fidlgen 會匯入kazoo
產生的zx
繫結,而不是根據zx
程式庫定義產生自己的網域物件。 ↩ -
目前我們無法將
@has_floats
屬性 (或has_float
修飾符) 新增至 FIDL,因為唯一的用途是在fidlgen_rust
中,而且即使在那裡,也不是重大問題。如果這些情況有所變動 (例如其他幾個後端有類似的PartialEq
/Eq
問題),則可能有必要進行調整。 ↩