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

Strong normalization broken in an open context #1428

Open
GoogleCodeExporter opened this issue Aug 8, 2015 · 16 comments
Open

Strong normalization broken in an open context #1428

GoogleCodeExporter opened this issue Aug 8, 2015 · 16 comments
Labels
sized types Sized types, termination checking with sized types, size inference termination Issues relating to the termination checker type: bug Issues and pull requests about actual bugs
Milestone

Comments

@GoogleCodeExporter
Copy link

data Nat (i : Size) : Set where
  zero : Nat i
  suc :  (j : Size< i)  Nat j  Nat i

unfoldaux : (f :  i  Nat i)   i  Nat i  Set1
unfoldaux f i zero = Set
unfoldaux f i (suc j n) = unfoldaux f j (f j)

Original issue reported on code.google.com by sanzhi...@gmail.com on 10 Feb 2015 at 7:24

@GoogleCodeExporter GoogleCodeExporter added type: bug Issues and pull requests about actual bugs auto-migrated termination Issues relating to the termination checker sized types Sized types, termination checking with sized types, size inference labels Aug 8, 2015
@GoogleCodeExporter
Copy link
Author

But this does not break normalization!

Original comment by andreas....@gmail.com on 10 Feb 2015 at 7:27

@GoogleCodeExporter
Copy link
Author

Is this a problem?

unfoldauxNat' : (f :  i  Nat i)   i  Set1
unfoldauxNat' f i = unfoldauxNat f i (f i)

problem : (f :  i  Size< i) (g :  i  Nat (f i))   i  Set1
problem f g i = unfoldauxNat' (\ i  suc (f i) (g i)) i

Original comment by sanzhi...@gmail.com on 10 Feb 2015 at 7:35

@GoogleCodeExporter
Copy link
Author

open import Common.Size
open import Common.Prelude

data Wrap (A : Set) : Set where
  wrap : A  Wrap A

module M (f :  i  Wrap (Size< i)) where

  test :  i  Wrap (Size< i)  ⊥
  test i (wrap j) = test j (f j)

module N (g :  i  Size< i) where

  open M (λ i  wrap (g i))

  loop : Size  ⊥
  loop i = test i (wrap (g i))

-- module N's code leaves size constraint  (↑ g i) =< i : Size open, which should hold.
-- Thus, we almost loop. 

A culprit seems to be that Size : Set. It should live in its own universe.
Also, the use of a data constructor "wrap" fools Agda into accepting j as a size eligible for justifying termination.
This is a somewhat sloppy analysis Agda does here.

Original comment by andreas....@gmail.com on 10 Feb 2015 at 8:21

  • Changed title: Strong normalization almost broken in an open context

@GoogleCodeExporter
Copy link
Author

Here is a variant that actually uses an (empty) sized type D.

open import Common.Size
open import Common.Prelude

data D (i : Size) : Set where
  wrap : (j : Size< i)  D i

module M (f :  i  D i) where

  test :  i  D i  ⊥
  test i (wrap j) = test j (f j)

module N (g :  i  Size< i) where

  f :  i  D i
  f i = wrap (g i)

  open M f

  loop : Size  ⊥
  loop i = test i (f i)

Original comment by andreas....@gmail.com on 13 Feb 2015 at 11:16

@GoogleCodeExporter
Copy link
Author

A bit more nicely, this test is written:

open import Common.Size
open import Common.Prelude

-- Note: the assumption of pred is absurd,
-- but still should not make Agda loop.

module _ (pred :  i  Size< i) where

data D (i : Size) : Set where
  wrap : (j : Size< i)  D i

loop :  i  D i  ⊥
loop i (wrap j) = loop j (wrap (pred j))
-- Loops during injectivity check

d :  i  D i
d i = wrap (pred i)

absurd : ⊥
absurd = loop ∞ (d ∞)

Original comment by andreas....@gmail.com on 13 Feb 2015 at 12:40

  • Changed title: Strong normalization broken in an open context

@GoogleCodeExporter
Copy link
Author

Here is a variant that uses a size in the recursive call that origins from a subtree. (Andrea's original example.)

data D (i : Size) : Set where
  c : (j : Size< i)  D j  D i

module _ (pred :  i  Size< i) (d :  i  D i) where

  loop :  i  D i  ⊥
  loop i (c j _) = loop j (c (pred j) (d (pred j)))

Original comment by andreas....@gmail.com on 14 Feb 2015 at 9:26

@GoogleCodeExporter
Copy link
Author

I think I want to disallow functions into Size and Size< to prevent this exploit.

Original comment by andreas....@gmail.com on 14 Feb 2015 at 9:29

@GoogleCodeExporter
Copy link
Author

I introduce a new sort SizeUniv to single out types Size and Size< and to prevent forming function spaces between them (so no function spaces in SizeUniv).

628fdcf

As a consequence, the SIZE builtins cannot have displayable Agda types any more:

531b71d

However, currently advance on this issue is stuck on the internal (hackish)
handling of sort metas, which are represented as level metas. This is also a
problem for double-checking meta solutions with CheckInternal.

I pushed my progress so far.

Original comment by andreas....@gmail.com on 15 Feb 2015 at 8:23

  • Changed state: Started
  • Added labels: Priority-High

@GoogleCodeExporter
Copy link
Author

Original comment by andreas....@gmail.com on 15 Feb 2015 at 8:34

@GoogleCodeExporter
Copy link
Author

Fixed by e69bc91

TODO: proper implementation of PTS rules in the presence of sort metas.

Original comment by andreas....@gmail.com on 17 Mar 2015 at 12:06

  • Changed state: Fixed

@GoogleCodeExporter
Copy link
Author

Currently, one can work around the "no-functions-into-size" check with parametrized modules.
This is still accepted:

open import Common.Size

data  : Set where

module Pred (i : Size) where
  postulate
    pred : Size< i
open Pred

data D (i : Size) : Set where
  c : Size< i  D i

iter :  i  D i  ⊥
iter i (c j) = iter j (c (pred j))

loop : Size  ⊥
loop i = iter i (c (pred i))

Original comment by andreas....@gmail.com on 17 Mar 2015 at 9:58

  • Changed state: Accepted

@GoogleCodeExporter
Copy link
Author

Fixed by forbidding size postulates in parametrized modules: f2740b9

Original comment by andreas....@gmail.com on 17 Mar 2015 at 12:00

  • Changed state: Fixed

@GoogleCodeExporter
Copy link
Author

-- One can still make Agda loop by defining pred with a hole.
-- However, I think this should maybe not be forbidden, 
-- as then abbreviation of sizes in where clauses become impossible.

open import Common.Size

data  : Set where

data D (i : Size) : Set where
  c : Size< i  D i

module _ (i : Size) where
  pred : Size< i
  pred = ?

-- The injectivity test loops here.
iter :  i  D i  ⊥
iter i (c j) = iter j (c (pred j))

absurd : ⊥
absurd = iter ∞ (c (pred ∞))

Original comment by andreas....@gmail.com on 17 Mar 2015 at 12:07

@GoogleCodeExporter
Copy link
Author

As a result of fixing this we have more BUILTIN pragmas which also introduces the constants.

For me, a pragma can be disregarded by some tools or alternative versions of Agda.

I know that the situation between builtins, primitives, and internal constructs is not really clear yet.

In particular while I understand that SizeUniv should be treated a bit like Set, Size, Size<, ↑_, and ∞ all have types and could then stay postulates.

Original comment by nicolas....@gmail.com on 3 Jul 2015 at 4:26

@GoogleCodeExporter
Copy link
Author

Indeed, they could remain postulates, if this is desirable.

Maybe there is another way to fix this issue, as the SizeUniv does not really harmonize with the universe hierarchy (at least the current implementation).

One could restrict Size< to negative positions, as in (i : <Size j) -> ...
However, this still needs <Size to live in a different universe.

Original comment by andreas....@gmail.com on 6 Jul 2015 at 6:07

andreasabel added a commit that referenced this issue Apr 14, 2016
With SizeUniv, sorts are no longer linear order, and the ptsRule is no
longer just maximum (lub).  This could be implemented properly, but is
serious effort due to the optimizations done for levels.

This patch defines SizeUniv = Set, so all the code for SizeUniv should
be dead.  I keep it, because I might come back and implement the ptsRule
properly.
@andreasabel andreasabel reopened this Apr 14, 2016
andreasabel added a commit that referenced this issue Apr 14, 2016
Fixing commit was 06b3e27
which deactivated SizeUniv
@asr asr added the status: blocked-by-issue This pull request is blocked on an open issue. label Oct 3, 2016
@UlfNorell UlfNorell added this to the 2.5.5 milestone May 28, 2018
@UlfNorell UlfNorell removed priority: high status: blocked-by-issue This pull request is blocked on an open issue. labels May 28, 2018
@jespercockx
Copy link
Member

We could try re-enabling SizeUniv now that the sort system actually allows it.

@jespercockx jespercockx modified the milestones: 2.6.0, 2.6.1 Nov 14, 2018
@jespercockx jespercockx modified the milestones: 2.6.1, 2.6.2 Dec 1, 2019
andreasabel added a commit that referenced this issue Oct 26, 2020
We now have Agda.Builtin.Size !
@jespercockx jespercockx modified the milestones: 2.6.2, 2.6.3 Feb 10, 2021
@UlfNorell UlfNorell modified the milestones: 2.6.3, 2.6.4 Apr 7, 2022
@jespercockx jespercockx modified the milestones: 2.6.4, Later Aug 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
sized types Sized types, termination checking with sized types, size inference termination Issues relating to the termination checker type: bug Issues and pull requests about actual bugs
Projects
None yet
Development

No branches or pull requests

5 participants