Skip to content

Commit 39494ca

Browse files
committed
More refine var
1 parent 72f2646 commit 39494ca

2 files changed

Lines changed: 45 additions & 28 deletions

File tree

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

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,7 @@ defmodule Module.Types.Of do
100100

101101
# We need to return error otherwise it leads to cascading errors
102102
if empty?(new_type) do
103-
{:error, error_type(),
104-
error({:refine_head_var, old_type, type, var, context}, meta, stack, context)}
103+
{:error, old_type, context}
105104
else
106105
{:ok, new_type, context}
107106
end
@@ -546,23 +545,6 @@ defmodule Module.Types.Of do
546545
error(__MODULE__, warning, meta, stack, context)
547546
end
548547

549-
def format_diagnostic({:refine_head_var, old_type, new_type, var, context}) do
550-
traces = collect_traces(var, context)
551-
552-
%{
553-
details: %{typing_traces: traces},
554-
message:
555-
IO.iodata_to_binary([
556-
"""
557-
incompatible types assigned to #{format_var(var)}:
558-
559-
#{to_quoted_string(old_type)} !~ #{to_quoted_string(new_type)}
560-
""",
561-
format_traces(traces)
562-
])
563-
}
564-
end
565-
566548
def format_diagnostic({:badbinary, kind, meta, expr, expected_type, actual_type, context}) do
567549
type = if kind == :match, do: "matching", else: "construction"
568550
hints = if meta[:inferred_bitstring_spec], do: [:inferred_bitstring_spec], else: []

lib/elixir/lib/module/types/pattern.ex

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,11 @@ defmodule Module.Types.Pattern do
170170
case of_pattern_var(path, actual, context) do
171171
{:ok, type} ->
172172
case Of.refine_head_var(var, type, expr, stack, context) do
173-
{:ok, _type, context} -> context
174-
{:error, _type, context} -> throw({types, context})
173+
{:ok, _type, context} ->
174+
context
175+
176+
{:error, old_type, context} ->
177+
throw({types, refine_error(var, old_type, type, stack, context)})
175178
end
176179

177180
:error ->
@@ -182,7 +185,11 @@ defmodule Module.Types.Pattern do
182185
{version, context}
183186
end)
184187

185-
{types, of_pattern_var_deps(changed, vars_paths, vars_deps, tag, stack, context)}
188+
try do
189+
{types, of_pattern_var_deps(changed, vars_paths, vars_deps, tag, stack, context)}
190+
catch
191+
{:error, context} -> {types, context}
192+
end
186193
catch
187194
{types, context} -> {types, error_vars(pattern_info, context)}
188195
end
@@ -212,8 +219,11 @@ defmodule Module.Types.Pattern do
212219
else
213220
_ ->
214221
case Of.refine_head_var(var, type, expr, stack, context) do
215-
{:ok, _type, context} -> {true, context}
216-
{:error, _type, context} -> throw({:error, context})
222+
{:ok, _type, context} ->
223+
{true, context}
224+
225+
{:error, old_type, context} ->
226+
throw({:error, refine_error(var, old_type, type, stack, context)})
217227
end
218228
end
219229

@@ -249,6 +259,10 @@ defmodule Module.Types.Pattern do
249259
context
250260
end
251261

262+
defp refine_error({_, meta, _} = var, old_type, type, stack, context) do
263+
error(__MODULE__, {:badvar, old_type, type, var, context}, meta, stack, context)
264+
end
265+
252266
defp badpattern_error(expr, index, tag, stack, context) do
253267
meta =
254268
if meta = get_meta(expr) do
@@ -361,8 +375,13 @@ defmodule Module.Types.Pattern do
361375
end
362376

363377
def of_match_var(var, expected, expr, stack, context) when is_var(var) do
364-
{_ok?, type, context} = Of.refine_head_var(var, expected, expr, stack, context)
365-
{type, context}
378+
case Of.refine_head_var(var, expected, expr, stack, context) do
379+
{:ok, type, context} ->
380+
{type, context}
381+
382+
{:error, old_type, context} ->
383+
{error_type(), refine_error(var, old_type, expected, stack, context)}
384+
end
366385
end
367386

368387
def of_match_var({:<<>>, _meta, args}, _expected, _expr, stack, context) do
@@ -415,7 +434,7 @@ defmodule Module.Types.Pattern do
415434
|> case do
416435
{match, []} ->
417436
version = make_ref()
418-
{match, version, {:temp, [version: version], __MODULE__}}
437+
{match, version, {:match, [version: version], __MODULE__}}
419438

420439
{pre, [{_, meta, _} = var | post]} ->
421440
version = Keyword.fetch!(meta, :version)
@@ -454,7 +473,6 @@ defmodule Module.Types.Pattern do
454473
end
455474

456475
# %Struct{...}
457-
# TODO: Once we support typed structs, we need to type check them here.
458476
defp of_pattern({:%, meta, [struct, {:%{}, _, args}]}, path, stack, context)
459477
when is_atom(struct) do
460478
{info, context} = Of.struct_info(struct, meta, stack, context)
@@ -781,6 +799,23 @@ defmodule Module.Types.Pattern do
781799
{pattern_info, %{context | pattern_info: nil}}
782800
end
783801

802+
def format_diagnostic({:badvar, old_type, new_type, var, context}) do
803+
traces = collect_traces(var, context)
804+
805+
%{
806+
details: %{typing_traces: traces},
807+
message:
808+
IO.iodata_to_binary([
809+
"""
810+
incompatible types assigned to #{format_var(var)}:
811+
812+
#{to_quoted_string(old_type)} !~ #{to_quoted_string(new_type)}
813+
""",
814+
format_traces(traces)
815+
])
816+
}
817+
end
818+
784819
def format_diagnostic({:badstruct, type, expr, context}) do
785820
traces = collect_traces(expr, context)
786821

0 commit comments

Comments
 (0)