packages feed

core-warn-0.1.0.0: src/Warn/Coercion.hs

{-# LANGUAGE CPP            #-}
{-# LANGUAGE NamedFieldPuns #-}

module Warn.Coercion where

#if __GLASGOW_HASKELL__ >= 900
import GHC.Core.Stats
import GHC.Plugins hiding ((<>))
import GHC.Utils.Ppr.Colour
#else
import CoreStats
import GhcPlugins hiding ((<>))
import PprColour
#endif

------------------------------------------------------------------------------
-- | Pretty print a "large number of coercions" warning.
pprWarnLargeCoerce :: [SrcSpan] -> CoreBndr -> CoreStats -> SDoc
pprWarnLargeCoerce refs bind stats =
  let srcSpanList = if length refs >= 3
                       then take 3 ((bullet <+>) . ppr <$> refs) <> [text "..."]
                       else (bullet <+>) . ppr <$> refs
      CS{..} = stats
   in vcat [ text "Found a large number of coercions in GHC Core."
           , nest 2 $  text " GHC produced a a quadratic number of coercions relative to the number of terms."
                    $$ text "This can happen for expensive type families that are used outside of phantom contexts."
           , blankLine
           , hsep [ text "These coercions were introduced in"
                 , coloured colBlueFg . ppr . getOccName $ bind
                 , text "at these locations:"
                 ]
           , nest 4 (vcat srcSpanList)
           , blankLine
           , sep [ text "Terms:",     coloured colBlueFg $ ppr cs_tm
                 , text "Types:",     coloured colBlueFg $ ppr cs_ty
                 , text "Coercions:", coloured colBlueFg $ ppr cs_co
                 ]
           , text ""
           ]


------------------------------------------------------------------------------
-- | Heuristic for whether we should show a "large number of coercions"
-- warning.
shouldWarnLargeCoercion :: CoreStats -> Bool
shouldWarnLargeCoercion CS {cs_tm, cs_co} =
  let quad = cs_tm * floor (logBase @Double 2 $ fromIntegral cs_tm)
   in cs_co >= quad && cs_co > 100