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

Set measures generate erroneous constraints when applied to non-polymorphic datatypes #2272

Closed
clayrat opened this issue Mar 1, 2024 · 14 comments · Fixed by ucsd-progsys/liquid-fixpoint#688 or #2282

Comments

@clayrat
Copy link
Contributor

clayrat commented Mar 1, 2024

Typechecking the following program:

{-@ LIQUID "--reflection" @-}

module SngBug where

import Data.Set

data Lst a = Emp | Cons a (Lst a)

{-@ measure lstHd @-}
lstHd :: Ord a => Lst a -> Set a
lstHd  Emp       = empty
lstHd (Cons x _) = singleton x

lcons ::  Lst l -> Lst (Lst l)
{-@ lcons :: p: Lst l -> {v:Lst (Lst l) | v = Cons p Emp } @-}
lcons p = Cons p Emp

crashes with the error:

crash: SMTLIB2 respSat = Error "line 3 column 25217: unknown constant smt_set_sng ((SngBug.Lst Int)) declared: (declare-fun smt_set_sng (Int) (Array Int Bool)) "

The error disappears if lstHd is declared reflect instead of measure. It triggers both with and without PLE.

It looks like the internal Lst l type doesn't get converted to Int which is what the encoding of sets as Array Int Bool expects. We currently think there are two possible solutions for this:

  1. Only generate set operations for elements whose type can be encoded as Int (simpler solution, will turn a crash into a proper typechecking error)
  2. Generate multiple set types for each potential set element type (more complex, but allows for expressing more programs)
@ranjitjhala
Copy link
Member

hi @clayrat -- i have a new laptop and am still installing stuff, can you remind me what smt_set_sng is declared as? i.e. there should be a line in the .liquid/foo.hs.smt2 file that says how it is declared?

@nikivazou
Copy link
Member

The problem is that the set elements as declared on SMT as int so every time the set operations are applied (via measures) to elements that are not encoded as int (e.g., list of lists) there is an SMT crash.

Also, .liquid/foo.hs.smt2 does not contain the declaration of smt_set_sng. I assume this is an optimization made by @facundominguez ?

@facundominguez
Copy link
Collaborator

Also, .liquid/foo.hs.smt2 does not contain the declaration of smt_set_sng. I assume this is an optimization made by @facundominguez ?

Not an optimization that I remember doing, but I could still be responsible :)

@clayrat
Copy link
Contributor Author

clayrat commented Mar 4, 2024

It looks like this optimization was added in ucsd-progsys/liquid-fixpoint#641

@ranjitjhala
Copy link
Member

hmm that is mysterious, we have to declare smt_set_sng somewhere surely...

@nikivazou
Copy link
Member

It is declared by fixpoint and I assume it is sent to the Z3. But, it is not printed at the .smt2 file (after the optimization).

@ranjitjhala
Copy link
Member

ranjitjhala commented Mar 4, 2024 via email

@clayrat
Copy link
Contributor Author

clayrat commented Mar 4, 2024

I've created a LF PR to fix the preamble logging: ucsd-progsys/liquid-fixpoint#681

@ranjitjhala
Copy link
Member

ranjitjhala commented Mar 4, 2024 via email

@nikivazou
Copy link
Member

That is indeed a good idea! cvc5 seems to have "polymorphic" arrays that we could use to define sets.
So maybe we should:

  1. put cvc5 in the benchmark tests (to see if it behaves as well as z3).
  2. create a minimum z3 test with the feature we want and as in the z3 github if there is a way to support it.

@facundominguez
Copy link
Collaborator

facundominguez commented Mar 4, 2024

ah ... that's unfortunate, the .smt2 files are supposed to be "standalone" i.e. you can just run z3 blah.smt2 so it looks like the optimization breaks that?

Maybe we could test that the smt2 files produce no errors in CI. I don't know if there is an easy way to test if the answers provided by z3 match the answers provided by LF.

@ranjitjhala
Copy link
Member

Looks like CVC5 does have polymorphic sets out of the box though, we should definitely try it out!

https://cvc5.github.io/docs/cvc5-1.0.0/theories/sets-and-relations.html#finite-sets

@ranjitjhala
Copy link
Member

@nikivazou -- I believe z3 also has polymorphic arrays? the problem if I recall correctly is that we define set using the z3 map functionality, but only do it "monomorphically"

https://stackoverflow.com/questions/17706219/defining-a-theory-of-sets-with-z3-smt-lib2

@ranjitjhala
Copy link
Member

Actually, it occurs to me that the "problem" with our encoding is we try to use the Z3 "function" declaration (e.g. smt_set_sng) which requires us to give a sort to that function, which has to be monomorphic (because I think functions can't be polymorphic?)

If instead we just inlined the function definition, then we wouldn't need any sorts :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants