diff --git a/lib/elixir/lib/exception.ex b/lib/elixir/lib/exception.ex index f3e02edbd55..63ec7a2407d 100644 --- a/lib/elixir/lib/exception.ex +++ b/lib/elixir/lib/exception.ex @@ -1997,8 +1997,23 @@ defmodule Protocol.UndefinedError do @impl true def message(%{protocol: protocol, value: value, description: description}) do - "protocol #{inspect(protocol)} not implemented for #{inspect(value)} of type " <> - value_type(value) <> maybe_description(description) <> maybe_available(protocol) + inspected = + value + |> inspect(pretty: true) + # Indent only lines with contents on them + |> String.replace(~r/^(?=.+)/m, " ") + + "protocol #{inspect(protocol)} not implemented for type " <> + value_type(value) <> + maybe_description(description) <> + maybe_available(protocol) <> + """ + + + Got value: + + #{inspected} + """ end defp value_type(%{__struct__: struct}), do: "#{inspect(struct)} (a struct)" diff --git a/lib/elixir/test/elixir/inspect_test.exs b/lib/elixir/test/elixir/inspect_test.exs index 9cd13caecc0..d7f2ffca477 100644 --- a/lib/elixir/test/elixir/inspect_test.exs +++ b/lib/elixir/test/elixir/inspect_test.exs @@ -526,16 +526,20 @@ defmodule Inspect.MapTest do # Inspect.Error is raised here when we tried to print the error message # called by another exception (Protocol.UndefinedError in this case) exception_message = ~s''' - protocol Enumerable not implemented for #Inspect.Error< - got ArgumentError with message: + protocol Enumerable not implemented for type Inspect.MapTest.Failing (a struct) - """ - errors were found at the given arguments: + Got value: - * 1st argument: not an atom - """ + #Inspect.Error< + got ArgumentError with message: - while inspecting: + """ + errors were found at the given arguments: + + * 1st argument: not an atom + """ + + while inspecting: ''' @@ -926,7 +930,11 @@ defmodule Inspect.CustomProtocolTest do got Protocol.UndefinedError with message: """ - protocol Inspect.CustomProtocolTest.CustomInspect not implemented for %Inspect.CustomProtocolTest.MissingImplementation{} of type Inspect.CustomProtocolTest.MissingImplementation (a struct) + protocol Inspect.CustomProtocolTest.CustomInspect not implemented for type Inspect.CustomProtocolTest.MissingImplementation (a struct) + + Got value: + + %Inspect.CustomProtocolTest.MissingImplementation{} """ while inspecting: @@ -953,7 +961,11 @@ defmodule Inspect.CustomProtocolTest do got Protocol.UndefinedError with message: """ - protocol Inspect.CustomProtocolTest.CustomInspect not implemented for %Inspect.CustomProtocolTest.MissingImplementation{} of type Inspect.CustomProtocolTest.MissingImplementation (a struct) + protocol Inspect.CustomProtocolTest.CustomInspect not implemented for type Inspect.CustomProtocolTest.MissingImplementation (a struct) + + Got value: + + %Inspect.CustomProtocolTest.MissingImplementation{} """ while inspecting: diff --git a/lib/elixir/test/elixir/protocol/consolidation_test.exs b/lib/elixir/test/elixir/protocol/consolidation_test.exs index 43ce2380c54..d8adc72dd97 100644 --- a/lib/elixir/test/elixir/protocol/consolidation_test.exs +++ b/lib/elixir/test/elixir/protocol/consolidation_test.exs @@ -182,8 +182,9 @@ defmodule Protocol.ConsolidationTest do test "protocol not implemented" do message = - "protocol Protocol.ConsolidationTest.Sample not implemented for :foo of type Atom. " <> - "This protocol is implemented for the following type(s): Protocol.ConsolidationTest.ImplStruct" + "protocol Protocol.ConsolidationTest.Sample not implemented for type Atom. " <> + "This protocol is implemented for the following type(s): Protocol.ConsolidationTest.ImplStruct" <> + "\n\nGot value:\n\n :foo\n" assert_raise Protocol.UndefinedError, message, fn -> sample = String.to_atom("Elixir.Protocol.ConsolidationTest.Sample") diff --git a/lib/elixir/test/elixir/protocol_test.exs b/lib/elixir/test/elixir/protocol_test.exs index 72184400e10..041937f44f1 100644 --- a/lib/elixir/test/elixir/protocol_test.exs +++ b/lib/elixir/test/elixir/protocol_test.exs @@ -113,7 +113,14 @@ defmodule ProtocolTest do end test "protocol not implemented" do - message = "protocol ProtocolTest.Sample not implemented for :foo of type Atom" + message = + """ + protocol ProtocolTest.Sample not implemented for type Atom + + Got value: + + :foo + """ assert_raise Protocol.UndefinedError, message, fn -> sample = String.to_atom("Elixir.ProtocolTest.Sample") diff --git a/lib/elixir/test/elixir/string/chars_test.exs b/lib/elixir/test/elixir/string/chars_test.exs index 934425f0292..dd3cf61a02e 100644 --- a/lib/elixir/test/elixir/string/chars_test.exs +++ b/lib/elixir/test/elixir/string/chars_test.exs @@ -105,7 +105,13 @@ defmodule String.Chars.ErrorsTest do test "bitstring" do message = - "protocol String.Chars not implemented for <<0, 1::size(4)>> of type BitString, cannot convert a bitstring to a string" + """ + protocol String.Chars not implemented for type BitString, cannot convert a bitstring to a string + + Got value: + + <<0, 1::size(4)>> + """ assert_raise Protocol.UndefinedError, message, fn -> to_string(<<1::size(12)-integer-signed>>) @@ -113,7 +119,13 @@ defmodule String.Chars.ErrorsTest do end test "tuple" do - message = "protocol String.Chars not implemented for {1, 2, 3} of type Tuple" + message = """ + protocol String.Chars not implemented for type Tuple + + Got value: + + {1, 2, 3} + """ assert_raise Protocol.UndefinedError, message, fn -> to_string({1, 2, 3}) @@ -121,7 +133,8 @@ defmodule String.Chars.ErrorsTest do end test "PID" do - message = ~r"^protocol String\.Chars not implemented for #PID<.+?> of type PID$" + message = + ~r"^protocol String\.Chars not implemented for type PID\n\nGot value:\n\n #PID<.+?>$" assert_raise Protocol.UndefinedError, message, fn -> to_string(self()) @@ -129,7 +142,8 @@ defmodule String.Chars.ErrorsTest do end test "ref" do - message = ~r"^protocol String\.Chars not implemented for #Reference<.+?> of type Reference$" + message = + ~r"^protocol String\.Chars not implemented for type Reference\n\nGot value:\n\n #Reference<.+?>$" assert_raise Protocol.UndefinedError, message, fn -> to_string(make_ref()) == "" @@ -137,7 +151,8 @@ defmodule String.Chars.ErrorsTest do end test "function" do - message = ~r"^protocol String\.Chars not implemented for #Function<.+?> of type Function$" + message = + ~r"^protocol String\.Chars not implemented for type Function\n\nGot value:\n\n #Function<.+?>$" assert_raise Protocol.UndefinedError, message, fn -> to_string(fn -> nil end) @@ -146,7 +161,9 @@ defmodule String.Chars.ErrorsTest do test "port" do [port | _] = Port.list() - message = ~r"^protocol String\.Chars not implemented for #Port<.+?> of type Port$" + + message = + ~r"^protocol String\.Chars not implemented for type Port\n\nGot value:\n\n #Port<.+?>$" assert_raise Protocol.UndefinedError, message, fn -> to_string(port) @@ -155,7 +172,7 @@ defmodule String.Chars.ErrorsTest do test "user-defined struct" do message = - "protocol String\.Chars not implemented for %String.Chars.ErrorsTest.Foo{foo: \"bar\"} of type String.Chars.ErrorsTest.Foo (a struct)" + "protocol String\.Chars not implemented for type String.Chars.ErrorsTest.Foo (a struct)\n\nGot value:\n\n %String.Chars.ErrorsTest.Foo{foo: \"bar\"}\n" assert_raise Protocol.UndefinedError, message, fn -> to_string(%Foo{})