Skip to content

Commit 2ab2bff

Browse files
author
José Valim
committed
Properly handle :erlang.element in Exception blame
1 parent 701c0b4 commit 2ab2bff

File tree

2 files changed

+37
-14
lines changed

2 files changed

+37
-14
lines changed

lib/elixir/lib/exception.ex

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,17 @@ defmodule Exception do
301301

302302
defp rewrite_guard(guard) do
303303
Macro.prewalk(guard, fn
304-
{:., _, [:erlang, call]} -> rewrite_guard_call(call)
305-
other -> other
304+
{{:., _, [:erlang, :element]}, _, [{{:., _, [:erlang, :+]}, _, [int, 1]}, arg]} ->
305+
{:elem, [], [arg, int]}
306+
307+
{{:., _, [:erlang, :element]}, _, [int, arg]} when is_integer(int) ->
308+
{:elem, [], [arg, int - 1]}
309+
310+
{:., _, [:erlang, call]} ->
311+
rewrite_guard_call(call)
312+
313+
other ->
314+
other
306315
end)
307316
end
308317

lib/elixir/test/elixir/exception_test.exs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -439,34 +439,48 @@ defmodule ExceptionTest do
439439
end
440440

441441
test "annotates args and clauses from mfa" do
442-
{:ok, :def, clauses} = Exception.blame_mfa(Keyword, :pop, [%{}, :key, nil])
442+
import PathHelpers
443443

444-
assert annotated_clauses_to_string(clauses) == [
445-
"{[+keywords+, +key+, +default+], [-is_list(keywords)-]}"
446-
]
444+
write_beam(
445+
defmodule Blaming do
446+
def with_elem(x, y) when elem(x, 1) == 0 and elem(x, y) == 1 do
447+
{x, y}
448+
end
447449

448-
{:ok, :def, clauses} = Exception.blame_mfa(Keyword, :fetch, [[], "oops"])
450+
def fetch(%module{} = container, key), do: {module, container, key}
451+
def fetch(map, key) when is_map(map), do: {map, key}
452+
def fetch(list, key) when is_list(list) and is_atom(key), do: {list, key}
453+
def fetch(nil, _key), do: nil
449454

450-
assert annotated_clauses_to_string(clauses) == [
451-
"{[+keywords+, +key+], [+is_list(keywords)+ and -is_atom(key)-]}"
452-
]
455+
require Integer
456+
def even_and_odd(foo, bar) when Integer.is_even(foo) and Integer.is_odd(bar), do: :ok
457+
end
458+
)
459+
460+
:code.delete(Blaming)
461+
:code.purge(Blaming)
453462

454-
{:ok, :def, clauses} = Exception.blame_mfa(Path, :type, [self()])
463+
{:ok, :def, clauses} = Exception.blame_mfa(Blaming, :with_elem, [1, 2])
455464

456465
assert annotated_clauses_to_string(clauses) == [
457-
"{[+name+], [-is_list(name)-, -is_binary(name)-]}"
466+
"{[+x+, +y+], [-elem(x, 1) == 0- and -elem(x, y) == 1-]}"
458467
]
459468

460-
{:ok, :def, clauses} = Exception.blame_mfa(Access, :fetch, [self(), "oops"])
469+
{:ok, :def, clauses} = Exception.blame_mfa(Blaming, :fetch, [self(), "oops"])
461470

462471
assert annotated_clauses_to_string(clauses) == [
463472
"{[-%module{} = container-, +key+], []}",
464473
"{[+map+, +key+], [-is_map(map)-]}",
465474
"{[+list+, +key+], [-is_list(list)- and -is_atom(key)-]}",
466-
"{[+list+, +key+], [-is_list(list)-]}",
467475
"{[-nil-, +_key+], []}"
468476
]
469477

478+
{:ok, :def, clauses} = Exception.blame_mfa(Blaming, :even_and_odd, [1, 1])
479+
480+
assert annotated_clauses_to_string(clauses) == [
481+
"{[+foo+, +bar+], [+is_integer(foo)+ and -Bitwise.band(foo, 1) == 0- and (+is_integer(bar)+ and +Bitwise.band(bar, 1) == 1+)]}"
482+
]
483+
470484
{:ok, :defmacro, clauses} = Exception.blame_mfa(Kernel, :!, [true])
471485

472486
assert annotated_clauses_to_string(clauses) == [

0 commit comments

Comments
 (0)