Note [Patching magic definitions]
We sometimes need to have access to defined Ids in pure contexts. Usually, we simply "wire in" these entities, as we do for types in GHC.Builtin.Types and for Ids in GHC.Types.Id.Make. See Note [Wired-in Ids] in GHC.Types.Id.Make. However, it is sometimes *much* easier to define entities in Haskell, even if we need pure access; note that wiring-in an Id requires all entities used in its definition *also* to be wired in, transitively and recursively. This can be a huge pain. The little trick documented here allows us to have the best of both worlds. Motivating example: unsafeCoerce#. See [Wiring in unsafeCoerce#] for the details. The trick is to * Define the known-key Id in a library module, with a stub definition, unsafeCoerce# :: ..a suitable type signature.. unsafeCoerce# = error "urk" * Magically over-write its RHS here in the desugarer, in patchMagicDefns. This update can be done with full access to the DsM monad, and hence, dsLookupGlobal. We thus do not have to wire in all the entities used internally, a potentially big win. This step should not change the Name or type of the Id. Because an Id stores its unfolding directly (as opposed to in the second component of a (Id, CoreExpr) pair), the patchMagicDefns function returns a new Id to use. Here are the moving parts: - patchMagicDefns checks whether we're in a module with magic definitions; if so, patch the magic definitions. If not, skip. - patchMagicDefn just looks up in an environment to find a magic defn and patches it in. - magicDefns holds the magic definitions. - magicDefnsEnv allows for quick access to magicDefns. - magicDefnModules, built also from magicDefns, contains the modules that need careful attention.
References 1
- Wired-in Ids GHC.Types.Id.Make
Referenced by 2
- Wiring in unsafeCoerce# GHC.HsToCore
- GHC.HsToCore call site