Skip to content

Commit

Permalink
Merge pull request #505 from xxdavid/fix_add_type_pat_union
Browse files Browse the repository at this point in the history
Fix exhaustiveness checking for union types
  • Loading branch information
erszcz authored Jan 26, 2023
2 parents b0dd64b + d8c97b8 commit d09a29a
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 19 deletions.
10 changes: 3 additions & 7 deletions src/typechecker.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2176,10 +2176,7 @@ type_check_list_op(Env, Arg1, Arg2) ->
{false, _} ->
throw(type_error(Arg1, Ty1, type(list)));
{_, false} ->
throw(type_error(Arg2, Ty2, type(list)));
_ ->
%% Prevent "Nonexhaustive patterns" when self-gradualizing.
erlang:error(unreachable)
throw(type_error(Arg2, Ty2, type(list)))
end.

-spec type_check_call_ty(env(), _, _, _) -> {type(), env(), constraints:t()}.
Expand Down Expand Up @@ -4833,11 +4830,10 @@ add_type_pat_union(Pat, ?type(union, UnionTys) = UnionTy, Env) ->
_SomeTysMatched ->
%% TODO: The constraints should be merged with *or* semantics
%% and var binds with intersection
{Ty, Cs} = glb(PatTys, Env),
{Ty,
{lub(PatTys, Env),
normalize(type(union, UBounds), Env),
union_var_binds(Envs, Env),
constraints:combine([Cs|Css])}
constraints:combine(Css)}
end.

%% TODO: This is incomplete!
Expand Down
File renamed without changes.
16 changes: 16 additions & 0 deletions test/known_problems/should_pass/intersection_should_pass.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-module(intersection_should_pass).

-export([f/1,
g/1]).

-spec f(a|b) -> a|b.
f(V) -> h(V).

-spec g(a|b) -> a|b.
g(V) ->
A = h(V),
A.

-spec h(a) -> a;
(b) -> b.
h(V) -> V.
10 changes: 10 additions & 0 deletions test/should_fail/intersection_fail.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-module(intersection_fail).

-export([k/1]).

-spec i(a, b) -> {a, b};
(d, e) -> {d, e}.
i(V, U) -> {V, U}.

-spec k({a, e} | {d, b}) -> {a, e} | {d, b}.
k({V, U}) -> i(V, U).
13 changes: 13 additions & 0 deletions test/should_pass/exhaustiveness_union_types.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-module(exhaustiveness_union_types).

-export([g/0]).

-spec f() -> ok | {error, foo} | {error, bar}.
f() -> ok.

-spec g() -> integer().
g() ->
case f() of
ok -> 42;
{error, _Sth} -> 43
end.
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
-module(intersection).
-export([f/1, g/1, j/1]).

-spec f(a|b) -> a|b.
f(V) -> h(V).

-spec g(a|b) -> a|b.
g(V) ->
A = h(V),
A.

-spec h(a) -> a;
(b) -> b.
h(V) -> V.
-export([i/2,
j/1]).

-spec i(a, b) -> {a, b};
(d, e) -> {d, e}.
Expand Down

0 comments on commit d09a29a

Please sign in to comment.