{-# language LambdaCase, Strict, TemplateHaskell, TupleSections, ViewPatterns #-} {-# options_ghc -Wincomplete-patterns -Wunused-imports #-} module StrictImplParams (plugin) where import System.Exit import Data.Foldable import GHC.Classes import GHC.Plugins import qualified Language.Haskell.TH as TH import qualified GHC.Core.TyCo.Rep as GHC plugin :: Plugin plugin = defaultPlugin { installCoreToDos = \_ todo -> pure (CoreDoPluginPass "Strict Implicit Params" pass : todo), pluginRecompile = purePlugin } fromTHName :: TH.Name -> CoreM Name fromTHName thn = thNameToGhcName thn >>= \case Nothing -> do errorMsg $ text "Could not resolve TH name" <+> text (show thn) liftIO exitFailure Just n -> pure n map' :: (a -> b) -> [a] -> [b] map' f = foldr' (\a bs -> ((:) $! f a) $! bs) [] {-# inline map' #-} forceVar :: Var -> CoreExpr -> Type -> CoreExpr forceVar x u uty = Case (Var x) x uty [Alt DEFAULT [] u] setNoOccInfo :: Var -> Var setNoOccInfo x = case idInfo x of i -> lazySetIdInfo x (i {occInfo = noOccInfo}) forceType :: Type -> Type forceType a = case tcView a of Just a' -> forceType a' _ -> a pass :: ModGuts -> CoreM ModGuts pass guts = do dflags <- getDynFlags ipName <- fromTHName ''GHC.Classes.IP let goDef :: [Var] -> CoreExpr -> Type -> CoreExpr goDef xs t a = case t of Lam x t -> case forceType a of GHC.ForAllTy _ a -> Lam x $! goDef xs t a GHC.FunTy _ _ a b | Just (getName -> con, _) <- splitTyConApp_maybe a, con == ipName -> Lam x $! goDef (((:) $! setNoOccInfo x) xs) t b | otherwise -> Lam x $! goDef xs t b a -> do error $ "unexpected lam type: " ++ showSDoc dflags (ppr a) t -> foldl' (\acc x -> forceVar x acc a) t xs let goBind :: CoreBind -> CoreBind goBind = \case NonRec b t -> NonRec b $! goDef [] t (varType b) Rec defs -> Rec $! map' (\(b, t) -> (b,) $! goDef [] t (varType b)) defs pure $! guts {mg_binds = map' goBind (mg_binds guts)}