@@ -321,15 +321,24 @@ defmodule Module.Types.Of do
321321
322322 for { mod , fun , clauses } <- [
323323 { :erlang , :binary_to_integer , [ { [ binary ( ) ] , integer ( ) } ] } ,
324- { :erlang , :integer_to_binary , [ { [ integer ( ) ] , binary ( ) } ] }
324+ { :erlang , :integer_to_binary , [ { [ integer ( ) ] , binary ( ) } ] } ,
325+
326+ # TODO: Replace term()/dynamic() by parametric types
327+ { :erlang , :hd , [ { [ non_empty_list ( term ( ) , term ( ) ) ] , dynamic ( ) } ] } ,
328+ { :erlang , :tl , [ { [ non_empty_list ( term ( ) , term ( ) ) ] , dynamic ( ) } ] } ,
329+ { :erlang , :delete_element ,
330+ [ { [ integer ( ) , open_tuple ( [ ] , term ( ) ) ] , dynamic ( open_tuple ( [ ] , term ( ) ) ) } ] } ,
331+ { :erlang , :element , [ { [ integer ( ) , open_tuple ( [ ] , term ( ) ) ] , dynamic ( ) } ] } ,
332+ { :erlang , :insert_element ,
333+ [ { [ integer ( ) , open_tuple ( [ ] , term ( ) ) , term ( ) ] , dynamic ( open_tuple ( [ ] , term ( ) ) ) } ] }
325334 ] do
326335 [ { args , _return } | _others ] = clauses
327336
328- defp strong_remote ( unquote ( mod ) , unquote ( fun ) , unquote ( length ( args ) ) ) ,
337+ defp remote ( unquote ( mod ) , unquote ( fun ) , unquote ( length ( args ) ) ) ,
329338 do: unquote ( Macro . escape ( clauses ) )
330339 end
331340
332- defp strong_remote ( _mod , _fun , _arity ) , do: [ ]
341+ defp remote ( _mod , _fun , _arity ) , do: [ ]
333342
334343 @ doc """
335344 Checks a module is a valid remote.
@@ -353,7 +362,7 @@ defmodule Module.Types.Of do
353362 if Keyword . get ( meta , :runtime_module , false ) do
354363 { :none , context }
355364 else
356- case strong_remote ( module , fun , arity ) do
365+ case remote ( module , fun , arity ) do
357366 [ ] -> { :none , check_export ( module , fun , arity , meta , stack , context ) }
358367 clauses -> { { :strong , clauses } , context }
359368 end
@@ -368,6 +377,9 @@ defmodule Module.Types.Of do
368377 { _optional? , value_type } ->
369378 { value_type , context }
370379
380+ :badtuple ->
381+ { error_type ( ) , badapply_error ( expr , [ integer ( ) , tuple ] , stack , context ) }
382+
371383 reason ->
372384 { error_type ( ) , error ( { reason , expr , tuple , index - 1 , context } , meta , stack , context ) }
373385 end
@@ -386,6 +398,9 @@ defmodule Module.Types.Of do
386398 value_type when is_descr ( value_type ) ->
387399 { value_type , context }
388400
401+ :badtuple ->
402+ { error_type ( ) , badapply_error ( expr , [ integer ( ) , tuple , value ] , stack , context ) }
403+
389404 reason ->
390405 { error_type ( ) , error ( { reason , expr , tuple , index - 2 , context } , meta , stack , context ) }
391406 end
@@ -397,6 +412,9 @@ defmodule Module.Types.Of do
397412 value_type when is_descr ( value_type ) ->
398413 { value_type , context }
399414
415+ :badtuple ->
416+ { error_type ( ) , badapply_error ( expr , [ integer ( ) , tuple ] , stack , context ) }
417+
400418 reason ->
401419 { error_type ( ) , error ( { reason , expr , tuple , index - 1 , context } , meta , stack , context ) }
402420 end
@@ -412,8 +430,8 @@ defmodule Module.Types.Of do
412430 { _ , value_type } ->
413431 { value_type , context }
414432
415- reason ->
416- { error_type ( ) , error ( { reason , expr , list , context } , elem ( expr , 1 ) , stack , context ) }
433+ :badnonemptylist ->
434+ { error_type ( ) , badapply_error ( expr , [ list ] , stack , context ) }
417435 end
418436 end
419437
@@ -422,8 +440,8 @@ defmodule Module.Types.Of do
422440 { _ , value_type } ->
423441 { value_type , context }
424442
425- reason ->
426- { error_type ( ) , error ( { reason , expr , list , context } , elem ( expr , 1 ) , stack , context ) }
443+ :badnonemptylist ->
444+ { error_type ( ) , badapply_error ( expr , [ list ] , stack , context ) }
427445 end
428446 end
429447
@@ -705,48 +723,6 @@ defmodule Module.Types.Of do
705723 }
706724 end
707725
708- def format_diagnostic ( { :badnonemptylist , expr , type , context } ) do
709- traces = collect_traces ( expr , context )
710-
711- % {
712- details: % { typing_traces: traces } ,
713- message:
714- IO . iodata_to_binary ( [
715- """
716- expected a non-empty list in #{ format_mfa ( expr ) } :
717-
718- #{ expr_to_string ( expr ) |> indent ( 4 ) }
719-
720- but got type:
721-
722- #{ to_quoted_string ( type ) |> indent ( 4 ) }
723- """ ,
724- format_traces ( traces )
725- ] )
726- }
727- end
728-
729- def format_diagnostic ( { :badtuple , expr , type , _index , context } ) do
730- traces = collect_traces ( expr , context )
731-
732- % {
733- details: % { typing_traces: traces } ,
734- message:
735- IO . iodata_to_binary ( [
736- """
737- expected a tuple in #{ format_mfa ( expr ) } :
738-
739- #{ expr_to_string ( expr ) |> indent ( 4 ) }
740-
741- but got type:
742-
743- #{ to_quoted_string ( type ) |> indent ( 4 ) }
744- """ ,
745- format_traces ( traces )
746- ] )
747- }
748- end
749-
750726 def format_diagnostic ( { :badindex , expr , type , index , context } ) do
751727 traces = collect_traces ( expr , context )
752728
@@ -794,23 +770,24 @@ defmodule Module.Types.Of do
794770
795771 def format_diagnostic ( { :badapply , expr , args_types , clauses , context } ) do
796772 traces = collect_traces ( expr , context )
773+ { { :. , _ , [ mod , fun ] } , _ , args } = expr
797774
798775 % {
799776 details: % { typing_traces: traces } ,
800777 message:
801778 IO . iodata_to_binary ( [
802779 """
803- incompatible types given to #{ format_mfa ( expr ) } :
780+ incompatible types given to #{ format_mfa ( mod , fun , args ) } :
804781
805782 #{ expr_to_string ( expr ) |> indent ( 4 ) }
806783
807784 expected types:
808785
809- #{ clauses_args_to_quoted_string ( clauses ) |> indent ( 4 ) }
786+ #{ clauses_args_to_quoted_string ( mod , fun , clauses ) |> indent ( 4 ) }
810787
811788 but got types:
812789
813- #{ args_to_quoted_string ( args_types ) |> indent ( 4 ) }
790+ #{ args_to_quoted_string ( mod , fun , args_types ) |> indent ( 4 ) }
814791 """ ,
815792 format_traces ( traces )
816793 ] )
@@ -936,15 +913,22 @@ defmodule Module.Types.Of do
936913 match? ( { { :. , _ , [ var , _fun ] } , _ , _args } when is_var ( var ) , expr )
937914 end
938915
939- defp clauses_args_to_quoted_string ( [ { args , _return } ] ) do
940- args_to_quoted_string ( args )
916+ defp badapply_error ( { { :. , _ , [ mod , fun ] } , meta , _ } = expr , args_types , stack , context ) do
917+ clauses = remote ( mod , fun , length ( args_types ) )
918+ error ( { :badapply , expr , args_types , clauses , context } , meta , stack , context )
919+ end
920+
921+ defp clauses_args_to_quoted_string ( mod , fun , [ { args , _return } ] ) do
922+ args_to_quoted_string ( mod , fun , args )
941923 end
942924
943- defp args_to_quoted_string ( [ arg ] ) do
925+ defp args_to_quoted_string ( _mod , _fun , [ arg ] ) do
944926 to_quoted_string ( arg )
945927 end
946928
947- defp args_to_quoted_string ( args ) do
929+ defp args_to_quoted_string ( mod , fun , args ) do
930+ { _mod , _fun , args } = :elixir_rewrite . erl_to_ex ( mod , fun , args )
931+
948932 { :_ , [ ] , Enum . map ( args , & to_quoted / 1 ) }
949933 |> Code.Formatter . to_algebra ( )
950934 |> Inspect.Algebra . format ( 98 )
@@ -960,6 +944,10 @@ defmodule Module.Types.Of do
960944 end
961945
962946 defp format_mfa ( { { :. , _ , [ mod , fun ] } , _ , args } ) do
947+ format_mfa ( mod , fun , args )
948+ end
949+
950+ defp format_mfa ( mod , fun , args ) do
963951 { mod , fun , args } = :elixir_rewrite . erl_to_ex ( mod , fun , args )
964952 Exception . format_mfa ( mod , fun , length ( args ) )
965953 end
0 commit comments