檢視原始碼 即將發生的潛在不相容性

簡介

本文檔列出了 Erlang/OTP 中計畫的即將發生的潛在不相容性。

OTP 27

Fun 建立者 pid 將永遠是本地 init 程序

從 OTP 27 開始,函數 erlang:fun_info/1,2 將永遠指出本地 init 程序建立了所有 fun,無論該 fun 最初是在哪個程序或節點上建立的。

在 OTP 28 中,{pid,_}元素將完全移除。

功能 maybe_expr 將預設啟用

從 OTP 27 開始,maybe_expr 功能將被核准並預設啟用。這表示使用未引號的原子 maybe 的程式碼將無法編譯。所有將 maybe 作為原子的用法都需要加上引號。或者,作為短期解決方案,可以停用 maybe_expr 功能。

建議盡快為所有使用原子 maybe 的地方加上引號。編譯器選項 warn_keywords 可用於發出關於所有未加引號的 maybe 出現的警告。

0.0 和 -0.0 將不再完全相等

目前,浮點數 0.0-0.0 有不同的內部表示。如果將它們轉換為二進制檔案,就可以看到這一點

1> <<0.0/float>>.
<<0,0,0,0,0,0,0,0>>
2> <<-0.0/float>>.
<<128,0,0,0,0,0,0,0>>

然而,當它們彼此匹配或使用 =:= 運算子比較時,它們被認為是相等的。因此,0.0 =:= -0.0 目前會返回 true

在 Erlang/OTP 27 中,0.0 =:= -0.0 將返回 false,並且將 0.0-0.0 匹配將會失敗。當用作映射鍵時,0.0-0.0 將被認為是不同的。

== 運算子將繼續為 0.0 == -0.0 返回 true

為了幫助找到可能需要修改的程式碼,在 OTP 27 中,當與 0.0 匹配或使用 =:= 運算子比較該值時,將會有一個新的編譯器警告。可以透過與 +0.0 匹配而不是 0.0 來抑制警告。

我們計畫在 OTP 26.1 中引入相同的警告,但預設情況下將停用它。

單例型別變數將變成編譯時錯誤

在 Erlang/OTP 26 之前,編譯器會靜默接受以下規格

-spec f(Opts) -> term() when
    Opts :: {ok, Unknown} | {error, Unknown}.
f(_) -> error.

在 OTP 26 中,編譯器會發出警告,指出型別變數 Unknown 未繫結

t.erl:6:18: Warning: type variable 'Unknown' is only used once (is unbound)
%    6|     Opts :: {ok, Unknown} | {error, Unknown}.
%     |                  ^

在 OTP 27 中,該警告將變成錯誤。

Escript 將預設編譯

Escript 將預設編譯而不是解釋。這表示必須提供 compiler 應用程式。

可以透過在指令碼檔案中新增以下行來還原解釋 escript 的舊行為

-mode(interpret).

在 OTP 28 中,將會移除對解釋 escript 的支援。

-code_path_choice 將預設為 strict

此命令列選項控制是否應將命令列、啟動指令碼和程式碼伺服器中給定的路徑解釋為嚴格或寬鬆。

OTP 26 及更早版本預設為 relaxed,這表示 -pa myapp/ebin 將嘗試載入 -pa myapp/ebin-pa myapp/myapp/ebin。該選項在 OTP 27 中將預設為 strict。

將移除封存回退

OTP 26 及更早版本允許應用程式的部分目錄為常規資料夾,而其他部分為封存檔。此功能之前由 reltool 使用,但從 OTP 26 開始不再如此。將在 OTP 27 中從程式碼伺服器中移除對封存回退的支援。

三引號字串

在 Erlang/OTP 27 之前,3 個或更多雙引號字元的序列會成對分組,每個雙引號都表示空字串,如果為奇數,則最後一個字元為字串的開頭。然後將空字串串連起來,並有效地消失。

在 Erlang/OTP 27 中;3 個或更多雙引號字元將被解釋為「三引號字串」的開頭。請參閱 EEP 64

以下是一些程式碼範例,其含義會發生變化。請注意,在 Erlang/OTP 27.0 之前的所有這些範例都很奇怪,因為沒有合理的理由這樣編寫。

"""String Content"""
%% Was interpreted as
"" "String Content" ""
%% Which becomes
"String Content"
%%
%% In OTP 27 it is instead a syntax error since no text is allowed
%% on the line after an opening triple-quote
"""
String Content
"""
%% Was interpreted as
"" "
String Content
" ""
%% Which becomes
"
String Content
"
%%
%% In OTP 27 it is instead interpreted as a
%% Triple-Quoted String equivalent to
"String Content"
""""
++ foo() ++
""""
%% Became
"" ++ foo() ++ ""
%%
%% In OTP 27 it is instead interpreted as a
%% Triple-Quoted String (triple-or-more) equivalent to
"++ foo() ++"

從 Erlang/OTP 26.1 到 27.0,編譯器會針對 3 個或更多雙引號字元的序列發出警告,因為這幾乎可以肯定是錯誤或類似於糟糕的自動程式碼產生結果。如果使用者收到該警告,則應更正程式碼,例如在空字串之間插入適當的空格,或完全刪除多餘的字串,這將在 Erlang/OTP 27 前後具有相同的含義。

OTP 28

re 模組將使用不同的正規表示式引擎

模組 re 的功能目前由 PCRE 程式庫提供,該程式庫不再積極維護。因此,在 OTP 28 中,我們將切換到不同的正規表示式程式庫。

OTP 團隊修改了 re 模組使用的 PCRE 原始碼,以確保在匹配巨大的輸入二進制檔案和/或使用高要求的(回溯)正規表示式時,正規表示式匹配會產生結果。由於這些修改,遷移到新版本的 PCRE 一直是一個耗時的過程,因為所有修改都必須再次手動應用於更新的 PCRE 原始碼。

最有可能的是,新的正規表示式程式庫將會是 RE2。RE2 保證匹配時間與輸入字串的長度呈線性關係,並且它也會避開遞迴以避免堆疊溢位。這應該可以使在不修改其原始碼的情況下使用 RE2。有關為什麼 RE2 是一個好選擇的更多資訊,請參閱 WhyRE2

此變更的一些影響如下

  • 我們預計將繼續支援 re 模組中的函數,儘管某些選項可能會停止使用。
  • 很可能只會支援 UTF8 編碼二進制檔案的模式比對(而不是 Latin1 編碼的二進制檔案)。
  • 為了保證線性時間效能,RE2 並不支援 PCRE 中正規表示式模式的所有結構。例如,不支援反向參考和環顧斷言。請參閱 Syntax 以了解 RE2 支援的內容。
  • 編譯正規表示式可能會比較慢,因此在與正規表示式匹配之前明確編譯它會獲得更多好處。

將移除 Fun 建立者 pid

從 OTP 28 開始,函數 erlang:fun_info/1 將不包含 {pid,_} 元素,並且函數 erlang:fun_info/2 將不再接受 pid 作為第二個引數。

將移除對解釋 escript 的支援

Escript 將被編譯,並且將不再可能透過使用指令 -mode(interpret) 來強制解釋 escript。

OTP 29

將不再可能停用功能 maybe_expr

從 OTP 29 開始,maybe_expr 功能將變成永久性的,並且不再可能停用。所有將 maybe 作為原子的用法都需要加上引號。

建議盡快為所有使用原子 maybe 的地方加上引號。編譯器選項 warn_keywords 可用於發出關於所有未加引號的 maybe 出現的警告。

cprof 和 eprof 將由 tprof 取代

從 OTP 29 開始,將會移除 cprofeprof,而改用 OTP 27 中新增的 tprof