Fix a pair of classic, but tricky, bugs in the type matcher; exposed by a program...
[ghc-hetmet.git] / compiler / types / Unify.lhs
index 9f5b405..34993ad 100644 (file)
@@ -1,3 +1,7 @@
+%
+% (c) The University of Glasgow 2006
+%
+
 \begin{code}
 module Unify ( 
        -- Matching of types: 
@@ -8,16 +12,11 @@ module Unify (
 
 #include "HsVersions.h"
 
-import Var             ( Var, TyVar, tyVarKind )
+import Var
 import VarEnv
 import VarSet
-import Type            ( typeKind, tyVarsOfType, tyVarsOfTypes, tyVarsOfTheta, mkTyVarTys,
-                         TvSubstEnv, emptyTvSubstEnv, TvSubst(..), substTy, tcEqTypeX,
-                         mkOpenTvSubst, tcView, isSubKind, eqKind, repSplitAppTy_maybe )
-import TypeRep          ( Type(..), PredType(..), funTyCon )
-import DataCon                 ( DataCon, dataConResTys )
-import Util            ( snocView )
-import ErrUtils                ( Message )
+import Type
+import TypeRep
 import Outputable
 import Maybes
 \end{code}
@@ -121,24 +120,26 @@ match :: MatchEnv -- For the most part this is pushed downwards
 -- it respects NewTypes and PredType
 
 match menv subst ty1 ty2 | Just ty1' <- tcView ty1 = match menv subst ty1' ty2
-match menv subst ty1 ty2 | Just ty2' <- tcView ty2 = match menv subst ty1 ty2'
+                         | Just ty2' <- tcView ty2 = match menv subst ty1 ty2'
 
 match menv subst (TyVarTy tv1) ty2
-  | tv1 `elemVarSet` me_tmpls menv
+  | tv1' `elemVarSet` me_tmpls menv
   = case lookupVarEnv subst tv1' of
-       Nothing | any (inRnEnvR rn_env) (varSetElems (tyVarsOfType ty2))
-               -> Nothing      -- Occurs check
-               | not (typeKind ty2 `isSubKind` tyVarKind tv1)
-               -> Nothing      -- Kind mis-match
-               | otherwise
-               -> Just (extendVarEnv subst tv1 ty2)
-
-       Just ty1' | tcEqTypeX (nukeRnEnvL rn_env) ty1' ty2
+       Nothing         -- No existing binding
+           | any (inRnEnvR rn_env) (varSetElems (tyVarsOfType ty2))
+           -> Nothing  -- Occurs check
+           | not (typeKind ty2 `isSubKind` tyVarKind tv1)
+           -> Nothing  -- Kind mis-match
+           | otherwise
+           -> Just (extendVarEnv subst tv1' ty2)
+
+       Just ty1'       -- There is an existing binding; check whether ty2 matches it
+           | tcEqTypeX (nukeRnEnvL rn_env) ty1' ty2
                -- ty1 has no locally-bound variables, hence nukeRnEnvL
                -- Note tcEqType...we are doing source-type matching here
-                 -> Just subst
-
-       other -> Nothing
+           -> Just subst
+           | otherwise -> Nothing      -- ty2 doesn't match
+           
 
    | otherwise -- tv1 is not a template tyvar
    = case ty2 of
@@ -162,6 +163,7 @@ match menv subst (FunTy ty1a ty1b) (FunTy ty2a ty2b)
        ; match menv subst' ty1b ty2b }
 match menv subst (AppTy ty1a ty1b) ty2
   | Just (ty2a, ty2b) <- repSplitAppTy_maybe ty2
+       -- 'repSplit' used because the tcView stuff is done above
   = do { subst' <- match menv subst ty1a ty2a
        ; match menv subst' ty1b ty2b }