
Simon Marlow
The right thing is to have a clean separation between runtime imports and compile-time imports. Perhaps we just annotate some imports to say they aren't needed at compile-time for running the TH code. but then we also need compile-time vs. runtime build-depends in our .cabal files, and so on.
Yes, I was just looking into this yesterday. We already have something similar for plugins, though of course the TH story is much more involved (in part because GHC has to compile haskell code, not just load and run a pre-existing object file).
Its a big project, but ultimately we do have to tackle it, because it's the right thing to do. Anyone interested in working on this? Maybe start a new proposal to flesh out the details.
Yeah, I'm going to at least try. Don't know where formal proposals go, but what I've got so far (definitely subject to change!): 1. Add a separate package database like we have for plugins for TH imports, defaulting to the normal package database when empty 2. Use the TH package db for code to be *run*, but resolve all reifications etc. against the normal target scope. 3. Add {-# TH #-}-annotated imports to specify modules to import compile-time code from (if a module *also* has definitions to be reified, it needs to be imported twice) 3a. If a module has any {-# TH #-} imports, enforce that *all* compile-time executed code is pulled in via {-# TH #-} imports. 3b. Optionally add a warning for TH-using code that doesn't use {-# TH #-}, as the first start of a migration path to enforcing compiletime/runtime separation across the ecosystem. 3c. Not sure what the specific difficulties are that require the staging restrictions, but possibly annotating same-module definitions with {-# TH -} might make this easier? 4. Teach cabal how to add packages to the TH database 4a. Not sure how all this works, but probably this is the place to e.g. request the non-profiled version of a package if ghc is non-profiled and the target code is profiled 5. Modify the build process of the cross-compiler to build a stage-2 compiler that builds code for the target *and* host (at least, enough of the host to build BCOs), and runs that host-targeted code in the interpreter. 5a. This will require some way to distinguish stage-2-as-target-native-compiler VS stage-2-as-hybrid-compiler.