[commit: ghc] wip/tc-plugins-amg: Modify runTcPluginsGiven to allow solving givens, avoid duplicating work (3080c9b)

git at git.haskell.org git at git.haskell.org
Mon Nov 17 17:43:54 UTC 2014


Repository : ssh://git@git.haskell.org/ghc

On branch  : wip/tc-plugins-amg
Link       : http://ghc.haskell.org/trac/ghc/changeset/3080c9b4a60aac47368f6adb04ac1483383af62c/ghc

>---------------------------------------------------------------

commit 3080c9b4a60aac47368f6adb04ac1483383af62c
Author: Adam Gundry <adam at well-typed.com>
Date:   Mon Nov 17 17:27:17 2014 +0000

    Modify runTcPluginsGiven to allow solving givens, avoid duplicating work


>---------------------------------------------------------------

3080c9b4a60aac47368f6adb04ac1483383af62c
 compiler/typecheck/TcInteract.lhs | 71 ++++++++++++++++++++++++++++-----------
 1 file changed, 52 insertions(+), 19 deletions(-)

diff --git a/compiler/typecheck/TcInteract.lhs b/compiler/typecheck/TcInteract.lhs
index c8fedfb..47997c6 100644
--- a/compiler/typecheck/TcInteract.lhs
+++ b/compiler/typecheck/TcInteract.lhs
@@ -39,7 +39,7 @@ import TcErrors
 import TcSMonad
 import Bag
 
-import Data.List( partition )
+import Data.List( partition, foldl', deleteFirstsBy )
 
 import VarEnv
 
@@ -125,8 +125,8 @@ solveFlatGivens loc givens
                                                 , ctev_pred = evVarPred ev_id
                                                 , ctev_loc  = loc })
     go givens = do { solveFlats givens
-                   ; (upd_givens, rerun) <- runTcPluginsGiven givens
-                   ; when rerun (go upd_givens)
+                   ; new_givens <- runTcPluginsGiven
+                   ; when (notNull new_givens) (go (listToBag new_givens))
                    }
 
 solveFlatWanteds :: Cts -> TcS WantedConstraints
@@ -189,30 +189,63 @@ setEv (ev,ct) = case ctEvidence ct of
                   CtWanted {ctev_evar = evar} -> setEvBind evar ev
                   _                           -> return ()
 
-runTcPluginsGiven :: Cts -> TcS (Cts, Bool)
-runTcPluginsGiven givens = do
+removeInertCts :: [Ct] -> InertCans -> InertCans
+removeInertCts cts icans = foldl' removeInertCt icans cts
+
+-- Remove the constraint from the inert set.  We use this either when:
+--   * a wanted constraint was solved, or
+--   * some constraint was marked as insoluable, and so it will be
+--     put right back into InertSet, but in the insoluable section.
+removeInertCt :: InertCans -> Ct -> InertCans
+removeInertCt is ct =
+  case ct of
+
+    CDictCan  { cc_class = cl, cc_tyargs = tys } ->
+      is { inert_dicts = delDict (inert_dicts is) cl tys }
+
+    CFunEqCan { cc_fun  = tf,  cc_tyargs = tys } ->
+      is { inert_funeqs = delFunEq (inert_funeqs is) tf tys }
+
+    CTyEqCan  { cc_tyvar = x,  cc_rhs    = ty  } ->
+      is { inert_eqs = delTyEq (inert_eqs is) x ty }
+
+    CIrredEvCan {}   -> panic "runTcPlugin/removeInert: CIrredEvCan"
+    CNonCanonical {} -> panic "runTcPlugin/removeInert: CNonCanonical"
+    CHoleCan {}      -> panic "runTcPlugin/removeInert: CHoleCan"
+
+
+-- | Extract the (inert) givens and invoke the plugins on them,
+-- removing solved givens from the inert set and emitting unsolvable
+-- constraints as we go.  Return new work produced by all the plugins,
+-- so that 'solveFlatGivens' can feed it back into the main solver.
+--
+-- It is slightly unfortunate that this doesn't quite line up with
+-- 'runTcPluginsWanted'...
+runTcPluginsGiven :: TcS [Ct]
+runTcPluginsGiven = do
     gblEnv <- getGblEnv
-    foldM f (givens, False) (tcg_tc_plugins gblEnv)
+    (givens,_,_) <- fmap splitInertCans getInertCans
+    fmap snd $ foldM f (givens, []) (tcg_tc_plugins gblEnv)
   where
-    f :: (Cts, Bool) -> TcPluginSolver -> TcS (Cts, Bool)
-    f (givens, rerun) solver = do
-      result <- runTcPluginTcS (solver (bagToList givens) [] [])
+    f :: ([Ct], [Ct]) -> TcPluginSolver -> TcS ([Ct], [Ct])
+    f (old_givens, new_givens) solver = do
+      result <- runTcPluginTcS (solver old_givens [] [])
       case result of
         TcPluginContradiction bad_cts -> do
           mapM_ emitInsoluble bad_cts
-          return (discard bad_cts givens, rerun)
-        TcPluginOk [] []              -> return (givens, rerun)
-        TcPluginOk [] new_cts         -> do
-          let new_facts = [ct | ct <- new_cts, not (any (eqCt ct) (bagToList givens))]
-          updWorkListTcS (extendWorkListCts new_facts)
-          return ( unionBags givens (listToBag new_facts)
-                 , rerun || notNull new_facts)
-        TcPluginOk _solved_cts _new_cts ->
-          panic "runTcPluginsGiven: plugin solved a given constraint"
+          return (discard bad_cts old_givens, new_givens)
+        TcPluginOk solved_cts new_cts -> do
+          updInertCans (removeInertCts $ map snd solved_cts)
+          let new_facts = [ct | ct <- new_cts, not (any (eqCt ct) old_givens)]
+          return ( discard (map snd solved_cts) old_givens
+                 , new_facts ++ new_givens)
       where
-        discard cs = filterBag (\ c -> not $ any (eqCt c) cs)
+        discard ys xs = deleteFirstsBy eqCt xs ys
         eqCt c c'  = ctEvPred (ctEvidence c) `eqType` ctEvPred (ctEvidence c')
 
+-- | Given a bag of (flattened, zonked) wanteds, invoke the plugins on
+-- them and produce an updated bag of wanteds.  If the boolean is
+-- 'True', these should be fed back into the main solver.
 runTcPluginsWanted :: Cts -> TcS (Cts, Bool)
 runTcPluginsWanted zonked_wanteds = do
     gblEnv <- getGblEnv



More information about the ghc-commits mailing list