Skip to content

The assert function should not be used in erased positions #428

@jespercockx

Description

@jespercockx

I was experimenting a bit with the assert function that I added in #388 for enforcing dynamic contracts. In particular, I wanted to implement the following function:

postcondition : (@0 P : b  Set) {{post :  {y}  Dec (P y)}}
          (f : a  b)
          (x : a)  ∃ b P

Now the way I expected to have to implement it is as follows:

postcondition post f x = assert (post (f x)) (f x ⟨ it ⟩)

(where it : {{a}} → a is defined as usual by it {{x}} = x). This leads to the expected Haskell code:

postcondition :: (b -> Bool) -> (a -> b) -> a -> b
postcondition post f x = assert (post (f x)) (f x)

However I realized I could also put the assert in the erased portion of the result:

postcondition post f x = f x ⟨ assert (post (f x)) it ⟩

which leads to Haskell code without any run-time check:

postcondition post f x = f x

Now we could in principle "fix" this by only allowing the assert function to appear in non-erased parts of a program. However this is rather strange because usually things work the other way around.

More generally, the current type of assert is logically inconsistent because you can always simply assert ⊥ to get a proof of anything. This is "fine" in unerased positions since it will lead to a run-time error, but in erased positions this is problematic. Maybe instead of using postulate in the definition of assert it should work more like the definition of error which requires a tactic argument of type .

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions