Skip to content

Commit 22409b1

Browse files
authored
Abort on "Unknown" side conditions, don't crash (#3907)
This PR makes sure we do not immediately hard-stop with an RPC error when receiving `Unknown` from Z3 in Booster. - use pure exceptions in SMT functions, check results at call sites to `checkPredicates` - threat Z3-`Unknown` predicates as any other unclear conditions: abort rewriting
1 parent 7f482b0 commit 22409b1

File tree

2 files changed

+18
-19
lines changed

2 files changed

+18
-19
lines changed

booster/library/Booster/Pattern/Rewrite.hs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,8 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu
359359
checkAllRequires <- SMT.checkPredicates solver prior mempty (Set.fromList unclearRequires)
360360

361361
case checkAllRequires of
362-
Nothing -> do
362+
Left _ -> do
363+
-- TODO: we could process SMTError here
363364
-- unclear even with the prior
364365
withContext "abort" $
365366
logMessage $
@@ -369,11 +370,11 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu
369370
RuleConditionUnclear rule . coerce $
370371
foldl1 AndTerm $
371372
map coerce unclearRequires
372-
Just False -> do
373+
Right False -> do
373374
-- requires is actually false given the prior
374375
withContext "failure" $ logMessage ("Required clauses evaluated to #Bottom." :: Text)
375376
RewriteRuleAppT $ pure NotApplied
376-
Just True ->
377+
Right True ->
377378
-- can proceed
378379
pure ()
379380
Nothing ->
@@ -397,7 +398,7 @@ applyRule pat@Pattern{ceilConditions} rule = withRuleContext rule $ runRewriteRu
397398
-- check all new constraints together with the known side constraints
398399
whenJust mbSolver $ \solver ->
399400
(lift $ SMT.checkPredicates solver prior mempty (Set.fromList newConstraints)) >>= \case
400-
Just False -> do
401+
Right False -> do
401402
withContext "success" $ logMessage ("New constraints evaluated to #Bottom." :: Text)
402403
RewriteRuleAppT $ pure Trivial
403404
_other -> pure ()

booster/library/Booster/SMT/Interface.hs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ module Booster.SMT.Interface (
1616
import Control.Exception (Exception, throw)
1717
import Control.Monad
1818
import Control.Monad.Trans.Class
19-
import Control.Monad.Trans.Maybe
19+
import Control.Monad.Trans.Except
2020
import Data.ByteString.Char8 qualified as BS
2121
import Data.Coerce
2222
import Data.Either (isLeft)
@@ -68,9 +68,6 @@ throwSMT = throw . GeneralSMTError
6868
throwSMT' :: String -> a
6969
throwSMT' = throwSMT . pack
7070

71-
throwUnknown :: Text -> Set Predicate -> Set Predicate -> a
72-
throwUnknown reason premises preds = throw $ SMTSolverUnknown reason premises preds
73-
7471
smtTranslateError :: Text -> a
7572
smtTranslateError = throw . SMTTranslationError
7673

@@ -266,14 +263,14 @@ checkPredicates ::
266263
Set Predicate ->
267264
Map Variable Term ->
268265
Set Predicate ->
269-
io (Maybe Bool)
266+
io (Either SMTError Bool)
270267
checkPredicates ctxt givenPs givenSubst psToCheck
271-
| null psToCheck = pure $ Just True -- or Nothing?
268+
| null psToCheck = pure $ Right True
272269
| Left errMsg <- translated = Log.withContext "smt" $ do
273270
Log.logErrorNS "booster" $ "SMT translation error: " <> errMsg
274271
Log.logMessage $ "SMT translation error: " <> errMsg
275-
pure Nothing
276-
| Right ((smtGiven, sexprsToCheck), transState) <- translated = Log.withContext "smt" $ runSMT ctxt . runMaybeT $ do
272+
pure . Left . SMTTranslationError $ errMsg
273+
| Right ((smtGiven, sexprsToCheck), transState) <- translated = Log.withContext "smt" $ runSMT ctxt . runExceptT $ do
277274
Log.logMessage $
278275
Text.unwords
279276
[ "Checking"
@@ -302,8 +299,9 @@ checkPredicates ctxt givenPs givenSubst psToCheck
302299
consistent <- smtRun CheckSat
303300
when (consistent /= Sat) $ do
304301
void $ smtRun Pop
305-
Log.logMessage ("Inconsistent ground truth, check returns Nothing" :: Text)
306-
fail "returns nothing"
302+
let errMsg = ("Inconsistent ground truth, check returns Nothing" :: Text)
303+
Log.logMessage errMsg
304+
throwE $ GeneralSMTError errMsg
307305

308306
-- save ground truth for 2nd check
309307
smtRun_ Push
@@ -324,22 +322,22 @@ checkPredicates ctxt givenPs givenSubst psToCheck
324322

325323
case (positive, negative) of
326324
(Unsat, Unsat) -> throwSMT "Inconsistent ground truth: should have been caught above"
327-
(Sat, Sat) -> fail "Implication not determined"
325+
(Sat, Sat) -> throwE $ GeneralSMTError "Implication not determined"
328326
(Sat, Unsat) -> pure True
329327
(Unsat, Sat) -> pure False
330328
(Unknown, _) -> do
331329
smtRun GetReasonUnknown >>= \case
332-
ReasonUnknown reason -> throwUnknown reason givenPs psToCheck
330+
ReasonUnknown reason -> throwE $ SMTSolverUnknown reason givenPs psToCheck
333331
other -> throwSMT' $ "Unexpected result while calling ':reason-unknown': " <> show other
334332
(_, Unknown) -> do
335333
smtRun GetReasonUnknown >>= \case
336-
ReasonUnknown reason -> throwUnknown reason givenPs psToCheck
334+
ReasonUnknown reason -> throwE $ SMTSolverUnknown reason givenPs psToCheck
337335
other -> throwSMT' $ "Unexpected result while calling ':reason-unknown': " <> show other
338336
other -> throwSMT' $ "Unexpected result while checking a condition: " <> show other
339337
where
340-
smtRun_ :: SMTEncode c => c -> MaybeT (SMT io) ()
338+
smtRun_ :: SMTEncode c => c -> ExceptT SMTError (SMT io) ()
341339
smtRun_ = lift . SMT.runCmd_
342-
smtRun :: SMTEncode c => c -> MaybeT (SMT io) Response
340+
smtRun :: SMTEncode c => c -> ExceptT SMTError (SMT io) Response
343341
smtRun = lift . SMT.runCmd
344342

345343
translated = SMT.runTranslator $ do

0 commit comments

Comments
 (0)