8000 fix(magic-sets): keep preceding rule calls in magic propagation rules (#297) by adityamukho · Pull Request #409 · project-minigraf/minigraf · GitHub
[go: up one dir, main page]

Skip to content

fix(magic-sets): keep preceding rule calls in magic propagation rules (#297) - #409

Merged
adityamukho merged 1 commit into
mainfrom
fix/297-magic-sets-rule-call
Sep 26, 2026
Merged

adityamukho merged 1 commit into
mainfrom
fix/297-magic-sets-rule-call

Conversation

@adityamukho
Copy link
Copy Markdown
Collaborator

Closes #297.

Problem

With a literal start, a recursive rule whose intermediate variable is bound by a call to another user rule failed:

(rule [(link ?x ?y) [?x :next ?y]])
(rule [(chain ?x ?y) (link ?x ?y)])
(rule [(chain ?x ?y) (link ?x ?mid) (chain ?mid ?y)])
(query [:find ?y :where (chain :a ?y)])  ; INT-022: Unbound variable in rule head: ?mid

build_propagation_rules built each magic propagation rule from the guard plus only the non-invocation clauses before the call, producing (__magic_chain_bf ?mid) :- (__magic_chain_bf ?x). (link ?x ?mid), the only binder of ?mid, was dropped. #300 fixed only the fact-pattern case.

Fix

Keep every preceding clause, including rule invocations, as in standard magic-sets rewriting. All rewritten rules are positive (rules with negation are left unrewritten), so the extra dependency on the guarded called predicate is safe.

Tests

  • tests/magic_sets_test.rs: the reopened repro, checked against the pattern-bound form that does not use magic sets; plus a left-recursive variant ((path ?x ?mid) (link ?mid ?y)), which failed the same way.
  • Unit test pinning the propagation-rule body.
  • 1195 passed, 0 failed, 8 ignored; cargo clippy -- -D warnings clean.

Unblocks project-minigraf/minigraf-playground#40 (sl3-s3, t3-s3).

🤖 Generated with Claude Code

https://claude.ai/code/session_01BedF9ZmqVZLkvDwn91fuKy

…#297)

A recursive rule whose intermediate variable is bound by a call to another
user rule, e.g. (chain ?x ?y) :- (link ?x ?mid) (chain ?mid ?y), failed
with "Unbound variable in rule head: ?mid" (INT-022) when queried with a
literal first argument such as (chain :a ?y).

build_propagation_rules built the magic rule for the recursive call from
the guard plus only the non-RuleInvocation clauses preceding it, so it
emitted (__magic_chain_bf ?mid) :- (__magic_chain_bf ?x) with ?mid unbound.
#300 fixed only the case where a fact pattern binds the intermediate.

Keep every preceding clause, including rule invocations, as standard
magic-sets rewriting does. All rewritten rules are positive, so the added
dependency on the (guarded) called predicate is safe.

Adds integration tests for the reopened repro and a left-recursive variant,
and a unit test pinning the propagation-rule body.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BedF9ZmqVZLkvDwn91fuKy
@adityamukho adityamukho added this to the v2.0.2 milestone Sep 26, 2026
@codecov
codecov Bot commented Sep 26, 2026
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@adityamukho
adityamukho merged commit e78d287 into main Sep 26, 2026
17 checks passed
@adityamukho
adityamukho deleted the fix/297-magic-sets-rule-call branch September 26, 2026 09:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: magic sets rewriting rejects intermediate variables when first rule arg is bound by literal keyword

1 participant

0