Skip to content

reflection of quot and rem #2540

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

Merged
merged 33 commits into from
May 29, 2025

Conversation

ninioArtillero
Copy link
Contributor

This PR aims to fix #1447

I start by adding a negative test showing the offending behavior.
It is on /test/reflect/neg/, but welcome suggestions if there is a more appropriate place.

A lead: both quot and rem functions are opaque-reflected, while div and mod are not.

@ninioArtillero ninioArtillero marked this pull request as draft May 20, 2025 19:46
@ninioArtillero ninioArtillero marked this pull request as ready for review May 22, 2025 19:22
@ninioArtillero
Copy link
Contributor Author

ninioArtillero commented May 22, 2025

I implemented quot and rem in the refinement logic and added define abs x = if x >= 0 then x else -x to src/GHC/Num_LHAssumptions.hs.
I think the implementation of both are correct, but still need to verify it. how should I go about it? Should I implement some unit tests? If so, where?

Also, I'm still to run all tests to look for regressions (or does ci/circleci does this already?).

@facundominguez
Copy link
Collaborator

Thanks @ninioArtillero. CI might catch some regressions indeed. For tests, you could add a module under "tests/" with concrete examples like

{-@ exQuot1 :: { -2 = quot -5 2 } @-}
exQuot1 :: ()
exQuot1 = ()

and/or create a testsuite in the liquidhaskell package for property based tests.

@ninioArtillero
Copy link
Contributor Author

ninioArtillero commented May 22, 2025

For the second option, you mean something like what I just pushed? I would add all the properties as post-conditions of that same function.

@facundominguez
Copy link
Collaborator

facundominguez commented May 23, 2025

For the second option, you mean something like what I just pushed? I would add all the properties as post-conditions of that same function.

Not really. It would have to be a test suite using QuickCheck, to test for the equivalence of quot and rem in Haskell and in the logic. But we can skip this and just stick with a module under tests/.

@ninioArtillero
Copy link
Contributor Author

Not really. It would have to be a test suite using QuickCheck, to test for the equivalence of quot and rem in Haskell and in the logic. But we can skip this and just stick with a module under tests/.

I have played around with QuickCheck and think I can implement the tests. As there are no custom data types involved, guess it should not be much of a problem.

@ninioArtillero
Copy link
Contributor Author

ninioArtillero commented May 24, 2025

I implemented quotRem in terms of divMod in the test-suite to test the implementation of quot and rem at src/GHC/Real_LHAssumptions.hs (kind of a inverse-reflect experiment). QuickCheck tests suggest implementation is correct.

Nevertheless, I found some specific cases that prevented verification of my original reflect-pos test, and I think I have found a bug: logic / and mod don´t behave as Haskell's div and mod when both arguments are negative as implied by the existing defines at said module.

Copy link
Collaborator

@facundominguez facundominguez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bravo @ninioArtillero! Here go some comments.

test/Main.hs Outdated
Comment on lines 15 to 18
-- | Throws error if a test fails. Use this alternative to abort build
-- in case of failure when test condition is enabled.
main' :: IO ()
main' = do
Copy link
Collaborator

@facundominguez facundominguez May 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good observation. In Haskell QuickCheck is used with tasty and tasty-quickcheck or similar scaffolding for tests.

I've found these tests can be integrated in tests:test:tasty. It is a testsuite inside the tests package. If you want, you can look into that. Otherwise I could do it too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could look into that after having my test pass LH verification.

ninioArtillero and others added 6 commits May 27, 2025 16:47
Co-authored-by: Facundo Domínguez <facundominguez@gmail.com>
Co-authored-by: Facundo Domínguez <facundominguez@gmail.com>
Co-authored-by: Facundo Domínguez <facundominguez@gmail.com>
@ninioArtillero
Copy link
Contributor Author

Used an alternative implementation proposed by @facundominguez that uses an explicit termination metric to make verification pass. Now both the property tests and LH verification pass, so we can be confident that the logic implementation of quot and rem is fine.

But the lemmaQuotRem at the reflect-pos test is complaining, even though the test examples work ok 😣

@ninioArtillero
Copy link
Contributor Author

ninioArtillero commented May 28, 2025

The regression was introduced at 7b648be9e where the definition of quot and rem at src/GHC/Real_LHAssumptions.hs was changed to the match the implementation proved correct at the test/QuotRem.

@facundominguez
Copy link
Collaborator

I'm setting up to merge. We need an issue to investigate the negative test.

Thanks @ninioArtillero!

@facundominguez
Copy link
Collaborator

hm, the neg test started failing after 280c0e1. I thought I had tested that before.

@facundominguez facundominguez merged commit d2397ca into ucsd-progsys:develop May 29, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

div and mod have interpretations in SMT, but quot and rem do not
3 participants