@@ -185,12 +185,15 @@ defmodule Module.Types.Pattern do
185185 { version , context }
186186 end )
187187
188- try do
189- { types , of_pattern_var_deps ( changed , vars_paths , vars_deps , tag , stack , context ) }
190- catch
191- { :error , context } -> { types , error_vars ( pattern_info , context ) }
192- end
188+ context =
189+ Enum . reduce ( changed , context , fn version , context ->
190+ { _ , context } = of_pattern_var_dep ( vars_paths , version , tag , stack , context )
191+ context
192+ end )
193+
194+ { types , of_pattern_var_deps ( changed , vars_paths , vars_deps , tag , stack , context ) }
193195 catch
196+ { :error , context } -> { types , error_vars ( pattern_info , context ) }
194197 { types , context } -> { types , error_vars ( pattern_info , context ) }
195198 end
196199 end
@@ -201,52 +204,55 @@ defmodule Module.Types.Pattern do
201204
202205 defp of_pattern_var_deps ( previous_changed , vars_paths , vars_deps , tag , stack , context ) do
203206 { changed , context } =
204- Enum . reduce ( previous_changed , { [ ] , context } , fn version , { changed , context } ->
205- paths = Map . get ( vars_paths , version , [ ] )
206-
207- { var_changed? , context } =
208- Enum . reduce ( paths , { false , context } , fn
209- % { var: var , expr: expr , root: root , path: path } , { var_changed? , context } ->
210- index = 0
211- actual = of_pattern_tree ( root , context )
212-
213- case of_pattern_var ( path , actual , context ) do
214- { :ok , type } ->
215- # Optimization: if current type is already a subtype, there is nothing to refine.
216- with % { ^ version => % { type: current_type } } <- context . vars ,
217- true <- subtype? ( current_type , type ) do
218- { var_changed? , context }
219- else
220- _ ->
221- case Of . refine_head_var ( var , type , expr , stack , context ) do
222- { :ok , _type , context } ->
223- { true , context }
224-
225- { :error , old_type , context } ->
226- throw ( { :error , refine_error ( var , old_type , type , stack , context ) } )
227- end
228- end
229-
230- :error ->
231- throw ( { :error , badpattern_error ( expr , index , tag , stack , context ) } )
232- end
233- end )
207+ previous_changed
208+ |> Enum . reduce ( % { } , fn version , acc ->
209+ case vars_deps do
210+ % { ^ version => deps } -> Map . merge ( acc , deps )
211+ % { } -> acc
212+ end
213+ end )
214+ |> Map . keys ( )
215+ |> Enum . reduce ( { [ ] , context } , fn version , { changed , context } ->
216+ { var_changed? , context } = of_pattern_var_dep ( vars_paths , version , tag , stack , context )
234217
235218 case var_changed? do
236219 false -> { changed , context }
237220 true -> { [ version | changed ] , context }
238221 end
239222 end )
240223
241- changed
242- |> Enum . reduce ( % { } , fn version , acc ->
243- case vars_deps do
244- % { ^ version => deps } -> Map . merge ( acc , deps )
245- % { } -> acc
246- end
224+ of_pattern_var_deps ( changed , vars_paths , vars_deps , tag , stack , context )
225+ end
226+
227+ defp of_pattern_var_dep ( vars_paths , version , tag , stack , context ) do
228+ paths = Map . get ( vars_paths , version , [ ] )
229+
230+ Enum . reduce ( paths , { false , context } , fn
231+ % { var: var , expr: expr , root: root , path: path } , { var_changed? , context } ->
232+ index = 0
233+ actual = of_pattern_tree ( root , context )
234+
235+ case of_pattern_var ( path , actual , context ) do
236+ { :ok , type } ->
237+ # Optimization: if current type is already a subtype, there is nothing to refine.
238+ with % { ^ version => % { type: current_type } } <- context . vars ,
239+ true <- subtype? ( current_type , type ) do
240+ { var_changed? , context }
241+ else
242+ _ ->
243+ case Of . refine_head_var ( var , type , expr , stack , context ) do
244+ { :ok , _type , context } ->
245+ { true , context }
246+
247+ { :error , old_type , context } ->
248+ throw ( { :error , refine_error ( var , old_type , type , stack , context ) } )
249+ end
250+ end
251+
252+ :error ->
253+ throw ( { :error , badpattern_error ( expr , index , tag , stack , context ) } )
254+ end
247255 end )
248- |> Map . keys ( )
249- |> of_pattern_var_deps ( vars_paths , vars_deps , tag , stack , context )
250256 end
251257
252258 defp error_vars ( { args_paths , vars_paths , _vars_deps } , context ) do
@@ -431,7 +437,7 @@ defmodule Module.Types.Pattern do
431437 { match , version , var } =
432438 match
433439 |> unpack_match ( [ ] )
434- |> Enum . split_while ( & ( not is_var ( & 1 ) ) )
440+ |> Enum . split_while ( & ( not is_versioned_var ( & 1 ) ) )
435441 |> case do
436442 { match , [ ] } ->
437443 version = make_ref ( )
@@ -575,6 +581,11 @@ defmodule Module.Types.Pattern do
575581 { { :var , version } , context }
576582 end
577583
584+ defp is_versioned_var ( { name , _meta , ctx } ) when is_atom ( name ) and is_atom ( ctx ) and name != :_ ,
585+ do: true
586+
587+ defp is_versioned_var ( _ ) , do: false
588+
578589 defp of_var ( var , version , reverse_path , context ) do
579590 { args_paths , vars_paths , vars_deps } = context . pattern_info
580591 [ % { root: root , expr: expr } | path ] = Enum . reverse ( reverse_path )
0 commit comments