Eliminating polymorphism in Boogie #195
Replies: 11 comments 2 replies
-
Dear Shaz, I am not sure I fully understand your post. Are you suggesting to find a different encoding of polymorphic types or are you proposing to drop polymorphism from the Boogie type system altogether (possibly going back to an "any" type like in the initial version of Boogie)? |
Beta Was this translation helpful? Give feedback.
-
I was being vague in the initial post. Thanks for the response and the suggestion to sharpen the discussion. I would like to remove the "polymorphic map" feature entirely. This feature is much more complex than the rest of polymorphic Boogie, which is based on parametric polymorphism found in other languages. The polymorphic map feature was added to address a specific use case: encoding the heap of an object-oriented language. However, this feature was not enough to address the encoding needs of Dafny and more encoding had to be done on top of it. In summary, this feature is complex, narrow, and inadequate. I am unsure about what to do about the other polymorphic features in Boogie. The current situation is untenable because even the translation of a Boogie program that does not use type parameters introduces quantifiers in the verification condition. To avoid quantifiers for a non-generic Boogie program, the user has to use the command-line flag /typeEncoding:m, a poorly-understood hack implemented by me many years ago. There is also another related mysterious flag /monomorphize whose purpose is unclear to me. Overall, the Boogie community should try to answer the following questions:
If the answer to either question above is Yes, then we should answer the following question:
|
Beta Was this translation helpful? Give feedback.
-
Hi Shaz and all, Thanks a lot for raising the topic and explaining in so much detail. Sorry that I'm a bit late to the party, but I'm hopefully getting up to speed now that I'm back online. In short, my opinion is that I'd really like polymorphism to stay in Boogie in some form. I have basically two reasons, which correspond to your two questions in your last post. Firstly, we use Boogie's polymorphism for one of the two main verification pathways in Viper. We have two verifiers for Viper programs: one performs symbolic execution and interacts directly with Z3; the other translates Viper programs to Boogie programs and verifies them with the standard Boogie verifier. In the Boogie-based verifier, we use polymorphic features for the following (I'm assuming types with parameters are included in the discussion, as well as explicit quantification over types):
I think point 5 is the hardest to work around, in the sense that I'm not even sure what one would do as an alternative. In fact, in our symbolic execution verifier we have exactly this issue: since we interact directly with Z3 we don't have the luxury of Boogie's polymorphic types for handling type instantiations. Instead, we've attempted to pre-instantiate the polymorphic types in the input Viper program, using a heuristic approach which we believed to be complete in practice, but have since found to create issues in certain examples, which are then hard to debug (e.g. this issue). Of course, it ought somehow to be possible to lift/generalise the approach that Boogie currently uses to the Viper level, but that would seem a shame to have to do. For the other points (particularly 1-3) above, I'm pretty sure there would be workarounds that would make our encoding a lot more verbose. My recollection from developing/working on these encodings is that particularly the places where we used Boogie's polymorphic features were quite prone to trivial mistakes (e.g. by me), and that Boogie's type checker called us out on these. I'm a bit afraid that those mistakes would in some cases become subtle verification errors instead (although I haven't thought the alternatives through fully yet), and if so that would certainly be scary. As a less important remark, we have also considered trying out exchanging alternative heap/map representations in our Boogie encoding (cf. Böhme and Moskal's quite old paper); it's currently quite straightforward (if a little tedious) to go between situations in which we use several related maps with slightly different signatures or one map to rule them all with a signature coerced to subsume them (using extra type parameters to simulate unions, as in point 2), and vice versa. I don't think this would be the case any more without polymorphism (effectively one would be forced into the more verbose many-maps representation, or else forced to have less actually type checking performed by using a more-coarse type encoding (which I think will lead to subtle bugs). So far we didn't encounter any limitations with respect to what we wanted to encoding in Boogie (perhaps some things would be more natural with (tagged) union types, but considering how much indirect modelling is already done, it doesn't really seem warranted). I'd be interested to understand what limitations were hit when trying to reuse these features for Dafny, but for Viper (which is still an intermediate language with quite simple types), Boogie's polymorphism is currently a great fit. Finally (this is the top-level "Secondly"!), I've used Boogie for teaching (as the middle of the toolchain used in this course). In particular, I use it for teaching how to model program verification constructs, and to head towards the kind of verification we do by modelling program heaps of various kinds. I use polymorphism in simplified ways of all of the points above, I think, and it makes the code extremely clear to read and teach. If this weren't possible any more, I'm not sure what I'd use instead; Viper doesn't have maps built in (and builds in a heap, so simulating a heap with maps seems a bit strange); I guess I could use Dafny directly, but for teaching the role of an intermediate verification language in this toolchain, it seems a strange choice. Well, that got kind of long, but hopefully it helps the discussion. As a potential remark in the other direction, I do often observe that slow examples we debug with the Axiom Profiler tend to have tons of instantiations of type-related Boogie-generated axioms. But I wasn't yet able to persuade myself that this was the actual cause of performance issues in any of the debugged examples (they all had non-trivial other axioms which were instantiated a lot, and seem to contribute more more-relevant terms to the e-graph). |
Beta Was this translation helpful? Give feedback.
-
I realise I didn't answer your last question. I'd be very happy to brainstorm on this together sometime if it would be useful! Just as a basic question, is there a reason why current Boogie couldn't simply omit various internally-generated axioms when the input program doesn't make use of polymorphic features? |
Beta Was this translation helpful? Give feedback.
-
Kind of related to this, Boogie has a So I would say that setting This was probably done so that Boogie does not introduce auxiliary axioms related to polymorphism when they are not needed, meaning then the input program is monomorphic. |
Beta Was this translation helpful? Give feedback.
-
@zvonimir is working on a PR #234 that will clean up the menagerie of command-line options related to monomorphic type encoding. Once this PR lands, the issue of monomorphic Boogie will be settled. If the input program is monomorphic, then automatically no type encoding will Question: Boogie currently supports polymorphic maps such as the following: |
Beta Was this translation helpful? Give feedback.
-
If we keep the support for polymorphic features in Boogie, is there any interest in an encoding that compiles away the polymorphic features via code duplication? On one hand, such an encoding is likely to be simpler since it continues to use the native types supported by solvers. On the other hand, code duplication will result in many more verification conditions being generated. |
Beta Was this translation helpful? Give feedback.
-
Just to be clear, polymorphic maps will work even after the pull request gets merged in (I did not change that part), but not with the theory of arrays ( @alexanderjsummers I think it would be a good to add a few small Viper-generated regressions into the Boogie repo that contain most, if not all, of the Boogie features and flags you rely on. That would guard against someone breaking the features you guys use. Just my 2 cents. |
Beta Was this translation helpful? Give feedback.
-
I guess I can speak for @alexanderjsummers (I am also part of the Viper team). Yes, we do. For example, we have the following type for the heap:
This is not the only place where we use polymorphic maps. @zvonimir That's a good point, thanks! I'll make a pull request. |
Beta Was this translation helpful? Give feedback.
-
Boogie (master branch) now supports monomorphization of functions, procedures, and implementations. You can take a look at the folder Test/monomorphize and file Test/inst/vector_generic.bpl for examples. You can also see the monomorphized program for yourself by using the option /printInstrumented. The current implementation supports polymorphic axioms in a limited way but I can generalize it to handle all polymorphic axioms in which all quantifiers in the negative normal formal of the axiom are universal. I don't know how to handle polymorphic type parameters in any other situation. Finally, I made an attempt to understand polymorphic maps. I am attaching a file with an initial attempt to monomorphize a simple program manually. Since I am unsure of the semantics, what I am doing there is an educated guess which I would love for you folks to confirm or refute. Original program:
Monomorphized program:
|
Beta Was this translation helpful? Give feedback.
-
The goal of monomorphic encoding was achieved without eliminating any polymorphic features. Closing this discussion. |
Beta Was this translation helpful? Give feedback.
-
The implementation of polymorphism in Boogie is complex because it introduces quantifiers and encodes all types into a single type. This complexity discourages Boogie users from exploiting this potentially useful feature. At the same time, the existing implementation is inadequate for fully encoding source-level polymorphism of a language such as Dafny. It is time to revisit the feature, potentially eliminate the current implementation, and start afresh. I am creating this issue so any users of could voice their concerns.
@RustanLeino : Thoughts? If you know of other users of Boogie polymorphism, please inform them that we are considering dropping support for this feature.
Beta Was this translation helpful? Give feedback.
All reactions