查看源代码 即将到来的潜在不兼容性

引言

本文档列出了 Erlang/OTP 中计划的即将到来的潜在不兼容性。

OTP 27

Fun 创建者 pid 将始终是本地 init 进程

从 OTP 27 开始,函数 erlang:fun_info/1,2 将始终表明本地 init 进程创建了所有 fun,而不管 fun 最初是在哪个进程或节点上创建的。

在 OTP 28 中,{pid,_} 元素将完全删除。

feature 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 中,该警告将变为错误。

Escripts 将默认编译

Escripts 将默认编译而不是解释。这意味着 compiler 应用程序必须可用。

可以通过将以下行添加到脚本文件中来恢复解释 escripts 的旧行为

-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 中,我们将切换到不同的正则表达式库。

re 模块使用的 PCRE 源代码已由 OTP 团队修改,以确保在匹配大型输入二进制文件和/或使用苛刻(回溯)正则表达式时正则表达式匹配会产生结果。由于这些修改,迁移到新版本的 PCRE 一直是一个耗时的过程,因为所有修改都必须再次手动应用于更新的 PCRE 源代码。

新的正则表达式库很可能是 RE2。RE2 保证匹配时间与输入字符串的长度呈线性关系,并且它还避免使用递归以防止堆栈溢出。这应该使在不修改其源代码的情况下使用 RE2 成为可能。有关为什么 RE2 是一个不错的选择的更多信息,请参阅 WhyRE2

此更改的一些影响是

  • 我们预计 re 模块中的函数将继续得到支持,尽管某些选项可能会被弃用。
  • 很可能仅支持 UTF8 编码的二进制文件的模式匹配(不支持 Latin1 编码的二进制文件)。
  • 为了保证线性时间性能,RE2 不支持 PCRE 中正则表达式模式中的所有构造。例如,不支持反向引用和环视断言。有关 RE2 支持的内容的描述,请参见 Syntax
  • 编译正则表达式可能会比较慢,因此通过在匹配之前显式编译正则表达式可以获得更多好处。

Fun 创建者 pid 将被删除

从 OTP 28 开始,函数 erlang:fun_info/1 将不包含 {pid,_} 元素,函数 erlang:fun_info/2 将不再接受 pid 作为第二个参数。

将删除对解释 escripts 的支持

Escripts 将被编译,并且不再可能使用指令 -mode(interpret) 强制解释 escript。

OTP 29

将不再可能禁用 feature maybe_expr

从 OTP 29 开始,maybe_expr 功能将成为永久性的,不再可能禁用。所有将 maybe 用作原子的用法都需要加引号。

建议尽快引用所有原子 maybe 的用法。编译器选项 warn_keywords 可用于发出关于所有未加引号的 maybe 出现的警告。

cprof 和 eprof 将被 tprof 取代

从 OTP 29 开始,将删除 cprofeprof,而采用 OTP 27 中添加的 tprof