Skip to content

Commit 1a4907a

Browse files
committed
Pass proper expression instead of bogus one
1 parent 6c51c8a commit 1a4907a

File tree

5 files changed

+109
-77
lines changed

5 files changed

+109
-77
lines changed

lib/elixir/lib/module/types.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ defmodule Module.Types do
285285
Pattern.of_head(args, guards, expected, {:infer, expected}, meta, stack, context)
286286

287287
{return_type, context} =
288-
Expr.of_expr(body, Descr.term(), :ok, stack, context)
288+
Expr.of_expr(body, Descr.term(), body, stack, context)
289289

290290
args_types =
291291
if stack.mode == :traversal do

lib/elixir/lib/module/types/expr.ex

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -133,19 +133,29 @@ defmodule Module.Types.Expr do
133133
end
134134

135135
# left = right
136-
# TODO: here
137-
def of_expr({:=, _, [left_expr, right_expr]} = expr, _expected, _expr, stack, context) do
136+
def of_expr({:=, _, [left_expr, right_expr]} = match, expected, expr, stack, context) do
138137
{left_expr, right_expr} = repack_match(left_expr, right_expr)
139-
{right_type, context} = of_expr(right_expr, @pending, expr, stack, context)
140138

141-
# We do not raise on underscore in case someone writes _ = raise "omg"
142-
context =
143-
case left_expr do
144-
{:_, _, ctx} when is_atom(ctx) -> context
145-
_ -> Pattern.of_match(left_expr, right_type, expr, {:match, right_type}, stack, context)
146-
end
139+
case left_expr do
140+
# We do not raise on underscore in case someone writes _ = raise "omg"
141+
{:_, _, ctx} when is_atom(ctx) ->
142+
of_expr(right_expr, expected, expr, stack, context)
143+
144+
_ ->
145+
type_fun = fn pattern_type, context ->
146+
# See if we can use the expected type to further refine the pattern type,
147+
# if we cannot, use the pattern type as that will fail later on.
148+
type =
149+
case compatible_intersection(pattern_type, expected) do
150+
{:ok, expected} -> expected
151+
:error -> pattern_type
152+
end
153+
154+
of_expr(right_expr, type, expr, stack, context)
155+
end
147156

148-
{right_type, context}
157+
Pattern.of_match(left_expr, type_fun, match, stack, context)
158+
end
149159
end
150160

151161
# %{map | ...}
@@ -236,23 +246,23 @@ defmodule Module.Types.Expr do
236246
end
237247

238248
# (expr; expr)
239-
def of_expr({:__block__, _meta, exprs}, expected, expr, stack, context) do
249+
def of_expr({:__block__, _meta, exprs}, expected, _expr, stack, context) do
240250
{pre, [post]} = Enum.split(exprs, -1)
241251

242252
context =
243253
Enum.reduce(pre, context, fn expr, context ->
244-
{_, context} = of_expr(expr, @term, :ok, stack, context)
254+
{_, context} = of_expr(expr, @term, expr, stack, context)
245255
context
246256
end)
247257

248-
of_expr(post, expected, expr, stack, context)
258+
of_expr(post, expected, post, stack, context)
249259
end
250260

251261
def of_expr({:cond, _meta, [[{:do, clauses}]]}, expected, expr, stack, original) do
252262
clauses
253263
|> reduce_non_empty({none(), original}, fn
254264
{:->, meta, [[head], body]}, {acc, context}, last? ->
255-
{head_type, context} = of_expr(head, @pending, :ok, stack, context)
265+
{head_type, context} = of_expr(head, @pending, head, stack, context)
256266

257267
context =
258268
if stack.mode in [:infer, :traversal] do
@@ -280,7 +290,7 @@ defmodule Module.Types.Expr do
280290

281291
# TODO: here
282292
def of_expr({:case, meta, [case_expr, [{:do, clauses}]]}, expected, expr, stack, context) do
283-
{case_type, context} = of_expr(case_expr, @pending, :ok, stack, context)
293+
{case_type, context} = of_expr(case_expr, @pending, case_expr, stack, context)
284294

285295
# If we are only type checking the expression and the expression is a literal,
286296
# let's mark it as generated, as it is most likely a macro code. However, if
@@ -307,7 +317,7 @@ defmodule Module.Types.Expr do
307317
[{:->, _, [head, _]} | _] = clauses
308318
{patterns, _guards} = extract_head(head)
309319
domain = Enum.map(patterns, fn _ -> dynamic() end)
310-
{_acc, context} = of_clauses(clauses, domain, @pending, :ok, :fn, stack, {none(), context})
320+
{_acc, context} = of_clauses(clauses, domain, @pending, nil, :fn, stack, {none(), context})
311321
{fun(), context}
312322
end
313323

@@ -318,7 +328,7 @@ defmodule Module.Types.Expr do
318328

319329
{type, context} =
320330
if else_block do
321-
{type, context} = of_expr(body, @pending, :ok, stack, original)
331+
{type, context} = of_expr(body, @pending, body, stack, original)
322332

323333
of_clauses(
324334
else_block,
@@ -362,7 +372,7 @@ defmodule Module.Types.Expr do
362372
|> dynamic_unless_static(stack)
363373

364374
if after_block do
365-
{_type, context} = of_expr(after_block, @term, :ok, stack, context)
375+
{_type, context} = of_expr(after_block, @term, after_block, stack, context)
366376
{type, context}
367377
else
368378
{type, context}
@@ -412,7 +422,7 @@ defmodule Module.Types.Expr do
412422
else
413423
into = Keyword.get(opts, :into, [])
414424
{into_wrapper, gradual?, context} = for_into(into, meta, stack, context)
415-
{block_type, context} = of_expr(block, @pending, :ok, stack, context)
425+
{block_type, context} = of_expr(block, @pending, block, stack, context)
416426

417427
for_type =
418428
for type <- into_wrapper do
@@ -443,7 +453,7 @@ defmodule Module.Types.Expr do
443453
{fun_type, context} = of_expr(fun, fun(), call, stack, context)
444454

445455
{_args_types, context} =
446-
Enum.map_reduce(args, context, &of_expr(&1, @pending, :ok, stack, &2))
456+
Enum.map_reduce(args, context, &of_expr(&1, @pending, &1, stack, &2))
447457

448458
case fun_fetch(fun_type, length(args)) do
449459
:ok ->
@@ -455,7 +465,6 @@ defmodule Module.Types.Expr do
455465
end
456466
end
457467

458-
# TODO: here
459468
def of_expr({{:., _, [callee, key_or_fun]}, meta, []} = call, expected, expr, stack, context)
460469
when not is_atom(callee) and is_atom(key_or_fun) do
461470
if Keyword.get(meta, :no_parens, false) do
@@ -490,7 +499,7 @@ defmodule Module.Types.Expr do
490499
end
491500

492501
{args_types, context} =
493-
Enum.map_reduce(args, context, &of_expr(&1, @pending, :ok, stack, &2))
502+
Enum.map_reduce(args, context, &of_expr(&1, @pending, &1, stack, &2))
494503

495504
{types, context} =
496505
Enum.map_reduce(funs, context, fn fun, context ->
@@ -511,7 +520,7 @@ defmodule Module.Types.Expr do
511520
{remote_type, context} = of_expr(remote, atom(), call, stack, context)
512521

513522
{args_types, context} =
514-
Enum.map_reduce(args, context, &of_expr(&1, @pending, :ok, stack, &2))
523+
Enum.map_reduce(args, context, &of_expr(&1, @pending, &1, stack, &2))
515524

516525
{mods, context} = Of.modules(remote_type, name, length(args), call, meta, stack, context)
517526
apply_many(mods, name, args, args_types, call, stack, context)
@@ -542,7 +551,7 @@ defmodule Module.Types.Expr do
542551
{_kind, fun} = Keyword.fetch!(meta, :super)
543552

544553
{args_types, context} =
545-
Enum.map_reduce(args, context, &of_expr(&1, @pending, :ok, stack, &2))
554+
Enum.map_reduce(args, context, &of_expr(&1, @pending, &1, stack, &2))
546555

547556
Apply.local(fun, args_types, expr, stack, context)
548557
end
@@ -552,7 +561,7 @@ defmodule Module.Types.Expr do
552561
def of_expr({fun, _meta, args} = expr, _expected, _expr, stack, context)
553562
when is_atom(fun) and is_list(args) do
554563
{args_types, context} =
555-
Enum.map_reduce(args, context, &of_expr(&1, @pending, :ok, stack, &2))
564+
Enum.map_reduce(args, context, &of_expr(&1, @pending, &1, stack, &2))
556565

557566
Apply.local(fun, args_types, expr, stack, context)
558567
end
@@ -602,7 +611,7 @@ defmodule Module.Types.Expr do
602611
context
603612
end
604613

605-
{type, context} = of_expr(body, @pending, :ok, stack, context)
614+
{type, context} = of_expr(body, @pending, body, stack, context)
606615
{type, reset_vars(context, original)}
607616
end
608617

@@ -611,19 +620,14 @@ defmodule Module.Types.Expr do
611620
defp for_clause({:<-, meta, [left, right]}, stack, context) do
612621
expr = {:<-, [type_check: :generator] ++ meta, [left, right]}
613622
{pattern, guards} = extract_head([left])
614-
{type, context} = of_expr(right, @pending, :ok, stack, context)
615-
616-
context = Pattern.of_match(pattern, guards, dynamic(), expr, :for, stack, context)
617-
618-
{_type, context} =
619-
Apply.remote(Enumerable, :count, [right], [type], expr, stack, context)
620-
621-
context
623+
{type, context} = of_expr(right, @pending, expr, stack, context)
624+
{_type, context} = Apply.remote(Enumerable, :count, [right], [type], expr, stack, context)
625+
Pattern.of_generator(pattern, guards, dynamic(), :for, expr, stack, context)
622626
end
623627

624628
defp for_clause({:<<>>, _, [{:<-, meta, [left, right]}]} = expr, stack, context) do
625629
{right_type, context} = of_expr(right, binary(), expr, stack, context)
626-
context = Pattern.of_match(left, binary(), expr, :for, stack, context)
630+
context = Pattern.of_generator(left, [], binary(), :for, expr, stack, context)
627631

628632
if compatible?(right_type, binary()) do
629633
context
@@ -648,7 +652,7 @@ defmodule Module.Types.Expr do
648652

649653
# TODO: Use the collectable protocol for the output
650654
defp for_into(into, meta, stack, context) do
651-
{type, context} = of_expr(into, @pending, :ok, stack, context)
655+
{type, context} = of_expr(into, @pending, into, stack, context)
652656

653657
# We use subtype? instead of compatible because we want to handle
654658
# only binary/list, even if a dynamic with something else is given.
@@ -675,24 +679,23 @@ defmodule Module.Types.Expr do
675679

676680
defp with_clause({:<-, _meta, [left, right]} = expr, stack, context) do
677681
{pattern, guards} = extract_head([left])
678-
context = Pattern.of_match(pattern, guards, dynamic(), expr, :with, stack, context)
679-
{_, context} = of_expr(right, @pending, :ok, stack, context)
680-
context
682+
{_type, context} = of_expr(right, @pending, right, stack, context)
683+
Pattern.of_generator(pattern, guards, dynamic(), :with, expr, stack, context)
681684
end
682685

683686
defp with_clause(expr, stack, context) do
684-
{_type, context} = of_expr(expr, @pending, :ok, stack, context)
687+
{_type, context} = of_expr(expr, @pending, expr, stack, context)
685688
context
686689
end
687690

688691
defp with_option({:do, body}, stack, context, original) do
689-
{_type, context} = of_expr(body, @pending, :ok, stack, context)
692+
{_type, context} = of_expr(body, @pending, body, stack, context)
690693
reset_vars(context, original)
691694
end
692695

693696
defp with_option({:else, clauses}, stack, context, _original) do
694697
{_, context} =
695-
of_clauses(clauses, [dynamic()], @pending, :ok, :with_else, stack, {none(), context})
698+
of_clauses(clauses, [dynamic()], @pending, nil, :with_else, stack, {none(), context})
696699

697700
context
698701
end
@@ -733,7 +736,7 @@ defmodule Module.Types.Expr do
733736
{patterns, guards} = extract_head(head)
734737
{_trees, context} = Pattern.of_head(patterns, guards, domain, info, meta, stack, context)
735738

736-
{body, context} = of_expr(body, expected, expr, stack, context)
739+
{body, context} = of_expr(body, expected, expr || body, stack, context)
737740
context = context |> set_failed(failed?) |> reset_vars(original)
738741

739742
if mode == :traversal do

0 commit comments

Comments
 (0)