{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ViewPatterns #-} module RewritePlugin where -- Rewriting type family applications. -- base import Data.Maybe ( catMaybes ) -- ghc import GHC.Builtin.Types ( unitTy ) import GHC.Core ( Expr(Coercion) ) import GHC.Core.Coercion ( Coercion, mkUnivCo ) import GHC.Core.Predicate ( EqRel(NomEq), Pred(EqPred) , classifyPredType ) import GHC.Core.Reduction ( Reduction(..) ) import GHC.Core.TyCo.Rep ( Type, UnivCoProvenance(PluginProv) ) import GHC.Core.TyCon ( TyCon ) import GHC.Core.Type ( eqType, mkTyConApp, splitTyConApp_maybe ) import GHC.Plugins ( Plugin ) import GHC.Tc.Plugin ( TcPluginM , unsafeTcPluginTcM ) import GHC.Tc.Types ( RewriteEnv , TcPluginRewriter, TcPluginRewriteResult(..) ) import GHC.Tc.Types.Constraint ( Ct(..), CanEqLHS(..) , ctPred ) import GHC.Tc.Types.Evidence ( EvTerm(EvExpr), Role(Nominal) ) import GHC.Types.Unique.FM ( UniqFM, listToUFM ) -- common import Common ( PluginDefs(..) , mkPlugin, don'tSolve ) -------------------------------------------------------------------------------- -- This plugin rewrites @Add a Zero@ to @a@ and @Add Zero a@ to @a@, -- by using the plugin rewriting functionality, -- and not the constraint solver plugin functionality. plugin :: Plugin plugin = mkPlugin don'tSolve rewriter rewriter :: [String] -> PluginDefs -> UniqFM TyCon TcPluginRewriter rewriter _args defs@( PluginDefs { add } ) = listToUFM [ ( add, rewriteAdd defs ) ] rewriteAdd :: PluginDefs -> RewriteEnv -> [ Ct ] -> [ Type ] -> TcPluginM TcPluginRewriteResult rewriteAdd ( PluginDefs { .. } ) _env givens args@[ arg1, arg2 ] | Just ( tyCon, [] ) <- splitTyConApp_maybe arg1 , tyCon == zero = pure $ TcPluginRewriteTo ( mkTyFamReduction add args arg2 ) [] | Just ( tyCon, [] ) <- splitTyConApp_maybe arg2 , tyCon == zero = pure $ TcPluginRewriteTo ( mkTyFamReduction add args arg1 ) [] rewriteAdd _ _ _ _ = pure TcPluginNoRewrite mkTyFamReduction :: TyCon -> [ Type ] -> Type -> Reduction mkTyFamReduction tyCon args res = Reduction co res where co :: Coercion co = mkUnivCo ( PluginProv "RewritePlugin" ) Nominal ( mkTyConApp tyCon args ) res