Skip to content

Commit b1a10f2

Browse files
author
José Valim
committed
Only perform behaviour checking if blaming
1 parent dcb4f22 commit b1a10f2

File tree

2 files changed

+26
-27
lines changed

2 files changed

+26
-27
lines changed

lib/elixir/lib/exception.ex

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -924,38 +924,14 @@ defmodule UndefinedFunctionError do
924924

925925
defp message(:"function not exported", module, function, arity) do
926926
formatted_fun = Exception.format_mfa(module, function, arity)
927-
fun_message = "function #{formatted_fun} is undefined or private"
928-
behaviour_hint = behaviour_hint(module, function, arity)
929-
{fun_message <> behaviour_hint, true}
927+
{"function #{formatted_fun} is undefined or private", true}
930928
end
931929

932930
defp message(reason, module, function, arity) do
933931
formatted_fun = Exception.format_mfa(module, function, arity)
934932
{"function #{formatted_fun} is undefined (#{reason})", false}
935933
end
936934

937-
defp behaviour_hint(module, function, arity) do
938-
case behaviours_for(module) do
939-
[] ->
940-
""
941-
942-
behaviours ->
943-
case Enum.find(behaviours, &expects_callback?(&1, function, arity)) do
944-
nil -> ""
945-
behaviour -> ", but the behaviour #{inspect(behaviour)} expects it to be present"
946-
end
947-
end
948-
rescue
949-
# In case the module was removed while we are computing this
950-
UndefinedFunctionError ->
951-
[]
952-
end
953-
954-
defp expects_callback?(behaviour, function, arity) do
955-
callbacks = behaviour.behaviour_info(:callbacks)
956-
Enum.member?(callbacks, {function, arity})
957-
end
958-
959935
@impl true
960936
def blame(exception, stacktrace) do
961937
%{reason: reason, module: module, function: function, arity: arity} = exception
@@ -970,7 +946,8 @@ defmodule UndefinedFunctionError do
970946
end
971947

972948
defp hint(module, function, arity, true) do
973-
hint_for_loaded_module(module, function, arity, nil)
949+
behaviour_hint(module, function, arity) <>
950+
hint_for_loaded_module(module, function, arity, nil)
974951
end
975952

976953
defp hint(_module, _function, _arity, _loaded?) do
@@ -1021,12 +998,33 @@ defmodule UndefinedFunctionError do
1021998
[" * ", Code.Identifier.inspect_as_function(fun), ?/, Integer.to_string(arity), ?\n]
1022999
end
10231000

1001+
defp behaviour_hint(module, function, arity) do
1002+
case behaviours_for(module) do
1003+
[] ->
1004+
""
1005+
1006+
behaviours ->
1007+
case Enum.find(behaviours, &expects_callback?(&1, function, arity)) do
1008+
nil -> ""
1009+
behaviour -> ", but the behaviour #{inspect(behaviour)} expects it to be present"
1010+
end
1011+
end
1012+
rescue
1013+
# In case the module was removed while we are computing this
1014+
UndefinedFunctionError -> ""
1015+
end
1016+
10241017
defp behaviours_for(module) do
10251018
:attributes
10261019
|> module.module_info()
10271020
|> Keyword.get(:behaviour, [])
10281021
end
10291022

1023+
defp expects_callback?(behaviour, function, arity) do
1024+
callbacks = behaviour.behaviour_info(:callbacks)
1025+
Enum.member?(callbacks, {function, arity})
1026+
end
1027+
10301028
defp exports_for(module) do
10311029
if function_exported?(module, :__info__, 1) do
10321030
module.__info__(:macros) ++ module.__info__(:functions)

lib/elixir/test/elixir/exception_test.exs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,8 @@ defmodule ExceptionTest do
739739
@behaviour Behaviour
740740
end
741741

742-
assert %UndefinedFunctionError{module: Implementation, function: :callback, arity: 0}
742+
assert Exception.blame(:error, :undef, [{Implementation, :callback, 0, []}])
743+
|> elem(0)
743744
|> message ==
744745
"function ExceptionTest.Implementation.callback/0 is undefined or private" <>
745746
", but the behaviour ExceptionTest.Behaviour expects it to be present"

0 commit comments

Comments
 (0)