agda / agda

Agda is a dependently typed programming language / interactive theorem prover.

Home Page:https://wiki.portal.chalmers.se/agda/pmwiki.php

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Use of Non-terminating Function in Data Declaration Makes Typechecker Loop

emekoi opened this issue · comments

The following causes Agda (agda --no-libraries Example.agda) to go into an infinite loop.

data Unit : Set where

data Flip' (x : Unit) : (y : Unit) -> Set

Flip : Unit -> Unit -> Set
Flip x y = Flip y x

data Flip' a where
  flip : Flip a a

I've attached the debug output at verbosity level 10 here. After a couple of seconds Agda stops producing output, but at verbosity level 999 (is there an upper limit? the manual doesn't say) when it starts looping it outputs the following:

E Semantics.Flip [] [E @0 [] [], E @0 [] []] []
M Semantics.Flip
  [E @0 [] [], E @0 [] []]
  done [x, y] (Semantics.Flip @0 @1)
  []
E (Semantics.Flip @0 @1) [@0 = E @0 [] [], @1 = E @0 [] []] [] []

This sounds somewhat similar to #2627 (specifically this comment.)


Agda version 2.6.4
Built with flags (cabal -f)
 - enable-cluster-counting: unicode cluster counting in LaTeX backend using the ICU library
 - optimise-heavily: extra optimizations

Yes, that's why we have a termination checker. But it does not run until the mutual block is complete. Your example opens an implicit mutual block with the data signature Flip' which is only closed until the data definition Flip' is provided.

Workaround is to use the {-# NON_TERMINATING #-} pragma (insert before Flip). This stops Flip from being unfolded.

Ah, so this is the intended (unavoidable) behavior? Are definitions lifted out of mutual blocks if there isn't an actual dependency? Because the following terminates just fine:

data Unit : Set where

data Flip' (x : Unit) : (y : Unit) -> Set

Flip : Unit -> Unit -> Set
Flip x y = Flip y x

data Flip' a where

EDIT: Nevermind, we don't use Flip here so when the termination checker runs, it doesn't get stuck trying to evaluate Flip since it's never used.

Ah, so this is the intended (unavoidable) behavior?

Yes, somewhat unfortunately it is hard to fix:

Are definitions lifted out of mutual blocks if there isn't an actual dependency?

They formally stay in the mutual block, but the termination checker computes the actual dependencies.

Because the following terminates just fine:

Yes here you get the expected termination error for Flip.

I am closing this as duplicate of #1270.