Comprehensive backend-independent counterexamples - #883
Merged
Conversation
marcoeilers
marked this pull request as ready for review
July 15, 2026 22:33
marcoeilers
commented
Jul 21, 2026
Aurel300
reviewed
Aug 3, 2026
There was a problem hiding this comment.
Pull request overview
This PR adds a shared, backend-independent counterexample representation (raw + resolved) and wires it into the Silver frontend/AST so both Silicon and Carbon can emit a common counterexample format, with new tests to validate reported store/heap values and permissions.
Changes:
- Introduces new counterexample data model (
RawCounterexample/ResolvedCounterexample) and value parsing utilities, plus a permissionRational. - Extends the Viper AST and pretty-printer with counterexample-only literals (
RefLit,BackendValueLit) and updates magic-wand structure generation to support unique placeholder names. - Adds expected-counterexample test annotations and a large set of
.vprregression tests covering values, permissions, collections, quantified permissions, predicates, and magic wands.
Reviewed changes
Copilot reviewed 33 out of 33 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/main/scala/viper/silver/verifier/Counterexample.scala | New backend-independent counterexample model types + value/permission parsing utilities. |
| src/main/scala/viper/silver/frontend/SilFrontEndConfig.scala | Adds `--counterexample raw |
| src/main/scala/viper/silver/ast/Expression.scala | Adds counterexample-only literal nodes; updates magic-wand structure generation (optional unique naming). |
| src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala | Pretty-prints new counterexample literal nodes. |
| src/main/scala/viper/silver/testing/BackendTypeTest.scala | Adds MPL header/copyright header. |
| src/test/scala/ExpectedCounterexampleAnnotation.scala | New annotation + parser to assert expected resolved counterexample content in tests. |
| src/test/scala/CounterexampleVariablesTests.scala | Removes duplicated parser/model definitions (now shared via new test file). |
| src/test/resources/counterexample_mapped/simple-refs.vpr | New mapped counterexample test for reference field values. |
| src/test/resources/counterexample_mapped/simple-refs-rec.vpr | New mapped counterexample test for locals/returns with refs. |
| src/test/resources/counterexample_mapped/sequence.vpr | New mapped counterexample test for sequence updates/element equality. |
| src/test/resources/counterexample_mapped/ref-sequence.vpr | New mapped counterexample test for sequence field lookup on refs. |
| src/test/resources/counterexample_mapped/predicate.vpr | New mapped counterexample test for predicate unfolding/field values. |
| src/test/resources/counterexample_mapped/permissions.vpr | New mapped counterexample test for insufficient permission assignments. |
| src/test/resources/counterexample_mapped/negative.vpr | New mapped counterexample test for negative integer values. |
| src/test/resources/counterexample_mapped/method-call.vpr | New mapped counterexample test for call precondition failures. |
| src/test/resources/counterexample_mapped/lseg.vpr | New mapped counterexample test for list-segment unfolding/permissions. |
| src/test/resources/counterexample_mapped/functions.vpr | New mapped counterexample test for function applications in counterexamples. |
| src/test/resources/counterexample_mapped/cyclic-ref.vpr | New mapped counterexample test for cyclic reference structures. |
| src/test/resources/counterexample_general/two_qp_same_field.vpr | New general test for summed quantified permissions on the same location. |
| src/test/resources/counterexample_general/sets.vpr | New general test for set value equality reporting. |
| src/test/resources/counterexample_general/sequences.vpr | New general tests for sequence element-wise reporting (incl. negatives). |
| src/test/resources/counterexample_general/qpred.vpr | New general test for quantified predicate permissions from multiple sources. |
| src/test/resources/counterexample_general/qfield.vpr | New general test for quantified field values reported at specific receivers. |
| src/test/resources/counterexample_general/predicate_permissions.vpr | New general tests for predicate permission amounts (non-QP). |
| src/test/resources/counterexample_general/predicate_permissions_qp.vpr | New general tests for predicate permission amounts under quantified permissions. |
| src/test/resources/counterexample_general/multisets.vpr | New general test for multiset value equality reporting. |
| src/test/resources/counterexample_general/maps.vpr | New general test for map value equality reporting. |
| src/test/resources/counterexample_general/magic_wands.vpr | New general test validating counterexamples after applying magic wands. |
| src/test/resources/counterexample_general/local_values.vpr | New general tests for local/param values (ints, negatives, refs, reassignment). |
| src/test/resources/counterexample_general/field_values.vpr | New general tests for field values on one/two objects and multiple fields. |
| src/test/resources/counterexample_general/field_values_qp.vpr | New general tests for field values under quantified permissions (set/seq/indexed). |
| src/test/resources/counterexample_general/field_permissions.vpr | New general tests for fractional field permission reporting (non-QP). |
| src/test/resources/counterexample_general/field_permissions_qp.vpr | New general tests for fractional field permission reporting under various QP forms. |
Suppressed comments (1)
src/main/scala/viper/silver/verifier/Counterexample.scala:211
- Same issue here:
map(...)mkString(...)is missing a.beforemkString, which will fail compilation. Add.mkString(...).
het match {
case PredicateType =>
s"Heap entry: ${reference.mkString("(", ", ", ")")} + ${field.mkString("(", ", ", ")")} --> (Permission: ${perm.getOrElse("None")}) ${if (insidePredicate.isDefined && !insidePredicate.get.isEmpty) insidePredicate.get.toSeq.map(x => s"${x._1} --> ${x._2}")mkString("{\n ", "\n ", "\n}") else ""}"
case _ => s"Heap entry: ${reference.mkString("(", ", ", ")")} + ${field.mkString("(", ", ", ")")} --> (Value: $valueID, Permission: ${perm.getOrElse("None")})"
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
This PR introduces a shared, backend-independent counterexample format in Silver, produced by both Silicon and Carbon. A counterexample is built in two layers:
RawCounterexample): the information collected from the backend model in a simple form, with heap resources still identified by backend-internal (SMT) identifiers.ResolvedCounterexample): the human-readable form; heap resources are bound to their AST nodes (fields, predicates, magic wands) and values are ordinary Viper AST expressions.Values are represented as normal Viper AST expressions (
ast.Exp). The two new AST nodesRefLit(a concrete reference) andBackendValueLit(an otherwise opaque backend value) cover things that have no ordinary Viper syntax.Select the layer on the command line:
--counterexample resolved(orraw). Silicon additionally requires--exhaleMode 1.Example:
The resolved counterexample shown to the user:
Seq(10, #undefined),Set(1, 2, 3),Multiset(7, 7, 8),Map(1 := 100));#undefinedmarks an entry the model does not pin down.Other resource kinds render analogously; a magic wand appears as the wand itself, e.g. Magic Wand Entry:
acc(x.f, 1/2) --* acc(x.f, 1/1) (Perm: 1/1), and (domain) function values are listed under a separate section, e.g.The same format is emitted by both Silicon and Carbon, so the two agree modulo backend-internal reference names (
$Ref!val!0vsT@U!val!0).This is the result of @rvandoren's practical work project, with a bunch of additions from me.