File 2101-dialyzer-Fix-infinite-loop-on-named-recursive-funs.patch of Package erlang
From 46be6eb38979777425011d3d41b230e19c7a9364 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org>
Date: Thu, 2 Dec 2021 11:40:34 +0100
Subject: [PATCH] dialyzer: Fix infinite loop on named recursive funs
---
lib/dialyzer/src/dialyzer_typesig.erl | 22 ++++++++++---------
.../test/small_SUITE_data/results/fun_hangs | 2 ++
.../test/small_SUITE_data/src/fun_named.erl | 10 +++++++++
3 files changed, 24 insertions(+), 10 deletions(-)
create mode 100644 lib/dialyzer/test/small_SUITE_data/results/fun_hangs
create mode 100644 lib/dialyzer/test/small_SUITE_data/src/fun_named.erl
diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl
index 3fd4e59e4a..45f2a2aebf 100644
--- a/lib/dialyzer/src/dialyzer_typesig.erl
+++ b/lib/dialyzer/src/dialyzer_typesig.erl
@@ -1888,20 +1888,22 @@ v2_solve_reference(Id, Map, V2State0) ->
{ok, Dom} -> t_fun(Dom, t_none())
end,
{FunType0, V2State1};
- {ok, NewMap, V2State1, U} ->
+ {ok, ResMap, V2State1, ResU} ->
?debug("Done solving fun: ~tp\n", [debug_lookup_name(Id)]),
- FunType0 = lookup_type(Id, NewMap),
- V2State2 = save_local_map(V2State1, Id, U, NewMap),
+ FunType0 = lookup_type(Id, ResMap),
+ V2State2 = save_local_map(V2State1, Id, ResU, ResMap),
{FunType0, V2State2}
end,
?debug("ref Id=~w Assigned ~ts\n", [Id, format_type(FunType)]),
- {NewMap1, U1} = enter_var_type(Id, FunType, Map),
- {NewMap2, U2} =
- case state__get_rec_var(Id, State) of
- {ok, Var} -> enter_var_type(Var, FunType, NewMap1);
- error -> {NewMap1, []}
- end,
- {ok, NewMap2, V2State, lists:umerge(U1, U2)}.
+ {NewMap0, U0} = enter_var_type(Id, FunType, Map),
+ case state__get_rec_var(Id, State) of
+ {ok, Var} ->
+ %% `Id` and `Var` are one and the same, so they need to be unified.
+ {ok, {NewMap, U}} = refine_bindings([{Var, FunType}], NewMap0, U0),
+ {ok, NewMap, V2State, U};
+ error ->
+ {ok, NewMap0, V2State, U0}
+ end.
v2_solve_self_recursive(Cs, Map, Id, RecType0, V2State0) ->
?debug("Solving self recursive ~tw\n", [debug_lookup_name(Id)]),
diff --git a/lib/dialyzer/test/small_SUITE_data/results/fun_hangs b/lib/dialyzer/test/small_SUITE_data/results/fun_hangs
new file mode 100644
index 0000000000..139597f9cb
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/fun_hangs
@@ -0,0 +1,2 @@
+
+
diff --git a/lib/dialyzer/test/small_SUITE_data/src/fun_named.erl b/lib/dialyzer/test/small_SUITE_data/src/fun_named.erl
new file mode 100644
index 0000000000..4c74f092fa
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/fun_named.erl
@@ -0,0 +1,10 @@
+%% Analysis could enter an infinite loop when a named fun called itself.
+-module(fun_hangs).
+-export([bar/1, foo/0]).
+
+-spec bar(fun((pos_integer()) -> term())) -> term().
+bar(Fun) ->
+ Fun.
+
+foo() ->
+ bar(fun F(_) -> F(1) end).
--
2.31.1