1- {-# LANGUAGE LambdaCase, RecordWildCards, ViewPatterns #-}
1+ {-# LANGUAGE LambdaCase, OverloadedStrings, RecordWildCards, ViewPatterns #-}
22module TypeLevel.Rewrite (plugin ) where
33
44import Control.Monad
@@ -8,9 +8,9 @@ import Data.Foldable
88import Data.Traversable
99
1010-- GHC API
11- import GhcPlugins (eqType )
1211import Coercion (Role (Representational ), mkUnivCo )
13- import Constraint (Ct , ctEvExpr , ctLoc , mkNonCanonical )
12+ import Constraint (CtEvidence (ctev_loc ), Ct , ctEvExpr , ctLoc , mkNonCanonical )
13+ import GhcPlugins (PredType , SDoc , eqType , fsep , ppr )
1414import Plugins (Plugin (pluginRecompile , tcPlugin ), CommandLineOption , defaultPlugin , purePlugin )
1515import TcEvidence (EvExpr , EvTerm , evCast )
1616import TcPluginM (newWanted )
@@ -72,15 +72,17 @@ lookupTypeRules
7272 :: [CommandLineOption ]
7373 -> TcPluginM [TypeRule ]
7474lookupTypeRules [] = do
75- usage (show [" TypeLevel.Append.RightIdentity" , " TypeLevel.Append.RightAssociative" ])
75+ usage (show [ " TypeLevel.Append.RightIdentity" :: String
76+ , " TypeLevel.Append.RightAssociative"
77+ ])
7678 " []"
7779lookupTypeRules fullyQualifiedTypeSynonyms = do
7880 -- ["TypeLevel.Append.RightIdentity", "TypeLevel.Append.RightAssociative"]
7981 for fullyQualifiedTypeSynonyms $ \ fullyQualifiedTypeSynonym -> do
8082 -- "TypeLevel.Append.RightIdentity"
8183 case splitLastDot fullyQualifiedTypeSynonym of
8284 Nothing -> do
83- usage (show " TypeLevel.Append.RightIdentity" )
85+ usage (show ( " TypeLevel.Append.RightIdentity" :: String ) )
8486 (show fullyQualifiedTypeSynonym)
8587 Just (moduleNameStr, tyConNameStr) -> do
8688 -- ("TypeLevel.Append", "RightIdentity")
@@ -114,6 +116,31 @@ plugin = defaultPlugin
114116 }
115117
116118
119+ mkErrCtx
120+ :: SDoc
121+ -> ErrCtxt
122+ mkErrCtx errDoc = (True , \ env -> pure (env, errDoc))
123+
124+ newRuleInducedWanted
125+ :: Ct
126+ -> TypeRule
127+ -> PredType
128+ -> TcPluginM CtEvidence
129+ newRuleInducedWanted oldCt rule newPredType = do
130+ let loc = ctLoc oldCt
131+
132+ -- include the rewrite rule in the error message, if any
133+ let errMsg = fsep [ " From the typelevel rewrite rule:"
134+ , ppr (fromTypeRule rule)
135+ ]
136+ let loc' = pushErrCtxtSameOrigin (mkErrCtx errMsg) loc
137+
138+ wanted <- newWanted loc' newPredType
139+
140+ -- ctLoc only copies the "arising from function X" part but not the location
141+ -- etc., so we need to copy the rest of it manually
142+ pure $ wanted { ctev_loc = loc' }
143+
117144solve
118145 :: [TypeRule ]
119146 -> [Ct ] -- ^ Given constraints
@@ -142,27 +169,27 @@ solve rules givens _ wanteds = do
142169 let typeTerms = fmap toTypeTerm types
143170 let predType = fromDecomposeConstraint types
144171
145- -- C a' b' c'
146- let typeTerms' = fmap (applyRules typeSubst rules) typeTerms
147- let types' = fmap fromTypeTerm typeTerms'
148- let predType' = fromDecomposeConstraint types'
149-
150- unless (eqType predType' predType) $ do
151- -- co :: C a' b' c' ~R C a b c
152- let co = mkUnivCo
153- (PluginProv " TypeLevel.Rewrite" )
154- Representational
155- predType'
156- predType
157- evWanted' <- lift $ newWanted (ctLoc wanted) predType'
158- let wanted' = mkNonCanonical evWanted'
159- let futureDict :: EvExpr
160- futureDict = ctEvExpr evWanted'
161- let replaceCt :: ReplaceCt
162- replaceCt = ReplaceCt
163- { evidenceOfCorrectness = evCast futureDict co
164- , replacedConstraint = wanted
165- , replacementConstraints = [wanted']
166- }
167- tell [replaceCt]
172+ for_ (applyRules typeSubst rules typeTerms) $ \ (rule, typeTerms') -> do
173+ -- C a' b' c'
174+ let types' = fmap fromTypeTerm typeTerms'
175+ let predType' = fromDecomposeConstraint types'
176+
177+ unless (eqType predType' predType) $ do
178+ -- co :: C a' b' c' ~R C a b c
179+ let co = mkUnivCo
180+ (PluginProv " TypeLevel.Rewrite" )
181+ Representational
182+ predType'
183+ predType
184+ evWanted' <- lift $ newRuleInducedWanted wanted rule predType'
185+ let wanted' = mkNonCanonical evWanted'
186+ let futureDict :: EvExpr
187+ futureDict = ctEvExpr evWanted'
188+ let replaceCt :: ReplaceCt
189+ replaceCt = ReplaceCt
190+ { evidenceOfCorrectness = evCast futureDict co
191+ , replacedConstraint = wanted
192+ , replacementConstraints = [wanted']
193+ }
194+ tell [replaceCt]
168195 pure $ combineReplaceCts replaceCts
0 commit comments