[ fix ] False positives checking for conflicts in coverage checking #3478
+40
−17
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.
Description
This fixes #3477. Idris considers
2 = length xs
as empty while checking missing cases in coverage checking, and it incorrectly accepts this as covering:There are two changes here:
I removed the
clearDefs
inconflictNF
to allow thelength xs
to expand whenxs
is known. Let me know if there is a reason we don't allow expansions here. It passes tests and it seems to be necessary to enable Idris to automatically use the2 = length xs
.Without this change, the following
impossible
clauses are required:The second change addresses the root cause. When checking for clashes between types in
conflictMatch
, idris checks if the heads clash, and if not it proceeds to check the arguments. This is a problem whenS (S Z)
is compared tolength xs
.S
andlength
do not clash, but it is not correct to then compareS Z
againstxs
. To remedy this, it is now only checking the spines in the case of matching data or type constructors. The helper function returnsNothing
to indicate the spine should be checked.Krivine.idr
was relying on this bug. The code was covering, but coverage checking was accepting it for the wrong reason. It was discounting the other case when looking atElement (EvalContext{}) _
vs(::) (Arr{}) ctx
(here::
is a function, not a constructor).Element
vs(::)
was not clashing, so it proceeded to compare the arguments and saw thatEvalContext{}
andArr{}
clashed (values headed by different constructors). After this change, it needed an impossible clause to unblock the(::)
.I've also added a test case, fixed a typo in a comment, and added a
log
message that I use do diagnose theseimpossible
issues. This will break code that relies on false positives in coverage, but given that the rest of papers and frex are uneffected, I suspect that is rare.