|
| 1 | +parent = self() |
| 2 | +{:ok, checker} = Module.ParallelChecker.start_link() |
| 3 | + |
| 4 | +{time, modules} = |
| 5 | + :timer.tc(fn -> |
| 6 | + [_ | _] = paths = Path.wildcard(Path.join(__DIR__, "../ebin/Elixir.*.beam")) |
| 7 | + |
| 8 | + paths |
| 9 | + |> Task.async_stream( |
| 10 | + fn path -> |
| 11 | + path = Path.expand(path) |
| 12 | + Module.ParallelChecker.put(parent, checker) |
| 13 | + cache = Module.ParallelChecker.get() |
| 14 | + binary = File.read!(path) |
| 15 | + |
| 16 | + {:ok, {_, [{:debug_info, debug_info}, {_, checker_blob}]}} = |
| 17 | + :beam_lib.chunks(binary, [:debug_info, ~c"ExCk"]) |
| 18 | + |
| 19 | + {:debug_info_v1, _backend, {:elixir_v1, module_map, _specs}} = debug_info |
| 20 | + |
| 21 | + %{module: module, file: file, attributes: attributes, definitions: definitions} = |
| 22 | + module_map |
| 23 | + |
| 24 | + {_, checker} = :erlang.binary_to_term(checker_blob) |
| 25 | + env = :elixir_env.new() |
| 26 | + |
| 27 | + # We assume that all private functions have been invoked at this point |
| 28 | + private = |
| 29 | + for {fun_arity, kind, _, _} <- definitions, kind in [:defp, :defmacrop], do: fun_arity |
| 30 | + |
| 31 | + {signatures, _} = |
| 32 | + Module.Types.infer(module, file, attributes, definitions, private, env, cache) |
| 33 | + |
| 34 | + checker = |
| 35 | + update_in(checker.exports, fn exports -> |
| 36 | + for {fun, info} <- exports do |
| 37 | + {fun, %{info | sig: Map.get(signatures, fun, info.sig)}} |
| 38 | + end |
| 39 | + end) |
| 40 | + |
| 41 | + [{"ExCk", checker_chunk}] = :elixir_erl.checker_chunk(checker, []) |
| 42 | + {:ok, ^module, chunks} = :beam_lib.all_chunks(binary) |
| 43 | + |
| 44 | + {:ok, new_binary} = |
| 45 | + chunks |
| 46 | + |> List.keyreplace(~c"ExCk", 0, {~c"ExCk", checker_chunk}) |
| 47 | + |> :beam_lib.build_module() |
| 48 | + |
| 49 | + File.write!(path, new_binary) |
| 50 | + {module, path} |
| 51 | + end, |
| 52 | + timeout: :infinity |
| 53 | + ) |
| 54 | + |> Enum.map(fn {:ok, result} -> result end) |
| 55 | + end) |
| 56 | + |
| 57 | +IO.puts(:stderr, ["Type inferred stdlib in ", Integer.to_string(div(time, 1000)), "ms"]) |
| 58 | + |
| 59 | +{time, _} = |
| 60 | + :timer.tc(fn -> |
| 61 | + Module.ParallelChecker.verify(checker, modules) |
| 62 | + end) |
| 63 | + |
| 64 | +IO.puts(:stderr, ["Type checked stdlib in ", Integer.to_string(div(time, 1000)), "ms"]) |
0 commit comments