Skip to content

Commit 6e358d8

Browse files
geo2ajberthold
authored andcommitted
Georgy/fix rule unification (#408)
Closes #406 * Make result indeterminate when trying to bind an already bound variable with a different expression. This was returning a failing result before, causing a soundness bug, because in some cases rules with duplicate variables in LHS would not be applied. * Make result indeterminate when unifying an injection with a variable. This allows us to get a clear remainder instead of a weird swapped substitution item * Only report violating substitution items
1 parent 57cd6f6 commit 6e358d8

File tree

4 files changed

+11
-8
lines changed

4 files changed

+11
-8
lines changed

booster/library/Booster/Pattern/Rewrite.hs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,10 @@ applyRule pat@Pattern{ceilConditions} rule = runRewriteRuleAppT $ do
257257

258258
-- check it is a "matching" substitution (substitutes variables
259259
-- from the subject term only). Fail the entire rewrite if not.
260-
unless (Map.keysSet subst == freeVariables rule.lhs) $
260+
unless (Map.keysSet subst == freeVariables rule.lhs) $ do
261+
let violatingItems = Map.restrictKeys subst (Map.keysSet subst `Set.difference` freeVariables rule.lhs)
261262
failRewrite $
262-
UnificationIsNotMatch rule pat.term subst
263+
UnificationIsNotMatch rule pat.term violatingItems
263264

264265
-- Also fail the whole rewrite if a rule applies but may introduce
265266
-- an undefined term.

booster/library/Booster/Pattern/Unify.hs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,11 @@ unify1
261261
if isSubsort
262262
then bindVariable var term2
263263
else failWith $ DifferentSorts term1 term2
264+
-- term1 is an injection. We could unify, but it would not be a matching substitution: indeterminate
265+
unify1
266+
inj@Injection{}
267+
v@Var{} =
268+
addIndeterminate inj v
264269
-- term2 variable (not target), term1 not a variable: swap arguments (won't recurse)
265270
unify1
266271
term1
@@ -575,7 +580,7 @@ bindVariable var term = do
575580
| otherwise ->
576581
-- the term in the binding could be _equivalent_
577582
-- (not necessarily syntactically equal) to term'
578-
failWith $ VariableConflict var oldTerm term
583+
addIndeterminate oldTerm term
579584
Nothing -> do
580585
let
581586
-- apply existing substitutions to term

booster/unit-tests/Test/Booster/Pattern/Rewrite.hs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,6 @@ unifyNotMatch =
215215
subst =
216216
Map.fromList
217217
[ (Variable someSort "X", dv someSort "otherThing")
218-
, (Variable someSort "Y", d)
219-
, (Variable kSort "RuleVar", var "ConfigVar" kSort)
220218
]
221219
[trm| kCell{}( kseq{}( inj{SomeSort{}, SortKItem{}}( con3{}( X:SomeSort{}, \dv{SomeSort{}}("thing") ) ), ConfigVar:SortK{}) ) |]
222220
`failsWith` UnificationIsNotMatch rule3 t subst

booster/unit-tests/Test/Booster/Pattern/Unify.hs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,8 @@ constructors =
125125
z = var "Z" someSort
126126
t1 = app con3 [var "X" someSort, var "X" someSort]
127127
t2 = app con3 [y, z]
128-
in test "Matching the same variable in a constructor (failing)" t1 t2 $
129-
failed $
130-
VariableConflict (Variable someSort "X") y z
128+
in test "Matching the same variable in a constructor (indeterminate)" t1 t2 $
129+
remainder [(y, z)]
131130
]
132131

133132
functions :: TestTree

0 commit comments

Comments
 (0)