[commit: ghc] wip/redundant-constraints: Replace fixVarSet with transCloVarSet (eaf2638)

git at git.haskell.org git at git.haskell.org
Mon Jan 5 15:01:16 UTC 2015


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

On branch  : wip/redundant-constraints
Link       : http://ghc.haskell.org/trac/ghc/changeset/eaf2638b24c1fc1d40a8d7bb782349e5ed989852/ghc

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

commit eaf2638b24c1fc1d40a8d7bb782349e5ed989852
Author: Simon Peyton Jones <simonpj at microsoft.com>
Date:   Sat Jan 3 23:36:09 2015 +0000

    Replace fixVarSet with transCloVarSet
    
    I think the new implementation is a bit more efficient, because
    it uses a work-list, rather than iterating over the entire set
    every time


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

eaf2638b24c1fc1d40a8d7bb782349e5ed989852
 compiler/basicTypes/VarSet.hs    | 29 ++++++++++++++++++++++-------
 compiler/typecheck/TcSimplify.hs | 31 +++++++++++++++++--------------
 2 files changed, 39 insertions(+), 21 deletions(-)

diff --git a/compiler/basicTypes/VarSet.hs b/compiler/basicTypes/VarSet.hs
index c134124..6c920ba 100644
--- a/compiler/basicTypes/VarSet.hs
+++ b/compiler/basicTypes/VarSet.hs
@@ -16,7 +16,8 @@ module VarSet (
         unionVarSet, unionVarSets, mapUnionVarSet,
         intersectVarSet, intersectsVarSet, disjointVarSet,
         isEmptyVarSet, delVarSet, delVarSetList, delVarSetByKey,
-        minusVarSet, foldVarSet, filterVarSet, fixVarSet,
+        minusVarSet, foldVarSet, filterVarSet, 
+        transCloVarSet,
         lookupVarSet, mapVarSet, sizeVarSet, seqVarSet,
         elemVarSetByKey, partitionVarSet
     ) where
@@ -69,7 +70,6 @@ extendVarSet_C  :: (Var->Var->Var) -> VarSet -> Var -> VarSet
 
 delVarSetByKey  :: VarSet -> Unique -> VarSet
 elemVarSetByKey :: Unique -> VarSet -> Bool
-fixVarSet       :: (VarSet -> VarSet) -> VarSet -> VarSet
 partitionVarSet :: (Var -> Bool) -> VarSet -> (VarSet, VarSet)
 
 emptyVarSet     = emptyUniqSet
@@ -110,11 +110,26 @@ intersectsVarSet s1 s2 = not (s1 `disjointVarSet` s2)
 disjointVarSet   s1 s2 = isEmptyVarSet (s1 `intersectVarSet` s2)
 subVarSet        s1 s2 = isEmptyVarSet (s1 `minusVarSet` s2)
 
--- Iterate f to a fixpoint
-fixVarSet f s | new_s `subVarSet` s = s
-              | otherwise           = fixVarSet f new_s
-              where
-                new_s = f s
+transCloVarSet :: (VarSet -> VarSet)
+                  -- Map some variables in the set to 
+                  -- *extra* variables that should be in it
+               -> VarSet -> VarSet
+-- (transCloVarSet f s) repeatedly applies f to the set s, adding any
+-- new variables to s that it finds thereby, until it reaches a fixed
+-- point.  The actual algorithm is a bit more efficient.
+transCloVarSet fn seeds
+  = go seeds seeds
+  where
+    go :: VarSet  -- Accumulating result
+       -> VarSet  -- Work-list; un-processed subset of accumulating result
+       -> VarSet
+    -- Specification: go acc vs = acc `union` transClo fn vs
+   
+    go acc candidates
+       | isEmptyVarSet new_vs = acc
+       | otherwise            = go (acc `unionVarSet` new_vs) new_vs
+       where
+         new_vs = fn candidates `minusVarSet` acc
 
 seqVarSet :: VarSet -> ()
 seqVarSet s = sizeVarSet s `seq` ()
diff --git a/compiler/typecheck/TcSimplify.hs b/compiler/typecheck/TcSimplify.hs
index 01da61f..0c9b093 100644
--- a/compiler/typecheck/TcSimplify.hs
+++ b/compiler/typecheck/TcSimplify.hs
@@ -468,17 +468,18 @@ quantifyPred qtvs pred
 growThetaTyVars :: ThetaType -> TyVarSet -> TyVarSet
 -- See Note [Growing the tau-tvs using constraints]
 growThetaTyVars theta tvs
-  | null theta             = tvs
-  | isEmptyVarSet seed_tvs = tvs
-  | otherwise              = fixVarSet mk_next seed_tvs
+  | null theta = tvs
+  | otherwise  = transCloVarSet mk_next seed_tvs
   where
     seed_tvs = tvs `unionVarSet` tyVarsOfTypes ips
     (ips, non_ips) = partition isIPPred theta
                          -- See note [Inheriting implicit parameters]
-    mk_next tvs = foldr grow_one tvs non_ips
-    grow_one pred tvs
-       | pred_tvs `intersectsVarSet` tvs = tvs `unionVarSet` pred_tvs
-       | otherwise                       = tvs
+
+    mk_next :: VarSet -> VarSet -- Maps current set to newly-grown ones
+    mk_next so_far = foldr (grow_one so_far) emptyVarSet non_ips
+    grow_one so_far pred tvs
+       | pred_tvs `intersectsVarSet` so_far = tvs `unionVarSet` pred_tvs
+       | otherwise                          = tvs
        where
          pred_tvs = tyVarsOfType pred
 
@@ -990,14 +991,16 @@ approximateWC wc
       = filterBag is_floatable simples `unionBags`
         do_bag (float_implic new_trapping_tvs) implics
       where
-        new_trapping_tvs = fixVarSet grow trapping_tvs
         is_floatable ct = tyVarsOfCt ct `disjointVarSet` new_trapping_tvs
-
-        grow tvs = foldrBag grow_one tvs simples
-        grow_one ct tvs | ct_tvs `intersectsVarSet` tvs = tvs `unionVarSet` ct_tvs
-                        | otherwise                     = tvs
-                        where
-                          ct_tvs = tyVarsOfCt ct
+        new_trapping_tvs = transCloVarSet grow trapping_tvs
+
+        grow :: VarSet -> VarSet  -- Maps current trapped tyvars to newly-trapped ones
+        grow so_far = foldrBag (grow_one so_far) emptyVarSet simples
+        grow_one so_far ct tvs 
+          | ct_tvs `intersectsVarSet` so_far = tvs `unionVarSet` ct_tvs
+          | otherwise                        = tvs
+          where
+            ct_tvs = tyVarsOfCt ct
 
     float_implic :: TcTyVarSet -> Implication -> Cts
     float_implic trapping_tvs imp



More information about the ghc-commits mailing list