[erlang-bugs] Double evaluation when using weird record syntax
Hans Bolinder
hans.bolinder@REDACTED
Thu Dec 27 15:17:46 CET 2007
[Dominic Williams:]
> The compiler seems to generate a double evaluation in the
> following case:
>
> -module(double_evaluation).
> -export([run/0]).
> -record(r, {f}).
>
> maker(F) ->
> io:format("maker(~p)~n",[F]),
> #r{f=F}.
>
> run()->
> (maker(1))#r{f=0},
> (maker(2))#r{}. % maker/1 called twice
Thanks for the bug report.
The following patch should solve the problem:
*** /usr/local/otp/releases/otp_beam_solaris8_r12b_patched/lib/stdlib-1.15/src/erl_expand_records.erl Tue Dec 4 16:55:18 2007
--- erl_expand_records.erl Thu Dec 27 14:59:36 2007
***************
*** 602,608 ****
%% Try to be intelligent about which method of updating record to use.
{Update,St} =
if
! Nu =:= 0 -> {R,St2}; %No fields updated
Nu =< Nc -> %Few fields updated
{record_setel(Var, Name, Fs, Us), St2};
true -> %The wide area inbetween
--- 602,608 ----
%% Try to be intelligent about which method of updating record to use.
{Update,St} =
if
! Nu =:= 0 -> {Var,St2}; %No fields updated
Nu =< Nc -> %Few fields updated
{record_setel(Var, Name, Fs, Us), St2};
true -> %The wide area inbetween
There should be a test of the record type even if there are no updated
fields. The patch below, which solves that problem, might not be
included in any R12B release since it is not backwards compatible. For
instance, "(#r2{})#r{}" will generate a 'badrecord' exception.
Best regards,
Hans Bolinder, Erlang/OTP team
*** /usr/local/otp/releases/otp_beam_solaris8_r12b_patched/lib/stdlib-1.15/src/erl_expand_records.erl Tue Dec 4 16:55:18 2007
--- erl_expand_records.erl Thu Dec 27 14:31:46 2007
***************
*** 602,621 ****
%% Try to be intelligent about which method of updating record to use.
{Update,St} =
if
! Nu =:= 0 -> {R,St2}; %No fields updated
Nu =< Nc -> %Few fields updated
{record_setel(Var, Name, Fs, Us), St2};
! true -> %The wide area inbetween
! record_match(Var, Name, Fs, Us, St2)
end,
! {{block,element(2, R),Pre ++ [{match,Line,Var,R},Update]},St}.
%% record_match(Record, RecordName, [RecDefField], [Update], State)
%% Build a 'case' expression to modify record fields.
! record_match(R, Name, Fs, Us, St0) ->
{Ps,News,St1} = record_upd_fs(Fs, Us, St0),
- Lr = element(2, hd(Us)),
{{'case',Lr,R,
[{clause,Lr,[{tuple,Lr,[{atom,Lr,Name} | Ps]}],[],
[{tuple,Lr,[{atom,Lr,Name} | News]}]},
--- 602,621 ----
%% Try to be intelligent about which method of updating record to use.
{Update,St} =
if
! Nu =:= 0 ->
! record_match(Var, Name, Line, Fs, Us, St2);
Nu =< Nc -> %Few fields updated
{record_setel(Var, Name, Fs, Us), St2};
! true -> %The wide area inbetween
! record_match(Var, Name, element(2, hd(Us)), Fs, Us, St2)
end,
! {{block,Line,Pre ++ [{match,Line,Var,R},Update]},St}.
%% record_match(Record, RecordName, [RecDefField], [Update], State)
%% Build a 'case' expression to modify record fields.
! record_match(R, Name, Lr, Fs, Us, St0) ->
{Ps,News,St1} = record_upd_fs(Fs, Us, St0),
{{'case',Lr,R,
[{clause,Lr,[{tuple,Lr,[{atom,Lr,Name} | Ps]}],[],
[{tuple,Lr,[{atom,Lr,Name} | News]}]},
More information about the erlang-bugs
mailing list