Skip to content

Commit f6aced3

Browse files
ggcampinhoJosé Valim
authored andcommitted
Remove dialyzer warnings from else in with clauses (#7031)
Add generated: true to guard clauses from else in with clauses Resolves #6426
1 parent 5e5eaca commit f6aced3

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

lib/elixir/src/elixir_erl_pass.erl

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,11 +371,31 @@ translate_with_else(Meta, [{else, Else}], S) ->
371371
RaiseExpr = {{'.', Generated, [erlang, error]}, Generated, [{with_clause, RaiseVar}]},
372372
RaiseClause = {'->', Generated, [[RaiseVar], RaiseExpr]},
373373

374-
GeneratedElse = [{'->', ?generated(ElseMeta), ElseArgs} || {'->', ElseMeta, ElseArgs} <- Else],
374+
GeneratedElse = [build_generated_clause(Generated, ElseClause) || ElseClause <- Else],
375+
375376
Case = {'case', [{export_vars, false} | Generated], [ElseVarEx, [{do, GeneratedElse ++ [RaiseClause]}]]},
376377
{TranslatedCase, SC} = elixir_erl_pass:translate(Case, SV),
377378
{{clause, ?ann(Generated), [ElseVarErl], [], [TranslatedCase]}, SC}.
378379

380+
build_generated_clause(Generated, {'->', _, [Args, Clause]}) ->
381+
NewArgs = [build_generated_clause_arg(Generated, Arg) || Arg <- Args],
382+
{'->', Generated, [NewArgs, Clause]}.
383+
384+
build_generated_clause_arg(Generated, Arg) ->
385+
{Expr, Guards} = elixir_utils:extract_guards(Arg),
386+
NewGuards = [build_generated_guard(Generated, Guard) || Guard <- Guards],
387+
concat_guards(Generated, Expr, NewGuards).
388+
389+
build_generated_guard(Generated, {{'.', _, _} = Call, _, Args}) ->
390+
{Call, Generated, [build_generated_guard(Generated, Arg) || Arg <- Args]};
391+
build_generated_guard(_, Expr) ->
392+
Expr.
393+
394+
concat_guards(_Meta, Expr, []) ->
395+
Expr;
396+
concat_guards(Meta, Expr, [Guard | Tail]) ->
397+
{'when', Meta, [Expr, concat_guards(Meta, Guard, Tail)]}.
398+
379399
translate_with_do([{'<-', Meta, [Left, Expr]} | Rest], Do, Else, S) ->
380400
{Args, Guards} = elixir_utils:extract_guards(Left),
381401
{TExpr, SR} = elixir_erl_pass:translate(Expr, S),

lib/elixir/test/elixir/fixtures/dialyzer/with.ex

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,25 @@
11
defmodule Dialyzer.With do
22
def with_else do
33
with :ok <- ok_or_error(),
4-
:ok <- ok_or_other_error() do
4+
:ok <- ok_or_other_error(),
5+
:ok <- ok_or_tuple_error(),
6+
:ok <- ok_or_tuple_list_error() do
57
:ok
68
else
79
:error ->
810
:error
11+
912
:other_error ->
1013
:other_error
14+
15+
{:error, msg} when is_list(msg) or is_tuple(msg) ->
16+
:error
17+
18+
{:error, msg} when is_list(msg) when is_tuple(msg) ->
19+
:error
20+
21+
{:error, _msg} ->
22+
:error
1123
end
1224
end
1325

@@ -20,4 +32,14 @@ defmodule Dialyzer.With do
2032
defp ok_or_other_error do
2133
Enum.random([:ok, :other_error])
2234
end
35+
36+
@spec ok_or_tuple_error() :: :ok | {:error, :err}
37+
defp ok_or_tuple_error do
38+
Enum.random([:ok, {:error, :err}])
39+
end
40+
41+
@spec ok_or_tuple_list_error() :: :ok | {:error, [:err]}
42+
defp ok_or_tuple_list_error do
43+
Enum.random([:ok, {:error, [:err]}])
44+
end
2345
end

0 commit comments

Comments
 (0)