Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Agda 2.6.4 RC1 fails to terminate type checking #6759

Closed
martinescardo opened this issue Aug 9, 2023 · 17 comments
Closed

Agda 2.6.4 RC1 fails to terminate type checking #6759

martinescardo opened this issue Aug 9, 2023 · 17 comments
Assignees
Labels
instance Instance resolution occurs check Problems with checking that metavariable solutions aren't loopy regression on master Unreleased regression in development version (Change to "regression in ..." should it be released!)
Milestone

Comments

@martinescardo
Copy link

Agda 2.6.4 RC1 with TypeTopology (https://github.com/martinescardo/TypeTopology) fails to terminate in the module source/Iterative/Ordinals.lagda.

The whole module is syntax-highlighted, using agda2-highlight-level 'interactive, so it is difficult to see where in the file the problem is occurring.

@martinescardo
Copy link
Author

By manual bisection, the function whose type checking seems to loop is Ord-to-𝕍-behaviour in line 917 of the above file.

@andreasabel
Copy link
Member

Not sure if it is related, but I noticed an error in debug printing:

Debug printing tc.lhs.top:10 failed due to exception:
  An internal error has occurred. Please report this as a bug.
  Location of the error: impossible, called at src/full/Agda/TypeChecking/Rules/Def.hs:755:46 

reportSDoc "tc.lhs.top" 10 $ vcat
[ "Clause before translation:"
, nest 2 $ vcat
[ "delta =" <+> do escapeContext impossible (size delta) $ prettyTCM delta

@andreasabel andreasabel added this to the 2.6.4 milestone Aug 9, 2023
@andreasabel andreasabel added the regression on master Unreleased regression in development version (Change to "regression in ..." should it be released!) label Aug 9, 2023
@andreasabel
Copy link
Member

andreasabel commented Aug 9, 2023

With -v10, Agda hangs at checking Ord-to-𝕍-behaviour, last words:

term _b_1399 := Iterative.Sets.φ-emb 𝓤 ua
                (Underlying.⟨ underlying-type-of-ordinal ⟩ α)
                (λ x → Ord-to-𝕍 (α ↓ x)) (_1389 (𝓤 = 𝓤) (ua = ua) (α = α))
                , (λ x → pr₂ (Ord-to-𝕍 (α ↓ x)))

Turning the body of Ord-to-𝕍-behaviour into a hole and then giving it succeeds.

Looks like the occurs checker is looping:

$ agda-2.6.4 Issue6759.lagda -v tc.meta.assign:20 -v tc.meta.occurs:40 
...
term _b_39 := Iterative.Sets.φ-emb 𝓤 ua
              (Underlying.⟨ underlying-type-of-ordinal ⟩ α)
              (λ x → Ord-to-𝕍 (α ↓ x)) (_29 (𝓤 = 𝓤) (ua = ua) (α = α))
              , (λ x → pr₂ (Ord-to-𝕍 (α ↓ x)))
mvar args: 2 1 0
fvars lhs (rel): 0 1 2
fvars lhs (nonstrict):
fvars lhs (irr):
initOccursCheck: we look into the following definitions:
Ord-to-𝕍-behaviour
occursCheck: meta variable _29 has relevance Relevant and quantity Quantity0 Q0Inferred
Meta occurs check found bad relevance
aborting because occurrence is flexible
initOccursCheck: we look into the following definitions:
Ord-to-𝕍-behaviour
<<BUSY>>

@andreasabel andreasabel added the status: bisecting A git bisect has been started to find the cause of the issue label Aug 9, 2023
@andreasabel
Copy link
Member

andreasabel commented Aug 9, 2023

My bisection run says: 2af2ff1 is the first bad commit

Date: Tue Nov 29 17:39:24 2022 +0100
[ fix #6364 ] Only filter instances based on their type, not their body

But I am not sure this is right, need to verify.

Ok, this commit is bad in the sense that it exhibits the loop, but is it the first?

Another bisect from v2.6.3 to this commit confirms, yes. (Ping @jespercockx .)

@andreasabel andreasabel removed the status: bisecting A git bisect has been started to find the cause of the issue label Aug 10, 2023
@andreasabel
Copy link
Member

What is weird about this bisection result is that TypeTopology does not use instance arguments.

@martinescardo
Copy link
Author

martinescardo commented Aug 17, 2023

It actually does use instance arguments. See source/Notation/*.lagda. If my automatic count is correct, 32 files declare instances (where some files declare lots of them, e.g. source/Various/Dedekind.lagda).

@andreasabel
Copy link
Member

@martinescardo: I made the mistake to grep in *.agda which didn't return any hits, but not for the reasons I believed...

Instance resolution has gone through a change, which is skimpily described in the changelog as follows:

agda/CHANGELOG.md

Lines 284 to 287 in 84b6bb2

* [**Breaking**] The algorithm for resolution of instance arguments
has been simplified. It will now only rely on the type of instances
to determine which candidate it should use, and no longer on their
values.

More information can be found in the issue and the PR:

It seems that other libraries had to be changed to work with the simplified instance resolution, so maybe a "continues to work without changes" cannot be expected for developments that use instance arguments.
What is not nice here, though, is that the result is not a failure to resolve some instances, but a seeming non-termination in the occurs checker.

@andreasabel
Copy link
Member

@jespercockx : Do you have time to look at this issue? It is blocking the next RC...

@jespercockx
Copy link
Member

I could try to take a look, but could you post the file that you used for bisection? That'd be a lot easier than starting from the TypeTopology library.

@jespercockx jespercockx self-assigned this Aug 25, 2023
@jespercockx jespercockx added instance Instance resolution occurs check Problems with checking that metavariable solutions aren't loopy labels Aug 25, 2023
@martinescardo
Copy link
Author

This example I could try to reduce. However, it is very strange. I tested the whole of TypeTopology with Agda 2.6.4 RC1, and only two errors, in 165k lines, occur, this one, and the __IMPOSSIBLE__ one in issue #6758.

What's more, regarding the issue here, a very similar short function occurs in another file with the same shape as this one, and no errors occur.

@andreasabel
Copy link
Member

@jespercockx Thanks! I put the files used for bisection up here:

@jespercockx
Copy link
Member

Comparing the debug output between 2.6.3 and 2.6.4, here is what I can make of the situation:

  • There are two metavariables _29 and _39.
  • The meta _29 comes from a type signature, so it is given modality @0.
  • Due to a change in the instance resolution, the order in which the metavariables _29 and _39 are solved is reversed: in 2.6.3, _29 is solved first, but in 2.6.4 Agda first tries to solve _39 instead.
  • The meta _29 appears in the solution to _39 in a flexible position.
  • Since _29 has modality @0, it is not allowed to be used in the solution to _39, causing a pattern violation.
  • Since the position of _29 in the solution of _39 is flexible, Agda doesn't do the usual trick of promoting _29 to a stricter modality.
  • Agda thinks it might be able to get rid of it by normalising the solution of _39.
  • Unfortunately, in this case normalising the solution takes a very long (infinite?) time. This was not noticeable in 2.6.3 since it was never normalised.

Writing this down and noticing that you are using --lossy-unification has given me an idea of how this could be solved: when --lossy-unification is enabled, we could apply the modality promotion of metavariables more eagerly as well. This might lose solutions, but with --lossy-unification you already don't have the guarantee of unique solutions, and the fact that you are using it implies avoiding normalisation is probably more important.

@jespercockx
Copy link
Member

Good news: my idea seems to fix the issue. After a few hours of staring at debug output, actually implementing the fix only took a minute. I've made a PR at #6796.

jespercockx added a commit to jespercockx/agda that referenced this issue Aug 26, 2023
jespercockx added a commit to jespercockx/agda that referenced this issue Aug 26, 2023
jespercockx added a commit to jespercockx/agda that referenced this issue Aug 27, 2023
@jespercockx
Copy link
Member

I wonder if a better solution that attacks the problem at its root would be to provide a flag that disables the normalization heuristic in the occurs checker. This wouldn't cause any regressions (like my fix in #6759 doesn), but would allow users who care more about performance than about powerful inference to turn off the part that makes Agda's typechecker slow.

@andreasabel
Copy link
Member

andreasabel commented Aug 31, 2023

@jespercockx wrote:

provide a flag that disables the normalization heuristic in the occurs checker.

One could experiment with this and see how larger developments are affected. I have no intuition how often normalization is needed in practice in the occurs check.

jespercockx added a commit to jespercockx/agda that referenced this issue Sep 3, 2023
@martinescardo
Copy link
Author

Thanks for fixing this issue!

@nad
Copy link
Contributor

nad commented Sep 5, 2023

Without normalisation there is presumably a risk that Agda's behaviour could be more brittle: replacing one piece of code with something definitionally equivalent could make the code stop working. We use normalisation in with abstraction to avoid problems of this kind, but the normalisation also makes with very slow in certain situations. On the other hand, the reflection machinery does not enforce normalisation, even though this could lead to brittleness.

Perhaps we could have a broader discussion about these things. My opinion is that, given that a non-trivial definitional equality is one of the defining features of this kind of type theory, we should try to make most features respect definitional equality.

JobPetrovcic pushed a commit to JobPetrovcic/agda that referenced this issue Apr 12, 2024
…abled (agda#6796)

When --lossy-unification is enabled, we already lose the guarantee that we only throw an error when a problem is really unsolvable in favor of taking the "obvious" solution.
In this case the "obvious" solution is to promote the meta even if it is in a flexible position, so that is what we do.

Commits:
* [ fix agda#6759 ] Promote flexible metas if --lossy-unification is enabled
* [ re agda#6759 ] Address comments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
instance Instance resolution occurs check Problems with checking that metavariable solutions aren't loopy regression on master Unreleased regression in development version (Change to "regression in ..." should it be released!)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants