@@ -30,19 +30,40 @@ defmodule Module.Types.Of do
3030
3131 @ doc """
3232 Marks a variable with error.
33+
34+ This purposedly deletes all traces of the variable,
35+ as it is often invoked when the cause for error is elsewhere.
36+ """
37+ def error_var ( { _var_name , meta , _var_context } , context ) do
38+ version = Keyword . fetch! ( meta , :version )
39+
40+ update_in ( context . vars [ version ] , fn
41+ % { errored: true } = data -> data
42+ data -> Map . put ( % { data | type: error_type ( ) , off_traces: [ ] } , :errored , true )
43+ end )
44+ end
45+
46+ @ doc """
47+ Declares a variable.
3348 """
34- def error_var ( var , context ) do
49+ def declare_var ( var , context ) do
3550 { var_name , meta , var_context } = var
3651 version = Keyword . fetch! ( meta , :version )
3752
38- data = % {
39- type: error_type ( ) ,
40- name: var_name ,
41- context: var_context ,
42- off_traces: [ ]
43- }
53+ case context . vars do
54+ % { ^ version => _ } ->
55+ context
56+
57+ vars ->
58+ data = % {
59+ type: term ( ) ,
60+ name: var_name ,
61+ context: var_context ,
62+ off_traces: [ ]
63+ }
4464
45- put_in ( context . vars [ version ] , data )
65+ % { context | vars: Map . put ( vars , version , data ) }
66+ end
4667 end
4768
4869 @ doc """
@@ -56,7 +77,7 @@ defmodule Module.Types.Of do
5677 version = Keyword . fetch! ( meta , :version )
5778 % { vars: % { ^ version => % { type: old_type , off_traces: off_traces } = data } = vars } = context
5879
59- if gradual? ( old_type ) and type not in [ term ( ) , dynamic ( ) ] do
80+ if gradual? ( old_type ) and type not in [ term ( ) , dynamic ( ) ] and not is_map_key ( data , :errored ) do
6081 case compatible_intersection ( old_type , type ) do
6182 { :ok , new_type } when new_type != old_type ->
6283 data = % {
@@ -82,11 +103,13 @@ defmodule Module.Types.Of do
82103 because we want to refine types. Otherwise we should
83104 use compatibility.
84105 """
85- def refine_head_var ( var , type , expr , stack , context ) do
86- { var_name , meta , var_context } = var
106+ def refine_head_var ( { _ , meta , _ } , type , expr , stack , context ) do
87107 version = Keyword . fetch! ( meta , :version )
88108
89109 case context . vars do
110+ % { ^ version => % { errored: true } } ->
111+ { :ok , error_type ( ) , context }
112+
90113 % { ^ version => % { type: old_type , off_traces: off_traces } = data } = vars ->
91114 new_type = intersection ( type , old_type )
92115
@@ -96,26 +119,14 @@ defmodule Module.Types.Of do
96119 off_traces: new_trace ( expr , type , stack , off_traces )
97120 }
98121
99- context = % { context | vars: % { vars | version => data } }
100-
101- # We need to return error otherwise it leads to cascading errors
102122 if empty? ( new_type ) do
103- { :error , error_type ( ) ,
104- error ( { :refine_head_var , old_type , type , var , context } , meta , stack , context ) }
123+ data = Map . put ( % { data | type: error_type ( ) } , :errored , true )
124+ context = % { context | vars: % { vars | version => data } }
125+ { :error , old_type , context }
105126 else
127+ context = % { context | vars: % { vars | version => data } }
106128 { :ok , new_type , context }
107129 end
108-
109- % { } = vars ->
110- data = % {
111- type: type ,
112- name: var_name ,
113- context: var_context ,
114- off_traces: new_trace ( expr , type , stack , [ ] )
115- }
116-
117- context = % { context | vars: Map . put ( vars , version , data ) }
118- { :ok , type , context }
119130 end
120131 end
121132
@@ -546,23 +557,6 @@ defmodule Module.Types.Of do
546557 error ( __MODULE__ , warning , meta , stack , context )
547558 end
548559
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-
566560 def format_diagnostic ( { :badbinary , kind , meta , expr , expected_type , actual_type , context } ) do
567561 type = if kind == :match , do: "matching" , else: "construction"
568562 hints = if meta [ :inferred_bitstring_spec ] , do: [ :inferred_bitstring_spec ] , else: [ ]
0 commit comments