@@ -36,7 +36,7 @@ module Data.SBV.Control.Utils (
36
36
) where
37
37
38
38
import Data.Maybe (isJust )
39
- import Data.List (sortBy , sortOn , elemIndex , partition , groupBy , tails )
39
+ import Data.List (sortBy , sortOn , elemIndex , partition , groupBy , tails , intercalate )
40
40
41
41
import Data.Char (isPunctuation , isSpace , chr )
42
42
import Data.Function (on )
@@ -740,9 +740,57 @@ runProofOn rm comments res@(Result ki _qcInfo _observables _codeSegs is consts t
740
740
741
741
-- | Execute a query
742
742
executeQuery :: QueryContext -> Query a -> Symbolic a
743
- executeQuery _queryContext (Query userQuery) = do
743
+ executeQuery queryContext (Query userQuery) = do
744
744
st <- R. ask
745
745
rm <- liftIO $ readIORef (runMode st)
746
+
747
+ -- If we're doing an external query, then we cannot allow quantifiers to be present. Why?
748
+ -- Consider:
749
+ --
750
+ -- issue = do x :: SBool <- forall_
751
+ -- y :: SBool <- exists_
752
+ -- constrain y
753
+ -- query $ do checkSat
754
+ -- (,) <$> getValue x <*> getValue y
755
+ --
756
+ -- This is the (simplified/annotated SMTLib we would generate:)
757
+ --
758
+ -- (declare-fun s1 (Bool) Bool) ; s1 is the function that corresponds to the skolemized 'y'
759
+ -- (assert (forall ((s0 Bool)) ; s0 is 'x'
760
+ -- (s1 s0))) ; s1 applied to s0 is the actual 'y'
761
+ -- (check-sat)
762
+ -- (get-value (s0)) ; s0 simply not visible here
763
+ -- (get-value (s1)) ; s1 is visible, but only via 's1 s0', so it is also not available.
764
+ --
765
+ -- And that would be terrible! The scoping rules of our "quantified" variables and how they map to
766
+ -- SMTLib is just not compatible. This is a historical design issue, but too late at this point. (We
767
+ -- should've never allowed general quantification like this, but only in limited contexts.)
768
+ --
769
+ -- So, we check if this is an external-query, and if there are quantified variables. If so, we
770
+ -- cowardly refuse to continue. For details, see: <http://github.com/LeventErkok/sbv/issues/407>
771
+
772
+ () <- liftIO $ case queryContext of
773
+ QueryInternal -> return () -- we're good, internal usages don't mess with scopes
774
+ QueryExternal -> do
775
+ (userInps, _) <- readIORef (rinps st)
776
+ let badInps = reverse [n | (ALL , (_, n)) <- userInps]
777
+ case badInps of
778
+ [] -> return ()
779
+ _ -> let plu | length badInps > 1 = " s require"
780
+ | True = " requires"
781
+ in error $ unlines [ " "
782
+ , " *** Data.SBV: Unsupported query call in the presence of quantified inputs."
783
+ , " ***"
784
+ , " *** The following variable" ++ plu ++ " explicit quantification: "
785
+ , " ***"
786
+ , " *** " ++ intercalate " , " badInps
787
+ , " ***"
788
+ , " *** While quantification and queries can co-exist in principle, SBV currently"
789
+ , " *** does not support this scenario. Avoid using quantifiers with user queries"
790
+ , " *** if possible. Please do get in touch if your use case does require such"
791
+ , " *** a feature to see how we can accommodate such scenarios."
792
+ ]
793
+
746
794
case rm of
747
795
-- Transitioning from setup
748
796
SMTMode stage isSAT cfg | not (isRunIStage stage) -> liftIO $ do
0 commit comments