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

openSUSE Build Service is sponsored by