This PR addresses a few issues in #2250 and issue #3276. They are caused by an issue with IAlternative in impossible clauses, a type confusion issue in impossible clauses, and treatment of out of hidden constructors as impossible. An additional issue was brought up in #2250 that is not addressed here. I'll first discuss the issues and how I resolved them and then discuss a frex issue that should be patched before merging.
Issues fixed
The IAlternative issue is illustrated at the top of #2550:
%default total
g : Not Bool
g () impossible
f : Void
f = g True
Here the impossible clause is accepted because the type doesn't match at all, but when it is converted by mkTerm to a term for coverage checking, the ambiguous () is converted to a pattern variable which is then considered to cover everything. I addressed this by choosing the default alternative. I didn't see a way to determine the appropriate alternative at that point in the code. A user will have to explicitly say Unit or Pair to get the other option in an impossible clause.
The type confusion issue is illustrated in #2250 by:
import Data.Nat
%default total
f : n `LTE` m -> Void
f Z impossible
f (LTESucc x) = f x
x : Void
x = f $ LTEZero {right=Z}
Here Z is impossible because it has the wrong type, but during coverage checking only the constructor tag is looked at and Z is confused with LTEZero. I addressed this by also checking that the name matches. I coerce the names to resolved names in getCons because some constructor names were resolved in the context and others were not.
Finally, in #3276 there was a false impossible because a constructor was not visible. I adjusted recoverableError to not consider InvisibleName to be evidence of impossible.
The issues fixed in #2250 and #3276 are included as test cases.
Frex
Frex is relying on the ambiguity bug with Pair/MkPair in one location. The function is indeed covering, but Idris cannot capable of determining that if MkPair is used instead of (,). The current code is only working because of the above bug. This can be addressed with the following patch to frex, which pushes the impossible match down to a separate case tree:
Description
This PR addresses a few issues in #2250 and issue #3276. They are caused by an issue with
IAlternative
in impossible clauses, a type confusion issue in impossible clauses, and treatment of out of hidden constructors as impossible. An additional issue was brought up in #2250 that is not addressed here. I'll first discuss the issues and how I resolved them and then discuss a frex issue that should be patched before merging.Issues fixed
The
IAlternative
issue is illustrated at the top of #2550:Here the
impossible
clause is accepted because the type doesn't match at all, but when it is converted bymkTerm
to a term for coverage checking, the ambiguous()
is converted to a pattern variable which is then considered to cover everything. I addressed this by choosing the default alternative. I didn't see a way to determine the appropriate alternative at that point in the code. A user will have to explicitly sayUnit
orPair
to get the other option in an impossible clause.The type confusion issue is illustrated in #2250 by:
Here
Z
is impossible because it has the wrong type, but during coverage checking only the constructor tag is looked at andZ
is confused withLTEZero
. I addressed this by also checking that the name matches. I coerce the names to resolved names ingetCons
because some constructor names were resolved in the context and others were not.Finally, in #3276 there was a false impossible because a constructor was not visible. I adjusted
recoverableError
to not considerInvisibleName
to be evidence of impossible.The issues fixed in #2250 and #3276 are included as test cases.
Frex
Frex is relying on the ambiguity bug with Pair/MkPair in one location. The function is indeed covering, but Idris cannot capable of determining that if
MkPair
is used instead of(,)
. The current code is only working because of the above bug. This can be addressed with the following patch to frex, which pushes the impossible match down to a separate case tree: