summaryrefslogtreecommitdiff
path: root/testsuite/tests/tcplugins/TyFamPlugin.hs
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/tests/tcplugins/TyFamPlugin.hs')
-rw-r--r--testsuite/tests/tcplugins/TyFamPlugin.hs81
1 files changed, 81 insertions, 0 deletions
diff --git a/testsuite/tests/tcplugins/TyFamPlugin.hs b/testsuite/tests/tcplugins/TyFamPlugin.hs
new file mode 100644
index 0000000000..523bdc10c1
--- /dev/null
+++ b/testsuite/tests/tcplugins/TyFamPlugin.hs
@@ -0,0 +1,81 @@
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ViewPatterns #-}
+
+module TyFamPlugin where
+-- Solving an equality constraint involving type families.
+
+-- base
+import Data.Maybe
+ ( catMaybes )
+
+-- ghc
+import GHC.Builtin.Types
+ ( unitTy )
+import GHC.Core
+ ( Expr(Coercion) )
+import GHC.Core.Coercion
+ ( mkUnivCo )
+import GHC.Core.Predicate
+ ( EqRel(NomEq), Pred(EqPred)
+ , classifyPredType
+ )
+import GHC.Core.TyCo.Rep
+ ( Type, UnivCoProvenance(PluginProv) )
+import GHC.Core.Type
+ ( eqType, mkTyConApp, splitTyConApp_maybe )
+import GHC.Plugins
+ ( Plugin )
+import GHC.Tc.Plugin
+ ( TcPluginM
+ , unsafeTcPluginTcM
+ )
+import GHC.Tc.Types
+ ( TcPluginResult(..) )
+import GHC.Tc.Types.Constraint
+ ( Ct(..), CanEqLHS(..)
+ , ctPred
+ )
+import GHC.Tc.Types.Evidence
+ ( EvTerm(EvExpr), Role(Nominal) )
+
+-- common
+import Common
+ ( PluginDefs(..)
+ , mkPlugin
+ )
+
+--------------------------------------------------------------------------------
+
+-- This plugin solves Wanted constraints of the form "MyTyFam a a ~ ()".
+--
+-- It does so by looking through the Wanted constraints for equality constraints
+-- whose left hand side is a type-family application "MyTyFam arg1 arg2",
+-- such that "arg1 `eqType` arg2" returns "True",
+-- and whose left hand side is the unit type "()".
+--
+-- In such a case, the plugin creates a universal coercion
+-- with Plugin provenance to prove the equality constraint.
+
+plugin :: Plugin
+plugin = mkPlugin solver
+
+solver :: [String]
+ -> PluginDefs -> [Ct] -> [Ct] -> [Ct]
+ -> TcPluginM TcPluginResult
+solver _args defs _gs _ds ws = do
+ solved <- catMaybes <$> traverse ( solveCt defs ) ws
+ pure $ TcPluginOk solved []
+
+-- Solve `MyTyFam a a ~ ()`.
+solveCt :: PluginDefs -> Ct -> TcPluginM ( Maybe (EvTerm, Ct) )
+solveCt ( PluginDefs {..} ) ct@( classifyPredType . ctPred -> EqPred NomEq lhs rhs )
+ | Just ( tyFam, [arg1, arg2] ) <- splitTyConApp_maybe lhs
+ , tyFam == myTyFam
+ , arg1 `eqType` arg2
+ , rhs `eqType` unitTy
+ , let
+ evTerm :: EvTerm
+ evTerm = EvExpr . Coercion
+ $ mkUnivCo ( PluginProv "TyFamPlugin" ) Nominal lhs rhs
+ = pure $ Just ( evTerm, ct )
+solveCt _ ct = pure Nothing