erlang 源码中的-file(文件名,行号)是个什么预处理?


这两天在看erlang的一个probuffer库gpb的时候发现了以下代码

...
-module(gpb_scan).
...
%% User code. This is placed here to allow extra attributes.
-file("src/gpb_scan.xrl", 122).
...

里面出现了例如-file("src/gpb_scan.xrl", 122).这样的预处理代码,第一次见到,也不记得在哪本书里面有见过,不得其解,网上也没有查到什么信息。
于是自己验证了一下,先说我的结论:
-file(文件名,行号)将改变本文件该标志以后的代码的定位文件名和行号,比如在a.erl文件里面有如下代码:

1 -module(a).
2 -export([f/0]).
3 -file("src/b.erl", 0).
4 f() ->
5    a = b.
6 

看代码我们可以知道,执行a:f().将引起报错,如果没有-file,报错信息将是

no match of right hand side value b
     in function  a:f/0 (a.erl, line 4)

有了-file("src/b.erl", 0).,报错信息将变成

no match of right hand side value b
     in function  a:f/0 (b.erl, line 1)

可见,该操作会将a.erl文件的第3行起,往后的每一行都标识为b.erl的第0+N行。
为什么我们要将错误位置定向到另一个地方去?该操作看起来很反人类,它的意义是什么?想不明白。

以下是我查找答案的过程:
生成a.erl的beam指令码, 区分加上-file("src/b.erl", 0).与否的区别

erlc +"'S'" a.erl

-file("src/b.erl", 0).
编译警告:a.erl:5: Warning: no clause will ever match

{module, a}.  %% version = 0

{exports, [{f,0},{module_info,0},{module_info,1}]}.

{attributes, []}.

{labels, 7}.


{function, f, 0, 2}.
  {label,1}.
    {line,[{location,"a.erl",4}]}.      %% 注意这行
    {func_info,{atom,a},{atom,f},0}.
  {label,2}.
    {line,[{location,"a.erl",5}]}.      %% 注意这行
    {badmatch,{atom,b}}.


{function, module_info, 0, 4}.
  {label,3}.
    {line,[]}.
    {func_info,{atom,a},{atom,module_info},0}.
  {label,4}.
    {move,{atom,a},{x,0}}.
    {line,[]}.
    {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.


{function, module_info, 1, 6}.
  {label,5}.
    {line,[]}.
    {func_info,{atom,a},{atom,module_info},1}.
  {label,6}.
    {move,{x,0},{x,1}}.
    {move,{atom,a},{x,0}}.
    {line,[]}.
    {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.

-file("src/b.erl", 0).
编译警告:src/b.erl:2: Warning: no clause will ever match

{module, a}.  %% version = 0

{exports, [{f,0},{module_info,0},{module_info,1}]}.

{attributes, []}.

{labels, 7}.


{function, f, 0, 2}.
  {label,1}.
    {line,[{location,"src/b.erl",1}]}.      %% 注意这行
    {func_info,{atom,a},{atom,f},0}.
  {label,2}.
    {line,[{location,"src/b.erl",2}]}.      %% 注意这行
    {badmatch,{atom,b}}.


{function, module_info, 0, 4}.
  {label,3}.
    {line,[]}.
    {func_info,{atom,a},{atom,module_info},0}.
  {label,4}.
    {move,{atom,a},{x,0}}.
    {line,[]}.
    {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.


{function, module_info, 1, 6}.
  {label,5}.
    {line,[]}.
    {func_info,{atom,a},{atom,module_info},1}.
  {label,6}.
    {move,{x,0},{x,1}}.
    {move,{atom,a},{x,0}}.
    {line,[]}.
    {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.

完.