From d09c774343b78d663143ecc8930743ccded5f1c1 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Mon, 24 Nov 2014 17:19:12 +0100 Subject: dialyzer: correct record updates Correct a bug introduced in commit 8498a3. --- lib/dialyzer/test/small_SUITE_data/results/record_update | 2 ++ lib/dialyzer/test/small_SUITE_data/src/record_update.erl | 10 ++++++++++ lib/stdlib/src/erl_expand_records.erl | 9 +++++++-- 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 lib/dialyzer/test/small_SUITE_data/results/record_update create mode 100644 lib/dialyzer/test/small_SUITE_data/src/record_update.erl diff --git a/lib/dialyzer/test/small_SUITE_data/results/record_update b/lib/dialyzer/test/small_SUITE_data/results/record_update new file mode 100644 index 0000000000..ea52057adf --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/record_update @@ -0,0 +1,2 @@ + +record_update.erl:7: Invalid type specification for function record_update:quux/2. The success typing is (#foo{bar::atom()},atom()) -> #foo{bar::atom()} diff --git a/lib/dialyzer/test/small_SUITE_data/src/record_update.erl b/lib/dialyzer/test/small_SUITE_data/src/record_update.erl new file mode 100644 index 0000000000..bad7a0a929 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/record_update.erl @@ -0,0 +1,10 @@ +-module(record_update). + +-export([quux/2]). + +-record(foo, {bar :: atom()}). + +-spec quux(#foo{}, string()) -> #foo{}. + +quux(Foo, NotBar) -> + Foo#foo{ bar = NotBar }. diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl index c74f68647f..64a00acd88 100644 --- a/lib/stdlib/src/erl_expand_records.erl +++ b/lib/stdlib/src/erl_expand_records.erl @@ -702,9 +702,10 @@ record_update(R, Name, Fs, Us0, St0) -> record_match(R, Name, Lr, Fs, Us, St0) -> {Ps,News,St1} = record_upd_fs(Fs, Us, St0), NLr = neg_line(Lr), + RLine = record_offset(Lr, St1), {{'case',Lr,R, - [{clause,Lr,[{tuple,Lr,[{atom,Lr,Name} | Ps]}],[], - [{tuple,Lr,[{atom,Lr,Name} | News]}]}, + [{clause,Lr,[{tuple,RLine,[{atom,Lr,Name} | Ps]}],[], + [{tuple,RLine,[{atom,Lr,Name} | News]}]}, {clause,NLr,[{var,NLr,'_'}],[], [call_error(NLr, {tuple,NLr,[{atom,NLr,badrecord},{atom,NLr,Name}]})]} ]}, @@ -733,6 +734,10 @@ record_setel(R, Name, Fs, Us0) -> Lr = element(2, hd(Us)), Wildcards = duplicate(length(Fs), {var,Lr,'_'}), NLr = neg_line(Lr), + %% Note: calling record_offset() here is not necessary since it is + %% targeted at Dialyzer which always calls the compiler with + %% 'strict_record_updates' meaning that record_setel() will never + %% be called. {'case',Lr,R, [{clause,Lr,[{tuple,Lr,[{atom,Lr,Name} | Wildcards]}],[], [foldr(fun ({I,Lf,Val}, Acc) -> -- cgit v1.2.3