Normalize Cryptol types on import #1790
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Cryptol has a normalization procedure for types. One of the things this procedure does is to put constants in types on the left. For example, if partial instantiation leads to a type that looks like
n * 3
, the type will be rewritten to3 * n
. Consider partially instantiatingsplit
:Now consider the Cryptol term
\x -> split`{each=3} x
- in particular, consider importing this term into SAWCore. Cryptol typechecking and type normalization is performed on the term at large. SAW then steps in to convert this expression to a term in Core, which involves lightweight interaction with the type environment Cryptol has built.When SAW sees
split`{each=10}
and needs its type, it usesCryptol.TypeCheck.TypeOf.fastTypeOf
, which reports that it is[parts * each]a -> [parts][each]a
instantiated whereeach
maps to3
. That instantiation is performed without normalization (viaCryptol.TypeCheck.TypeOf.simpleSubst
), leading to a type that looks like[parts * 3]a -> [parts][3]a
.When SAW sees
x
in argument or value position, it usesfastTypeOf
again, which delegates to the typing environment that Cryptol has built with normalization, and reports thatx
's type is[3 * parts]a
.Since these terms are not "the same", SAW resorts to type coercion to construct its Core representation, and ends up with something that looks like this:
These coercions are plainly unnecessary, though not technically unsound. Whether or not this constitutes a bug, it is certainly unexpected behavior, and impacts usability of conducting Cryptol proofs in SAW. I see two ways to fix this.
The first, which I've done here, is to apply Cryptol's type normalization procedure (via
Cryptol.TypeCheck.SimpType.tRebuild
) when SAW imports Cryptol types as Core terms. This doesn't actually avoid generating coercions during the conversion process, but causes coercions to citeRefl
as evidence for their validity, which (it seems) lets them be eliminated automatically elsewhere in the conversion process. With this fix in place, SAW now generates Core for\x -> split`{each=3} x
that looks like:The second is to apply the same normalization in
fastTypeOf
, within Cryptol. I didn't do this for fear that it would subvert the "fast" nature of that function, and because I don't have a good sense of the ripple effect that change might produce, but it may be better at encapsulating Cryptol's notion of type normalization than my fix here.(Forgive the amount of text accompanying such a small change - writing this helped me better understand SAWCore and Cryptol, and I hope it may do the same for others.)