X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2Ftypes%2FFunDeps.lhs;h=7f9f0509e2f2a14f58a6d4a817dd9622fa38746b;hb=1ae354e107715a9e3fd4e2d67b61f868c090e4ae;hp=a7e9f19b064d9ea6931460dae45a0d7d50e67f43;hpb=d9e439063bbd9827df7a6f75471834d8479c3ea3;p=ghc-hetmet.git diff --git a/compiler/types/FunDeps.lhs b/compiler/types/FunDeps.lhs index a7e9f19..7f9f050 100644 --- a/compiler/types/FunDeps.lhs +++ b/compiler/types/FunDeps.lhs @@ -8,13 +8,6 @@ FunDeps - functional dependencies It's better to read it as: "if we know these, then we're going to know these" \begin{code} -{-# OPTIONS -w #-} --- The above warning supression flag is a temporary kludge. --- While working on this module you are encouraged to remove it and fix --- any warnings in the module. See --- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings --- for details - module FunDeps ( Equation, pprEquation, oclose, grow, improveOne, @@ -27,13 +20,16 @@ module FunDeps ( import Name import Var import Class -import TcGadt import TcType +import Unify import InstEnv import VarSet import VarEnv import Outputable import Util +import FastString + +import Data.List ( nubBy ) import Data.Maybe ( isJust ) \end{code} @@ -204,9 +200,10 @@ type Equation = (TyVarSet, [(Type, Type)]) -- We usually act on an equation by instantiating the quantified type varaibles -- to fresh type variables, and then calling the standard unifier. +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 @@ -250,7 +247,7 @@ improveOne :: (Class -> [Instance]) -- Gives instances for given class -- combined (for error messages) -- Just do improvement triggered by a single, distinguised predicate -improveOne inst_env pred@(IParam ip ty, _) preds +improveOne _inst_env pred@(IParam ip ty, _) preds = [ ((emptyVarSet, [(ty,ty2)]), pred, p2) | p2@(IParam ip2 ty2, _) <- preds , ip==ip2 @@ -297,11 +294,11 @@ 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") + ptext (sLit "arising from the instance declaration at") <+> ppr (getSrcLoc ispec)) ] -improveOne inst_env eq_pred preds +improveOne _ _ _ = [] @@ -473,7 +470,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, @@ -486,19 +484,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}