fix: cover outer-scope bracket key handling

Agent-Logs-Url: https://github.com/microsoft/regorus/sessions/992f5462-7cc4-4e4f-bd7f-799308063765

Co-authored-by: anakrish <35780660+anakrish@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-05-07 03:08:59 +00:00
committed by GitHub
parent 5ae1d8abf2
commit eb6e156e8a
6 changed files with 84 additions and 10 deletions

View File

@@ -1757,13 +1757,14 @@ impl Interpreter {
match expr.as_ref() {
Expr::Var { span, .. } => {
// A variable that is not currently bound in local scope behaves like
// A variable that is not currently bound in any active local scope behaves like
// a stable global/package reference for this evaluation.
let scope = self
let is_bound = self
.scopes
.last()
.ok_or_else(|| anyhow!("internal error: no current scope"))?;
Ok(!scope.contains_key(&span.source_str()))
.iter()
.rev()
.any(|scope| scope.contains_key(&span.source_str()));
Ok(!is_bound)
}
Expr::RefDot { refr, .. } => self.is_constant_key_expr(refr),
Expr::RefBrack { refr, index, .. } => {

View File

@@ -181,6 +181,10 @@ impl<'a> Compiler<'a> {
}
fn evaluate_default_rule(&mut self, rule_path: &str) -> Option<u16> {
if !self.may_have_default_rule(rule_path) {
return None;
}
let mut interpreter = Interpreter::new_from_compiled_policy(self.policy.inner.clone());
match interpreter.eval_default_rule_for_compiler(rule_path) {
@@ -196,6 +200,33 @@ impl<'a> Compiler<'a> {
None
}
fn may_have_default_rule(&self, rule_path: &str) -> bool {
if self.policy.inner.default_rules.contains_key(rule_path) {
return true;
}
let Some((parent_path, index)) = rule_path.rsplit_once('.') else {
return false;
};
self.policy
.inner
.default_rules
.get(parent_path)
.is_some_and(|rules| {
rules
.iter()
.any(|(_, rule_index)| match rule_index.as_deref() {
Some(rule_index) if rule_index == index => true,
Some(rule_index) => rule_index
.strip_prefix('"')
.and_then(|rule_index| rule_index.strip_suffix('"'))
.is_some_and(|rule_index| rule_index == index),
None => false,
})
})
}
fn extract_destructuring_blocks(&self, rule_index: u16) -> Vec<Option<u32>> {
self.rule_definition_destructuring_patterns[rule_index as usize].clone()
}

View File

@@ -349,7 +349,7 @@ cases:
package test
import rego.v1
default config["timeout"] := 30
config["timeout"] := input.val if {
config["timeout"] := val if {
val := input.val
}
query: data.test.config.timeout
@@ -364,7 +364,7 @@ cases:
package test
import rego.v1
default config["timeout"] := 30
config["timeout"] := input.val if {
config["timeout"] := val if {
val := input.val
}
query: data.test.config.timeout

View File

@@ -201,6 +201,27 @@ cases:
BAZ: true
FOO: true
- note: partial_object_key_bound_in_outer_scope_v1
data: {}
input:
outer:
FOO: [1, 2]
BAR: [3]
BAZ: []
modules:
- |
package test
import rego.v1
violations[k] if {
some k, arr in input.outer
some _ in arr
}
query: data.test.violations
want_result:
BAR: true
FOO: true
- note: complete_rule_same_value_definitions_still_work_v1
data: {}
input:

View File

@@ -55,7 +55,7 @@ cases:
package test
import rego.v1
default config["timeout"] := 30
config["timeout"] := input.val if {
config["timeout"] := val if {
val := input.val
}
query: data.test.config.timeout
@@ -70,7 +70,7 @@ cases:
package test
import rego.v1
default config["timeout"] := 30
config["timeout"] := input.val if {
config["timeout"] := val if {
val := input.val
}
query: data.test.config.timeout

View File

@@ -186,7 +186,7 @@ cases:
seen contains k if {
some k, _ in input.x
}
main := {
"seen": seen,
"violations": violations,
@@ -200,6 +200,27 @@ cases:
BAZ: true
FOO: true
- note: partial_object_key_bound_in_outer_scope_v1
data: {}
input:
outer:
FOO: [1, 2]
BAR: [3]
BAZ: []
modules:
- |
package test
import rego.v1
violations[k] if {
some k, arr in input.outer
some _ in arr
}
query: data.test.violations
want_result:
BAR: true
FOO: true
- note: complete_rule_same_value_definitions_still_work_v1
data: {}
input: