Skip to content

Commit 86d7543

Browse files
committed
copilot-theorem: Record Typed evidence in XEmptyArray and XArray. Refs #589.
Currently, the `Copilot.Theorem.What4.prove` function returns a list of results, where each result contains a `SatResult` that describes whether a property is `Valid`, `Invalid`, or `Unknown`. The `Invalid` result has the limitation that it does not give any information about a specific counterexample that could drive Copilot into falsifying the property, however. This makes it challenging to interpret what the results of prove mean. To update the `valFromExpr` function in order to produce concrete array values for counterexample purposes, we need to call the `Array` data constructor, which has a `Typed` constraint. However, the `XEmptyArray` and `XArray` data constructors do not record evidence that their array element types were instances of the `Typed` class, which makes it impossible to use them in `valFromExpr`. This commit adds the necessary constraints to each data constructor to make their array elements `Typed`.
1 parent 0bd29d5 commit 86d7543

File tree

1 file changed

+36
-21
lines changed

1 file changed

+36
-21
lines changed

copilot-theorem/src/Copilot/Theorem/What4/Translate.hs

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ import Data.Parameterized.NatRepr (LeqProof (..), NatCases (..),
5656
intValue, isZeroOrGT1,
5757
knownNat, minusPlusCancel,
5858
mkNatRepr, testNatCases,
59-
testStrictLeq)
59+
testStrictLeq, withKnownNat)
6060
import Data.Parameterized.Some (Some (..))
6161
import Data.Parameterized.SymbolRepr (SymbolRepr, knownSymbol)
6262
import qualified Data.Parameterized.Vector as V
@@ -370,10 +370,10 @@ translateConstExpr sym tp a = case tp of
370370
elts <- traverse (translateConstExpr sym tp) (CT.arrayElems a)
371371
Some n <- return $ mkNatRepr (genericLength elts)
372372
case isZeroOrGT1 n of
373-
Left Refl -> return XEmptyArray
373+
Left Refl -> return $ XEmptyArray tp
374374
Right LeqProof -> do
375375
let Just v = V.fromList n elts
376-
return $ XArray v
376+
return $ withKnownNat n $ XArray v
377377
CT.Struct _ -> do
378378
elts <- forM (CT.toValues a) $ \(CT.Value tp (CT.Field a)) ->
379379
translateConstExpr sym tp a
@@ -409,7 +409,7 @@ freshCPConstant sym nm tp = case tp of
409409
atp@(CT.Array itp) -> do
410410
let n = arrayLen atp
411411
case isZeroOrGT1 n of
412-
Left Refl -> return XEmptyArray
412+
Left Refl -> return $ XEmptyArray itp
413413
Right LeqProof -> do
414414
Refl <- return $ minusPlusCancel n (knownNat @1)
415415
elts :: V.Vector n (XExpr t) <-
@@ -1281,7 +1281,13 @@ mkIte sym pred xe1 xe2 = case (xe1, xe2) of
12811281
XDouble <$> WFP.iFloatIte @_ @WFP.DoubleFloat sym pred e1 e2
12821282
(XStruct xes1, XStruct xes2) ->
12831283
XStruct <$> zipWithM (mkIte sym pred) xes1 xes2
1284-
(XEmptyArray, XEmptyArray) -> return XEmptyArray
1284+
(XEmptyArray tp1, XEmptyArray tp2) ->
1285+
case tp1 `testEquality` tp2 of
1286+
Just Refl -> return (XEmptyArray tp1)
1287+
Nothing -> panic [ "Element type mismatch in ite"
1288+
, show tp1
1289+
, show tp2
1290+
]
12851291
(XArray xes1, XArray xes2) ->
12861292
case V.length xes1 `testEquality` V.length xes2 of
12871293
Just Refl -> XArray <$> V.zipWithM (mkIte sym pred) xes1 xes2
@@ -1438,25 +1444,34 @@ data XExpr sym where
14381444
sym
14391445
(WFP.SymInterpretedFloatType sym WFP.DoubleFloat)
14401446
-> XExpr sym
1441-
XEmptyArray :: XExpr sym
1442-
XArray :: 1 <= n => V.Vector n (XExpr sym) -> XExpr sym
1447+
1448+
-- | An empty array. The 'CT.Typed' constraint and accompanying 'CT.Type'
1449+
-- field are necessary in order to record evidence that the array type can be
1450+
-- used in a context where 'CT.Typed' is required.
1451+
XEmptyArray :: CT.Typed t => CT.Type t -> XExpr sym
1452+
1453+
-- | A non-empty array. The 'KnownNat' constraint is necessary in order to
1454+
-- record evidence that the array type can be used in a context for 'CT.Typed'
1455+
-- is required.
1456+
XArray :: (KnownNat n, 1 <= n) => V.Vector n (XExpr sym) -> XExpr sym
1457+
14431458
XStruct :: [XExpr sym] -> XExpr sym
14441459

14451460
instance WI.IsExprBuilder sym => Show (XExpr sym) where
1446-
show (XBool e) = "XBool " ++ show (WI.printSymExpr e)
1447-
show (XInt8 e) = "XInt8 " ++ show (WI.printSymExpr e)
1448-
show (XInt16 e) = "XInt16 " ++ show (WI.printSymExpr e)
1449-
show (XInt32 e) = "XInt32 " ++ show (WI.printSymExpr e)
1450-
show (XInt64 e) = "XInt64 " ++ show (WI.printSymExpr e)
1451-
show (XWord8 e) = "XWord8 " ++ show (WI.printSymExpr e)
1452-
show (XWord16 e) = "XWord16 " ++ show (WI.printSymExpr e)
1453-
show (XWord32 e) = "XWord32 " ++ show (WI.printSymExpr e)
1454-
show (XWord64 e) = "XWord64 " ++ show (WI.printSymExpr e)
1455-
show (XFloat e) = "XFloat " ++ show (WI.printSymExpr e)
1456-
show (XDouble e) = "XDouble " ++ show (WI.printSymExpr e)
1457-
show XEmptyArray = "[]"
1458-
show (XArray vs) = showList (V.toList vs) ""
1459-
show (XStruct xs) = "XStruct " ++ showList xs ""
1461+
show (XBool e) = "XBool " ++ show (WI.printSymExpr e)
1462+
show (XInt8 e) = "XInt8 " ++ show (WI.printSymExpr e)
1463+
show (XInt16 e) = "XInt16 " ++ show (WI.printSymExpr e)
1464+
show (XInt32 e) = "XInt32 " ++ show (WI.printSymExpr e)
1465+
show (XInt64 e) = "XInt64 " ++ show (WI.printSymExpr e)
1466+
show (XWord8 e) = "XWord8 " ++ show (WI.printSymExpr e)
1467+
show (XWord16 e) = "XWord16 " ++ show (WI.printSymExpr e)
1468+
show (XWord32 e) = "XWord32 " ++ show (WI.printSymExpr e)
1469+
show (XWord64 e) = "XWord64 " ++ show (WI.printSymExpr e)
1470+
show (XFloat e) = "XFloat " ++ show (WI.printSymExpr e)
1471+
show (XDouble e) = "XDouble " ++ show (WI.printSymExpr e)
1472+
show (XEmptyArray _) = "[]"
1473+
show (XArray vs) = showList (V.toList vs) ""
1474+
show (XStruct xs) = "XStruct " ++ showList xs ""
14601475

14611476
-- * Stream offsets
14621477

0 commit comments

Comments
 (0)