Skip to content

Error retrieving interface file for ghc-prim type

Summary

I'm working on lift-type, which provides a function liftType :: Typeable a => TemplateHaskell.Type, as part of working on discover-instances. I ran into a bug in discover-instances where polykinded classes (ie class TypeScript (a :: k) where ... break the library. I determined that I can't discover all kinds of instances, but I can pick a single kind. $$(discoverInstances @(TypeScript :: Type -> Constraint)) works fine, for example.

In chasing it down, I determined that I needed to use lift-type to turn the provided kind into a Type so I can pass it to discoverInstances. Instead of providing [VarT (mkName "a")], I need to provide reifyInstances cls [SigT (VarT (mkName "a")) (liftType @Data.Kind.Type)].

When I do that, however, I get a GHC error:

/home/matt/Projects/lift-type/test/Spec.hs:12:34: error:
    • Can't find interface-file declaration for data constructor ghc-prim-0.6.1:GHC.Prim.LiftedRep
        Probable cause: bug in .hi-boot file, or inconsistent .hi file
        Use -ddump-if-trace to get an idea of which file caused the error
    • In the first argument of ‘TYPE’, namely
        ‘'ghc-prim-0.6.1:GHC.Prim.LiftedRep’
      In the first argument of ‘Proxy’, namely
        ‘(TYPE 'ghc-prim-0.6.1:GHC.Prim.LiftedRep)’
      In an expression type signature:
        Proxy (TYPE 'ghc-prim-0.6.1:GHC.Prim.LiftedRep)
   |        
12 |         type_ = Proxy :: Proxy $(liftTypeQ @Type)
   |                                  ^^^^^^^^^^^^^^^

With -ddump-splices, I get this:

/home/matt/Projects/lift-type/test/Spec.hs:14:34-48: Splicing type
    liftTypeQ @Type ======> TYPE 'ghc-prim-0.6.1:GHC.Prim.LiftedRep

The code that produces it is here:

    mk :: TyCon -> Type
    mk tyCon =
        let
            tcName =
                tyConName tyCon
            trySymbol =
                case tcName of
                    '"' : cs ->
                        Just $ LitT (StrTyLit (zipWith const cs (drop 1 cs)))
                    _ ->
                        Nothing
            tryTicked =
                case tcName of
                    '\'' : dcName ->
                        let nameBase =
                                mkOccName dcName

                            flavor =
                                NameG
                                    DataName
                                    (mkPkgName $ tyConPackage tyCon)
                                    (mkModName $ tyConModule tyCon)
                            name =
                                Name
                                    nameBase
                                    flavor
                        in
                            Just (PromotedT name)
                    _ ->
                        Nothing
            tryNat =
                LitT . NumTyLit <$> readMaybe tcName
            plainType =
                let
                    nameBase =
                        mkOccName tcName
                    flavor =
                        NameG
                            TcClsName
                            (mkPkgName $ tyConPackage tyCon)
                            (mkModName $ tyConModule tyCon)
                    name =
                        Name
                            nameBase
                            flavor
                in
                    ConT name
        in fromMaybe plainType $ asum [tryTicked, trySymbol, tryNat]

It's taking the tryTicked path, which constructs the NameG DataName pkgName modName for TemplateHaskell to work with non-imported terms.

I've worked around this by introducing this case:

    go :: forall k (a :: k). TypeRep a -> Type
    go tr
        | Just HRefl <- eqTypeRep (typeRep @Kind.Type) tr
        = ConT ''Kind.Type
        | otherwise =

However, that's brittle, and won't work for other kinds than just Type, and it introduces a performance impact.

Steps to reproduce

git clone git@github.com:parsonsmatt/lift-type
cd lift-type
git checkout mattp/demonstrate-interface-bug
cabal test

Expected behavior

I would expect the built-in types to work as well as the regular ones.

For what it's worth, liftType @Word# works fine, so it's not only an issue wiht built-in types

Environment

Optional:

  • Operating System: Ubuntu
  • System Architecture: x86-64
Edited by sheaf
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information