Skip to content

Commit 4847214

Browse files
author
José Valim
committed
Do not fill in stacktraces on protocol dispatch
1 parent e56df8a commit 4847214

File tree

3 files changed

+39
-37
lines changed

3 files changed

+39
-37
lines changed

lib/eex/test/eex_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ defmodule EExText.Compiled do
2929
try do
3030
:erlang.error "failed"
3131
catch
32-
:error, _, stack -> stack
32+
:error, _ -> System.stacktrace
3333
end
3434
end
3535
end

lib/elixir/lib/protocol.ex

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,10 @@ defmodule Protocol do
5454
target = Module.concat(__MODULE__, mod)
5555

5656
Kernel.def impl_for(data) when :erlang.unquote(guard)(data) do
57-
unquote(target).__impl__(:name)
58-
catch :error, :undef, [[{ unquote(target), :__impl__, [:name], _ }|_]|_] ->
59-
any_impl_for
57+
case impl_for?(unquote(target)) do
58+
true -> unquote(target).__impl__(:name)
59+
false -> any_impl_for
60+
end
6061
end
6162
end
6263

@@ -68,10 +69,10 @@ defmodule Protocol do
6869
# Internal handler for Any
6970
if @fallback_to_any do
7071
Kernel.defp any_impl_for do
71-
__MODULE__.Any.__impl__(:name)
72-
catch
73-
:error, :undef, [[{ __MODULE__.Any, :__impl__, [:name], _ }|_]|_] ->
74-
nil
72+
case impl_for?(__MODULE__.Any) do
73+
true -> __MODULE__.Any.__impl__(:name)
74+
false -> nil
75+
end
7576
end
7677
else
7778
Kernel.defp any_impl_for, do: nil
@@ -80,15 +81,20 @@ defmodule Protocol do
8081
# Internal handler for Structs
8182
Kernel.defp struct_impl_for(struct) do
8283
target = Module.concat(__MODULE__, struct)
83-
try do
84-
target.__impl__(:name)
85-
catch :error, :undef, [[{ ^target, :__impl__, [:name], _ }|_]|_] ->
86-
any_impl_for
84+
case impl_for?(target) do
85+
true -> target.__impl__(:name)
86+
false -> any_impl_for
8787
end
8888
end
8989

90+
# Check if compilation is available internally
91+
Kernel.defp impl_for?(target) do
92+
Code.ensure_compiled?(target) and
93+
function_exported?(target, :__impl__, 1)
94+
end
95+
9096
# Inline any and struct implementations
91-
@compile { :inline, any_impl_for: 0, struct_impl_for: 1 }
97+
@compile { :inline, any_impl_for: 0, struct_impl_for: 1, impl_for?: 1 }
9298

9399
if :code.ensure_loaded(Kernel.Typespec) == { :module, Kernel.Typespec } and
94100
not Kernel.Typespec.defines_type?(__MODULE__, :t, 0) do
@@ -162,17 +168,17 @@ defmodule Protocol do
162168
# Builtin types.
163169
@doc false
164170
def builtin do
165-
[ is_tuple: Tuple,
166-
is_atom: Atom,
167-
is_list: List,
168-
is_map: Map,
169-
is_bitstring: BitString,
170-
is_integer: Integer,
171-
is_float: Float,
172-
is_function: Function,
173-
is_pid: PID,
174-
is_port: Port,
175-
is_reference: Reference ]
171+
[is_tuple: Tuple,
172+
is_atom: Atom,
173+
is_list: List,
174+
is_map: Map,
175+
is_bitstring: BitString,
176+
is_integer: Integer,
177+
is_float: Float,
178+
is_function: Function,
179+
is_pid: PID,
180+
is_port: Port,
181+
is_reference: Reference]
176182
end
177183

178184
# Implements the function that detects the protocol and
@@ -184,10 +190,9 @@ defmodule Protocol do
184190
target = Module.concat(current, Tuple)
185191

186192
fallback = quote do
187-
try do
188-
unquote(target).__impl__(:name)
189-
catch :error, :undef, [[{ unquote(target), :__impl__, [:name], _ }|_]|_] ->
190-
any_impl_for
193+
case impl_for?(unquote(target)) do
194+
true -> unquote(target).__impl__(:name)
195+
false -> any_impl_for
191196
end
192197
end
193198

@@ -197,11 +202,9 @@ defmodule Protocol do
197202
case not(atom in unquote(all)) and match?('Elixir.' ++ _, atom_to_list(atom)) do
198203
true ->
199204
target = Module.concat(unquote(current), atom)
200-
try do
201-
target.__impl__(:name)
202-
catch
203-
:error, :undef, [[{ ^target, :__impl__, [:name], _ }|_]|_] ->
204-
unquote(fallback)
205+
case impl_for?(target) do
206+
true -> target.__impl__(:name)
207+
false -> unquote(fallback)
205208
end
206209
false ->
207210
unquote(fallback)

lib/elixir/src/elixir_try.erl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@ each_clause({ 'catch', Meta, Raw, Expr }, Return, S) ->
1515
{ Args, Guards } = elixir_clauses:extract_splat_guards(Raw),
1616

1717
Final = case Args of
18-
[X] -> [throw, X, { '_', Meta, nil }];
19-
[X,Y] -> [X, Y, { '_', Meta, nil }];
20-
[_,_,_] -> Args;
21-
_ ->
18+
[X] -> [throw, X, { '_', Meta, nil }];
19+
[X,Y] -> [X, Y, { '_', Meta, nil }];
20+
_ ->
2221
elixir_errors:compile_error(Meta, S#elixir_scope.file, "too many arguments given for catch")
2322
end,
2423

0 commit comments

Comments
 (0)