diff --git a/lib/elixir/lib/inspect.ex b/lib/elixir/lib/inspect.ex index 7c20bcf8140..ff1c86d728f 100644 --- a/lib/elixir/lib/inspect.ex +++ b/lib/elixir/lib/inspect.ex @@ -662,35 +662,13 @@ end defimpl Inspect, for: Any do def inspect(%module{} = struct, opts) do - try do - module.__info__(:struct) - rescue - _ -> Inspect.Map.inspect_as_map(struct, opts) - else - info -> - if valid_struct?(info, struct) do - info = - for %{field: field} = map <- info, - field != :__exception__, - do: map - - Inspect.Map.inspect_as_struct(struct, Macro.inspect_atom(:literal, module), info, opts) - else - Inspect.Map.inspect_as_map(struct, opts) - end - end - end + info = + for %{field: field} = map <- module.__info__(:struct), + field != :__exception__, + do: map - defp valid_struct?(info, struct), do: valid_struct?(info, struct, map_size(struct) - 1) - - defp valid_struct?([%{field: field} | info], struct, count) when is_map_key(struct, field), - do: valid_struct?(info, struct, count - 1) - - defp valid_struct?([], _struct, 0), - do: true - - defp valid_struct?(_fields, _struct, _count), - do: false + Inspect.Map.inspect_as_struct(struct, Macro.inspect_atom(:literal, module), info, opts) + end def inspect_as_struct(map, name, infos, opts) do open = color_doc("#" <> name <> "<", :map, opts) diff --git a/lib/elixir/lib/inspect/algebra.ex b/lib/elixir/lib/inspect/algebra.ex index 62e039c938c..99b8d5cce55 100644 --- a/lib/elixir/lib/inspect/algebra.ex +++ b/lib/elixir/lib/inspect/algebra.ex @@ -396,7 +396,7 @@ defmodule Inspect.Algebra do def to_doc_with_opts(term, opts) def to_doc_with_opts(%_{} = struct, %Inspect.Opts{inspect_fun: fun} = opts) do - if opts.structs do + if opts.structs and valid_struct?(struct) do try do fun.(struct, opts) rescue @@ -453,6 +453,26 @@ defmodule Inspect.Algebra do fun.(arg, opts) |> pack_opts(opts) end + defp valid_struct?(%module{} = struct) do + try do + module.__info__(:struct) + rescue + _ -> false + else + info -> + valid_struct?(info, struct, map_size(struct) - 1) + end + end + + defp valid_struct?([%{field: field} | info], struct, count) when is_map_key(struct, field), + do: valid_struct?(info, struct, count - 1) + + defp valid_struct?([], _struct, 0), + do: true + + defp valid_struct?(_fields, _struct, _count), + do: false + defp pack_opts({_doc, %Inspect.Opts{}} = doc_opts, _opts), do: doc_opts defp pack_opts(doc, opts), do: {doc, opts} diff --git a/lib/elixir/test/elixir/calendar/date_range_test.exs b/lib/elixir/test/elixir/calendar/date_range_test.exs index 10fbf53df37..39465421ca4 100644 --- a/lib/elixir/test/elixir/calendar/date_range_test.exs +++ b/lib/elixir/test/elixir/calendar/date_range_test.exs @@ -149,27 +149,6 @@ defmodule Date.RangeTest do end describe "old date ranges" do - test "inspect" do - asc = %{ - __struct__: Date.Range, - first: ~D[2021-07-14], - first_in_iso_days: 738_350, - last: ~D[2021-07-17], - last_in_iso_days: 738_353 - } - - desc = %{ - __struct__: Date.Range, - first: ~D[2021-07-17], - first_in_iso_days: 738_353, - last: ~D[2021-07-14], - last_in_iso_days: 738_350 - } - - assert inspect(asc) == "Date.range(~D[2021-07-14], ~D[2021-07-17])" - assert inspect(desc) == "Date.range(~D[2021-07-17], ~D[2021-07-14], -1)" - end - test "enumerable" do asc = %{ __struct__: Date.Range, diff --git a/lib/elixir/test/elixir/inspect_test.exs b/lib/elixir/test/elixir/inspect_test.exs index ddc5cc04bd2..be589836b33 100644 --- a/lib/elixir/test/elixir/inspect_test.exs +++ b/lib/elixir/test/elixir/inspect_test.exs @@ -445,6 +445,13 @@ defmodule Inspect.MapTest do "%{__struct__: Inspect.MapTest.Public, foo: :bar, key: 1}" end + test "public modified struct with defimpl" do + map_set = MapSet.new([1, 2]) + + assert inspect(Map.put(map_set, :foo, :bar), custom_options: [sort_maps: true]) == + "%{__struct__: MapSet, foo: :bar, map: %{1 => [], 2 => []}}" + end + test "private struct" do assert inspect(%{__struct__: Private, key: 1}, custom_options: [sort_maps: true]) == "%{__struct__: Inspect.MapTest.Private, key: 1}" diff --git a/lib/elixir/test/elixir/range_test.exs b/lib/elixir/test/elixir/range_test.exs index 4f8783f261a..d273c992019 100644 --- a/lib/elixir/test/elixir/range_test.exs +++ b/lib/elixir/test/elixir/range_test.exs @@ -200,14 +200,6 @@ defmodule RangeTest do end describe "old ranges" do - test "inspect" do - asc = %{__struct__: Range, first: 1, last: 3} - desc = %{__struct__: Range, first: 3, last: 1} - - assert inspect(asc) == "1..3" - assert inspect(desc) == "3..1//-1" - end - test "enum" do asc = %{__struct__: Range, first: 1, last: 3} desc = %{__struct__: Range, first: 3, last: 1}