Skip to content

Commit b5eb309

Browse files
committed
Fix clause rewriting in typing violations on apply
1 parent 6886f7c commit b5eb309

File tree

5 files changed

+55
-58
lines changed

5 files changed

+55
-58
lines changed

lib/elixir/lib/exception.ex

+2-2
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,8 @@ defmodule Exception do
407407

408408
defp erl_to_ex(mod, fun, args, meta) do
409409
case :elixir_rewrite.erl_to_ex(mod, fun, args) do
410-
{Kernel, fun, args} -> {fun, meta, args}
411-
{mod, fun, args} -> {{:., [], [mod, fun]}, meta, args}
410+
{Kernel, fun, args, _} -> {fun, meta, args}
411+
{mod, fun, args, _} -> {{:., [], [mod, fun]}, meta, args}
412412
end
413413
end
414414

lib/elixir/lib/module/types/helpers.ex

+4-8
Original file line numberDiff line numberDiff line change
@@ -195,21 +195,17 @@ defmodule Module.Types.Helpers do
195195
"""
196196
def expr_to_string(expr) do
197197
expr
198-
|> reverse_rewrite()
199-
|> Macro.to_string()
200-
end
201-
202-
defp reverse_rewrite(guard) do
203-
Macro.prewalk(guard, fn
198+
|> Macro.prewalk(fn
204199
{{:., _, [mod, fun]}, meta, args} -> erl_to_ex(mod, fun, args, meta)
205200
other -> other
206201
end)
202+
|> Macro.to_string()
207203
end
208204

209205
defp erl_to_ex(mod, fun, args, meta) do
210206
case :elixir_rewrite.erl_to_ex(mod, fun, args) do
211-
{Kernel, fun, args} -> {fun, meta, args}
212-
{mod, fun, args} -> {{:., [], [mod, fun]}, meta, args}
207+
{Kernel, fun, args, _} -> {fun, meta, args}
208+
{mod, fun, args, _} -> {{:., [], [mod, fun]}, meta, args}
213209
end
214210
end
215211

lib/elixir/lib/module/types/of.ex

+15-18
Original file line numberDiff line numberDiff line change
@@ -931,21 +931,23 @@ defmodule Module.Types.Of do
931931
traces = collect_traces(expr, context)
932932
{{:., _, [mod, fun]}, _, args} = expr
933933

934+
{mod, fun, args, converter} = :elixir_rewrite.erl_to_ex(mod, fun, args)
935+
934936
%{
935937
details: %{typing_traces: traces},
936938
message:
937939
IO.iodata_to_binary([
938940
"""
939-
incompatible types given to #{format_mfa(mod, fun, args)}:
941+
incompatible types given to #{Exception.format_mfa(mod, fun, length(args))}:
940942
941943
#{expr_to_string(expr) |> indent(4)}
942944
943945
given types:
944946
945-
#{args_to_quoted_string(mod, fun, args_types, domain) |> indent(4)}
947+
#{args_to_quoted_string(args_types, domain, converter) |> indent(4)}
946948
947949
but expected one of:
948-
#{clauses_args_to_quoted_string(mod, fun, clauses)}
950+
#{clauses_args_to_quoted_string(clauses, converter)}
949951
""",
950952
format_traces(traces)
951953
])
@@ -1082,41 +1084,37 @@ defmodule Module.Types.Of do
10821084
end
10831085

10841086
defp format_mfa({{:., _, [mod, fun]}, _, args}) do
1085-
format_mfa(mod, fun, args)
1086-
end
1087-
1088-
defp format_mfa(mod, fun, args) do
1089-
{mod, fun, args} = :elixir_rewrite.erl_to_ex(mod, fun, args)
1087+
{mod, fun, args, _} = :elixir_rewrite.erl_to_ex(mod, fun, args)
10901088
Exception.format_mfa(mod, fun, length(args))
10911089
end
10921090

10931091
## Algebra helpers
10941092

10951093
alias Inspect.Algebra, as: IA
10961094

1097-
defp clauses_args_to_quoted_string(mod, fun, [{args, _return}]) do
1098-
"\n " <> (clause_args_to_quoted_string(mod, fun, args) |> indent(4))
1095+
defp clauses_args_to_quoted_string([{args, _return}], converter) do
1096+
"\n " <> (clause_args_to_quoted_string(args, converter) |> indent(4))
10991097
end
11001098

1101-
defp clauses_args_to_quoted_string(mod, fun, clauses) do
1099+
defp clauses_args_to_quoted_string(clauses, converter) do
11021100
clauses
11031101
|> Enum.with_index(fn {args, _return}, index ->
11041102
"""
11051103
11061104
##{index + 1}
1107-
#{clause_args_to_quoted_string(mod, fun, args)}\
1105+
#{clause_args_to_quoted_string(args, converter)}\
11081106
"""
11091107
|> indent(4)
11101108
end)
11111109
|> Enum.join("\n")
11121110
end
11131111

1114-
defp clause_args_to_quoted_string(mod, fun, args) do
1112+
defp clause_args_to_quoted_string(args, converter) do
11151113
docs = Enum.map(args, &(&1 |> to_quoted() |> Code.Formatter.to_algebra()))
1116-
args_docs_to_quoted_string(mod, fun, docs)
1114+
args_docs_to_quoted_string(converter.(docs))
11171115
end
11181116

1119-
defp args_to_quoted_string(mod, fun, args_types, domain) do
1117+
defp args_to_quoted_string(args_types, domain, converter) do
11201118
ansi? = IO.ANSI.enabled?()
11211119

11221120
docs =
@@ -1130,11 +1128,10 @@ defmodule Module.Types.Of do
11301128
end
11311129
end)
11321130

1133-
args_docs_to_quoted_string(mod, fun, docs)
1131+
args_docs_to_quoted_string(converter.(docs))
11341132
end
11351133

1136-
defp args_docs_to_quoted_string(mod, fun, docs) do
1137-
{_mod, _fun, docs} = :elixir_rewrite.erl_to_ex(mod, fun, docs)
1134+
defp args_docs_to_quoted_string(docs) do
11381135
doc = IA.fold(docs, fn doc, acc -> IA.glue(IA.concat(doc, ","), acc) end)
11391136

11401137
wrapped_docs =

lib/elixir/src/elixir_rewrite.erl

+19-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
-module(elixir_rewrite).
22
-compile({inline, [inner_inline/4, inner_rewrite/5]}).
3+
-compile(nowarn_shadow_vars).
34
-export([erl_to_ex/3, inline/3, rewrite/5, match/6, guard/6, format_error/1]).
45
-include("elixir.hrl").
56

@@ -36,13 +37,13 @@
3637
-define(
3738
rewrite(ExMod, ExFun, ExArgs, ErlMod, ErlFun, ErlArgs),
3839
inner_rewrite(ex_to_erl, _Meta, ExMod, ExFun, ExArgs) -> {ErlMod, ErlFun, ErlArgs};
39-
inner_rewrite(erl_to_ex, _Meta, ErlMod, ErlFun, ErlArgs) -> {ExMod, ExFun, ExArgs}
40+
inner_rewrite(erl_to_ex, _Meta, ErlMod, ErlFun, ErlArgs) -> {ExMod, ExFun, ExArgs, fun(ErlArgs) -> ExArgs end}
4041
).
4142

4243
erl_to_ex(Mod, Fun, Args) ->
4344
case inner_inline(erl_to_ex, Mod, Fun, length(Args)) of
4445
false -> inner_rewrite(erl_to_ex, [], Mod, Fun, Args);
45-
{ExMod, ExFun} -> {ExMod, ExFun, Args}
46+
{ExMod, ExFun} -> {ExMod, ExFun, Args, fun identity/1}
4647
end.
4748

4849
%% Inline rules
@@ -270,29 +271,32 @@ inner_rewrite(ex_to_erl, Meta, ?kernel, put_elem, [Tuple, Index, Value]) ->
270271
{erlang, setelement, [increment(Meta, Index), Tuple, Value]};
271272

272273
inner_rewrite(erl_to_ex, _Meta, erlang, delete_element, [Index, Tuple]) when is_number(Index) ->
273-
{?tuple, delete_at, [Tuple, Index - 1]};
274+
{?tuple, delete_at, [Tuple, Index - 1], fun([Index, Tuple]) -> [Tuple, Index] end};
274275
inner_rewrite(erl_to_ex, _Meta, erlang, insert_element, [Index, Tuple, Term]) when is_number(Index) ->
275-
{?tuple, insert_at, [Tuple, Index - 1, Term]};
276+
{?tuple, insert_at, [Tuple, Index - 1, Term], fun([Index, Tuple, Term]) -> [Tuple, Index, Term] end};
276277
inner_rewrite(erl_to_ex, _Meta, erlang, element, [Index, Tuple]) when is_number(Index) ->
277-
{?kernel, elem, [Tuple, Index - 1]};
278-
inner_rewrite(erl_to_ex, _Meta, erlang, setelement, [Index, Tuple, Value]) when is_number(Index) ->
279-
{?kernel, put_elem, [Tuple, Index - 1, Value]};
278+
{?kernel, elem, [Tuple, Index - 1], fun([Index, Tuple]) -> [Tuple, Index] end};
279+
inner_rewrite(erl_to_ex, _Meta, erlang, setelement, [Index, Tuple, Term]) when is_number(Index) ->
280+
{?kernel, put_elem, [Tuple, Index - 1, Term], fun([Index, Tuple, Term]) -> [Tuple, Index, Term] end};
280281

281282
inner_rewrite(erl_to_ex, _Meta, erlang, delete_element, [{{'.', _, [erlang, '+']}, _, [Index, 1]}, Tuple]) ->
282-
{?tuple, delete_at, [Tuple, Index]};
283+
{?tuple, delete_at, [Tuple, Index], fun([Index, Tuple]) -> [Tuple, Index] end};
283284
inner_rewrite(erl_to_ex, _Meta, erlang, insert_element, [{{'.', _, [erlang, '+']}, _, [Index, 1]}, Tuple, Term]) ->
284-
{?tuple, insert_at, [Tuple, Index, Term]};
285+
{?tuple, insert_at, [Tuple, Index, Term], fun([Index, Tuple, Term]) -> [Tuple, Index, Term] end};
285286
inner_rewrite(erl_to_ex, _Meta, erlang, element, [{{'.', _, [erlang, '+']}, _, [Index, 1]}, Tuple]) ->
286-
{?kernel, elem, [Tuple, Index]};
287-
inner_rewrite(erl_to_ex, _Meta, erlang, setelement, [{{'.', _, [erlang, '+']}, _, [Index, 1]}, Tuple, Value]) ->
288-
{?kernel, put_elem, [Tuple, Index, Value]};
287+
{?kernel, elem, [Tuple, Index], fun([Index, Tuple]) -> [Tuple, Index] end};
288+
inner_rewrite(erl_to_ex, _Meta, erlang, setelement, [{{'.', _, [erlang, '+']}, _, [Index, 1]}, Tuple, Term]) ->
289+
{?kernel, put_elem, [Tuple, Index, Term], fun([Index, Tuple, Term]) -> [Tuple, Index, Term] end};
289290

290291
inner_rewrite(erl_to_ex, _Meta, erlang, 'orelse', [_, _] = Args) ->
291-
{?kernel, 'or', Args};
292+
{?kernel, 'or', Args, fun identity/1};
292293
inner_rewrite(erl_to_ex, _Meta, erlang, 'andalso', [_, _] = Args) ->
293-
{?kernel, 'and', Args};
294+
{?kernel, 'and', Args, fun identity/1};
294295

295-
inner_rewrite(_To, _Meta, Mod, Fun, Args) -> {Mod, Fun, Args}.
296+
inner_rewrite(ex_to_erl, _Meta, Mod, Fun, Args) -> {Mod, Fun, Args};
297+
inner_rewrite(erl_to_ex, _Meta, Mod, Fun, Args) -> {Mod, Fun, Args, fun identity/1}.
298+
299+
identity(Arg) -> Arg.
296300

297301
increment(_Meta, Number) when is_number(Number) ->
298302
Number + 1;

lib/elixir/test/elixir/module/types/expr_test.exs

+15-15
Original file line numberDiff line numberDiff line change
@@ -317,25 +317,25 @@ defmodule Module.Types.ExprTest do
317317
assert typecheck!([x], elem({:ok, x}, 0)) == dynamic(atom([:ok]))
318318
assert typecheck!([x], elem({:ok, x}, 1)) == dynamic(term())
319319

320-
assert typeerror!([<<x::integer>>], elem(x, 0)) |> strip_ansi() ==
320+
assert typeerror!([<<x::float>>], elem(x, 0)) |> strip_ansi() ==
321321
~l"""
322322
incompatible types given to Kernel.elem/2:
323323
324324
elem(x, 0)
325325
326326
given types:
327327
328-
integer(), integer()
328+
float(), integer()
329329
330330
but expected one of:
331331
332-
integer(), {...}
332+
{...}, integer()
333333
334334
where "x" was given the type:
335335
336-
# type: integer()
336+
# type: float()
337337
# from: types_test.ex:LINE-1
338-
<<x::integer>>
338+
<<x::float>>
339339
"""
340340

341341
assert typeerror!(elem({:ok, 123}, 2)) ==
@@ -362,25 +362,25 @@ defmodule Module.Types.ExprTest do
362362
assert typecheck!(Tuple.insert_at({:ok, 123}, 2, "foo")) ==
363363
tuple([atom([:ok]), integer(), binary()])
364364

365-
assert typeerror!([<<x::integer>>], Tuple.insert_at(x, 0, "foo")) |> strip_ansi() ==
365+
assert typeerror!([<<x::float>>], Tuple.insert_at(x, 0, "foo")) |> strip_ansi() ==
366366
~l"""
367367
incompatible types given to Tuple.insert_at/3:
368368
369369
Tuple.insert_at(x, 0, "foo")
370370
371371
given types:
372372
373-
integer(), integer(), binary()
373+
float(), integer(), binary()
374374
375375
but expected one of:
376376
377-
integer(), {...}, term()
377+
{...}, integer(), term()
378378
379379
where "x" was given the type:
380380
381-
# type: integer()
381+
# type: float()
382382
# from: types_test.ex:LINE-1
383-
<<x::integer>>
383+
<<x::float>>
384384
"""
385385

386386
assert typeerror!(Tuple.insert_at({:ok, 123}, 3, "foo")) ==
@@ -401,25 +401,25 @@ defmodule Module.Types.ExprTest do
401401
assert typecheck!([x], Tuple.delete_at({:ok, x}, 0)) == dynamic(tuple([term()]))
402402
assert typecheck!([x], Tuple.delete_at({:ok, x}, 1)) == dynamic(tuple([atom([:ok])]))
403403

404-
assert typeerror!([<<x::integer>>], Tuple.delete_at(x, 0)) |> strip_ansi() ==
404+
assert typeerror!([<<x::float>>], Tuple.delete_at(x, 0)) |> strip_ansi() ==
405405
~l"""
406406
incompatible types given to Tuple.delete_at/2:
407407
408408
Tuple.delete_at(x, 0)
409409
410410
given types:
411411
412-
integer(), integer()
412+
float(), integer()
413413
414414
but expected one of:
415415
416-
integer(), {...}
416+
{...}, integer()
417417
418418
where "x" was given the type:
419419
420-
# type: integer()
420+
# type: float()
421421
# from: types_test.ex:LINE-1
422-
<<x::integer>>
422+
<<x::float>>
423423
"""
424424

425425
assert typeerror!(Tuple.delete_at({:ok, 123}, 2)) ==

0 commit comments

Comments
 (0)