[project @ 2002-09-13 15:02:25 by simonpj]
[ghc-hetmet.git] / ghc / compiler / types / FunDeps.lhs
index f089e98..79f62fb 100644 (file)
@@ -7,20 +7,26 @@ It's better to read it as: "if we know these, then we're going to know these"
 
 \begin{code}
 module FunDeps (
+       Equation, pprEquation, pprEquationDoc,
        oclose, grow, improve, checkInstFDs, checkClsFD, pprFundeps
     ) where
 
 #include "HsVersions.h"
 
-import Var             ( TyVar )
+import Name            ( getSrcLoc )
+import Var             ( Id, TyVar )
 import Class           ( Class, FunDep, classTvsFds )
-import Type            ( Type, ThetaType, PredType(..), predTyUnique, tyVarsOfTypes, tyVarsOfPred )
 import Subst           ( mkSubst, emptyInScopeSet, substTy )
-import Unify           ( unifyTyListsX )
-import Outputable      ( Outputable, SDoc, interppSP, ptext, empty, hsep, punctuate, comma )
+import TcType          ( Type, ThetaType, SourceType(..), PredType,
+                         predTyUnique, mkClassPred, tyVarsOfTypes, tyVarsOfPred,
+                         unifyTyListsX, unifyExtendTysX, tcEqType
+                       )
+import PprType         (  )
 import VarSet
 import VarEnv
+import Outputable
 import List            ( tails )
+import Maybes          ( maybeToBool )
 import ListSetOps      ( equivClassesByUniq )
 \end{code}
 
@@ -107,7 +113,7 @@ oclose preds fixed_tvs
        -- In our example, tv_fds will be [ ({x,y}, {z}), ({x,p},{q}) ]
        -- Meaning "knowing x,y fixes z, knowing x,p fixes q"
     tv_fds  = [ (tyVarsOfTypes xs, tyVarsOfTypes ys)
-             | Class cls tys <- preds,         -- Ignore implicit params
+             | ClassP cls tys <- preds,                -- Ignore implicit params
                let (cls_tvs, cls_fds) = classTvsFds cls,
                fd <- cls_fds,
                let (xs,ys) = instFD fd cls_tvs tys
@@ -117,8 +123,8 @@ oclose preds fixed_tvs
 \begin{code}
 grow :: [PredType] -> TyVarSet -> TyVarSet
 grow preds fixed_tvs 
-  | null pred_sets = fixed_tvs
-  | otherwise     = loop fixed_tvs
+  | null preds = fixed_tvs
+  | otherwise  = loop fixed_tvs
   where
     loop fixed_tvs
        | new_fixed_tvs `subVarSet` fixed_tvs = fixed_tvs
@@ -142,14 +148,28 @@ grow preds fixed_tvs
 
 \begin{code}
 ----------
-type Equation = (Type,Type)    -- These two types should be equal
-                               -- INVARIANT: they aren't already equal
+type Equation = (TyVarSet, Type, Type) -- These two types should be equal, for some
+                                       -- substitution of the tyvars in the tyvar set
+       -- For example, ({a,b}, (a,Int,b), (Int,z,Bool))
+       -- We unify z with Int, but since a and b are quantified we do nothing to them
+       -- We usually act on an equation by instantiating the quantified type varaibles
+       -- to fresh type variables, and then calling the standard unifier.
+       -- 
+       -- INVARIANT: they aren't already equal
+       --
+
+
+pprEquationDoc (eqn, doc) = vcat [pprEquation eqn, nest 2 doc]
+
+pprEquation (qtvs, t1, t2) = ptext SLIT("forall") <+> braces (pprWithCommas ppr (varSetElems qtvs))
+                                                 <+> ppr t1 <+> ptext SLIT(":=:") <+> ppr t2
 
 ----------
-improve :: InstEnv a           -- Gives instances for given class
-       -> [PredType]           -- Current constraints
-       -> [Equation]           -- Derived equalities that must also hold
+improve :: InstEnv Id          -- Gives instances for given class
+       -> [(PredType,SDoc)]    -- Current constraints; doc says where they come from
+       -> [(Equation,SDoc)]    -- Derived equalities that must also hold
                                -- (NB the above INVARIANT for type Equation)
+                               -- The SDoc explains why the equation holds (for error messages)
 
 type InstEnv a = Class -> [(TyVarSet, [Type], a)]
 -- This is a bit clumsy, because InstEnv is really
@@ -190,22 +210,23 @@ NOTA BENE:
 
 \begin{code}
 improve inst_env preds
-  = [ eqn | group <- equivClassesByUniq predTyUnique preds,
+  = [ eqn | group <- equivClassesByUniq (predTyUnique . fst) preds,
            eqn   <- checkGroup inst_env group ]
 
 ----------
-checkGroup :: InstEnv a -> [PredType] -> [Equation]
+checkGroup :: InstEnv Id -> [(PredType,SDoc)] -> [(Equation, SDoc)]
   -- The preds are all for the same class or implicit param
 
-checkGroup inst_env (IParam _ ty : ips)
+checkGroup inst_env (p1@(IParam _ ty, _) : ips)
   =    -- For implicit parameters, all the types must match
-    [(ty, ty') | IParam _ ty' <- ips, ty /= ty']
+    [ ((emptyVarSet, ty, ty'), mkEqnMsg p1 p2) 
+    | p2@(IParam _ ty', _) <- ips, not (ty `tcEqType` ty')]
 
-checkGroup inst_env clss@(Class cls tys : _)
+checkGroup inst_env clss@((ClassP cls _, _) : _)
   =    -- For classes life is more complicated  
        -- Suppose the class is like
        --      classs C as | (l1 -> r1), (l2 -> r2), ... where ...
-       -- Then FOR EACH PAIR (Class c tys1, Class c tys2) in the list clss
+       -- Then FOR EACH PAIR (ClassP c tys1, ClassP c tys2) in the list clss
        -- we check whether
        --      U l1[tys1/as] = U l2[tys2/as]
        --  (where U is a unifier)
@@ -223,42 +244,73 @@ checkGroup inst_env clss@(Class cls tys : _)
 
        -- NOTE that we iterate over the fds first; they are typically
        -- empty, which aborts the rest of the loop.
-    pairwise_eqns :: [(Type,Type)]
+    pairwise_eqns :: [(Equation,SDoc)]
     pairwise_eqns      -- This group comes from pairwise comparison
-      = [ eqn | fd <- cls_fds,
-               Class _ tys1 : rest <- tails clss,
-               Class _ tys2    <- rest,
-               eqn <- checkClsFD emptyVarSet fd cls_tvs tys1 tys2
+      = [ (eqn, mkEqnMsg p1 p2)
+       | fd <- cls_fds,
+         p1@(ClassP _ tys1, _) : rest <- tails clss,
+         p2@(ClassP _ tys2, _) <- rest,
+         eqn <- checkClsFD emptyVarSet fd cls_tvs tys1 tys2
        ]
 
-    instance_eqns :: [(Type,Type)]
+    instance_eqns :: [(Equation,SDoc)]
     instance_eqns      -- This group comes from comparing with instance decls
-      = [ eqn | fd <- cls_fds,
-               (qtvs, tys1, _) <- cls_inst_env,
-               Class _ tys2    <- clss,
-               eqn <- checkClsFD qtvs fd cls_tvs tys1 tys2
+      = [ (eqn, mkEqnMsg p1 p2)
+       | fd <- cls_fds,
+         (qtvs, tys1, dfun_id)  <- cls_inst_env,
+         let p1 = (mkClassPred cls tys1, 
+                   ptext SLIT("arising from the instance declaration at") <+> ppr (getSrcLoc dfun_id)),
+         p2@(ClassP _ tys2, _) <- clss,
+         eqn <- checkClsFD qtvs fd cls_tvs tys1 tys2
        ]
 
-
+mkEqnMsg (pred1,from1) (pred2,from2)
+  = vcat [ptext SLIT("When using functional dependencies to combine"),
+         nest 2 (sep [ppr pred1 <> comma, nest 2 from1]), 
+         nest 2 (sep [ppr pred2 <> comma, nest 2 from2])]
 ----------
-checkClsFD :: TyVarSet                         -- The quantified type variables, which
-                                       -- can be instantiated to make the types match
+checkClsFD :: TyVarSet                         -- Quantified type variables; see note below
           -> FunDep TyVar -> [TyVar]   -- One functional dependency from the class
           -> [Type] -> [Type]
           -> [Equation]
 
 checkClsFD qtvs fd clas_tvs tys1 tys2
+-- 'qtvs' are the quantified type variables, the ones which an be instantiated 
+-- to make the types match.  For example, given
+--     class C a b | a->b where ...
+--     instance C (Maybe x) (Tree x) where ..
+-- and an Inst of form (C (Maybe t1 t2), 
+-- then we will call checkClsFD with
+--
+--     qtvs = {x}, tys1 = [Maybe x,  Tree x]
+--                 tys2 = [Maybe t1, t2]
+--
+-- We can instantiate x to t1, and then we want to force
+--     Tree x [t1/x]  :=:   t2
+
 -- We use 'unify' even though we are often only matching
 -- unifyTyListsX will only bind variables in qtvs, so it's OK!
   = case unifyTyListsX qtvs ls1 ls2 of
        Nothing   -> []
-       Just unif -> [(sr1, sr2) | (r1,r2) <- rs1 `zip` rs2,
-                                  let sr1 = substTy full_unif r1,
-                                  let sr2 = substTy full_unif r2,
-                                  sr1 /= sr2]
+       Just unif -> -- pprTrace "checkFD" (vcat [ppr_fd fd,
+                    --                        ppr (varSetElems qtvs) <+> (ppr ls1 $$ ppr ls2),
+                    --                        ppr unif]) $ 
+                    [ (qtvs', substTy full_unif r1, substTy full_unif r2)
+                    | (r1,r2) <- rs1 `zip` rs2,
+                      not (maybeToBool (unifyExtendTysX qtvs unif r1 r2))]
+                       -- Don't include any equations that already hold
+                       -- taking account of the fact that any qtvs that aren't 
+                       -- already instantiated can be instantiated to anything at all
+                       -- NB: qtvs, not qtvs' because unifyExtendTysX only tries to
+                       --     look template tyvars up in the substitution
                  where
                    full_unif = mkSubst emptyInScopeSet unif
                        -- No for-alls in sight; hmm
+
+                   qtvs' = filterVarSet (\v -> not (v `elemSubstEnv` unif)) qtvs
+                       -- qtvs' are the quantified type variables
+                       -- that have not been substituted out
   where
     (ls1, rs1) = instFD fd clas_tvs tys1
     (ls2, rs2) = instFD fd clas_tvs tys2