Skip to content

Commit 5743b4a

Browse files
authored
fix(evaluator): update lazy scope cache when variable is reassigned (#2075)
fix(evaluator): update lazy scope cache when variable is reassigned (fixes #2074) When a variable is reassigned with a new ValueRef (for example, via |= which creates a new value via deep_copy), force update the lazy scope cache to avoid stale references in subsequent subscript assignments. Signed-off-by: John Gardiner Myers <jgmyers@proofpoint.com>
1 parent b36755c commit 5743b4a

File tree

10 files changed

+57
-1
lines changed

10 files changed

+57
-1
lines changed

crates/evaluator/src/lazy.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,4 +389,18 @@ impl<'ctx> Evaluator<'ctx> {
389389
scope.cache.insert(key.to_string(), value.clone());
390390
}
391391
}
392+
393+
/// Force update the lazy scope cache with a new value.
394+
/// This is used when a variable is reassigned with a new ValueRef
395+
/// (for example, via |= which creates a new value via deep_copy)
396+
/// to avoid stale references in subsequent subscript assignments.
397+
#[inline]
398+
pub(crate) fn update_lazy_scope_cache(&self, pkgpath: &str, key: &str, value: &ValueRef) {
399+
let mut lazy_scopes = self.lazy_scopes.borrow_mut();
400+
if let Some(scope) = lazy_scopes.get_mut(pkgpath) {
401+
if scope.cache.contains_key(key) {
402+
scope.cache.insert(key.to_string(), value.clone());
403+
}
404+
}
405+
}
392406
}

crates/evaluator/src/scope.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,10 @@ impl<'ctx> Evaluator<'ctx> {
330330
if variables.get(&name.to_string()).is_some() {
331331
variables.insert(name.to_string(), value.clone());
332332
if save_lazy_scope {
333-
self.set_value_to_lazy_scope(&current_pkgpath, name, &value)
333+
self.set_value_to_lazy_scope(&current_pkgpath, name, &value);
334+
// Also force update the cache to avoid stale references when
335+
// the variable is reassigned with a new value (for example, via |=)
336+
self.update_lazy_scope_cache(&current_pkgpath, name, &value);
334337
}
335338
existed = true;
336339
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Test for issue #2074: augmented assignment followed by subscript assignment
2+
# in if block caused the subscript assignment to be silently ignored.
3+
4+
_map = {}
5+
if True:
6+
_map |= {a: 1}
7+
_map["b"] = 2
8+
result = _map
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
result:
2+
a: 1
3+
b: 2
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Test for issue #2074: binary | reassignment followed by subscript assignment in if block
2+
_map = {}
3+
if True:
4+
_map = _map | {a: 1}
5+
_map["b"] = 2
6+
result = _map
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
result:
2+
a: 1
3+
b: 2
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Test for issue #2074: multiple subscript assignments after |= in if block
2+
_map = {}
3+
if True:
4+
_map |= {a: 1}
5+
_map["b"] = 2
6+
_map["c"] = 3
7+
result = _map
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
result:
2+
a: 1
3+
b: 2
4+
c: 3
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Test for issue #2074: |= on list followed by subscript assignment in if block
2+
_list = []
3+
if True:
4+
_list |= [1]
5+
_list[0] = 99
6+
result = _list
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
result:
2+
- 99

0 commit comments

Comments
 (0)