@@ -62,13 +62,13 @@ defmodule Module.Types.Pattern do
6262 { trees , context } = of_pattern_args_index ( patterns , 0 , [ ] , stack , context )
6363 { pattern_info , context } = pop_pattern_info ( context )
6464
65- { _ , context } =
65+ context =
6666 case of_pattern_args_tree ( trees , expected , 0 , [ ] , tag , stack , context ) do
6767 { :ok , types , context } ->
6868 of_pattern_recur ( types , tag , pattern_info , stack , context )
6969
7070 { :error , context } ->
71- { expected , error_vars ( pattern_info , context ) }
71+ error_vars ( pattern_info , context )
7272 end
7373
7474 { trees , context }
@@ -149,7 +149,7 @@ defmodule Module.Types.Pattern do
149149 defp of_single_pattern_recur ( expected , tag , tree , pattern_info , expr , stack , context ) do
150150 case of_pattern_intersect ( tree , expected , expr , 0 , tag , stack , context ) do
151151 { :ok , type , context } ->
152- of_pattern_recur ( [ type ] , tag , pattern_info , stack , context )
152+ { [ type ] , of_pattern_recur ( [ type ] , tag , pattern_info , stack , context ) }
153153
154154 { :error , context } ->
155155 { [ expected ] , error_vars ( pattern_info , context ) }
@@ -160,40 +160,44 @@ defmodule Module.Types.Pattern do
160160 { args_paths , vars_paths , vars_deps } = pattern_info
161161
162162 try do
163- { changed , context } =
164- Enum . map_reduce ( args_paths , context , fn { version , paths } , context ->
165- context =
166- Enum . reduce ( paths , context , fn
167- % { var: var , expr: expr , root: { :arg , index } , path: path } , context ->
168- actual = Enum . fetch! ( types , index )
169-
170- case of_pattern_var ( path , actual , context ) do
171- { :ok , type } ->
172- case Of . refine_head_var ( var , type , expr , stack , context ) do
173- { :ok , _type , context } ->
174- context
175-
176- { :error , old_type , context } ->
177- throw ( { types , badvar_error ( var , old_type , type , expr , stack , context ) } )
178- end
179-
180- :error ->
181- throw ( { types , badpattern_error ( expr , index , tag , stack , context ) } )
182- end
183- end )
163+ Enum . map_reduce ( args_paths , context , fn { version , paths } , context ->
164+ context =
165+ Enum . reduce ( paths , context , fn
166+ % { var: var , expr: expr , root: { :arg , index } , path: path } , context ->
167+ actual = Enum . fetch! ( types , index )
184168
185- { version , context }
186- end )
169+ case of_pattern_var ( path , actual , context ) do
170+ { :ok , new_type } ->
171+ case Of . refine_head_var ( var , new_type , expr , stack , context ) do
172+ { :ok , _type , context } ->
173+ context
174+
175+ { :error , old_type , error_context } ->
176+ if match_error? ( var , new_type ) do
177+ throw ( badpattern_error ( expr , index , tag , stack , context ) )
178+ else
179+ throw ( badvar_error ( var , old_type , new_type , stack , error_context ) )
180+ end
181+ end
187182
188- context =
189- Enum . reduce ( changed , context , fn version , context ->
190- { _ , context } = of_pattern_var_dep ( vars_paths , version , stack , context )
191- context
192- end )
183+ :error ->
184+ throw ( badpattern_error ( expr , index , tag , stack , context ) )
185+ end
186+ end )
193187
194- { types , of_pattern_var_deps ( changed , vars_paths , vars_deps , stack , context ) }
188+ { version , context }
189+ end )
195190 catch
196- { types , context } -> { types , error_vars ( pattern_info , context ) }
191+ context -> error_vars ( pattern_info , context )
192+ else
193+ { changed , context } ->
194+ context =
195+ Enum . reduce ( changed , context , fn version , context ->
196+ { _ , context } = of_pattern_var_dep ( vars_paths , version , stack , context )
197+ context
198+ end )
199+
200+ of_pattern_var_deps ( changed , vars_paths , vars_deps , stack , context )
197201 end
198202 end
199203
@@ -227,29 +231,33 @@ defmodule Module.Types.Pattern do
227231 paths = Map . get ( vars_paths , version , [ ] )
228232
229233 case context . vars do
230- % { ^ version => % { type: current_type } = data } when not is_map_key ( data , :errored ) ->
234+ % { ^ version => % { type: old_type } = data } when not is_map_key ( data , :errored ) ->
231235 try do
232236 Enum . reduce ( paths , { false , context } , fn
233237 % { var: var , expr: expr , root: root , path: path } , { var_changed? , context } ->
234238 actual = of_pattern_tree ( root , context )
235239
236240 case of_pattern_var ( path , actual , context ) do
237- { :ok , type } ->
241+ { :ok , new_type } ->
238242 # Optimization: if current type is already a subtype, there is nothing to refine.
239- if current_type != term ( ) and subtype? ( current_type , type ) do
243+ if old_type != term ( ) and subtype? ( old_type , new_type ) do
240244 { var_changed? , context }
241245 else
242- case Of . refine_head_var ( var , type , expr , stack , context ) do
246+ case Of . refine_head_var ( var , new_type , expr , stack , context ) do
243247 { :ok , _type , context } ->
244248 { true , context }
245249
246- { :error , _ , context } ->
247- throw ( badvar_error ( var , current_type , type , expr , stack , context ) )
250+ { :error , _old_type , error_context } ->
251+ if match_error? ( var , new_type ) do
252+ throw ( badmatch_error ( var , expr , stack , context ) )
253+ else
254+ throw ( badvar_error ( var , old_type , new_type , stack , error_context ) )
255+ end
248256 end
249257 end
250258
251259 :error ->
252- throw ( badmatch_error ( expr , stack , Of . error_var ( var , context ) ) )
260+ throw ( badmatch_error ( var , expr , stack , context ) )
253261 end
254262 end )
255263 catch
@@ -271,18 +279,16 @@ defmodule Module.Types.Pattern do
271279 context
272280 end
273281
274- defp badmatch_error ( expr , stack , context ) do
282+ defp match_error? ( { :match , _ , __MODULE__ } , _type ) , do: true
283+ defp match_error? ( _var , type ) , do: empty? ( type )
284+
285+ defp badmatch_error ( var , expr , stack , context ) do
286+ context = Of . error_var ( var , context )
275287 error ( __MODULE__ , { :badmatch , expr , context } , error_meta ( expr , stack ) , stack , context )
276288 end
277289
278- defp badvar_error ( { var_name , _ , var_context } = var , old_type , new_type , expr , stack , context ) do
279- error =
280- if var_name == :match and var_context == __MODULE__ do
281- { :badmatch , expr , context }
282- else
283- { :badvar , old_type , new_type , var , context }
284- end
285-
290+ defp badvar_error ( var , old_type , new_type , stack , context ) do
291+ error = { :badvar , old_type , new_type , var , context }
286292 error ( __MODULE__ , error , error_meta ( var , stack ) , stack , context )
287293 end
288294
@@ -404,8 +410,8 @@ defmodule Module.Types.Pattern do
404410 { :ok , type , context } ->
405411 { type , context }
406412
407- { :error , old_type , context } ->
408- { error_type ( ) , badvar_error ( var , old_type , expected , expr , stack , context ) }
413+ { :error , old_type , error_context } ->
414+ { error_type ( ) , badvar_error ( var , old_type , expected , stack , error_context ) }
409415 end
410416 end
411417
@@ -838,7 +844,7 @@ defmodule Module.Types.Pattern do
838844 message:
839845 IO . iodata_to_binary ( [
840846 """
841- incompatible types in expression :
847+ this match will never succeed due to incompatible types :
842848
843849 #{ expr_to_string ( expr ) |> indent ( 4 ) }
844850 """ ,
0 commit comments