Skip to content

Commit eb1f6ed

Browse files
committed
Refactor refine_body_var for guards
1 parent e193fd5 commit eb1f6ed

3 files changed

Lines changed: 18 additions & 30 deletions

File tree

lib/elixir/lib/module/types.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ defmodule Module.Types do
452452
subpatterns: %{},
453453
# Variables that are specific to the current environment/conditional
454454
conditional_vars: nil,
455-
# Track metadata specific to matches and guards
455+
# Track metadata specific to patterns and guards
456456
pattern_info: nil,
457457
# If type checking has found an error/failure
458458
failed: false,

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

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,14 @@ defmodule Module.Types.Of do
8686
or if we are doing a guard analysis or occurrence typing.
8787
Returns `true` if there was a refinement, `false` otherwise.
8888
"""
89-
def refine_body_var(var_or_version, type, expr, stack, context, allow_empty? \\ false)
89+
@skip_refinement_for [term(), dynamic()]
90+
def refine_body_var(var_or_version, type, expr, stack, context)
9091

91-
def refine_body_var({_, meta, _}, type, expr, stack, context, allow_empty?) do
92-
refine_body_var(Keyword.fetch!(meta, :version), type, expr, stack, context, allow_empty?)
92+
def refine_body_var({_, meta, _}, type, expr, stack, context) do
93+
refine_body_var(Keyword.fetch!(meta, :version), type, expr, stack, context)
9394
end
9495

95-
def refine_body_var(version, type, expr, stack, context, allow_empty?)
96+
def refine_body_var(version, type, expr, stack, context)
9697
when is_integer(version) or is_reference(version) do
9798
%{vars: %{^version => %{type: old_type, off_traces: off_traces} = data} = vars} = context
9899

@@ -105,12 +106,15 @@ defmodule Module.Types.Of do
105106
context
106107
end
107108

108-
if match?(%{pattern_info: %{allow_empty?: _}}, context) do
109-
if type not in [term(), dynamic()] and not is_map_key(data, :errored) do
109+
case context do
110+
_ when type in @skip_refinement_for or is_map_key(data, :errored) ->
111+
{old_type, context}
112+
113+
%{pattern_info: %{guard_context: guard_context}} ->
110114
new_type = intersection(old_type, type)
111115

112116
case empty?(new_type) do
113-
true when allow_empty? ->
117+
true when guard_context == :orelse ->
114118
data = %{
115119
data
116120
| type: none(),
@@ -131,21 +135,9 @@ defmodule Module.Types.Of do
131135
_ ->
132136
{old_type, context}
133137
end
134-
else
135-
{old_type, context}
136-
end
137-
else
138-
if gradual?(old_type) and type not in [term(), dynamic()] and not is_map_key(data, :errored) do
139-
case compatible_intersection(old_type, type) do
140-
{:error, _} when allow_empty? ->
141-
data = %{
142-
data
143-
| type: none(),
144-
off_traces: new_trace(expr, none(), stack, off_traces)
145-
}
146-
147-
{none(), %{context | vars: %{vars | version => data}}}
148138

139+
_ ->
140+
case gradual?(old_type) and compatible_intersection(old_type, type) do
149141
{:ok, new_type} when new_type != old_type ->
150142
data = %{
151143
data
@@ -158,9 +150,6 @@ defmodule Module.Types.Of do
158150
_ ->
159151
{old_type, context}
160152
end
161-
else
162-
{old_type, context}
163-
end
164153
end
165154
end
166155

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,7 +1026,7 @@ defmodule Module.Types.Pattern do
10261026
defp of_guards(guards, vars, stack, context) do
10271027
context =
10281028
init_pattern_info(context, %{
1029-
allow_empty?: false,
1029+
guard_context: :andalso,
10301030
parent_version: nil,
10311031
vars: vars,
10321032
changed: %{}
@@ -1066,7 +1066,7 @@ defmodule Module.Types.Pattern do
10661066
end
10671067

10681068
defp enable_conditional_mode(%{pattern_info: pattern_info} = context) do
1069-
%{context | pattern_info: %{pattern_info | allow_empty?: true}, conditional_vars: %{}}
1069+
%{context | pattern_info: %{pattern_info | guard_context: :orelse}, conditional_vars: %{}}
10701070
end
10711071

10721072
defp maybe_badguard(type, guard, stack, context) do
@@ -1184,8 +1184,7 @@ defmodule Module.Types.Pattern do
11841184
# and also when vars change, so we need to deal with all possibilities
11851185
# for pattern_info.
11861186
case context.pattern_info do
1187-
%{allow_empty?: allow_empty?, vars: vars, parent_version: parent_version, changed: changed} =
1188-
pattern_info ->
1187+
%{vars: vars, parent_version: parent_version, changed: changed} = pattern_info ->
11891188
vars =
11901189
is_map(vars) and not is_map_key(vars, version) and
11911190
not list_subpattern?(version, context) and vars
@@ -1199,7 +1198,7 @@ defmodule Module.Types.Pattern do
11991198
do: Of.track_var(version, [parent_version], [], context),
12001199
else: context
12011200

1202-
Of.refine_body_var(version, expected, expr, stack, context, allow_empty?)
1201+
Of.refine_body_var(version, expected, expr, stack, context)
12031202

12041203
list when is_list(list) ->
12051204
node = path_node(expected, var, expr, [])

0 commit comments

Comments
 (0)