11defmodule Module.Types do
22 @ moduledoc false
33
4- alias Module.Types . { Expr , Pattern }
4+ alias Module.Types . { Descr , Expr , Pattern }
5+
6+ @ doc false
7+ def infer ( module , file , defs , env ) do
8+ context = context ( )
9+
10+ for { { fun , arity } , :def , _meta , clauses } <- defs , into: % { } do
11+ stack = stack ( :infer , file , module , { fun , arity } , :all , env )
12+ expected = List . duplicate ( Descr . dynamic ( ) , arity )
13+
14+ pair_types =
15+ Enum . map ( clauses , fn { meta , args , guards , body } ->
16+ try do
17+ { args , context } =
18+ Pattern . of_head ( args , guards , expected , :default , meta , stack , context )
19+
20+ { return , _context } = Expr . of_expr ( body , stack , context )
21+ { args , return }
22+ rescue
23+ e -> internal_error! ( e , __STACKTRACE__ , :def , meta , module , fun , args , guards , body )
24+ end
25+ end )
26+
27+ # TODO: Reuse context from patterns and guards
28+ # TODO: Simplify pair types
29+ # TODO: Handle local calls
30+ { { fun , arity } , { :infer , pair_types } }
31+ end
32+ end
533
634 @ doc false
735 def warnings ( module , file , defs , no_warn_undefined , cache ) do
836 context = context ( )
937
10- Enum . flat_map ( defs , fn { { fun , arity } = function , kind , meta , clauses } ->
11- stack =
12- stack ( :dynamic , with_file_meta ( meta , file ) , module , function , no_warn_undefined , cache )
38+ Enum . flat_map ( defs , fn { { fun , arity } , kind , meta , clauses } ->
39+ file = with_file_meta ( meta , file )
40+ stack = stack ( :dynamic , file , module , { fun , arity } , no_warn_undefined , cache )
41+ expected = List . duplicate ( Descr . dynamic ( ) , arity )
1342
1443 Enum . flat_map ( clauses , fn { meta , args , guards , body } ->
1544 try do
16- warnings_from_clause ( meta , args , guards , body , stack , context )
45+ { _types , context } =
46+ Pattern . of_head ( args , guards , expected , :default , meta , stack , context )
47+
48+ { _type , context } = Expr . of_expr ( body , stack , context )
49+ context . warnings
1750 rescue
1851 e ->
19- def_expr = { kind , meta , [ guards_to_expr ( guards , { fun , [ ] , args } ) , [ do: body ] ] }
20-
21- error =
22- RuntimeError . exception ( """
23- found error while checking types for #{ Exception . format_mfa ( module , fun , arity ) } :
24-
25- #{ Exception . format_banner ( :error , e , __STACKTRACE__ ) } \
26-
27- The exception happened while checking this code:
28-
29- #{ Macro . to_string ( def_expr ) }
30-
31- Please report this bug at: https://github.com/elixir-lang/elixir/issues
32- """ )
33-
34- reraise error , __STACKTRACE__
52+ internal_error! ( e , __STACKTRACE__ , kind , meta , module , fun , args , guards , body )
3553 end
3654 end )
3755 end )
@@ -44,6 +62,25 @@ defmodule Module.Types do
4462 end
4563 end
4664
65+ defp internal_error! ( e , stack , kind , meta , module , fun , args , guards , body ) do
66+ def_expr = { kind , meta , [ guards_to_expr ( guards , { fun , [ ] , args } ) , [ do: body ] ] }
67+
68+ exception =
69+ RuntimeError . exception ( """
70+ found error while checking types for #{ Exception . format_mfa ( module , fun , length ( args ) ) } :
71+
72+ #{ Exception . format_banner ( :error , e , stack ) } \
73+
74+ The exception happened while checking this code:
75+
76+ #{ Macro . to_string ( def_expr ) }
77+
78+ Please report this bug at: https://github.com/elixir-lang/elixir/issues
79+ """ )
80+
81+ reraise exception , stack
82+ end
83+
4784 defp guards_to_expr ( [ ] , left ) do
4885 left
4986 end
@@ -52,14 +89,6 @@ defmodule Module.Types do
5289 guards_to_expr ( guards , { :when , [ ] , [ left , guard ] } )
5390 end
5491
55- defp warnings_from_clause ( meta , args , guards , body , stack , context ) do
56- dynamic = Module.Types.Descr . dynamic ( )
57- expected = Enum . map ( args , fn _ -> dynamic end )
58- { _types , context } = Pattern . of_head ( args , guards , expected , :default , meta , stack , context )
59- { _type , context } = Expr . of_expr ( body , stack , context )
60- context . warnings
61- end
62-
6392 @ doc false
6493 def stack ( mode , file , module , function , no_warn_undefined , cache )
6594 when mode in [ :static , :dynamic , :infer ] do
@@ -72,9 +101,9 @@ defmodule Module.Types do
72101 module: module ,
73102 # Current function
74103 function: function ,
75- # List of calls to not warn on as undefined
104+ # List of calls to not warn on as undefined or :all
76105 no_warn_undefined: no_warn_undefined ,
77- # A list of cached modules received from the parallel compiler
106+ # A tuple with cache information or a Macro.Env struct indicating no remote traversals
78107 cache: cache ,
79108 # The mode controls what happens on function application when
80109 # there are gradual arguments. Non-gradual arguments always
0 commit comments