Skip to content

Commit c012456

Browse files
author
José Valim
committed
Reject __struct__ field on struct/2
1 parent 860c056 commit c012456

File tree

2 files changed

+50
-50
lines changed

2 files changed

+50
-50
lines changed

lib/elixir/lib/kernel.ex

Lines changed: 49 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,55 +1494,6 @@ defmodule Kernel do
14941494
:erlang.setelement(index + 1, tuple, value)
14951495
end
14961496

1497-
@doc """
1498-
Creates and updates structs.
1499-
1500-
The struct argument may be an atom (which defines `defstruct`)
1501-
or a struct itself. The second argument is any Enumerable that
1502-
emits two-item tuples (key-value) during enumeration.
1503-
1504-
If one of the keys in the Enumerable does not exist in the struct,
1505-
they are automatically discarded.
1506-
1507-
This function is useful for dynamically creating and updating
1508-
structs.
1509-
1510-
## Example
1511-
1512-
defmodule User do
1513-
defstruct name: "jose"
1514-
end
1515-
1516-
struct(User)
1517-
#=> %User{name: "jose"}
1518-
1519-
opts = [name: "eric"]
1520-
user = struct(User, opts)
1521-
#=> %User{name: "eric"}
1522-
1523-
struct(user, unknown: "value")
1524-
#=> %User{name: "eric"}
1525-
1526-
"""
1527-
def struct(struct, kv \\ [])
1528-
1529-
def struct(struct, []) when is_atom(struct) do
1530-
apply(struct, :__struct__, [])
1531-
end
1532-
1533-
def struct(struct, kv) when is_atom(struct) do
1534-
struct(apply(struct, :__struct__, []), kv)
1535-
end
1536-
1537-
def struct(%{ __struct__: _ } = struct, kv) do
1538-
Enum.reduce(kv, struct, fn { k, v }, acc ->
1539-
case :maps.is_key(k, acc) do
1540-
true -> :maps.put(k, v, acc)
1541-
false -> acc
1542-
end
1543-
end)
1544-
end
1545-
15461497
## Implemented in Elixir
15471498

15481499
@doc """
@@ -1928,6 +1879,55 @@ defmodule Kernel do
19281879
Inspect.Algebra.pretty(Inspect.Algebra.to_doc(arg, opts), limit)
19291880
end
19301881

1882+
@doc """
1883+
Creates and updates structs.
1884+
1885+
The struct argument may be an atom (which defines `defstruct`)
1886+
or a struct itself. The second argument is any Enumerable that
1887+
emits two-item tuples (key-value) during enumeration.
1888+
1889+
If one of the keys in the Enumerable does not exist in the struct,
1890+
they are automatically discarded.
1891+
1892+
This function is useful for dynamically creating and updating
1893+
structs.
1894+
1895+
## Example
1896+
1897+
defmodule User do
1898+
defstruct name: "jose"
1899+
end
1900+
1901+
struct(User)
1902+
#=> %User{name: "jose"}
1903+
1904+
opts = [name: "eric"]
1905+
user = struct(User, opts)
1906+
#=> %User{name: "eric"}
1907+
1908+
struct(user, unknown: "value")
1909+
#=> %User{name: "eric"}
1910+
1911+
"""
1912+
def struct(struct, kv \\ [])
1913+
1914+
def struct(struct, []) when is_atom(struct) do
1915+
apply(struct, :__struct__, [])
1916+
end
1917+
1918+
def struct(struct, kv) when is_atom(struct) do
1919+
struct(apply(struct, :__struct__, []), kv)
1920+
end
1921+
1922+
def struct(%{ __struct__: _ } = struct, kv) do
1923+
Enum.reduce(kv, struct, fn { k, v }, acc ->
1924+
case :maps.is_key(k, acc) and k != :__struct__ do
1925+
true -> :maps.put(k, v, acc)
1926+
false -> acc
1927+
end
1928+
end)
1929+
end
1930+
19311931
@doc """
19321932
Converts the argument to a string according to the String.Chars protocol.
19331933
This is the function invoked when there is string interpolation.

lib/elixir/test/elixir/kernel_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ defmodule KernelTest do
169169

170170
assert struct(user, unknown: "key") == user
171171
assert struct(user, name: "jose") == %User{ name: "jose" }
172-
assert struct(user, name: "other") == %User{ name: "other" }
172+
assert struct(user, name: "other", __struct__: Post) == %User{ name: "other" }
173173
end
174174

175175
defmodule Conversions do

0 commit comments

Comments
 (0)