From 0211f5d73c5fe261534b0f84ed0e7d131b62d324 Mon Sep 17 00:00:00 2001 From: Saoirse Aronson Date: Fri, 10 Apr 2026 12:25:21 +0200 Subject: [PATCH] Compute variable shadow check with linear scan Closure parameters will always be an extremely small N (usually one, sometimes two); constructing two HashSets and iterating the intersection is wasteful vs a linear scan over the closure parameters. --- biscuit-auth/src/datalog/expression.rs | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/biscuit-auth/src/datalog/expression.rs b/biscuit-auth/src/datalog/expression.rs index ee06da75..1938da37 100644 --- a/biscuit-auth/src/datalog/expression.rs +++ b/biscuit-auth/src/datalog/expression.rs @@ -9,7 +9,7 @@ use super::{SymbolTable, TemporarySymbolTable}; use regex::Regex; use std::sync::Arc; use std::{ - collections::{HashMap, HashSet}, + collections::HashMap, convert::TryFrom, }; @@ -625,13 +625,7 @@ impl Expression { Some(StackElem::Closure(params, right_ops)), Some(StackElem::Term(left_term)), ) => { - if values - .keys() - .collect::>() - .intersection(¶ms.iter().collect()) - .next() - .is_some() - { + if params.iter().any(|p| values.contains_key(p)) { return Err(error::Expression::ShadowedVariable); } let mut values = values.clone(); @@ -648,13 +642,7 @@ impl Expression { Some(StackElem::Term(right_term)), Some(StackElem::Closure(params, left_ops)), ) => { - if values - .keys() - .collect::>() - .intersection(¶ms.iter().collect()) - .next() - .is_some() - { + if params.iter().any(|p| values.contains_key(p)) { return Err(error::Expression::ShadowedVariable); } let mut values = values.clone();