Comments only
[ghc-hetmet.git] / compiler / types / FunDeps.lhs
index 8f529a4..02b0a2a 100644 (file)
@@ -10,7 +10,7 @@ It's better to read it as: "if we know these, then we're going to know these"
 \begin{code}
 module FunDeps (
        Equation, pprEquation,
-       oclose, grow, improveOne,
+       oclose, improveOne,
        checkInstCoverage, checkFunDeps,
        pprFundeps
     ) where
@@ -29,6 +29,7 @@ import Outputable
 import Util
 import FastString
 
+import Data.List       ( nubBy )
 import Data.Maybe      ( isJust )
 \end{code}
 
@@ -131,44 +132,6 @@ oclose preds fixed_tvs
              ]
 \end{code}
 
-Note [Growing the tau-tvs using constraints]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-(grow preds tvs) is the result of extend the set of tyvars tvs
-                using all conceivable links from pred
-
-E.g. tvs = {a}, preds = {H [a] b, K (b,Int) c, Eq e}
-Then grow precs tvs = {a,b,c}
-
-All the type variables from an implicit parameter are added, whether or
-not they are mentioned in tvs; see Note [Implicit parameters and ambiguity] 
-in TcSimplify.
-
-See also Note [Ambiguity] in TcSimplify
-
-\begin{code}
-grow :: [PredType] -> TyVarSet -> TyVarSet
-grow preds fixed_tvs 
-  | null preds = fixed_tvs
-  | otherwise  = loop real_fixed_tvs
-  where
-       -- Add the implicit parameters; 
-       -- see Note [Implicit parameters and ambiguity] in TcSimplify
-    real_fixed_tvs = foldr unionVarSet fixed_tvs ip_tvs
-    loop fixed_tvs
-       | new_fixed_tvs `subVarSet` fixed_tvs = fixed_tvs
-       | otherwise                           = loop new_fixed_tvs
-       where
-         new_fixed_tvs = foldl extend fixed_tvs non_ip_tvs
-
-    extend fixed_tvs pred_tvs 
-       | fixed_tvs `intersectsVarSet` pred_tvs = fixed_tvs `unionVarSet` pred_tvs
-       | otherwise                             = fixed_tvs
-
-    (ip_tvs, non_ip_tvs) = partitionWith get_ip preds
-    get_ip (IParam _ ty) = Left (tyVarsOfType ty)
-    get_ip other         = Right (tyVarsOfPred other)
-\end{code}
     
 %************************************************************************
 %*                                                                     *
@@ -201,8 +164,8 @@ type Equation = (TyVarSet, [(Type, Type)])
 
 pprEquation :: Equation -> SDoc
 pprEquation (qtvs, pairs) 
-  = vcat [ptext SLIT("forall") <+> braces (pprWithCommas ppr (varSetElems qtvs)),
-         nest 2 (vcat [ ppr t1 <+> ptext SLIT(":=:") <+> ppr t2 | (t1,t2) <- pairs])]
+  = vcat [ptext (sLit "forall") <+> braces (pprWithCommas ppr (varSetElems qtvs)),
+         nest 2 (vcat [ ppr t1 <+> ptext (sLit "~") <+> ppr t2 | (t1,t2) <- pairs])]
 \end{code}
 
 Given a bunch of predicates that must hold, such as
@@ -293,8 +256,9 @@ improveOne inst_env pred@(ClassP cls tys, _) preds
        , not (instanceCantMatch inst_tcs trimmed_tcs)
        , eqn <- checkClsFD qtvs fd cls_tvs tys_inst tys
        , let p_inst = (mkClassPred cls tys_inst, 
-                       ptext SLIT("arising from the instance declaration at")
-                       <+> ppr (getSrcLoc ispec))
+                       sep [ ptext (sLit "arising from the dependency") <+> quotes (pprFunDep fd)
+                           , ptext (sLit "in the instance declaration at") 
+                                 <+> ppr (getSrcLoc ispec)])
        ]
 
 improveOne _ _ _
@@ -319,7 +283,7 @@ checkClsFD qtvs fd clas_tvs tys1 tys2
 --                 tys2 = [Maybe t1, t2]
 --
 -- We can instantiate x to t1, and then we want to force
---     (Tree x) [t1/x]  :=:   t2
+--     (Tree x) [t1/x]  ~   t2
 --
 -- This function is also used when matching two Insts (rather than an Inst
 -- against an instance decl. In that case, qtvs is empty, and we are doing
@@ -469,7 +433,8 @@ badFunDeps :: [Instance] -> Class
           -> TyVarSet -> [Type]        -- Proposed new instance type
           -> [Instance]
 badFunDeps cls_insts clas ins_tv_set ins_tys 
-  = [ ispec | fd <- fds,       -- fds is often empty
+  = nubBy eq_inst $
+    [ ispec | fd <- fds,       -- fds is often empty, so do this first!
              let trimmed_tcs = trimRoughMatchTcs clas_tvs fd rough_tcs,
              ispec@(Instance { is_tcs = inst_tcs, is_tvs = tvs, 
                                is_tys = tys }) <- cls_insts,
@@ -482,19 +447,26 @@ badFunDeps cls_insts clas ins_tv_set ins_tys
   where
     (clas_tvs, fds) = classTvsFds clas
     rough_tcs = roughMatchTcs ins_tys
+    eq_inst i1 i2 = instanceDFunId i1 == instanceDFunId i2
+       -- An single instance may appear twice in the un-nubbed conflict list
+       -- because it may conflict with more than one fundep.  E.g.
+       --      class C a b c | a -> b, a -> c
+       --      instance C Int Bool Bool
+       --      instance C Int Char Char
+       -- The second instance conflicts with the first by *both* fundeps
 
 trimRoughMatchTcs :: [TyVar] -> FunDep TyVar -> [Maybe Name] -> [Maybe Name]
 -- Computing rough_tcs for a particular fundep
---     class C a b c | a -> b where ... 
+--     class C a b c | a -> b where ...
 -- For each instance .... => C ta tb tc
--- we want to match only on the types ta, tc; so our
+-- we want to match only on the type ta; so our
 -- rough-match thing must similarly be filtered.  
--- Hence, we Nothing-ise the tb type right here
-trimRoughMatchTcs clas_tvs (_,rtvs) mb_tcs
+-- Hence, we Nothing-ise the tb and tc types right here
+trimRoughMatchTcs clas_tvs (ltvs, _) mb_tcs
   = zipWith select clas_tvs mb_tcs
   where
-    select clas_tv mb_tc | clas_tv `elem` rtvs = Nothing
-                        | otherwise           = mb_tc
+    select clas_tv mb_tc | clas_tv `elem` ltvs = mb_tc
+                         | otherwise           = Nothing
 \end{code}