Skip to content

Commit 862ff78

Browse files
committed
Report clearer errors for violations on !, closes #15404
1 parent edc61ce commit 862ff78

2 files changed

Lines changed: 84 additions & 16 deletions

File tree

lib/elixir/lib/module/types/pattern.ex

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,30 +1546,43 @@ defmodule Module.Types.Pattern do
15461546
message =
15471547
with {_op, meta, expr, type} <- info,
15481548
true <- previous_subtype?(expected, previous) do
1549-
if match?({:case, :||}, meta[:type_check]) do
1550-
"""
1551-
the right-hand side of || will always execute:
1549+
case meta[:type_check] do
1550+
{:case, :||} ->
1551+
"""
1552+
the right-hand side of || will always execute:
15521553
1553-
#{expr_to_string(expr) |> indent(4)}
1554+
#{expr_to_string(expr) |> indent(4)}
15541555
1555-
because the left-hand side always evaluates to:
1556+
because the left-hand side always evaluates to:
15561557
1557-
#{to_quoted_string(type) |> indent(4)}
1558-
"""
1559-
else
1560-
"""
1561-
the following clause cannot match because the previous clauses already matched all possible values:
1558+
#{to_quoted_string(type) |> indent(4)}
1559+
"""
15621560

1563-
#{args_to_string(args) |> indent(4)} ->
1561+
{:case, :!} ->
1562+
"""
1563+
the following conditional expression:
15641564
1565-
it attempts to match on the result of:
1565+
#{expr_to_string({:!, [], [expr]}) |> indent(4)}
15661566
1567-
#{expr_to_string(expr) |> indent(4)}
1567+
will always evaluate to true because the expression has type:
15681568
1569-
which has the already matched type:
1569+
#{to_quoted_string(type) |> indent(4)}
1570+
"""
15701571

1571-
#{to_quoted_string(type) |> indent(4)}
1572-
"""
1572+
_ ->
1573+
"""
1574+
the following clause cannot match because the previous clauses already matched all possible values:
1575+
1576+
#{args_to_string(args) |> indent(4)} ->
1577+
1578+
it attempts to match on the result of:
1579+
1580+
#{expr_to_string(expr) |> indent(4)}
1581+
1582+
which has the already matched type:
1583+
1584+
#{to_quoted_string(type) |> indent(4)}
1585+
"""
15731586
end
15741587
else
15751588
_ ->
@@ -1702,6 +1715,17 @@ defmodule Module.Types.Pattern do
17021715
#{to_quoted_string(type) |> indent(4)}
17031716
"""
17041717

1718+
op == :! ->
1719+
"""
1720+
the following conditional expression:
1721+
1722+
#{expr_to_string({:!, [], [expr]}) |> indent(4)}
1723+
1724+
will always evaluate to false because the expression has type:
1725+
1726+
#{to_quoted_string(type) |> indent(4)}
1727+
"""
1728+
17051729
true ->
17061730
"""
17071731
the following conditional expression:

lib/elixir/test/elixir/module/types/expr_test.exs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2368,6 +2368,50 @@ defmodule Module.Types.ExprTest do
23682368
dynamic(false)
23692369
"""
23702370
end
2371+
2372+
test "! reports violations" do
2373+
assert typeerror!([x = 123], !x) =~ ~l"""
2374+
the following conditional expression:
2375+
2376+
!x
2377+
2378+
will always evaluate to false because the expression has type:
2379+
2380+
integer()
2381+
2382+
where "x" was given the type:
2383+
2384+
# type: integer()
2385+
# from: types_test.ex:LINE
2386+
x = 123
2387+
"""
2388+
2389+
assert typewarn!([x = nil], !x) |> elem(1) =~ ~l"""
2390+
the following conditional expression:
2391+
2392+
!x
2393+
2394+
will always evaluate to true because the expression has type:
2395+
2396+
dynamic(nil)
2397+
"""
2398+
2399+
assert typeerror!([x = 123], !!x) =~ ~l"""
2400+
the following conditional expression:
2401+
2402+
!x
2403+
2404+
will always evaluate to false because the expression has type:
2405+
2406+
integer()
2407+
2408+
where "x" was given the type:
2409+
2410+
# type: integer()
2411+
# from: types_test.ex:LINE
2412+
x = 123
2413+
"""
2414+
end
23712415
end
23722416

23732417
describe "receive" do

0 commit comments

Comments
 (0)