Skip to content

Commit ba4664d

Browse files
committed
Start moving unreachable checks to types
1 parent 453a435 commit ba4664d

File tree

10 files changed

+40
-41
lines changed

10 files changed

+40
-41
lines changed

lib/elixir/lib/code.ex

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,6 @@ defmodule Code do
249249
:debug_info,
250250
:ignore_already_consolidated,
251251
:ignore_module_conflict,
252-
:infer_signatures,
253252
:relative_paths
254253
]
255254

@@ -1562,8 +1561,8 @@ defmodule Code do
15621561
15631562
## Examples
15641563
1565-
Code.compiler_options(infer_signatures: false)
1566-
#=> %{infer_signatures: true}
1564+
Code.compiler_options(ignore_module_conflict: true)
1565+
#=> %{ignore_module_conflict: false}
15671566
15681567
"""
15691568
@spec compiler_options(Enumerable.t({atom, term})) :: %{optional(atom) => term}
@@ -1647,15 +1646,6 @@ defmodule Code do
16471646
* `:ignore_module_conflict` - when `true`, does not warn when a module has
16481647
already been defined. Defaults to `false`.
16491648
1650-
* `:infer_signatures` (since v1.18.0) - when `false`, it disables module-local
1651-
signature inference used when type checking remote calls to the compiled
1652-
module. Type checking will be executed regardless of this value of this option.
1653-
Defaults to `true`.
1654-
1655-
`mix test` automatically disables this option via the `:test_elixirc_options`
1656-
project configuration, as there is typically no need to store infer signatures
1657-
for test files.
1658-
16591649
* `:relative_paths` - when `true`, uses relative paths in quoted nodes,
16601650
warnings, and errors generated by the compiler. Note disabling this option
16611651
won't affect runtime warnings and errors. Defaults to `true`.

lib/elixir/lib/module/parallel_checker.ex

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,10 @@ defmodule Module.ParallelChecker do
4747
@doc """
4848
Spawns a process that runs the parallel checker.
4949
"""
50-
def spawn(pid_checker, module_map, log?, infer_types?, env) do
50+
def spawn(pid_checker, module_map, log?, env) do
5151
%{module: module, definitions: definitions, file: file} = module_map
52-
53-
module_map =
54-
if infer_types? do
55-
%{module_map | signatures: Module.Types.infer(module, file, definitions, env)}
56-
else
57-
module_map
58-
end
52+
{signatures, unreachable} = Module.Types.infer(module, file, definitions, env)
53+
module_map = %{module_map | signatures: signatures, unreachable: unreachable}
5954

6055
with {pid, checker} <- pid_checker do
6156
ets = :gen_server.call(checker, :ets, :infinity)

lib/elixir/lib/module/types.ex

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,27 @@ defmodule Module.Types do
1616
stack = stack(:infer, file, module, {:__info__, 1}, :all, env, handler)
1717
context = context(%{})
1818

19-
{types, _context} =
19+
{types, %{local_sigs: local_sigs}} =
2020
for {fun_arity, kind, _meta, _clauses} = def <- defs,
21-
kind == :def and fun_arity not in @no_infer,
21+
kind == :def or kind == :defmacro,
2222
reduce: {[], context} do
2323
{types, context} ->
2424
{_kind, inferred, context} = local_handler(fun_arity, stack, context, fn _ -> def end)
25-
{[{fun_arity, inferred} | types], context}
25+
26+
if kind == :def and fun_arity not in @no_infer do
27+
{[{fun_arity, inferred} | types], context}
28+
else
29+
{types, context}
30+
end
2631
end
2732

28-
Map.new(types)
33+
unreachable =
34+
for {fun_arity, kind, meta, _clauses} <- defs,
35+
kind == :defp or kind == :defmacrop,
36+
not is_map_key(local_sigs, fun_arity),
37+
do: {fun_arity, meta}
38+
39+
{Map.new(types), unreachable}
2940
end
3041

3142
@doc false

lib/elixir/src/elixir.erl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ start(_Type, _Args) ->
8888

8989
%% Compiler options
9090
{docs, true},
91-
{infer_signatures, true},
9291
{ignore_already_consolidated, false},
9392
{ignore_module_conflict, false},
9493
{on_undefined_variable, raise},

lib/elixir/src/elixir_compiler.erl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ bootstrap() ->
144144
elixir_config:static(#{bootstrap => true}),
145145
elixir_config:put(docs, false),
146146
elixir_config:put(ignore_module_conflict, true),
147-
elixir_config:put(infer_signatures, false),
148147
elixir_config:put(on_undefined_variable, raise),
149148
elixir_config:put(parser_options, []),
150149
elixir_config:put(relative_paths, false),

lib/elixir/src/elixir_def.erl

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,11 @@ fun_for(Meta, Module, Name, Arity, Kinds, External) ->
3737
{[{_, Kind, LocalMeta, _, _, _}], ClausesPairs} ->
3838
case (Kinds == all) orelse (lists:member(Kind, Kinds)) of
3939
true ->
40-
Local = {value, fun(Fun, Args) -> invoke_local(Meta, Module, Fun, Args, External) end},
40+
TrackLocal = (Kind == defmacrop),
41+
TrackLocal andalso track_local(Module, Tuple),
42+
Local = {value, fun(Fun, Args) -> invoke_local(Meta, Module, Fun, Args, TrackLocal, External) end},
4143
Clauses = [Clause || {_, Clause} <- ClausesPairs],
42-
elixir_erl:definition_to_anonymous(Kind, LocalMeta, Clauses, Local, External);
44+
{Kind, elixir_erl:definition_to_anonymous(Kind, LocalMeta, Clauses, Local, External)};
4345
false ->
4446
false
4547
end;
@@ -49,17 +51,22 @@ fun_for(Meta, Module, Name, Arity, Kinds, External) ->
4951
_:_ -> false
5052
end.
5153

52-
invoke_local(Meta, Module, ErlName, Args, External) ->
54+
invoke_local(Meta, Module, ErlName, Args, TrackLocal, External) ->
5355
{Name, Arity} = elixir_utils:erl_fa_to_elixir_fa(ErlName, length(Args)),
5456

5557
case fun_for(Meta, Module, Name, Arity, all, External) of
5658
false ->
5759
{current_stacktrace, [_ | T]} = erlang:process_info(self(), current_stacktrace),
5860
erlang:raise(error, undef, [{Module, Name, Arity, []} | T]);
59-
Fun ->
61+
{Kind, Fun} ->
62+
(TrackLocal and (Kind == defp)) andalso track_local(Module, {Name, Arity}),
6063
apply(Fun, Args)
6164
end.
6265

66+
track_local(Module, FunArity) ->
67+
{_, Bag} = elixir_module:data_tables(Module),
68+
ets:insert(Bag, {macro_private_calls, FunArity}).
69+
6370
invoke_external(Meta, Mod, Name, Args, E) ->
6471
is_map(E) andalso elixir_env:trace({require, Meta, Mod, []}, E),
6572
apply(Mod, Name, Args).

lib/elixir/src/elixir_dispatch.erl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,23 +171,23 @@ expand_import(Meta, Name, Arity, E, Extra, AllowLocals, Trace) ->
171171
_ ->
172172
Local = AllowLocals andalso elixir_def:local_for(Meta, Name, Arity, [defmacro, defmacrop], E),
173173

174-
case Dispatch of
174+
case {Dispatch, Local} of
175175
%% There is a local and an import. This is a conflict unless
176176
%% the receiver is the same as module (happens on bootstrap).
177-
{_, Receiver} when Local /= false, Receiver /= Module ->
177+
{{_, Receiver}, {_, _}} when Receiver /= Module ->
178178
{conflict, Receiver};
179179

180180
%% There is no local. Dispatch the import.
181-
_ when Local == false ->
181+
{_, false} ->
182182
do_expand_import(Dispatch, Meta, Name, Arity, Module, E, Trace);
183183

184184
%% Dispatch to the local.
185-
_ ->
185+
{_, {_Kind, Fun}} ->
186186
Trace andalso begin
187187
elixir_env:trace({local_macro, Meta, Name, Arity}, E),
188188
elixir_locals:record_local(Tuple, Module, ?key(E, function), Meta, true)
189189
end,
190-
{macro, Module, expander_macro_fun(Meta, Local, Module, Name, E)}
190+
{macro, Module, expander_macro_fun(Meta, Fun, Module, Name, E)}
191191
end
192192
end.
193193

lib/elixir/src/elixir_map.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ maybe_load_struct(Meta, Name, Assocs, E) ->
192192
false ->
193193
Name:'__struct__'(Assocs);
194194

195-
ExternalFun ->
195+
{_, ExternalFun} ->
196196
%% There is an inherent race condition when using external_for.
197197
%% By the time we got to execute the function, the ETS table
198198
%% with temporary definitions for the given module may no longer

lib/elixir/src/elixir_module.erl

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -540,12 +540,10 @@ spawn_parallel_checker(CheckerInfo, ModuleMap, E) ->
540540
_ -> true
541541
end,
542542

543-
Infer = elixir_config:get(infer_signatures),
544-
545543
if
546544
%% We need this clause for bootstrap reasons
547-
CheckerInfo /= nil; Infer ->
548-
'Elixir.Module.ParallelChecker':spawn(CheckerInfo, ModuleMap, Log, Infer, E);
545+
CheckerInfo /= nil ->
546+
'Elixir.Module.ParallelChecker':spawn(CheckerInfo, ModuleMap, Log, E);
549547
true ->
550548
ModuleMap
551549
end.

lib/mix/lib/mix/compilers/test.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ defmodule Mix.Compilers.Test do
2323
"""
2424
def require_and_run(matched_test_files, test_paths, elixirc_opts, opts) do
2525
elixirc_opts =
26-
Keyword.merge([docs: false, debug_info: false, infer_signatures: false], elixirc_opts)
26+
Keyword.merge([docs: false, debug_info: false], elixirc_opts)
2727

2828
previous_opts = Code.compiler_options(elixirc_opts)
2929

0 commit comments

Comments
 (0)