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.