Skip to content

Commit 3c90f4b

Browse files
committed
Clean up apply_infer/apply_strong
1 parent eebc132 commit 3c90f4b

File tree

1 file changed

+63
-50
lines changed

1 file changed

+63
-50
lines changed

lib/elixir/lib/module/types/apply.ex

Lines changed: 63 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -278,20 +278,19 @@ defmodule Module.Types.Apply do
278278
{_args_types, context} = apply_no_domain_args(args, args_fun, expr, stack, context)
279279
{dynamic(), context}
280280

281-
info ->
282-
apply_remote(info, nil, name, args, args_fun, expr, stack, context)
283-
end
284-
end
281+
{:strong, domain, clauses} ->
282+
domain = domain(domain, clauses)
283+
{args_types, context} = apply_args(args, domain, [], args_fun, expr, stack, context)
285284

286-
defp apply_remote(info, mod, fun, args, args_fun, expr, stack, context) do
287-
case apply_signature(info, args, args_fun, expr, stack, context) do
288-
{:ok, _indexes, type, context} ->
289-
{type, context}
285+
case apply_strong(domain, clauses, args_types, stack) do
286+
{_used, type} ->
287+
{type, context}
290288

291-
{:error, args_types, domain, clauses, context} ->
292-
mfac = mfac(expr, mod, fun, length(args_types))
293-
error = {{:badremote, clauses}, domain, args_types, mfac, expr, context}
294-
{error_type(), error(error, elem(expr, 1), stack, context)}
289+
:error ->
290+
mfac = mfac(expr, nil, name, arity)
291+
error = {{:badremote, clauses}, domain, args_types, mfac, expr, context}
292+
{error_type(), error(error, elem(expr, 1), stack, context)}
293+
end
295294
end
296295
end
297296

@@ -375,7 +374,7 @@ defmodule Module.Types.Apply do
375374
{args_types, context} = apply_args(args, domain, [], args_fun, expr, stack, context)
376375

377376
case remote_apply(info, args_types, stack) do
378-
{:ok, _indexes, type} ->
377+
{:ok, type} ->
379378
{type, context}
380379

381380
{:error, error} ->
@@ -386,79 +385,61 @@ defmodule Module.Types.Apply do
386385
end
387386

388387
defp remote_apply(:none, _args_types, _stack) do
389-
{:ok, [], dynamic()}
388+
{:ok, dynamic()}
390389
end
391390

392391
defp remote_apply({:infer, _domain, clauses}, args_types, _stack) do
393-
case apply_clauses(clauses, args_types, 0, 0, [], []) do
394-
{0, [], []} ->
395-
{:error, {:badremote, clauses}}
396-
397-
{count, used, _returns} when count > @max_clauses ->
398-
{:ok, used, dynamic()}
399-
400-
{_count, used, returns} ->
401-
{:ok, used, returns |> Enum.reduce(&union/2) |> dynamic()}
402-
end
403-
end
404-
405-
defp remote_apply({:strong, _, [{expected, return}] = clauses}, args_types, stack) do
406-
# Optimize single clauses as the domain is the single clause args.
407-
case zip_compatible?(args_types, expected) do
408-
true -> {:ok, [0], return(return, args_types, stack)}
409-
false -> {:error, {:badremote, clauses}}
392+
case apply_infer(clauses, args_types) do
393+
{_used, type} -> {:ok, type}
394+
:error -> {:error, {:badremote, clauses}}
410395
end
411396
end
412397

413398
defp remote_apply({:strong, domain, clauses}, args_types, stack) do
414-
# If the type is only gradual, the compatibility check is the same
415-
# as a non disjoint check. So we skip checking compatibility twice.
416-
with true <- zip_compatible_or_only_gradual?(args_types, domain),
417-
{count, used, returns} when count > 0 <- apply_clauses(clauses, args_types, 0, 0, [], []) do
418-
{:ok, used, returns |> Enum.reduce(&union/2) |> return(args_types, stack)}
419-
else
420-
_ -> {:error, {:badremote, clauses}}
399+
case apply_strong(domain, clauses, args_types, stack) do
400+
{_used, type} -> {:ok, type}
401+
:error -> {:error, {:badremote, clauses}}
421402
end
422403
end
423404

424405
defp remote_apply({:element, index}, [_index, tuple], _stack) do
425406
case tuple_fetch(tuple, index - 1) do
426-
{_optional?, value_type} -> {:ok, [0], value_type}
407+
{_optional?, value_type} -> {:ok, value_type}
427408
:badtuple -> {:error, badremote(:erlang, :element, 2)}
428409
:badindex -> {:error, {:badindex, index, tuple}}
429410
end
430411
end
431412

432413
defp remote_apply({:insert_element, index}, [_index, tuple, value], _stack) do
433414
case tuple_insert_at(tuple, index - 1, value) do
434-
value_type when is_descr(value_type) -> {:ok, [0], value_type}
415+
value_type when is_descr(value_type) -> {:ok, value_type}
435416
:badtuple -> {:error, badremote(:erlang, :insert_element, 3)}
436417
:badindex -> {:error, {:badindex, index - 1, tuple}}
437418
end
438419
end
439420

440421
defp remote_apply({:delete_element, index}, [_index, tuple], _stack) do
441422
case tuple_delete_at(tuple, index - 1) do
442-
value_type when is_descr(value_type) -> {:ok, [0], value_type}
423+
value_type when is_descr(value_type) -> {:ok, value_type}
443424
:badtuple -> {:error, badremote(:erlang, :delete_element, 2)}
444425
:badindex -> {:error, {:badindex, index, tuple}}
445426
end
446427
end
447428

448429
defp remote_apply({:make_tuple, size}, [_size, elem], _stack) do
449-
{:ok, [0], tuple(List.duplicate(elem, size))}
430+
{:ok, tuple(List.duplicate(elem, size))}
450431
end
451432

452433
defp remote_apply(:hd, [list], _stack) do
453434
case list_hd(list) do
454-
{_, value_type} -> {:ok, [0], value_type}
435+
{_, value_type} -> {:ok, value_type}
455436
:badnonemptylist -> {:error, badremote(:erlang, :hd, 1)}
456437
end
457438
end
458439

459440
defp remote_apply(:tl, [list], _stack) do
460441
case list_tl(list) do
461-
{_, value_type} -> {:ok, [0], value_type}
442+
{_, value_type} -> {:ok, value_type}
462443
:badnonemptylist -> {:error, badremote(:erlang, :tl, 1)}
463444
end
464445
end
@@ -473,20 +454,20 @@ defmodule Module.Types.Apply do
473454

474455
cond do
475456
skip? ->
476-
{:ok, [0], result}
457+
{:ok, result}
477458

478459
match?({false, _}, map_fetch(left, :__struct__)) or
479460
match?({false, _}, map_fetch(right, :__struct__)) ->
480461
{:error, :struct_comparison}
481462

482463
number_type?(left) and number_type?(right) ->
483-
{:ok, [0], result}
464+
{:ok, result}
484465

485466
disjoint?(left, right) ->
486467
{:error, :mismatched_comparison}
487468

488469
true ->
489-
{:ok, [0], result}
470+
{:ok, result}
490471
end
491472
end
492473

@@ -495,16 +476,16 @@ defmodule Module.Types.Apply do
495476

496477
cond do
497478
skip? ->
498-
{:ok, [0], result}
479+
{:ok, result}
499480

500481
name in [:==, :"/="] and number_type?(left) and number_type?(right) ->
501-
{:ok, [0], result}
482+
{:ok, result}
502483

503484
disjoint?(left, right) ->
504485
{:error, :mismatched_comparison}
505486

506487
true ->
507-
{:ok, [0], result}
488+
{:ok, result}
508489
end
509490
end
510491

@@ -806,6 +787,38 @@ defmodule Module.Types.Apply do
806787
{Enum.reverse(acc), context}
807788
end
808789

790+
defp apply_infer(clauses, args_types) do
791+
case apply_clauses(clauses, args_types, 0, 0, [], []) do
792+
{0, [], []} ->
793+
:error
794+
795+
{count, used, _returns} when count > @max_clauses ->
796+
{used, dynamic()}
797+
798+
{_count, used, returns} ->
799+
{used, returns |> Enum.reduce(&union/2) |> dynamic()}
800+
end
801+
end
802+
803+
defp apply_strong(_domain, [{expected, return}], args_types, stack) do
804+
# Optimize single clauses as the domain is the single clause args.
805+
case zip_compatible?(args_types, expected) do
806+
true -> {[0], return(return, args_types, stack)}
807+
false -> :error
808+
end
809+
end
810+
811+
defp apply_strong(domain, clauses, args_types, stack) do
812+
# If the type is only gradual, the compatibility check is the same
813+
# as a non disjoint check. So we skip checking compatibility twice.
814+
with true <- zip_compatible_or_only_gradual?(args_types, domain),
815+
{count, used, returns} when count > 0 <- apply_clauses(clauses, args_types, 0, 0, [], []) do
816+
{used, returns |> Enum.reduce(&union/2) |> return(args_types, stack)}
817+
else
818+
_ -> :error
819+
end
820+
end
821+
809822
defp apply_clauses([{expected, return} | clauses], args_types, index, count, used, returns) do
810823
if zip_not_disjoint?(args_types, expected) do
811824
apply_clauses(clauses, args_types, index + 1, count + 1, [index | used], [return | returns])

0 commit comments

Comments
 (0)