Skip to content

Commit 1ca0636

Browse files
committed
Type checking of stacktrace and error/raise functions
1 parent 3e9fb4d commit 1ca0636

File tree

6 files changed

+115
-59
lines changed

6 files changed

+115
-59
lines changed

lib/elixir/lib/kernel.ex

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,28 +2217,22 @@ defmodule Kernel do
22172217
case Macro.expand(message, __CALLER__) do
22182218
message when is_binary(message) ->
22192219
quote do
2220-
:erlang.error(
2221-
:erlang.raise(:error, RuntimeError.exception(unquote(message)), unquote(stacktrace))
2222-
)
2220+
:erlang.raise(:error, RuntimeError.exception(unquote(message)), unquote(stacktrace))
22232221
end
22242222

22252223
{:<<>>, _, _} = message ->
22262224
quote do
2227-
:erlang.error(
2228-
:erlang.raise(:error, RuntimeError.exception(unquote(message)), unquote(stacktrace))
2229-
)
2225+
:erlang.raise(:error, RuntimeError.exception(unquote(message)), unquote(stacktrace))
22302226
end
22312227

22322228
alias when is_atom(alias) ->
22332229
quote do
2234-
:erlang.error(:erlang.raise(:error, unquote(alias).exception([]), unquote(stacktrace)))
2230+
:erlang.raise(:error, unquote(alias).exception([]), unquote(stacktrace))
22352231
end
22362232

22372233
message ->
22382234
quote do
2239-
:erlang.error(
2240-
:erlang.raise(:error, Kernel.Utils.raise(unquote(message)), unquote(stacktrace))
2241-
)
2235+
:erlang.raise(:error, Kernel.Utils.raise(unquote(message)), unquote(stacktrace))
22422236
end
22432237
end
22442238
end

lib/elixir/lib/module/types/expr.ex

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,12 @@ defmodule Module.Types.Expr do
110110
# left = right
111111
def of_expr({:=, _meta, [left_expr, right_expr]} = expr, stack, context) do
112112
{right_type, context} = of_expr(right_expr, stack, context)
113-
Pattern.of_match(left_expr, right_type, expr, stack, context)
113+
114+
# We do not raise on underscore in case someone writes _ = raise "omg"
115+
case left_expr do
116+
{:_, _, ctx} when is_atom(ctx) -> {right_type, context}
117+
_ -> Pattern.of_match(left_expr, right_type, expr, stack, context)
118+
end
114119
end
115120

116121
# %{map | ...}

lib/elixir/lib/module/types/of.ex

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,28 @@ defmodule Module.Types.Of do
365365

366366
is_clauses = [{[term()], boolean()}]
367367

368+
args_or_arity = union(list(term()), integer())
369+
args_or_none = union(list(term()), atom([:none]))
370+
371+
kw = fn kw ->
372+
kw
373+
|> Enum.map(fn {key, type} when is_atom(key) ->
374+
tuple([atom([key]), type])
375+
end)
376+
|> Enum.reduce(&union/2)
377+
|> list()
378+
end
379+
380+
extra_info = kw.(file: list(integer()), line: integer(), error_info: open_map())
381+
382+
raise_stacktrace =
383+
list(
384+
tuple([atom(), atom(), args_or_arity, extra_info])
385+
|> union(tuple([atom(), atom(), args_or_arity]))
386+
|> union(tuple([fun(), args_or_arity, extra_info]))
387+
|> union(tuple([fun(), args_or_arity]))
388+
)
389+
368390
for {mod, fun, clauses} <- [
369391
# :binary
370392
{:binary, :copy, [{[binary(), integer()], binary()}]},
@@ -403,6 +425,9 @@ defmodule Module.Types.Of do
403425
{:erlang, :byte_size, [{[binary()], integer()}]},
404426
{:erlang, :ceil, [{[union(integer(), float())], integer()}]},
405427
{:erlang, :div, [{[integer(), integer()], integer()}]},
428+
{:erlang, :error, [{[term()], none()}]},
429+
{:erlang, :error, [{[term(), args_or_none], none()}]},
430+
{:erlang, :error, [{[term(), args_or_none, kw.(error_info: open_map())], none()}]},
406431
{:erlang, :floor, [{[union(integer(), float())], integer()}]},
407432
{:erlang, :function_exported, [{[atom(), atom(), integer()], boolean()}]},
408433
{:erlang, :integer_to_binary, [{[integer()], binary()}]},
@@ -437,6 +462,7 @@ defmodule Module.Types.Of do
437462
{:erlang, :node, [{[], atom()}]},
438463
{:erlang, :node, [{[pid() |> union(reference()) |> union(port())], atom()}]},
439464
{:erlang, :not, [{[atom([false])], atom([true])}, {[atom([true])], atom([false])}]},
465+
{:erlang, :raise, [{[atom([:error, :exit, :throw]), term(), raise_stacktrace], none()}]},
440466
{:erlang, :rem, [{[integer(), integer()], integer()}]},
441467
{:erlang, :round, [{[union(integer(), float())], integer()}]},
442468
{:erlang, :self, [{[], pid()}]},

lib/elixir/test/elixir/kernel/raise_test.exs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -163,16 +163,6 @@ defmodule Kernel.RaiseTest do
163163
end
164164
end
165165

166-
test "reraise with invalid stacktrace" do
167-
try do
168-
reraise %RuntimeError{message: "message"}, {:oops, @trace}
169-
rescue
170-
ArgumentError ->
171-
{name, arity} = __ENV__.function
172-
assert [{__MODULE__, ^name, ^arity, _} | _] = __STACKTRACE__
173-
end
174-
end
175-
176166
describe "rescue" do
177167
test "runtime error" do
178168
result =

lib/elixir/test/elixir/module/types/pattern_test.exs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ defmodule Module.Types.PatternTest do
6969
"""
7070
end
7171

72-
test "can be access even if they don't match" do
72+
test "can be accessed even if they don't match" do
7373
assert typeerror!(
7474
(
7575
# This will never match, info should not be "corrupted"
@@ -78,6 +78,10 @@ defmodule Module.Types.PatternTest do
7878
)
7979
) =~ "incompatible types in expression"
8080
end
81+
82+
test "does not check underscore" do
83+
assert typecheck!(_ = raise("oops")) == none()
84+
end
8185
end
8286

8387
describe "structs" do

0 commit comments

Comments
 (0)