Skip to content

Error messages and constraints can easily be lost by accident

Today I rediscovered a nasty, subtle bug, which we have seen before: #19470 (closed)

The problem is that in the typechecker we use this idiom quite a lot

   do { (gbl_env, lcl_env) <- tcRnSrcDecls ...
      ; setGblEnv gbl_env $ setLclEnv lcl_env $
        more_stuff }

The tcRnSrcDecls extends the environments in gbl_env and lcl_env which we then want to be in scope in more stuff.

The problem is that lcl_env :: TcLclEnv has an IORef for error messages tcl_errs, and another for constraints (tcl_lie),a and another for Linear Haskell usage information (tcl_usage). Now suppose we change it a tiny bit

   do { (gbl_env, lcl_env) <- checkNoErrs $
                              tcRnSrcDecls ...
      ; setGblEnv gbl_env $ setLclEnv lcl_env $
        more_stuff }

That should be innocuous. But alas, checkNoErrs gathers errors in a fresh IORef *which is then captured in the returned lcl_env. When we do the setLclEnv we'll make that captured IORef into the place where we gather error messages -- but no one is going to look at that IORef any more, so the errors are simply lost.

This was worked around in the fix to #19470 (closed), namely !5495 (closed). But it bit me in a different way today.

We should make a more general fix.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information