Fix exhaustiveness checking for union types #505
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I've looked into issue #477 and traced the issue down to
add_type_pat_union/3
. If I understand it correctly, theadd_type_pat
function computes which parts of typeTy
are covered by patternPat
.add_type_union
is a special case whenTy
is a union type.It computes
add_type_pat
on all "parts of the union" and when one pattern matches more than one "part of the union", it computes the GLB of them. But I think this is not the correct behaviour.Imagine the following code
where
E
is of typeT = (T1 | T2 | … | TM)
. If for exampleP1
covers bothT1
andT2
,add_type_pat_union(T, P1)
outputsGLB(T1, T2)
. But it does not make much sense to me. It covers both of them, so I think it should be the lowest upper bound (i.e., union) of them instead.In the example mentioned in #477,
add_type_pat_union({error, foo} | {error, bar}, {error, _Sth})
returnsGLB({error, foo}. {error, bar})
which isnone()
. But it should rather be{error, foo} | {error, bar}
.I've fixed it, and apart from the example (
test/should_pass/exhaustiveness_union_types.erl
) now passing, three other things happened.First, this workaround for
is no longer needed.
Second, this false positive is gone as well:
I've moved
intersection.erl
intotest/should_pass/intersection.erl
, but it does not satisfy tests either because Gradualizer still outputsWhat should we do in this case? Maybe we can put part of the file into
known_problems/should_pass
and part intoshould_pass
?Third, gradualizing
test/should_fail/tuple_union_arg.erl
no longer reports an error. However, this is tricky. Until now, it reportedand this is the same false positive we've already seen. It should fail with a different error (something like that
i
cannot be called withd, b
and neither witha, e
). I've moved it into known problems.