Skip to content

Commit 7c382b9

Browse files
author
José Valim
committed
Ensure we also normalize badmap and badkey in rescue
1 parent 9297a91 commit 7c382b9

File tree

5 files changed

+56
-15
lines changed

5 files changed

+56
-15
lines changed

lib/elixir/lib/exception.ex

+14-14
Original file line numberDiff line numberDiff line change
@@ -565,10 +565,10 @@ defmodule BadStructError do
565565
end
566566

567567
defmodule BadMapError do
568-
defexception [map: nil]
569-
568+
defexception [term: nil]
569+
570570
def message(exception) do
571-
"expected a map, got: #{inspect(exception.map)}"
571+
"expected a map, got: #{inspect(exception.term)}"
572572
end
573573
end
574574

@@ -780,19 +780,19 @@ defmodule ErlangError do
780780
def normalize({:badmatch, term}, _stacktrace) do
781781
%MatchError{term: term}
782782
end
783-
784-
# Erlang R18.0 changed this for various functions in the maps module
785-
def normalize({:badmap, map}, _stacktrace) do
786-
%BadMapError{map: map}
783+
784+
def normalize({:badmap, term}, _stacktrace) do
785+
%BadMapError{term: term}
787786
end
788-
789-
# Erlang R18.0 changed this for various functions in the maps module
787+
790788
def normalize({:badkey, key}, stacktrace) do
791-
term = case stacktrace do
792-
[{:maps, :update, [_, _, map], []}|_] -> map
793-
_ -> nil
794-
end
795-
%KeyError{key: key, term: term }
789+
term =
790+
case stacktrace || :erlang.get_stacktrace do
791+
[{:maps, :update, [_, _, map], _}|_] -> map
792+
[{:maps, :get, [_, map], _}|_] -> map
793+
_ -> nil
794+
end
795+
%KeyError{key: key, term: term}
796796
end
797797

798798
def normalize({:case_clause, term}, _stacktrace) do

lib/elixir/src/elixir_translator.erl

+3
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,9 @@ translate({{'.', _, [Left, Right]}, Meta, Args}, S)
257257
%% the is_map/1 guard instead of matching on map. Hopefully
258258
%% we can use a match on 17.1.
259259
%%
260+
%% In the future, we could also use maps:get/2 instead
261+
%% of pattern match, reducing the AST footprint.
262+
%%
260263
%% http://erlang.org/pipermail/erlang-bugs/2014-April/004338.html
261264
{{'case', -1, TLeft, [
262265
{clause, -1,

lib/elixir/src/elixir_try.erl

+10
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,16 @@ erl_rescue_guard_for(Meta, Var, 'Elixir.BadStructError') ->
156156
erl_tuple_size(Meta, Var, 3),
157157
erl_record_compare(Meta, Var, badstruct));
158158

159+
erl_rescue_guard_for(Meta, Var, 'Elixir.BadMapError') ->
160+
erl_and(Meta,
161+
erl_tuple_size(Meta, Var, 2),
162+
erl_record_compare(Meta, Var, badmap));
163+
164+
erl_rescue_guard_for(Meta, Var, 'Elixir.KeyError') ->
165+
erl_and(Meta,
166+
erl_tuple_size(Meta, Var, 2),
167+
erl_record_compare(Meta, Var, badkey));
168+
159169
erl_rescue_guard_for(Meta, Var, 'Elixir.ArgumentError') ->
160170
erl_or(Meta,
161171
{erl(Meta, '=='), Meta, [Var, badarg]},

lib/elixir/test/elixir/kernel/raise_test.exs

+28
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,34 @@ defmodule Kernel.RaiseTest do
304304
assert result == "no match of right hand side value: 0"
305305
end
306306

307+
test :bad_key_error do
308+
result = try do
309+
%{%{} | foo: :bar}
310+
rescue
311+
x in [KeyError] -> Exception.message(x)
312+
end
313+
314+
assert result == "key :foo not found"
315+
316+
result = try do
317+
%{}.foo
318+
rescue
319+
x in [KeyError] -> Exception.message(x)
320+
end
321+
322+
assert result == "key :foo not found in: %{}"
323+
end
324+
325+
test :bad_map_error do
326+
result = try do
327+
%{zero(0) | foo: :bar}
328+
rescue
329+
x in [BadMapError] -> Exception.message(x)
330+
end
331+
332+
assert result == "expected a map, got: 0"
333+
end
334+
307335
test :case_clause_error do
308336
x = :example
309337
result = try do

lib/elixir/test/elixir/map_test.exs

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ defmodule MapTest do
8484

8585
test "update maps" do
8686
assert %{two_items_map | a: 3} == %{a: 3, b: 2}
87-
87+
8888
# TODO: proper handling of API changes in different Erlang/OTP releases
8989
case :erlang.system_info(:otp_release) do
9090
'17' ->

0 commit comments

Comments
 (0)