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

Printing of Cryptol newtypes in counterexamples throws away too much information #2119

Open
sauclovian-g opened this issue Sep 10, 2024 · 4 comments
Labels
subsystem: cryptol-saw-core Issues related to Cryptol -> saw-core translation with cryptol-saw-core tech debt Issues that document or involve technical debt topics: error-handling Issues involving the way SAW responds to an error condition topics: error-messages Issues involving the messages SAW produces on error usability An issue that impedes efficient understanding and use
Milestone

Comments

@sauclovian-g
Copy link
Collaborator

If your model has a Cryptol newtype in it (recall that newtypes are records) it gets embedded into saw-core as a tuple and throws away the record field names. This translation, however, also throws away the field ordering; the fields get sorted alphabetically before or during the translation.

The result of this is that when a counterexample containing a newtype gets printed, it comes out as a tuple of unlabeled values whose order does not (in general) match the original declaration. Once you realize what's going on, it's possible to sort this out by hand. It's not reasonable to expect the user to do that though, and also before you figure out what's going on the results are just incomprehensible.

It's not clear to me if we ought to throw away less information when translating to saw-core (that is, add record types and maybe other things to saw-core, which is a fairly big deal) or if this ought to get fixed by introducing a mechanism to lift saw-core counterexample values back to their source-level language. (That is also likely a fairly big deal, because it almost certainly involves substantial structural changes, and might still also require carrying more information around in saw-core.)

However, I think something needs to be done about it.

@sauclovian-g sauclovian-g added topics: error-messages Issues involving the messages SAW produces on error usability An issue that impedes efficient understanding and use tech debt Issues that document or involve technical debt topics: error-handling Issues involving the way SAW responds to an error condition labels Sep 10, 2024
@RyanGlScott
Copy link
Contributor

For a specific example of this in action, run the following SAW script:

// Test.cry
newtype T = { x : [16], y : [32] }
// test.saw
import "Test.cry";
prove_print z3 {{ \(t : T) -> False }};
$ ~/Software/saw-1.2/bin/saw test.saw
[16:22:21.150] Loading file "/home/ryanscott/Documents/Hacking/SAW/test.saw"
[16:22:21.225] Stack trace:
"prove_print" (/home/ryanscott/Documents/Hacking/SAW/test.saw:3:1-3:12)
prove: 1 unsolved subgoal(s)
Invalid: [t = (0, 0)]

Note that the counterexample is printed as t = (0, 0) rather than something like t = T { x = 0, y = 0 }.

@RyanGlScott
Copy link
Contributor

Cryptol also suffers from the same problem, but in a more limited context. This is because when Cryptol typechecks newtypes, it throws away the name of the newtype and treats it the same as any record. For example, if you try proving this in the Cryptol REPL (after loading Test.cry above):

$ ~/Software/cryptol-3.2.0/bin/cryptol Test.cry 
┏━╸┏━┓╻ ╻┏━┓╺┳╸┏━┓╻  
┃  ┣┳┛┗┳┛┣━┛ ┃ ┃ ┃┃  
┗━╸╹┗╸ ╹ ╹   ╹ ┗━┛┗━╸
version 3.2.0 (1bcb75c)
https://cryptol.net  :? for help

Loading module Cryptol
Loading module Main
Main> :prove \(x : T) -> False
Counterexample
(\(x : T) -> False) {x = 0x0000, y = 0x00000000} = False
(Total Elapsed Time: 0.016s, using "Z3")

Then the counterexample is printed as a value of type {x : [16], y : [32]} rather than as a value of type T.

@sauclovian-g
Copy link
Collaborator Author

I've seen that, and I don't think I ever noticed the missing T. FWIW.

Does that mean SAW gets the type as a plain record without the newtype name?

@RyanGlScott
Copy link
Contributor

Does that mean SAW gets the type as a plain record without the newtype name?

I'm a bit fuzzy on the details, but I believe that after Cryptol's typechecking phase, newtype values look exactly like record values. That being said, I do believe that the distinction between newtype types and record types is kept, given that we record the existence of newtypes in the post-typechecked AST (here).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
subsystem: cryptol-saw-core Issues related to Cryptol -> saw-core translation with cryptol-saw-core tech debt Issues that document or involve technical debt topics: error-handling Issues involving the way SAW responds to an error condition topics: error-messages Issues involving the messages SAW produces on error usability An issue that impedes efficient understanding and use
Projects
None yet
Development

No branches or pull requests

3 participants