-
Notifications
You must be signed in to change notification settings - Fork 273
Make sure free symbols are declared in SMT2_conv after quantifier rewriting #8361
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
Conversation
791aefe
to
7e5d539
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #8361 +/- ##
========================================
Coverage 78.34% 78.35%
========================================
Files 1726 1726
Lines 188415 188424 +9
Branches 18248 18248
========================================
+ Hits 147623 147631 +8
- Misses 40792 40793 +1 ☔ View full report in Codecov by Sentry. |
I will pull this change, rebuild and retry on all my test cases this morning. |
Please note that the quantified symbols do not need to be unique. As in SMT-LIB, quantifiers introduce a local scope. I hence suspect that the problem is something else, possibly after instantiating the quantifier expressions incorrectly. |
Sorry I wasn't clear in the description. The universal quantified expression in assertion will later be rewritten to non-quantified expression. If such bounded symbols (and later become unbounded after the rewriting) in assertions are not unique, i.e., have the same name as the bounded symbols in some previous assumptions, the |
This should be fixed when doing the rewriting, not before. |
I believe the rewriting in |
I'd propose the following patch instead (making the regression test pass as expected): diff --git a/src/solvers/smt2/smt2_conv.cpp b/src/solvers/smt2/smt2_conv.cpp
index d132114cb2..45f525e3fb 100644
--- a/src/solvers/smt2/smt2_conv.cpp
+++ b/src/solvers/smt2/smt2_conv.cpp
@@ -4908,17 +4908,30 @@ void smt2_convt::find_symbols(const exprt &expr)
if(expr.id() == ID_exists || expr.id() == ID_forall)
{
+ std::unordered_map<irep_idt, std::optional<identifiert>> hidden_syms;
+
// do not declare the quantified symbol, but record
// as 'bound symbol'
const auto &q_expr = to_quantifier_expr(expr);
for(const auto &symbol : q_expr.variables())
{
const auto identifier = symbol.get_identifier();
- identifiert &id = identifier_map[identifier];
- id.type = symbol.type();
- id.is_bound = true;
+ auto id_entry = identifier_map.insert({identifier, identifiert{}});
+ hidden_syms.insert(
+ {identifier,
+ id_entry.second ? std::nullopt
+ : std::optional{id_entry.first->second}});
+ id_entry.first->second.is_bound = true;
}
find_symbols(q_expr.where());
+ for(const auto &[id, hidden_val] : hidden_syms)
+ {
+ auto previous_entry = identifier_map.find(id);
+ if(!hidden_val.has_value())
+ identifier_map.erase(previous_entry);
+ else
+ previous_entry->second = std::move(*hidden_val);
+ }
return;
}
@@ -4943,7 +4956,7 @@ void smt2_convt::find_symbols(const exprt &expr)
identifiert &id=identifier_map[identifier];
- if(id.type.is_nil())
+ if(!id.is_bound && id.type.is_nil())
{
id.type=expr.type(); |
Thank you Michael, I applied your patch and undo the changes in symex. |
It's ok to have a symbol both bound and free, what's the issue? |
It should be ok, but SMT conversion's |
"Unique quantified symbols" is a non goal! |
That's also not what the code change actually does, it rather does the opposite. |
I changed the commit message and the title of this PR to make them align with the actual change. |
…riting A bound variable may shadow another free or bound variable.
Resolve #8329 in which CBMC with SMT2 fails on nested loop contracts with quantifiers.
We only kept quantified symbols unique during
symex_assert
.Once there are some assertion containing quantified symbols
x
following an assumption also containingx
,symex_assume
won't make the twox
distinct.This PR record and keep quantified symbols unique also in
symex_assume
.