Skip to content

eqTypeRep does not inline

GHC never seems to inline eqTypeRep. That's no good! It produces a Maybe, which users will almost certainly want to match on immediately.

I really don't understand why it doesn't inline. It's a tiny function, none of the functions it calls are themselves marked INLINE, and the advantage to inlining seems obvious. Does the unsafeCoerce get in the way somehow? If so, how can we fix it?

Example:

{-# language GADTs, ScopedTypeVariables, TypeApplications,
       AllowAmbiguousTypes #-}
module Foo where
import Type.Reflection

foo :: forall a. Typeable a => Bool
foo = case eqTypeRep (typeRep @a) (typeRep @Int) of
          Just _ -> True
          Nothing -> False

compiles (with -O2) to

foo [InlPrag=NOINLINE] :: forall a. Typeable a => Bool
[GblId, Arity=1, Str=<S,1*U>]
foo
  = \ (@ a_a5un) ($dTypeable_a5up :: Typeable a_a5un) ->
      case eqTypeRep
             @ *
             @ *
             @ a_a5un
             @ Int
             ($dTypeable_a5up
              `cast` (base-4.10.1.0:Data.Typeable.Internal.N:Typeable[0] <*>_N <a_a5un>_N
                      :: (Typeable a_a5un :: Constraint) ~R# (TypeRep a_a5un :: *)))
             lvl4_r69g
      of {
        Nothing -> GHC.Types.False;
        Just ds_d5CQ -> GHC.Types.True
      }

For reference, eqTypeRep is defined like this:

eqTypeRep :: forall k1 k2 (a :: k1) (b :: k2).
             TypeRep a -> TypeRep b -> Maybe (a :~~: b)
eqTypeRep a b
  | typeRepFingerprint a == typeRepFingerprint b = Just (unsafeCoerce HRefl)
  | otherwise                                    = Nothing
Edited by David Feuer
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information