Expand description
Port of hermes::PersistentScopedMap
(include/hermes/ADT/PersistentScopedMap.h): a scoped hash table similar
to hermes::ScopedHashTable, but scopes can be retained and reactivated
after they have been popped from the table.
The type ScopePtr, which in C++ is an intrusive reference-counting
smart pointer, is used to retain ownership of a scope. The pointer can be
used to reactivate the scope in the table using
PersistentScopedMap::activate_scope.
Scopes can also be re-activated even if they are currently active but are not the current scope. Note however that if there are active scopes in the stack, in the end we must restore the state — the top-most scope in the stack must be active.
Example (mirrors the C++ doc comment):
use hermes_support::persistent_scoped_map::{PersistentScopedMap, Scope, ScopePtr};
let table: PersistentScopedMap<&str, &str> = PersistentScopedMap::new();
let mut ptr: ScopePtr<&str, &str> = ScopePtr::default();
let a = Scope::new(&table);
let b = Scope::new(&table);
// At this point, A and B are active scopes in the table.
// A(active)->B(active)
// We can reactivate A:
table.activate_scope(&a.ptr());
// Now the state is the same as it was when A was active initially.
table.activate_scope(&b.ptr());
// The state has been restored to "normal".
{
let c = Scope::new(&table);
// A(active)->B(active)->C(active)
// Save C for later.
ptr = c.ptr();
}
// A(active)->B(active)
let d = Scope::new(&table);
// A(active)->B(active)->D(active).
// Activate C again.
table.activate_scope(&ptr);
// A(active)->B(active)->C(active)
// Restore normal state.
table.activate_scope(&d.ptr());
ptr.reset();
drop(d);
drop(b);
drop(a);§Deviations from the C++ implementation
support is #![forbid(unsafe_code)], so this port cannot reproduce the
C++ web of raw pointers and an intrusive, manually-maintained reference
count (PersistentScopedMapScopeData::addRef/decRef). Instead:
- A scope’s data (
ScopeData<K, V>, the port ofdetail::PersistentScopedMapScopeData) is held behind anRc.ScopePtrisOption<ScopeRef<K, V>>;Rc’s own strong count replaces the manualrefCount_, andClone/DroponRcreplaceaddRef/decRef— there is nothing left to implement by hand. - The C++
Nodeintrusive linked lists (nextInScope_links every node created in a scope;nextShadowed_links a node to the same-key node it shadows in an ancestor scope) become, per scope, aVec<Entry<K, V>>in insertion order (ScopeData::entries) plus ashadowed: Option<Slot<K, V>>field onEntry(Slot<K, V> = (Rc<ScopeData<K, V>>, usize)) that identifies the shadowed entry by(scope, index)instead of by raw pointer. The map from key to innermost definition (C++map_: DenseMap<K, Node *>) becomesmap: RefCell<HashMap<K, Slot<K, V>>>. - Because each key is inserted at most once per scope (
try_emplacerefuses a second insertion into the same scope), the order in which a scope’s own entries are popped/pushed does not affect observable behavior. This port walksentriesforward (insertion order); the C++ walkshead_/nextInScope_, which is reverse insertion order. Only the internal traversal order differs — not behavior. lookup,find,find_with_depth, andfind_in_current_scopereturn an ownedOption<V>(hence theV: Clonebound) rather than C++’sV*/ default-constructedV(forlookup). Interior mutability (RefCell) means we cannot hand back a reference into the map that outlives the call, so callers get a clone instead.countstill returnsu32(0 or 1), matchingDenseMap::count’s semantics for a unique key.- All
PersistentScopedMapmethods take&self: the map’s mutable state lives inRefCells so it can be shared behind a plain reference, which is what a scope-retaining API needs (aScopeborrows the map for its whole lifetime whileScopePtrs to older scopes may outlive it).
Every method below keeps the corresponding C++ comment (adapted) and the
same assertions, expressed as debug_assert!/assert!.
Structs§
- Persistent
Scoped Map - Scoped hash table similar to
hermes::ScopedHashTable, but scopes can be retained and reactivated after they have been popped from the table. See the module documentation for the full example and for the deviations from the C++ implementation. - Scope
- RAII for creating and popping a scope. Port of
PersistentScopedMapScope. - Scope
Ptr - Smart pointer retaining ownership of a scope so it can be reactivated
after it has been popped from the table. Port of
PersistentScopedMapScopePtr;Rc’s automatic reference counting replaces the manualaddRef/decRefpair.