You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This discussion proposes formal specifications (class invariants, pre/post-conditions) to improve code correctness and maintainability for core Z3 utility data structures.
Rationale: The number of elements must never exceed allocated capacity. This is fundamental to preventing buffer overflows and maintaining memory safety.
Placement: Add to a check_invariant() method called after state-modifying operations
Rationale: Ensures proper alignment of stored elements, critical for correctness on architectures with strict alignment requirements and for performance.
Rationale: Guarantees forward progress in capacity growth, preventing infinite loops
Method: reset() / clear()
Post-condition: Size is zero
Assertion: SASSERT(size() == 0)
Rationale: Ensures the vector is properly cleared
2. core_hashtable Class (src/util/hashtable.h)
Class Invariants
The class already has a comprehensive check_invariant() method (lines 640-669) that validates:
✅ Capacity is a power of two
✅ m_num_deleted + m_size <= m_capacity
✅ m_num_deleted <= m_size
✅ Actual count of deleted/used entries matches metadata
Additional Invariants Proposed
Invariant 1: Non-null Table Pointer
Assertion: SASSERT(m_table != nullptr)
Rationale: The table pointer should never be null after construction. Current design always allocates at least DEFAULT_HASHTABLE_INITIAL_CAPACITY (8) entries.
Rationale: Capacity should never fall below the initial capacity unless in OOM state
Placement: In check_invariant() method
Invariant 3: Load Factor Upper Bound
Assertion: SASSERT((m_size + m_num_deleted) * 4 <= m_capacity * 3 + 1) (relaxed by 1 for off-by-one)
Rationale: The hash table maintains a load factor of at most 75% (3/4) to ensure good performance. This is enforced by expand_table() but worth checking as an invariant.
Placement: After insert() operations complete
Pre-conditions
Method: insert(data && e)
Pre-condition: Hash function doesn't cause overflow
Note: This is implicitly assumed but difficult to assert without access to the hash computation
Current Status: Relies on well-behaved HashProc
Method: expand_table() - NEW
Pre-condition: Not in out-of-memory state (for reliability)
Assertion: SASSERT(!memory::is_out_of_memory())
Rationale: Expanding in OOM state is futile and could cause issues
Post-conditions
Method: insert(data const & e) - NEW
Post-condition: Element is in the table
Assertion: SASSERT(contains(e))
Rationale: Verifies successful insertion (but note: expensive, should be #ifdef DEBUG)
Note: Current assertion at line 569 checks !contains(e) before insertion in insert_if_not_there_core, which is good
This is a smaller class but with critical scope-management invariants.
Class Invariants
Invariant 1: Monotonic Scope Sizes
Assertion:
boolcheck_scope_invariant() const {
for (unsigned i = 1; i < m_lim.size(); ++i) {
SASSERT(m_lim[i-1] <= m_lim[i]);
}
returntrue;
}
Rationale: Scope boundaries must be monotonically increasing - each new scope starts at or after the previous scope's boundary. This is fundamental to the backtracking mechanism.
Placement: Called at the end of push_scope() and pop_scope()
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
✨ Automatic Specification Mining
This discussion proposes formal specifications (class invariants, pre/post-conditions) to improve code correctness and maintainability for core Z3 utility data structures.
📋 Classes Analyzed
vector(T)insrc/util/vector.hcore_hashtableinsrc/util/hashtable.hlim_svector(T)insrc/util/lim_vector.h🔍 Specifications Proposed
1.
vector(T)Class (src/util/vector.h)Class Invariants
Invariant 1: Size-Capacity Relationship
SASSERT(m_data == nullptr || size() <= capacity())check_invariant()method called after state-modifying operationsInvariant 2: Null Pointer Consistency
SASSERT(m_data != nullptr || (size() == 0 && capacity() == 0))m_datais null, both size and capacity must be zero (empty vector state). This ensures consistent representation of empty vectors.check_invariant()methodInvariant 3: Metadata Memory Alignment
SASSERT(m_data == nullptr || reinterpret_cast(uintptr_t)(m_data) % alignof(T) == 0)check_invariant()methodInvariant 4: Capacity Growth Validity
SASSERT(m_data == nullptr || capacity() >= 2)(after first expansion)expand_vector().expand_vector()completesPre-conditions
Method:
operator[](SZ idx)andget(SZ idx)SASSERT(idx < size())Method:
back()SASSERT(!empty())Method:
pop_back()SASSERT(!empty())Method:
erase(iterator pos)SASSERT(pos >= begin() && pos < end())Method:
init(SZ s)- NEWSASSERT(m_data == nullptr)Post-conditions
Method:
push_back(T const & elem)SASSERT(size() == old_size + 1)(requires capturing old_size)Method:
expand_vector()- NEWSASSERT(capacity() > old_capacity)Method:
reset()/clear()SASSERT(size() == 0)2.
core_hashtableClass (src/util/hashtable.h)Class Invariants
The class already has a comprehensive
check_invariant()method (lines 640-669) that validates:m_num_deleted + m_size <= m_capacitym_num_deleted <= m_sizeAdditional Invariants Proposed
Invariant 1: Non-null Table Pointer
SASSERT(m_table != nullptr)DEFAULT_HASHTABLE_INITIAL_CAPACITY(8) entries.check_invariant()methodInvariant 2: Minimum Capacity
SASSERT(m_capacity >= DEFAULT_HASHTABLE_INITIAL_CAPACITY || memory::is_out_of_memory())check_invariant()methodInvariant 3: Load Factor Upper Bound
SASSERT((m_size + m_num_deleted) * 4 <= m_capacity * 3 + 1)(relaxed by 1 for off-by-one)expand_table()but worth checking as an invariant.insert()operations completePre-conditions
Method:
insert(data && e)Method:
expand_table()- NEWSASSERT(!memory::is_out_of_memory())Post-conditions
Method:
insert(data const & e)- NEWSASSERT(contains(e))#ifdef DEBUG)!contains(e)before insertion ininsert_if_not_there_core, which is goodMethod:
reset()- NEWSASSERT(m_size == 0 && m_num_deleted == 0)3.
lim_svector(T)Class (src/util/lim_vector.h)This is a smaller class but with critical scope-management invariants.
Class Invariants
Invariant 1: Monotonic Scope Sizes
push_scope()andpop_scope()Invariant 2: Last Scope Boundary Validity
SASSERT(m_lim.empty() || m_lim.back() <= this->size())m_limor the base vector sizeInvariant 3: Scope Stack Non-negativity
SASSERT(num_scopes() >= 0)(trivially true for unsigned, but documents intent)Pre-conditions
Method:
pop_scope(unsigned num_scopes)SASSERT(num_scopes > 0 && num_scopes <= m_lim.size())num_scopes > 0, should also verifynum_scopes <= m_lim.size()Method:
old_size(unsigned n)- NEWSASSERT(n > 0 && n <= m_lim.size())nmust reference a valid scope in the stackPost-conditions
Method:
push_scope()SASSERT(num_scopes() == old_scope_count + 1)Method:
pop_scope(unsigned num_scopes)- NEWSASSERT(this->size() == m_lim[m_lim.size()])(after restoring old size)shrink()call on line 32🎯 Goals Achieved
Performance Considerations:
lim_svectoris O(n) in scope count - should be#ifdef DEBUGor called selectivelyImplementation Strategy:
check_invariant()methods where missing (e.g., invector(T))#ifndef NDEBUGguards for expensive checksExisting Coverage:
vector(T)already has good pre-condition checking for array accesscore_hashtablealready has a comprehensivecheck_invariant()methodManual Review Needed:
vector(T)may need adjustment based on platform-specific alignment requirementscore_hashtableshould account for edge cases during expansionlim_svectorshould be verified against usage patterns in the SMT solver💡 Recommendations
For
vector(T):check_invariant()method (conditionally compiled)For
core_hashtable:check_invariant()with the additional invariants proposedcheck_invariant()return early ifmemory::is_out_of_memory()to avoid false failurescheck_invariant_fast()for hot pathsFor
lim_svector:📚 Methodology
Specifications synthesized using LLM-based invariant mining inspired by:
🔄 Next Steps
🤖 Generated by SpecBot - Automatic Specification Mining Agent
Analysis Date: 2026-01-27
Commit: Current HEAD
Beta Was this translation helpful? Give feedback.
All reactions