@@ -248,16 +248,31 @@ setValues :: IdeRule k v
248248 -> NormalizedFilePath
249249 -> Value v
250250 -> IO ()
251−setValues state key file val = modifyVar_ state $
252− pure . HMap.insert (file, Key key) (fmap toDyn val)
251+setValues state key file val = modifyVar_ state $ \vals -> do
252+ -- Force to make sure the old HashMap is not retained
253+ evaluate $ HMap.insert (file, Key key) (fmap toDyn val) vals
253254
254255-- | We return Nothing if the rule has not run and Just Failed if it has failed to produce a value.
255256getValues :: forall k v. IdeRule k v => Var Values -> k -> NormalizedFilePath -> IO (Maybe (Value v))
256257getValues state key file = do
257258 vs <- readVar state
258− return $ do
259− v <- HMap.lookup (file, Key key) vs
260− pure $ fmap (fromJust . fromDynamic @v) v
259+ case HMap.lookup (file, Key key) vs of
260+ Nothing -> pure Nothing
261+ Just v -> do
262+ let r = fmap (fromJust . fromDynamic @v) v
263+ -- Force to make sure we do not retain a reference to the HashMap
264+ -- and we blow up immediately if the fromJust should fail
265+ -- (which would be an internal error).
266+ evaluate (r `seqValue` Just r)
267+
268+-- | Seq the result stored in the Shake value. This only
269+-- evaluates the value to WHNF not NF. We take care of the latter
270+-- elsewhere and doing it twice is expensive.
271+seqValue :: Value v -> b -> b
272+seqValue v b = case v of
273+ Succeeded ver v -> rnf ver `seq` v `seq` b
274+ Stale ver v -> rnf ver `seq` v `seq` b
275+ Failed -> b
261276
262277-- | Open a 'IdeState', should be shut using 'shakeShut'.
263278shakeOpen :: (LSP.FromServerMessage -> IO ()) -- ^ diagnostic handler