@@ -1179,10 +1179,9 @@ pub type Transform<C = ()> = Box<
11791179
11801180/// Predicate evaluated after a rule's query matches and before its transform
11811181/// runs. Returning `false` makes the rule behave as if its query did not
1182- /// match, so the driver continues to the next rule. The user context is a
1183- /// private clone for this rule attempt; mutations are retained for the
1184- /// transform when the guard succeeds and discarded when it fails.
1185- pub type Guard < C = ( ) > = Box < dyn Fn ( & Ast , & Captures , & mut C ) -> Result < bool , String > + Send + Sync > ;
1182+ /// match, so the driver continues to the next rule. Guards have read-only
1183+ /// access to the shared user context.
1184+ pub type Guard < C = ( ) > = Box < dyn Fn ( & Ast , & Captures , & C ) -> Result < bool , String > + Send + Sync > ;
11861185
11871186pub struct Rule < C = ( ) > {
11881187 query : QueryNode ,
@@ -1202,8 +1201,8 @@ impl<C> Rule<C> {
12021201 }
12031202 }
12041203
1205- /// Construct a guarded rule. The guard sees raw captures and shares its
1206- /// private user-context clone with the transform when it succeeds .
1204+ /// Construct a guarded rule. The guard sees raw captures and has read-only
1205+ /// access to the user context .
12071206 pub fn guarded ( query : QueryNode , guard : Guard < C > , transform : Transform < C > ) -> Self {
12081207 Self {
12091208 query,
@@ -1230,12 +1229,7 @@ impl<C> Rule<C> {
12301229
12311230 /// Evaluate this rule's guard against a successful query match. An
12321231 /// unguarded rule always succeeds.
1233- fn guard_matches (
1234- & self ,
1235- ast : & Ast ,
1236- captures : & Captures ,
1237- user_ctx : & mut C ,
1238- ) -> Result < bool , String > {
1232+ fn guard_matches ( & self , ast : & Ast , captures : & Captures , user_ctx : & C ) -> Result < bool , String > {
12391233 if let Some ( guard) = & self . guard {
12401234 guard ( ast, captures, user_ctx)
12411235 } else {
@@ -1327,15 +1321,14 @@ fn apply_rules_inner<C: Clone>(
13271321 continue ;
13281322 } ;
13291323
1330- // Clone only after the query matches, but before the guard runs.
1331- // Guard mutations are visible to the transform and transitively-
1332- // translated captures when the guard succeeds; a failed guard drops
1333- // the clone before trying the next rule.
1334- let mut local = user_ctx. clone ( ) ;
1335- if !rule. guard_matches ( ast, & captures, & mut local) ? {
1324+ if !rule. guard_matches ( ast, & captures, user_ctx) ? {
13361325 continue ;
13371326 }
13381327
1328+ // The transform gets a private context clone. Its mutations are visible
1329+ // to transitively translated captures, but not to sibling rule attempts.
1330+ let mut local = user_ctx. clone ( ) ;
1331+
13391332 // Build the translator handle the transform will use to recursively
13401333 // translate captured input nodes when they are consumed.
13411334 let translator = TranslatorHandle {
0 commit comments