-
Notifications
You must be signed in to change notification settings - Fork 0
/
Unify.lhs
781 lines (638 loc) · 25.6 KB
/
Unify.lhs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
%
% (c) The University of Glasgow 2006
%
\begin{code}
module Unify (
-- Matching of types:
-- the "tc" prefix indicates that matching always
-- respects newtypes (rather than looking through them)
tcMatchTy, tcMatchTys, tcMatchTyX,
ruleMatchTyX, tcMatchPreds, MatchEnv(..),
dataConCannotMatch,
-- GADT type refinement
Refinement, emptyRefinement, isEmptyRefinement,
matchRefine, refineType, refinePred, refineResType,
-- side-effect free unification
tcUnifyTys, BindFlag(..)
) where
#include "HsVersions.h"
import Var
import VarEnv
import VarSet
import Type
import Coercion
import TyCon
import DataCon
import TypeRep
import Outputable
import ErrUtils
import Util
import Maybes
import UniqFM
import FastString
\end{code}
%************************************************************************
%* *
Matching
%* *
%************************************************************************
Matching is much tricker than you might think.
1. The substitution we generate binds the *template type variables*
which are given to us explicitly.
2. We want to match in the presence of foralls;
e.g (forall a. t1) ~ (forall b. t2)
That is what the RnEnv2 is for; it does the alpha-renaming
that makes it as if a and b were the same variable.
Initialising the RnEnv2, so that it can generate a fresh
binder when necessary, entails knowing the free variables of
both types.
3. We must be careful not to bind a template type variable to a
locally bound variable. E.g.
(forall a. x) ~ (forall b. b)
where x is the template type variable. Then we do not want to
bind x to a/b! This is a kind of occurs check.
The necessary locals accumulate in the RnEnv2.
\begin{code}
data MatchEnv
= ME { me_tmpls :: VarSet -- Template tyvars
, me_env :: RnEnv2 -- Renaming envt for nested foralls
} -- In-scope set includes template tyvars
tcMatchTy :: TyVarSet -- Template tyvars
-> Type -- Template
-> Type -- Target
-> Maybe TvSubst -- One-shot; in principle the template
-- variables could be free in the target
tcMatchTy tmpls ty1 ty2
= case match menv emptyTvSubstEnv ty1 ty2 of
Just subst_env -> Just (TvSubst in_scope subst_env)
Nothing -> Nothing
where
menv = ME { me_tmpls = tmpls, me_env = mkRnEnv2 in_scope }
in_scope = mkInScopeSet (tmpls `unionVarSet` tyVarsOfType ty2)
-- We're assuming that all the interesting
-- tyvars in tys1 are in tmpls
tcMatchTys :: TyVarSet -- Template tyvars
-> [Type] -- Template
-> [Type] -- Target
-> Maybe TvSubst -- One-shot; in principle the template
-- variables could be free in the target
tcMatchTys tmpls tys1 tys2
= case match_tys menv emptyTvSubstEnv tys1 tys2 of
Just subst_env -> Just (TvSubst in_scope subst_env)
Nothing -> Nothing
where
menv = ME { me_tmpls = tmpls, me_env = mkRnEnv2 in_scope }
in_scope = mkInScopeSet (tmpls `unionVarSet` tyVarsOfTypes tys2)
-- We're assuming that all the interesting
-- tyvars in tys1 are in tmpls
-- This is similar, but extends a substitution
tcMatchTyX :: TyVarSet -- Template tyvars
-> TvSubst -- Substitution to extend
-> Type -- Template
-> Type -- Target
-> Maybe TvSubst
tcMatchTyX tmpls (TvSubst in_scope subst_env) ty1 ty2
= case match menv subst_env ty1 ty2 of
Just subst_env -> Just (TvSubst in_scope subst_env)
Nothing -> Nothing
where
menv = ME {me_tmpls = tmpls, me_env = mkRnEnv2 in_scope}
tcMatchPreds
:: [TyVar] -- Bind these
-> [PredType] -> [PredType]
-> Maybe TvSubstEnv
tcMatchPreds tmpls ps1 ps2
= match_list (match_pred menv) emptyTvSubstEnv ps1 ps2
where
menv = ME { me_tmpls = mkVarSet tmpls, me_env = mkRnEnv2 in_scope_tyvars }
in_scope_tyvars = mkInScopeSet (tyVarsOfTheta ps1 `unionVarSet` tyVarsOfTheta ps2)
-- This one is called from the expression matcher, which already has a MatchEnv in hand
ruleMatchTyX :: MatchEnv
-> TvSubstEnv -- Substitution to extend
-> Type -- Template
-> Type -- Target
-> Maybe TvSubstEnv
ruleMatchTyX menv subst ty1 ty2 = match menv subst ty1 ty2 -- Rename for export
\end{code}
Now the internals of matching
\begin{code}
match :: MatchEnv -- For the most part this is pushed downwards
-> TvSubstEnv -- Substitution so far:
-- Domain is subset of template tyvars
-- Free vars of range is subset of
-- in-scope set of the RnEnv2
-> Type -> Type -- Template and target respectively
-> Maybe TvSubstEnv
-- This matcher works on core types; that is, it ignores PredTypes
-- Watch out if newtypes become transparent agin!
-- this matcher must respect newtypes
match menv subst ty1 ty2 | Just ty1' <- coreView ty1 = match menv subst ty1' ty2
| Just ty2' <- coreView ty2 = match menv subst ty1 ty2'
match menv subst (TyVarTy tv1) ty2
| Just ty1' <- lookupVarEnv subst tv1' -- tv1' is already bound
= if tcEqTypeX (nukeRnEnvL rn_env) ty1' ty2
-- ty1 has no locally-bound variables, hence nukeRnEnvL
-- Note tcEqType...we are doing source-type matching here
then Just subst
else Nothing -- ty2 doesn't match
| tv1' `elemVarSet` me_tmpls menv
= if any (inRnEnvR rn_env) (varSetElems (tyVarsOfType ty2))
then Nothing -- Occurs check
else do { subst1 <- match_kind menv subst tv1 ty2
-- Note [Matching kinds]
; return (extendVarEnv subst1 tv1' ty2) }
| otherwise -- tv1 is not a template tyvar
= case ty2 of
TyVarTy tv2 | tv1' == rnOccR rn_env tv2 -> Just subst
_ -> Nothing
where
rn_env = me_env menv
tv1' = rnOccL rn_env tv1
match menv subst (ForAllTy tv1 ty1) (ForAllTy tv2 ty2)
= match menv' subst ty1 ty2
where -- Use the magic of rnBndr2 to go under the binders
menv' = menv { me_env = rnBndr2 (me_env menv) tv1 tv2 }
match menv subst (PredTy p1) (PredTy p2)
= match_pred menv subst p1 p2
match menv subst (TyConApp tc1 tys1) (TyConApp tc2 tys2)
| tc1 == tc2 = match_tys menv subst tys1 tys2
match menv subst (FunTy ty1a ty1b) (FunTy ty2a ty2b)
= do { subst' <- match menv subst ty1a ty2a
; 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 }
match _ _ _ _
= Nothing
--------------
match_kind :: MatchEnv -> TvSubstEnv -> TyVar -> Type -> Maybe TvSubstEnv
-- Match the kind of the template tyvar with the kind of Type
-- Note [Matching kinds]
match_kind menv subst tv ty
| isCoVar tv = do { let (ty1,ty2) = splitCoercionKind (tyVarKind tv)
(ty3,ty4) = coercionKind ty
; subst1 <- match menv subst ty1 ty3
; match menv subst1 ty2 ty4 }
| otherwise = if typeKind ty `isSubKind` tyVarKind tv
then Just subst
else Nothing
-- Note [Matching kinds]
-- ~~~~~~~~~~~~~~~~~~~~~
-- For ordinary type variables, we don't want (m a) to match (n b)
-- if say (a::*) and (b::*->*). This is just a yes/no issue.
--
-- For coercion kinds matters are more complicated. If we have a
-- coercion template variable co::a~[b], where a,b are presumably also
-- template type variables, then we must match co's kind against the
-- kind of the actual argument, so as to give bindings to a,b.
--
-- In fact I have no example in mind that *requires* this kind-matching
-- to instantiate template type variables, but it seems like the right
-- thing to do. C.f. Note [Matching variable types] in Rules.lhs
--------------
match_tys :: MatchEnv -> TvSubstEnv -> [Type] -> [Type] -> Maybe TvSubstEnv
match_tys menv subst tys1 tys2 = match_list (match menv) subst tys1 tys2
--------------
match_list :: (TvSubstEnv -> a -> a -> Maybe TvSubstEnv)
-> TvSubstEnv -> [a] -> [a] -> Maybe TvSubstEnv
match_list _ subst [] [] = Just subst
match_list fn subst (ty1:tys1) (ty2:tys2) = do { subst' <- fn subst ty1 ty2
; match_list fn subst' tys1 tys2 }
match_list _ _ _ _ = Nothing
--------------
match_pred :: MatchEnv -> TvSubstEnv -> PredType -> PredType -> Maybe TvSubstEnv
match_pred menv subst (ClassP c1 tys1) (ClassP c2 tys2)
| c1 == c2 = match_tys menv subst tys1 tys2
match_pred menv subst (IParam n1 t1) (IParam n2 t2)
| n1 == n2 = match menv subst t1 t2
match_pred _ _ _ _ = Nothing
\end{code}
%************************************************************************
%* *
GADTs
%* *
%************************************************************************
Note [Pruning dead case alternatives]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider data T a where
T1 :: T Int
T2 :: T a
newtype X = MkX Int
newtype Y = MkY Char
type family F a
type instance F Bool = Int
Now consider case x of { T1 -> e1; T2 -> e2 }
The question before the house is this: if I know something about the type
of x, can I prune away the T1 alternative?
Suppose x::T Char. It's impossible to construct a (T Char) using T1,
Answer = YES (clearly)
Suppose x::T (F a), where 'a' is in scope. Then 'a' might be instantiated
to 'Bool', in which case x::T Int, so
ANSWER = NO (clearly)
Suppose x::T X. Then *in Haskell* it's impossible to construct a (non-bottom)
value of type (T X) using T1. But *in FC* it's quite possible. The newtype
gives a coercion
CoX :: X ~ Int
So (T CoX) :: T X ~ T Int; hence (T1 `cast` sym (T CoX)) is a non-bottom value
of type (T X) constructed with T1. Hence
ANSWER = NO (surprisingly)
Furthermore, this can even happen; see Trac #1251. GHC's newtype-deriving
mechanism uses a cast, just as above, to move from one dictionary to another,
in effect giving the programmer access to CoX.
Finally, suppose x::T Y. Then *even in FC* we can't construct a
non-bottom value of type (T Y) using T1. That's because we can get
from Y to Char, but not to Int.
Here's a related question. data Eq a b where EQ :: Eq a a
Consider
case x of { EQ -> ... }
Suppose x::Eq Int Char. Is the alternative dead? Clearly yes.
What about x::Eq Int a, in a context where we have evidence that a~Char.
Then again the alternative is dead.
Summary
We are really doing a test for unsatisfiability of the type
constraints implied by the match. And that is clearly, in general, a
hard thing to do.
However, since we are simply dropping dead code, a conservative test
suffices. There is a continuum of tests, ranging from easy to hard, that
drop more and more dead code.
For now we implement a very simple test: type variables match
anything, type functions (incl newtypes) match anything, and only
distinct data types fail to match. We can elaborate later.
\begin{code}
dataConCannotMatch :: [Type] -> DataCon -> Bool
-- Returns True iff the data con *definitely cannot* match a
-- scrutinee of type (T tys)
-- where T is the type constructor for the data con
--
dataConCannotMatch tys con
| null eq_spec = False -- Common
| all isTyVarTy tys = False -- Also common
| otherwise
= cant_match_s (map (substTyVar subst . fst) eq_spec)
(map snd eq_spec)
where
dc_tvs = dataConUnivTyVars con
eq_spec = dataConEqSpec con
subst = zipTopTvSubst dc_tvs tys
cant_match_s :: [Type] -> [Type] -> Bool
cant_match_s tys1 tys2 = ASSERT( equalLength tys1 tys2 )
or (zipWith cant_match tys1 tys2)
cant_match :: Type -> Type -> Bool
cant_match t1 t2
| Just t1' <- coreView t1 = cant_match t1' t2
| Just t2' <- coreView t2 = cant_match t1 t2'
cant_match (FunTy a1 r1) (FunTy a2 r2)
= cant_match a1 a2 || cant_match r1 r2
cant_match (TyConApp tc1 tys1) (TyConApp tc2 tys2)
| isDataTyCon tc1 && isDataTyCon tc2
= tc1 /= tc2 || cant_match_s tys1 tys2
cant_match (FunTy {}) (TyConApp tc _) = isDataTyCon tc
cant_match (TyConApp tc _) (FunTy {}) = isDataTyCon tc
-- tc can't be FunTyCon by invariant
cant_match (AppTy f1 a1) ty2
| Just (f2, a2) <- repSplitAppTy_maybe ty2
= cant_match f1 f2 || cant_match a1 a2
cant_match ty1 (AppTy f2 a2)
| Just (f1, a1) <- repSplitAppTy_maybe ty1
= cant_match f1 f2 || cant_match a1 a2
cant_match _ _ = False -- Safe!
-- Things we could add;
-- foralls
-- look through newtypes
-- take account of tyvar bindings (EQ example above)
\end{code}
%************************************************************************
%* *
What a refinement is
%* *
%************************************************************************
\begin{code}
data Refinement = Reft InScopeSet InternalReft
type InternalReft = TyVarEnv (Coercion, Type)
-- INVARIANT: a->(co,ty) then co :: (a:=:ty)
-- Not necessarily idemopotent
instance Outputable Refinement where
ppr (Reft _in_scope env)
= ptext (sLit "Refinement") <+>
braces (ppr env)
emptyRefinement :: Refinement
emptyRefinement = (Reft emptyInScopeSet emptyVarEnv)
isEmptyRefinement :: Refinement -> Bool
isEmptyRefinement (Reft _ env) = isEmptyVarEnv env
refineType :: Refinement -> Type -> Maybe (Coercion, Type)
-- Apply the refinement to the type.
-- If (refineType r ty) = (co, ty')
-- Then co :: ty:=:ty'
-- Nothing => the refinement does nothing to this type
refineType (Reft in_scope env) ty
| not (isEmptyVarEnv env), -- Common case
any (`elemVarEnv` env) (varSetElems (tyVarsOfType ty))
= Just (substTy co_subst ty, substTy tv_subst ty)
| otherwise
= Nothing -- The type doesn't mention any refined type variables
where
tv_subst = mkTvSubst in_scope (mapVarEnv snd env)
co_subst = mkTvSubst in_scope (mapVarEnv fst env)
refinePred :: Refinement -> PredType -> Maybe (Coercion, PredType)
refinePred (Reft in_scope env) pred
| not (isEmptyVarEnv env), -- Common case
any (`elemVarEnv` env) (varSetElems (tyVarsOfPred pred))
= Just (mkPredTy (substPred co_subst pred), substPred tv_subst pred)
| otherwise
= Nothing -- The type doesn't mention any refined type variables
where
tv_subst = mkTvSubst in_scope (mapVarEnv snd env)
co_subst = mkTvSubst in_scope (mapVarEnv fst env)
refineResType :: Refinement -> Type -> Maybe (Coercion, Type)
-- Like refineType, but returns the 'sym' coercion
-- If (refineResType r ty) = (co, ty')
-- Then co :: ty':=:ty
refineResType reft ty
= case refineType reft ty of
Just (co, ty1) -> Just (mkSymCoercion co, ty1)
Nothing -> Nothing
\end{code}
%************************************************************************
%* *
Simple generation of a type refinement
%* *
%************************************************************************
\begin{code}
matchRefine :: [TyVar] -> [Coercion] -> Refinement
\end{code}
Given a list of coercions, where for each coercion c::(ty1~ty2), the type ty2
is a specialisation of ty1, produce a type refinement that maps the variables
of ty1 to the corresponding sub-terms of ty2 using appropriate coercions; eg,
matchRefine (co :: [(a, b)] ~ [(c, Maybe d)])
= { right (left (right co)) :: a ~ c
, right (right co) :: b ~ Maybe d
}
Precondition: The rhs types must indeed be a specialisation of the lhs types;
i.e., some free variables of the lhs are replaced with either distinct free
variables or proper type terms to obtain the rhs. (We don't perform full
unification or type matching here!)
NB: matchRefine does *not* expand the type synonyms.
\begin{code}
matchRefine in_scope_tvs cos
= Reft in_scope (foldr plusVarEnv emptyVarEnv (map refineOne cos))
where
in_scope = mkInScopeSet (mkVarSet in_scope_tvs)
-- NB: in_scope_tvs include both coercion variables
-- *and* the tyvars in their kinds
refineOne co = refine co ty1 ty2
where
(ty1, ty2) = coercionKind co
refine co (TyVarTy tv) ty = unitVarEnv tv (co, ty)
refine co (TyConApp _ tys) (TyConApp _ tys') = refineArgs co tys tys'
refine _ (PredTy _) (PredTy _) =
error "Unify.matchRefine: PredTy"
refine co (FunTy arg res) (FunTy arg' res') =
refine (mkRightCoercion (mkLeftCoercion co)) arg arg'
`plusVarEnv`
refine (mkRightCoercion co) res res'
refine co (AppTy fun arg) (AppTy fun' arg') =
refine (mkLeftCoercion co) fun fun'
`plusVarEnv`
refine (mkRightCoercion co) arg arg'
refine co (ForAllTy tv ty) (ForAllTy _tv ty') =
refine (mkForAllCoercion tv co) ty ty' `delVarEnv` tv
refine _ _ _ = error "RcGadt.matchRefine: mismatch"
refineArgs :: Coercion -> [Type] -> [Type] -> InternalReft
refineArgs co tys tys' =
fst $ foldr refineArg (emptyVarEnv, id) (zip tys tys')
where
refineArg (ty, ty') (reft, coWrapper)
= (refine (mkRightCoercion (coWrapper co)) ty ty' `plusVarEnv` reft,
mkLeftCoercion . coWrapper)
\end{code}
%************************************************************************
%* *
Unification
%* *
%************************************************************************
\begin{code}
tcUnifyTys :: (TyVar -> BindFlag)
-> [Type] -> [Type]
-> Maybe TvSubst -- A regular one-shot substitution
-- The two types may have common type variables, and indeed do so in the
-- second call to tcUnifyTys in FunDeps.checkClsFD
--
tcUnifyTys bind_fn tys1 tys2
= maybeErrToMaybe $ initUM bind_fn $
do { subst <- unifyList emptyTvSubstEnv tys1 tys2
-- Find the fixed point of the resulting non-idempotent substitution
; let in_scope = mkInScopeSet (tvs1 `unionVarSet` tvs2)
tv_env = fixTvSubstEnv in_scope subst
; return (mkTvSubst in_scope tv_env) }
where
tvs1 = tyVarsOfTypes tys1
tvs2 = tyVarsOfTypes tys2
----------------------------
-- XXX Can we do this more nicely, by exploiting laziness?
-- Or avoid needing it in the first place?
fixTvSubstEnv :: InScopeSet -> TvSubstEnv -> TvSubstEnv
fixTvSubstEnv in_scope env = f env
where
f e = let e' = mapUFM (substTy (mkTvSubst in_scope e)) e
in if and $ eltsUFM $ intersectUFM_C tcEqType e e'
then e
else f e'
\end{code}
%************************************************************************
%* *
The workhorse
%* *
%************************************************************************
\begin{code}
unify :: TvSubstEnv -- An existing substitution to extend
-> Type -> Type -- Types to be unified, and witness of their equality
-> UM TvSubstEnv -- Just the extended substitution,
-- Nothing if unification failed
-- We do not require the incoming substitution to be idempotent,
-- nor guarantee that the outgoing one is. That's fixed up by
-- the wrappers.
-- Respects newtypes, PredTypes
-- in unify, any NewTcApps/Preds should be taken at face value
unify subst (TyVarTy tv1) ty2 = uVar subst tv1 ty2
unify subst ty1 (TyVarTy tv2) = uVar subst tv2 ty1
unify subst ty1 ty2 | Just ty1' <- tcView ty1 = unify subst ty1' ty2
unify subst ty1 ty2 | Just ty2' <- tcView ty2 = unify subst ty1 ty2'
unify subst (PredTy p1) (PredTy p2) = unify_pred subst p1 p2
unify subst (TyConApp tyc1 tys1) (TyConApp tyc2 tys2)
| tyc1 == tyc2 = unify_tys subst tys1 tys2
unify subst (FunTy ty1a ty1b) (FunTy ty2a ty2b)
= do { subst' <- unify subst ty1a ty2a
; unify subst' ty1b ty2b }
-- Applications need a bit of care!
-- They can match FunTy and TyConApp, so use splitAppTy_maybe
-- NB: we've already dealt with type variables and Notes,
-- so if one type is an App the other one jolly well better be too
unify subst (AppTy ty1a ty1b) ty2
| Just (ty2a, ty2b) <- repSplitAppTy_maybe ty2
= do { subst' <- unify subst ty1a ty2a
; unify subst' ty1b ty2b }
unify subst ty1 (AppTy ty2a ty2b)
| Just (ty1a, ty1b) <- repSplitAppTy_maybe ty1
= do { subst' <- unify subst ty1a ty2a
; unify subst' ty1b ty2b }
unify _ ty1 ty2 = failWith (misMatch ty1 ty2)
-- ForAlls??
------------------------------
unify_pred :: TvSubstEnv -> PredType -> PredType -> UM TvSubstEnv
unify_pred subst (ClassP c1 tys1) (ClassP c2 tys2)
| c1 == c2 = unify_tys subst tys1 tys2
unify_pred subst (IParam n1 t1) (IParam n2 t2)
| n1 == n2 = unify subst t1 t2
unify_pred _ p1 p2 = failWith (misMatch (PredTy p1) (PredTy p2))
------------------------------
unify_tys :: TvSubstEnv -> [Type] -> [Type] -> UM TvSubstEnv
unify_tys subst xs ys = unifyList subst xs ys
unifyList :: TvSubstEnv -> [Type] -> [Type] -> UM TvSubstEnv
unifyList subst orig_xs orig_ys
= go subst orig_xs orig_ys
where
go subst [] [] = return subst
go subst (x:xs) (y:ys) = do { subst' <- unify subst x y
; go subst' xs ys }
go _ _ _ = failWith (lengthMisMatch orig_xs orig_ys)
---------------------------------
uVar :: TvSubstEnv -- An existing substitution to extend
-> TyVar -- Type variable to be unified
-> Type -- with this type
-> UM TvSubstEnv
-- PRE-CONDITION: in the call (uVar swap r tv1 ty), we know that
-- if swap=False (tv1:=:ty)
-- if swap=True (ty:=:tv1)
uVar subst tv1 ty
= -- Check to see whether tv1 is refined by the substitution
case (lookupVarEnv subst tv1) of
Just ty' -> unify subst ty' ty -- Yes, call back into unify'
Nothing -> uUnrefined subst -- No, continue
tv1 ty ty
uUnrefined :: TvSubstEnv -- An existing substitution to extend
-> TyVar -- Type variable to be unified
-> Type -- with this type
-> Type -- (version w/ expanded synonyms)
-> UM TvSubstEnv
-- We know that tv1 isn't refined
uUnrefined subst tv1 ty2 ty2'
| Just ty2'' <- tcView ty2'
= uUnrefined subst tv1 ty2 ty2'' -- Unwrap synonyms
-- This is essential, in case we have
-- type Foo a = a
-- and then unify a :=: Foo a
uUnrefined subst tv1 ty2 (TyVarTy tv2)
| tv1 == tv2 -- Same type variable
= return subst
-- Check to see whether tv2 is refined
| Just ty' <- lookupVarEnv subst tv2
= uUnrefined subst tv1 ty' ty'
-- So both are unrefined; next, see if the kinds force the direction
| eqKind k1 k2 -- Can update either; so check the bind-flags
= do { b1 <- tvBindFlag tv1
; b2 <- tvBindFlag tv2
; case (b1,b2) of
(BindMe, _) -> bind tv1 ty2
(Skolem, Skolem) -> failWith (misMatch ty1 ty2)
(Skolem, _) -> bind tv2 ty1
}
| k1 `isSubKind` k2 = bindTv subst tv2 ty1 -- Must update tv2
| k2 `isSubKind` k1 = bindTv subst tv1 ty2 -- Must update tv1
| otherwise = failWith (kindMisMatch tv1 ty2)
where
ty1 = TyVarTy tv1
k1 = tyVarKind tv1
k2 = tyVarKind tv2
bind tv ty = return $ extendVarEnv subst tv ty
uUnrefined subst tv1 ty2 ty2' -- ty2 is not a type variable
| tv1 `elemVarSet` substTvSet subst (tyVarsOfType ty2')
= failWith (occursCheck tv1 ty2) -- Occurs check
| not (k2 `isSubKind` k1)
= failWith (kindMisMatch tv1 ty2) -- Kind check
| otherwise
= bindTv subst tv1 ty2 -- Bind tyvar to the synonym if poss
where
k1 = tyVarKind tv1
k2 = typeKind ty2'
substTvSet :: TvSubstEnv -> TyVarSet -> TyVarSet
-- Apply the non-idempotent substitution to a set of type variables,
-- remembering that the substitution isn't necessarily idempotent
substTvSet subst tvs
= foldVarSet (unionVarSet . get) emptyVarSet tvs
where
get tv = case lookupVarEnv subst tv of
Nothing -> unitVarSet tv
Just ty -> substTvSet subst (tyVarsOfType ty)
bindTv :: TvSubstEnv -> TyVar -> Type -> UM TvSubstEnv
bindTv subst tv ty -- ty is not a type variable
= do { b <- tvBindFlag tv
; case b of
Skolem -> failWith (misMatch (TyVarTy tv) ty)
BindMe -> return $ extendVarEnv subst tv ty
}
\end{code}
%************************************************************************
%* *
Binding decisions
%* *
%************************************************************************
\begin{code}
data BindFlag
= BindMe -- A regular type variable
| Skolem -- This type variable is a skolem constant
-- Don't bind it; it only matches itself
\end{code}
%************************************************************************
%* *
Unification monad
%* *
%************************************************************************
\begin{code}
newtype UM a = UM { unUM :: (TyVar -> BindFlag)
-> MaybeErr Message a }
instance Monad UM where
return a = UM (\_tvs -> Succeeded a)
fail s = UM (\_tvs -> Failed (text s))
m >>= k = UM (\tvs -> case unUM m tvs of
Failed err -> Failed err
Succeeded v -> unUM (k v) tvs)
initUM :: (TyVar -> BindFlag) -> UM a -> MaybeErr Message a
initUM badtvs um = unUM um badtvs
tvBindFlag :: TyVar -> UM BindFlag
tvBindFlag tv = UM (\tv_fn -> Succeeded (tv_fn tv))
failWith :: Message -> UM a
failWith msg = UM (\_tv_fn -> Failed msg)
maybeErrToMaybe :: MaybeErr fail succ -> Maybe succ
maybeErrToMaybe (Succeeded a) = Just a
maybeErrToMaybe (Failed _) = Nothing
\end{code}
%************************************************************************
%* *
Error reporting
We go to a lot more trouble to tidy the types
in TcUnify. Maybe we'll end up having to do that
here too, but I'll leave it for now.
%* *
%************************************************************************
\begin{code}
misMatch :: Type -> Type -> SDoc
misMatch t1 t2
= ptext (sLit "Can't match types") <+> quotes (ppr t1) <+>
ptext (sLit "and") <+> quotes (ppr t2)
lengthMisMatch :: [Type] -> [Type] -> SDoc
lengthMisMatch tys1 tys2
= sep [ptext (sLit "Can't match unequal length lists"),
nest 2 (ppr tys1), nest 2 (ppr tys2) ]
kindMisMatch :: TyVar -> Type -> SDoc
kindMisMatch tv1 t2
= vcat [ptext (sLit "Can't match kinds") <+> quotes (ppr (tyVarKind tv1)) <+>
ptext (sLit "and") <+> quotes (ppr (typeKind t2)),
ptext (sLit "when matching") <+> quotes (ppr tv1) <+>
ptext (sLit "with") <+> quotes (ppr t2)]
occursCheck :: TyVar -> Type -> SDoc
occursCheck tv ty
= hang (ptext (sLit "Can't construct the infinite type"))
2 (ppr tv <+> equals <+> ppr ty)
\end{code}