@@ -68,6 +68,8 @@ import KMerge.Heap
6868import NoThunks.Class
6969import System.FS.API
7070import System.FS.BlockIO.API
71+ import System.FS.IO
72+ import System.FS.Sim.MockFS
7173import Test.QuickCheck (Property , Testable (.. ), counterexample )
7274import Unsafe.Coerce
7375
@@ -542,7 +544,7 @@ instance (NoThunks a, Typeable s, Typeable a) => NoThunks (MutableHeap s a) wher
542544-- a)@, can not be satisfied for arbitrary @m@\/@s@, and must be instantiated
543545-- for a concrete @m@\/@s@, like @IO@\/@RealWorld@.
544546class ( forall a . NoThunks a => NoThunks (StrictTVar m a )
545- , forall a . NoThunks a => NoThunks (StrictMVar m a )
547+ , forall a . ( NoThunks a , Typeable a ) => NoThunks (StrictMVar m a )
546548 ) => NoThunksIOLike' m s
547549
548550instance NoThunksIOLike' IO RealWorld
@@ -564,11 +566,37 @@ instance NoThunks a => NoThunks (StrictTVar IO a) where
564566#endif
565567#endif
566568
567- instance NoThunks a => NoThunks (StrictMVar IO a ) where
568- showTypeOf (_ :: Proxy (StrictMVar IO a )) = " StrictMVar IO"
569- wNoThunks ctx var = do
570- x <- readMVar var
571- noThunks ctx x
569+ -- TODO: in some cases, strict-mvar functions leave thunks behind, in particular
570+ -- modifyMVarMasked and modifyMVarMasked_. So in some specific cases we evaluate
571+ -- the contents of the MVar to WHNF, and keep checking nothunks from there. See
572+ -- lsm-tree#444.
573+ --
574+ -- TODO: we tried using overlapping instances for @StrictMVar IO a@ and
575+ -- @StrictMVar IO (MergingRunState IO h)@, but the quantified constraint in
576+ -- NoThunksIOLike' will throw a compiler error telling us to mark the instances
577+ -- for StrictMVar as incoherent. Marking them as incoherent makes the tests
578+ -- fail... We are unsure if it can be overcome, but the current casting approach
579+ -- works, so there is no priority to use rewrite this code to use overlapping
580+ -- instances.
581+ instance (NoThunks a , Typeable a ) => NoThunks (StrictMVar IO a ) where
582+ showTypeOf (p :: Proxy (StrictMVar IO a )) = show $ typeRep p
583+ wNoThunks ctx var
584+ | Just (Proxy :: Proxy (MergingRunState IO HandleIO ))
585+ <- gcast (Proxy @ a )
586+ = workAroundCheck
587+ | Just (Proxy :: Proxy (MergingRunState IO HandleMock ))
588+ <- gcast (Proxy @ a )
589+ = workAroundCheck
590+ | otherwise
591+ = properCheck
592+ where
593+ properCheck = do
594+ x <- readMVar var
595+ noThunks ctx x
596+
597+ workAroundCheck = do
598+ ! x <- readMVar var
599+ noThunks ctx x
572600
573601{- ------------------------------------------------------------------------------
574602 vector
0 commit comments