[project @ 2000-10-23 09:03:26 by simonpj]
[ghc-hetmet.git] / ghc / compiler / types / Unify.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
3 %
4 \section{Unify}
5
6 This module contains a unifier and a matcher, both of which
7 use an explicit substitution
8
9 \begin{code}
10 module Unify ( unifyTysX, unifyTyListsX,
11                match, matchTy, matchTys
12   ) where 
13
14 import TypeRep  ( Type(..) )     -- friend
15 import Type     ( typeKind, tyVarsOfType, splitAppTy_maybe )
16
17 import PprType  ()      -- Instances
18                         -- This import isn't strictly necessary, but it makes sure that
19                         -- PprType is below Unify in the hierarchy, which in turn makes
20                         -- fewer modules boot-import PprType
21
22 import Var      ( tyVarKind )
23 import VarSet
24 import VarEnv   ( TyVarSubstEnv, emptySubstEnv, lookupSubstEnv, extendSubstEnv, 
25                   SubstResult(..)
26                 )
27
28 import Outputable( panic )
29 \end{code}
30
31 %************************************************************************
32 %*                                                                      *
33 \subsection{Unification wih a explicit substitution}
34 %*                                                                      *
35 %************************************************************************
36
37 Unify types with an explicit substitution and no monad.
38
39 \begin{code}
40 type MySubst
41    = (TyVarSet,         -- Set of template tyvars
42       TyVarSubstEnv)    -- Not necessarily idempotent
43
44 unifyTysX :: TyVarSet           -- Template tyvars
45           -> Type
46           -> Type
47           -> Maybe TyVarSubstEnv
48 unifyTysX tmpl_tyvars ty1 ty2
49   = uTysX ty1 ty2 (\(_,s) -> Just s) (tmpl_tyvars, emptySubstEnv)
50
51 unifyTyListsX :: TyVarSet -> [Type] -> [Type]
52               -> Maybe TyVarSubstEnv
53 unifyTyListsX tmpl_tyvars tys1 tys2
54   = uTyListsX tys1 tys2 (\(_,s) -> Just s) (tmpl_tyvars, emptySubstEnv)
55
56
57 uTysX :: Type
58       -> Type
59       -> (MySubst -> Maybe result)
60       -> MySubst
61       -> Maybe result
62
63 uTysX (NoteTy _ ty1) ty2 k subst = uTysX ty1 ty2 k subst
64 uTysX ty1 (NoteTy _ ty2) k subst = uTysX ty1 ty2 k subst
65
66         -- Variables; go for uVar
67 uTysX (TyVarTy tyvar1) (TyVarTy tyvar2) k subst 
68   | tyvar1 == tyvar2
69   = k subst
70 uTysX (TyVarTy tyvar1) ty2 k subst@(tmpls,_)
71   | tyvar1 `elemVarSet` tmpls
72   = uVarX tyvar1 ty2 k subst
73 uTysX ty1 (TyVarTy tyvar2) k subst@(tmpls,_)
74   | tyvar2 `elemVarSet` tmpls
75   = uVarX tyvar2 ty1 k subst
76
77         -- Functions; just check the two parts
78 uTysX (FunTy fun1 arg1) (FunTy fun2 arg2) k subst
79   = uTysX fun1 fun2 (uTysX arg1 arg2 k) subst
80
81         -- Type constructors must match
82 uTysX (TyConApp con1 tys1) (TyConApp con2 tys2) k subst
83   | (con1 == con2 && length tys1 == length tys2)
84   = uTyListsX tys1 tys2 k subst
85
86         -- Applications need a bit of care!
87         -- They can match FunTy and TyConApp, so use splitAppTy_maybe
88         -- NB: we've already dealt with type variables and Notes,
89         -- so if one type is an App the other one jolly well better be too
90 uTysX (AppTy s1 t1) ty2 k subst
91   = case splitAppTy_maybe ty2 of
92       Just (s2, t2) -> uTysX s1 s2 (uTysX t1 t2 k) subst
93       Nothing       -> Nothing    -- Fail
94
95 uTysX ty1 (AppTy s2 t2) k subst
96   = case splitAppTy_maybe ty1 of
97       Just (s1, t1) -> uTysX s1 s2 (uTysX t1 t2 k) subst
98       Nothing       -> Nothing    -- Fail
99
100         -- Not expecting for-alls in unification
101 #ifdef DEBUG
102 uTysX (ForAllTy _ _) ty2 k subst = panic "Unify.uTysX subst:ForAllTy (1st arg)"
103 uTysX ty1 (ForAllTy _ _) k subst = panic "Unify.uTysX subst:ForAllTy (2nd arg)"
104 #endif
105
106         -- Anything else fails
107 uTysX ty1 ty2 k subst = Nothing
108
109
110 uTyListsX []         []         k subst = k subst
111 uTyListsX (ty1:tys1) (ty2:tys2) k subst = uTysX ty1 ty2 (uTyListsX tys1 tys2 k) subst
112 uTyListsX tys1       tys2       k subst = Nothing   -- Fail if the lists are different lengths
113 \end{code}
114
115 \begin{code}
116 -- Invariant: tv1 is a unifiable variable
117 uVarX tv1 ty2 k subst@(tmpls, env)
118   = case lookupSubstEnv env tv1 of
119       Just (DoneTy ty1) ->    -- Already bound
120                      uTysX ty1 ty2 k subst
121
122       Nothing        -- Not already bound
123                |  typeKind ty2 == tyVarKind tv1
124                && occur_check_ok ty2
125                ->     -- No kind mismatch nor occur check
126                   k (tmpls, extendSubstEnv env tv1 (DoneTy ty2))
127
128                | otherwise -> Nothing   -- Fail if kind mis-match or occur check
129   where
130     occur_check_ok ty = all occur_check_ok_tv (varSetElems (tyVarsOfType ty))
131     occur_check_ok_tv tv | tv1 == tv = False
132                          | otherwise = case lookupSubstEnv env tv of
133                                          Nothing           -> True
134                                          Just (DoneTy ty)  -> occur_check_ok ty
135 \end{code}
136
137
138
139 %************************************************************************
140 %*                                                                      *
141 \subsection{Matching on types}
142 %*                                                                      *
143 %************************************************************************
144
145 Matching is a {\em unidirectional} process, matching a type against a
146 template (which is just a type with type variables in it).  The
147 matcher assumes that there are no repeated type variables in the
148 template, so that it simply returns a mapping of type variables to
149 types.  It also fails on nested foralls.
150
151 @matchTys@ matches corresponding elements of a list of templates and
152 types.
153
154 \begin{code}
155 matchTy :: TyVarSet                     -- Template tyvars
156         -> Type                         -- Template
157         -> Type                         -- Proposed instance of template
158         -> Maybe TyVarSubstEnv          -- Matching substitution
159                                         
160
161 matchTys :: TyVarSet                    -- Template tyvars
162          -> [Type]                      -- Templates
163          -> [Type]                      -- Proposed instance of template
164          -> Maybe (TyVarSubstEnv,               -- Matching substitution
165                    [Type])              -- Left over instance types
166
167 matchTy tmpls ty1 ty2 = match ty1 ty2 tmpls (\ senv -> Just senv) emptySubstEnv
168
169 matchTys tmpls tys1 tys2 = match_list tys1 tys2 tmpls 
170                                       (\ (senv,tys) -> Just (senv,tys))
171                                       emptySubstEnv
172 \end{code}
173
174 @match@ is the main function.
175
176 \begin{code}
177 match :: Type -> Type                           -- Current match pair
178       -> TyVarSet                               -- Template vars
179       -> (TyVarSubstEnv -> Maybe result)        -- Continuation
180       -> TyVarSubstEnv                          -- Current subst
181       -> Maybe result
182
183 -- When matching against a type variable, see if the variable
184 -- has already been bound.  If so, check that what it's bound to
185 -- is the same as ty; if not, bind it and carry on.
186
187 match (TyVarTy v) ty tmpls k senv
188   | v `elemVarSet` tmpls
189   =     -- v is a template variable
190     case lookupSubstEnv senv v of
191         Nothing -> k (extendSubstEnv senv v (DoneTy ty))
192         Just (DoneTy ty')  | ty' == ty         -> k senv   -- Succeeds
193                            | otherwise         -> Nothing  -- Fails
194
195   | otherwise
196   =     -- v is not a template variable; ty had better match
197         -- Can't use (==) because types differ
198     case ty of
199         TyVarTy v' | v == v' -> k senv    -- Success
200         other                -> Nothing   -- Failure
201
202 match (FunTy arg1 res1) (FunTy arg2 res2) tmpls k senv
203   = match arg1 arg2 tmpls (match res1 res2 tmpls k) senv
204
205 match (AppTy fun1 arg1) ty2 tmpls k senv 
206   = case splitAppTy_maybe ty2 of
207         Just (fun2,arg2) -> match fun1 fun2 tmpls (match arg1 arg2 tmpls k) senv
208         Nothing          -> Nothing     -- Fail
209
210 match (TyConApp tc1 tys1) (TyConApp tc2 tys2) tmpls k senv
211   | tc1 == tc2
212   = match_list tys1 tys2 tmpls k' senv
213   where
214     k' (senv', tys2') | null tys2' = k senv'    -- Succeed
215                       | otherwise  = Nothing    -- Fail 
216
217         -- With type synonyms, we have to be careful for the exact
218         -- same reasons as in the unifier.  Please see the
219         -- considerable commentary there before changing anything
220         -- here! (WDP 95/05)
221 match (NoteTy _ ty1) ty2            tmpls k senv = match ty1 ty2 tmpls k senv
222 match ty1            (NoteTy _ ty2) tmpls k senv = match ty1 ty2 tmpls k senv
223
224 -- Catch-all fails
225 match _ _ _ _ _ = Nothing
226
227 match_list []         tys2       tmpls k senv = k (senv, tys2)
228 match_list (ty1:tys1) []         tmpls k senv = Nothing -- Not enough arg tys => failure
229 match_list (ty1:tys1) (ty2:tys2) tmpls k senv = match ty1 ty2 tmpls (match_list tys1 tys2 tmpls k) senv
230 \end{code}
231
232