Debugging Template Haskell
Template Haskell powers a lot of really neat functionality in Yesod and friends, but sometimes it can be broken. I'm writing this post to collect all the info learned about GHC and Cabal from an unpleasant debugging session in one place.
I was tracking down a problem causing my work project
to not build on a newer GHC version
(spoiler: it was this
and hit a brick wall when this happened:
/home/lf/dev/Carnap/Carnap-Server/Model.hs:16:7: error: • Not in scope: type constructor or class ‘CoInstructorId’ • In the untyped splice: $(persistFileWith lowerCaseSettings "config/models") | 16 | $(persistFileWith lowerCaseSettings "config/models") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The next step was to figure out what was generating these type constructors and
why it was stuffed. The Internet
suggested that I should pass
-ddump-splices -ddump-to-file to ghc. Cool! So I
did and it didn't make any visible files. Dammit.
Some more Googling led to the option
-dth-dec-file, which I also applied to
no observable effect. At this point my emotions were best described as 🤡.
So I read the documentation and find that there are still no mentions of what
the file is called or where it goes. I compile the version that is known to
work with the
-dth-dec-file, since allegedly that one produces
Filename.th.hs files, and this time try a little harder to find them, using
find -name '*.th.hs*'. As it turns out, those files end up in the
dist-newstyle directory if running in Cabal. Specifically here:
Once I found the files, I could track them down on the broken version, except
there was a problem:
-dth-dec-file appears to run at one of the last compile
phases, which the broken file was not passing. If you are debugging compile
problems in a file that doesn't itself compile, you should use
-dth-dec-filefor a slightly shorter (11k lines vs 12k lines for Carnap's models), and possibly more readable TH output, if the file containing the splice builds.
-ddump-splices -ddump-to-fileif the file containing the splice doesn't build.
- Outputs will be in
- GHC documentation on dump options is here