@@ -217,43 +217,45 @@ defmodule Module.Types.Pattern do
217217 ## GUARDS
218218
219219 # TODO: Some guards can be changed to intersection types or higher order types
220+ @ boolean { :union , [ { :atom , true } , { :atom , false } ] }
221+ @ number { :union , [ :integer , :float ] }
220222
221223 @ guard_functions % {
222- { :is_atom , 1 } => { [ :atom ] , : boolean} ,
223- { :is_binary , 1 } => { [ :binary ] , : boolean} ,
224- { :is_bitstring , 1 } => { [ :binary ] , : boolean} ,
225- { :is_boolean , 1 } => { [ : boolean] , : boolean} ,
226- { :is_float , 1 } => { [ :float ] , : boolean} ,
227- { :is_function , 1 } => { [ :fun ] , : boolean} ,
228- { :is_function , 2 } => { [ :fun , :integer ] , : boolean} ,
229- { :is_integer , 1 } => { [ :integer ] , : boolean} ,
230- { :is_list , 1 } => { [ { :list , :dynamic } ] , : boolean} ,
231- { :is_map , 1 } => { [ { :map , [ { :optional , :dynamic , :dynamic } ] } ] , : boolean} ,
224+ { :is_atom , 1 } => { [ :atom ] , @ boolean } ,
225+ { :is_binary , 1 } => { [ :binary ] , @ boolean } ,
226+ { :is_bitstring , 1 } => { [ :binary ] , @ boolean } ,
227+ { :is_boolean , 1 } => { [ @ boolean ] , @ boolean } ,
228+ { :is_float , 1 } => { [ :float ] , @ boolean } ,
229+ { :is_function , 1 } => { [ :fun ] , @ boolean } ,
230+ { :is_function , 2 } => { [ :fun , :integer ] , @ boolean } ,
231+ { :is_integer , 1 } => { [ :integer ] , @ boolean } ,
232+ { :is_list , 1 } => { [ { :list , :dynamic } ] , @ boolean } ,
233+ { :is_map , 1 } => { [ { :map , [ { :optional , :dynamic , :dynamic } ] } ] , @ boolean } ,
232234 { :is_map_key , 2 } => { [ :dynamic , { :map , [ { :optional , :dynamic , :dynamic } ] } ] , :dynamic } ,
233- { :is_number , 1 } => { [ : number] , : boolean} ,
234- { :is_pid , 1 } => { [ :pid ] , : boolean} ,
235- { :is_port , 1 } => { [ :port ] , : boolean} ,
236- { :is_reference , 1 } => { [ :reference ] , : boolean} ,
237- { :is_tuple , 1 } => { [ :tuple ] , : boolean} ,
238- { :< , 2 } => { [ :dynamic , :dynamic ] , : boolean} ,
239- { :"=<" , 2 } => { [ :dynamic , :dynamic ] , : boolean} ,
240- { :> , 2 } => { [ :dynamic , :dynamic ] , : boolean} ,
241- { :>= , 2 } => { [ :dynamic , :dynamic ] , : boolean} ,
242- { :"/=" , 2 } => { [ :dynamic , :dynamic ] , : boolean} ,
243- { :"=/=" , 2 } => { [ :dynamic , :dynamic ] , : boolean} ,
244- { :== , 2 } => { [ :dynamic , :dynamic ] , : boolean} ,
245- { :"=:=" , 2 } => { [ :dynamic , :dynamic ] , : boolean} ,
246- { :* , 2 } => { [ : number, : number] , : number} ,
247- { :+ , 1 } => { [ : number] , : number} ,
248- { :+ , 2 } => { [ : number, : number] , : number} ,
249- { :- , 1 } => { [ : number] , : number} ,
250- { :- , 2 } => { [ : number, : number] , : number} ,
251- { :/ , 2 } => { [ : number, : number] , : number} ,
252- { :abs , 1 } => { [ : number] , : number} ,
253- { :ceil , 1 } => { [ : number] , :integer } ,
254- { :floor , 1 } => { [ : number] , :integer } ,
255- { :round , 1 } => { [ : number] , :integer } ,
256- { :trunc , 1 } => { [ : number] , :integer } ,
235+ { :is_number , 1 } => { [ @ number ] , @ boolean } ,
236+ { :is_pid , 1 } => { [ :pid ] , @ boolean } ,
237+ { :is_port , 1 } => { [ :port ] , @ boolean } ,
238+ { :is_reference , 1 } => { [ :reference ] , @ boolean } ,
239+ { :is_tuple , 1 } => { [ :tuple ] , @ boolean } ,
240+ { :< , 2 } => { [ :dynamic , :dynamic ] , @ boolean } ,
241+ { :"=<" , 2 } => { [ :dynamic , :dynamic ] , @ boolean } ,
242+ { :> , 2 } => { [ :dynamic , :dynamic ] , @ boolean } ,
243+ { :>= , 2 } => { [ :dynamic , :dynamic ] , @ boolean } ,
244+ { :"/=" , 2 } => { [ :dynamic , :dynamic ] , @ boolean } ,
245+ { :"=/=" , 2 } => { [ :dynamic , :dynamic ] , @ boolean } ,
246+ { :== , 2 } => { [ :dynamic , :dynamic ] , @ boolean } ,
247+ { :"=:=" , 2 } => { [ :dynamic , :dynamic ] , @ boolean } ,
248+ { :* , 2 } => { [ @ number , @ number ] , @ number } ,
249+ { :+ , 1 } => { [ @ number ] , @ number } ,
250+ { :+ , 2 } => { [ @ number , @ number ] , @ number } ,
251+ { :- , 1 } => { [ @ number ] , @ number } ,
252+ { :- , 2 } => { [ @ number , @ number ] , @ number } ,
253+ { :/ , 2 } => { [ @ number , @ number ] , @ number } ,
254+ { :abs , 1 } => { [ @ number ] , @ number } ,
255+ { :ceil , 1 } => { [ @ number ] , :integer } ,
256+ { :floor , 1 } => { [ @ number ] , :integer } ,
257+ { :round , 1 } => { [ @ number ] , :integer } ,
258+ { :trunc , 1 } => { [ @ number ] , :integer } ,
257259 { :element , 2 } => { [ :integer , :tuple ] , :dynamic } ,
258260 { :hd , 1 } => { [ { :list , :dynamic } ] , :dynamic } ,
259261 { :length , 1 } => { [ { :list , :dynamic } ] , :integer } ,
@@ -265,7 +267,7 @@ defmodule Module.Types.Pattern do
265267 { :binary_part , 3 } => { [ :binary , :integer , :integer ] , :binary } ,
266268 { :bit_size , 1 } => { [ :binary ] , :integer } ,
267269 { :byte_size , 1 } => { [ :binary ] , :integer } ,
268- { :size , 1 } => { [ { :union , [ :binary , :tuple ] } ] , : boolean} ,
270+ { :size , 1 } => { [ { :union , [ :binary , :tuple ] } ] , @ boolean } ,
269271 { :div , 2 } => { [ :integer , :integer ] , :integer } ,
270272 { :rem , 2 } => { [ :integer , :integer ] , :integer } ,
271273 { :node , 0 } => { [ ] , :atom } ,
@@ -276,15 +278,15 @@ defmodule Module.Types.Pattern do
276278 { :bxor , 2 } => { [ :integer , :integer ] , :integer } ,
277279 { :bsl , 2 } => { [ :integer , :integer ] , :integer } ,
278280 { :bsr , 2 } => { [ :integer , :integer ] , :integer } ,
279- { :or , 2 } => { [ : boolean, : boolean] , : boolean} ,
280- { :and , 2 } => { [ : boolean, : boolean] , : boolean} ,
281- { :xor , 2 } => { [ : boolean, : boolean] , : boolean} ,
282- { :not , 1 } => { [ : boolean] , : boolean}
281+ { :or , 2 } => { [ @ boolean , @ boolean ] , @ boolean } ,
282+ { :and , 2 } => { [ @ boolean , @ boolean ] , @ boolean } ,
283+ { :xor , 2 } => { [ @ boolean , @ boolean ] , @ boolean } ,
284+ { :not , 1 } => { [ @ boolean ] , @ boolean }
283285
284286 # Following guards are matched explicitly to handle
285287 # type guard functions such as is_atom/1
286- # {:andalso, 2} => {[: boolean, : boolean], : boolean}
287- # {:orelse, 2} => {[: boolean, : boolean], : boolean}
288+ # {:andalso, 2} => {[@ boolean, @ boolean], @ boolean}
289+ # {:orelse, 2} => {[@ boolean, @ boolean], @ boolean}
288290 }
289291
290292 @ type_guards [
@@ -320,9 +322,9 @@ defmodule Module.Types.Pattern do
320322 with { :ok , left_type , left_context } <- of_guard ( left , stack , fresh_context ) ,
321323 { :ok , right_type , right_context } <- of_guard ( right , stack , fresh_context ) ,
322324 { :ok , context } <- merge_context_and ( context , stack , left_context , right_context ) ,
323- { :ok , _ , context } <- unify ( left_type , : boolean, stack , context ) ,
324- { :ok , _ , context } <- unify ( right_type , : boolean, stack , context ) ,
325- do: { :ok , : boolean, context }
325+ { :ok , _ , context } <- unify ( left_type , @ boolean , stack , context ) ,
326+ { :ok , _ , context } <- unify ( right_type , @ boolean , stack , context ) ,
327+ do: { :ok , @ boolean , context }
326328 end
327329
328330 def of_guard ( { { :. , _ , [ :erlang , :orelse ] } , _ , [ left , right ] } = expr , stack , context ) do
@@ -332,8 +334,8 @@ defmodule Module.Types.Pattern do
332334 with { :ok , left_type , left_context } <- of_guard ( left , stack , fresh_context ) ,
333335 { :ok , _right_type , right_context } <- of_guard ( right , stack , fresh_context ) ,
334336 { :ok , context } <- merge_context_or ( context , stack , left_context , right_context ) ,
335- { :ok , _ , context } <- unify ( left_type , : boolean, stack , context ) ,
336- do: { :ok , : boolean, context }
337+ { :ok , _ , context } <- unify ( left_type , @ boolean , stack , context ) ,
338+ do: { :ok , @ boolean , context }
337339 end
338340
339341 # The unary operators + and - are special cased to avoid common warnings until
0 commit comments